=================================================================== RCS file: /cvs/pod2mdoc/pod2mdoc.c,v retrieving revision 1.55 retrieving revision 1.56 diff -u -p -r1.55 -r1.56 --- pod2mdoc/pod2mdoc.c 2015/02/19 16:34:32 1.55 +++ pod2mdoc/pod2mdoc.c 2015/02/20 13:33:52 1.56 @@ -1,4 +1,4 @@ -/* $Id: pod2mdoc.c,v 1.55 2015/02/19 16:34:32 schwarze Exp $ */ +/* $Id: pod2mdoc.c,v 1.56 2015/02/20 13:33:52 schwarze Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons * Copyright (c) 2014, 2015 Ingo Schwarze @@ -208,7 +208,7 @@ outbuf_flush(struct state *st) if (0 == st->outbuflen) return; - if (OUST_TXT == st->oust && st->wantws) + if (OUST_NL != st->oust && st->wantws) putchar(' '); if (OUST_MAC == st->oust && '"' == *st->outbuf) @@ -441,7 +441,7 @@ again: '?' != buf[*start + 1] && '-' != buf[*start + 1]) { (*start)--; - fputs("Ar ", stdout); + fputs("Ar", stdout); return; } @@ -461,7 +461,7 @@ again: assert(i < end); if ( ! (' ' == buf[i] || '>' == buf[i])) { - printf("Ar "); + fputs("Ar", stdout); return; } @@ -472,7 +472,7 @@ again: (end - *start == 2 || ' ' == buf[*start + 2])) printf("\\&"); - printf("%.*s ", (int)(i - *start), &buf[*start]); + printf("%.*s", (int)(i - *start), &buf[*start]); *start = i; if (' ' == buf[i]) { @@ -483,7 +483,7 @@ again: *start = i; goto again; } - printf("Ar "); + fputs("Ar", stdout); *start = i; } } @@ -511,6 +511,7 @@ formatcode(struct state *st, const char *buf, size_t * size_t i, j, dsz; enum fmt fmt; unsigned char uc; + int gotmacro, wantws; assert(*start + 1 < end); assert('<' == buf[*start + 1]); @@ -588,31 +589,35 @@ formatcode(struct state *st, const char *buf, size_t * if (FMT__MAX != fmt && !nomacro) { /* + * Do we need spacing before the upcoming macro, + * after any pending text already in the outbuf? + * We may already have wantws if there was whitespace + * before the code ("text Bwantws && ! st->outbuflen); + + /* * If we are on a text line and there is no * whitespace before our content, we have to make * the previous word a prefix to the macro line. */ - if (OUST_MAC != st->oust && ' ' != buf[*start] && - st->outbuflen) { + if (OUST_MAC != st->oust && ! wantws) { if (OUST_NL != st->oust) mdoc_newln(st); - printf(".Pf "); + fputs(".Pf", stdout); st->oust = OUST_MAC; - st->wantws = 1; + st->wantws = wantws = 1; } outbuf_flush(st); - /* - * Whitespace is easier to suppress on macro lines. - * We may already have wantws if there was whitespace - * before the code ("text Boust && ' ' != buf[*start] && - ! st->wantws) + if (OUST_MAC == st->oust && ! wantws) printf(" Ns"); /* Unless we are on a macro line, start one. */ @@ -633,16 +638,16 @@ formatcode(struct state *st, const char *buf, size_t * switch (fmt) { case (FMT_ITALIC): - printf("Em "); + fputs("Em", stdout); break; case (FMT_BOLD): if (SECT_SYNOPSIS == st->sect) { if (1 == dsz && '-' == buf[*start]) dosynopsisfl(buf, start, end); else if (0 == pos) - printf("Nm "); + fputs("Nm", stdout); else - printf("Ar "); + fputs("Ar", stdout); break; } i = 0; @@ -652,40 +657,42 @@ formatcode(struct state *st, const char *buf, size_t * if ('=' != uc && '>' != uc) i = 0; if (4 == i && ! strncmp(buf + *start, "NULL", 4)) { - printf("Dv "); + fputs("Dv", stdout); break; } switch (i ? dict_get(buf + *start, i) : MDOC_MAX) { case MDOC_Fa: - printf("Fa "); + fputs("Fa", stdout); break; case MDOC_Vt: - printf("Vt "); + fputs("Vt", stdout); break; default: - printf("Sy "); + fputs("Sy", stdout); break; } break; case (FMT_CODE): - printf("Qo Li "); + fputs("Qo Li", stdout); break; case (FMT_LINK): /* Try to link; use "No" if it's empty. */ if ( ! trylink(buf, start, end, dsz)) - printf("No "); + fputs("No", stdout); break; case (FMT_FILE): - printf("Pa "); + fputs("Pa", stdout); break; case (FMT_NBSP): - printf("No "); + fputs("No", stdout); break; default: abort(); } - } else + } else { outbuf_flush(st); + st->wantws = 0; + } /* * Process until we reach the end marker (e.g., '>') or until we @@ -693,6 +700,8 @@ formatcode(struct state *st, const char *buf, size_t * * Don't emit any newlines: since we're on a macro line, we * don't want to break the line. */ + + gotmacro = 0; while (*start < end) { if ('>' == buf[*start] && 1 == dsz) { (*start)++; @@ -716,54 +725,58 @@ formatcode(struct state *st, const char *buf, size_t * } if (*start + 1 < end && '<' == buf[*start + 1] && 'A' <= buf[*start] && 'Z' >= buf[*start]) { - if ( ! formatcode(st, buf, start, end, nomacro, 1)) - st->wantws = 1; + gotmacro = formatcode(st, buf, + start, end, nomacro, 1); continue; } /* Suppress newlines and multiple spaces. */ last = buf[(*start)++]; - if (' ' == last || '\n' == last) { - putchar(' '); - while (*start < end && ' ' == buf[*start]) + if (isspace(last)) { + outbuf_flush(st); + st->wantws = 1; + gotmacro = 0; + while (*start < end && + isspace((unsigned char)buf[*start])) (*start)++; continue; } if (OUST_MAC == st->oust && FMT__MAX != fmt) { - if ( ! st->wantws) { - printf(" Ns "); + if (gotmacro && ! st->wantws) { + printf(" Ns"); st->wantws = 1; } + gotmacro = 0; /* * Escape macro-like words. * This matches "Xx " and "XxEOLN". */ - if (end - *start > 0 && - isupper((unsigned char)last) && + if (*start < end && ! st->outbuflen && + isupper(last) && islower((unsigned char)buf[*start]) && (end - *start == 1 || ' ' == buf[*start + 1] || '>' == buf[*start + 1])) - printf("\\&"); + outbuf_addstr(st, "\\&"); + last = buf[*start - 1]; } + outbuf_addchar(st); + } - putchar(last); + if (FMT__MAX == fmt) + return(0); - /* Protect against character escapes. */ + outbuf_flush(st); - if ('\\' == last) - putchar('e'); - } - if ( ! nomacro && FMT_CODE == fmt) - printf(" Qc "); + fputs(" Qc", stdout); st->wantws = ' ' == last; - return(FMT__MAX != fmt); + return(1); } /* @@ -776,52 +789,45 @@ static void formatcodeln(struct state *st, const char *linemac, const char *buf, size_t *start, size_t end, int nomacro) { - int gotmacro, wantws; + int gotmacro; assert(OUST_NL == st->oust); assert(st->wantws); - printf(".%s ", linemac); + printf(".%s", linemac); st->oust = OUST_MAC; gotmacro = 0; while (*start < end) { - 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; } + /* Suppress newlines and multiple spaces. */ + + last = buf[(*start)++]; + if (isspace(last)) { + outbuf_flush(st); + st->wantws = 1; + while (*start < end && + isspace((unsigned char)buf[*start])) + (*start)++; + continue; + } + if (gotmacro) { - if (*start < end || st->outbuflen) { - if (st->wantws || - (wantws && !st->outbuflen)) - printf(" No "); + if (*start < end) { + if (st->wantws) + printf(" No"); else - printf(" Ns "); + printf(" Ns"); } + st->wantws = 1; 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. @@ -829,21 +835,16 @@ formatcodeln(struct state *st, const char *linemac, * are used in troff and we don't want to escape * something that needn't be escaped. */ - if (' ' == last && end - *start > 1 && - isupper((unsigned char)buf[*start]) && - islower((unsigned char)buf[*start + 1]) && - (end - *start == 2 || ' ' == buf[*start + 2])) - printf("\\&"); - - putchar(last = buf[*start]); - - /* Protect against character escapes. */ - - if ('\\' == last) - putchar('e'); - - (*start)++; + if (*start < end && ! st->outbuflen && isupper(last) && + islower((unsigned char)buf[*start]) && + (end - *start == 1 || ' ' == buf[*start + 1])) { + outbuf_addstr(st, "\\&"); + last = buf[*start - 1]; + } + outbuf_addchar(st); } + outbuf_flush(st); + st->wantws = 1; } /* @@ -1529,9 +1530,9 @@ ordinary(struct state *st, const char *buf, size_t sta st->outbuf[wend] = '\0'; mdoc_newln(st); if (MDOC_Fo == mtype) - fputs(".Fn ", stdout); + fputs(".Fn", stdout); else - fputs(".Xr ", stdout); + fputs(".Xr", stdout); st->oust = OUST_MAC; } } else { @@ -1540,7 +1541,7 @@ ordinary(struct state *st, const char *buf, size_t sta savechar = st->outbuf[wend]; st->outbuf[wend] = '\0'; mdoc_newln(st); - fputs(".Dv ", stdout); + fputs(".Dv", stdout); st->oust = OUST_MAC; } else mtype = MDOC_Fa; @@ -1623,7 +1624,7 @@ ordinary(struct state *st, const char *buf, size_t sta ('<' != buf[start + 1] || 'A' > buf[start] || 'Z' < buf[start])) { - printf(" Ns "); + fputs(" Ns", stdout); st->wantws = 1; } }