=================================================================== RCS file: /cvs/mandoc/mdoc.c,v retrieving revision 1.114 retrieving revision 1.122 diff -u -p -r1.114 -r1.122 --- mandoc/mdoc.c 2010/01/01 17:14:29 1.114 +++ mandoc/mdoc.c 2010/04/08 07:06:15 1.122 @@ -1,4 +1,4 @@ -/* $Id: mdoc.c,v 1.114 2010/01/01 17:14:29 kristaps Exp $ */ +/* $Id: mdoc.c,v 1.122 2010/04/08 07:06:15 kristaps Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons * @@ -26,6 +26,7 @@ #include #include #include +#include #include "libmdoc.h" #include "libmandoc.h" @@ -140,10 +141,13 @@ const char *const __mdoc_argnames[MDOC_ARG_MAX] = { const char * const *mdoc_macronames = __mdoc_macronames; const char * const *mdoc_argnames = __mdoc_argnames; +static void mdoc_node_free(struct mdoc_node *); +static void mdoc_node_unlink(struct mdoc *, + struct mdoc_node *); static void mdoc_free1(struct mdoc *); static void mdoc_alloc1(struct mdoc *); static struct mdoc_node *node_alloc(struct mdoc *, int, int, - int, enum mdoc_type); + enum mdoct, enum mdoc_type); static int node_append(struct mdoc *, struct mdoc_node *); static int parsetext(struct mdoc *, int, char *); @@ -176,7 +180,7 @@ mdoc_free1(struct mdoc *mdoc) { if (mdoc->first) - mdoc_node_freelist(mdoc->first); + mdoc_node_delete(mdoc, mdoc->first); if (mdoc->meta.title) free(mdoc->meta.title); if (mdoc->meta.os) @@ -341,19 +345,33 @@ mdoc_err(struct mdoc *m, int line, int pos, int iserr, int -mdoc_macro(struct mdoc *m, int tok, +mdoc_macro(struct mdoc *m, enum mdoct tok, int ln, int pp, int *pos, char *buf) { - /* - * If we're in the prologue, deny "body" macros. Similarly, if - * we're in the body, deny prologue calls. - */ + assert(tok < MDOC_MAX); + + /* If we're in the body, deny prologue calls. */ + if (MDOC_PROLOGUE & mdoc_macros[tok].flags && MDOC_PBODY & m->flags) return(mdoc_perr(m, ln, pp, EPROLBODY)); + + /* If we're in the prologue, deny "body" macros. */ + if ( ! (MDOC_PROLOGUE & mdoc_macros[tok].flags) && - ! (MDOC_PBODY & m->flags)) - return(mdoc_perr(m, ln, pp, EBODYPROL)); + ! (MDOC_PBODY & m->flags)) { + if ( ! mdoc_pwarn(m, ln, pp, EBODYPROL)) + return(0); + if (NULL == m->meta.title) + m->meta.title = mandoc_strdup("unknown"); + if (NULL == m->meta.vol) + m->meta.vol = mandoc_strdup("local"); + if (NULL == m->meta.os) + m->meta.os = mandoc_strdup("local"); + if (0 == m->meta.date) + m->meta.date = time(NULL); + m->flags |= MDOC_PBODY; + } return((*mdoc_macros[tok].fp)(m, tok, ln, pp, pos, buf)); } @@ -424,8 +442,8 @@ node_append(struct mdoc *mdoc, struct mdoc_node *p) static struct mdoc_node * -node_alloc(struct mdoc *m, int line, - int pos, int tok, enum mdoc_type type) +node_alloc(struct mdoc *m, int line, int pos, + enum mdoct tok, enum mdoc_type type) { struct mdoc_node *p; @@ -434,15 +452,14 @@ node_alloc(struct mdoc *m, int line, p->line = line; p->pos = pos; p->tok = tok; - if (MDOC_TEXT != (p->type = type)) - assert(p->tok >= 0); + p->type = type; return(p); } int -mdoc_tail_alloc(struct mdoc *m, int line, int pos, int tok) +mdoc_tail_alloc(struct mdoc *m, int line, int pos, enum mdoct tok) { struct mdoc_node *p; @@ -455,7 +472,7 @@ mdoc_tail_alloc(struct mdoc *m, int line, int pos, int int -mdoc_head_alloc(struct mdoc *m, int line, int pos, int tok) +mdoc_head_alloc(struct mdoc *m, int line, int pos, enum mdoct tok) { struct mdoc_node *p; @@ -471,7 +488,7 @@ mdoc_head_alloc(struct mdoc *m, int line, int pos, int int -mdoc_body_alloc(struct mdoc *m, int line, int pos, int tok) +mdoc_body_alloc(struct mdoc *m, int line, int pos, enum mdoct tok) { struct mdoc_node *p; @@ -485,7 +502,7 @@ mdoc_body_alloc(struct mdoc *m, int line, int pos, int int mdoc_block_alloc(struct mdoc *m, int line, int pos, - int tok, struct mdoc_arg *args) + enum mdoct tok, struct mdoc_arg *args) { struct mdoc_node *p; @@ -502,7 +519,7 @@ mdoc_block_alloc(struct mdoc *m, int line, int pos, int mdoc_elem_alloc(struct mdoc *m, int line, int pos, - int tok, struct mdoc_arg *args) + enum mdoct tok, struct mdoc_arg *args) { struct mdoc_node *p; @@ -549,8 +566,6 @@ void mdoc_node_free(struct mdoc_node *p) { - if (p->parent) - p->parent->nchild--; if (p->string) free(p->string); if (p->args) @@ -559,16 +574,53 @@ mdoc_node_free(struct mdoc_node *p) } -void -mdoc_node_freelist(struct mdoc_node *p) +static void +mdoc_node_unlink(struct mdoc *m, struct mdoc_node *n) { - if (p->child) - mdoc_node_freelist(p->child); - if (p->next) - mdoc_node_freelist(p->next); + /* Adjust siblings. */ + if (n->prev) + n->prev->next = n->next; + if (n->next) + n->next->prev = n->prev; + + /* Adjust parent. */ + + if (n->parent) { + n->parent->nchild--; + if (n->parent->child == n) + n->parent->child = n->prev ? n->prev : n->next; + } + + /* Adjust parse point, if applicable. */ + + if (m && m->last == n) { + if (n->prev) { + m->last = n->prev; + m->next = MDOC_NEXT_SIBLING; + } else { + m->last = n->parent; + m->next = MDOC_NEXT_CHILD; + } + } + + if (m && m->first == n) + m->first = NULL; +} + + +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); } @@ -581,6 +633,7 @@ static int parsetext(struct mdoc *m, int line, char *buf) { int i, j; + char sv; if (SEC_NONE == m->lastnamed) return(mdoc_perr(m, line, 0, ETEXTPROL)); @@ -597,9 +650,20 @@ parsetext(struct mdoc *m, int line, char *buf) for (i = 0; ' ' == buf[i]; i++) /* Skip leading whitespace. */ ; - if (0 == buf[i]) - return(mdoc_perr(m, line, 0, ENOBLANK)); + if ('\0' == buf[i]) { + if ( ! mdoc_pwarn(m, line, 0, ENOBLANK)) + return(0); + /* + * Assume that a `Pp' should be inserted in the case of + * a blank line. Technically, blank lines aren't + * allowed, but enough manuals assume this behaviour + * that we want to work around it. + */ + if ( ! mdoc_elem_alloc(m, line, 0, MDOC_Pp, NULL)) + return(0); + } + /* * Break apart a free-form line into tokens. Spaces are * stripped out of the input. @@ -613,15 +677,30 @@ parsetext(struct mdoc *m, int line, char *buf) if (i && ' ' == buf[i] && '\\' == buf[i - 1]) continue; - buf[i++] = 0; + sv = buf[i]; + buf[i++] = '\0'; + if ( ! pstring(m, line, j, &buf[j], (size_t)(i - j))) return(0); + /* Trailing whitespace? Check at overwritten byte. */ + + if (' ' == sv && '\0' == buf[i]) + if ( ! mdoc_pwarn(m, line, i - 1, ETAILWS)) + return(0); + for ( ; ' ' == buf[i]; i++) /* Skip trailing whitespace. */ ; j = i; - if (0 == buf[i]) + + /* Trailing whitespace? */ + + if (' ' == buf[i - 1] && '\0' == buf[i]) + if ( ! mdoc_pwarn(m, line, i - 1, ETAILWS)) + return(0); + + if ('\0' == buf[i]) break; } @@ -658,7 +737,7 @@ parsemacro(struct mdoc *m, int ln, char *buf) /* Empty lines are ignored. */ - if (0 == buf[1]) + if ('\0' == buf[1]) return(1); i = 1; @@ -669,14 +748,14 @@ parsemacro(struct mdoc *m, int ln, char *buf) i++; while (buf[i] && ' ' == buf[i]) i++; - if (0 == buf[i]) + if ('\0' == buf[i]) return(1); } /* Copy the first word into a nil-terminated buffer. */ for (j = 0; j < 4; j++, i++) { - if (0 == (mac[j] = buf[i])) + if ('\0' == (mac[j] = buf[i])) break; else if (' ' == buf[i]) break; @@ -706,6 +785,12 @@ parsemacro(struct mdoc *m, int ln, char *buf) while (buf[i] && ' ' == buf[i]) i++; + + /* Trailing whitespace? */ + + if ('\0' == buf[i] && ' ' == buf[i - 1]) + if ( ! mdoc_pwarn(m, ln, i - 1, ETAILWS)) + goto err; /* * Begin recursive parse sequence. Since we're at the start of