/* * Lookup a macro following the initial line macro. */ static enum mdoct lookup_raw(const char *p) { enum mdoct res; if (MDOC_MAX == (res = mdoc_hash_find(p))) return(MDOC_MAX); if (MDOC_CALLABLE & mdoc_macros[res].flags) return(res); return(MDOC_MAX); }
static int post_bl_block_width(POST_ARGS) { size_t width; int i; enum mdoct tok; struct mdoc_node *n; char buf[NUMSIZ]; n = mdoc->last; /* * Calculate the real width of a list from the -width string, * which may contain a macro (with a known default width), a * literal string, or a scaling width. * * If the value to -width is a macro, then we re-write it to be * the macro's width as set in share/tmac/mdoc/doc-common. */ if (0 == strcmp(n->norm->Bl.width, "Ds")) width = 6; else if (MDOC_MAX == (tok = mdoc_hash_find(n->norm->Bl.width))) return(1); else if (0 == (width = mdoc_macro2len(tok))) { mdoc_nmsg(mdoc, n, MANDOCERR_BADWIDTH); return(1); } /* The value already exists: free and reallocate it. */ assert(n->args); for (i = 0; i < (int)n->args->argc; i++) if (MDOC_Width == n->args->argv[i].arg) break; assert(i < (int)n->args->argc); snprintf(buf, NUMSIZ, "%zun", width); free(n->args->argv[i].value[0]); n->args->argv[i].value[0] = mandoc_strdup(buf); /* Set our width! */ n->norm->Bl.width = n->args->argv[i].value[0]; return(1); }
/* * Look up the macro at *p called by "from", * or as a line macro if from == MDOC_MAX. */ static enum mdoct lookup(struct mdoc *mdoc, enum mdoct from, int line, int ppos, const char *p) { enum mdoct res; if (from == MDOC_MAX || mdoc_macros[from].flags & MDOC_PARSED) { res = mdoc_hash_find(p); if (res != MDOC_MAX) { if (mdoc_macros[res].flags & MDOC_CALLABLE) return(res); if (res != MDOC_br && res != MDOC_sp && res != MDOC_ll) mandoc_msg(MANDOCERR_MACRO_CALL, mdoc->parse, line, ppos, p); } } return(MDOC_MAX); }
/* * Look up the macro at *p called by "from", * or as a line macro if from == TOKEN_NONE. */ static int lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p) { int res; if (mdoc->flags & MDOC_PHRASEQF) { mdoc->flags &= ~MDOC_PHRASEQF; return TOKEN_NONE; } if (from == TOKEN_NONE || mdoc_macros[from].flags & MDOC_PARSED) { res = mdoc_hash_find(p); if (res != TOKEN_NONE) { if (mdoc_macros[res].flags & MDOC_CALLABLE) return res; if (res != MDOC_br && res != MDOC_sp && res != MDOC_ll) mandoc_msg(MANDOCERR_MACRO_CALL, mdoc->parse, line, ppos, p); } } return TOKEN_NONE; }
/* * Parse a macro line, that is, a line beginning with the control * character. */ static int mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs) { enum mdoct tok; int i, j, sv; char mac[5]; struct mdoc_node *n; /* Empty lines are ignored. */ offs++; if ('\0' == buf[offs]) return(1); i = offs; /* Accept tabs/whitespace after the initial control char. */ if (' ' == buf[i] || '\t' == buf[i]) { i++; while (buf[i] && (' ' == buf[i] || '\t' == buf[i])) i++; if ('\0' == buf[i]) return(1); } sv = i; /* * Copy the first word into a nil-terminated buffer. * Stop copying when a tab, space, or eoln is encountered. */ j = 0; while (j < 4 && '\0' != buf[i] && ' ' != buf[i] && '\t' != buf[i]) mac[j++] = buf[i++]; mac[j] = '\0'; tok = (j > 1 || j < 4) ? mdoc_hash_find(mac) : MDOC_MAX; if (MDOC_MAX == tok) { mdoc_vmsg(m, MANDOCERR_MACRO, ln, sv, "%s", buf + sv - 1); return(1); } /* Disregard the first trailing tab, if applicable. */ if ('\t' == buf[i]) i++; /* Jump to the next non-whitespace word. */ while (buf[i] && ' ' == buf[i]) i++; /* * Trailing whitespace. Note that tabs are allowed to be passed * into the parser as "text", so we only warn about spaces here. */ if ('\0' == buf[i] && ' ' == buf[i - 1]) mdoc_pmsg(m, ln, i - 1, MANDOCERR_EOLNSPACE); /* * If an initial macro or a list invocation, divert directly * into macro processing. */ if (NULL == m->last || MDOC_It == tok || MDOC_El == tok) { if ( ! mdoc_macro(m, tok, ln, sv, &i, buf)) goto err; return(1); } n = m->last; assert(m->last); /* * If the first macro of a `Bl -column', open an `It' block * context around the parsed macro. */ if (MDOC_Bl == n->tok && MDOC_BODY == n->type && LIST_column == n->norm->Bl.type) { m->flags |= MDOC_FREECOL; if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf)) goto err; return(1); } /* * If we're following a block-level `It' within a `Bl -column' * context (perhaps opened in the above block or in ptext()), * then open an `It' block context around the parsed macro. */ if (MDOC_It == n->tok && MDOC_BLOCK == n->type && NULL != n->parent && MDOC_Bl == n->parent->tok && LIST_column == n->parent->norm->Bl.type) { m->flags |= MDOC_FREECOL; if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf)) goto err; return(1); } /* Normal processing of a macro. */ if ( ! mdoc_macro(m, tok, ln, sv, &i, buf)) goto err; return(1); err: /* Error out. */ m->flags |= MDOC_HALT; return(0); }
/* * Parse a macro line, that is, a line beginning with the control * character. */ static int mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs) { struct mdoc_node *n; const char *cp; enum mdoct tok; int i, sv; char mac[5]; sv = offs; /* * Copy the first word into a nil-terminated buffer. * Stop when a space, tab, escape, or eoln is encountered. */ i = 0; while (i < 4 && strchr(" \t\\", buf[offs]) == NULL) mac[i++] = buf[offs++]; mac[i] = '\0'; tok = (i > 1 && i < 4) ? mdoc_hash_find(mac) : MDOC_MAX; if (tok == MDOC_MAX) { mandoc_msg(MANDOCERR_MACRO, mdoc->parse, ln, sv, buf + sv - 1); return(1); } /* Skip a leading escape sequence or tab. */ switch (buf[offs]) { case '\\': cp = buf + offs + 1; mandoc_escape(&cp, NULL, NULL); offs = cp - buf; break; case '\t': offs++; break; default: break; } /* Jump to the next non-whitespace word. */ while (buf[offs] && ' ' == buf[offs]) offs++; /* * Trailing whitespace. Note that tabs are allowed to be passed * into the parser as "text", so we only warn about spaces here. */ if ('\0' == buf[offs] && ' ' == buf[offs - 1]) mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse, ln, offs - 1, NULL); /* * If an initial macro or a list invocation, divert directly * into macro processing. */ if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok) { mdoc_macro(mdoc, tok, ln, sv, &offs, buf); return(1); } n = mdoc->last; assert(mdoc->last); /* * If the first macro of a `Bl -column', open an `It' block * context around the parsed macro. */ if (MDOC_Bl == n->tok && MDOC_BODY == n->type && LIST_column == n->norm->Bl.type) { mdoc->flags |= MDOC_FREECOL; mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf); return(1); } /* * If we're following a block-level `It' within a `Bl -column' * context (perhaps opened in the above block or in ptext()), * then open an `It' block context around the parsed macro. */ if (MDOC_It == n->tok && MDOC_BLOCK == n->type && NULL != n->parent && MDOC_Bl == n->parent->tok && LIST_column == n->parent->norm->Bl.type) { mdoc->flags |= MDOC_FREECOL; mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf); return(1); } /* Normal processing of a macro. */ mdoc_macro(mdoc, tok, ln, sv, &offs, buf); /* In quick mode (for mandocdb), abort after the NAME section. */ if (mdoc->quick && MDOC_Sh == tok && SEC_NAME != mdoc->last->sec) return(2); return(1); }