=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.309 retrieving revision 1.317 diff -u -p -r1.309 -r1.317 --- mandoc/roff.c 2017/06/14 13:00:31 1.309 +++ mandoc/roff.c 2017/06/25 11:42:02 1.317 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.309 2017/06/14 13:00:31 schwarze Exp $ */ +/* $Id: roff.c,v 1.317 2017/06/25 11:42:02 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons * Copyright (c) 2010-2015, 2017 Ingo Schwarze @@ -39,6 +39,14 @@ /* Maximum number of string expansions per line, to break infinite loops. */ #define EXPAND_LIMIT 1000 +/* Types of definitions of macros and strings. */ +#define ROFFDEF_USER (1 << 1) /* User-defined. */ +#define ROFFDEF_PRE (1 << 2) /* Predefined. */ +#define ROFFDEF_REN (1 << 3) /* Renamed standard macro. */ +#define ROFFDEF_STD (1 << 4) /* mdoc(7) or man(7) macro. */ +#define ROFFDEF_ANY (ROFFDEF_USER | ROFFDEF_PRE | \ + ROFFDEF_REN | ROFFDEF_STD) + /* --- data types --------------------------------------------------------- */ /* @@ -146,6 +154,7 @@ static void roffnode_cleanscope(struct roff *); static void roffnode_pop(struct roff *); static void roffnode_push(struct roff *, enum roff_tok, const char *, int, int); +static enum rofferr roff_als(ROFF_ARGS); static enum rofferr roff_block(ROFF_ARGS); static enum rofferr roff_block_text(ROFF_ARGS); static enum rofferr roff_block_sub(ROFF_ARGS); @@ -176,10 +185,8 @@ static int roff_getregn(const struct roff *, const char *, size_t); static int roff_getregro(const struct roff *, const char *name); -static const char *roff_getrenn(const struct roff *, - const char *, size_t); static const char *roff_getstrn(const struct roff *, - const char *, size_t); + const char *, size_t, int *); static int roff_hasregn(const struct roff *, const char *, size_t); static enum rofferr roff_insec(ROFF_ARGS); @@ -206,7 +213,6 @@ static void roff_setstrn(struct roffkv **, const cha static enum rofferr roff_so(ROFF_ARGS); static enum rofferr roff_tr(ROFF_ARGS); static enum rofferr roff_Dd(ROFF_ARGS); -static enum rofferr roff_TH(ROFF_ARGS); static enum rofferr roff_TE(ROFF_ARGS); static enum rofferr roff_TS(ROFF_ARGS); static enum rofferr roff_EQ(ROFF_ARGS); @@ -222,8 +228,8 @@ static enum rofferr roff_userdef(ROFF_ARGS); const char *__roff_name[MAN_MAX + 1] = { "br", "ce", "ft", "ll", - "mc", "rj", "sp", "ta", - "ti", NULL, + "mc", "po", "rj", "sp", + "ta", "ti", NULL, "ab", "ad", "af", "aln", "als", "am", "am1", "ami", "ami1", "as", "as1", "asciify", @@ -264,7 +270,7 @@ const char *__roff_name[MAN_MAX + 1] = { "open", "opena", "os", "output", "padj", "papersize", "pc", "pev", "pi", "PI", "pl", "pm", - "pn", "pnr", "po", "ps", + "pn", "pnr", "ps", "psbb", "pshape", "pso", "ptr", "pvs", "rchar", "rd", "recursionlimit", "return", "rfschar", "rhang", @@ -324,7 +330,7 @@ const char *__roff_name[MAN_MAX + 1] = { "RE", "RS", "DT", "UC", "PD", "AT", "in", "OP", "EX", "EE", "UR", - "UE", NULL + "UE", "MT", "ME", NULL }; const char *const *roff_name = __roff_name; @@ -334,6 +340,7 @@ static struct roffmac roffs[TOKEN_NONE] = { { roff_onearg, NULL, NULL, 0 }, /* ft */ { roff_onearg, NULL, NULL, 0 }, /* ll */ { roff_onearg, NULL, NULL, 0 }, /* mc */ + { roff_onearg, NULL, NULL, 0 }, /* po */ { roff_onearg, NULL, NULL, 0 }, /* rj */ { roff_onearg, NULL, NULL, 0 }, /* sp */ { roff_manyarg, NULL, NULL, 0 }, /* ta */ @@ -343,7 +350,7 @@ static struct roffmac roffs[TOKEN_NONE] = { { roff_line_ignore, NULL, NULL, 0 }, /* ad */ { roff_line_ignore, NULL, NULL, 0 }, /* af */ { roff_unsupp, NULL, NULL, 0 }, /* aln */ - { roff_unsupp, NULL, NULL, 0 }, /* als */ + { roff_als, NULL, NULL, 0 }, /* als */ { roff_block, roff_block_text, roff_block_sub, 0 }, /* am */ { roff_block, roff_block_text, roff_block_sub, 0 }, /* am1 */ { roff_block, roff_block_text, roff_block_sub, 0 }, /* ami */ @@ -499,7 +506,6 @@ static struct roffmac roffs[TOKEN_NONE] = { { roff_line_ignore, NULL, NULL, 0 }, /* pm */ { roff_line_ignore, NULL, NULL, 0 }, /* pn */ { roff_line_ignore, NULL, NULL, 0 }, /* pnr */ - { roff_line_ignore, NULL, NULL, 0 }, /* po */ { roff_line_ignore, NULL, NULL, 0 }, /* ps */ { roff_unsupp, NULL, NULL, 0 }, /* psbb */ { roff_unsupp, NULL, NULL, 0 }, /* pshape */ @@ -535,7 +541,7 @@ static struct roffmac roffs[TOKEN_NONE] = { { roff_T_, NULL, NULL, 0 }, /* T& */ { roff_unsupp, NULL, NULL, 0 }, /* tc */ { roff_TE, NULL, NULL, 0 }, /* TE */ - { roff_TH, NULL, NULL, 0 }, /* TH */ + { roff_Dd, NULL, NULL, 0 }, /* TH */ { roff_line_ignore, NULL, NULL, 0 }, /* tkf */ { roff_unsupp, NULL, NULL, 0 }, /* tl */ { roff_line_ignore, NULL, NULL, 0 }, /* tm */ @@ -573,39 +579,6 @@ static struct roffmac roffs[TOKEN_NONE] = { { roff_userdef, NULL, NULL, 0 } }; -/* not currently implemented: Ds em Eq LP Me PP pp Or Rd Sf SH */ -const char *const __mdoc_reserved[] = { - "Ac", "Ad", "An", "Ao", "Ap", "Aq", "Ar", "At", - "Bc", "Bd", "Bf", "Bk", "Bl", "Bo", "Bq", - "Brc", "Bro", "Brq", "Bsx", "Bt", "Bx", - "Cd", "Cm", "Db", "Dc", "Dd", "Dl", "Do", "Dq", - "Dt", "Dv", "Dx", "D1", - "Ec", "Ed", "Ef", "Ek", "El", "Em", - "En", "Eo", "Er", "Es", "Ev", "Ex", - "Fa", "Fc", "Fd", "Fl", "Fn", "Fo", "Fr", "Ft", "Fx", - "Hf", "Ic", "In", "It", "Lb", "Li", "Lk", "Lp", - "Ms", "Mt", "Nd", "Nm", "No", "Ns", "Nx", - "Oc", "Oo", "Op", "Os", "Ot", "Ox", - "Pa", "Pc", "Pf", "Po", "Pp", "Pq", - "Qc", "Ql", "Qo", "Qq", "Re", "Rs", "Rv", - "Sc", "Sh", "Sm", "So", "Sq", - "Ss", "St", "Sx", "Sy", - "Ta", "Tn", "Ud", "Ux", "Va", "Vt", "Xc", "Xo", "Xr", - "%A", "%B", "%C", "%D", "%I", "%J", "%N", "%O", - "%P", "%Q", "%R", "%T", "%U", "%V", - NULL -}; - -/* not currently implemented: BT DE DS ME MT PT SY TQ YS */ -const char *const __man_reserved[] = { - "AT", "B", "BI", "BR", "DT", - "EE", "EN", "EQ", "EX", "HP", "I", "IB", "IP", "IR", - "LP", "OP", "P", "PD", "PP", - "R", "RB", "RE", "RI", "RS", "SB", "SH", "SM", "SS", - "TE", "TH", "TP", "TS", "T&", "UC", "UE", "UR", - NULL -}; - /* Array of injected predefined strings. */ #define PREDEFS_MAX 38 static const struct predef predefs[PREDEFS_MAX] = { @@ -846,14 +819,14 @@ roff_man_free(struct roff_man *man) struct roff_man * roff_man_alloc(struct roff *roff, struct mparse *parse, - const char *defos, int quick) + const char *os_s, int quick) { struct roff_man *man; man = mandoc_calloc(1, sizeof(*man)); man->parse = parse; man->roff = roff; - man->defos = defos; + man->os_s = os_s; man->quick = quick; roff_man_alloc1(man); roff->man = man; @@ -1165,11 +1138,13 @@ roff_res(struct roff *r, struct buf *buf, int ln, int size_t maxl; /* expected length of the escape name */ size_t naml; /* actual length of the escape name */ enum mandoc_esc esc; /* type of the escape sequence */ + enum mandoc_os os_e; /* kind of RCS id seen */ int inaml; /* length returned from mandoc_escape() */ int expand_count; /* to avoid infinite loops */ int npos; /* position in numeric expression */ int arg_complete; /* argument not interrupted by eol */ int done; /* no more input available */ + int deftype; /* type of definition to paste */ char term; /* character terminating the escape */ /* Search forward for comments. */ @@ -1182,6 +1157,27 @@ roff_res(struct roff *r, struct buf *buf, int ln, int stesc++; if (*stesc != '"' && *stesc != '#') continue; + + /* Comment found, look for RCS id. */ + + if ((cp = strstr(stesc, "$" "OpenBSD")) != NULL) { + os_e = MANDOC_OS_OPENBSD; + cp += 8; + } else if ((cp = strstr(stesc, "$" "NetBSD")) != NULL) { + os_e = MANDOC_OS_NETBSD; + cp += 7; + } + if (cp != NULL && + isalnum((unsigned char)*cp) == 0 && + strchr(cp, '$') != NULL) { + if (r->man->meta.rcsids & (1 << os_e)) + mandoc_msg(MANDOCERR_RCS_REP, r->parse, + ln, stesc + 1 - buf->buf, stesc + 1); + r->man->meta.rcsids |= 1 << os_e; + } + + /* Handle trailing whitespace. */ + cp = strchr(stesc--, '\0') - 1; if (*cp == '\n') { done = 1; @@ -1346,8 +1342,10 @@ roff_res(struct roff *r, struct buf *buf, int ln, int switch (stesc[1]) { case '*': - if (arg_complete) - res = roff_getstrn(r, stnam, naml); + if (arg_complete) { + deftype = ROFFDEF_USER | ROFFDEF_PRE; + res = roff_getstrn(r, stnam, naml, &deftype); + } break; case 'B': npos = 0; @@ -1616,6 +1614,7 @@ roff_parse(struct roff *r, char *buf, int *pos, int ln char *cp; const char *mac; size_t maclen; + int deftype; enum roff_tok t; cp = buf + *pos; @@ -1626,14 +1625,21 @@ roff_parse(struct roff *r, char *buf, int *pos, int ln mac = cp; maclen = roff_getname(r, &cp, ln, ppos); - t = (r->current_string = roff_getstrn(r, mac, maclen)) ? - ROFF_USERDEF : - (r->current_string = roff_getrenn(r, mac, maclen)) ? - ROFF_RENAMED : roffhash_find(r->reqtab, mac, maclen); - + deftype = ROFFDEF_USER | ROFFDEF_REN; + r->current_string = roff_getstrn(r, mac, maclen, &deftype); + switch (deftype) { + case ROFFDEF_USER: + t = ROFF_USERDEF; + break; + case ROFFDEF_REN: + t = ROFF_RENAMED; + break; + default: + t = roffhash_find(r->reqtab, mac, maclen); + break; + } if (t != TOKEN_NONE) *pos = cp - buf; - return t; } @@ -1725,9 +1731,10 @@ roff_ccond(struct roff *r, int ln, int ppos) static enum rofferr roff_block(ROFF_ARGS) { - const char *name; - char *iname, *cp; - size_t namesz; + const char *name, *value; + char *call, *cp, *iname, *rname; + size_t csz, namesz, rsz; + int deftype; /* Ignore groff compatibility mode for now. */ @@ -1755,7 +1762,9 @@ roff_block(ROFF_ARGS) /* Resolve the macro name argument if it is indirect. */ if (namesz && (tok == ROFF_dei || tok == ROFF_ami)) { - if ((name = roff_getstrn(r, iname, namesz)) == NULL) { + deftype = ROFFDEF_USER; + name = roff_getstrn(r, iname, namesz, &deftype); + if (name == NULL) { mandoc_vmsg(MANDOCERR_STR_UNDEF, r->parse, ln, (int)(iname - buf->buf), "%.*s", (int)namesz, iname); @@ -1779,8 +1788,37 @@ roff_block(ROFF_ARGS) * appended from roff_block_text() in multiline mode. */ - if (tok == ROFF_de || tok == ROFF_dei) + if (tok == ROFF_de || tok == ROFF_dei) { roff_setstrn(&r->strtab, name, namesz, "", 0, 0); + roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0); + } else if (tok == ROFF_am || tok == ROFF_ami) { + deftype = ROFFDEF_ANY; + value = roff_getstrn(r, iname, namesz, &deftype); + switch (deftype) { /* Before appending, ... */ + case ROFFDEF_PRE: /* copy predefined to user-defined. */ + roff_setstrn(&r->strtab, name, namesz, + value, strlen(value), 0); + break; + case ROFFDEF_REN: /* call original standard macro. */ + csz = mandoc_asprintf(&call, ".%.*s \\$* \\\"\n", + (int)strlen(value), value); + roff_setstrn(&r->strtab, name, namesz, call, csz, 0); + roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0); + free(call); + break; + case ROFFDEF_STD: /* rename and call standard macro. */ + rsz = mandoc_asprintf(&rname, "__%s_renamed", name); + roff_setstrn(&r->rentab, rname, rsz, name, namesz, 0); + csz = mandoc_asprintf(&call, ".%.*s \\$* \\\"\n", + (int)rsz, rname); + roff_setstrn(&r->strtab, name, namesz, call, csz, 0); + free(call); + free(rname); + break; + default: + break; + } + } if (*cp == '\0') return ROFF_IGN; @@ -1793,7 +1831,9 @@ roff_block(ROFF_ARGS) /* Resolve the end marker if it is indirect. */ if (namesz && (tok == ROFF_dei || tok == ROFF_ami)) { - if ((name = roff_getstrn(r, iname, namesz)) == NULL) { + deftype = ROFFDEF_USER; + name = roff_getstrn(r, iname, namesz, &deftype); + if (name == NULL) { mandoc_vmsg(MANDOCERR_STR_UNDEF, r->parse, ln, (int)(iname - buf->buf), "%.*s", (int)namesz, iname); @@ -2065,7 +2105,7 @@ roff_evalcond(struct roff *r, int ln, char *v, int *po { char *cp, *name; size_t sz; - int number, savepos, wanttrue; + int deftype, number, savepos, istrue, wanttrue; if ('!' == v[*pos]) { wanttrue = 0; @@ -2081,17 +2121,29 @@ roff_evalcond(struct roff *r, int ln, char *v, int *po (*pos)++; return wanttrue; case 'c': - case 'd': case 'e': case 't': case 'v': (*pos)++; return !wanttrue; + case 'd': case 'r': - cp = name = v + ++*pos; - sz = roff_getname(r, &cp, ln, *pos); + cp = v + *pos + 1; + while (*cp == ' ') + cp++; + name = cp; + sz = roff_getname(r, &cp, ln, cp - v); + if (sz == 0) + istrue = 0; + else if (v[*pos] == 'r') + istrue = roff_hasregn(r, name, sz); + else { + deftype = ROFFDEF_ANY; + roff_getstrn(r, name, sz, &deftype); + istrue = !!deftype; + } *pos = cp - v; - return (sz && roff_hasregn(r, name, sz)) == wanttrue; + return istrue == wanttrue; default: break; } @@ -2243,6 +2295,7 @@ roff_ds(ROFF_ARGS) /* The rest is the value. */ roff_setstrn(&r->strtab, name, namesz, string, strlen(string), ROFF_as == tok); + roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0); return ROFF_IGN; } @@ -2654,6 +2707,7 @@ roff_rm(ROFF_ARGS) name = cp; namesz = roff_getname(r, &cp, ln, (int)(cp - buf->buf)); roff_setstrn(&r->strtab, name, namesz, NULL, 0, 0); + roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0); if (name[namesz] == '\\') break; } @@ -2692,34 +2746,34 @@ roff_it(ROFF_ARGS) static enum rofferr roff_Dd(ROFF_ARGS) { - const char *const *cp; + int mask; + enum roff_tok t, te; - if ((r->options & (MPARSE_MDOC | MPARSE_QUICK)) == 0) - for (cp = __mdoc_reserved; *cp; cp++) - roff_setstr(r, *cp, NULL, 0); - - if (r->format == 0) - r->format = MPARSE_MDOC; - + switch (tok) { + case ROFF_Dd: + tok = MDOC_Dd; + te = MDOC_MAX; + if (r->format == 0) + r->format = MPARSE_MDOC; + mask = MPARSE_MDOC | MPARSE_QUICK; + break; + case ROFF_TH: + tok = MAN_TH; + te = MAN_MAX; + if (r->format == 0) + r->format = MPARSE_MAN; + mask = MPARSE_QUICK; + break; + default: + abort(); + } + if ((r->options & mask) == 0) + for (t = tok; t < te; t++) + roff_setstr(r, roff_name[t], NULL, 0); return ROFF_CONT; } static enum rofferr -roff_TH(ROFF_ARGS) -{ - const char *const *cp; - - if ((r->options & MPARSE_QUICK) == 0) - for (cp = __man_reserved; *cp; cp++) - roff_setstr(r, *cp, NULL, 0); - - if (r->format == 0) - r->format = MPARSE_MAN; - - return ROFF_CONT; -} - -static enum rofferr roff_TE(ROFF_ARGS) { @@ -2952,6 +3006,33 @@ roff_manyarg(ROFF_ARGS) } static enum rofferr +roff_als(ROFF_ARGS) +{ + char *oldn, *newn, *end, *value; + size_t oldsz, newsz, valsz; + + newn = oldn = buf->buf + pos; + if (*newn == '\0') + return ROFF_IGN; + + newsz = roff_getname(r, &oldn, ln, pos); + if (newn[newsz] == '\\' || *oldn == '\0') + return ROFF_IGN; + + end = oldn; + oldsz = roff_getname(r, &end, ln, oldn - buf->buf); + if (oldsz == 0) + return ROFF_IGN; + + valsz = mandoc_asprintf(&value, ".%.*s \\$*\\\"\n", + (int)oldsz, oldn); + roff_setstrn(&r->strtab, newn, newsz, value, valsz, 0); + roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0); + free(value); + return ROFF_IGN; +} + +static enum rofferr roff_br(ROFF_ARGS) { if (r->man->flags & (MAN_BLINE | MAN_ELINE)) @@ -3077,6 +3158,7 @@ roff_rn(ROFF_ARGS) const char *value; char *oldn, *newn, *end; size_t oldsz, newsz; + int deftype; oldn = newn = buf->buf + pos; if (*oldn == '\0') @@ -3091,33 +3173,32 @@ roff_rn(ROFF_ARGS) if (newsz == 0) return ROFF_IGN; - /* - * Rename a user-defined macro bearing the old name, - * overriding an existing renamed high-level macro - * bearing the new name, if that exists. - */ - - if ((value = roff_getstrn(r, oldn, oldsz)) != NULL) { + deftype = ROFFDEF_ANY; + value = roff_getstrn(r, oldn, oldsz, &deftype); + switch (deftype) { + case ROFFDEF_USER: roff_setstrn(&r->strtab, newn, newsz, value, strlen(value), 0); roff_setstrn(&r->strtab, oldn, oldsz, NULL, 0, 0); roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0); - return ROFF_IGN; - } - - /* - * Rename a high-level macro bearing the old name, - * either renaming it a second time if it was already - * renamed before, or renaming it for the first time. - * In both cases, override an existing user-defined - * macro bearing the new name, if that exists. - */ - - if ((value = roff_getrenn(r, oldn, oldsz)) != NULL) { + break; + case ROFFDEF_PRE: + roff_setstrn(&r->strtab, newn, newsz, value, strlen(value), 0); + roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0); + break; + case ROFFDEF_REN: roff_setstrn(&r->rentab, newn, newsz, value, strlen(value), 0); roff_setstrn(&r->rentab, oldn, oldsz, NULL, 0, 0); - } else + roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0); + break; + case ROFFDEF_STD: roff_setstrn(&r->rentab, newn, newsz, oldn, oldsz, 0); - roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0); + roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0); + break; + default: + roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0); + roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0); + break; + } return ROFF_IGN; } @@ -3156,7 +3237,7 @@ roff_so(ROFF_ARGS) static enum rofferr roff_userdef(ROFF_ARGS) { - const char *arg[9], *ap; + const char *arg[16], *ap; char *cp, *n1, *n2; int expand_count, i, ib, ie; size_t asz, rsz; @@ -3168,7 +3249,7 @@ roff_userdef(ROFF_ARGS) r->argc = 0; cp = buf->buf + pos; - for (i = 0; i < 9; i++) { + for (i = 0; i < 16; i++) { if (*cp == '\0') arg[i] = ""; else { @@ -3304,8 +3385,8 @@ roff_renamed(ROFF_ARGS) { char *nbuf; - buf->sz = mandoc_asprintf(&nbuf, ".%s %s", r->current_string, - buf->buf + pos) + 1; + buf->sz = mandoc_asprintf(&nbuf, ".%s%s%s", r->current_string, + buf->buf[pos] == '\0' ? "" : " ", buf->buf + pos) + 1; free(buf->buf); buf->buf = nbuf; return ROFF_CONT; @@ -3360,9 +3441,12 @@ static void roff_setstr(struct roff *r, const char *name, const char *string, int append) { + size_t namesz; - roff_setstrn(&r->strtab, name, strlen(name), string, + namesz = strlen(name); + roff_setstrn(&r->strtab, name, namesz, string, string ? strlen(string) : 0, append); + roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0); } static void @@ -3438,38 +3522,63 @@ roff_setstrn(struct roffkv **r, const char *name, size } static const char * -roff_getstrn(const struct roff *r, const char *name, size_t len) +roff_getstrn(const struct roff *r, const char *name, size_t len, + int *deftype) { - const struct roffkv *n; - int i; + const struct roffkv *n; + int i; + enum roff_tok tok; - for (n = r->strtab; n; n = n->next) - if (0 == strncmp(name, n->key.p, len) && - '\0' == n->key.p[(int)len]) - return n->val.p; - - for (i = 0; i < PREDEFS_MAX; i++) - if (0 == strncmp(name, predefs[i].name, len) && - '\0' == predefs[i].name[(int)len]) - return predefs[i].str; - - return NULL; -} - -/* - * Check whether *name is the renamed name of a high-level macro. - * Return the standard name, or NULL if it is not. - */ -static const char * -roff_getrenn(const struct roff *r, const char *name, size_t len) -{ - const struct roffkv *n; - - for (n = r->rentab; n; n = n->next) - if (0 == strncmp(name, n->key.p, len) && - '\0' == n->key.p[(int)len]) - return n->val.p; - + if (*deftype & ROFFDEF_USER) { + for (n = r->strtab; n != NULL; n = n->next) { + if (strncmp(name, n->key.p, len) == 0 && + n->key.p[len] == '\0' && + n->val.p != NULL) { + *deftype = ROFFDEF_USER; + return n->val.p; + } + } + } + if (*deftype & ROFFDEF_PRE) { + for (i = 0; i < PREDEFS_MAX; i++) { + if (strncmp(name, predefs[i].name, len) == 0 && + predefs[i].name[len] == '\0') { + *deftype = ROFFDEF_PRE; + return predefs[i].str; + } + } + } + if (*deftype & ROFFDEF_REN) { + for (n = r->rentab; n != NULL; n = n->next) { + if (strncmp(name, n->key.p, len) == 0 && + n->key.p[len] == '\0' && + n->val.p != NULL) { + *deftype = ROFFDEF_REN; + return n->val.p; + } + } + } + if (*deftype & ROFFDEF_STD) { + if (r->man->macroset != MACROSET_MAN) { + for (tok = MDOC_Dd; tok < MDOC_MAX; tok++) { + if (strncmp(name, roff_name[tok], len) == 0 && + roff_name[tok][len] == '\0') { + *deftype = ROFFDEF_STD; + return NULL; + } + } + } + if (r->man->macroset != MACROSET_MDOC) { + for (tok = MAN_TH; tok < MAN_MAX; tok++) { + if (strncmp(name, roff_name[tok], len) == 0 && + roff_name[tok][len] == '\0') { + *deftype = ROFFDEF_STD; + return NULL; + } + } + } + } + *deftype = 0; return NULL; }