version 1.14, 2015/02/25 14:37:17 |
version 1.18, 2015/02/28 08:41:59 |
Line 122 texiabort(struct texi *p, const char *errstring) |
|
Line 122 texiabort(struct texi *p, const char *errstring) |
|
void |
void |
texiwarn(const struct texi *p, const char *fmt, ...) |
texiwarn(const struct texi *p, const char *fmt, ...) |
{ |
{ |
va_list ap; |
va_list ap; |
|
const struct texifile *f; |
|
|
fprintf(stderr, "%s:%zu:%zu: warning: ", |
f = &p->files[p->filepos - 1]; |
p->files[p->filepos - 1].name, |
|
p->files[p->filepos - 1].line + 1, |
if (f->insplice) |
p->files[p->filepos - 1].col + 1); |
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); |
va_start(ap, fmt); |
vfprintf(stderr, fmt, ap); |
vfprintf(stderr, fmt, ap); |
va_end(ap); |
va_end(ap); |
Line 141 texiwarn(const struct texi *p, const char *fmt, ...) |
|
Line 148 texiwarn(const struct texi *p, const char *fmt, ...) |
|
void |
void |
texierr(struct texi *p, const char *fmt, ...) |
texierr(struct texi *p, const char *fmt, ...) |
{ |
{ |
va_list ap; |
va_list ap; |
|
struct texifile *f; |
|
|
fprintf(stderr, "%s:%zu:%zu: error: ", |
f = &p->files[p->filepos - 1]; |
p->files[p->filepos - 1].name, |
|
p->files[p->filepos - 1].line + 1, |
if (f->insplice) |
p->files[p->filepos - 1].col + 1); |
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); |
va_start(ap, fmt); |
vfprintf(stderr, fmt, ap); |
vfprintf(stderr, fmt, ap); |
va_end(ap); |
va_end(ap); |
Line 306 texivspace(struct texi *p) |
|
Line 320 texivspace(struct texi *p) |
|
void |
void |
advance(struct texi *p, size_t *pos) |
advance(struct texi *p, size_t *pos) |
{ |
{ |
|
struct texifile *f; |
|
|
if ('\n' == BUF(p)[*pos]) { |
f = &p->files[p->filepos - 1]; |
p->files[p->filepos - 1].line++; |
|
p->files[p->filepos - 1].col = 0; |
|
} else |
|
p->files[p->filepos - 1].col++; |
|
|
|
|
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)++; |
(*pos)++; |
} |
} |
|
|
Line 419 advanceto(struct texi *p, size_t *pos, size_t end) |
|
Line 442 advanceto(struct texi *p, size_t *pos, size_t end) |
|
} |
} |
|
|
static void |
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, |
size_t valsz, realsz, aasz, asz, |
ssz, i, j, k, start, end; |
ssz, i, j, k, start, end; |
Line 427 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
Line 450 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
char **args; |
char **args; |
const char *cp; |
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); |
args = argparse(p, pos, &asz, m->argsz); |
if (asz != m->argsz) |
if (asz != m->argsz) |
texiwarn(p, "invalid macro argument length"); |
texiwarn(p, "invalid macro argument length"); |
aasz = asz < m->argsz ? asz : m->argsz; |
aasz = asz < m->argsz ? asz : m->argsz; |
|
|
if (0 == aasz) { |
if (0 == aasz) { |
texisplice(p, m->value, strlen(m->value), pos); |
texisplice(p, m->value, valsz, pos); |
return; |
return; |
} |
} |
|
|
valsz = realsz = strlen(m->value); |
|
val = strdup(m->value); |
val = strdup(m->value); |
|
|
for (i = j = 0; i < realsz; i++) { |
for (i = j = 0; i < realsz; i++) { |
Line 569 texicmd(struct texi *p, size_t pos, size_t *end, struc |
|
Line 606 texicmd(struct texi *p, size_t pos, size_t *end, struc |
|
return(TEXICMD__MAX); |
return(TEXICMD__MAX); |
|
|
/* Alphabetic commands are special. */ |
/* Alphabetic commands are special. */ |
if ( ! isalpha(BUF(p)[pos])) { |
if ( ! isalpha((unsigned char)BUF(p)[pos])) { |
if ((*end = pos + 1) == BUFSZ(p)) |
if ((*end = pos + 1) == BUFSZ(p)) |
return(TEXICMD__MAX); |
return(TEXICMD__MAX); |
for (i = 0; i < TEXICMD__MAX; i++) { |
for (i = 0; i < TEXICMD__MAX; i++) { |
Line 633 texicmd(struct texi *p, size_t pos, size_t *end, struc |
|
Line 670 texicmd(struct texi *p, size_t pos, size_t *end, struc |
|
int |
int |
parsearg(struct texi *p, size_t *pos, size_t num) |
parsearg(struct texi *p, size_t *pos, size_t num) |
{ |
{ |
size_t end; |
size_t end, sv; |
enum texicmd cmd; |
enum texicmd cmd; |
struct teximacro *macro; |
struct teximacro *macro; |
|
|
Line 664 parsearg(struct texi *p, size_t *pos, size_t num) |
|
Line 701 parsearg(struct texi *p, size_t *pos, size_t num) |
|
continue; |
continue; |
} |
} |
|
|
|
sv = p->files[p->filepos - 1].insplice; |
cmd = texicmd(p, *pos, &end, ¯o); |
cmd = texicmd(p, *pos, &end, ¯o); |
advanceto(p, pos, end); |
advanceto(p, pos, end); |
if (NULL != macro) |
if (NULL != macro) |
texiexecmacro(p, macro, pos); |
texiexecmacro(p, macro, sv, pos); |
if (TEXICMD__MAX == cmd) |
if (TEXICMD__MAX == cmd) |
continue; |
continue; |
if (NULL != texitoks[cmd].fp) |
if (NULL != texitoks[cmd].fp) |
Line 681 parsearg(struct texi *p, size_t *pos, size_t num) |
|
Line 719 parsearg(struct texi *p, size_t *pos, size_t num) |
|
* This will stop in the event of EOF or if we're not at a bracket. |
* This will stop in the event of EOF or if we're not at a bracket. |
*/ |
*/ |
void |
void |
parsebracket(struct texi *p, size_t *pos) |
parsebracket(struct texi *p, size_t *pos, int dostack) |
{ |
{ |
size_t end; |
size_t end, sv, stack; |
enum texicmd cmd; |
enum texicmd cmd; |
struct teximacro *macro; |
struct teximacro *macro; |
|
|
Line 694 parsebracket(struct texi *p, size_t *pos) |
|
Line 732 parsebracket(struct texi *p, size_t *pos) |
|
return; |
return; |
advance(p, pos); |
advance(p, pos); |
|
|
|
stack = 0; |
while ((*pos = advancenext(p, pos)) < BUFSZ(p)) { |
while ((*pos = advancenext(p, pos)) < BUFSZ(p)) { |
switch (BUF(p)[*pos]) { |
switch (BUF(p)[*pos]) { |
case ('}'): |
case ('}'): |
|
if (stack > 0) { |
|
stack--; |
|
advance(p, pos); |
|
texiputchar(p, '}'); |
|
continue; |
|
} |
advance(p, pos); |
advance(p, pos); |
return; |
return; |
case ('{'): |
case ('{'): |
|
if (dostack) { |
|
stack++; |
|
advance(p, pos); |
|
texiputchar(p, '{'); |
|
continue; |
|
} |
if (0 == p->ign) |
if (0 == p->ign) |
texiwarn(p, "unexpected \"{\""); |
texiwarn(p, "unexpected \"{\""); |
advance(p, pos); |
advance(p, pos); |
Line 711 parsebracket(struct texi *p, size_t *pos) |
|
Line 762 parsebracket(struct texi *p, size_t *pos) |
|
continue; |
continue; |
} |
} |
|
|
|
sv = p->files[p->filepos - 1].insplice; |
cmd = texicmd(p, *pos, &end, ¯o); |
cmd = texicmd(p, *pos, &end, ¯o); |
advanceto(p, pos, end); |
advanceto(p, pos, end); |
if (NULL != macro) |
if (NULL != macro) |
texiexecmacro(p, macro, pos); |
texiexecmacro(p, macro, sv, pos); |
if (TEXICMD__MAX == cmd) |
if (TEXICMD__MAX == cmd) |
continue; |
continue; |
if (NULL != texitoks[cmd].fp) |
if (NULL != texitoks[cmd].fp) |
Line 730 parsebracket(struct texi *p, size_t *pos) |
|
Line 782 parsebracket(struct texi *p, size_t *pos) |
|
void |
void |
parseeoln(struct texi *p, size_t *pos) |
parseeoln(struct texi *p, size_t *pos) |
{ |
{ |
size_t end; |
size_t end, sv; |
enum texicmd cmd; |
enum texicmd cmd; |
struct teximacro *macro; |
struct teximacro *macro; |
|
|
Line 759 parseeoln(struct texi *p, size_t *pos) |
|
Line 811 parseeoln(struct texi *p, size_t *pos) |
|
continue; |
continue; |
} |
} |
|
|
|
sv = p->files[p->filepos - 1].insplice; |
cmd = texicmd(p, *pos, &end, ¯o); |
cmd = texicmd(p, *pos, &end, ¯o); |
advanceto(p, pos, end); |
advanceto(p, pos, end); |
if (NULL != macro) |
if (NULL != macro) |
texiexecmacro(p, macro, pos); |
texiexecmacro(p, macro, sv, pos); |
if (TEXICMD__MAX == cmd) |
if (TEXICMD__MAX == cmd) |
continue; |
continue; |
if (NULL != texitoks[cmd].fp) |
if (NULL != texitoks[cmd].fp) |
Line 780 parseeoln(struct texi *p, size_t *pos) |
|
Line 833 parseeoln(struct texi *p, size_t *pos) |
|
static void |
static void |
parsesingle(struct texi *p, size_t *pos) |
parsesingle(struct texi *p, size_t *pos) |
{ |
{ |
size_t end; |
size_t end, sv; |
enum texicmd cmd; |
enum texicmd cmd; |
struct teximacro *macro; |
struct teximacro *macro; |
|
|
Line 805 parsesingle(struct texi *p, size_t *pos) |
|
Line 858 parsesingle(struct texi *p, size_t *pos) |
|
return; |
return; |
} |
} |
|
|
|
sv = p->files[p->filepos - 1].insplice; |
cmd = texicmd(p, *pos, &end, ¯o); |
cmd = texicmd(p, *pos, &end, ¯o); |
advanceto(p, pos, end); |
advanceto(p, pos, end); |
if (NULL != macro) |
if (NULL != macro) |
texiexecmacro(p, macro, pos); |
texiexecmacro(p, macro, sv, pos); |
if (TEXICMD__MAX == cmd) |
if (TEXICMD__MAX == cmd) |
return; |
return; |
if (NULL != texitoks[cmd].fp) |
if (NULL != texitoks[cmd].fp) |
Line 833 parselinearg(struct texi *p, size_t *pos) |
|
Line 887 parselinearg(struct texi *p, size_t *pos) |
|
} |
} |
|
|
if (*pos < BUFSZ(p) && '{' == BUF(p)[*pos]) |
if (*pos < BUFSZ(p) && '{' == BUF(p)[*pos]) |
parsebracket(p, pos); |
parsebracket(p, pos, 0); |
else if (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) |
else if (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) |
parsesingle(p, pos); |
parsesingle(p, pos); |
else |
else |
Line 871 texisplice(struct texi *p, const char *buf, size_t sz, |
|
Line 925 texisplice(struct texi *p, const char *buf, size_t sz, |
|
f->map = cp; |
f->map = cp; |
} |
} |
|
|
|
f->insplice += sz; |
memmove(f->map + *pos + sz, f->map + *pos, f->mapsz - *pos); |
memmove(f->map + *pos + sz, f->map + *pos, f->mapsz - *pos); |
memcpy(f->map + *pos, buf, sz); |
memcpy(f->map + *pos, buf, sz); |
f->mapsz += sz; |
f->mapsz += sz; |
Line 884 texisplice(struct texi *p, const char *buf, size_t sz, |
|
Line 939 texisplice(struct texi *p, const char *buf, size_t sz, |
|
void |
void |
parseto(struct texi *p, size_t *pos, const char *endtoken) |
parseto(struct texi *p, size_t *pos, const char *endtoken) |
{ |
{ |
size_t end; |
size_t end, sv; |
enum texicmd cmd; |
enum texicmd cmd; |
size_t endtoksz; |
size_t endtoksz; |
struct teximacro *macro; |
struct teximacro *macro; |
Line 911 parseto(struct texi *p, size_t *pos, const char *endto |
|
Line 966 parseto(struct texi *p, size_t *pos, const char *endto |
|
continue; |
continue; |
} |
} |
|
|
|
sv = p->files[p->filepos - 1].insplice; |
cmd = texicmd(p, *pos, &end, ¯o); |
cmd = texicmd(p, *pos, &end, ¯o); |
advanceto(p, pos, end); |
advanceto(p, pos, end); |
if (TEXICMD_END == cmd) { |
if (TEXICMD_END == cmd) { |
Line 931 parseto(struct texi *p, size_t *pos, const char *endto |
|
Line 987 parseto(struct texi *p, size_t *pos, const char *endto |
|
continue; |
continue; |
} |
} |
if (NULL != macro) |
if (NULL != macro) |
texiexecmacro(p, macro, pos); |
texiexecmacro(p, macro, sv, pos); |
if (TEXICMD__MAX == cmd) |
if (TEXICMD__MAX == cmd) |
continue; |
continue; |
if (NULL != texitoks[cmd].fp) |
if (NULL != texitoks[cmd].fp) |
Line 1188 argparse(struct texi *p, size_t *pos, size_t *argsz, s |
|
Line 1244 argparse(struct texi *p, size_t *pos, size_t *argsz, s |
|
args = NULL; |
args = NULL; |
*argsz = 0; |
*argsz = 0; |
|
|
|
if (*pos == BUFSZ(p)) |
|
return(args); |
|
|
if ('{' != BUF(p)[*pos] && hint) { |
if ('{' != BUF(p)[*pos] && hint) { |
/* |
/* |
* Special case: if we encounter an unbracketed argument |
* Special case: if we encounter an unbracketed argument |
Line 1213 argparse(struct texi *p, size_t *pos, size_t *argsz, s |
|
Line 1272 argparse(struct texi *p, size_t *pos, size_t *argsz, s |
|
return(args); |
return(args); |
} else if ('{' != BUF(p)[*pos]) |
} else if ('{' != BUF(p)[*pos]) |
return(args); |
return(args); |
|
|
|
assert('{' == BUF(p)[*pos]); |
|
|
/* Parse til the closing '}', putting into the array. */ |
/* Parse til the closing '}', putting into the array. */ |
advance(p, pos); |
advance(p, pos); |