version 1.261, 2015/02/17 17:16:52 |
version 1.265, 2015/04/18 17:28:36 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
* Copyright (c) 2010, 2011, 2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2009-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> |
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> |
* Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
|
|
|
|
#include "mandoc.h" |
#include "mandoc.h" |
#include "mandoc_aux.h" |
#include "mandoc_aux.h" |
|
#include "roff.h" |
#include "libmandoc.h" |
#include "libmandoc.h" |
#include "libroff.h" |
#include "libroff.h" |
|
|
Line 412 static const char *roff_getstrn(const struct roff *, |
|
Line 413 static const char *roff_getstrn(const struct roff *, |
|
static enum rofferr roff_insec(ROFF_ARGS); |
static enum rofferr roff_insec(ROFF_ARGS); |
static enum rofferr roff_it(ROFF_ARGS); |
static enum rofferr roff_it(ROFF_ARGS); |
static enum rofferr roff_line_ignore(ROFF_ARGS); |
static enum rofferr roff_line_ignore(ROFF_ARGS); |
|
static void roff_man_alloc1(struct roff_man *); |
|
static void roff_man_free1(struct roff_man *); |
static enum rofferr roff_nr(ROFF_ARGS); |
static enum rofferr roff_nr(ROFF_ARGS); |
static enum rofft roff_parse(struct roff *, char *, int *, |
static enum rofft roff_parse(struct roff *, char *, int *, |
int, int); |
int, int); |
Line 898 roff_alloc(struct mparse *parse, const struct mchars * |
|
Line 901 roff_alloc(struct mparse *parse, const struct mchars * |
|
return(r); |
return(r); |
} |
} |
|
|
|
static void |
|
roff_man_free1(struct roff_man *man) |
|
{ |
|
|
|
if (man->first != NULL) { |
|
if (man->macroset == MACROSET_MDOC) |
|
mdoc_node_delete(man, man->first); |
|
else |
|
man_node_delete(man, man->first); |
|
} |
|
free(man->meta.msec); |
|
free(man->meta.vol); |
|
free(man->meta.os); |
|
free(man->meta.arch); |
|
free(man->meta.title); |
|
free(man->meta.name); |
|
free(man->meta.date); |
|
} |
|
|
|
static void |
|
roff_man_alloc1(struct roff_man *man) |
|
{ |
|
|
|
memset(&man->meta, 0, sizeof(man->meta)); |
|
man->first = mandoc_calloc(1, sizeof(*man->first)); |
|
man->first->type = ROFFT_ROOT; |
|
man->last = man->first; |
|
man->last_es = NULL; |
|
man->flags = 0; |
|
man->macroset = MACROSET_NONE; |
|
man->lastsec = man->lastnamed = SEC_NONE; |
|
man->next = ROFF_NEXT_CHILD; |
|
} |
|
|
|
void |
|
roff_man_reset(struct roff_man *man) |
|
{ |
|
|
|
roff_man_free1(man); |
|
roff_man_alloc1(man); |
|
} |
|
|
|
void |
|
roff_man_free(struct roff_man *man) |
|
{ |
|
|
|
roff_man_free1(man); |
|
free(man); |
|
} |
|
|
|
struct roff_man * |
|
roff_man_alloc(struct roff *roff, struct mparse *parse, |
|
const char *defos, int quick) |
|
{ |
|
struct roff_man *man; |
|
|
|
man = mandoc_calloc(1, sizeof(*man)); |
|
man->parse = parse; |
|
man->roff = roff; |
|
man->defos = defos; |
|
man->quick = quick; |
|
roff_man_alloc1(man); |
|
return(man); |
|
} |
|
|
/* |
/* |
* In the current line, expand escape sequences that tend to get |
* In the current line, expand escape sequences that tend to get |
* used in numerical expressions and conditional requests. |
* used in numerical expressions and conditional requests. |
Line 1128 roff_parsetext(struct buf *buf, int pos, int *offs) |
|
Line 1196 roff_parsetext(struct buf *buf, int pos, int *offs) |
|
esc = mandoc_escape((const char **)&p, NULL, NULL); |
esc = mandoc_escape((const char **)&p, NULL, NULL); |
if (esc == ESCAPE_ERROR) |
if (esc == ESCAPE_ERROR) |
break; |
break; |
|
while (*p == '-') |
|
p++; |
continue; |
continue; |
} else if (p == start) { |
} else if (p == start) { |
p++; |
p++; |
Line 2337 roff_it(ROFF_ARGS) |
|
Line 2407 roff_it(ROFF_ARGS) |
|
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
/* Arm the input line trap. */ |
while (isspace((unsigned char)buf->buf[pos])) |
|
pos++; |
|
|
|
/* |
|
* Arm the input line trap. |
|
* Special-casing "an-trap" is an ugly workaround to cope |
|
* with DocBook stupidly fiddling with man(7) internals. |
|
*/ |
|
|
roffit_lines = iv; |
roffit_lines = iv; |
roffit_macro = mandoc_strdup(buf->buf + pos); |
roffit_macro = mandoc_strdup(iv != 1 || |
|
strcmp(buf->buf + pos, "an-trap") ? |
|
buf->buf + pos : "br"); |
return(ROFF_IGN); |
return(ROFF_IGN); |
} |
} |
|
|
Line 2644 roff_so(ROFF_ARGS) |
|
Line 2723 roff_so(ROFF_ARGS) |
|
static enum rofferr |
static enum rofferr |
roff_userdef(ROFF_ARGS) |
roff_userdef(ROFF_ARGS) |
{ |
{ |
const char *arg[9]; |
const char *arg[9], *ap; |
char *cp, *n1, *n2; |
char *cp, *n1, *n2; |
int i; |
int i; |
|
size_t asz, rsz; |
|
|
/* |
/* |
* Collect pointers to macro argument strings |
* Collect pointers to macro argument strings |
* and NUL-terminate them. |
* and NUL-terminate them. |
*/ |
*/ |
|
|
cp = buf->buf + pos; |
cp = buf->buf + pos; |
for (i = 0; i < 9; i++) |
for (i = 0; i < 9; i++) |
arg[i] = *cp == '\0' ? "" : |
arg[i] = *cp == '\0' ? "" : |
Line 2660 roff_userdef(ROFF_ARGS) |
|
Line 2741 roff_userdef(ROFF_ARGS) |
|
/* |
/* |
* Expand macro arguments. |
* Expand macro arguments. |
*/ |
*/ |
buf->sz = 0; |
|
n1 = cp = mandoc_strdup(r->current_string); |
buf->sz = strlen(r->current_string) + 1; |
while ((cp = strstr(cp, "\\$")) != NULL) { |
n1 = cp = mandoc_malloc(buf->sz); |
i = cp[2] - '1'; |
memcpy(n1, r->current_string, buf->sz); |
if (0 > i || 8 < i) { |
while (*cp != '\0') { |
/* Not an argument invocation. */ |
|
cp += 2; |
/* Scan ahead for the next argument invocation. */ |
|
|
|
if (*cp++ != '\\') |
continue; |
continue; |
|
if (*cp++ != '$') |
|
continue; |
|
i = *cp - '1'; |
|
if (0 > i || 8 < i) |
|
continue; |
|
cp -= 2; |
|
|
|
/* |
|
* Determine the size of the expanded argument, |
|
* taking escaping of quotes into account. |
|
*/ |
|
|
|
asz = 0; |
|
for (ap = arg[i]; *ap != '\0'; ap++) { |
|
asz++; |
|
if (*ap == '"') |
|
asz += 3; |
} |
} |
*cp = '\0'; |
if (asz != 3) { |
buf->sz = mandoc_asprintf(&n2, "%s%s%s", |
|
n1, arg[i], cp + 3) + 1; |
/* |
cp = n2 + (cp - n1); |
* Determine the size of the rest of the |
free(n1); |
* unexpanded macro, including the NUL. |
n1 = n2; |
*/ |
|
|
|
rsz = buf->sz - (cp - n1) - 3; |
|
|
|
/* |
|
* When shrinking, move before |
|
* releasing the storage. |
|
*/ |
|
|
|
if (asz < 3) |
|
memmove(cp + asz, cp + 3, rsz); |
|
|
|
/* |
|
* Resize the storage for the macro |
|
* and readjust the parse pointer. |
|
*/ |
|
|
|
buf->sz += asz - 3; |
|
n2 = mandoc_realloc(n1, buf->sz); |
|
cp = n2 + (cp - n1); |
|
n1 = n2; |
|
|
|
/* |
|
* When growing, make room |
|
* for the expanded argument. |
|
*/ |
|
|
|
if (asz > 3) |
|
memmove(cp + asz, cp + 3, rsz); |
|
} |
|
|
|
/* Copy the expanded argument, escaping quotes. */ |
|
|
|
n2 = cp; |
|
for (ap = arg[i]; *ap != '\0'; ap++) { |
|
if (*ap == '"') { |
|
memcpy(n2, "\\(dq", 4); |
|
n2 += 4; |
|
} else |
|
*n2++ = *ap; |
|
} |
} |
} |
|
|
/* |
/* |
* Replace the macro invocation |
* Replace the macro invocation |
* by the expanded macro. |
* by the expanded macro. |
*/ |
*/ |
|
|
free(buf->buf); |
free(buf->buf); |
buf->buf = n1; |
buf->buf = n1; |
if (buf->sz == 0) |
|
buf->sz = strlen(buf->buf) + 1; |
|
*offs = 0; |
*offs = 0; |
|
|
return(buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ? |
return(buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ? |