=================================================================== RCS file: /cvs/texi2mdoc/main.c,v retrieving revision 1.24 retrieving revision 1.25 diff -u -p -r1.24 -r1.25 --- texi2mdoc/main.c 2015/02/20 09:58:50 1.24 +++ texi2mdoc/main.c 2015/02/20 12:25:25 1.25 @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.24 2015/02/20 09:58:50 kristaps Exp $ */ +/* $Id: main.c,v 1.25 2015/02/20 12:25:25 kristaps Exp $ */ /* * Copyright (c) 2015 Kristaps Dzonsons * @@ -71,6 +71,7 @@ static void dosymbol(struct texi *, enum texicmd, cons static void dotab(struct texi *, enum texicmd, const char *, size_t, size_t *); static void dotitle(struct texi *, enum texicmd, const char *, size_t, size_t *); static void dovalue(struct texi *, enum texicmd, const char *, size_t, size_t *); +static void doverb(struct texi *, enum texicmd, const char *, size_t, size_t *); static void doverbinclude(struct texi *, enum texicmd, const char *, size_t, size_t *); static const struct texitok __texitoks[TEXICMD__MAX] = { @@ -83,6 +84,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { dosection, "appendixsec", 11 }, /* TEXICMD_APPENDIXSEC */ { dosubsection, "appendixsubsec", 14 }, /* TEXICMD_APPENDIXSUBSEC */ { dosubsubsection, "appendixsubsubsec", 17 }, /* TEXICMD_APPENDIXSUBSUBSEC */ + { doinline, "asis", 4 }, /* TEXICMD_ASIS */ { dosymbol, "*", 1 }, /* TEXICMD_ASTERISK */ { dosymbol, "@", 1 }, /* TEXICMD_AT */ { doignline, "author", 6 }, /* TEXICMD_AUTHOR */ @@ -138,6 +140,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { doinline, "env", 3 }, /* TEXICMD_ENV */ { dosymbol, "error", 5 }, /* TEXICMD_ERROR */ { doexample, "example", 7 }, /* TEXICMD_EXAMPLE */ + { doignline, "exdent", 6 }, /* TEXICMD_EXDENT */ { dosymbol, "expansion", 9 }, /* TEXICMD_EXPANSION */ { doinline, "file", 4 }, /* TEXICMD_FILE */ { doignline, "finalout", 8 }, /* TEXICMD_FINALOUT */ @@ -149,6 +152,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { dosection, "heading", 7 }, /* TEXICMD_HEADING */ { doignline, "headings", 8 }, /* TEXICMD_HEADINGS */ { doitem, "headitem", 8 }, /* TEXICMD_HEADITEM */ + { doignblock, "html", 4 }, /* TEXICMD_HTML */ { dosymbol, "-", 1 }, /* TEXICMD_HYPHEN */ { doinline, "i", 1 }, /* TEXICMD_I */ { dovalue, "ifclear", 7 }, /* TEXICMD_IFCLEAR */ @@ -180,6 +184,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { dosecoffs, "lowersections", 13 }, /* TEXICMD_LOWERSECTIONS */ { domath, "math", 4 }, /* TEXICMD_MATH */ { doignblock, "menu", 4 }, /* TEXICMD_MENU */ + { dosymbol, "minus", 5 }, /* TEXICMD_MINUS */ { domultitable, "multitable", 10 }, /* TEXICMD_MULTITABLE */ { doignline, "need", 4 }, /* TEXICMD_NEED */ { dosymbol, "\n", 1 }, /* TEXICMD_NEWLINE */ @@ -190,7 +195,8 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { dosymbol, "?", 1 }, /* TEXICMD_QUESTIONMARK */ { doquotation, "quotation", 9 }, /* TEXICMD_QUOTATION */ { doignline, "page", 4 }, /* TEXICMD_PAGE */ - { doignline, "paragraphindent", 14 }, /* TEXICMD_PARINDENT */ + { doignline, "paragraphindent", 15 }, /* TEXICMD_PARINDENT */ + { dosymbol, ".", 1 }, /* TEXICMD_PERIOD */ { doignline, "printindex", 10 }, /* TEXICMD_PRINTINDEX */ { doinline, "r", 1 }, /* TEXICMD_R */ { dosecoffs, "raisesections", 13 }, /* TEXICMD_RAISESECTIONS */ @@ -204,6 +210,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { doignline, "setchapternewpage", 17 }, /* TEXICMD_SETCHAPNEWPAGE */ { doignline, "setfilename", 11 }, /* TEXICMD_SETFILENAME */ { dotitle, "settitle", 8 }, /* TEXICMD_SETTITLE */ + { doignline, "shortcontents", 13 }, /* TEXICMD_SHORTCONTENTS */ { doinline, "slanted", 7 }, /* TEXICMD_SLANTED */ { dosp, "sp", 2 }, /* TEXICMD_SP */ { dosymbol, " ", 1 }, /* TEXICMD_SPACE */ @@ -219,6 +226,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { dosubsection, "subsection", 10 }, /* TEXICMD_SUBSECTION */ { dosubsubsection, "subsubsection", 13 }, /* TEXICMD_SUBSUBSECTION */ { doignline, "subtitle", 8 }, /* TEXICMD_SUBTITLE */ + { doignline, "summarycontents", 15 }, /* TEXICMD_SUMMARYCONTENTS */ { doignline, "syncodeindex", 12 }, /* TEXICMD_SYNCODEINDEX */ { doinline, "t", 1 }, /* TEXICMD_T */ { dotab, "tab", 3 }, /* TEXICMD_TAB */ @@ -227,6 +235,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { doignblock, "tex", 3 }, /* TEXICMD_TEX */ { dosymbol, "TeX", 3 }, /* TEXICMD_TEXSYM */ { doaccent, "~", 1 }, /* TEXICMD_TILDE */ + { doignline, "tindex", 6 }, /* TEXICMD_TINDEX */ { doignline, "title", 5 }, /* TEXICMD_TITLE */ { dobracket, "titlefont", 9 }, /* TEXICMD_TITLEFONT */ { doignblock, "titlepage", 9 }, /* TEXICMD_TITLEPAGE */ @@ -240,6 +249,7 @@ static const struct texitok __texitoks[TEXICMD__MAX] = { dolink, "url", 3 }, /* TEXICMD_URL */ { dovalue, "value", 5 }, /* TEXICMD_VALUE */ { doinline, "var", 3 }, /* TEXICMD_VAR */ + { doverb, "verbatim", 8 }, /* TEXICMD_VERBATIM */ { doverbinclude, "verbatiminclude", 15 }, /* TEXICMD_VERBATIMINCLUDE */ { doignline, "vindex", 6 }, /* TEXICMD_VINDEX */ { dosp, "vskip", 5 }, /* TEXICMD_VSKIP */ @@ -251,32 +261,6 @@ static const struct texitok __texitoks[TEXICMD__MAX] = const struct texitok *const texitoks = __texitoks; -static char * -lineargdup(struct texi *p, const char *buf, size_t sz, size_t *pos) -{ - char *key; - size_t start, end; - - while (*pos < sz && isws(buf[*pos])) - advance(p, buf, pos); - if (*pos == sz) - return(NULL); - for (start = end = *pos; end < sz; end++) - if ('\n' == buf[end]) - break; - advanceto(p, buf, pos, end); - if (*pos < sz) - advance(p, buf, pos); - key = malloc(end - start + 1); - if (NULL == key) { - perror(NULL); - exit(EXIT_FAILURE); - } - memcpy(key, &buf[start], end - start); - key[end - start] = '\0'; - return(key); -} - static void dodefn(struct texi *p, enum texicmd cmd, const char *buf, size_t sz, size_t *pos) @@ -461,7 +445,7 @@ doinline(struct texi *p, enum texicmd cmd, break; } - if (NULL == macro || p->literal) { + if (NULL == macro || p->literal || TEXILIST_TABLE == p->list) { parsebracket(p, buf, sz, pos); return; } @@ -474,22 +458,76 @@ doinline(struct texi *p, enum texicmd cmd, } static void +doverb(struct texi *p, enum texicmd cmd, + const char *buf, size_t sz, size_t *pos) +{ + const char *end, *term; + size_t endsz, endpos; + + /* We end at exactly this token. */ + end = "\n@end verbatim\n"; + endsz = strlen(end); + + /* + * Look up where our end token occurs. + * Set our end position based on the relative offset of that + * from our current position. + */ + term = memmem(&buf[*pos], sz, end, endsz); + endpos = NULL == term ? sz : + *pos + term - &buf[*pos]; + + teximacro(p, "Bd -literal -offset indent"); + assert(endpos <= sz); + /* Run to the point inclusive the endpoint newline. */ + while (*pos < endpos + 1) { + if (*pos > 0 && '.' == buf[*pos]) + if ('\n' == buf[*pos - 1]) + fputs("\\&", stdout); + putchar(buf[*pos]); + if ('\\' == buf[*pos]) + putchar('e'); + advance(p, buf, pos); + } + teximacro(p, "Ed"); + advanceto(p, buf, pos, *pos + endpos + endsz); +} + +static void doverbinclude(struct texi *p, enum texicmd cmd, const char *buf, size_t sz, size_t *pos) { - char fname[PATH_MAX], path[PATH_MAX]; - int rc; - size_t i; + char fname[PATH_MAX], path[PATH_MAX]; + int rc; + size_t i, end; + const char *v; + enum texicmd type; while (*pos < sz && ' ' == buf[*pos]) advance(p, buf, pos); - /* Read in the filename. */ - for (i = 0; *pos < sz && '\n' != buf[*pos]; i++) { + for (i = 0; *pos < sz && '\n' != buf[*pos]; ) { if (i == sizeof(fname) - 1) break; - fname[i] = buf[*pos]; - advance(p, buf, pos); + if ('@' != buf[*pos]) { + fname[i++] = buf[*pos]; + advance(p, buf, pos); + continue; + } + type = texicmd(p, buf, *pos, sz, &end); + advanceto(p, buf, pos, end); + if (TEXICMD_VALUE != type) + texierr(p, "unknown verbatiminclude command"); + v = valueblookup(p, buf, sz, pos); + if (NULL == v) + continue; + while ('\0' != *v) { + if (i == sizeof(fname) - 1) + break; + fname[i++] = *v++; + } + if ('\0' != *v) + break; } if (i == 0) @@ -517,19 +555,38 @@ static void doinclude(struct texi *p, enum texicmd cmd, const char *buf, size_t sz, size_t *pos) { - char fname[PATH_MAX], path[PATH_MAX]; - size_t i; - int rc; + char fname[PATH_MAX], path[PATH_MAX]; + size_t i, end; + int rc; + const char *v; + enum texicmd type; while (*pos < sz && ' ' == buf[*pos]) advance(p, buf, pos); /* Read in the filename. */ - for (i = 0; *pos < sz && '\n' != buf[*pos]; i++) { + for (i = 0; *pos < sz && '\n' != buf[*pos]; ) { if (i == sizeof(fname) - 1) break; - fname[i] = buf[*pos]; - advance(p, buf, pos); + if ('@' != buf[*pos]) { + fname[i++] = buf[*pos]; + advance(p, buf, pos); + continue; + } + type = texicmd(p, buf, *pos, sz, &end); + advanceto(p, buf, pos, end); + if (TEXICMD_VALUE != type) + texierr(p, "unknown include command"); + v = valueblookup(p, buf, sz, pos); + if (NULL == v) + continue; + while ('\0' != *v) { + if (i == sizeof(fname) - 1) + break; + fname[i++] = *v++; + } + if ('\0' != *v) + break; } if (i == 0) @@ -754,6 +811,12 @@ dosymbol(struct texi *p, enum texicmd cmd, case (TEXICMD_LATEX): texiputchars(p, "LaTeX"); break; + case (TEXICMD_MINUS): + texiputchars(p, "\\-"); + break; + case (TEXICMD_PERIOD): + texiputchar(p, '.'); + break; case (TEXICMD_QUESTIONMARK): texiputchar(p, '?'); break; @@ -830,23 +893,21 @@ static void dovalue(struct texi *p, enum texicmd cmd, const char *buf, size_t sz, size_t *pos) { - size_t i, start, end; - int clr; - char *key, *val; + size_t start, end; + int clr; + char *key, *val; + const char *cp; if (TEXICMD_SET == cmd) { - /* - * If we're going to set a value, then first parse the - * key and value from the input stream. - * Disallow empty keys. - */ while (*pos < sz && isws(buf[*pos])) advance(p, buf, pos); for (start = end = *pos; end < sz; end++) if (ismspace(buf[end])) break; + /* We don't allow empty keys. */ if (start == end) return; + advanceto(p, buf, pos, end); key = malloc(end - start + 1); if (NULL == key) { @@ -856,13 +917,13 @@ dovalue(struct texi *p, enum texicmd cmd, memcpy(key, &buf[start], end - start); key[end - start] = '\0'; - advanceto(p, buf, pos, end); - while (*pos < sz && isws(buf[*pos])) advance(p, buf, pos); for (start = end = *pos; end < sz; end++) if ('\n' == buf[end]) break; + /* We do allow empty values. */ + advanceeoln(p, buf, sz, pos, 1); val = malloc(end - start + 1); if (NULL == val) { @@ -871,100 +932,24 @@ dovalue(struct texi *p, enum texicmd cmd, } memcpy(val, &buf[start], end - start); val[end - start] = '\0'; - - /* - * Now look up the key in our table of existing keys. - * If we find it, then free the local key and replace - * the value (freeing the existing) of the existing. - * If not, reallocate the structure. - */ - for (i = 0; i < p->valsz; i++) - if (0 == strcmp(p->vals[i].key, key)) - break; - - if (i < p->valsz) { - free(key); - free(p->vals[i].value); - p->vals[i].value = val; - } else { - p->vals = realloc(p->vals, - (p->valsz + 1) * - sizeof(struct texivalue)); - if (NULL == p->vals) { - perror(NULL); - exit(EXIT_FAILURE); - } - p->vals[p->valsz].key = key; - p->vals[p->valsz].value = val; - p->valsz++; - } - - advanceeoln(p, buf, sz, pos, 1); + valueadd(p, key, val); } else if (TEXICMD_VALUE == cmd) { - /* - * First, parse out the key from the stream, which is - * just the material within the quotes. - */ - while (*pos < sz && '{' != buf[*pos]) - advance(p, buf, pos); - if (*pos == sz) - return; - advance(p, buf, pos); - start = *pos; - while (*pos < sz && '}' != buf[*pos]) - advance(p, buf, pos); - if ((end = *pos) < sz) - advance(p, buf, pos); - - key = malloc(end - start + 1); - if (NULL == key) { - perror(NULL); - exit(EXIT_FAILURE); - } - memcpy(key, &buf[start], end - start); - key[end - start] = '\0'; - - /* - * Next, look up the key in our table. - * If it exists, print it out, being mindful all the - * while of prior whitespace. - * If it doesn't, print out a message. - */ - for (i = 0; i < p->valsz; i++) - if (0 == strcmp(p->vals[i].key, key)) - break; if (p->seenws) texiputchar(p, ' '); p->seenws = 0; - if (i == p->valsz || NULL == p->vals[i].value) { - texiputchars(p, "{No value for \\(lq"); - texiputchars(p, key); - texiputchars(p, "\\(rq}"); - } else - texiputchars(p, p->vals[i].value); - free(key); - } else if (TEXICMD_CLEAR == cmd) { - key = lineargdup(p, buf, sz, pos); - for (i = 0; i < p->valsz; i++) - if (0 == strcmp(p->vals[i].key, key)) { - free(p->vals[i].value); - p->vals[i].value = NULL; - break; - } - free(key); + if (NULL == (cp = valueblookup(p, buf, sz, pos))) + texiputchars(p, "{No value}"); + else + texiputchars(p, cp); } else if (TEXICMD_IFCLEAR == cmd) { - key = lineargdup(p, buf, sz, pos); - for (i = 0; i < p->valsz; i++) - if (0 == strcmp(p->vals[i].key, key)) - break; - free(key); - clr = i < p->valsz && NULL != p->vals[i].value; + clr = NULL != valuellookup(p, buf, sz, pos); if (clr) p->ign++; parseto(p, buf, sz, pos, texitoks[cmd].tok); if (clr) p->ign--; - } + } else if (TEXICMD_CLEAR == cmd) + valuelclear(p, buf, sz, pos); } static void @@ -1244,7 +1229,7 @@ domultitable(struct texi *p, enum texicmd cmd, type = texicmd(p, buf, *pos, sz, &end); advanceto(p, buf, pos, end); if (TEXICMD_COLUMNFRACTIONS != type) - texierr(p, "unknown multitable type"); + texierr(p, "unknown multitable command"); while (*pos < sz && '\n' != buf[*pos]) { while (*pos < sz && isws(buf[*pos])) advance(p, buf, pos);