version 1.44, 2015/02/24 21:06:52 |
version 1.50, 2015/02/26 10:41:30 |
|
|
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <time.h> |
#include <time.h> |
|
#include <unistd.h> |
|
|
#include "extern.h" |
#include "extern.h" |
|
|
Line 38 static const char *const sects[SECTSZ] = { |
|
Line 39 static const char *const sects[SECTSZ] = { |
|
"No", |
"No", |
}; |
}; |
|
|
static void doaccent(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doaccent(struct texi *, enum texicmd, size_t *); |
static void doblock(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doblock(struct texi *, enum texicmd, size_t *); |
static void dobracket(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dobracket(struct texi *, enum texicmd, size_t *); |
static void dobye(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dobye(struct texi *, enum texicmd, size_t *); |
static void dodefindex(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dodefindex(struct texi *, enum texicmd, size_t *); |
static void dodefn(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dodefn(struct texi *, enum texicmd, size_t *); |
static void dodisplay(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dodisplay(struct texi *, enum texicmd, size_t *); |
static void doend(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doend(struct texi *, enum texicmd, size_t *); |
static void doenumerate(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doenumerate(struct texi *, enum texicmd, size_t *); |
static void doexample(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doexample(struct texi *, enum texicmd, size_t *); |
static void doignargn(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doignargn(struct texi *, enum texicmd, size_t *); |
static void doignblock(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doignblock(struct texi *, enum texicmd, size_t *); |
static void doignbracket(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doignbracket(struct texi *, enum texicmd, size_t *); |
static void doignline(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doignline(struct texi *, enum texicmd, size_t *); |
static void doinline(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doinline(struct texi *, enum texicmd, size_t *); |
static void doinclude(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doinclude(struct texi *, enum texicmd, size_t *); |
static void doitem(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doitem(struct texi *, enum texicmd, size_t *); |
static void doitemize(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doitemize(struct texi *, enum texicmd, size_t *); |
static void dolink(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dolink(struct texi *, enum texicmd, size_t *); |
static void domacro(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void domacro(struct texi *, enum texicmd, size_t *); |
static void domath(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void domath(struct texi *, enum texicmd, size_t *); |
static void domultitable(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void domultitable(struct texi *, enum texicmd, size_t *); |
static void doquotation(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doquotation(struct texi *, enum texicmd, size_t *); |
static void dotable(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dotable(struct texi *, enum texicmd, size_t *); |
static void dotop(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dotop(struct texi *, enum texicmd, size_t *); |
static void dosecoffs(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dosecoffs(struct texi *, enum texicmd, size_t *); |
static void dosection(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dosection(struct texi *, enum texicmd, size_t *); |
static void dosp(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dosp(struct texi *, enum texicmd, size_t *); |
static void dosubsection(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dosubsection(struct texi *, enum texicmd, size_t *); |
static void dosubsubsection(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dosubsubsection(struct texi *, enum texicmd, size_t *); |
static void dosymbol(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dosymbol(struct texi *, enum texicmd, size_t *); |
static void dotab(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dotab(struct texi *, enum texicmd, size_t *); |
static void dotitle(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dotitle(struct texi *, enum texicmd, size_t *); |
static void dovalue(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void dovalue(struct texi *, enum texicmd, size_t *); |
static void doverb(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doverb(struct texi *, enum texicmd, size_t *); |
static void doverbatim(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doverbatim(struct texi *, enum texicmd, size_t *); |
static void doverbinclude(struct texi *, enum texicmd, const char *, size_t, size_t *); |
static void doverbinclude(struct texi *, enum texicmd, size_t *); |
|
|
static const struct texitok __texitoks[TEXICMD__MAX] = { |
static const struct texitok __texitoks[TEXICMD__MAX] = { |
/* TEXICMD__BEGIN */ |
/* TEXICMD__BEGIN */ |
Line 295 static const struct texitok __texitoks[TEXICMD__MAX] = |
|
Line 296 static const struct texitok __texitoks[TEXICMD__MAX] = |
|
{ dosubsubsection, "subsubsection", 13 }, /* TEXICMD_SUBSUBSECTION */ |
{ dosubsubsection, "subsubsection", 13 }, /* TEXICMD_SUBSUBSECTION */ |
{ doignline, "subtitle", 8 }, /* TEXICMD_SUBTITLE */ |
{ doignline, "subtitle", 8 }, /* TEXICMD_SUBTITLE */ |
{ doignline, "summarycontents", 15 }, /* TEXICMD_SUMMARYCONTENTS */ |
{ doignline, "summarycontents", 15 }, /* TEXICMD_SUMMARYCONTENTS */ |
{ doignline, "synindex", 8 }, /* TEXICMD_SYNINDEX */ |
{ dodefindex, "synindex", 8 }, /* TEXICMD_SYNINDEX */ |
{ doignline, "syncodeindex", 12 }, /* TEXICMD_SYNCODEINDEX */ |
{ dodefindex, "syncodeindex", 12 }, /* TEXICMD_SYNCODEINDEX */ |
{ doinline, "t", 1 }, /* TEXICMD_T */ |
{ doinline, "t", 1 }, /* TEXICMD_T */ |
{ dotab, "tab", 3 }, /* TEXICMD_TAB */ |
{ dotab, "tab", 3 }, /* TEXICMD_TAB */ |
{ dosymbol, "\t", 1 }, /* TEXICMD_TABSYM */ |
{ dosymbol, "\t", 1 }, /* TEXICMD_TABSYM */ |
Line 342 static const struct texitok __texitoks[TEXICMD__MAX] = |
|
Line 343 static const struct texitok __texitoks[TEXICMD__MAX] = |
|
const struct texitok *const texitoks = __texitoks; |
const struct texitok *const texitoks = __texitoks; |
|
|
static void |
static void |
dodefindex(struct texi *p, enum texicmd cmd, |
dodefindex(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
size_t start, end; |
size_t start, end; |
char *cp; |
char *cp; |
|
|
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
|
|
start = end = *pos; |
start = end = *pos; |
while (end < sz && ! ismspace(buf[end])) |
while (end < BUFSZ(p) && ! ismspace(BUF(p)[end])) |
end++; |
end++; |
|
|
if (start == end) { |
if (start == end) { |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
return; |
return; |
} else if (NULL == (cp = malloc(end - start + 1))) |
} else if (NULL == (cp = malloc(end - start + 1))) |
texiabort(p, NULL); |
texiabort(p, NULL); |
|
|
memcpy(cp, &buf[start], end - start); |
memcpy(cp, &BUF(p)[start], end - start); |
cp[end - start] = '\0'; |
cp[end - start] = '\0'; |
|
|
p->indexs = realloc(p->indexs, |
p->indexs = realloc(p->indexs, |
Line 373 dodefindex(struct texi *p, enum texicmd cmd, |
|
Line 373 dodefindex(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
static void |
static void |
dodefn(struct texi *p, enum texicmd cmd, |
dodefn(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
const char *blk; |
const char *blk; |
|
|
Line 399 dodefn(struct texi *p, enum texicmd cmd, |
|
Line 398 dodefn(struct texi *p, enum texicmd cmd, |
|
|
|
if (p->ign) { |
if (p->ign) { |
NULL != blk ? |
NULL != blk ? |
parseto(p, buf, sz, pos, blk) : |
parseto(p, pos, blk) : |
parseeoln(p, buf, sz, pos); |
parseeoln(p, pos); |
return; |
return; |
} |
} |
|
|
Line 429 dodefn(struct texi *p, enum texicmd cmd, |
|
Line 428 dodefn(struct texi *p, enum texicmd cmd, |
|
texiputchars(p, "Function"); |
texiputchars(p, "Function"); |
break; |
break; |
default: |
default: |
parselinearg(p, buf, sz, pos); |
parselinearg(p, pos); |
break; |
break; |
} |
} |
|
|
texiputchars(p, ":\n"); |
texiputchar(p, ':'); |
|
texiputchar(p, '\n'); |
|
|
switch (cmd) { |
switch (cmd) { |
case (TEXICMD_DEFMAC): |
case (TEXICMD_DEFMAC): |
case (TEXICMD_DEFMACX): |
case (TEXICMD_DEFMACX): |
teximacroopen(p, "Dv"); |
teximacroopen(p, "Dv"); |
while (parselinearg(p, buf, sz, pos)) |
while (parselinearg(p, pos)) |
/* Spin. */ ; |
/* Spin. */ ; |
teximacroclose(p); |
teximacroclose(p); |
break; |
break; |
Line 448 dodefn(struct texi *p, enum texicmd cmd, |
|
Line 448 dodefn(struct texi *p, enum texicmd cmd, |
|
case (TEXICMD_DEFUN): |
case (TEXICMD_DEFUN): |
case (TEXICMD_DEFUNX): |
case (TEXICMD_DEFUNX): |
teximacroopen(p, "Fo"); |
teximacroopen(p, "Fo"); |
parselinearg(p, buf, sz, pos); |
parselinearg(p, pos); |
teximacroclose(p); |
teximacroclose(p); |
teximacroopen(p, "Fa"); |
teximacroopen(p, "Fa"); |
while (parselinearg(p, buf, sz, pos)) |
while (parselinearg(p, pos)) |
/* Spin. */ ; |
/* Spin. */ ; |
teximacroclose(p); |
teximacroclose(p); |
teximacro(p, "Fc"); |
teximacro(p, "Fc"); |
Line 463 dodefn(struct texi *p, enum texicmd cmd, |
|
Line 463 dodefn(struct texi *p, enum texicmd cmd, |
|
case (TEXICMD_DEFTYPEMETHOD): |
case (TEXICMD_DEFTYPEMETHOD): |
case (TEXICMD_DEFTYPEMETHODX): |
case (TEXICMD_DEFTYPEMETHODX): |
teximacroopen(p, "Ft"); |
teximacroopen(p, "Ft"); |
parselinearg(p, buf, sz, pos); |
parselinearg(p, pos); |
teximacroclose(p); |
teximacroclose(p); |
teximacroopen(p, "Fo"); |
teximacroopen(p, "Fo"); |
parselinearg(p, buf, sz, pos); |
parselinearg(p, pos); |
teximacroclose(p); |
teximacroclose(p); |
teximacroopen(p, "Fa"); |
teximacroopen(p, "Fa"); |
while (parselinearg(p, buf, sz, pos)) |
while (parselinearg(p, pos)) |
/* Spin. */ ; |
/* Spin. */ ; |
teximacroclose(p); |
teximacroclose(p); |
teximacro(p, "Fc"); |
teximacro(p, "Fc"); |
Line 481 dodefn(struct texi *p, enum texicmd cmd, |
|
Line 481 dodefn(struct texi *p, enum texicmd cmd, |
|
case (TEXICMD_DEFTYPEVR): |
case (TEXICMD_DEFTYPEVR): |
case (TEXICMD_DEFTYPEVRX): |
case (TEXICMD_DEFTYPEVRX): |
teximacroopen(p, "Vt"); |
teximacroopen(p, "Vt"); |
while (parselinearg(p, buf, sz, pos)) |
while (parselinearg(p, pos)) |
/* Spin. */ ; |
/* Spin. */ ; |
teximacroclose(p); |
teximacroclose(p); |
break; |
break; |
Line 490 dodefn(struct texi *p, enum texicmd cmd, |
|
Line 490 dodefn(struct texi *p, enum texicmd cmd, |
|
case (TEXICMD_DEFVR): |
case (TEXICMD_DEFVR): |
case (TEXICMD_DEFVRX): |
case (TEXICMD_DEFVRX): |
teximacroopen(p, "Va"); |
teximacroopen(p, "Va"); |
while (parselinearg(p, buf, sz, pos)) |
while (parselinearg(p, pos)) |
/* Spin. */ ; |
/* Spin. */ ; |
teximacroclose(p); |
teximacroclose(p); |
break; |
break; |
Line 500 dodefn(struct texi *p, enum texicmd cmd, |
|
Line 500 dodefn(struct texi *p, enum texicmd cmd, |
|
|
|
texivspace(p); |
texivspace(p); |
if (NULL != blk) |
if (NULL != blk) |
parseto(p, buf, sz, pos, blk); |
parseto(p, pos, blk); |
} |
} |
|
|
static void |
static void |
domacro(struct texi *p, enum texicmd cmd, |
domacro(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
size_t start, end, endtoksz, len; |
size_t start, end, endtoksz, len; |
struct teximacro m; |
struct teximacro m; |
Line 513 domacro(struct texi *p, enum texicmd cmd, |
|
Line 512 domacro(struct texi *p, enum texicmd cmd, |
|
|
|
memset(&m, 0, sizeof(struct teximacro)); |
memset(&m, 0, sizeof(struct teximacro)); |
|
|
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
|
|
for (start = end = *pos; end < sz; end++) |
for (start = end = *pos; end < BUFSZ(p); end++) |
if (ismspace(buf[end]) || '{' == buf[end]) |
if (ismspace(BUF(p)[end]) || '{' == BUF(p)[end]) |
break; |
break; |
|
|
if (start == end) |
if (start == end) |
texierr(p, "zero-length macro name"); |
texierr(p, "zero-length macro name"); |
|
|
advanceto(p, buf, pos, end); |
advanceto(p, pos, end); |
|
|
m.key = malloc(end - start + 1); |
m.key = malloc(end - start + 1); |
if (NULL == m.key) |
if (NULL == m.key) |
texiabort(p, NULL); |
texiabort(p, NULL); |
memcpy(m.key, &buf[start], end - start); |
memcpy(m.key, &BUF(p)[start], end - start); |
m.key[end - start] = '\0'; |
m.key[end - start] = '\0'; |
|
|
m.args = argparse(p, buf, sz, pos, &m.argsz, 0); |
m.args = argparse(p, pos, &m.argsz, 0); |
advanceeoln(p, buf, sz, pos, 0); |
|
|
|
|
/* Note: we advance to the beginning of the macro. */ |
|
advanceeoln(p, pos, 1); |
|
|
|
/* |
|
* According to the Texinfo manual, the macro ends on the |
|
* newline subsequent the @end macro. |
|
* That's COMPLETELY FUCKING WRONG. |
|
* It ends inclusive the newline, which is why so many macros |
|
* say things like @r{hello}@c, where the subsequent @c swallows |
|
* the newline. |
|
* However, it does swallow the leading newline, so look for the |
|
* @end macro without the leading newline else we might look |
|
* past empty macros. |
|
*/ |
start = *pos; |
start = *pos; |
endtok = "\n@end macro\n"; |
endtok = "@end macro\n"; |
endtoksz = strlen(endtok); |
endtoksz = strlen(endtok); |
blk = memmem(&buf[start], sz, endtok, endtoksz); |
blk = memmem(&BUF(p)[start], BUFSZ(p) - start, endtok, endtoksz); |
if (NULL == blk) |
if (NULL == blk) |
texierr(p, "unterminated macro body"); |
texierr(p, "unterminated macro body"); |
while (&buf[*pos] != blk) |
/* Roll us back one character. */ |
advance(p, buf, pos); |
while (&BUF(p)[*pos] != blk) |
assert('\n' == buf[*pos]); |
advance(p, pos); |
advance(p, buf, pos); |
assert('@' == BUF(p)[*pos]); |
len = blk - &buf[start]; |
if ('\n' != BUF(p)[*pos - 1]) |
|
texierr(p, "cannot handle @end macro in-line"); |
|
|
|
len = blk - &BUF(p)[start]; |
m.value = malloc(len + 1); |
m.value = malloc(len + 1); |
if (NULL == m.value) |
if (NULL == m.value) |
texiabort(p, NULL); |
texiabort(p, NULL); |
memcpy(m.value, &buf[start], len); |
memcpy(m.value, &BUF(p)[start], len); |
m.value[len] = '\0'; |
m.value[len] = '\0'; |
|
|
p->macros = realloc |
p->macros = realloc |
Line 559 domacro(struct texi *p, enum texicmd cmd, |
|
Line 574 domacro(struct texi *p, enum texicmd cmd, |
|
texiabort(p, NULL); |
texiabort(p, NULL); |
|
|
p->macros[p->macrosz++] = m; |
p->macros[p->macrosz++] = m; |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
} |
} |
|
|
static void |
static void |
doignblock(struct texi *p, enum texicmd cmd, |
doignblock(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
char end[32]; |
char end[32], start[32]; |
const char *term; |
const char *endt, *startt; |
size_t endsz, endpos; |
size_t esz, ssz, newpos, stack; |
|
|
/* |
/* |
* We want to completely ignore everything in these blocks, so |
* FIXME: this is cheating. |
* simply jump to the @end block. |
* These tokens are supposed to begin on a newline. |
|
* However, if we do that, then we would need to check within |
|
* the loop for trailer (or leading, as the case may be) |
|
* newline, and that's just a bit too complicated right now. |
|
* This is becasue |
|
* @ifset BAR |
|
* @ifset FOO |
|
* @end ifset |
|
* @end ifset |
|
* won't work right now: we'd read after the first "@end ifset" |
|
* to the next line, then look for the next line after that. |
*/ |
*/ |
endsz = snprintf(end, sizeof(end), |
ssz = snprintf(start, sizeof(start), |
"\n@end %s\n", texitoks[cmd].tok); |
"@%s", texitoks[cmd].tok); |
assert(endsz < sizeof(end)); |
assert(ssz < sizeof(start)); |
|
esz = snprintf(end, sizeof(end), |
|
"@end %s\n", texitoks[cmd].tok); |
|
assert(esz < sizeof(end)); |
|
stack = 1; |
|
|
/* |
/* |
* Look up where our end token occurs. |
* Here we look for the end token "end" somewhere in the file in |
* Set our end position based on the relative offset of that |
* front of us. |
* from our current position, or the EOF if we don't have a |
* It's not that easy, of course: if we have a nested block, |
* proper ending point. |
* then there'll be an "end" token of the same kind between us. |
|
* Thus, we keep track of scopes for matching "end" blocks. |
*/ |
*/ |
term = memmem(&buf[*pos], sz, end, endsz); |
while (stack > 0 && *pos < BUFSZ(p)) { |
endpos = NULL == term ? sz : |
if (stack > 10) |
*pos + (size_t)(term - &buf[*pos]); |
abort(); |
assert(endpos <= sz); |
endt = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, end, esz); |
while (*pos < endpos) |
startt = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, start, ssz); |
advance(p, buf, pos); |
if (NULL == endt) { |
|
texiwarn(p, "unterminated \"%s\" " |
|
"block", texitoks[cmd].tok); |
|
*pos = BUFSZ(p); |
|
break; |
|
} |
|
|
/* Only do this if we're not already at the end. */ |
newpos = *pos; |
if (endpos < sz) |
if (NULL == startt || startt > endt) { |
advanceto(p, buf, pos, endpos + endsz); |
newpos += esz + (size_t)(endt - &BUF(p)[*pos]); |
|
stack--; |
|
} else { |
|
newpos += ssz + (size_t)(startt - &BUF(p)[*pos]); |
|
stack++; |
|
} |
|
|
|
assert(newpos <= BUFSZ(p)); |
|
while (*pos < newpos) |
|
advance(p, pos); |
|
} |
} |
} |
|
|
static void |
static void |
doblock(struct texi *p, enum texicmd cmd, |
doblock(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
parseto(p, buf, sz, pos, texitoks[cmd].tok); |
parseto(p, pos, texitoks[cmd].tok); |
} |
} |
|
|
static void |
static void |
doinline(struct texi *p, enum texicmd cmd, |
doinline(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
const char *macro = NULL; |
const char *macro = NULL; |
|
|
Line 648 doinline(struct texi *p, enum texicmd cmd, |
|
Line 690 doinline(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
if (NULL == macro || p->literal || TEXILIST_TABLE == p->list) { |
if (NULL == macro || p->literal || TEXILIST_TABLE == p->list) { |
parsebracket(p, buf, sz, pos); |
parsebracket(p, pos); |
return; |
return; |
} |
} |
|
|
teximacroopen(p, macro); |
teximacroopen(p, macro); |
p->seenws = 0; |
p->seenws = 0; |
parsebracket(p, buf, sz, pos); |
parsebracket(p, pos); |
texipunctuate(p, buf, sz, pos); |
texipunctuate(p, pos); |
teximacroclose(p); |
teximacroclose(p); |
} |
} |
|
|
static void |
static void |
doverb(struct texi *p, enum texicmd cmd, |
doverb(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
char delim; |
char delim; |
size_t start; |
size_t start; |
|
|
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
if (*pos == sz || '{' != buf[*pos]) |
if (*pos == BUFSZ(p) || '{' != BUF(p)[*pos]) |
return; |
return; |
advance(p, buf, pos); |
advance(p, pos); |
if (*pos == sz) |
if (*pos == BUFSZ(p)) |
return; |
return; |
|
|
delim = buf[*pos]; |
delim = BUF(p)[*pos]; |
advance(p, buf, pos); |
advance(p, pos); |
/* Make sure we flush out our initial whitespace... */ |
/* Make sure we flush out our initial whitespace... */ |
if (p->seenws && p->outcol && 0 == p->literal) |
if (p->seenws && p->outcol && 0 == p->literal) |
texiputchar(p, ' '); |
texiputchar(p, ' '); |
p->seenws = 0; |
p->seenws = 0; |
start = *pos; |
start = *pos; |
/* Read until we see the delimiter then end-brace. */ |
/* Read until we see the delimiter then end-brace. */ |
while (*pos < sz - 1) { |
while (*pos < BUFSZ(p) - 1) { |
if (buf[*pos] == delim && buf[*pos + 1] == '}') |
if (BUF(p)[*pos] == delim && BUF(p)[*pos + 1] == '}') |
break; |
break; |
advance(p, buf, pos); |
advance(p, pos); |
} |
} |
if (*pos == sz - 1) |
if (*pos == BUFSZ(p) - 1) |
return; |
return; |
texiputbuf(p, buf, start, *pos); |
texiputbuf(p, start, *pos); |
|
|
/* Make sure we read after the end-brace. */ |
/* Make sure we read after the end-brace. */ |
assert(delim == buf[*pos]); |
assert(delim == BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
assert('}' == buf[*pos]); |
assert('}' == BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
} |
} |
|
|
static void |
static void |
doverbatim(struct texi *p, enum texicmd cmd, |
doverbatim(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
const char *end, *term; |
const char *end, *term; |
size_t endsz, endpos; |
size_t endsz, endpos; |
|
|
advanceeoln(p, buf, sz, pos, 1); |
/* We read from the @verbatim\n newline inclusive! */ |
|
|
/* We end at exactly this token. */ |
|
end = "\n@end verbatim\n"; |
end = "\n@end verbatim\n"; |
endsz = strlen(end); |
endsz = strlen(end); |
|
advanceeoln(p, pos, 0); |
|
if (*pos == BUFSZ(p)) { |
|
texiwarn(p, "unexpected end of file"); |
|
return; |
|
} |
|
|
/* |
term = memmem(&BUF(p)[*pos], BUFSZ(p) - *pos, end, endsz); |
* Look up where our end token occurs. |
if (NULL == term) { |
* Set our end position based on the relative offset of that |
texiwarn(p, "unterminated verbatim block"); |
* from our current position. |
endpos = BUFSZ(p); |
*/ |
} else |
term = memmem(&buf[*pos], sz, end, endsz); |
endpos = *pos + (size_t)(term - &BUF(p)[*pos]); |
endpos = NULL == term ? sz : |
|
*pos + (size_t)(term - &buf[*pos]); |
|
|
|
|
assert(endpos <= BUFSZ(p)); |
|
assert('\n' == BUF(p)[*pos]); |
|
advance(p, pos); |
teximacro(p, "Bd -literal -offset indent"); |
teximacro(p, "Bd -literal -offset indent"); |
assert(endpos <= sz); |
|
while (*pos < endpos) { |
while (*pos < endpos) { |
texiputchar(p, buf[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
} |
} |
teximacro(p, "Ed"); |
teximacro(p, "Ed"); |
advanceto(p, buf, pos, endpos + endsz); |
if (*pos < BUFSZ(p)) |
|
advanceto(p, pos, endpos + endsz); |
} |
} |
|
|
static void |
static void |
doverbinclude(struct texi *p, enum texicmd cmd, |
doverbinclude(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
char fname[PATH_MAX], path[PATH_MAX]; |
char fname[PATH_MAX], path[PATH_MAX]; |
int rc; |
int rc; |
Line 740 doverbinclude(struct texi *p, enum texicmd cmd, |
|
Line 783 doverbinclude(struct texi *p, enum texicmd cmd, |
|
const char *v; |
const char *v; |
enum texicmd type; |
enum texicmd type; |
|
|
while (*pos < sz && ' ' == buf[*pos]) |
while (*pos < BUFSZ(p) && ' ' == BUF(p)[*pos]) |
advance(p, buf, pos); |
advance(p, pos); |
|
|
for (i = 0; *pos < sz && '\n' != buf[*pos]; ) { |
for (i = 0; *pos < BUFSZ(p) && '\n' != BUF(p)[*pos]; ) { |
if (i == sizeof(fname) - 1) |
if (i == sizeof(fname) - 1) |
break; |
break; |
if ('@' != buf[*pos]) { |
if ('@' != BUF(p)[*pos]) { |
fname[i++] = buf[*pos]; |
fname[i++] = BUF(p)[*pos]; |
advance(p, buf, pos); |
advance(p, pos); |
continue; |
continue; |
} |
} |
type = texicmd(p, buf, *pos, sz, &end, NULL); |
type = texicmd(p, *pos, &end, NULL); |
advanceto(p, buf, pos, end); |
advanceto(p, pos, end); |
if (TEXICMD_VALUE != type) |
if (TEXICMD_VALUE != type) |
texierr(p, "unknown verbatiminclude command"); |
texierr(p, "unknown verbatiminclude command"); |
v = valueblookup(p, buf, sz, pos); |
v = valueblookup(p, pos); |
if (NULL == v) |
if (NULL == v) |
continue; |
continue; |
while ('\0' != *v) { |
while ('\0' != *v) { |
Line 769 doverbinclude(struct texi *p, enum texicmd cmd, |
|
Line 812 doverbinclude(struct texi *p, enum texicmd cmd, |
|
|
|
if (i == 0) |
if (i == 0) |
texierr(p, "path too short"); |
texierr(p, "path too short"); |
else if ('\n' != buf[*pos]) |
else if ('\n' != BUF(p)[*pos]) |
texierr(p, "path too long"); |
texierr(p, "path too long"); |
else if ('/' == fname[0]) |
else if ('/' == fname[0]) |
texierr(p, "no absolute paths"); |
texierr(p, "no absolute paths"); |
Line 789 doverbinclude(struct texi *p, enum texicmd cmd, |
|
Line 832 doverbinclude(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
static void |
static void |
doinclude(struct texi *p, enum texicmd cmd, |
doinclude(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
char fname[PATH_MAX], path[PATH_MAX]; |
char fname[PATH_MAX], path[PATH_MAX]; |
size_t i, end; |
size_t i, end; |
Line 798 doinclude(struct texi *p, enum texicmd cmd, |
|
Line 840 doinclude(struct texi *p, enum texicmd cmd, |
|
const char *v; |
const char *v; |
enum texicmd type; |
enum texicmd type; |
|
|
while (*pos < sz && ' ' == buf[*pos]) |
while (*pos < BUFSZ(p) && ' ' == BUF(p)[*pos]) |
advance(p, buf, pos); |
advance(p, pos); |
|
|
/* Read in the filename. */ |
/* Read in the filename. */ |
for (i = 0; *pos < sz && '\n' != buf[*pos]; ) { |
for (i = 0; *pos < BUFSZ(p) && '\n' != BUF(p)[*pos]; ) { |
if (i == sizeof(fname) - 1) |
if (i == sizeof(fname) - 1) |
break; |
break; |
if ('@' != buf[*pos]) { |
if ('@' != BUF(p)[*pos]) { |
fname[i++] = buf[*pos]; |
fname[i++] = BUF(p)[*pos]; |
advance(p, buf, pos); |
advance(p, pos); |
continue; |
continue; |
} |
} |
type = texicmd(p, buf, *pos, sz, &end, NULL); |
type = texicmd(p, *pos, &end, NULL); |
advanceto(p, buf, pos, end); |
advanceto(p, pos, end); |
if (TEXICMD_VALUE != type) |
if (TEXICMD_VALUE != type) |
texierr(p, "unknown include command"); |
texierr(p, "unknown include command"); |
v = valueblookup(p, buf, sz, pos); |
v = valueblookup(p, pos); |
if (NULL == v) |
if (NULL == v) |
continue; |
continue; |
while ('\0' != *v) { |
while ('\0' != *v) { |
Line 828 doinclude(struct texi *p, enum texicmd cmd, |
|
Line 870 doinclude(struct texi *p, enum texicmd cmd, |
|
|
|
if (i == 0) |
if (i == 0) |
texierr(p, "path too short"); |
texierr(p, "path too short"); |
else if ('\n' != buf[*pos]) |
else if ('\n' != BUF(p)[*pos]) |
texierr(p, "path too long"); |
texierr(p, "path too long"); |
else if ('/' == fname[0]) |
else if ('/' == fname[0]) |
texierr(p, "no absolute paths"); |
texierr(p, "no absolute paths"); |
Line 855 doinclude(struct texi *p, enum texicmd cmd, |
|
Line 897 doinclude(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
static void |
static void |
dobracket(struct texi *p, enum texicmd cmd, |
dobracket(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
parsebracket(p, buf, sz, pos); |
parsebracket(p, pos); |
} |
} |
|
|
static void |
static void |
dodisplay(struct texi *p, enum texicmd cmd, |
dodisplay(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
switch (cmd) { |
switch (cmd) { |
Line 879 dodisplay(struct texi *p, enum texicmd cmd, |
|
Line 919 dodisplay(struct texi *p, enum texicmd cmd, |
|
|
|
p->seenvs = 1; |
p->seenvs = 1; |
/* FIXME: ignore and parseeoln. */ |
/* FIXME: ignore and parseeoln. */ |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
parseto(p, buf, sz, pos, texitoks[cmd].tok); |
parseto(p, pos, texitoks[cmd].tok); |
teximacro(p, "Ed"); |
teximacro(p, "Ed"); |
} |
} |
|
|
static void |
static void |
doexample(struct texi *p, enum texicmd cmd, |
doexample(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
teximacro(p, "Bd -literal -offset indent"); |
teximacro(p, "Bd -literal -offset indent"); |
/* FIXME: ignore and parseeoln. */ |
/* FIXME: ignore and parseeoln. */ |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
p->literal++; |
p->literal++; |
parseto(p, buf, sz, pos, texitoks[cmd].tok); |
parseto(p, pos, texitoks[cmd].tok); |
p->literal--; |
p->literal--; |
teximacro(p, "Ed"); |
teximacro(p, "Ed"); |
} |
} |
|
|
static void |
static void |
dobye(struct texi *p, enum texicmd cmd, |
dobye(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
texiexit(p); |
texiexit(p); |
Line 908 dobye(struct texi *p, enum texicmd cmd, |
|
Line 946 dobye(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
static void |
static void |
dotitle(struct texi *p, enum texicmd cmd, |
dotitle(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
size_t start, end; |
size_t start, end; |
|
|
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
start = end = *pos; |
start = end = *pos; |
while (end < sz && '\n' != buf[end]) |
while (end < BUFSZ(p) && '\n' != BUF(p)[end]) |
end++; |
end++; |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
free(p->subtitle); |
free(p->subtitle); |
p->subtitle = malloc(end - start + 1); |
p->subtitle = malloc(end - start + 1); |
if (NULL == p->subtitle) |
if (NULL == p->subtitle) |
texiabort(p, NULL); |
texiabort(p, NULL); |
memcpy(p->subtitle, &buf[start], end - start); |
memcpy(p->subtitle, &BUF(p)[start], end - start); |
p->subtitle[end - start] = '\0'; |
p->subtitle[end - start] = '\0'; |
} |
} |
|
|
static void |
static void |
doaccent(struct texi *p, enum texicmd cmd, |
doaccent(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
int brace = 0; |
int brace = 0; |
|
|
if (*pos == sz) { |
if (*pos == BUFSZ(p)) { |
texiwarn(p, "truncated: @%s", texitoks[cmd].tok); |
texiwarn(p, "truncated: @%s", texitoks[cmd].tok); |
return; |
return; |
} |
} |
Line 951 doaccent(struct texi *p, enum texicmd cmd, |
|
Line 987 doaccent(struct texi *p, enum texicmd cmd, |
|
* the critical one. |
* the critical one. |
* Otherwise, space can sit between us and our argument. |
* Otherwise, space can sit between us and our argument. |
*/ |
*/ |
if ('{' == buf[*pos]) { |
if ('{' == BUF(p)[*pos]) { |
brace = 1; |
brace = 1; |
advance(p, buf, pos); |
advance(p, pos); |
} else if (isalpha(texitoks[cmd].tok[0])) |
} else if (isalpha((unsigned char)texitoks[cmd].tok[0])) |
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
|
|
if (*pos == sz) { |
if (*pos == BUFSZ(p)) { |
texiwarn(p, "truncated: @%s", texitoks[cmd].tok); |
texiwarn(p, "truncated: @%s", texitoks[cmd].tok); |
return; |
return; |
} |
} |
|
|
switch (cmd) { |
switch (cmd) { |
case (TEXICMD_ACUTE): |
case (TEXICMD_ACUTE): |
switch (buf[*pos]) { |
switch (BUF(p)[*pos]) { |
case ('a'): case ('A'): |
case ('a'): case ('A'): |
case ('e'): case ('E'): |
case ('e'): case ('E'): |
case ('i'): case ('I'): |
case ('i'): case ('I'): |
Line 977 doaccent(struct texi *p, enum texicmd cmd, |
|
Line 1013 doaccent(struct texi *p, enum texicmd cmd, |
|
texiwarn(p, "ignoring accent"); |
texiwarn(p, "ignoring accent"); |
break; |
break; |
} |
} |
texiputchar(p, buf[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
break; |
break; |
case (TEXICMD_CEDILLA): |
case (TEXICMD_CEDILLA): |
if ('c' == buf[*pos] || 'C' == buf[*pos]) |
if ('c' == BUF(p)[*pos] || 'C' == BUF(p)[*pos]) |
texiputchars(p, "\\(,"); |
texiputchars(p, "\\(,"); |
else |
else |
texiwarn(p, "ignoring accent"); |
texiwarn(p, "ignoring accent"); |
texiputchar(p, buf[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
break; |
break; |
case (TEXICMD_CIRCUMFLEX): |
case (TEXICMD_CIRCUMFLEX): |
switch (buf[*pos]) { |
switch (BUF(p)[*pos]) { |
case ('a'): case ('A'): |
case ('a'): case ('A'): |
case ('e'): case ('E'): |
case ('e'): case ('E'): |
case ('i'): case ('I'): |
case ('i'): case ('I'): |
Line 1001 doaccent(struct texi *p, enum texicmd cmd, |
|
Line 1037 doaccent(struct texi *p, enum texicmd cmd, |
|
texiwarn(p, "ignoring accent"); |
texiwarn(p, "ignoring accent"); |
break; |
break; |
} |
} |
texiputchar(p, buf[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
break; |
break; |
case (TEXICMD_DOTLESS): |
case (TEXICMD_DOTLESS): |
if ('i' == buf[*pos] || 'j' == buf[*pos]) |
if ('i' == BUF(p)[*pos] || 'j' == BUF(p)[*pos]) |
texiputchars(p, "\\(."); |
texiputchars(p, "\\(."); |
else |
else |
texiwarn(p, "ignoring accent"); |
texiwarn(p, "ignoring accent"); |
texiputchar(p, buf[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
break; |
break; |
case (TEXICMD_GRAVE): |
case (TEXICMD_GRAVE): |
switch (buf[*pos]) { |
switch (BUF(p)[*pos]) { |
case ('a'): case ('A'): |
case ('a'): case ('A'): |
case ('e'): case ('E'): |
case ('e'): case ('E'): |
case ('i'): case ('I'): |
case ('i'): case ('I'): |
Line 1025 doaccent(struct texi *p, enum texicmd cmd, |
|
Line 1061 doaccent(struct texi *p, enum texicmd cmd, |
|
texiwarn(p, "ignoring accent"); |
texiwarn(p, "ignoring accent"); |
break; |
break; |
} |
} |
texiputchar(p, buf[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
break; |
break; |
case (TEXICMD_TILDE): |
case (TEXICMD_TILDE): |
switch (buf[*pos]) { |
switch (BUF(p)[*pos]) { |
case ('a'): case ('A'): |
case ('a'): case ('A'): |
case ('n'): case ('N'): |
case ('n'): case ('N'): |
case ('o'): case ('O'): |
case ('o'): case ('O'): |
Line 1039 doaccent(struct texi *p, enum texicmd cmd, |
|
Line 1075 doaccent(struct texi *p, enum texicmd cmd, |
|
texiwarn(p, "ignoring accent"); |
texiwarn(p, "ignoring accent"); |
break; |
break; |
} |
} |
texiputchar(p, buf[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
break; |
break; |
case (TEXICMD_UMLAUT): |
case (TEXICMD_UMLAUT): |
switch (buf[*pos]) { |
switch (BUF(p)[*pos]) { |
case ('a'): case ('A'): |
case ('a'): case ('A'): |
case ('e'): case ('E'): |
case ('e'): case ('E'): |
case ('i'): case ('I'): |
case ('i'): case ('I'): |
Line 1056 doaccent(struct texi *p, enum texicmd cmd, |
|
Line 1092 doaccent(struct texi *p, enum texicmd cmd, |
|
texiwarn(p, "ignoring accent"); |
texiwarn(p, "ignoring accent"); |
break; |
break; |
} |
} |
texiputchar(p, buf[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
break; |
break; |
default: |
default: |
texiputchar(p, buf[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
break; |
break; |
} |
} |
|
|
if (brace) { |
if (brace) { |
while (*pos < sz && '}' != buf[*pos]) { |
while (*pos < BUFSZ(p) && '}' != BUF(p)[*pos]) { |
texiputchar(p, buf[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, buf, pos); |
advance(p, pos); |
} |
} |
if (*pos < sz) |
if (*pos < BUFSZ(p)) |
advance(p, buf, pos); |
advance(p, pos); |
} |
} |
|
|
switch (cmd) { |
switch (cmd) { |
Line 1087 doaccent(struct texi *p, enum texicmd cmd, |
|
Line 1123 doaccent(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
static void |
static void |
dosymbol(struct texi *p, enum texicmd cmd, |
dosymbol(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
/* Remember to pad us. */ |
/* Remember to pad us. */ |
Line 1277 dosymbol(struct texi *p, enum texicmd cmd, |
|
Line 1312 dosymbol(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
/* Alphabetic commands have braces we ignore. */ |
/* Alphabetic commands have braces we ignore. */ |
if (isalpha(texitoks[cmd].tok[0])) |
if (isalpha((unsigned char)texitoks[cmd].tok[0])) |
doignbracket(p, cmd, buf, sz, pos); |
doignbracket(p, cmd, pos); |
} |
} |
|
|
static void |
static void |
doquotation(struct texi *p, enum texicmd cmd, |
doquotation(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
teximacro(p, "Qo"); |
teximacro(p, "Qo"); |
parseto(p, buf, sz, pos, "quotation"); |
parseto(p, pos, "quotation"); |
teximacro(p, "Qc"); |
teximacro(p, "Qc"); |
} |
} |
|
|
static void |
static void |
domath(struct texi *p, enum texicmd cmd, |
domath(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
size_t nest, start; |
size_t nest, start; |
|
|
Line 1303 domath(struct texi *p, enum texicmd cmd, |
|
Line 1336 domath(struct texi *p, enum texicmd cmd, |
|
* terms of @-commands. |
* terms of @-commands. |
* This departs from GNU's rules, but whatever. |
* This departs from GNU's rules, but whatever. |
*/ |
*/ |
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
if (*pos == sz || '{' != buf[*pos]) |
if (*pos == BUFSZ(p) || '{' != BUF(p)[*pos]) |
return; |
return; |
advance(p, buf, pos); |
advance(p, pos); |
if (p->seenws && p->outcol && 0 == p->literal) |
if (p->seenws && p->outcol && 0 == p->literal) |
texiputchar(p, ' '); |
texiputchar(p, ' '); |
p->seenws = 0; |
p->seenws = 0; |
for (nest = 1, start = *pos; *pos < sz && nest > 0; ) { |
for (nest = 1, start = *pos; *pos < BUFSZ(p) && nest > 0; ) { |
if ('{' == buf[*pos]) |
if ('{' == BUF(p)[*pos]) |
nest++; |
nest++; |
else if ('}' == buf[*pos]) |
else if ('}' == BUF(p)[*pos]) |
if (0 == --nest) |
if (0 == --nest) |
continue; |
continue; |
advance(p, buf, pos); |
advance(p, pos); |
} |
} |
if (*pos == sz) |
if (*pos == BUFSZ(p)) |
return; |
return; |
assert('}' == buf[*pos]); |
assert('}' == BUF(p)[*pos]); |
texiputbuf(p, buf, start, *pos); |
texiputbuf(p, start, *pos); |
advance(p, buf, pos); |
advance(p, pos); |
} |
} |
|
|
static void |
static void |
dovalue(struct texi *p, enum texicmd cmd, |
dovalue(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
size_t start, end, i; |
size_t start, end; |
char *key, *val; |
char *key, *val; |
const char *cp; |
const char *cp; |
|
|
if (TEXICMD_SET == cmd) { |
if (TEXICMD_SET == cmd) { |
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
for (start = end = *pos; end < sz; end++) |
for (start = end = *pos; end < BUFSZ(p); end++) |
if (ismspace(buf[end])) |
if (ismspace(BUF(p)[end])) |
break; |
break; |
/* We don't allow empty keys. */ |
/* We don't allow empty keys. */ |
if (start == end) |
if (start == end) |
return; |
return; |
advanceto(p, buf, pos, end); |
advanceto(p, pos, end); |
|
|
key = malloc(end - start + 1); |
key = malloc(end - start + 1); |
if (NULL == key) |
if (NULL == key) |
texiabort(p, NULL); |
texiabort(p, NULL); |
memcpy(key, &buf[start], end - start); |
memcpy(key, &BUF(p)[start], end - start); |
key[end - start] = '\0'; |
key[end - start] = '\0'; |
|
|
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
for (start = end = *pos; end < sz; end++) |
for (start = end = *pos; end < BUFSZ(p); end++) |
if ('\n' == buf[end]) |
if ('\n' == BUF(p)[end]) |
break; |
break; |
/* We do allow empty values. */ |
/* We do allow empty values. */ |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
|
|
val = malloc(end - start + 1); |
val = malloc(end - start + 1); |
if (NULL == val) |
if (NULL == val) |
texiabort(p, NULL); |
texiabort(p, NULL); |
memcpy(val, &buf[start], end - start); |
memcpy(val, &BUF(p)[start], end - start); |
val[end - start] = '\0'; |
val[end - start] = '\0'; |
valueadd(p, key, val); |
valueadd(p, key, val); |
} else if (TEXICMD_VALUE == cmd) { |
} else if (TEXICMD_VALUE == cmd) { |
if (p->seenws) |
if (p->seenws) |
texiputchar(p, ' '); |
texiputchar(p, ' '); |
p->seenws = 0; |
p->seenws = 0; |
if (NULL != (cp = valueblookup(p, buf, sz, pos))) { |
if (NULL != (cp = valueblookup(p, pos))) |
for (i = 0; i < p->valstackpos; i++) |
texisplice(p, cp, strlen(cp), pos); |
if (cp == p->valstack[i]) |
else |
break; |
|
if (i < p->valstackpos) |
|
texierr(p, "recursive value"); |
|
if (64 == p->valstackpos) |
|
texierr(p, "too many nested values"); |
|
p->valstack[p->valstackpos++] = cp; |
|
parsemembuf(p, cp, strlen(cp)); |
|
p->valstackpos--; |
|
} else |
|
texiputchars(p, "{No value}"); |
texiputchars(p, "{No value}"); |
} else if (TEXICMD_IFCLEAR == cmd) { |
} else if (TEXICMD_IFCLEAR == cmd) { |
if (NULL != valuellookup(p, buf, sz, pos)) |
if (NULL != valuellookup(p, pos)) |
doignblock(p, cmd, buf, sz, pos); |
doignblock(p, cmd, pos); |
else |
else |
parseto(p, buf, sz, pos, texitoks[cmd].tok); |
parseto(p, pos, texitoks[cmd].tok); |
} else if (TEXICMD_IFSET == cmd) { |
} else if (TEXICMD_IFSET == cmd) { |
if (NULL == valuellookup(p, buf, sz, pos)) |
if (NULL == valuellookup(p, pos)) |
doignblock(p, cmd, buf, sz, pos); |
doignblock(p, cmd, pos); |
else |
else |
parseto(p, buf, sz, pos, texitoks[cmd].tok); |
parseto(p, pos, texitoks[cmd].tok); |
} else if (TEXICMD_CLEAR == cmd) |
} else if (TEXICMD_CLEAR == cmd) |
valuelclear(p, buf, sz, pos); |
valuelclear(p, pos); |
} |
} |
|
|
static void |
static void |
dolink(struct texi *p, enum texicmd cmd, |
dolink(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
int c; |
int c; |
|
|
Line 1427 dolink(struct texi *p, enum texicmd cmd, |
|
Line 1449 dolink(struct texi *p, enum texicmd cmd, |
|
abort(); |
abort(); |
} |
} |
|
|
c = parsearg(p, buf, sz, pos, 0); |
c = parsearg(p, pos, 0); |
p->ign++; |
p->ign++; |
while (c > 0) |
while (c > 0) |
c = parsearg(p, buf, sz, pos, 1); |
c = parsearg(p, pos, 1); |
p->ign--; |
p->ign--; |
|
|
texipunctuate(p, buf, sz, pos); |
texipunctuate(p, pos); |
teximacroclose(p); |
teximacroclose(p); |
} |
} |
|
|
static void |
static void |
doignargn(struct texi *p, enum texicmd cmd, |
doignargn(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
int c; |
int c; |
|
|
c = parsearg(p, buf, sz, pos, 0); |
c = parsearg(p, pos, 0); |
p->ign++; |
p->ign++; |
while (c > 0) |
while (c > 0) |
c = parsearg(p, buf, sz, pos, 1); |
c = parsearg(p, pos, 1); |
p->ign--; |
p->ign--; |
} |
} |
|
|
Line 1471 sectioner(struct texi *p, int sec) |
|
Line 1492 sectioner(struct texi *p, int sec) |
|
} |
} |
|
|
static void |
static void |
dosubsubsection(struct texi *p, enum texicmd cmd, |
dosubsubsection(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
int sec; |
int sec; |
|
|
Line 1481 dosubsubsection(struct texi *p, enum texicmd cmd, |
|
Line 1501 dosubsubsection(struct texi *p, enum texicmd cmd, |
|
/* We don't have a subsubsubsection, so make one up. */ |
/* We don't have a subsubsubsection, so make one up. */ |
texivspace(p); |
texivspace(p); |
teximacroopen(p, sects[sec]); |
teximacroopen(p, sects[sec]); |
parseeoln(p, buf, sz, pos); |
parseeoln(p, pos); |
teximacroclose(p); |
teximacroclose(p); |
texivspace(p); |
texivspace(p); |
} |
} |
|
|
static void |
static void |
dosubsection(struct texi *p, enum texicmd cmd, |
dosubsection(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
int sec; |
int sec; |
|
|
Line 1503 dosubsection(struct texi *p, enum texicmd cmd, |
|
Line 1522 dosubsection(struct texi *p, enum texicmd cmd, |
|
if (sec > 1) |
if (sec > 1) |
texivspace(p); |
texivspace(p); |
teximacroopen(p, sects[sec]); |
teximacroopen(p, sects[sec]); |
parseeoln(p, buf, sz, pos); |
parseeoln(p, pos); |
teximacroclose(p); |
teximacroclose(p); |
if (sec > 1) |
if (sec > 1) |
texivspace(p); |
texivspace(p); |
} |
} |
|
|
static void |
static void |
dosecoffs(struct texi *p, enum texicmd cmd, |
dosecoffs(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
if (TEXICMD_RAISESECTIONS == cmd) |
if (TEXICMD_RAISESECTIONS == cmd) |
Line 1521 dosecoffs(struct texi *p, enum texicmd cmd, |
|
Line 1539 dosecoffs(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
static void |
static void |
dosection(struct texi *p, enum texicmd cmd, |
dosection(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
int sec; |
int sec; |
|
|
Line 1549 dosection(struct texi *p, enum texicmd cmd, |
|
Line 1566 dosection(struct texi *p, enum texicmd cmd, |
|
texierr(p, "\"%s\" in a literal scope!?", sects[sec]); |
texierr(p, "\"%s\" in a literal scope!?", sects[sec]); |
|
|
teximacroopen(p, sects[sec]); |
teximacroopen(p, sects[sec]); |
parseeoln(p, buf, sz, pos); |
parseeoln(p, pos); |
teximacroclose(p); |
teximacroclose(p); |
p->seenvs = 1; |
p->seenvs = 1; |
} |
} |
|
|
static void |
static void |
dosp(struct texi *p, enum texicmd cmd, |
dosp(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
if (p->literal) |
if (p->literal) |
Line 1564 dosp(struct texi *p, enum texicmd cmd, |
|
Line 1580 dosp(struct texi *p, enum texicmd cmd, |
|
else |
else |
texivspace(p); |
texivspace(p); |
/* FIXME: ignore and parseeoln. */ |
/* FIXME: ignore and parseeoln. */ |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
} |
} |
|
|
static void |
static void |
dotop(struct texi *p, enum texicmd cmd, |
dotop(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
const char *cp; |
const char *cp; |
time_t t; |
time_t t; |
char date[32]; |
char date[32]; |
|
|
if (--p->ign) |
if (--p->ign) |
texierr(p, "@top command while ignoring (%d)", p->ign); |
texierr(p, "@top command while ignoring"); |
|
|
/* |
/* |
* Here we print our standard mdoc(7) prologue. |
* Here we print our standard mdoc(7) prologue. |
Line 1593 dotop(struct texi *p, enum texicmd cmd, |
|
Line 1608 dotop(struct texi *p, enum texicmd cmd, |
|
teximacroclose(p); |
teximacroclose(p); |
teximacroopen(p, "Dt"); |
teximacroopen(p, "Dt"); |
for (cp = p->title; '\0' != *cp; cp++) |
for (cp = p->title; '\0' != *cp; cp++) |
texiputchar(p, toupper(*cp)); |
texiputchar(p, toupper((unsigned int)*cp)); |
texiputchars(p, " 7"); |
texiputchars(p, " 7"); |
teximacroclose(p); |
teximacroclose(p); |
teximacro(p, "Os"); |
teximacro(p, "Os"); |
Line 1610 dotop(struct texi *p, enum texicmd cmd, |
|
Line 1625 dotop(struct texi *p, enum texicmd cmd, |
|
texiputchars(p, "Unknown description"); |
texiputchars(p, "Unknown description"); |
teximacroclose(p); |
teximacroclose(p); |
p->seenvs = 1; |
p->seenvs = 1; |
dosection(p, cmd, buf, sz, pos); |
dosection(p, cmd, pos); |
} |
} |
|
|
static void |
static void |
doitem(struct texi *p, enum texicmd cmd, |
doitem(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
/* Multitable is using raw tbl(7). */ |
/* Multitable is using raw tbl(7). */ |
Line 1643 doitem(struct texi *p, enum texicmd cmd, |
|
Line 1657 doitem(struct texi *p, enum texicmd cmd, |
|
|
|
/* Trick so we don't start with Pp. */ |
/* Trick so we don't start with Pp. */ |
p->seenvs = 1; |
p->seenvs = 1; |
parseeoln(p, buf, sz, pos); |
parseeoln(p, pos); |
|
|
if (TEXILIST_ITEM == p->list) |
if (TEXILIST_ITEM == p->list) |
teximacroclose(p); |
teximacroclose(p); |
Line 1652 doitem(struct texi *p, enum texicmd cmd, |
|
Line 1666 doitem(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
static void |
static void |
dotab(struct texi *p, enum texicmd cmd, |
dotab(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
/* This command is only useful in @multitable. */ |
/* This command is only useful in @multitable. */ |
Line 1662 dotab(struct texi *p, enum texicmd cmd, |
|
Line 1675 dotab(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
static void |
static void |
domultitable(struct texi *p, enum texicmd cmd, |
domultitable(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
enum texilist sv = p->list; |
enum texilist sv = p->list; |
int svliteral = p->literal; |
int svliteral = p->literal; |
Line 1680 domultitable(struct texi *p, enum texicmd cmd, |
|
Line 1692 domultitable(struct texi *p, enum texicmd cmd, |
|
columns = 0; |
columns = 0; |
|
|
/* Advance to the first argument... */ |
/* Advance to the first argument... */ |
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
|
|
/* Make sure we don't print anything when scanning. */ |
/* Make sure we don't print anything when scanning. */ |
p->ign++; |
p->ign++; |
if ('@' == buf[*pos]) { |
if ('@' == BUF(p)[*pos]) { |
/* |
/* |
* Look for @columnfractions. |
* Look for @columnfractions. |
* We ignore these, but we do use the number of |
* We ignore these, but we do use the number of |
* arguments to set the number of columns that we'll |
* arguments to set the number of columns that we'll |
* have. |
* have. |
*/ |
*/ |
type = texicmd(p, buf, *pos, sz, &end, NULL); |
type = texicmd(p, *pos, &end, NULL); |
advanceto(p, buf, pos, end); |
advanceto(p, pos, end); |
if (TEXICMD_COLUMNFRACTIONS != type) |
if (TEXICMD_COLUMNFRACTIONS != type) |
texierr(p, "unknown multitable command"); |
texierr(p, "unknown multitable command"); |
while (*pos < sz && '\n' != buf[*pos]) { |
while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) { |
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
while (*pos < sz && ! isws(buf[*pos])) { |
while (*pos < BUFSZ(p) && ! isws(BUF(p)[*pos])) { |
if ('\n' == buf[*pos]) |
if ('\n' == BUF(p)[*pos]) |
break; |
break; |
advance(p, buf, pos); |
advance(p, pos); |
} |
} |
columns++; |
columns++; |
} |
} |
Line 1713 domultitable(struct texi *p, enum texicmd cmd, |
|
Line 1725 domultitable(struct texi *p, enum texicmd cmd, |
|
* tbl(7) figure it out. |
* tbl(7) figure it out. |
* So use this only to count arguments. |
* So use this only to count arguments. |
*/ |
*/ |
while (parselinearg(p, buf, sz, pos) > 0) |
while (parselinearg(p, pos) > 0) |
columns++; |
columns++; |
p->ign--; |
p->ign--; |
|
|
Line 1725 domultitable(struct texi *p, enum texicmd cmd, |
|
Line 1737 domultitable(struct texi *p, enum texicmd cmd, |
|
} |
} |
texiputchars(p, ".\n"); |
texiputchars(p, ".\n"); |
p->outmacro++; |
p->outmacro++; |
parseto(p, buf, sz, pos, texitoks[cmd].tok); |
parseto(p, pos, texitoks[cmd].tok); |
p->outmacro--; |
p->outmacro--; |
teximacro(p, "TE"); |
teximacro(p, "TE"); |
p->literal = svliteral; |
p->literal = svliteral; |
Line 1733 domultitable(struct texi *p, enum texicmd cmd, |
|
Line 1745 domultitable(struct texi *p, enum texicmd cmd, |
|
} |
} |
|
|
static void |
static void |
dotable(struct texi *p, enum texicmd cmd, |
dotable(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
enum texilist sv = p->list; |
enum texilist sv = p->list; |
|
|
p->list = TEXILIST_ITEM; |
p->list = TEXILIST_ITEM; |
teximacro(p, "Bl -tag -width Ds"); |
teximacro(p, "Bl -tag -width Ds"); |
/* FIXME: ignore and parseeoln. */ |
/* FIXME: ignore and parseeoln. */ |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
p->seenvs = 1; |
p->seenvs = 1; |
parseto(p, buf, sz, pos, texitoks[cmd].tok); |
parseto(p, pos, texitoks[cmd].tok); |
teximacro(p, "El"); |
teximacro(p, "El"); |
p->list = sv; |
p->list = sv; |
} |
} |
|
|
static void |
static void |
doend(struct texi *p, enum texicmd cmd, |
doend(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
size_t start; |
size_t start; |
|
|
while (*pos < sz && isws(buf[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, buf, pos); |
advance(p, pos); |
start = *pos; |
start = *pos; |
while (*pos < sz && '\n' != buf[*pos]) |
while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) |
advance(p, buf, pos); |
advance(p, pos); |
|
|
texiwarn(p, "unexpected \"end\": %.*s", (int)(*pos - start), &buf[start]); |
texiwarn(p, "unexpected \"end\": %.*s", (int)(*pos - start), &BUF(p)[start]); |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
} |
} |
|
|
static void |
static void |
doenumerate(struct texi *p, enum texicmd cmd, |
doenumerate(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
enum texilist sv = p->list; |
enum texilist sv = p->list; |
|
|
Line 1774 doenumerate(struct texi *p, enum texicmd cmd, |
|
Line 1783 doenumerate(struct texi *p, enum texicmd cmd, |
|
teximacro(p, "Bl -enum"); |
teximacro(p, "Bl -enum"); |
p->seenvs = 1; |
p->seenvs = 1; |
/* FIXME: ignore and parseeoln. */ |
/* FIXME: ignore and parseeoln. */ |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
parseto(p, buf, sz, pos, "enumerate"); |
parseto(p, pos, "enumerate"); |
teximacro(p, "El"); |
teximacro(p, "El"); |
p->list = sv; |
p->list = sv; |
} |
} |
|
|
static void |
static void |
doitemize(struct texi *p, enum texicmd cmd, |
doitemize(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
enum texilist sv = p->list; |
enum texilist sv = p->list; |
|
|
Line 1790 doitemize(struct texi *p, enum texicmd cmd, |
|
Line 1798 doitemize(struct texi *p, enum texicmd cmd, |
|
teximacro(p, "Bl -bullet"); |
teximacro(p, "Bl -bullet"); |
p->seenvs = 1; |
p->seenvs = 1; |
/* FIXME: ignore and parseeoln. */ |
/* FIXME: ignore and parseeoln. */ |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
parseto(p, buf, sz, pos, "itemize"); |
parseto(p, pos, "itemize"); |
teximacro(p, "El"); |
teximacro(p, "El"); |
p->list = sv; |
p->list = sv; |
} |
} |
|
|
static void |
static void |
doignbracket(struct texi *p, enum texicmd cmd, |
doignbracket(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
p->ign++; |
p->ign++; |
parsebracket(p, buf, sz, pos); |
parsebracket(p, pos); |
p->ign--; |
p->ign--; |
} |
} |
|
|
static void |
static void |
doignline(struct texi *p, enum texicmd cmd, |
doignline(struct texi *p, enum texicmd cmd, size_t *pos) |
const char *buf, size_t sz, size_t *pos) |
|
{ |
{ |
|
|
/* FIXME: ignore and parseeoln. */ |
/* FIXME: ignore and parseeoln. */ |
advanceeoln(p, buf, sz, pos, 1); |
advanceeoln(p, pos, 1); |
} |
} |
|
|
/* |
/* |