=================================================================== RCS file: /cvs/pod2mdoc/pod2mdoc.c,v retrieving revision 1.23 retrieving revision 1.30 diff -u -p -r1.23 -r1.30 --- pod2mdoc/pod2mdoc.c 2014/04/07 11:46:03 1.23 +++ pod2mdoc/pod2mdoc.c 2014/07/15 19:00:48 1.30 @@ -1,4 +1,4 @@ -/* $Id: pod2mdoc.c,v 1.23 2014/04/07 11:46:03 kristaps Exp $ */ +/* $Id: pod2mdoc.c,v 1.30 2014/07/15 19:00:48 schwarze Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons * @@ -181,7 +181,6 @@ trylink(const char *buf, size_t *start, size_t end, si { size_t linkstart, realend, linkend, i, j, textsz, stack; - const char *text; /* * Scan to the start of the terminus. @@ -218,7 +217,6 @@ trylink(const char *buf, size_t *start, size_t end, si linkend = dsz > 1 ? realend - 1 : realend; /* Re-scan to see if we have a title or section. */ - text = &buf[*start]; for (textsz = *start; textsz < linkend; textsz++) if ('|' == buf[textsz] || '/' == buf[textsz]) break; @@ -399,19 +397,12 @@ formatcode(struct state *st, const char *buf, size_t * /* * First, look up the format code. - * If it's not valid, then exit immediately. + * If it's not valid, treat it as a NOOP. */ for (fmt = 0; fmt < FMT__MAX; fmt++) if (buf[*start] == fmts[fmt]) break; - if (FMT__MAX == fmt) { - putchar(last = buf[(*start)++]); - if ('\\' == last) - putchar('e'); - return(0); - } - /* * Determine whether we're overriding our delimiter. * According to POD, if we have more than one '<' followed by a @@ -460,6 +451,13 @@ formatcode(struct state *st, const char *buf, size_t * (*start) += dsz; break; } + if (*start < end) { + assert('>' == buf[*start]); + (*start)++; + } + if (isspace(last)) + while (*start < end && isspace((int)buf[*start])) + (*start)++; return(0); } @@ -467,7 +465,7 @@ formatcode(struct state *st, const char *buf, size_t * * Check whether we're supposed to print macro stuff (this is * suppressed in, e.g., "Nm" and "Sh" macros). */ - if ( ! nomacro) { + if (FMT__MAX != fmt && !nomacro) { /* * Print out the macro describing this format code. * If we're not "reentrant" (not yet on a macro line) @@ -504,7 +502,12 @@ formatcode(struct state *st, const char *buf, size_t * printf("Ar "); break; } - printf("Sy "); + if (0 == strncmp(buf + *start, "NULL", 4) && + ('=' == buf[*start + 4] || + '>' == buf[*start + 4])) + printf("Dv "); + else + printf("Sy "); break; case (FMT_CODE): printf("Qo Li "); @@ -589,6 +592,9 @@ formatcode(struct state *st, const char *buf, size_t * (*start)++; } + if (FMT__MAX == fmt) + return(0); + if ( ! nomacro && FMT_CODE == fmt) printf(" Qc "); @@ -1085,18 +1091,12 @@ ordinary(struct state *st, const char *buf, size_t sta } if (start < end - 1 && '<' == buf[start + 1]) { - /* - * We've encountered a format code. - * This is going to trigger a macro no matter - * what, so print a newline now. - * Then print the (possibly nested) macros and - * following that, a newline. - * Consume all whitespace so we don't - * accidentally start an implicit literal line. - * If the macro ends with a flush comma or - * period, let mdoc(7) handle it for us. - */ if (formatcode(st, buf, &start, end, 0, 0, seq)) { + /* + * Let mdoc(7) handle trailing punctuation. + * XXX Some punctuation characters + * are not handled yet. + */ if ((start == end - 1 || (start < end - 1 && (' ' == buf[start + 1] || @@ -1106,7 +1106,13 @@ ordinary(struct state *st, const char *buf, size_t sta putchar(' '); putchar(buf[start++]); } + /* End the macro line. */ putchar(last = '\n'); + /* + * Consume all whitespace + * so we don't accidentally start + * an implicit literal line. + */ while (start < end && ' ' == buf[start]) start++; } @@ -1168,24 +1174,40 @@ static void dofile(const struct args *args, const char *fname, const struct tm *tm, const char *buf, size_t sz) { - size_t sup, end, i, cur = 0; - struct state st; - const char *section, *date; char datebuf[64]; + struct state st; + const char *fbase, *fext, *section, *date; char *title, *cp; + size_t sup, end, i, cur = 0; if (0 == sz) return; - /* Title is last path component of the filename. */ + /* + * Parsing the filename is almost always required, + * except when both the title and the section + * are provided on the command line. + */ - if (NULL != args->title) - title = strdup(args->title); - else if (NULL != (cp = strrchr(fname, '/'))) - title = strdup(cp + 1); - else - title = strdup(fname); - + if (NULL == args->title || NULL == args->section) { + fbase = strrchr(fname, '/'); + if (NULL == fbase) + fbase = fname; + else + fbase++; + fext = strrchr(fbase, '.'); + } else + fext = NULL; + + /* + * The title will be converted to uppercase, + * so it needs to be copied. + */ + + title = (NULL != args->title) ? strdup(args->title) : + (NULL != fext) ? strndup(fbase, fext - fbase) : + strdup(fbase); + if (NULL == title) { perror(NULL); exit(EXIT_FAILURE); @@ -1193,14 +1215,9 @@ dofile(const struct args *args, const char *fname, /* Section is 1 unless suffix is "pm". */ - if (NULL == (section = args->section)) { - section = "1"; - if (NULL != (cp = strrchr(title, '.'))) { - *cp++ = '\0'; - if (0 == strcmp(cp, "pm")) - section = PERL_SECTION; - } - } + section = (NULL != args->section) ? args->section : + (NULL == fext || strcmp(fext + 1, "pm")) ? "1" : + PERL_SECTION; /* Date. Or the given "tm" if not supplied. */ @@ -1263,8 +1280,6 @@ readfile(const struct args *args, const char *fname) time_t ttm; struct stat st; - assert(NULL != fname); - fd = 0 != strcmp("-", fname) ? open(fname, O_RDONLY, 0) : STDIN_FILENO; @@ -1370,8 +1385,8 @@ main(int argc, char *argv[]) /* Accept only a single input file. */ - if (argc > 2) - return(EXIT_FAILURE); + if (argc > 1) + goto usage; else if (1 == argc) fname = *argv; @@ -1380,7 +1395,7 @@ main(int argc, char *argv[]) usage: fprintf(stderr, "usage: %s [-d date] " - "[-n title] [-s section]\n", name); + "[-n title] [-s section] [file]\n", name); return(EXIT_FAILURE); }