version 1.327, 2018/04/10 00:52:30 |
version 1.337, 2018/08/20 17:25:09 |
|
|
int rstacksz; /* current size limit of rstack */ |
int rstacksz; /* current size limit of rstack */ |
int rstackpos; /* position in rstack */ |
int rstackpos; /* position in rstack */ |
int format; /* current file in mdoc or man format */ |
int format; /* current file in mdoc or man format */ |
int argc; /* number of args of the last macro */ |
|
char control; /* control character */ |
char control; /* control character */ |
char escape; /* escape character */ |
char escape; /* escape character */ |
}; |
}; |
Line 197 static enum rofferr roff_line_ignore(ROFF_ARGS); |
|
Line 196 static enum rofferr roff_line_ignore(ROFF_ARGS); |
|
static void roff_man_alloc1(struct roff_man *); |
static void roff_man_alloc1(struct roff_man *); |
static void roff_man_free1(struct roff_man *); |
static void roff_man_free1(struct roff_man *); |
static enum rofferr roff_manyarg(ROFF_ARGS); |
static enum rofferr roff_manyarg(ROFF_ARGS); |
|
static enum rofferr roff_nop(ROFF_ARGS); |
static enum rofferr roff_nr(ROFF_ARGS); |
static enum rofferr roff_nr(ROFF_ARGS); |
static enum rofferr roff_onearg(ROFF_ARGS); |
static enum rofferr roff_onearg(ROFF_ARGS); |
static enum roff_tok roff_parse(struct roff *, char *, int *, |
static enum roff_tok roff_parse(struct roff *, char *, int *, |
Line 326 const char *__roff_name[MAN_MAX + 1] = { |
|
Line 326 const char *__roff_name[MAN_MAX + 1] = { |
|
"Dx", "%Q", "%U", "Ta", |
"Dx", "%Q", "%U", "Ta", |
NULL, |
NULL, |
"TH", "SH", "SS", "TP", |
"TH", "SH", "SS", "TP", |
|
"TQ", |
"LP", "PP", "P", "IP", |
"LP", "PP", "P", "IP", |
"HP", "SM", "SB", "BI", |
"HP", "SM", "SB", "BI", |
"IB", "BR", "RB", "R", |
"IB", "BR", "RB", "R", |
Line 333 const char *__roff_name[MAN_MAX + 1] = { |
|
Line 334 const char *__roff_name[MAN_MAX + 1] = { |
|
"nf", "fi", |
"nf", "fi", |
"RE", "RS", "DT", "UC", |
"RE", "RS", "DT", "UC", |
"PD", "AT", "in", |
"PD", "AT", "in", |
"OP", "EX", "EE", "UR", |
"SY", "YS", "OP", |
|
"EX", "EE", "UR", |
"UE", "MT", "ME", NULL |
"UE", "MT", "ME", NULL |
}; |
}; |
const char *const *roff_name = __roff_name; |
const char *const *roff_name = __roff_name; |
Line 490 static struct roffmac roffs[TOKEN_NONE] = { |
|
Line 492 static struct roffmac roffs[TOKEN_NONE] = { |
|
{ roff_line_ignore, NULL, NULL, 0 }, /* nhychar */ |
{ roff_line_ignore, NULL, NULL, 0 }, /* nhychar */ |
{ roff_unsupp, NULL, NULL, 0 }, /* nm */ |
{ roff_unsupp, NULL, NULL, 0 }, /* nm */ |
{ roff_unsupp, NULL, NULL, 0 }, /* nn */ |
{ roff_unsupp, NULL, NULL, 0 }, /* nn */ |
{ roff_unsupp, NULL, NULL, 0 }, /* nop */ |
{ roff_nop, NULL, NULL, 0 }, /* nop */ |
{ roff_nr, NULL, NULL, 0 }, /* nr */ |
{ roff_nr, NULL, NULL, 0 }, /* nr */ |
{ roff_unsupp, NULL, NULL, 0 }, /* nrf */ |
{ roff_unsupp, NULL, NULL, 0 }, /* nrf */ |
{ roff_line_ignore, NULL, NULL, 0 }, /* nroff */ |
{ roff_line_ignore, NULL, NULL, 0 }, /* nroff */ |
Line 762 roff_alloc(struct mparse *parse, int options) |
|
Line 764 roff_alloc(struct mparse *parse, int options) |
|
|
|
r = mandoc_calloc(1, sizeof(struct roff)); |
r = mandoc_calloc(1, sizeof(struct roff)); |
r->parse = parse; |
r->parse = parse; |
r->reqtab = roffhash_alloc(0, ROFF_USERDEF); |
r->reqtab = roffhash_alloc(0, ROFF_RENAMED); |
r->options = options; |
r->options = options; |
r->format = options & (MPARSE_MDOC | MPARSE_MAN); |
r->format = options & (MPARSE_MDOC | MPARSE_MAN); |
r->rstackpos = -1; |
r->rstackpos = -1; |
Line 1122 static enum rofferr |
|
Line 1124 static enum rofferr |
|
roff_res(struct roff *r, struct buf *buf, int ln, int pos) |
roff_res(struct roff *r, struct buf *buf, int ln, int pos) |
{ |
{ |
char ubuf[24]; /* buffer to print the number */ |
char ubuf[24]; /* buffer to print the number */ |
|
struct roff_node *n; /* used for header comments */ |
const char *start; /* start of the string to process */ |
const char *start; /* start of the string to process */ |
char *stesc; /* start of an escape sequence ('\\') */ |
char *stesc; /* start of an escape sequence ('\\') */ |
|
char *ep; /* end of comment string */ |
const char *stnam; /* start of the name, after "[(*" */ |
const char *stnam; /* start of the name, after "[(*" */ |
const char *cp; /* end of the name, e.g. before ']' */ |
const char *cp; /* end of the name, e.g. before ']' */ |
const char *res; /* the string to be substituted */ |
const char *res; /* the string to be substituted */ |
Line 1173 roff_res(struct roff *r, struct buf *buf, int ln, int |
|
Line 1177 roff_res(struct roff *r, struct buf *buf, int ln, int |
|
|
|
/* Handle trailing whitespace. */ |
/* Handle trailing whitespace. */ |
|
|
cp = strchr(stesc--, '\0') - 1; |
ep = strchr(stesc--, '\0') - 1; |
if (*cp == '\n') { |
if (*ep == '\n') { |
done = 1; |
done = 1; |
cp--; |
ep--; |
} |
} |
if (*cp == ' ' || *cp == '\t') |
if (*ep == ' ' || *ep == '\t') |
mandoc_msg(MANDOCERR_SPACE_EOL, r->parse, |
mandoc_msg(MANDOCERR_SPACE_EOL, r->parse, |
ln, cp - buf->buf, NULL); |
ln, ep - buf->buf, NULL); |
while (stesc > start && stesc[-1] == ' ') |
|
|
/* |
|
* Save comments preceding the title macro |
|
* in the syntax tree. |
|
*/ |
|
|
|
if (r->format == 0) { |
|
while (*ep == ' ' || *ep == '\t') |
|
ep--; |
|
ep[1] = '\0'; |
|
n = roff_node_alloc(r->man, |
|
ln, stesc + 1 - buf->buf, |
|
ROFFT_COMMENT, TOKEN_NONE); |
|
n->string = mandoc_strdup(stesc + 2); |
|
roff_node_append(r->man, n); |
|
n->flags |= NODE_VALID | NODE_ENDED; |
|
r->man->next = ROFF_NEXT_SIBLING; |
|
} |
|
|
|
/* Line continuation with comment. */ |
|
|
|
if (stesc[1] == '#') { |
|
*stesc = '\0'; |
|
return ROFF_APPEND; |
|
} |
|
|
|
/* Discard normal comments. */ |
|
|
|
while (stesc > start && stesc[-1] == ' ' && |
|
(stesc == start + 1 || stesc[-2] != '\\')) |
stesc--; |
stesc--; |
*stesc = '\0'; |
*stesc = '\0'; |
break; |
break; |
Line 1343 roff_res(struct roff *r, struct buf *buf, int ln, int |
|
Line 1376 roff_res(struct roff *r, struct buf *buf, int ln, int |
|
if (arg_complete) { |
if (arg_complete) { |
deftype = ROFFDEF_USER | ROFFDEF_PRE; |
deftype = ROFFDEF_USER | ROFFDEF_PRE; |
res = roff_getstrn(r, stnam, naml, &deftype); |
res = roff_getstrn(r, stnam, naml, &deftype); |
|
|
|
/* |
|
* If not overriden, let \*(.T |
|
* through to the formatters. |
|
*/ |
|
|
|
if (res == NULL && naml == 2 && |
|
stnam[0] == '.' && stnam[1] == 'T') { |
|
roff_setstrn(&r->strtab, |
|
".T", 2, NULL, 0, 0); |
|
stesc--; |
|
continue; |
|
} |
} |
} |
break; |
break; |
case 'B': |
case 'B': |
|
|
static int |
static int |
roff_evalcond(struct roff *r, int ln, char *v, int *pos) |
roff_evalcond(struct roff *r, int ln, char *v, int *pos) |
{ |
{ |
char *cp, *name; |
const char *start, *end; |
size_t sz; |
char *cp, *name; |
int deftype, number, savepos, istrue, wanttrue; |
size_t sz; |
|
int deftype, len, number, savepos, istrue, wanttrue; |
|
|
if ('!' == v[*pos]) { |
if ('!' == v[*pos]) { |
wanttrue = 0; |
wanttrue = 0; |
Line 2138 roff_evalcond(struct roff *r, int ln, char *v, int *po |
|
Line 2185 roff_evalcond(struct roff *r, int ln, char *v, int *po |
|
case 'o': |
case 'o': |
(*pos)++; |
(*pos)++; |
return wanttrue; |
return wanttrue; |
case 'c': |
|
case 'e': |
case 'e': |
case 't': |
case 't': |
case 'v': |
case 'v': |
(*pos)++; |
(*pos)++; |
return !wanttrue; |
return !wanttrue; |
|
case 'c': |
|
do { |
|
(*pos)++; |
|
} while (v[*pos] == ' '); |
|
|
|
/* |
|
* Quirk for groff compatibility: |
|
* The horizontal tab is neither available nor unavailable. |
|
*/ |
|
|
|
if (v[*pos] == '\t') { |
|
(*pos)++; |
|
return 0; |
|
} |
|
|
|
/* Printable ASCII characters are available. */ |
|
|
|
if (v[*pos] != '\\') { |
|
(*pos)++; |
|
return wanttrue; |
|
} |
|
|
|
end = v + ++*pos; |
|
switch (mandoc_escape(&end, &start, &len)) { |
|
case ESCAPE_SPECIAL: |
|
istrue = mchars_spec2cp(start, len) != -1; |
|
break; |
|
case ESCAPE_UNICODE: |
|
istrue = 1; |
|
break; |
|
case ESCAPE_NUMBERED: |
|
istrue = mchars_num2char(start, len) != -1; |
|
break; |
|
default: |
|
istrue = !wanttrue; |
|
break; |
|
} |
|
*pos = end - v; |
|
return istrue == wanttrue; |
case 'd': |
case 'd': |
case 'r': |
case 'r': |
cp = v + *pos + 1; |
cp = v + *pos + 1; |
Line 2577 roff_getregro(const struct roff *r, const char *name) |
|
Line 2662 roff_getregro(const struct roff *r, const char *name) |
|
|
|
switch (*name) { |
switch (*name) { |
case '$': /* Number of arguments of the last macro evaluated. */ |
case '$': /* Number of arguments of the last macro evaluated. */ |
return r->argc; |
return 0; |
case 'A': /* ASCII approximation mode is always off. */ |
case 'A': /* ASCII approximation mode is always off. */ |
return 0; |
return 0; |
case 'g': /* Groff compatibility mode is always on. */ |
case 'g': /* Groff compatibility mode is always on. */ |
Line 2822 roff_TE(ROFF_ARGS) |
|
Line 2907 roff_TE(ROFF_ARGS) |
|
free(buf->buf); |
free(buf->buf); |
buf->buf = mandoc_strdup(".sp"); |
buf->buf = mandoc_strdup(".sp"); |
buf->sz = 4; |
buf->sz = 4; |
|
*offs = 0; |
return ROFF_REPARSE; |
return ROFF_REPARSE; |
} |
} |
r->tbl = NULL; |
r->tbl = NULL; |
Line 3137 roff_eo(ROFF_ARGS) |
|
Line 3223 roff_eo(ROFF_ARGS) |
|
} |
} |
|
|
static enum rofferr |
static enum rofferr |
|
roff_nop(ROFF_ARGS) |
|
{ |
|
while (buf->buf[pos] == ' ') |
|
pos++; |
|
*offs = pos; |
|
return ROFF_RERUN; |
|
} |
|
|
|
static enum rofferr |
roff_tr(ROFF_ARGS) |
roff_tr(ROFF_ARGS) |
{ |
{ |
const char *p, *first, *second; |
const char *p, *first, *second; |
Line 3285 roff_userdef(ROFF_ARGS) |
|
Line 3380 roff_userdef(ROFF_ARGS) |
|
{ |
{ |
const char *arg[16], *ap; |
const char *arg[16], *ap; |
char *cp, *n1, *n2; |
char *cp, *n1, *n2; |
int expand_count, i, ib, ie; |
int argc, expand_count, i, ib, ie; |
size_t asz, rsz; |
size_t asz, esz, rsz; |
|
|
/* |
/* |
* Collect pointers to macro argument strings |
* Collect pointers to macro argument strings |
* and NUL-terminate them. |
* and NUL-terminate them. |
*/ |
*/ |
|
|
r->argc = 0; |
argc = 0; |
cp = buf->buf + pos; |
cp = buf->buf + pos; |
for (i = 0; i < 16; i++) { |
for (i = 0; i < 16; i++) { |
if (*cp == '\0') |
if (*cp == '\0') |
arg[i] = ""; |
arg[i] = ""; |
else { |
else { |
arg[i] = mandoc_getarg(r->parse, &cp, ln, &pos); |
arg[i] = mandoc_getarg(r->parse, &cp, ln, &pos); |
r->argc = i + 1; |
argc = i + 1; |
} |
} |
} |
} |
|
|
Line 3322 roff_userdef(ROFF_ARGS) |
|
Line 3417 roff_userdef(ROFF_ARGS) |
|
continue; |
continue; |
if (*cp == '*') { /* \\$* inserts all arguments */ |
if (*cp == '*') { /* \\$* inserts all arguments */ |
ib = 0; |
ib = 0; |
ie = r->argc - 1; |
ie = argc - 1; |
} else { /* \\$1 .. \\$9 insert one argument */ |
} else { /* \\$1 .. \\$9 insert one argument */ |
ib = ie = *cp - '1'; |
ib = ie = *cp - '1'; |
if (ib < 0 || ib > 8) |
if (ib < 0 || ib > 8) |
Line 3341 roff_userdef(ROFF_ARGS) |
|
Line 3436 roff_userdef(ROFF_ARGS) |
|
ln, (int)(cp - n1), NULL); |
ln, (int)(cp - n1), NULL); |
free(buf->buf); |
free(buf->buf); |
buf->buf = n1; |
buf->buf = n1; |
|
*offs = 0; |
return ROFF_IGN; |
return ROFF_IGN; |
} |
} |
|
|
Line 3410 roff_userdef(ROFF_ARGS) |
|
Line 3506 roff_userdef(ROFF_ARGS) |
|
} |
} |
|
|
/* |
/* |
|
* Expand the number of arguments, if it is used. |
|
* This never makes the expanded macro longer. |
|
*/ |
|
|
|
for (cp = n1; *cp != '\0'; cp++) { |
|
if (cp[0] != '\\') |
|
continue; |
|
if (cp[1] == '\\') { |
|
cp++; |
|
continue; |
|
} |
|
if (strncmp(cp + 1, "n(.$", 4) == 0) |
|
esz = 5; |
|
else if (strncmp(cp + 1, "n[.$]", 5) == 0) |
|
esz = 6; |
|
else |
|
continue; |
|
asz = snprintf(cp, esz, "%d", argc); |
|
assert(asz < esz); |
|
rsz = buf->sz - (cp - n1) - esz; |
|
memmove(cp + asz, cp + esz, rsz); |
|
buf->sz -= esz - asz; |
|
n2 = mandoc_realloc(n1, buf->sz); |
|
cp = n2 + (cp - n1) + asz; |
|
n1 = n2; |
|
} |
|
|
|
/* |
* Replace the macro invocation |
* Replace the macro invocation |
* by the expanded macro. |
* by the expanded macro. |
*/ |
*/ |
Line 3435 roff_renamed(ROFF_ARGS) |
|
Line 3559 roff_renamed(ROFF_ARGS) |
|
buf->buf[pos] == '\0' ? "" : " ", buf->buf + pos) + 1; |
buf->buf[pos] == '\0' ? "" : " ", buf->buf + pos) + 1; |
free(buf->buf); |
free(buf->buf); |
buf->buf = nbuf; |
buf->buf = nbuf; |
|
*offs = 0; |
return ROFF_CONT; |
return ROFF_CONT; |
} |
} |
|
|