version 1.8, 2015/02/23 11:56:39 |
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) |
|
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 181 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; |
} |
} |
|
|
/* |
/* |
|
* This puts all characters onto the output stream but makes sure to |
|
* escape mdoc(7) slashes. |
|
*/ |
|
void |
|
texiputbuf(struct texi *p, const char *buf, size_t start, size_t end) |
|
{ |
|
|
|
for ( ; start < end; start++) { |
|
texiputchar(p, buf[start]); |
|
if ('\\' == buf[start]) |
|
texiputchar(p, 'e'); |
|
} |
|
} |
|
|
|
/* |
* Close an mdoc(7) macro opened with teximacroopen(). |
* Close an mdoc(7) macro opened with teximacroopen(). |
* If there are no more macros on the line, prints a newline. |
* If there are no more macros on the line, prints a newline. |
*/ |
*/ |
Line 347 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 477 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 931 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 949 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 967 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 1143 argparse(struct texi *p, const char *buf, |
|
Line 1202 argparse(struct texi *p, const char *buf, |
|
args = NULL; |
args = NULL; |
*argsz = 0; |
*argsz = 0; |
|
|
/* Check for no arguments. */ |
if ('{' != buf[*pos] && hint) { |
if ('{' != buf[*pos]) |
/* |
|
* Special case: if we encounter an unbracketed argument |
|
* and we're being invoked with non-zero arguments |
|
* (versus being set, i.e., hint>0), then parse until |
|
* the end of line. |
|
*/ |
|
*argsz = 1; |
|
args = calloc(1, sizeof(char *)); |
|
if (NULL == args) |
|
texiabort(p, NULL); |
|
start = *pos; |
|
while (*pos < sz) { |
|
if ('\n' == buf[*pos]) |
|
break; |
|
advance(p, buf, pos); |
|
} |
|
args[0] = malloc(*pos - start + 1); |
|
memcpy(args[0], &buf[start], *pos - start); |
|
args[0][*pos - start] = '\0'; |
|
if (*pos < sz && '\n' == buf[*pos]) |
|
advance(p, buf, pos); |
return(args); |
return(args); |
|
} else if ('{' != buf[*pos]) |
|
return(args); |
|
|
/* Parse til the closing '}', putting into the array. */ |
/* Parse til the closing '}', putting into the array. */ |
advance(p, buf, pos); |
advance(p, buf, pos); |
Line 1179 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 *) * |