=================================================================== RCS file: /cvs/mandoc/mdoc.c,v retrieving revision 1.124 retrieving revision 1.128 diff -u -p -r1.124 -r1.128 --- mandoc/mdoc.c 2010/05/07 15:49:36 1.124 +++ mandoc/mdoc.c 2010/05/12 16:01:01 1.128 @@ -1,4 +1,4 @@ -/* $Id: mdoc.c,v 1.124 2010/05/07 15:49:36 kristaps Exp $ */ +/* $Id: mdoc.c,v 1.128 2010/05/12 16:01:01 kristaps Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons * @@ -542,7 +542,7 @@ mdoc_word_alloc(struct mdoc *m, int line, int pos, con len = strlen(p); - n = node_alloc(m, line, pos, -1, MDOC_TEXT); + n = node_alloc(m, line, pos, MDOC_MAX, MDOC_TEXT); n->string = mandoc_malloc(len + 1); sv = strlcpy(n->string, p, len + 1); @@ -665,29 +665,65 @@ mdoc_ptext(struct mdoc *m, int line, char *buf) return(1); } - /* Warn if the last un-escaped character is whitespace. */ + /* + * Warn if the last un-escaped character is whitespace. Then + * strip away the remaining spaces (tabs stay!). + */ i = (int)strlen(buf); assert(i); - if (' ' == buf[i - 1] || '\t' == buf[i - 1]) - if (1 == i || ('\\' != buf[i - 2])) + if (' ' == buf[i - 1] || '\t' == buf[i - 1]) { + if (i > 1 && '\\' != buf[i - 2]) if ( ! mdoc_pwarn(m, line, i - 1, ETAILWS)) return(0); + for (--i; i && ' ' == buf[i]; i--) + /* Spin back to non-space. */ ; + + /* Jump ahead of escaped whitespace. */ + i += '\\' == buf[i] ? 2 : 1; + + buf[i] = '\0'; + } + /* Allocate the whole word. */ - return(mdoc_word_alloc(m, line, 0, buf)); -} + if ( ! mdoc_word_alloc(m, line, 0, buf)) + return(0); + /* + * End-of-sentence check. If the last character is an unescaped + * EOS character, then flag the node as being the end of a + * sentence. The front-end will know how to interpret this. + */ + assert(i); + switch (buf[i - 1]) { + case ('.'): + if (i > 1 && '\\' == buf[i - 2]) + break; + /* FALLTHROUGH */ + case ('!'): + /* FALLTHROUGH */ + case ('?'): + m->last->flags |= MDOC_EOS; + break; + default: + break; + + } + + return(1); +} + + static int macrowarn(struct mdoc *m, int ln, const char *buf) { if ( ! (MDOC_IGN_MACRO & m->pflags)) - return(mdoc_verr(m, ln, 0, - "unknown macro: %s%s", + return(mdoc_verr(m, ln, 0, "unknown macro: %s%s", buf, strlen(buf) > 3 ? "..." : "")); return(mdoc_vwarn(m, ln, 0, "unknown macro: %s%s", buf, strlen(buf) > 3 ? "..." : "")); @@ -701,8 +737,9 @@ macrowarn(struct mdoc *m, int ln, const char *buf) int mdoc_pmacro(struct mdoc *m, int ln, char *buf) { - int i, j, c; - char mac[5]; + enum mdoct tok; + int i, j; + char mac[5]; /* Empty lines are ignored. */ @@ -744,7 +781,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf) return(1); } - if (MDOC_MAX == (c = mdoc_hash_find(mac))) { + if (MDOC_MAX == (tok = mdoc_hash_find(mac))) { if ( ! macrowarn(m, ln, mac)) goto err; return(1); @@ -755,7 +792,10 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf) while (buf[i] && ' ' == buf[i]) i++; - /* Trailing whitespace? */ + /* + * 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]) if ( ! mdoc_pwarn(m, ln, i - 1, ETAILWS)) @@ -765,7 +805,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf) * Begin recursive parse sequence. Since we're at the start of * the line, we don't need to do callable/parseable checks. */ - if ( ! mdoc_macro(m, c, ln, 1, &i, buf)) + if ( ! mdoc_macro(m, tok, ln, 1, &i, buf)) goto err; return(1);