=================================================================== RCS file: /cvs/texi2mdoc/util.c,v retrieving revision 1.11 retrieving revision 1.13 diff -u -p -r1.11 -r1.13 --- texi2mdoc/util.c 2015/02/23 17:24:51 1.11 +++ texi2mdoc/util.c 2015/02/24 14:35:40 1.13 @@ -1,4 +1,4 @@ -/* $Id: util.c,v 1.11 2015/02/23 17:24:51 kristaps Exp $ */ +/* $Id: util.c,v 1.13 2015/02/24 14:35:40 kristaps Exp $ */ /* * Copyright (c) 2015 Kristaps Dzonsons * @@ -43,7 +43,10 @@ texifilepop(struct texi *p) assert(p->filepos > 0); f = &p->files[--p->filepos]; - munmap(f->map, f->mapsz); + if (TEXISRC_FILE == f->type) + munmap(f->map, f->mapsz); + else + free(f->map); } static void @@ -157,9 +160,7 @@ texierr(struct texi *p, const char *fmt, ...) /* * Put a single data character to the output if we're not ignoring. - * Makes sure we don't spurriously start a macro. - * Adjusts our output status. - * This shouldn't be called for macros: just for ordinary text. + * Escape starting a line with a control character and slashes. */ void texiputchar(struct texi *p, char c) @@ -167,13 +168,14 @@ texiputchar(struct texi *p, char c) if (p->ign) return; - if ('.' == c && 0 == p->outcol) fputs("\\&", stdout); if ('\'' == c && 0 == p->outcol) fputs("\\&", stdout); putchar(c); + if ('\\' == c) + putchar('e'); p->seenvs = 0; if ('\n' == c) { p->outcol = 0; @@ -183,15 +185,22 @@ texiputchar(struct texi *p, char c) } /* - * Put multiple characters (see texiputchar()). - * This shouldn't be called for macros: just for ordinary text. + * Put an opaque series of characters. + * Characters starting a line with a control character are escaped, but + * that's it, so don't use this for non-controlled sequences of text. */ void texiputchars(struct texi *p, const char *s) { - while ('\0' != *s) - texiputchar(p, *s++); + if (p->ign) + return; + if ('.' == *s && 0 == p->outcol) + fputs("\\&", stdout); + if ('\'' == *s && 0 == p->outcol) + fputs("\\&", stdout); + p->outcol += fputs(s, stdout); + p->seenvs = 0; } /* @@ -364,9 +373,6 @@ advancenext(struct texi *p, const char *buf, size_t sz if (p->literal) { while (*pos < sz && ismspace(buf[*pos])) { - if (*pos && '\n' == buf[*pos] && - '\\' == buf[*pos - 1]) - texiputchar(p, 'e'); texiputchar(p, buf[*pos]); advance(p, buf, pos); } @@ -548,9 +554,6 @@ texiword(struct texi *p, const char *buf, '\'' == buf[*pos + 1]) { texiputchars(p, "\\(rq"); advance(p, buf, pos); - } else if ('\\' == buf[*pos]) { - texiputchar(p, buf[*pos]); - texiputchar(p, 'e'); } else texiputchar(p, buf[*pos]); advance(p, buf, pos); @@ -955,6 +958,47 @@ parseto(struct texi *p, const char *buf, } /* + * Like parsefile() but used for reading from stdandard input. + * This can only be called for the first file! + */ +void +parsestdin(struct texi *p) +{ + struct texifile *f; + size_t off; + ssize_t ssz; + + assert(0 == p->filepos); + f = &p->files[p->filepos]; + memset(f, 0, sizeof(struct texifile)); + + f->type = TEXISRC_STDIN; + f->name = ""; + + for (off = 0; ; off += (size_t)ssz) { + if (off == f->mapsz) { + if (f->mapsz == (1U << 31)) + texierr(p, "stdin buffer too long"); + f->mapsz = f->mapsz > 65536 / 2 ? + 2 * f->mapsz : 65536; + f->map = realloc(f->map, f->mapsz); + if (NULL == f->map) + texiabort(p, NULL); + } + ssz = read(STDIN_FILENO, + f->map + (int)off, f->mapsz - off); + if (0 == ssz) + break; + else if (-1 == ssz) + texiabort(p, NULL); + } + + p->filepos++; + parseeof(p, f->map, off); + texifilepop(p); +} + +/* * Memory-map the file "fname" and begin parsing it unless "parse" is * zero, in which case we just dump the file to stdout (making sure it * doesn't trip up mdoc(7) along the way). @@ -973,6 +1017,7 @@ parsefile(struct texi *p, const char *fname, int parse f = &p->files[p->filepos]; memset(f, 0, sizeof(struct texifile)); + f->type = TEXISRC_FILE; f->name = fname; if (-1 == (fd = open(fname, O_RDONLY, 0))) { texiabort(p, fname); @@ -991,20 +1036,10 @@ parsefile(struct texi *p, const char *fname, int parse p->filepos++; if ( ! parse) { - /* - * We're printing verbatim output. - * Make sure it doesn't get interpreted as mdoc by - * escaping escapes and making sure leading dots don't - * trigger mdoc(7) expansion. - */ - for (i = 0; i < f->mapsz; i++) { - if (i > 0 && '.' == f->map[i]) - if ('\n' == f->map[i - 1]) - fputs("\\&", stdout); - putchar(f->map[i]); - if ('\\' == f->map[i]) - putchar('e'); - } + for (i = 0; i < f->mapsz; i++) + texiputchar(p, f->map[i]); + if (p->outcol) + texiputchar(p, '\n'); } else parseeof(p, f->map, f->mapsz); texifilepop(p);