=================================================================== RCS file: /cvs/mandoc/out.c,v retrieving revision 1.8 retrieving revision 1.15 diff -u -p -r1.8 -r1.15 --- mandoc/out.c 2009/11/07 08:26:45 1.8 +++ mandoc/out.c 2010/04/07 11:29:55 1.15 @@ -1,4 +1,4 @@ -/* $Id: out.c,v 1.8 2009/11/07 08:26:45 kristaps Exp $ */ +/* $Id: out.c,v 1.15 2010/04/07 11:29:55 kristaps Exp $ */ /* * Copyright (c) 2009 Kristaps Dzonsons * @@ -14,6 +14,10 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include @@ -25,10 +29,26 @@ #include "out.h" -#ifdef __linux__ -extern size_t strlcat(char *, const char *, size_t); -#endif +/* See a2roffdeco(). */ +#define C2LIM(c, l) do { \ + (l) = 1; \ + if ('[' == (c) || '\'' == (c)) \ + (l) = 0; \ + else if ('(' == (c)) \ + (l) = 2; } \ + while (/* CONSTCOND */ 0) +/* See a2roffdeco(). */ +#define C2TERM(c, t) do { \ + (t) = 0; \ + if ('\'' == (c)) \ + (t) = 1; \ + else if ('[' == (c)) \ + (t) = 2; \ + else if ('(' == (c)) \ + (t) = 3; } \ + while (/* CONSTCOND */ 0) + /* * Convert a `scaling unit' to a consistent form, or fail. Scaling * units are documented in groff.7, mdoc.7, man.7. @@ -167,26 +187,29 @@ time2a(time_t t, char *dst, size_t sz) } -/* Returns length of parsed string. */ +/* + * Returns length of parsed string (the leading "\" should NOT be + * included). This can be zero if the current character is the nil + * terminator. "d" is set to the type of parsed decorator, which may + * have an adjoining "word" of size "sz" (e.g., "(ab" -> "ab", 2). + */ int a2roffdeco(enum roffdeco *d, const char **word, size_t *sz) { - int j, type, sv, t, lim; - const char *wp; + int j, term, lim; + char set; + const char *wp, *sp; *d = DECO_NONE; - wp = *word; - type = 1; - switch (*wp) { + switch ((set = *wp)) { case ('\0'): return(0); case ('('): - wp++; - if ('\0' == *wp) + if ('\0' == *(++wp)) return(1); if ('\0' == *(wp + 1)) return(2); @@ -196,16 +219,74 @@ a2roffdeco(enum roffdeco *d, *word = wp; return(3); - case ('*'): - wp++; + case ('F'): + /* FALLTHROUGH */ + case ('f'): + /* + * FIXME: this needs work and consolidation (it should + * follow the sequence that special characters do, for + * one), but isn't a priority at the moment. Note, for + * one, that in reality \fB != \FB, although here we let + * these slip by. + */ + switch (*(++wp)) { + case ('\0'): + return(1); + case ('3'): + /* FALLTHROUGH */ + case ('B'): + *d = DECO_BOLD; + return(2); + case ('2'): + /* FALLTHROUGH */ + case ('I'): + *d = DECO_ITALIC; + return(2); + case ('P'): + *d = DECO_PREVIOUS; + return(2); + case ('1'): + /* FALLTHROUGH */ + case ('R'): + *d = DECO_ROMAN; + return(2); + case ('('): + if ('\0' == *(++wp)) + return(2); + if ('\0' == *(wp + 1)) + return(3); - switch (*wp) { + *d = 'F' == set ? DECO_FFONT : DECO_FONT; + *sz = 2; + *word = wp; + return(4); + case ('['): + *word = ++wp; + for (j = 0; *wp && ']' != *wp; wp++, j++) + /* Loop... */ ; + + if ('\0' == *wp) + return(j + 2); + + *d = 'F' == set ? DECO_FFONT : DECO_FONT; + *sz = (size_t)j; + return(j + 3); + default: + break; + } + + *d = 'F' == set ? DECO_FFONT : DECO_FONT; + *sz = 1; + *word = wp; + return(2); + + case ('*'): + switch (*(++wp)) { case ('\0'): return(1); case ('('): - wp++; - if ('\0' == *wp) + if ('\0' == *(++wp)) return(2); if ('\0' == *(wp + 1)) return(3); @@ -216,145 +297,103 @@ a2roffdeco(enum roffdeco *d, return(4); case ('['): - type = 0; - break; + *word = ++wp; + for (j = 0; *wp && ']' != *wp; wp++, j++) + /* Loop... */ ; - default: + if ('\0' == *wp) + return(j + 2); + *d = DECO_RESERVED; - *sz = 1; - *word = wp; - return(3); + *sz = (size_t)j; + return(j + 3); + + default: + break; } - break; -#if 0 - case ('s'): - wp++; + *d = DECO_RESERVED; + *sz = 1; + *word = wp; + return(2); - /* This closely follows mandoc_special(). */ - if ('\0' == *wp) + case ('s'): + sp = wp; + if ('\0' == *(++wp)) return(1); - t = 0; - lim = 1; + C2LIM(*wp, lim); + C2TERM(*wp, term); - if (*wp == '\'') { - lim = 0; - t = 1; - ++wp; - } else if (*wp == '[') { - lim = 0; - t = 2; - ++wp; - } else if (*wp == '(') { - lim = 2; - t = 3; - ++wp; - } + if (term) + wp++; + *word = wp; + if (*wp == '+' || *wp == '-') ++wp; - if (*wp == '\'') { - if (t) { - *word = wp; - return; - } - lim = 0; - t = 1; - ++wp; - } else if (*wp == '[') { - if (t) { - *word = wp; - return; - } - lim = 0; - t = 2; - ++wp; - } else if (*wp == '(') { - if (t) { - *word = wp; - return; - } - lim = 2; - t = 3; - ++wp; - } + switch (*wp) { + case ('\''): + /* FALLTHROUGH */ + case ('['): + /* FALLTHROUGH */ + case ('('): + if (term) + return((int)(wp - sp)); - if ( ! isdigit((u_char)*wp)) { - *word = --wp; - return; + C2LIM(*wp, lim); + C2TERM(*wp, term); + wp++; + break; + default: + break; } + if ( ! isdigit((u_char)*wp)) + return((int)(wp - sp)); + for (j = 0; isdigit((u_char)*wp); j++) { if (lim && j >= lim) break; ++wp; } - if (t && t < 3) { - if (1 == t && *wp != '\'') { - *word = --wp; - return; - } - if (2 == t && *wp != ']') { - *word = --wp; - return; - } + if (term && term < 3) { + if (1 == term && *wp != '\'') + return((int)(wp - sp)); + if (2 == term && *wp != ']') + return((int)(wp - sp)); ++wp; } - *word = --wp; - return; -#endif - case ('f'): - wp++; + *d = DECO_SIZE; + return((int)(wp - sp)); - switch (*wp) { - case ('\0'): - return(1); - case ('3'): - /* FALLTHROUGH */ - case ('B'): - *d = DECO_BOLD; - break; - case ('2'): - /* FALLTHROUGH */ - case ('I'): - *d = DECO_ITALIC; - break; - case ('P'): - *d = DECO_PREVIOUS; - break; - case ('1'): - /* FALLTHROUGH */ - case ('R'): - *d = DECO_ROMAN; - break; - default: - break; - } + case ('['): + *word = ++wp; - return(2); + for (j = 0; *wp && ']' != *wp; wp++, j++) + /* Loop... */ ; - case ('['): - break; + if ('\0' == *wp) + return(j + 1); - default: *d = DECO_SPECIAL; - *word = wp; + *sz = (size_t)j; + return(j + 2); + + case ('c'): + *d = DECO_NOSPACE; *sz = 1; return(1); + + default: + break; } - *word = ++wp; - for (j = 0; *wp && ']' != *wp; wp++, j++) - /* Loop... */ ; - - if ('\0' == *wp) - return(j + 1); - - *d = type ? DECO_SPECIAL : DECO_RESERVED; - *sz = j; - return (j + 2); + *d = DECO_SPECIAL; + *word = wp; + *sz = 1; + return(1); }