version 1.10, 2015/02/23 15:09:09 |
version 1.13, 2015/02/24 14:35:40 |
Line 43 texifilepop(struct texi *p) |
|
Line 43 texifilepop(struct texi *p) |
|
|
|
assert(p->filepos > 0); |
assert(p->filepos > 0); |
f = &p->files[--p->filepos]; |
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 |
static void |
Line 157 texierr(struct texi *p, const char *fmt, ...) |
|
Line 160 texierr(struct texi *p, const char *fmt, ...) |
|
|
|
/* |
/* |
* Put a single data character to the output if we're not ignoring. |
* Put a single data character to the output if we're not ignoring. |
* Makes sure we don't spurriously start a macro. |
* Escape starting a line with a control character and slashes. |
* Adjusts our output status. |
|
* This shouldn't be called for macros: just for ordinary text. |
|
*/ |
*/ |
void |
void |
texiputchar(struct texi *p, char c) |
texiputchar(struct texi *p, char c) |
Line 167 texiputchar(struct texi *p, char c) |
|
Line 168 texiputchar(struct texi *p, char c) |
|
|
|
if (p->ign) |
if (p->ign) |
return; |
return; |
|
|
if ('.' == c && 0 == p->outcol) |
if ('.' == c && 0 == p->outcol) |
fputs("\\&", stdout); |
fputs("\\&", stdout); |
if ('\'' == c && 0 == p->outcol) |
if ('\'' == c && 0 == p->outcol) |
fputs("\\&", stdout); |
fputs("\\&", stdout); |
|
|
putchar(c); |
putchar(c); |
|
if ('\\' == c) |
|
putchar('e'); |
p->seenvs = 0; |
p->seenvs = 0; |
if ('\n' == c) { |
if ('\n' == c) { |
p->outcol = 0; |
p->outcol = 0; |
Line 183 texiputchar(struct texi *p, char c) |
|
Line 185 texiputchar(struct texi *p, char c) |
|
} |
} |
|
|
/* |
/* |
* Put multiple characters (see texiputchar()). |
* Put an opaque series of characters. |
* This shouldn't be called for macros: just for ordinary text. |
* 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 |
void |
texiputchars(struct texi *p, const char *s) |
texiputchars(struct texi *p, const char *s) |
{ |
{ |
|
|
while ('\0' != *s) |
if (p->ign) |
texiputchar(p, *s++); |
return; |
|
if ('.' == *s && 0 == p->outcol) |
|
fputs("\\&", stdout); |
|
if ('\'' == *s && 0 == p->outcol) |
|
fputs("\\&", stdout); |
|
p->outcol += fputs(s, stdout); |
|
p->seenvs = 0; |
} |
} |
|
|
/* |
/* |
Line 364 advancenext(struct texi *p, const char *buf, size_t sz |
|
Line 373 advancenext(struct texi *p, const char *buf, size_t sz |
|
|
|
if (p->literal) { |
if (p->literal) { |
while (*pos < sz && ismspace(buf[*pos])) { |
while (*pos < sz && ismspace(buf[*pos])) { |
if (*pos && '\n' == buf[*pos] && |
|
'\\' == buf[*pos - 1]) |
|
texiputchar(p, 'e'); |
|
texiputchar(p, buf[*pos]); |
texiputchar(p, buf[*pos]); |
advance(p, buf, pos); |
advance(p, buf, pos); |
} |
} |
|
|
texiexecmacro(struct texi *p, struct teximacro *m, |
texiexecmacro(struct texi *p, struct teximacro *m, |
const char *buf, size_t sz, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
{ |
{ |
size_t valsz, realsz, aasz, asz, |
size_t valsz, realsz, aasz, asz, |
ssz, i, j, k, start, end; |
ssz, i, j, k, start, end; |
char *val; |
char *val; |
char **args; |
char **args; |
|
const char *cp; |
|
|
args = argparse(p, buf, sz, pos, &asz, m->argsz); |
args = argparse(p, buf, sz, pos, &asz, m->argsz); |
if (asz != m->argsz) |
if (asz != m->argsz) |
Line 494 texiexecmacro(struct texi *p, struct teximacro *m, |
|
Line 501 texiexecmacro(struct texi *p, struct teximacro *m, |
|
texiabort(p, NULL); |
texiabort(p, NULL); |
} |
} |
|
|
j = strlcat(val, args[k], valsz + 1); |
for (cp = args[k]; '\0' != *cp; cp++) |
|
val[j++] = *cp; |
|
|
|
val[j] = '\0'; |
i = end; |
i = end; |
} |
} |
|
|
Line 544 texiword(struct texi *p, const char *buf, |
|
Line 554 texiword(struct texi *p, const char *buf, |
|
'\'' == buf[*pos + 1]) { |
'\'' == buf[*pos + 1]) { |
texiputchars(p, "\\(rq"); |
texiputchars(p, "\\(rq"); |
advance(p, buf, pos); |
advance(p, buf, pos); |
} else if ('\\' == buf[*pos]) { |
|
texiputchar(p, buf[*pos]); |
|
texiputchar(p, 'e'); |
|
} else |
} else |
texiputchar(p, buf[*pos]); |
texiputchar(p, buf[*pos]); |
advance(p, buf, pos); |
advance(p, buf, pos); |
Line 951 parseto(struct texi *p, const char *buf, |
|
Line 958 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 = "<stdin>"; |
|
|
|
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 |
* 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 |
* zero, in which case we just dump the file to stdout (making sure it |
* doesn't trip up mdoc(7) along the way). |
* doesn't trip up mdoc(7) along the way). |
Line 969 parsefile(struct texi *p, const char *fname, int parse |
|
Line 1017 parsefile(struct texi *p, const char *fname, int parse |
|
f = &p->files[p->filepos]; |
f = &p->files[p->filepos]; |
memset(f, 0, sizeof(struct texifile)); |
memset(f, 0, sizeof(struct texifile)); |
|
|
|
f->type = TEXISRC_FILE; |
f->name = fname; |
f->name = fname; |
if (-1 == (fd = open(fname, O_RDONLY, 0))) { |
if (-1 == (fd = open(fname, O_RDONLY, 0))) { |
texiabort(p, fname); |
texiabort(p, fname); |
Line 987 parsefile(struct texi *p, const char *fname, int parse |
|
Line 1036 parsefile(struct texi *p, const char *fname, int parse |
|
|
|
p->filepos++; |
p->filepos++; |
if ( ! parse) { |
if ( ! parse) { |
/* |
for (i = 0; i < f->mapsz; i++) |
* We're printing verbatim output. |
texiputchar(p, f->map[i]); |
* Make sure it doesn't get interpreted as mdoc by |
if (p->outcol) |
* escaping escapes and making sure leading dots don't |
texiputchar(p, '\n'); |
* 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'); |
|
} |
|
} else |
} else |
parseeof(p, f->map, f->mapsz); |
parseeof(p, f->map, f->mapsz); |
texifilepop(p); |
texifilepop(p); |
Line 1221 argparse(struct texi *p, const char *buf, |
|
Line 1260 argparse(struct texi *p, const char *buf, |
|
/* Test for zero-length '{ }'. */ |
/* Test for zero-length '{ }'. */ |
if (start == end && '}' == buf[*pos] && 0 == *argsz) |
if (start == end && '}' == buf[*pos] && 0 == *argsz) |
break; |
break; |
if (start == end) |
|
texierr(p, "zero-length argument"); |
|
/* FIXME: use reallocarray. */ |
/* FIXME: use reallocarray. */ |
args = realloc |
args = realloc |
(args, sizeof(char *) * |
(args, sizeof(char *) * |