=================================================================== RCS file: /cvs/pod2mdoc/pod2mdoc.c,v retrieving revision 1.32 retrieving revision 1.38 diff -u -p -r1.32 -r1.38 --- pod2mdoc/pod2mdoc.c 2014/07/18 05:09:32 1.32 +++ pod2mdoc/pod2mdoc.c 2015/02/13 12:40:54 1.38 @@ -1,6 +1,7 @@ -/* $Id: pod2mdoc.c,v 1.32 2014/07/18 05:09:32 schwarze Exp $ */ +/* $Id: pod2mdoc.c,v 1.38 2015/02/13 12:40:54 schwarze Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons + * Copyright (c) 2014, 2015 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,6 +27,8 @@ #include #include +#include "dict.h" + /* * In what section can we find Perl module manuals? * Sometimes (Mac OS X) it's 3pm, sometimes (OpenBSD, etc.) 3p. @@ -169,6 +172,7 @@ outbuf_addstr(struct state *st, const char *str) if (st->outbuflen + slen >= st->outbufsz) outbuf_grow(st, slen); memcpy(st->outbuf + st->outbuflen, str, slen+1); + st->outbuflen += slen; last = str[slen - 1]; st->wantws = 0; } @@ -242,7 +246,7 @@ formatescape(struct state *st, const char *buf, size_t outbuf_addstr(st, "\\(la"); else if (0 == strcmp(esc, "gt")) outbuf_addstr(st, "\\(ra"); - else if (0 == strcmp(esc, "vb")) + else if (0 == strcmp(esc, "verbar")) outbuf_addstr(st, "\\(ba"); else if (0 == strcmp(esc, "sol")) outbuf_addstr(st, "\\(sl"); @@ -469,7 +473,7 @@ again: * We usually exit in OUST_MAC mode, except when * entering without OUST_MAC and the code is invalid. */ -static void +static int formatcode(struct state *st, const char *buf, size_t *start, size_t end, int nomacro, int pos) { @@ -512,7 +516,7 @@ formatcode(struct state *st, const char *buf, size_t * */ if (FMT_ESCAPE == fmt) { formatescape(st, buf, start, end); - return; + return(0); } else if (FMT_NULL == fmt || FMT_INDEX == fmt) { /* * Just consume til the end delimiter, accounting for @@ -542,7 +546,7 @@ formatcode(struct state *st, const char *buf, size_t * if (isspace(last)) while (*start < end && isspace((int)buf[*start])) (*start)++; - return; + return(0); } /* @@ -611,8 +615,16 @@ formatcode(struct state *st, const char *buf, size_t * } if (0 == strncmp(buf + *start, "NULL", 4) && ('=' == buf[*start + 4] || - '>' == buf[*start + 4])) + '>' == buf[*start + 4])) { printf("Dv "); + break; + } + i = 0; + while (isalnum((unsigned char)buf[*start + i]) || + '_' == buf[*start + i]) + i++; + if (i && MDOC_Fa == dict_get(buf + *start, i)) + printf("Fa "); else printf("Sy "); break; @@ -665,7 +677,8 @@ formatcode(struct state *st, const char *buf, size_t * break; } } - if (*start + 1 < end && '<' == buf[*start + 1]) { + if (*start + 1 < end && '<' == buf[*start + 1] && + 'A' <= buf[*start] && 'Z' >= buf[*start]) { formatcode(st, buf, start, end, nomacro, 1); continue; } @@ -680,7 +693,7 @@ formatcode(struct state *st, const char *buf, size_t * continue; } - if (OUST_MAC == st->oust) { + if (OUST_MAC == st->oust && FMT__MAX != fmt) { if ( ! st->wantws) { printf(" Ns "); st->wantws = 1; @@ -708,11 +721,14 @@ formatcode(struct state *st, const char *buf, size_t * putchar('e'); } + if (FMT__MAX == fmt) + return(0); + if ( ! nomacro && FMT_CODE == fmt) printf(" Qc "); - if (FMT__MAX != fmt) - st->wantws = ' ' == last; + st->wantws = ' ' == last; + return(1); } /* @@ -725,27 +741,52 @@ static void formatcodeln(struct state *st, const char *linemac, const char *buf, size_t *start, size_t end, int nomacro) { + int gotmacro, wantws; assert(OUST_NL == st->oust); assert(st->wantws); printf(".%s ", linemac); st->oust = OUST_MAC; - last = ' '; + gotmacro = 0; while (*start < end) { - if (*start + 1 < end && '<' == buf[*start + 1]) { - formatcode(st, buf, start, end, nomacro, 1); + wantws = ' ' == buf[*start] || '\n' == buf[*start]; + if (wantws) { + last = ' '; + do { + (*start)++; + } while (*start < end && ' ' == buf[*start]); + } + + if (*start + 1 < end && '<' == buf[*start + 1] && + 'A' <= buf[*start] && 'Z' >= buf[*start]) { + st->wantws |= wantws; + gotmacro = formatcode(st, buf, + start, end, nomacro, 1); continue; } - if (OUST_MAC == st->oust) { - if ( ! st->wantws && - ' ' != buf[*start] && - '\n' != buf[*start]) - printf(" Ns "); - st->wantws = 1; + if (gotmacro) { + if (*start < end || st->outbuflen) { + if (st->wantws || + (wantws && !st->outbuflen)) + printf(" No "); + else + printf(" Ns "); + } + gotmacro = 0; } + outbuf_flush(st); + st->wantws = wantws; + if (*start >= end) + break; + + if (st->wantws) { + putchar(' '); + st->wantws = 0; + } + /* * Since we're already on a macro line, we want to make * sure that we don't inadvertently invoke a macro. @@ -754,18 +795,15 @@ formatcodeln(struct state *st, const char *linemac, * something that needn't be escaped. */ if (' ' == last && end - *start > 1 && - isupper((int)buf[*start]) && - islower((int)buf[*start + 1]) && - (end - *start == 2 || - ' ' == buf[*start + 2])) + isupper((unsigned char)buf[*start]) && + islower((unsigned char)buf[*start + 1]) && + (end - *start == 2 || ' ' == buf[*start + 2])) printf("\\&"); - if ('\n' == buf[*start]) - putchar(last = ' '); - else - putchar(last = buf[*start]); + putchar(last = buf[*start]); /* Protect against character escapes. */ + if ('\\' == last) putchar('e'); @@ -981,11 +1019,13 @@ command(struct state *st, const char *buf, size_t star * always stays in OUST_NL/wantws mode. */ static void -verbatim(struct state *st, const char *buf, size_t start, size_t end) +verbatim(struct state *st, char *buf, size_t start, size_t end) { - size_t i; + size_t i, ift, ifo, ifa, ifc, inl; + char *cp, *cp2; + int nopen; - if ( ! st->parsing || st->paused) + if ( ! st->parsing || st->paused || start == end) return; again: /* @@ -996,10 +1036,11 @@ again: */ if (SECT_SYNOPSIS == st->sect) { i = start; - for (i = start; i < end && ' ' == buf[i]; i++) - /* Spin. */ ; + while (i < end && buf[i] == ' ') + i++; if (i == end) return; + /* We're an include block! */ if (end - i > 10 && 0 == memcmp(&buf[i], "#include <", 10)) { @@ -1020,10 +1061,98 @@ again: goto again; return; } + + /* Parse function declaration. */ + ifo = ifa = ifc = 0; + inl = end; + nopen = 0; + for (ift = i; i < end; i++) { + if (ifc) { + if (buf[i] != '\n') + continue; + inl = i; + break; + } + switch (buf[i]) { + case ' ': + if ( ! ifa) + ifo = i; + break; + case '(': + if (ifo) { + nopen++; + if ( ! ifa) + ifa = i; + } else + i = end; + break; + case ')': + switch (nopen) { + case 0: + i = end; + break; + case 1: + ifc = i; + break; + default: + nopen--; + break; + } + break; + default: + break; + } + } + + /* Encode function declaration. */ + if (ifc) { + for (i = ifa; i < ifc; i++) + if (buf[i] == '\n') + buf[i] = ' '; + buf[ifo++] = '\0'; + printf(".Ft %s", buf + ift); + if (buf[ifo] == '*') { + fputs(" *", stdout); + ifo++; + } + putchar('\n'); + buf[ifa++] = '\0'; + printf(".Fo %s\n", buf + ifo); + dict_put(buf + ifo, MDOC_Fo); + buf[ifc++] = '\0'; + for (;;) { + cp = strchr(buf + ifa, ','); + if (cp != NULL) { + cp2 = cp; + *cp++ = '\0'; + } else + cp2 = strchr(buf + ifa, '\0'); + while (isalnum((unsigned char)cp2[-1]) || + '_' == cp2[-1]) + cp2--; + if ('\0' != *cp2) + dict_put(cp2, MDOC_Fa); + printf(".Fa \"%s\"\n", buf + ifa); + if (cp == NULL) + break; + while (*cp == ' ') + cp++; + ifa = cp - buf; + } + puts(".Fc"); + if (buf[ifc] == ';') + ifc++; + if (ifc < inl) { + buf[inl] = '\0'; + puts(buf + ifc); + } + start = inl + 1; + if (start < end) + goto again; + return; + } } - if (start == end) - return; puts(".Bd -literal"); for (last = ' '; start < end; start++) { /* @@ -1195,7 +1324,8 @@ ordinary(struct state *st, const char *buf, size_t sta * Escape initial control characters. */ while (start < end) { - if (start < end - 1 && '<' == buf[start + 1]) + if (start < end - 1 && '<' == buf[start + 1] && + 'A' <= buf[start] && 'Z' >= buf[start]) break; else if ('\n' == buf[start]) break; @@ -1223,15 +1353,30 @@ ordinary(struct state *st, const char *buf, size_t sta */ last = buf[start++]; - if (' ' == last) { - outbuf_flush(st); - putchar(' '); - st->wantws = 1; - } else + if (' ' != last) { outbuf_addchar(st); + continue; + } + + if ( ! strcmp(st->outbuf + st->outbuflen - 2, "()") && + dict_get(st->outbuf, st->outbuflen - 2) == + MDOC_Fo) { + st->outbuflen -= 2; + st->outbuf[st->outbuflen] = '\0'; + mdoc_newln(st); + fputs(".Fn ", stdout); + outbuf_flush(st); + mdoc_newln(st); + continue; + } + + outbuf_flush(st); + putchar(' '); + st->wantws = 1; } - if (start < end - 1 && '<' == buf[start + 1]) { + if (start < end - 1 && '<' == buf[start + 1] && + 'A' <= buf[start] && 'Z' >= buf[start]) { formatcode(st, buf, &start, end, 0, seq); if (OUST_MAC == st->oust) { /* @@ -1269,7 +1414,9 @@ ordinary(struct state *st, const char *buf, size_t sta */ if ( ! st->wantws && start < end && - '<' != buf[start + 1]) { + ('<' != buf[start + 1] || + 'A' > buf[start] || + 'Z' < buf[start])) { printf(" Ns "); st->wantws = 1; } @@ -1304,7 +1451,7 @@ ordinary(struct state *st, const char *buf, size_t sta * (default: starts with "="). */ static void -dopar(struct state *st, const char *buf, size_t start, size_t end) +dopar(struct state *st, char *buf, size_t start, size_t end) { assert(OUST_NL == st->oust); @@ -1326,7 +1473,7 @@ dopar(struct state *st, const char *buf, size_t start, */ static void dofile(const struct args *args, const char *fname, - const struct tm *tm, const char *buf, size_t sz) + const struct tm *tm, char *buf, size_t sz) { char datebuf[64]; struct state st; @@ -1391,6 +1538,7 @@ dofile(const struct args *args, const char *fname, free(title); + dict_init(); memset(&st, 0, sizeof(struct state)); st.oust = OUST_NL; st.wantws = 1; @@ -1418,6 +1566,7 @@ dofile(const struct args *args, const char *fname, dopar(&st, buf, cur, end); cur = sup; } + dict_destroy(); } /*