=================================================================== RCS file: /cvs/texi2mdoc/util.c,v retrieving revision 1.14 retrieving revision 1.17 diff -u -p -r1.14 -r1.17 --- texi2mdoc/util.c 2015/02/25 14:37:17 1.14 +++ texi2mdoc/util.c 2015/02/28 00:03:20 1.17 @@ -1,4 +1,4 @@ -/* $Id: util.c,v 1.14 2015/02/25 14:37:17 kristaps Exp $ */ +/* $Id: util.c,v 1.17 2015/02/28 00:03:20 kristaps Exp $ */ /* * Copyright (c) 2015 Kristaps Dzonsons * @@ -122,12 +122,19 @@ texiabort(struct texi *p, const char *errstring) void texiwarn(const struct texi *p, const char *fmt, ...) { - va_list ap; + va_list ap; + const struct texifile *f; - fprintf(stderr, "%s:%zu:%zu: warning: ", - p->files[p->filepos - 1].name, - p->files[p->filepos - 1].line + 1, - p->files[p->filepos - 1].col + 1); + f = &p->files[p->filepos - 1]; + + if (f->insplice) + fprintf(stderr, "%s:%zu:%zu (%zuB left in splice): " + "warning: ", f->name, f->line + 1, + f->col + 1, f->insplice); + else + fprintf(stderr, "%s:%zu:%zu: warning: ", + f->name, f->line + 1, f->col + 1); + va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); @@ -141,12 +148,19 @@ texiwarn(const struct texi *p, const char *fmt, ...) void texierr(struct texi *p, const char *fmt, ...) { - va_list ap; + va_list ap; + struct texifile *f; - fprintf(stderr, "%s:%zu:%zu: error: ", - p->files[p->filepos - 1].name, - p->files[p->filepos - 1].line + 1, - p->files[p->filepos - 1].col + 1); + f = &p->files[p->filepos - 1]; + + if (f->insplice) + fprintf(stderr, "%s:%zu:%zu: (%zuB left in splice): " + "error: ", f->name, f->line + 1, + f->col + 1, f->insplice); + else + fprintf(stderr, "%s:%zu:%zu: error: ", + f->name, f->line + 1, f->col + 1); + va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); @@ -306,13 +320,22 @@ texivspace(struct texi *p) void advance(struct texi *p, size_t *pos) { + struct texifile *f; - if ('\n' == BUF(p)[*pos]) { - p->files[p->filepos - 1].line++; - p->files[p->filepos - 1].col = 0; - } else - p->files[p->filepos - 1].col++; + f = &p->files[p->filepos - 1]; + if (0 == f->insplice) { + if ('\n' == BUF(p)[*pos]) { + f->line++; + f->col = 0; + } else + f->col++; + } else { + --f->insplice; + if (0 == f->insplice) + f->depth = 0; + } + (*pos)++; } @@ -419,7 +442,7 @@ advanceto(struct texi *p, size_t *pos, size_t end) } static void -texiexecmacro(struct texi *p, struct teximacro *m, size_t *pos) +texiexecmacro(struct texi *p, struct teximacro *m, size_t sv, size_t *pos) { size_t valsz, realsz, aasz, asz, ssz, i, j, k, start, end; @@ -427,17 +450,31 @@ texiexecmacro(struct texi *p, struct teximacro *m, siz char **args; const char *cp; + /* Disregard empty macros. */ + if (0 == (valsz = realsz = strlen(m->value))) + return; + + /* + * This is important: it protect us from macros that invoke more + * macros, possibly going on infinitely. + * We use "sv" instead of the current position because we might + * be invoked at the end of the macro (i.e., insplice == 0). + * The "sv" value was initialised at the start of the macro. + */ + if (sv > 0) + if (++p->files[p->filepos].depth > 64) + texierr(p, "maximium recursive depth"); + args = argparse(p, pos, &asz, m->argsz); if (asz != m->argsz) texiwarn(p, "invalid macro argument length"); aasz = asz < m->argsz ? asz : m->argsz; if (0 == aasz) { - texisplice(p, m->value, strlen(m->value), pos); + texisplice(p, m->value, valsz, pos); return; } - valsz = realsz = strlen(m->value); val = strdup(m->value); for (i = j = 0; i < realsz; i++) { @@ -569,7 +606,7 @@ texicmd(struct texi *p, size_t pos, size_t *end, struc return(TEXICMD__MAX); /* Alphabetic commands are special. */ - if ( ! isalpha(BUF(p)[pos])) { + if ( ! isalpha((unsigned char)BUF(p)[pos])) { if ((*end = pos + 1) == BUFSZ(p)) return(TEXICMD__MAX); for (i = 0; i < TEXICMD__MAX; i++) { @@ -633,7 +670,7 @@ texicmd(struct texi *p, size_t pos, size_t *end, struc int parsearg(struct texi *p, size_t *pos, size_t num) { - size_t end; + size_t end, sv; enum texicmd cmd; struct teximacro *macro; @@ -664,10 +701,11 @@ parsearg(struct texi *p, size_t *pos, size_t num) continue; } + sv = p->files[p->filepos - 1].insplice; cmd = texicmd(p, *pos, &end, ¯o); advanceto(p, pos, end); if (NULL != macro) - texiexecmacro(p, macro, pos); + texiexecmacro(p, macro, sv, pos); if (TEXICMD__MAX == cmd) continue; if (NULL != texitoks[cmd].fp) @@ -683,7 +721,7 @@ parsearg(struct texi *p, size_t *pos, size_t num) void parsebracket(struct texi *p, size_t *pos) { - size_t end; + size_t end, sv; enum texicmd cmd; struct teximacro *macro; @@ -711,10 +749,11 @@ parsebracket(struct texi *p, size_t *pos) continue; } + sv = p->files[p->filepos - 1].insplice; cmd = texicmd(p, *pos, &end, ¯o); advanceto(p, pos, end); if (NULL != macro) - texiexecmacro(p, macro, pos); + texiexecmacro(p, macro, sv, pos); if (TEXICMD__MAX == cmd) continue; if (NULL != texitoks[cmd].fp) @@ -730,7 +769,7 @@ parsebracket(struct texi *p, size_t *pos) void parseeoln(struct texi *p, size_t *pos) { - size_t end; + size_t end, sv; enum texicmd cmd; struct teximacro *macro; @@ -759,10 +798,11 @@ parseeoln(struct texi *p, size_t *pos) continue; } + sv = p->files[p->filepos - 1].insplice; cmd = texicmd(p, *pos, &end, ¯o); advanceto(p, pos, end); if (NULL != macro) - texiexecmacro(p, macro, pos); + texiexecmacro(p, macro, sv, pos); if (TEXICMD__MAX == cmd) continue; if (NULL != texitoks[cmd].fp) @@ -780,7 +820,7 @@ parseeoln(struct texi *p, size_t *pos) static void parsesingle(struct texi *p, size_t *pos) { - size_t end; + size_t end, sv; enum texicmd cmd; struct teximacro *macro; @@ -805,10 +845,11 @@ parsesingle(struct texi *p, size_t *pos) return; } + sv = p->files[p->filepos - 1].insplice; cmd = texicmd(p, *pos, &end, ¯o); advanceto(p, pos, end); if (NULL != macro) - texiexecmacro(p, macro, pos); + texiexecmacro(p, macro, sv, pos); if (TEXICMD__MAX == cmd) return; if (NULL != texitoks[cmd].fp) @@ -871,6 +912,7 @@ texisplice(struct texi *p, const char *buf, size_t sz, f->map = cp; } + f->insplice += sz; memmove(f->map + *pos + sz, f->map + *pos, f->mapsz - *pos); memcpy(f->map + *pos, buf, sz); f->mapsz += sz; @@ -884,7 +926,7 @@ texisplice(struct texi *p, const char *buf, size_t sz, void parseto(struct texi *p, size_t *pos, const char *endtoken) { - size_t end; + size_t end, sv; enum texicmd cmd; size_t endtoksz; struct teximacro *macro; @@ -911,6 +953,7 @@ parseto(struct texi *p, size_t *pos, const char *endto continue; } + sv = p->files[p->filepos - 1].insplice; cmd = texicmd(p, *pos, &end, ¯o); advanceto(p, pos, end); if (TEXICMD_END == cmd) { @@ -931,7 +974,7 @@ parseto(struct texi *p, size_t *pos, const char *endto continue; } if (NULL != macro) - texiexecmacro(p, macro, pos); + texiexecmacro(p, macro, sv, pos); if (TEXICMD__MAX == cmd) continue; if (NULL != texitoks[cmd].fp) @@ -1188,6 +1231,9 @@ argparse(struct texi *p, size_t *pos, size_t *argsz, s args = NULL; *argsz = 0; + if (*pos == BUFSZ(p)) + return(args); + if ('{' != BUF(p)[*pos] && hint) { /* * Special case: if we encounter an unbracketed argument @@ -1213,6 +1259,8 @@ argparse(struct texi *p, size_t *pos, size_t *argsz, s return(args); } else if ('{' != BUF(p)[*pos]) return(args); + + assert('{' == BUF(p)[*pos]); /* Parse til the closing '}', putting into the array. */ advance(p, pos);