=================================================================== RCS file: /cvs/mandoc/mdoc.c,v retrieving revision 1.176 retrieving revision 1.189 diff -u -p -r1.176 -r1.189 --- mandoc/mdoc.c 2011/01/01 12:59:17 1.176 +++ mandoc/mdoc.c 2011/07/18 07:46:41 1.189 @@ -1,6 +1,6 @@ -/* $Id: mdoc.c,v 1.176 2011/01/01 12:59:17 kristaps Exp $ */ +/* $Id: mdoc.c,v 1.189 2011/07/18 07:46:41 kristaps Exp $ */ /* - * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons + * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any @@ -28,6 +28,7 @@ #include #include +#include "mdoc.h" #include "mandoc.h" #include "libmdoc.h" #include "libmandoc.h" @@ -98,15 +99,13 @@ static int node_append(struct mdoc *, struct mdoc_node *); static int mdoc_ptext(struct mdoc *, int, char *, int); static int mdoc_pmacro(struct mdoc *, int, char *, int); -static int mdoc_span_alloc(struct mdoc *, - const struct tbl_span *); - const struct mdoc_node * mdoc_node(const struct mdoc *m) { - return(MDOC_HALT & m->flags ? NULL : m->first); + assert( ! (MDOC_HALT & m->flags)); + return(m->first); } @@ -114,7 +113,8 @@ const struct mdoc_meta * mdoc_meta(const struct mdoc *m) { - return(MDOC_HALT & m->flags ? NULL : &m->meta); + assert( ! (MDOC_HALT & m->flags)); + return(&m->meta); } @@ -139,6 +139,8 @@ mdoc_free1(struct mdoc *mdoc) free(mdoc->meta.vol); if (mdoc->meta.msec) free(mdoc->meta.msec); + if (mdoc->meta.date) + free(mdoc->meta.date); } @@ -191,15 +193,14 @@ mdoc_free(struct mdoc *mdoc) * Allocate volatile and non-volatile parse resources. */ struct mdoc * -mdoc_alloc(struct regset *regs, void *data, mandocmsg msg) +mdoc_alloc(struct roff *roff, struct mparse *parse) { struct mdoc *p; p = mandoc_calloc(1, sizeof(struct mdoc)); - p->msg = msg; - p->data = data; - p->regs = regs; + p->parse = parse; + p->roff = roff; mdoc_hash_init(); mdoc_alloc1(p); @@ -215,30 +216,59 @@ int mdoc_endparse(struct mdoc *m) { - if (MDOC_HALT & m->flags) - return(0); - else if (mdoc_macroend(m)) + assert( ! (MDOC_HALT & m->flags)); + if (mdoc_macroend(m)) return(1); m->flags |= MDOC_HALT; return(0); } int -mdoc_addspan(struct mdoc *m, const struct tbl_span *sp) +mdoc_addeqn(struct mdoc *m, const struct eqn *ep) { + struct mdoc_node *n; - if (MDOC_HALT & m->flags) + assert( ! (MDOC_HALT & m->flags)); + + /* No text before an initial macro. */ + + if (SEC_NONE == m->lastnamed) { + mdoc_pmsg(m, ep->line, ep->pos, MANDOCERR_NOTEXT); + return(1); + } + + n = node_alloc(m, ep->line, ep->pos, MDOC_MAX, MDOC_EQN); + n->eqn = ep; + + if ( ! node_append(m, n)) return(0); + m->next = MDOC_NEXT_SIBLING; + return(1); +} + +int +mdoc_addspan(struct mdoc *m, const struct tbl_span *sp) +{ + struct mdoc_node *n; + + assert( ! (MDOC_HALT & m->flags)); + /* No text before an initial macro. */ if (SEC_NONE == m->lastnamed) { - /* FIXME: grab from span. */ - mdoc_pmsg(m, 0, 0, MANDOCERR_NOTEXT); + mdoc_pmsg(m, sp->line, 0, MANDOCERR_NOTEXT); return(1); } - return(mdoc_span_alloc(m, sp)); + n = node_alloc(m, sp->line, 0, MDOC_MAX, MDOC_TBL); + n->span = sp; + + if ( ! node_append(m, n)) + return(0); + + m->next = MDOC_NEXT_SIBLING; + return(1); } @@ -250,8 +280,7 @@ int mdoc_parseln(struct mdoc *m, int ln, char *buf, int offs) { - if (MDOC_HALT & m->flags) - return(0); + assert( ! (MDOC_HALT & m->flags)); m->flags |= MDOC_NEWLINE; @@ -261,35 +290,19 @@ mdoc_parseln(struct mdoc *m, int ln, char *buf, int of * whether this mode is on or off. * Note that this mode is also switched by the Sh macro. */ - if (m->regs->regs[(int)REG_nS].set) { - if (m->regs->regs[(int)REG_nS].v.u) + if (roff_regisset(m->roff, REG_nS)) { + if (roff_regget(m->roff, REG_nS)) m->flags |= MDOC_SYNOPSIS; else m->flags &= ~MDOC_SYNOPSIS; } - return(('.' == buf[offs] || '\'' == buf[offs]) ? + return(mandoc_getcontrol(buf, &offs) ? mdoc_pmacro(m, ln, buf, offs) : mdoc_ptext(m, ln, buf, offs)); } - int -mdoc_vmsg(struct mdoc *mdoc, enum mandocerr t, - int ln, int pos, const char *fmt, ...) -{ - char buf[256]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf) - 1, fmt, ap); - va_end(ap); - - return((*mdoc->msg)(t, mdoc->data, ln, pos, buf)); -} - - -int mdoc_macro(MACRO_PROT_ARGS) { assert(tok < MDOC_MAX); @@ -315,8 +328,9 @@ mdoc_macro(MACRO_PROT_ARGS) 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); + if (NULL == m->meta.date) + m->meta.date = mandoc_normdate + (m->parse, NULL, line, ppos); m->flags |= MDOC_PBODY; } @@ -547,23 +561,6 @@ mdoc_elem_alloc(struct mdoc *m, int line, int pos, return(1); } -static int -mdoc_span_alloc(struct mdoc *m, const struct tbl_span *sp) -{ - struct mdoc_node *n; - - /* FIXME: grab from tbl_span. */ - n = node_alloc(m, 0, 0, MDOC_MAX, MDOC_TBL); - n->span = sp; - - if ( ! node_append(m, n)) - return(0); - - m->next = MDOC_NEXT_SIBLING; - return(1); -} - - int mdoc_word_alloc(struct mdoc *m, int line, int pos, const char *p) { @@ -664,15 +661,6 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int of char *c, *ws, *end; struct mdoc_node *n; - /* Ignore bogus comments. */ - - if ('\\' == buf[offs] && - '.' == buf[offs + 1] && - '"' == buf[offs + 2]) { - mdoc_pmsg(m, line, offs, MANDOCERR_BADCOMMENT); - return(1); - } - /* No text before an initial macro. */ if (SEC_NONE == m->lastnamed) { @@ -799,64 +787,57 @@ static int mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs) { enum mdoct tok; - int i, j, sv; + int i, sv; char mac[5]; struct mdoc_node *n; - /* Empty lines are ignored. */ + /* Empty post-control lines are ignored. */ - offs++; - - if ('\0' == buf[offs]) + if ('"' == buf[offs]) { + mdoc_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT); return(1); + } else if ('\0' == buf[offs]) + return(1); - i = offs; + sv = 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'; + i = 0; + while (i < 4 && '\0' != buf[offs] && + ' ' != buf[offs] && '\t' != buf[offs]) + mac[i++] = buf[offs++]; - tok = (j > 1 || j < 4) ? mdoc_hash_find(mac) : MDOC_MAX; + mac[i] = '\0'; + + tok = (i > 1 || i < 4) ? mdoc_hash_find(mac) : MDOC_MAX; + if (MDOC_MAX == tok) { - mdoc_vmsg(m, MANDOCERR_MACRO, ln, sv, "%s", buf + sv - 1); + mandoc_vmsg(MANDOCERR_MACRO, m->parse, + ln, sv, "%s", buf + sv - 1); return(1); } /* Disregard the first trailing tab, if applicable. */ - if ('\t' == buf[i]) - i++; + if ('\t' == buf[offs]) + offs++; /* Jump to the next non-whitespace word. */ - while (buf[i] && ' ' == buf[i]) - i++; + 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[i] && ' ' == buf[i - 1]) - mdoc_pmsg(m, ln, i - 1, MANDOCERR_EOLNSPACE); + if ('\0' == buf[offs] && ' ' == buf[offs - 1]) + mdoc_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE); /* * If an initial macro or a list invocation, divert directly @@ -864,7 +845,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int off */ if (NULL == m->last || MDOC_It == tok || MDOC_El == tok) { - if ( ! mdoc_macro(m, tok, ln, sv, &i, buf)) + if ( ! mdoc_macro(m, tok, ln, sv, &offs, buf)) goto err; return(1); } @@ -903,7 +884,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int off /* Normal processing of a macro. */ - if ( ! mdoc_macro(m, tok, ln, sv, &i, buf)) + if ( ! mdoc_macro(m, tok, ln, sv, &offs, buf)) goto err; return(1); @@ -914,4 +895,48 @@ err: /* Error out. */ return(0); } +enum mdelim +mdoc_isdelim(const char *p) +{ + if ('\0' == p[0]) + return(DELIM_NONE); + + if ('\0' == p[1]) + switch (p[0]) { + case('('): + /* FALLTHROUGH */ + case('['): + return(DELIM_OPEN); + case('|'): + return(DELIM_MIDDLE); + case('.'): + /* FALLTHROUGH */ + case(','): + /* FALLTHROUGH */ + case(';'): + /* FALLTHROUGH */ + case(':'): + /* FALLTHROUGH */ + case('?'): + /* FALLTHROUGH */ + case('!'): + /* FALLTHROUGH */ + case(')'): + /* FALLTHROUGH */ + case(']'): + return(DELIM_CLOSE); + default: + return(DELIM_NONE); + } + + if ('\\' != p[0]) + return(DELIM_NONE); + + if (0 == strcmp(p + 1, ".")) + return(DELIM_CLOSE); + if (0 == strcmp(p + 1, "*(Ba")) + return(DELIM_MIDDLE); + + return(DELIM_NONE); +}