=================================================================== RCS file: /cvs/texi2mdoc/main.c,v retrieving revision 1.57 retrieving revision 1.64 diff -u -p -r1.57 -r1.64 --- texi2mdoc/main.c 2015/03/01 16:57:39 1.57 +++ texi2mdoc/main.c 2015/03/07 11:49:32 1.64 @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.57 2015/03/01 16:57:39 kristaps Exp $ */ +/* $Id: main.c,v 1.64 2015/03/07 11:49:32 kristaps Exp $ */ /* * Copyright (c) 2015 Kristaps Dzonsons * @@ -42,6 +42,7 @@ static void doaccent(struct texi *, enum texicmd, size static void doblock(struct texi *, enum texicmd, size_t *); static void dobracket(struct texi *, enum texicmd, size_t *); static void dobye(struct texi *, enum texicmd, size_t *); +static void docopying(struct texi *, enum texicmd, size_t *); static void dodefindex(struct texi *, enum texicmd, size_t *); static void dodefn(struct texi *, enum texicmd, size_t *); static void dodisplay(struct texi *, enum texicmd, size_t *); @@ -54,11 +55,15 @@ static void doignbracket(struct texi *, enum texicmd, static void doignline(struct texi *, enum texicmd, size_t *); static void doinline(struct texi *, enum texicmd, size_t *); static void doinclude(struct texi *, enum texicmd, size_t *); +static void doinsertcopying(struct texi *, enum texicmd, size_t *); static void doitem(struct texi *, enum texicmd, size_t *); static void doitemize(struct texi *, enum texicmd, size_t *); static void dolink(struct texi *, enum texicmd, size_t *); static void domacro(struct texi *, enum texicmd, size_t *); static void domath(struct texi *, enum texicmd, size_t *); +#if 0 +static void domenu(struct texi *, enum texicmd, size_t *); +#endif static void domultitable(struct texi *, enum texicmd, size_t *); static void doquotation(struct texi *, enum texicmd, size_t *); static void dotable(struct texi *, enum texicmd, size_t *); @@ -94,7 +99,8 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { dosymbol, "*", 1 }, /* TEXICMD_ASTERISK */ { dosymbol, "@", 1 }, /* TEXICMD_AT */ { doignline, "author", 6 }, /* TEXICMD_AUTHOR */ - { doinline, "b", 1 }, /* TEXICMD_BOLD */ + { doinline, "b", 1 }, /* TEXICMD_B */ + { dosymbol, "\\", 1 }, /* TEXICMD_BACKSLASH */ { dosymbol, "!", 1 }, /* TEXICMD_BANG */ { dosymbol, "bullet", 6 }, /* TEXICMD_BULLET */ { dobye, "bye", 3 }, /* TEXICMD_BYE */ @@ -114,7 +120,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { doignline, "c", 1 }, /* TEXICMD_COMMENT */ { doignline, "comment", 7 }, /* TEXICMD_COMMENT_LONG */ { doignline, "contents", 8 }, /* TEXICMD_CONTENTS */ - { doignblock, "copying", 7 }, /* TEXICMD_COPYING */ + { docopying, "copying", 7 }, /* TEXICMD_COPYING */ { dosymbol, "copyright", 9 }, /* TEXICMD_COPYRIGHT */ { dodefindex, "defcodeindex", 12 }, /* TEXICMD_DEFCODEINDEX */ { dodefn, "deffn", 5 }, /* TEXICMD_DEFFN */ @@ -213,7 +219,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { dodisplay, "indentblock", 11 }, /* TEXICMD_INDENTBLOCK */ { dolink, "indicateurl", 11 }, /* TEXICMD_INDICATEURL */ { dolink, "inforef", 7 }, /* TEXICMD_INFOREF */ - { doignline, "insertcopying", 13 }, /* TEXICMD_INSERTCOPYING */ + { doinsertcopying, "insertcopying", 13 }, /* TEXICMD_INSERTCOPYING */ { doitem, "item", 4 }, /* TEXICMD_ITEM */ { doitemize, "itemize", 7 }, /* TEXICMD_ITEMIZE */ { doitem, "itemx", 5 }, /* TEXICMD_ITEMX */ @@ -268,7 +274,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { doaccent, "ringaccent", 10 }, /* TEXICMD_RINGACCENT */ { doinline, "samp", 4 }, /* TEXICMD_SAMP */ { doinline, "sansserif", 9 }, /* TEXICMD_SANSSERIF */ - { dobracket, "sc", 2 }, /* TEXICMD_SC */ + { doinline, "sc", 2 }, /* TEXICMD_SC */ { dosection, "section", 7 }, /* TEXICMD_SECTION */ { dovalue, "set", 3 }, /* TEXICMD_SET */ { doignline, "setchapternewpage", 17 }, /* TEXICMD_SETCHAPNEWPAGE */ @@ -341,6 +347,12 @@ static const struct texitok __texitoks[TEXICMD__MAX] = const struct texitok *const texitoks = __texitoks; +/* + * Texinfo has lots of indexes. + * You can add new ones in a variety of ways. + * We maintain an array of all of these index names (usually a few + * letters) and pass unknown commands through the array list. + */ static void dodefindex(struct texi *p, enum texicmd cmd, size_t *pos) { @@ -349,7 +361,6 @@ dodefindex(struct texi *p, enum texicmd cmd, size_t *p while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) advance(p, pos); - start = end = *pos; while (end < BUFSZ(p) && ! ismspace(BUF(p)[end])) end++; @@ -357,18 +368,21 @@ dodefindex(struct texi *p, enum texicmd cmd, size_t *p if (start == end) { advanceeoln(p, pos, 1); return; - } else if (NULL == (cp = malloc(end - start + 1))) + } + + if (NULL == (cp = malloc(end - start + 1))) texiabort(p, NULL); - memcpy(cp, &BUF(p)[start], end - start); cp[end - start] = '\0'; + /* FIXME: use reallocarray(). */ p->indexs = realloc(p->indexs, sizeof(char *) * (p->indexsz + 1)); - if (NULL == p->indexs) texiabort(p, NULL); p->indexs[p->indexsz++] = cp; + + advanceeoln(p, pos, 1); } static void @@ -533,9 +547,9 @@ dodefn(struct texi *p, enum texicmd cmd, size_t *pos) break; } teximacro(p, "Bd -filled -offset indent"); - p->seenvs = 1; parseto(p, pos, blk); teximacro(p, "Ed"); + p->seenvs = 1; } static void @@ -725,13 +739,34 @@ doinline(struct texi *p, enum texicmd cmd, size_t *pos } if (NULL == macro || p->literal || TEXILIST_TABLE == p->list) { + if (TEXICMD_SC == cmd) + p->uppercase++; parsebracket(p, pos, 0); + if (TEXICMD_SC == cmd) + p->uppercase--; return; } + /* + * If we haven't seen any whitespace, then we don't want the + * subsequent macro to insert any whitespace. + */ + if (p->outmacro && 0 == p->seenws) { + teximacroopen(p, "Ns"); + teximacroclose(p); + } + teximacroopen(p, macro); p->seenws = 0; + if (TEXICMD_CODE == cmd) + p->literal++; + if (TEXICMD_SC == cmd) + p->uppercase++; parsebracket(p, pos, 0); + if (TEXICMD_SC == cmd) + p->uppercase--; + if (TEXICMD_CODE == cmd) + p->literal--; texipunctuate(p, pos); teximacroclose(p); } @@ -775,6 +810,53 @@ doverb(struct texi *p, enum texicmd cmd, size_t *pos) } static void +doinsertcopying(struct texi *p, enum texicmd cmd, size_t *pos) +{ + + advanceeoln(p, pos, 0); + if (NULL == p->copying) + return; + texisplice(p, p->copying, p->copyingsz, *pos); +} + +static void +docopying(struct texi *p, enum texicmd cmd, size_t *pos) +{ + const char *end, *term; + size_t endsz, endpos; + + /* We retain our starting (but not ending) newlines. */ + end = "\n@end copying\n"; + endsz = strlen(end); + advanceeoln(p, pos, 0); + if (*pos == BUFSZ(p)) { + texiwarn(p, "unterminated \"%s\"", texitoks[cmd].tok); + return; + } + + term = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, end, endsz); + if (NULL == term) { + texiwarn(p, "unterminated \"%s\"", texitoks[cmd].tok); + endpos = BUFSZ(p); + } else + endpos = *pos + (size_t)(term - &BUF(p)[*pos]); + + assert(endpos <= BUFSZ(p)); + assert('\n' == BUF(p)[*pos]); + advance(p, pos); + + p->copying = malloc(endpos - *pos + 1); + p->copyingsz = endpos - *pos; + memcpy(p->copying, &BUF(p)[*pos], p->copyingsz); + p->copying[endpos - *pos] = '\0'; + + while (*pos < endpos) + advance(p, pos); + if (*pos < BUFSZ(p)) + advanceto(p, pos, endpos + endsz); +} + +static void doverbatim(struct texi *p, enum texicmd cmd, size_t *pos) { const char *end, *term; @@ -785,13 +867,13 @@ doverbatim(struct texi *p, enum texicmd cmd, size_t *p endsz = strlen(end); advanceeoln(p, pos, 0); if (*pos == BUFSZ(p)) { - texiwarn(p, "unexpected end of file"); + texiwarn(p, "unterminated \"%s\"", texitoks[cmd].tok); return; } term = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, end, endsz); if (NULL == term) { - texiwarn(p, "unterminated verbatim block"); + texiwarn(p, "unterminated \"%s\"", texitoks[cmd].tok); endpos = BUFSZ(p); } else endpos = *pos + (size_t)(term - &BUF(p)[*pos]); @@ -805,6 +887,7 @@ doverbatim(struct texi *p, enum texicmd cmd, size_t *p advance(p, pos); } teximacro(p, "Ed"); + p->seenvs = 1; if (*pos < BUFSZ(p)) advanceto(p, pos, endpos + endsz); } @@ -954,9 +1037,9 @@ dodisplay(struct texi *p, enum texicmd cmd, size_t *po break; } - p->seenvs = 1; parseto(p, pos, texitoks[cmd].tok); teximacro(p, "Ed"); + p->seenvs = 1; } static void @@ -970,6 +1053,7 @@ doexample(struct texi *p, enum texicmd cmd, size_t *po parseto(p, pos, texitoks[cmd].tok); p->literal--; teximacro(p, "Ed"); + p->seenvs = 1; } static void @@ -1196,6 +1280,9 @@ dosymbol(struct texi *p, enum texicmd cmd, size_t *pos case (TEXICMD_AT): texiputchar(p, '@'); break; + case (TEXICMD_BACKSLASH): + texiputchar(p, '\\'); + break; case (TEXICMD_BANG): texiputchar(p, '!'); break; @@ -1367,7 +1454,118 @@ doquotation(struct texi *p, enum texicmd cmd, size_t * teximacro(p, "Qc"); } +#if 0 static void +domenu(struct texi *p, enum texicmd cmd, size_t *pos) +{ + size_t start; + + if (NULL != p->chapters) { + doignblock(p, cmd, pos); + return; + } + + advanceeoln(p, pos, 1); + + teximacro(p, "Bl -tag -width Ds"); + while (*pos < BUFSZ(p)) { + /* Read to next menu item. */ + while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) + advance(p, pos); + if ('*' != BUF(p)[*pos]) + break; + + assert('*' == BUF(p)[*pos]); + advance(p, pos); + while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) + advance(p, pos); + start = *pos; + while (*pos < BUFSZ(p) && ':' != BUF(p)[*pos]) + advance(p, pos); + if (*pos == BUFSZ(p) || *pos == start) { + texiwarn(p, "empty menu name"); + break; + } + teximacroopen(p, "It"); + teximacroopen(p, "Sx"); + for ( ; start < *pos; start++) + texiputchar(p, BUF(p)[start]); + teximacroclose(p); + teximacroclose(p); + + advance(p, pos); + if (*pos == BUFSZ(p)) { + texiwarn(p, "bad menu syntax"); + break; + } else if (':' != BUF(p)[*pos]) { + while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) + advance(p, pos); + start = *pos; + while (*pos < BUFSZ(p)) { + switch (BUF(p)[*pos]) { + case ('\t'): + case ('\n'): + case (','): + break; + case ('.'): + if (*pos + 1 == BUFSZ(p)) { + advance(p, pos); + continue; + } + if (' ' == BUF(p)[*pos + 1]) { + advance(p, pos); + break; + } + /* FALLTHROUGH */ + default: + advance(p, pos); + continue; + } + advance(p, pos); + break; + } + } else + advance(p, pos); + + while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) + advance(p, pos); + + if (*pos == BUFSZ(p)) { + texiwarn(p, "bad menu syntax"); + break; + } + + while (*pos < BUFSZ(p)) { + if ('*' == BUF(p)[*pos]) + break; + if ('\n' != BUF(p)[*pos]) { + texiputchar(p, BUF(p)[*pos]); + advance(p, pos); + continue; + } + advance(p, pos); + while (*pos == BUFSZ(p)) { + texiwarn(p, "bad menu syntax"); + break; + } + if ('\n' == BUF(p)[*pos]) { + advance(p, pos); + break; + } else if ('*' == BUF(p)[*pos]) { + continue; + } else if ('@' == BUF(p)[*pos]) + break; + texiputchar(p, ' '); + } + } + + teximacro(p, "El"); + + doignblock(p, cmd, pos); +} +#endif + +static void domath(struct texi *p, enum texicmd cmd, size_t *pos) { @@ -1590,7 +1788,6 @@ dosection(struct texi *p, enum texicmd cmd, size_t *po teximacroopen(p, sects[sec]); parseeoln(p, pos); teximacroclose(p); - p->seenvs = 1; } static void @@ -1622,7 +1819,8 @@ doitem(struct texi *p, enum texicmd cmd, size_t *pos) /* Multitable is using raw tbl(7). */ if (TEXILIST_TABLE == p->list) { - texiputchar(p, '\n'); + if (p->outcol > 0) + texiputchar(p, '\n'); return; } @@ -1644,7 +1842,6 @@ doitem(struct texi *p, enum texicmd cmd, size_t *pos) } /* Trick so we don't start with Pp. */ - p->seenvs = 1; parseeoln(p, pos); if (TEXILIST_ITEM == p->list) @@ -1658,7 +1855,7 @@ dotab(struct texi *p, enum texicmd cmd, size_t *pos) { /* This command is only useful in @multitable. */ - if (TEXILIST_TABLE == p->list) + if (TEXILIST_TABLE == p->list && p->outcol) texiputchar(p, '\t'); } @@ -1670,6 +1867,7 @@ domultitable(struct texi *p, enum texicmd cmd, size_t enum texicmd type; size_t i, end, columns; + texivspace(p); p->list = TEXILIST_TABLE; /* * TS/TE blocks aren't "in mdoc(7)", so we can disregard the @@ -1723,7 +1921,9 @@ domultitable(struct texi *p, enum texicmd cmd, size_t texiputchar(p, ' '); texiputchar(p, 'l'); } - texiputchars(p, ".\n"); + + texiputchar(p, '.'); + texiputchar(p, '\n'); p->outmacro++; parseto(p, pos, texitoks[cmd].tok); p->outmacro--; @@ -1741,9 +1941,9 @@ dotable(struct texi *p, enum texicmd cmd, size_t *pos) p->list = TEXILIST_ITEM; teximacro(p, "Bl -tag -width Ds"); - p->seenvs = 1; parseto(p, pos, texitoks[cmd].tok); teximacro(p, "El"); + p->seenvs = 1; p->list = sv; } @@ -1772,9 +1972,9 @@ doenumerate(struct texi *p, enum texicmd cmd, size_t * p->list = TEXILIST_NOITEM; teximacro(p, "Bl -enum"); - p->seenvs = 1; parseto(p, pos, texitoks[cmd].tok); teximacro(p, "El"); + p->seenvs = 1; p->list = sv; } @@ -1787,9 +1987,9 @@ doitemize(struct texi *p, enum texicmd cmd, size_t *po p->list = TEXILIST_NOITEM; teximacro(p, "Bl -bullet"); - p->seenvs = 1; parseto(p, pos, texitoks[cmd].tok); teximacro(p, "El"); + p->seenvs = 1; p->list = sv; }