=================================================================== RCS file: /cvs/pod2mdoc/pod2mdoc.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -p -r1.4 -r1.5 --- pod2mdoc/pod2mdoc.c 2014/03/20 15:29:57 1.4 +++ pod2mdoc/pod2mdoc.c 2014/03/23 13:00:24 1.5 @@ -1,4 +1,4 @@ -/* $Id: pod2mdoc.c,v 1.4 2014/03/20 15:29:57 schwarze Exp $ */ +/* $Id: pod2mdoc.c,v 1.5 2014/03/23 13:00:24 kristaps Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons * @@ -154,12 +154,15 @@ formatescape(const char *buf, size_t *start, size_t en /* * Skip space characters. */ -static void +static int skipspace(const char *buf, size_t *start, size_t end) { + size_t sv = *start; while (*start < end && ' ' == buf[*start]) (*start)++; + + return(*start > sv); } /* @@ -178,10 +181,26 @@ formatcode(const char *buf, size_t *start, size_t end, int reentrant, int last, int nomacro) { enum fmt fmt; + size_t i, j, dsz; assert(*start + 1 < end); assert('<' == buf[*start + 1]); + /* + * Determine whether we're overriding our delimiter. + * According to POD, if we have more than one '<' followed by a + * space, then we need a space followed by matching '>' to close + * the expression. + * Otherwise we use the usual '<' and '>' matched pair. + */ + i = *start + 1; + while (i < end && '<' == buf[i]) + i++; + assert(i > *start + 1); + dsz = i - (*start + 1); + if (dsz > 1 && (i >= end || ' ' != buf[i])) + dsz = 1; + for (fmt = 0; fmt < FMT__MAX; fmt++) if (buf[*start] == fmts[fmt]) break; @@ -194,7 +213,8 @@ formatcode(const char *buf, size_t *start, return(0); } - *start += 2; + /* Remember, if dsz>1, to jump the trailing space. */ + *start += dsz + 1 + (dsz > 1 ? 1 : 0); /* * Escapes don't print macro sequences, so just output them like @@ -204,11 +224,28 @@ formatcode(const char *buf, size_t *start, formatescape(buf, start, end); return(0); } else if (FMT_NULL == fmt || FMT_INDEX == fmt) { - /* For indices and nulls, just consume. */ - while (*start < end && '>' != buf[*start]) - (*start)++; - if (*start < end) - (*start)++; + /* + * For indices and nulls, just consume. + * Be wary of encountering custom delimiters (dsz>1), + * which require special handling. + */ + for ( ; *start < end; (*start)++) { + if ('>' != buf[*start]) + continue; + else if (dsz == 1) + break; + assert(*start > 0); + if (' ' != buf[*start - 1]) + continue; + i = *start; + for (j = 0; i < end && j < dsz; j++) + if ('>' != buf[i++]) + break; + if (dsz != j) + continue; + (*start) += dsz; + break; + } return(0); } @@ -259,15 +296,31 @@ formatcode(const char *buf, size_t *start, } /* - * Read until we reach the end market ('>') or until we find a - * nested format code. + * Read until we reach the end market (e.g., '>') or until we + * find a nested format code. * Don't emit any newlines: since we're on a macro line, we * don't want to break the line. */ while (*start < end) { - if ('>' == buf[*start]) { + if ('>' == buf[*start] && 1 == dsz) { (*start)++; break; + } else if ('>' == buf[*start] && + ' ' == buf[*start - 1]) { + /* + * Handle custom delimiters. + * These require a certain number of + * space-preceded carrots before we're really at + * the end. + */ + i = *start; + for (j = 0; i < end && j < dsz; j++) + if ('>' != buf[i++]) + break; + if (dsz == j) { + *start += dsz; + break; + } } if (*start + 1 < end && '<' == buf[*start + 1]) { formatcode(buf, start, end, 1, last, nomacro); @@ -302,12 +355,15 @@ formatcode(const char *buf, size_t *start, if (reentrant) return(1); + /* FIXME: with the "Qc", this doens't work good. */ + /* * If we're not reentrant, we want to put ending punctuation on * the macro line so that it's properly handled by being * smooshed against the terminal word. */ skipspace(buf, start, end); + if (',' != buf[*start] && '.' != buf[*start] && '!' != buf[*start] && '?' != buf[*start] && ')' != buf[*start]) @@ -601,11 +657,13 @@ ordinary(struct state *st, const char *buf, size_t sta for ( ; i > start; i--) if ('-' != buf[i]) break; - /* FIXME: escape macro-like words etc. */ - printf(".Nm %.*s\n", - (int)((i + 1) - start), &buf[start]); - printf(".Nd %.*s\n", - (int)(end - (j + 1)), &buf[j + 1]); + printf(".Nm "); + formatcodeln(buf, &start, i + 1, 1); + putchar('\n'); + start = j + 1; + printf(".Nd "); + formatcodeln(buf, &start, end, 1); + putchar('\n'); return; } }