static int pre_par(PRE_ARGS) { if (NULL == mdoc->last) return(1); if (MDOC_ELEM != n->type && MDOC_BLOCK != n->type) return(1); /* * Don't allow prior `Lp' or `Pp' prior to a paragraph-type * block: `Lp', `Pp', or non-compact `Bd' or `Bl'. */ if (MDOC_Pp != mdoc->last->tok && MDOC_Lp != mdoc->last->tok) return(1); if (MDOC_Bl == n->tok && n->norm->Bl.comp) return(1); if (MDOC_Bd == n->tok && n->norm->Bd.comp) return(1); if (MDOC_It == n->tok && n->parent->norm->Bl.comp) return(1); mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_IGNPAR); mdoc_node_delete(mdoc, mdoc->last); return(1); }
void mdoc_node_delete(struct mdoc *m, struct mdoc_node *p) { while (p->child) { assert(p->nchild); mdoc_node_delete(m, p->child); } assert(0 == p->nchild); mdoc_node_unlink(m, p); mdoc_node_free(p); }
static int post_ignpar(POST_ARGS) { struct mdoc_node *np; if (MDOC_BODY != mdoc->last->type) return(1); if (NULL != (np = mdoc->last->child)) if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { mdoc_nmsg(mdoc, np, MANDOCERR_IGNPAR); mdoc_node_delete(mdoc, np); } if (NULL != (np = mdoc->last->last)) if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { mdoc_nmsg(mdoc, np, MANDOCERR_IGNPAR); mdoc_node_delete(mdoc, np); } return(1); }
/* * Frees volatile resources (parse tree, meta-data, fields). */ static void mdoc_free1(struct mdoc *mdoc) { if (mdoc->first) mdoc_node_delete(mdoc, mdoc->first); free(mdoc->meta.msec); free(mdoc->meta.vol); free(mdoc->meta.arch); free(mdoc->meta.date); free(mdoc->meta.title); free(mdoc->meta.os); free(mdoc->meta.name); }
static int post_prol(POST_ARGS) { /* * Remove prologue macros from the document after they're * processed. The final document uses mdoc_meta for these * values and discards the originals. */ mdoc_node_delete(mdoc, mdoc->last); if (mdoc->meta.title && mdoc->meta.date && mdoc->meta.os) mdoc->flags |= MDOC_PBODY; return(1); }
static int post_st(POST_ARGS) { struct mdoc_node *ch; const char *p; if (NULL == (ch = mdoc->last->child)) { mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY); mdoc_node_delete(mdoc, mdoc->last); return(1); } assert(MDOC_TEXT == ch->type); if (NULL == (p = mdoc_a2st(ch->string))) { mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADSTANDARD); mdoc_node_delete(mdoc, mdoc->last); } else { free(ch->string); ch->string = mandoc_strdup(p); } return(1); }
static int ebool(struct mdoc *mdoc) { if (NULL == mdoc->last->child) { mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_MACROEMPTY); mdoc_node_delete(mdoc, mdoc->last); return(1); } check_count(mdoc, MDOC_ELEM, CHECK_WARN, CHECK_EQ, 1); assert(MDOC_TEXT == mdoc->last->child->type); if (0 == strcmp(mdoc->last->child->string, "on")) return(1); if (0 == strcmp(mdoc->last->child->string, "off")) return(1); mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADBOOL); return(1); }
static int post_rs(POST_ARGS) { struct mdoc_node *nn, *next, *prev; int i, j; switch (mdoc->last->type) { case (MDOC_HEAD): check_count(mdoc, MDOC_HEAD, CHECK_WARN, CHECK_EQ, 0); return(1); case (MDOC_BODY): if (mdoc->last->child) break; check_count(mdoc, MDOC_BODY, CHECK_WARN, CHECK_GT, 0); return(1); default: return(1); } /* * Make sure only certain types of nodes are allowed within the * the `Rs' body. Delete offending nodes and raise a warning. * Do this before re-ordering for the sake of clarity. */ next = NULL; for (nn = mdoc->last->child; nn; nn = next) { for (i = 0; i < RSORD_MAX; i++) if (nn->tok == rsord[i]) break; if (i < RSORD_MAX) { if (MDOC__J == rsord[i]) mdoc->last->norm->Rs.child_J = nn; next = nn->next; continue; } next = nn->next; mdoc_nmsg(mdoc, nn, MANDOCERR_CHILD); mdoc_node_delete(mdoc, nn); } /* * The full `Rs' block needs special handling to order the * sub-elements according to `rsord'. Pick through each element * and correctly order it. This is a insertion sort. */ next = NULL; for (nn = mdoc->last->child->next; nn; nn = next) { /* Determine order of `nn'. */ for (i = 0; i < RSORD_MAX; i++) if (rsord[i] == nn->tok) break; /* * Remove `nn' from the chain. This somewhat * repeats mdoc_node_unlink(), but since we're * just re-ordering, there's no need for the * full unlink process. */ if (NULL != (next = nn->next)) next->prev = nn->prev; if (NULL != (prev = nn->prev)) prev->next = nn->next; nn->prev = nn->next = NULL; /* * Scan back until we reach a node that's * ordered before `nn'. */ for ( ; prev ; prev = prev->prev) { /* Determine order of `prev'. */ for (j = 0; j < RSORD_MAX; j++) if (rsord[j] == prev->tok) break; if (j <= i) break; } /* * Set `nn' back into its correct place in front * of the `prev' node. */ nn->prev = prev; if (prev) { if (prev->next) prev->next->prev = nn; nn->next = prev->next; prev->next = nn; } else { mdoc->last->child->prev = nn; nn->next = mdoc->last->child; mdoc->last->child = nn; } } return(1); }
static int post_bl_head(POST_ARGS) { struct mdoc_node *np, *nn, *nnp; int i, j; if (LIST_column != mdoc->last->norm->Bl.type) /* FIXME: this should be ERROR class... */ return(hwarn_eq0(mdoc)); /* * Convert old-style lists, where the column width specifiers * trail as macro parameters, to the new-style ("normal-form") * lists where they're argument values following -column. */ /* First, disallow both types and allow normal-form. */ /* * TODO: technically, we can accept both and just merge the two * lists, but I'll leave that for another day. */ if (mdoc->last->norm->Bl.ncols && mdoc->last->nchild) { mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_COLUMNS); return(0); } else if (NULL == mdoc->last->child) return(1); np = mdoc->last->parent; assert(np->args); for (j = 0; j < (int)np->args->argc; j++) if (MDOC_Column == np->args->argv[j].arg) break; assert(j < (int)np->args->argc); assert(0 == np->args->argv[j].sz); /* * Accomodate for new-style groff column syntax. Shuffle the * child nodes, all of which must be TEXT, as arguments for the * column field. Then, delete the head children. */ np->args->argv[j].sz = (size_t)mdoc->last->nchild; np->args->argv[j].value = mandoc_malloc ((size_t)mdoc->last->nchild * sizeof(char *)); mdoc->last->norm->Bl.ncols = np->args->argv[j].sz; mdoc->last->norm->Bl.cols = (const char **)np->args->argv[j].value; for (i = 0, nn = mdoc->last->child; nn; i++) { np->args->argv[j].value[i] = nn->string; nn->string = NULL; nnp = nn; nn = nn->next; mdoc_node_delete(NULL, nnp); } mdoc->last->nchild = 0; mdoc->last->child = NULL; return(1); }