/* * Phrases occur within `Bl -column' entries, separated by `Ta' or tabs. * They're unusual because they're basically free-form text until a * macro is encountered. */ static void phrase_ta(MACRO_PROT_ARGS) { struct roff_node *body, *n; /* Make sure we are in a column list or ignore this macro. */ body = NULL; for (n = mdoc->last; n != NULL; n = n->parent) { if (n->flags & MDOC_ENDED) continue; if (n->tok == MDOC_It && n->type == ROFFT_BODY) body = n; if (n->tok == MDOC_Bl) break; } if (n == NULL || n->norm->Bl.type != LIST_column) { mandoc_msg(MANDOCERR_TA_STRAY, mdoc->parse, line, ppos, "Ta"); return; } /* Advance to the next column. */ rew_last(mdoc, body); roff_body_alloc(mdoc, line, ppos, MDOC_It); parse_rest(mdoc, TOKEN_NONE, line, pos, buf); }
static void in_line_eoln(MACRO_PROT_ARGS) { struct roff_node *n; struct mdoc_arg *arg; if ((tok == MDOC_Pp || tok == MDOC_Lp) && ! (mdoc->flags & MDOC_SYNOPSIS)) { n = mdoc->last; if (mdoc->next == ROFF_NEXT_SIBLING) n = n->parent; if (n->tok == MDOC_Nm) rew_last(mdoc, n->parent); } if (buf[*pos] == '\0' && (tok == MDOC_Fd || mdoc_macronames[tok][0] == '%')) { mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, line, ppos, mdoc_macronames[tok]); return; } mdoc_argv(mdoc, line, tok, &arg, pos, buf); mdoc_elem_alloc(mdoc, line, ppos, tok, arg); if (parse_rest(mdoc, tok, line, pos, buf)) return; rew_elem(mdoc, tok); }
void my_parse_other(char *str, int n, t_server *s_info) { if (strcmp("expulse", str) == 0) my_expulse(n, s_info); else if (strcmp("connect_nbr", str) == 0) my_connectnbr(n, s_info); else parse_rest(str, n, s_info); }
static void blk_full(MACRO_PROT_ARGS) { int la, nl, parsed; struct mdoc_arg *arg; struct roff_node *blk; /* Our own or a broken block. */ struct roff_node *head; /* Our own head. */ struct roff_node *body; /* Our own body. */ struct roff_node *n; enum margserr ac, lac; char *p; nl = MDOC_NEWLINE & mdoc->flags; if (buf[*pos] == '\0' && (tok == MDOC_Sh || tok == MDOC_Ss)) { mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, line, ppos, mdoc_macronames[tok]); return; } if ( ! (mdoc_macros[tok].flags & MDOC_EXPLICIT)) { /* Here, tok is one of Sh Ss Nm Nd It. */ blk = NULL; for (n = mdoc->last; n != NULL; n = n->parent) { if (n->flags & MDOC_ENDED) { if ( ! (n->flags & MDOC_VALID)) n->flags |= MDOC_BROKEN; continue; } if (n->type != ROFFT_BLOCK) continue; if (tok == MDOC_It && n->tok == MDOC_Bl) { if (blk != NULL) { mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, "It breaks %s", mdoc_macronames[blk->tok]); rew_pending(mdoc, blk); } break; } if (mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { switch (tok) { case MDOC_Sh: case MDOC_Ss: mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, "%s breaks %s", mdoc_macronames[tok], mdoc_macronames[n->tok]); rew_pending(mdoc, n); n = mdoc->last; continue; case MDOC_It: /* Delay in case it's astray. */ blk = n; continue; default: break; } break; } /* Here, n is one of Sh Ss Nm Nd It. */ if (tok != MDOC_Sh && (n->tok == MDOC_Sh || (tok != MDOC_Ss && (n->tok == MDOC_Ss || (tok != MDOC_It && n->tok == MDOC_It))))) break; /* Item breaking an explicit block. */ if (blk != NULL) { mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, "It breaks %s", mdoc_macronames[blk->tok]); rew_pending(mdoc, blk); blk = NULL; } /* Close out prior implicit scopes. */ rew_last(mdoc, n); } /* Skip items outside lists. */ if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) { mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse, line, ppos, "It %s", buf + *pos); roff_elem_alloc(mdoc, line, ppos, MDOC_br); rew_elem(mdoc, MDOC_br); return; } } /* * This routine accommodates implicitly- and explicitly-scoped * macro openings. Implicit ones first close out prior scope * (seen above). Delay opening the head until necessary to * allow leading punctuation to print. Special consideration * for `It -column', which has phrase-part syntax instead of * regular child nodes. */ mdoc_argv(mdoc, line, tok, &arg, pos, buf); blk = mdoc_block_alloc(mdoc, line, ppos, tok, arg); head = body = NULL; /* * Exception: Heads of `It' macros in `-diag' lists are not * parsed, even though `It' macros in general are parsed. */ parsed = tok != MDOC_It || mdoc->last->parent->tok != MDOC_Bl || mdoc->last->parent->norm->Bl.type != LIST_diag; /* * The `Nd' macro has all arguments in its body: it's a hybrid * of block partial-explicit and full-implicit. Stupid. */ if (tok == MDOC_Nd) { head = roff_head_alloc(mdoc, line, ppos, tok); rew_last(mdoc, head); body = roff_body_alloc(mdoc, line, ppos, tok); } if (tok == MDOC_Bk) mdoc->flags |= MDOC_KEEP; ac = ARGS_EOLN; for (;;) { /* * If we are right after a tab character, * do not parse the first word for macros. */ if (mdoc->flags & MDOC_PHRASEQN) { mdoc->flags &= ~MDOC_PHRASEQN; mdoc->flags |= MDOC_PHRASEQF; } la = *pos; lac = ac; ac = mdoc_args(mdoc, line, pos, buf, tok, &p); if (ac == ARGS_EOLN) { if (lac != ARGS_PHRASE || ! (mdoc->flags & MDOC_PHRASEQF)) break; /* * This line ends in a tab; start the next * column now, with a leading blank. */ if (body != NULL) rew_last(mdoc, body); body = roff_body_alloc(mdoc, line, ppos, tok); roff_word_alloc(mdoc, line, ppos, "\\&"); break; } if (tok == MDOC_Bd || tok == MDOC_Bk) { mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, line, la, "%s ... %s", mdoc_macronames[tok], buf + la); break; } if (tok == MDOC_Rs) { mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, line, la, "Rs %s", buf + la); break; } if (ac == ARGS_PUNCT) break; /* * Emit leading punctuation (i.e., punctuation before * the ROFFT_HEAD) for non-phrase types. */ if (head == NULL && ac != ARGS_PHRASE && ac != ARGS_QWORD && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); continue; } /* Open a head if one hasn't been opened. */ if (head == NULL) head = roff_head_alloc(mdoc, line, ppos, tok); if (ac == ARGS_PHRASE) { /* * If we haven't opened a body yet, rewind the * head; if we have, rewind that instead. */ rew_last(mdoc, body == NULL ? head : body); body = roff_body_alloc(mdoc, line, ppos, tok); /* Process to the tab or to the end of the line. */ mdoc->flags |= MDOC_PHRASE; parse_rest(mdoc, TOKEN_NONE, line, &la, buf); mdoc->flags &= ~MDOC_PHRASE; /* There may have been `Ta' macros. */ while (body->next != NULL) body = body->next; continue; } if (macro_or_word(mdoc, tok, line, la, pos, buf, parsed)) break; } if (blk->flags & MDOC_VALID) return; if (head == NULL) head = roff_head_alloc(mdoc, line, ppos, tok); if (nl && tok != MDOC_Bd && tok != MDOC_Bl && tok != MDOC_Rs) append_delims(mdoc, line, pos, buf); if (body != NULL) goto out; if (find_pending(mdoc, tok, line, ppos, head)) return; /* Close out scopes to remain in a consistent state. */ rew_last(mdoc, head); body = roff_body_alloc(mdoc, line, ppos, tok); out: if (mdoc->flags & MDOC_FREECOL) { rew_last(mdoc, body); rew_last(mdoc, blk); mdoc->flags &= ~MDOC_FREECOL; } }
static void blk_full(MACRO_PROT_ARGS) { int la, nl, parsed; struct mdoc_arg *arg; struct mdoc_node *blk; /* Our own or a broken block. */ struct mdoc_node *head; /* Our own head. */ struct mdoc_node *body; /* Our own body. */ struct mdoc_node *n; enum margserr ac, lac; char *p; nl = MDOC_NEWLINE & mdoc->flags; if (buf[*pos] == '\0' && (tok == MDOC_Sh || tok == MDOC_Ss)) { mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse, line, ppos, mdoc_macronames[tok]); return; } if ( ! (mdoc_macros[tok].flags & MDOC_EXPLICIT)) { /* Here, tok is one of Sh Ss Nm Nd It. */ blk = NULL; for (n = mdoc->last; n != NULL; n = n->parent) { if (n->flags & MDOC_ENDED) { if ( ! (n->flags & MDOC_VALID)) n->flags |= MDOC_BROKEN; continue; } if (n->type != MDOC_BLOCK) continue; if (tok == MDOC_It && n->tok == MDOC_Bl) { if (blk != NULL) { mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, "It breaks %s", mdoc_macronames[blk->tok]); rew_pending(mdoc, blk); } break; } if (mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { switch (tok) { case MDOC_Sh: /* FALLTHROUGH */ case MDOC_Ss: mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, "%s breaks %s", mdoc_macronames[tok], mdoc_macronames[n->tok]); rew_pending(mdoc, n); n = mdoc->last; continue; case MDOC_It: /* Delay in case it's astray. */ blk = n; continue; default: break; } break; } /* Here, n is one of Sh Ss Nm Nd It. */ if (tok != MDOC_Sh && (n->tok == MDOC_Sh || (tok != MDOC_Ss && (n->tok == MDOC_Ss || (tok != MDOC_It && n->tok == MDOC_It))))) break; /* Item breaking an explicit block. */ if (blk != NULL) { mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, "It breaks %s", mdoc_macronames[blk->tok]); rew_pending(mdoc, blk); blk = NULL; } /* Close out prior implicit scopes. */ rew_last(mdoc, n); } /* Skip items outside lists. */ if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) { mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse, line, ppos, "It %s", buf + *pos); mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL); rew_elem(mdoc, MDOC_br); return; } } /* * This routine accommodates implicitly- and explicitly-scoped * macro openings. Implicit ones first close out prior scope * (seen above). Delay opening the head until necessary to * allow leading punctuation to print. Special consideration * for `It -column', which has phrase-part syntax instead of * regular child nodes. */ mdoc_argv(mdoc, line, tok, &arg, pos, buf); blk = mdoc_block_alloc(mdoc, line, ppos, tok, arg); head = body = NULL; /* * Exception: Heads of `It' macros in `-diag' lists are not * parsed, even though `It' macros in general are parsed. */ parsed = tok != MDOC_It || mdoc->last->parent->tok != MDOC_Bl || mdoc->last->parent->norm->Bl.type != LIST_diag; /* * The `Nd' macro has all arguments in its body: it's a hybrid * of block partial-explicit and full-implicit. Stupid. */ if (tok == MDOC_Nd) { head = mdoc_head_alloc(mdoc, line, ppos, tok); rew_last(mdoc, head); body = mdoc_body_alloc(mdoc, line, ppos, tok); } if (tok == MDOC_Bk) mdoc->flags |= MDOC_KEEP; ac = ARGS_PEND; for (;;) { la = *pos; lac = ac; ac = mdoc_args(mdoc, line, pos, buf, tok, &p); if (ac == ARGS_EOLN) { if (lac != ARGS_PPHRASE && lac != ARGS_PHRASE) break; /* * This is necessary: if the last token on a * line is a `Ta' or tab, then we'll get * ARGS_EOLN, so we must be smart enough to * reopen our scope if the last parse was a * phrase or partial phrase. */ if (body != NULL) rew_last(mdoc, body); body = mdoc_body_alloc(mdoc, line, ppos, tok); break; } if (tok == MDOC_Bd || tok == MDOC_Bk) { mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, line, la, "%s ... %s", mdoc_macronames[tok], buf + la); break; } if (tok == MDOC_Rs) { mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, line, la, "Rs %s", buf + la); break; } if (ac == ARGS_PUNCT) break; /* * Emit leading punctuation (i.e., punctuation before * the MDOC_HEAD) for non-phrase types. */ if (head == NULL && ac != ARGS_PEND && ac != ARGS_PHRASE && ac != ARGS_PPHRASE && ac != ARGS_QWORD && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); continue; } /* Open a head if one hasn't been opened. */ if (head == NULL) head = mdoc_head_alloc(mdoc, line, ppos, tok); if (ac == ARGS_PHRASE || ac == ARGS_PEND || ac == ARGS_PPHRASE) { /* * If we haven't opened a body yet, rewind the * head; if we have, rewind that instead. */ rew_last(mdoc, body == NULL ? head : body); body = mdoc_body_alloc(mdoc, line, ppos, tok); /* * Process phrases: set whether we're in a * partial-phrase (this effects line handling) * then call down into the phrase parser. */ if (ac == ARGS_PPHRASE) mdoc->flags |= MDOC_PPHRASE; if (ac == ARGS_PEND && lac == ARGS_PPHRASE) mdoc->flags |= MDOC_PPHRASE; parse_rest(mdoc, MDOC_MAX, line, &la, buf); mdoc->flags &= ~MDOC_PPHRASE; continue; } if (macro_or_word(mdoc, tok, line, la, pos, buf, parsed)) break; } if (blk->flags & MDOC_VALID) return; if (head == NULL) head = mdoc_head_alloc(mdoc, line, ppos, tok); if (nl && tok != MDOC_Bd && tok != MDOC_Bl && tok != MDOC_Rs) append_delims(mdoc, line, pos, buf); if (body != NULL) goto out; /* * If there is an open (i.e., unvalidated) sub-block requiring * explicit close-out, postpone switching the current block from * head to body until the rew_pending() call closing out that * sub-block. */ for (n = mdoc->last; n && n != head; n = n->parent) { if (n->flags & MDOC_ENDED) { if ( ! (n->flags & MDOC_VALID)) n->flags |= MDOC_BROKEN; continue; } if (n->type == MDOC_BLOCK && mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { n->flags = MDOC_BROKEN; head->flags = MDOC_ENDED; } } if (head->flags & MDOC_ENDED) return; /* Close out scopes to remain in a consistent state. */ rew_last(mdoc, head); body = mdoc_body_alloc(mdoc, line, ppos, tok); out: if (mdoc->flags & MDOC_FREECOL) { rew_last(mdoc, body); rew_last(mdoc, blk); mdoc->flags &= ~MDOC_FREECOL; } }