=================================================================== RCS file: /cvs/texi2mdoc/main.c,v retrieving revision 1.50 retrieving revision 1.58 diff -u -p -r1.50 -r1.58 --- texi2mdoc/main.c 2015/02/26 10:41:30 1.50 +++ texi2mdoc/main.c 2015/03/02 18:12:53 1.58 @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.50 2015/02/26 10:41:30 kristaps Exp $ */ +/* $Id: main.c,v 1.58 2015/03/02 18:12:53 kristaps Exp $ */ /* * Copyright (c) 2015 Kristaps Dzonsons * @@ -26,7 +26,6 @@ #include #include #include -#include #include #include "extern.h" @@ -269,7 +268,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 */ @@ -498,9 +497,45 @@ dodefn(struct texi *p, enum texicmd cmd, size_t *pos) abort(); } - texivspace(p); - if (NULL != blk) - parseto(p, pos, blk); + if (NULL == blk) + return; + + /* + * All "block" definitions have their block bodies indented + * unless they have the "x" form of the command following. + * E.g., + * @deffn some function + * @deffnx another + * An explanation. + * @end deffn + * With this loop, we delay opening the indented block until we + * skipped past conformant macros. + */ + for (;;) { + switch (peekcmd(p, *pos)) { + case (TEXICMD_DEFFNX): + case (TEXICMD_DEFMACX): + case (TEXICMD_DEFTPX): + case (TEXICMD_DEFTYPEFNX): + case (TEXICMD_DEFTYPEFUNX): + case (TEXICMD_DEFTYPEMETHODX): + case (TEXICMD_DEFTYPEVARX): + case (TEXICMD_DEFTYPEVRX): + case (TEXICMD_DEFUNX): + case (TEXICMD_DEFVARX): + case (TEXICMD_DEFVRX): + texivspace(p); + parseeoln(p, pos); + continue; + default: + break; + } + break; + } + teximacro(p, "Bd -filled -offset indent"); + p->seenvs = 1; + parseto(p, pos, blk); + teximacro(p, "Ed"); } static void @@ -614,8 +649,8 @@ doignblock(struct texi *p, enum texicmd cmd, size_t *p * Thus, we keep track of scopes for matching "end" blocks. */ while (stack > 0 && *pos < BUFSZ(p)) { - if (stack > 10) - abort(); + if (stack > 64) + texierr(p, "run-away nested stack?"); endt = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, end, esz); startt = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, start, ssz); if (NULL == endt) { @@ -690,13 +725,21 @@ doinline(struct texi *p, enum texicmd cmd, size_t *pos } if (NULL == macro || p->literal || TEXILIST_TABLE == p->list) { - parsebracket(p, pos); + if (TEXICMD_SC == cmd) + p->uppercase++; + parsebracket(p, pos, 0); + if (TEXICMD_SC == cmd) + p->uppercase--; return; } teximacroopen(p, macro); p->seenws = 0; - parsebracket(p, pos); + if (TEXICMD_SC == cmd) + p->uppercase++; + parsebracket(p, pos, 0); + if (TEXICMD_SC == cmd) + p->uppercase--; texipunctuate(p, pos); teximacroclose(p); } @@ -728,7 +771,7 @@ doverb(struct texi *p, enum texicmd cmd, size_t *pos) break; advance(p, pos); } - if (*pos == BUFSZ(p) - 1) + if (*pos >= BUFSZ(p) - 1) return; texiputbuf(p, start, *pos); @@ -900,13 +943,15 @@ static void dobracket(struct texi *p, enum texicmd cmd, size_t *pos) { - parsebracket(p, pos); + parsebracket(p, pos, 0); } static void dodisplay(struct texi *p, enum texicmd cmd, size_t *pos) { + advanceeoln(p, pos, 1); + switch (cmd) { case (TEXICMD_FORMAT): case (TEXICMD_SMALLFORMAT): @@ -918,8 +963,6 @@ dodisplay(struct texi *p, enum texicmd cmd, size_t *po } p->seenvs = 1; - /* FIXME: ignore and parseeoln. */ - advanceeoln(p, pos, 1); parseto(p, pos, texitoks[cmd].tok); teximacro(p, "Ed"); } @@ -928,9 +971,9 @@ static void doexample(struct texi *p, enum texicmd cmd, size_t *pos) { - teximacro(p, "Bd -literal -offset indent"); - /* FIXME: ignore and parseeoln. */ advanceeoln(p, pos, 1); + + teximacro(p, "Bd -literal -offset indent"); p->literal++; parseto(p, pos, texitoks[cmd].tok); p->literal--; @@ -948,20 +991,27 @@ dobye(struct texi *p, enum texicmd cmd, size_t *pos) static void dotitle(struct texi *p, enum texicmd cmd, size_t *pos) { - size_t start, end; + size_t start; while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) advance(p, pos); - start = end = *pos; - while (end < BUFSZ(p) && '\n' != BUF(p)[end]) - end++; - advanceeoln(p, pos, 1); + + /* We want to suck down the entire line, inclusive \n. */ + start = *pos; + while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) { + if ('@' == BUF(p)[*pos]) + advance(p, pos); + advance(p, pos); + } + if (*pos < BUFSZ(p)) + advance(p, pos); + + /* Copy this into a buffer. */ free(p->subtitle); - p->subtitle = malloc(end - start + 1); - if (NULL == p->subtitle) + if (NULL == (p->subtitle = malloc(*pos - start + 1))) texiabort(p, NULL); - memcpy(p->subtitle, &BUF(p)[start], end - start); - p->subtitle[end - start] = '\0'; + memcpy(p->subtitle, &BUF(p)[start], *pos - start); + p->subtitle[*pos - start] = '\0'; } static void @@ -1328,35 +1378,8 @@ doquotation(struct texi *p, enum texicmd cmd, size_t * static void domath(struct texi *p, enum texicmd cmd, size_t *pos) { - size_t nest, start; - /* - * Math handling is different from everything else. - * We don't allow any subcomponents, and we ignore the rules in - * terms of @-commands. - * This departs from GNU's rules, but whatever. - */ - while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) - advance(p, pos); - if (*pos == BUFSZ(p) || '{' != BUF(p)[*pos]) - return; - advance(p, pos); - if (p->seenws && p->outcol && 0 == p->literal) - texiputchar(p, ' '); - p->seenws = 0; - for (nest = 1, start = *pos; *pos < BUFSZ(p) && nest > 0; ) { - if ('{' == BUF(p)[*pos]) - nest++; - else if ('}' == BUF(p)[*pos]) - if (0 == --nest) - continue; - advance(p, pos); - } - if (*pos == BUFSZ(p)) - return; - assert('}' == BUF(p)[*pos]); - texiputbuf(p, start, *pos); - advance(p, pos); + parsebracket(p, pos, 1); } static void @@ -1402,7 +1425,7 @@ dovalue(struct texi *p, enum texicmd cmd, size_t *pos) texiputchar(p, ' '); p->seenws = 0; if (NULL != (cp = valueblookup(p, pos))) - texisplice(p, cp, strlen(cp), pos); + texisplice(p, cp, strlen(cp), *pos); else texiputchars(p, "{No value}"); } else if (TEXICMD_IFCLEAR == cmd) { @@ -1544,9 +1567,11 @@ dosection(struct texi *p, enum texicmd cmd, size_t *po int sec; switch (cmd) { + case (TEXICMD_TOP): + sec = 0; + break; case (TEXICMD_APPENDIX): case (TEXICMD_CHAPTER): - case (TEXICMD_TOP): case (TEXICMD_UNNUMBERED): sec = sectioner(p, 0); break; @@ -1565,6 +1590,11 @@ dosection(struct texi *p, enum texicmd cmd, size_t *po else if (p->literal) texierr(p, "\"%s\" in a literal scope!?", sects[sec]); + if (0 == sec && NULL != p->chapters) { + teximdocclose(p, 0); + teximdocopen(p, pos); + } + teximacroopen(p, sects[sec]); parseeoln(p, pos); teximacroclose(p); @@ -1572,60 +1602,26 @@ dosection(struct texi *p, enum texicmd cmd, size_t *po } static void -dosp(struct texi *p, enum texicmd cmd, size_t *pos) -{ - - if (p->literal) - texiputchar(p, '\n'); - else - texivspace(p); - /* FIXME: ignore and parseeoln. */ - advanceeoln(p, pos, 1); -} - -static void dotop(struct texi *p, enum texicmd cmd, size_t *pos) { - const char *cp; - time_t t; - char date[32]; if (--p->ign) texierr(p, "@top command while ignoring"); - /* - * Here we print our standard mdoc(7) prologue. - * We use the title set with @settitle for the `Nd' description - * and the source document filename (the first one as invoked on - * the command line) for the title. - * The date is set to the current date. - */ - t = time(NULL); - strftime(date, sizeof(date), "%F", localtime(&t)); + if (NULL == p->chapters) + teximdocopen(p, pos); + dosection(p, cmd, pos); +} - teximacroopen(p, "Dd"); - texiputchars(p, date); - teximacroclose(p); - teximacroopen(p, "Dt"); - for (cp = p->title; '\0' != *cp; cp++) - texiputchar(p, toupper((unsigned int)*cp)); - texiputchars(p, " 7"); - teximacroclose(p); - teximacro(p, "Os"); - teximacro(p, "Sh NAME"); - teximacroopen(p, "Nm"); - for (cp = p->title; '\0' != *cp; cp++) - texiputchar(p, *cp); - teximacroclose(p); - teximacroopen(p, "Nd"); - if (NULL != p->subtitle) - for (cp = p->subtitle; '\0' != *cp; cp++) - texiputchar(p, *cp); +static void +dosp(struct texi *p, enum texicmd cmd, size_t *pos) +{ + + advanceeoln(p, pos, 1); + if (p->literal) + texiputchar(p, '\n'); else - texiputchars(p, "Unknown description"); - teximacroclose(p); - p->seenvs = 1; - dosection(p, cmd, pos); + texivspace(p); } static void @@ -1697,7 +1693,7 @@ domultitable(struct texi *p, enum texicmd cmd, size_t /* Make sure we don't print anything when scanning. */ p->ign++; - if ('@' == BUF(p)[*pos]) { + if (*pos < BUFSZ(p) && '@' == BUF(p)[*pos]) { /* * Look for @columnfractions. * We ignore these, but we do use the number of @@ -1749,10 +1745,10 @@ dotable(struct texi *p, enum texicmd cmd, size_t *pos) { enum texilist sv = p->list; + advanceeoln(p, pos, 1); + p->list = TEXILIST_ITEM; teximacro(p, "Bl -tag -width Ds"); - /* FIXME: ignore and parseeoln. */ - advanceeoln(p, pos, 1); p->seenvs = 1; parseto(p, pos, texitoks[cmd].tok); teximacro(p, "El"); @@ -1770,7 +1766,8 @@ doend(struct texi *p, enum texicmd cmd, size_t *pos) while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) advance(p, pos); - texiwarn(p, "unexpected \"end\": %.*s", (int)(*pos - start), &BUF(p)[start]); + texiwarn(p, "unexpected \"end\": %.*s", + (int)(*pos - start), &BUF(p)[start]); advanceeoln(p, pos, 1); } @@ -1779,12 +1776,12 @@ doenumerate(struct texi *p, enum texicmd cmd, size_t * { enum texilist sv = p->list; + advanceeoln(p, pos, 1); + p->list = TEXILIST_NOITEM; teximacro(p, "Bl -enum"); p->seenvs = 1; - /* FIXME: ignore and parseeoln. */ - advanceeoln(p, pos, 1); - parseto(p, pos, "enumerate"); + parseto(p, pos, texitoks[cmd].tok); teximacro(p, "El"); p->list = sv; } @@ -1794,12 +1791,12 @@ doitemize(struct texi *p, enum texicmd cmd, size_t *po { enum texilist sv = p->list; + advanceeoln(p, pos, 1); + p->list = TEXILIST_NOITEM; teximacro(p, "Bl -bullet"); p->seenvs = 1; - /* FIXME: ignore and parseeoln. */ - advanceeoln(p, pos, 1); - parseto(p, pos, "itemize"); + parseto(p, pos, texitoks[cmd].tok); teximacro(p, "El"); p->list = sv; } @@ -1809,7 +1806,7 @@ doignbracket(struct texi *p, enum texicmd cmd, size_t { p->ign++; - parsebracket(p, pos); + parsebracket(p, pos, 0); p->ign--; } @@ -1817,8 +1814,7 @@ static void doignline(struct texi *p, enum texicmd cmd, size_t *pos) { - /* FIXME: ignore and parseeoln. */ - advanceeoln(p, pos, 1); + advanceeoln(p, pos, 1); } /* @@ -1876,10 +1872,14 @@ main(int argc, char *argv[]) memset(&texi, 0, sizeof(struct texi)); texi.ign = 1; + texi.outfile = stdout; Idir = NULL; - while (-1 != (c = getopt(argc, argv, "I:"))) + while (-1 != (c = getopt(argc, argv, "C:I:"))) switch (c) { + case ('C'): + texi.chapters = optarg; + break; case ('I'): Idir = optarg; break; @@ -1913,8 +1913,8 @@ main(int argc, char *argv[]) } texiexit(&texi); - return(EXIT_FAILURE); + exit(EXIT_SUCCESS); usage: - fprintf(stderr, "usage: %s [-Idirs] [file]\n", progname); + fprintf(stderr, "usage: %s [-Cdir] [-Idirs] [file]\n", progname); return(EXIT_FAILURE); }