=================================================================== RCS file: /cvs/texi2mdoc/util.c,v retrieving revision 1.29 retrieving revision 1.30 diff -u -p -r1.29 -r1.30 --- texi2mdoc/util.c 2015/03/07 11:53:21 1.29 +++ texi2mdoc/util.c 2015/03/11 12:51:41 1.30 @@ -1,4 +1,4 @@ -/* $Id: util.c,v 1.29 2015/03/07 11:53:21 kristaps Exp $ */ +/* $Id: util.c,v 1.30 2015/03/11 12:51:41 kristaps Exp $ */ /* * Copyright (c) 2015 Kristaps Dzonsons * @@ -103,7 +103,121 @@ texivaluefree(struct texivalue *p) free(p->value); } +static void +texidex_free(struct texidex *p) +{ + size_t i; + + for (i = 0; i < p->indexsz; i++) + free(p->index[i]); + + free(p->index); + free(p->name); + p->index = NULL; + p->indexsz = 0; +} + /* + * Add the text beginning at "index" and of "sz" bytes to the index + * named "tok" with name size "toksz". + * This will also output the necessary mdoc(7) to construct the index. + */ +void +texindex(struct texi *p, const char *tok, + size_t toksz, const char *index, size_t sz) +{ + size_t i; +#ifdef HAVE_INDEX + char *cp; +#endif + + if (0 == sz) { + texiwarn(p, "zero-length index entry"); + return; + } + + /* Look for the index. (Must be found.) */ + for (i = 0; i < p->indexsz; i++) { + if (strlen(p->indexs[i].name) != toksz) + continue; + if (strncmp(p->indexs[i].name, tok, toksz)) + continue; + break; + } + + assert(i < p->indexsz); + /* Reallocate index's terms. */ + p->indexs[i].index = realloc + (p->indexs[i].index, + (p->indexs[i].indexsz + 1) * + sizeof(char *)); + if (NULL == p->indexs[i].index) + texiabort(p, NULL); + + /* Add term to term array. */ + p->indexs[i].index[p->indexs[i].indexsz] = + malloc(sz + 1); + if (NULL == p->indexs[i].index[p->indexs[i].indexsz]) + texiabort(p, NULL); + memcpy(p->indexs[i].index[p->indexs[i].indexsz], + index, sz); + p->indexs[i].index[p->indexs[i].indexsz][sz] = '\0'; + + /* Output mdoc(7) for index. */ +#ifdef HAVE_INDEX + p->seenvs = -1; + teximacroopen(p, "Ix"); + texiputchars(p, "idx"); + texiputchars(p, p->indexs[i].name); + cp = p->indexs[i].index[p->indexs[i].indexsz]; + while ('\n' != *cp) { + assert('\0' != *cp); + texiputchar(p, *cp++); + } + teximacroclose(p); +#endif + p->indexs[i].indexsz++; +} + +/* + * Add an index entry named "tok" of length "sz". + * This usually consists of two letters, e.g., "cp" or "vr". + * This does nothing if the index exists or is zero-sized. + */ +void +texindex_add(struct texi *p, const char *tok, size_t sz) +{ + size_t i; + char *cp; + + if (0 == sz) + return; + + /* Make sure we don't have a duplicate. */ + for (i = 0; i < p->indexsz; i++) { + if (strlen(p->indexs[i].name) != sz) + continue; + if (strncmp(p->indexs[i].name, tok, sz)) + continue; + return; + } + + /* Reallocate indices. */ + p->indexs = realloc(p->indexs, + sizeof(struct texidex) * (p->indexsz + 1)); + if (NULL == p->indexs) + texiabort(p, NULL); + if (NULL == (cp = malloc(sz + 1))) + texiabort(p, NULL); + memcpy(cp, tok, sz); + cp[sz] = '\0'; + p->indexs[p->indexsz].name = cp; + p->indexs[p->indexsz].index = NULL; + p->indexs[p->indexsz].indexsz = 0; + p->indexsz++; +} + +/* * Unmap all files that we're currently using and free all resources * that we've allocated during the parse. * The utility should exit(...) after this is called. @@ -128,7 +242,7 @@ texiexit(struct texi *p) for (i = 0; i < p->dirsz; i++) free(p->dirs[i]); for (i = 0; i < p->indexsz; i++) - free(p->indexs[i]); + texidex_free(&p->indexs[i]); for (i = 0; i < p->valsz; i++) texivaluefree(&p->vals[i]); @@ -280,14 +394,13 @@ void teximacroclose(struct texi *p) { - if (p->ign) + if (p->ign || p->literal|| TEXILIST_TABLE == p->list) return; if (0 == --p->outmacro) { fputc('\n', p->outfile); p->outcol = p->seenws = 0; } - p->seenvs = 0; } /* @@ -301,7 +414,7 @@ teximacroopen(struct texi *p, const char *s) { int rc; - if (p->ign) + if (p->ign || p->literal|| TEXILIST_TABLE == p->list) return; if (p->outcol && 0 == p->outmacro) { @@ -309,6 +422,9 @@ teximacroopen(struct texi *p, const char *s) p->outcol = 0; } + if (p->seenvs > 0 && 0 == p->outmacro) + fputs(".Pp\n", p->outfile); + if (0 == p->outmacro) fputc('.', p->outfile); else @@ -320,8 +436,7 @@ teximacroopen(struct texi *p, const char *s) fputc(' ', p->outfile); p->outcol++; p->outmacro++; - p->seenws = 0; - p->seenvs = 0; + p->seenws = p->seenvs = 0; } /* @@ -338,15 +453,15 @@ teximacro(struct texi *p, const char *s) texierr(p, "\"%s\" in open line scope!?", s); if (p->literal) texierr(p, "\"%s\" in a literal scope!?", s); - if (p->outcol) fputc('\n', p->outfile); + if (p->seenvs > 0) + fputs(".Pp\n", p->outfile); fputc('.', p->outfile); fputs(s, p->outfile); fputc('\n', p->outfile); p->outcol = p->seenws = 0; - p->seenvs = 0; } /* @@ -356,8 +471,8 @@ void texivspace(struct texi *p) { - if (TEXILIST_TABLE != p->list) - teximacro(p, "Pp"); + if (TEXILIST_TABLE != p->list && p->seenvs >= 0) + p->seenvs = 1; } /* @@ -420,7 +535,7 @@ texipunctuate(struct texi *p, size_t *pos) if (end == *pos) return; if (end + 1 == BUFSZ(p) || ' ' == BUF(p)[end] || - '\n' == BUF(p)[end]) { + '@' == BUF(p)[end] || '\n' == BUF(p)[end]) { for ( ; start < end; start++) { texiputchar(p, ' '); texiputchar(p, BUF(p)[start]); @@ -448,6 +563,9 @@ advancenext(struct texi *p, size_t *pos) while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) { p->seenws = 1; + if (0 == p->seenvs && '\n' == BUF(p)[*pos]) + if (*pos + 1 < BUFSZ(p) && '\n' == BUF(p)[*pos + 1]) + p->seenvs = 1; advance(p, pos); } return(*pos); @@ -608,11 +726,13 @@ parseword(struct texi *p, size_t *pos, char extra) * We don't do this if we're in a literal context (we'll print * out the newlines themselves) nor in a `TS' table. */ - if (p->seenvs && 0 == p->literal && TEXILIST_TABLE != p->list) - teximacro(p, "Pp"); + if (p->seenvs > 0 && 0 == p->literal && TEXILIST_TABLE != p->list) { + if (p->outcol > 0) + fputc('\n', p->outfile); + fputs(".Pp\n", p->outfile); + p->outcol = 0; + } - p->seenvs = 0; - /* * Some line control: if we (non-macro, non-literal) already * have more than 72 characters written to the screen, then @@ -684,7 +804,9 @@ parseword(struct texi *p, size_t *pos, char extra) continue; } - if (*pos < BUFSZ(p) - 2 && + if ('"' == BUF(p)[*pos]) { + texiputchars(p, "\\(dq"); + } else if (*pos < BUFSZ(p) - 2 && '-' == BUF(p)[*pos] && '-' == BUF(p)[*pos + 1] && '-' == BUF(p)[*pos + 2]) { @@ -712,19 +834,23 @@ parseword(struct texi *p, size_t *pos, char extra) advance(p, pos); } - if (*pos + 1 < BUFSZ(p) && - '\n' == BUF(p)[*pos] && - '\n' == BUF(p)[*pos + 1]) - p->seenvs = 1; - /* * New sentence, new line:if we (non-macro, non-literal) see a * period at the end of the last printed word, then open a * newline. */ - if (0 == p->literal && 0 == p->outmacro && - *pos < BUFSZ(p) && '.' == BUF(p)[*pos - 1]) - texiputchar(p, '\n'); + if (0 == p->literal && 0 == p->outmacro && *pos < BUFSZ(p)) + switch (BUF(p)[*pos - 1]) { + case ('.'): + case ('!'): + case ('?'): + texiputchar(p, '\n'); + break; + default: + break; + } + + p->seenvs = 0; } /* @@ -778,10 +904,10 @@ texicmd(const struct texi *p, size_t pos, size_t *end, /* Look for it in our indices. */ for (i = 0; i < p->indexsz; i++) { - toksz = strlen(p->indexs[i]); + toksz = strlen(p->indexs[i].name); if (len != 5 + toksz) continue; - if (strncmp(&BUF(p)[pos], p->indexs[i], toksz)) + if (strncmp(&BUF(p)[pos], p->indexs[i].name, toksz)) continue; if (0 == strncmp(&BUF(p)[pos + toksz], "index", 5)) return(TEXICMD_USER_INDEX); @@ -946,6 +1072,8 @@ parseeoln(struct texi *p, size_t *pos) texiwarn(p, "unexpected \"{\""); advance(p, pos); continue; + case ('\n'): + continue; case ('@'): break; default: @@ -968,6 +1096,18 @@ parseeoln(struct texi *p, size_t *pos) advance(p, pos); } +enum texicmd +peeklinecmd(const struct texi *p, size_t pos) +{ + size_t end; + + while (pos < BUFSZ(p) && isws(BUF(p)[pos])) + pos++; + if (pos == BUFSZ(p) || '@' != BUF(p)[pos]) + return(TEXICMD__MAX); + return(texicmd(p, pos, &end, NULL)); +} + /* * Peek to see if there's a command after subsequent whitespace. * If so, return the macro identifier. @@ -1152,6 +1292,9 @@ parseto(struct texi *p, size_t *pos, const char *endto if (NULL != texitoks[cmd].fp) (*texitoks[cmd].fp)(p, cmd, pos); } + + if (*pos == BUFSZ(p)) + texiwarn(p, "EOF expecting \"%s\" end\n", endtoken); } /* @@ -1577,6 +1720,7 @@ teximdocopen(struct texi *p, size_t *pos) t = time(NULL); strftime(date, sizeof(date), "%F", localtime(&t)); + p->seenvs = -1; teximacroopen(p, "Dd"); texiputchars(p, date); teximacroclose(p);