version 1.30, 2015/03/11 12:51:41 |
version 1.36, 2018/11/13 09:07:58 |
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <time.h> |
|
#include <unistd.h> |
#include <unistd.h> |
|
|
#include "extern.h" |
#include "extern.h" |
Line 109 texidex_free(struct texidex *p) |
|
Line 108 texidex_free(struct texidex *p) |
|
size_t i; |
size_t i; |
|
|
for (i = 0; i < p->indexsz; i++) |
for (i = 0; i < p->indexsz; i++) |
free(p->index[i]); |
free(p->index[i].term); |
|
|
free(p->index); |
free(p->index); |
free(p->name); |
free(p->name); |
|
|
texindex(struct texi *p, const char *tok, |
texindex(struct texi *p, const char *tok, |
size_t toksz, const char *index, size_t sz) |
size_t toksz, const char *index, size_t sz) |
{ |
{ |
size_t i; |
size_t i, isz; |
#ifdef HAVE_INDEX |
#ifdef HAVE_INDEX |
char *cp; |
char *cp; |
#endif |
#endif |
Line 146 texindex(struct texi *p, const char *tok, |
|
Line 145 texindex(struct texi *p, const char *tok, |
|
} |
} |
|
|
assert(i < p->indexsz); |
assert(i < p->indexsz); |
|
isz = p->indexs[i].indexsz; |
/* Reallocate index's terms. */ |
/* Reallocate index's terms. */ |
p->indexs[i].index = realloc |
p->indexs[i].index = realloc |
(p->indexs[i].index, |
(p->indexs[i].index, |
(p->indexs[i].indexsz + 1) * |
(isz + 1) * sizeof(struct texiterm)); |
sizeof(char *)); |
|
if (NULL == p->indexs[i].index) |
if (NULL == p->indexs[i].index) |
texiabort(p, NULL); |
texiabort(p, NULL); |
|
|
/* Add term to term array. */ |
/* Add term to term array. */ |
p->indexs[i].index[p->indexs[i].indexsz] = |
p->indexs[i].index[isz].chapter = p->nodecur; |
malloc(sz + 1); |
p->indexs[i].index[isz].term = malloc(sz + 1); |
if (NULL == p->indexs[i].index[p->indexs[i].indexsz]) |
if (NULL == p->indexs[i].index[isz].term) |
texiabort(p, NULL); |
texiabort(p, NULL); |
memcpy(p->indexs[i].index[p->indexs[i].indexsz], |
memcpy(p->indexs[i].index[isz].term, index, sz); |
index, sz); |
p->indexs[i].index[isz].term[sz] = '\0'; |
p->indexs[i].index[p->indexs[i].indexsz][sz] = '\0'; |
|
|
|
/* Output mdoc(7) for index. */ |
/* Output mdoc(7) for index. */ |
#ifdef HAVE_INDEX |
#ifdef HAVE_INDEX |
p->seenvs = -1; |
p->seenvs = -1; |
teximacroopen(p, "Ix"); |
teximacroopen(p, "Ix"); |
texiputchars(p, "idx"); |
texiputchars(p, "idx"); |
texiputchars(p, p->indexs[i].name); |
texiputchars(p, p->indexs[i].name); |
cp = p->indexs[i].index[p->indexs[i].indexsz]; |
cp = p->indexs[i].index[isz].term; |
while ('\n' != *cp) { |
while ('\n' != *cp) |
assert('\0' != *cp); |
|
texiputchar(p, *cp++); |
texiputchar(p, *cp++); |
} |
|
teximacroclose(p); |
teximacroclose(p); |
#endif |
#endif |
p->indexs[i].indexsz++; |
p->indexs[i].indexsz++; |
Line 203 texindex_add(struct texi *p, const char *tok, size_t s |
|
Line 199 texindex_add(struct texi *p, const char *tok, size_t s |
|
} |
} |
|
|
/* Reallocate indices. */ |
/* Reallocate indices. */ |
p->indexs = realloc(p->indexs, |
p->indexs = realloc(p->indexs, |
sizeof(struct texidex) * (p->indexsz + 1)); |
sizeof(struct texidex) * |
|
(p->indexsz + 1)); |
if (NULL == p->indexs) |
if (NULL == p->indexs) |
texiabort(p, NULL); |
texiabort(p, NULL); |
if (NULL == (cp = malloc(sz + 1))) |
if (NULL == (cp = malloc(sz + 1))) |
Line 243 texiexit(struct texi *p) |
|
Line 240 texiexit(struct texi *p) |
|
free(p->dirs[i]); |
free(p->dirs[i]); |
for (i = 0; i < p->indexsz; i++) |
for (i = 0; i < p->indexsz; i++) |
texidex_free(&p->indexs[i]); |
texidex_free(&p->indexs[i]); |
for (i = 0; i < p->valsz; i++) |
for (i = 0; i < p->valsz; i++) |
texivaluefree(&p->vals[i]); |
texivaluefree(&p->vals[i]); |
|
|
|
free(p->nodecache); |
free(p->macros); |
free(p->macros); |
free(p->vals); |
free(p->vals); |
free(p->indexs); |
free(p->indexs); |
Line 275 texiabort(struct texi *p, const char *errstring) |
|
Line 273 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; |
const struct texifile *f; |
|
|
f = &p->files[p->filepos - 1]; |
f = &p->files[p->filepos - 1]; |
|
|
if (f->insplice) |
if (f->insplice) |
fprintf(stderr, "%s:%zu:%zu (%zuB left in splice): " |
fprintf(stderr, "%s:%zu:%zu (%zuB left in splice): " |
"warning: ", f->name, f->line + 1, |
"warning: ", f->name, f->line + 1, |
f->col + 1, f->insplice); |
f->col + 1, f->insplice); |
else |
else |
fprintf(stderr, "%s:%zu:%zu: warning: ", |
fprintf(stderr, "%s:%zu:%zu: warning: ", |
Line 301 texiwarn(const struct texi *p, const char *fmt, ...) |
|
Line 299 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; |
struct texifile *f; |
|
|
f = &p->files[p->filepos - 1]; |
f = &p->files[p->filepos - 1]; |
|
|
if (f->insplice) |
if (f->insplice) |
fprintf(stderr, "%s:%zu:%zu: (%zuB left in splice): " |
fprintf(stderr, "%s:%zu:%zu: (%zuB left in splice): " |
"error: ", f->name, f->line + 1, |
"error: ", f->name, f->line + 1, |
f->col + 1, f->insplice); |
f->col + 1, f->insplice); |
else |
else |
fprintf(stderr, "%s:%zu:%zu: error: ", |
fprintf(stderr, "%s:%zu:%zu: error: ", |
Line 365 texiputchars(struct texi *p, const char *s) |
|
Line 363 texiputchars(struct texi *p, const char *s) |
|
fputs("\\&", p->outfile); |
fputs("\\&", p->outfile); |
if ('\'' == *s && 0 == p->outcol) |
if ('\'' == *s && 0 == p->outcol) |
fputs("\\&", p->outfile); |
fputs("\\&", p->outfile); |
if (p->uppercase) |
if (p->uppercase) |
for ( ; '\0' != *s; s++) |
for ( ; '\0' != *s; s++) |
p->outcol += fputc(toupper |
p->outcol += fputc(toupper |
((unsigned int)*s), p->outfile); |
((unsigned int)*s), p->outfile); |
Line 534 texipunctuate(struct texi *p, size_t *pos) |
|
Line 532 texipunctuate(struct texi *p, size_t *pos) |
|
} |
} |
if (end == *pos) |
if (end == *pos) |
return; |
return; |
if (end + 1 == BUFSZ(p) || ' ' == BUF(p)[end] || |
if (end + 1 == BUFSZ(p) || ' ' == BUF(p)[end] || |
'@' == BUF(p)[end] || '\n' == BUF(p)[end]) { |
'@' == BUF(p)[end] || '\n' == BUF(p)[end]) { |
for ( ; start < end; start++) { |
for ( ; start < end; start++) { |
texiputchar(p, ' '); |
texiputchar(p, ' '); |
Line 552 texipunctuate(struct texi *p, size_t *pos) |
|
Line 550 texipunctuate(struct texi *p, size_t *pos) |
|
static size_t |
static size_t |
advancenext(struct texi *p, size_t *pos) |
advancenext(struct texi *p, size_t *pos) |
{ |
{ |
|
|
if (p->literal) { |
if (p->literal) { |
while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) { |
while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) { |
texiputchar(p, BUF(p)[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, pos); |
advance(p, pos); |
} |
} |
return(*pos); |
return(*pos); |
} |
} |
|
|
while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) { |
while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) { |
p->seenws = 1; |
p->seenws = 1; |
Line 583 advanceeoln(struct texi *p, size_t *pos, int consumenl |
|
Line 581 advanceeoln(struct texi *p, size_t *pos, int consumenl |
|
while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) { |
while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) { |
if ('@' == BUF(p)[*pos]) |
if ('@' == BUF(p)[*pos]) |
advance(p, pos); |
advance(p, pos); |
advance(p, pos); |
if (*pos < BUFSZ(p)) |
|
advance(p, pos); |
} |
} |
if (*pos < BUFSZ(p) && consumenl) |
if (*pos < BUFSZ(p) && consumenl) |
advance(p, pos); |
advance(p, pos); |
Line 599 advanceto(struct texi *p, size_t *pos, size_t end) |
|
Line 598 advanceto(struct texi *p, size_t *pos, size_t end) |
|
{ |
{ |
|
|
assert(*pos <= end); |
assert(*pos <= end); |
while (*pos < end) |
while (*pos < end) |
advance(p, pos); |
advance(p, pos); |
} |
} |
|
|
static void |
static void |
texiexecmacro(struct texi *p, struct teximacro *m, size_t sv, 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; |
char *val; |
char *val; |
char **args; |
char **args; |
Line 664 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
Line 663 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
|
|
/* Parse to terminating delimiter. */ |
/* Parse to terminating delimiter. */ |
/* FIXME: embedded, escaped delimiters? */ |
/* FIXME: embedded, escaped delimiters? */ |
for (start = end = i + 1; end < realsz; end++) |
for (start = end = i + 1; end < realsz; end++) |
if ('\\' == m->value[end]) |
if ('\\' == m->value[end]) |
break; |
break; |
if (end == realsz) |
if (end == realsz) |
Line 678 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
Line 677 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
break; |
break; |
} |
} |
|
|
/* |
/* |
* Argument didn't exist in argument table. |
* Argument didn't exist in argument table. |
* Just ignore it. |
* Just ignore it. |
*/ |
*/ |
if (k == aasz) { |
if (k == aasz) { |
Line 694 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
Line 693 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
texiabort(p, NULL); |
texiabort(p, NULL); |
} |
} |
|
|
for (cp = args[k]; '\0' != *cp; cp++) |
for (cp = args[k]; '\0' != *cp; cp++) |
val[j++] = *cp; |
val[j++] = *cp; |
|
|
val[j] = '\0'; |
val[j] = '\0'; |
Line 707 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
Line 706 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
free(args[i]); |
free(args[i]); |
free(args); |
free(args); |
free(val); |
free(val); |
} |
} |
|
|
/* |
/* |
* Output a free-form word in the input stream, progressing to the next |
* Output a free-form word in the input stream, progressing to the next |
Line 717 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
Line 716 texiexecmacro(struct texi *p, struct teximacro *m, siz |
|
static void |
static void |
parseword(struct texi *p, size_t *pos, char extra) |
parseword(struct texi *p, size_t *pos, char extra) |
{ |
{ |
size_t i, end, len; |
size_t i, end, len; |
int c; |
int c; |
|
|
/* |
/* |
* If a prior word had a terminating double-newline, then begin |
* If a prior word had a terminating double-newline, then begin |
Line 729 parseword(struct texi *p, size_t *pos, char extra) |
|
Line 728 parseword(struct texi *p, size_t *pos, char extra) |
|
if (p->seenvs > 0 && 0 == p->literal && TEXILIST_TABLE != p->list) { |
if (p->seenvs > 0 && 0 == p->literal && TEXILIST_TABLE != p->list) { |
if (p->outcol > 0) |
if (p->outcol > 0) |
fputc('\n', p->outfile); |
fputc('\n', p->outfile); |
fputs(".Pp\n", p->outfile); |
if (p->ign == 0) |
|
fputs(".Pp\n", p->outfile); |
p->outcol = 0; |
p->outcol = 0; |
} |
} |
|
|
Line 738 parseword(struct texi *p, size_t *pos, char extra) |
|
Line 738 parseword(struct texi *p, size_t *pos, char extra) |
|
* have more than 72 characters written to the screen, then |
* have more than 72 characters written to the screen, then |
* output a newline before getting started. |
* output a newline before getting started. |
*/ |
*/ |
if (p->seenws && 0 == p->outmacro && |
if (p->seenws && 0 == p->outmacro && |
p->outcol > 72 && 0 == p->literal) |
p->outcol > 72 && 0 == p->literal) |
texiputchar(p, '\n'); |
texiputchar(p, '\n'); |
|
|
Line 806 parseword(struct texi *p, size_t *pos, char extra) |
|
Line 806 parseword(struct texi *p, size_t *pos, char extra) |
|
|
|
if ('"' == BUF(p)[*pos]) { |
if ('"' == BUF(p)[*pos]) { |
texiputchars(p, "\\(dq"); |
texiputchars(p, "\\(dq"); |
} else if (*pos < BUFSZ(p) - 2 && |
} else if (*pos < BUFSZ(p) - 2 && |
'-' == BUF(p)[*pos] && |
'-' == BUF(p)[*pos] && |
'-' == BUF(p)[*pos + 1] && |
'-' == BUF(p)[*pos + 1] && |
'-' == BUF(p)[*pos + 2]) { |
'-' == BUF(p)[*pos + 2]) { |
texiputchars(p, "\\(em"); |
texiputchars(p, "\\(em"); |
advance(p, pos); |
advance(p, pos); |
advance(p, pos); |
advance(p, pos); |
} else if (*pos < BUFSZ(p) - 1 && |
} else if (*pos < BUFSZ(p) - 1 && |
'-' == BUF(p)[*pos] && |
'-' == BUF(p)[*pos] && |
'-' == BUF(p)[*pos + 1]) { |
'-' == BUF(p)[*pos + 1]) { |
texiputchars(p, "\\(en"); |
texiputchars(p, "\\(en"); |
advance(p, pos); |
advance(p, pos); |
} else if (*pos < BUFSZ(p) - 1 && |
} else if (*pos < BUFSZ(p) - 1 && |
'`' == BUF(p)[*pos] && |
'`' == BUF(p)[*pos] && |
'`' == BUF(p)[*pos + 1]) { |
'`' == BUF(p)[*pos + 1]) { |
texiputchars(p, "\\(lq"); |
texiputchars(p, "\\(lq"); |
advance(p, pos); |
advance(p, pos); |
} else if (*pos < BUFSZ(p) - 1 && |
} else if (*pos < BUFSZ(p) - 1 && |
'\'' == BUF(p)[*pos] && |
'\'' == BUF(p)[*pos] && |
'\'' == BUF(p)[*pos + 1]) { |
'\'' == BUF(p)[*pos + 1]) { |
texiputchars(p, "\\(rq"); |
texiputchars(p, "\\(rq"); |
advance(p, pos); |
advance(p, pos); |
Line 834 parseword(struct texi *p, size_t *pos, char extra) |
|
Line 834 parseword(struct texi *p, size_t *pos, char extra) |
|
advance(p, pos); |
advance(p, pos); |
} |
} |
|
|
/* |
/* |
* New sentence, new line:if we (non-macro, non-literal) see a |
* New sentence, new line:if we (non-macro, non-literal) see a |
* period at the end of the last printed word, then open a |
* period at the end of the last printed word, then open a |
* newline. |
* newline. |
Line 889 texicmd(const struct texi *p, size_t pos, size_t *end, |
|
Line 889 texicmd(const struct texi *p, size_t pos, size_t *end, |
|
|
|
/* Scan to the end of the possible command name. */ |
/* Scan to the end of the possible command name. */ |
for (*end = pos; *end < BUFSZ(p) && ! ismspace(BUF(p)[*end]); (*end)++) |
for (*end = pos; *end < BUFSZ(p) && ! ismspace(BUF(p)[*end]); (*end)++) |
if ((*end > pos && ('@' == BUF(p)[*end] || |
if ((*end > pos && ('@' == BUF(p)[*end] || |
'{' == BUF(p)[*end] || '}' == BUF(p)[*end]))) |
'{' == BUF(p)[*end] || '}' == BUF(p)[*end]))) |
break; |
break; |
|
|
Line 974 parsearg(struct texi *p, size_t *pos, size_t num) |
|
Line 974 parsearg(struct texi *p, size_t *pos, size_t num) |
|
advanceto(p, pos, end); |
advanceto(p, pos, end); |
if (NULL != macro) |
if (NULL != macro) |
texiexecmacro(p, macro, sv, 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) |
(*texitoks[cmd].fp)(p, cmd, pos); |
(*texitoks[cmd].fp)(p, cmd, pos); |
Line 1035 parsebracket(struct texi *p, size_t *pos, int dostack) |
|
Line 1035 parsebracket(struct texi *p, size_t *pos, int dostack) |
|
advanceto(p, pos, end); |
advanceto(p, pos, end); |
if (NULL != macro) |
if (NULL != macro) |
texiexecmacro(p, macro, sv, 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) |
(*texitoks[cmd].fp)(p, cmd, pos); |
(*texitoks[cmd].fp)(p, cmd, pos); |
Line 1061 parseeoln(struct texi *p, size_t *pos) |
|
Line 1061 parseeoln(struct texi *p, size_t *pos) |
|
texiputchar(p, BUF(p)[*pos]); |
texiputchar(p, BUF(p)[*pos]); |
advance(p, pos); |
advance(p, pos); |
} |
} |
|
if (*pos == BUFSZ(p)) { |
|
texiwarn(p, "unexpected EOF"); |
|
return; |
|
} |
switch (BUF(p)[*pos]) { |
switch (BUF(p)[*pos]) { |
case ('}'): |
case ('}'): |
if (0 == p->ign) |
if (0 == p->ign) |
Line 1086 parseeoln(struct texi *p, size_t *pos) |
|
Line 1090 parseeoln(struct texi *p, size_t *pos) |
|
advanceto(p, pos, end); |
advanceto(p, pos, end); |
if (NULL != macro) |
if (NULL != macro) |
texiexecmacro(p, macro, sv, 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) |
(*texitoks[cmd].fp)(p, cmd, pos); |
(*texitoks[cmd].fp)(p, cmd, pos); |
Line 1129 peekcmd(const struct texi *p, size_t pos) |
|
Line 1133 peekcmd(const struct texi *p, size_t pos) |
|
* Parse a single word or command. |
* Parse a single word or command. |
* This will return immediately at the EOF. |
* This will return immediately at the EOF. |
*/ |
*/ |
static void |
void |
parsesingle(struct texi *p, size_t *pos) |
parsesingle(struct texi *p, size_t *pos) |
{ |
{ |
size_t end, sv; |
size_t end, sv; |
Line 1162 parsesingle(struct texi *p, size_t *pos) |
|
Line 1166 parsesingle(struct texi *p, size_t *pos) |
|
advanceto(p, pos, end); |
advanceto(p, pos, end); |
if (NULL != macro) |
if (NULL != macro) |
texiexecmacro(p, macro, sv, 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) |
(*texitoks[cmd].fp)(p, cmd, pos); |
(*texitoks[cmd].fp)(p, cmd, pos); |
Line 1203 parseeof(struct texi *p) |
|
Line 1207 parseeof(struct texi *p) |
|
{ |
{ |
size_t pos; |
size_t pos; |
|
|
for (pos = 0; pos < BUFSZ(p); ) |
for (pos = 0; pos < BUFSZ(p); ) |
parsesingle(p, &pos); |
parsesingle(p, &pos); |
} |
} |
|
|
Line 1245 parseto(struct texi *p, size_t *pos, const char *endto |
|
Line 1249 parseto(struct texi *p, size_t *pos, const char *endto |
|
|
|
endtoksz = strlen(endtoken); |
endtoksz = strlen(endtoken); |
assert(endtoksz > 0); |
assert(endtoksz > 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 ('}'): |
Line 1271 parseto(struct texi *p, size_t *pos, const char *endto |
|
Line 1275 parseto(struct texi *p, size_t *pos, const char *endto |
|
if (TEXICMD_END == cmd) { |
if (TEXICMD_END == cmd) { |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
while (*pos < BUFSZ(p) && isws(BUF(p)[*pos])) |
advance(p, pos); |
advance(p, pos); |
/* |
/* |
* FIXME: check the full word, not just its |
* FIXME: check the full word, not just its |
* initial substring! |
* initial substring! |
*/ |
*/ |
Line 1284 parseto(struct texi *p, size_t *pos, const char *endto |
|
Line 1288 parseto(struct texi *p, size_t *pos, const char *endto |
|
texiwarn(p, "unexpected \"end\""); |
texiwarn(p, "unexpected \"end\""); |
advanceeoln(p, pos, 0); |
advanceeoln(p, pos, 0); |
continue; |
continue; |
} |
} |
if (NULL != macro) |
if (NULL != macro) |
texiexecmacro(p, macro, sv, 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) |
(*texitoks[cmd].fp)(p, cmd, pos); |
(*texitoks[cmd].fp)(p, cmd, pos); |
} |
} |
|
|
if (*pos == BUFSZ(p)) |
if (*pos == BUFSZ(p)) |
texiwarn(p, "EOF expecting \"%s\" end\n", endtoken); |
texiwarn(p, "EOF expecting \"%s\" end\n", endtoken); |
} |
} |
|
|
Line 1318 parsestdin(struct texi *p) |
|
Line 1322 parsestdin(struct texi *p) |
|
if (f->mapsz == f->mapmaxsz) { |
if (f->mapsz == f->mapmaxsz) { |
if (f->mapmaxsz == (1U << 31)) |
if (f->mapmaxsz == (1U << 31)) |
texierr(p, "stdin buffer too long"); |
texierr(p, "stdin buffer too long"); |
f->mapmaxsz = f->mapmaxsz > 65536 / 2 ? |
f->mapmaxsz = f->mapmaxsz > 65536 / 2 ? |
2 * f->mapmaxsz : 65536; |
2 * f->mapmaxsz : 65536; |
f->map = realloc(f->map, f->mapmaxsz); |
f->map = realloc(f->map, f->mapmaxsz); |
if (NULL == f->map) |
if (NULL == f->map) |
texiabort(p, NULL); |
texiabort(p, NULL); |
} |
} |
ssz = read(STDIN_FILENO, f->map + |
ssz = read(STDIN_FILENO, f->map + |
(int)f->mapsz, f->mapmaxsz - f->mapsz); |
(int)f->mapsz, f->mapmaxsz - f->mapsz); |
if (0 == ssz) |
if (0 == ssz) |
break; |
break; |
else if (-1 == ssz) |
else if (-1 == ssz) |
texiabort(p, NULL); |
texiabort(p, NULL); |
} |
} |
|
|
Line 1352 parsefile(struct texi *p, const char *fname, int parse |
|
Line 1356 parsefile(struct texi *p, const char *fname, int parse |
|
size_t i; |
size_t i; |
char *map; |
char *map; |
|
|
if (64 == p->filepos) |
if (64 == p->filepos) |
texierr(p, "too many open files"); |
texierr(p, "too many open files"); |
f = &p->files[p->filepos]; |
f = &p->files[p->filepos]; |
memset(f, 0, sizeof(struct texifile)); |
memset(f, 0, sizeof(struct texifile)); |
Line 1364 parsefile(struct texi *p, const char *fname, int parse |
|
Line 1368 parsefile(struct texi *p, const char *fname, int parse |
|
} else if (-1 == fstat(fd, &st)) { |
} else if (-1 == fstat(fd, &st)) { |
close(fd); |
close(fd); |
texiabort(p, fname); |
texiabort(p, fname); |
} |
} |
|
|
f->mapsz = f->mapmaxsz = st.st_size; |
f->mapsz = f->mapmaxsz = st.st_size; |
map = mmap(NULL, f->mapsz, |
map = mmap(NULL, f->mapsz, |
Line 1514 valueadd(struct texi *p, char *key, char *val) |
|
Line 1518 valueadd(struct texi *p, char *key, char *val) |
|
p->vals[i].value = val; |
p->vals[i].value = val; |
} else { |
} else { |
/* FIXME: reallocarray() */ |
/* FIXME: reallocarray() */ |
p->vals = realloc(p->vals, |
p->vals = realloc(p->vals, |
(p->valsz + 1) * |
(p->valsz + 1) * |
sizeof(struct texivalue)); |
sizeof(struct texivalue)); |
if (NULL == p->vals) |
if (NULL == p->vals) |
Line 1585 argparse(struct texi *p, size_t *pos, size_t *argsz, s |
|
Line 1589 argparse(struct texi *p, size_t *pos, size_t *argsz, s |
|
start = *pos; |
start = *pos; |
stack = 0; |
stack = 0; |
while (*pos < BUFSZ(p)) { |
while (*pos < BUFSZ(p)) { |
/* |
/* |
* According to the manual, commas within |
* According to the manual, commas within |
* embedded commands are escaped. |
* embedded commands are escaped. |
* We keep track of embedded-ness in the "stack" |
* We keep track of embedded-ness in the "stack" |
Line 1627 argparse(struct texi *p, size_t *pos, size_t *argsz, s |
|
Line 1631 argparse(struct texi *p, size_t *pos, size_t *argsz, s |
|
advance(p, pos); |
advance(p, pos); |
} |
} |
|
|
if (*pos == BUFSZ(p)) |
if (*pos == BUFSZ(p)) |
texierr(p, "unterminated arguments"); |
texierr(p, "unterminated arguments"); |
assert('}' == BUF(p)[*pos]); |
assert('}' == BUF(p)[*pos]); |
advance(p, pos); |
advance(p, pos); |
Line 1646 teximdocclose(struct texi *p, int last) |
|
Line 1650 teximdocclose(struct texi *p, int last) |
|
{ |
{ |
char buf[PATH_MAX]; |
char buf[PATH_MAX]; |
|
|
if (NULL == p->chapters || 0 == p->chapnum) |
if (NULL == p->chapters || 1 == p->nodesz) |
return; |
return; |
|
|
teximacro(p, "Sh INFO NAVIGATION"); |
teximacro(p, "Sh INFO NAVIGATION"); |
|
|
/* Print a reference to the "top" node. */ |
/* Print a reference to the "top" node. */ |
if (p->chapnum > 1) { |
if (-1 != p->nodecache[p->nodecur].up) { |
texiputchars(p, "Top node,"); |
texiputchars(p, "Top node,"); |
snprintf(buf, sizeof(buf), "node1 7"); |
snprintf(buf, sizeof(buf), "%s-%zd 7", |
|
p->chapters, p->nodecache[p->nodecur].up); |
|
p->seenvs = 0; |
teximacroopen(p, "Xr "); |
teximacroopen(p, "Xr "); |
texiputchars(p, buf); |
texiputchars(p, buf); |
texiputchars(p, " ;"); |
texiputchars(p, " ;"); |
teximacroclose(p); |
teximacroclose(p); |
} |
} |
|
|
/* Print a reference to the previous node. */ |
if (-1 != p->nodecache[p->nodecur].prev) { |
if (p->chapnum > 2) { |
|
texiputchars(p, "previous node,"); |
texiputchars(p, "previous node,"); |
snprintf(buf, sizeof(buf), |
snprintf(buf, sizeof(buf), "%s-%zd 7", |
"node%zu 7", p->chapnum - 1); |
p->chapters, p->nodecache[p->nodecur].prev); |
|
p->seenvs = 0; |
teximacroopen(p, "Xr "); |
teximacroopen(p, "Xr "); |
texiputchars(p, buf); |
texiputchars(p, buf); |
if ( ! last) |
if ( ! last) |
texiputchars(p, " ;"); |
texiputchars(p, " ;"); |
teximacroclose(p); |
teximacroclose(p); |
} |
} |
|
|
/* Print a reference to the next node. */ |
if (-1 != p->nodecache[p->nodecur].next) { |
if ( ! last) { |
texiputchars(p, "next node,"); |
if (1 == p->chapnum) |
snprintf(buf, sizeof(buf), "%s-%zd 7", |
texiputchars(p, "Next node,"); |
p->chapters, p->nodecache[p->nodecur].next); |
else |
p->seenvs = 0; |
texiputchars(p, "next node,"); |
|
snprintf(buf, sizeof(buf), |
|
"node%zu 7", p->chapnum + 1); |
|
teximacroopen(p, "Xr "); |
teximacroopen(p, "Xr "); |
texiputchars(p, buf); |
texiputchars(p, buf); |
teximacroclose(p); |
teximacroclose(p); |
} |
} |
|
|
fclose(p->outfile); |
fclose(p->outfile); |
|
p->outfile = NULL; |
} |
} |
|
|
|
ssize_t |
|
texicache(struct texi *p, const char *buf, size_t sz) |
|
{ |
|
size_t i; |
|
|
|
for (i = 0; i < p->nodecachesz; i++) { |
|
if (sz != strlen(p->nodecache[i].name)) |
|
continue; |
|
if (strncmp(buf, p->nodecache[i].name, sz)) |
|
continue; |
|
break; |
|
} |
|
if (i < p->nodecachesz) |
|
return(i); |
|
if (NULL == buf) |
|
return(-1); |
|
p->nodecache = realloc |
|
(p->nodecache, |
|
(p->nodecachesz + 1) * sizeof(struct texinode)); |
|
if (NULL == p->nodecache) |
|
texiabort(p, NULL); |
|
p->nodecache[p->nodecachesz].name = malloc(sz + 1); |
|
if (NULL == p->nodecache[p->nodecachesz].name) |
|
texiabort(p, NULL); |
|
memcpy(p->nodecache[p->nodecachesz].name, buf, sz); |
|
p->nodecache[p->nodecachesz].name[sz] = '\0'; |
|
p->nodecache[p->nodecachesz].up = |
|
p->nodecache[p->nodecachesz].next = |
|
p->nodecache[p->nodecachesz].prev = -1; |
|
p->nodecachesz++; |
|
return(p->nodecachesz - 1); |
|
} |
|
|
/* |
/* |
* Open a mdoc(7) context. |
* Here we print our standard mdoc(7) prologue. |
* If we're printing chapters, then open the outfile here, too. |
* We use the title set with @settitle for the `Nd' description |
* Otherwise just print the mdoc(7) prologue. |
* and the source document filename (the first one as invoked on |
|
* the command line) for the title. |
|
* The date is set to the modification time of the input. |
*/ |
*/ |
void |
void |
teximdocopen(struct texi *p, size_t *pos) |
teximdocopen(struct texi *p, size_t *pos) |
{ |
{ |
const char *cp; |
const char *cp; |
time_t t; |
|
char date[32]; |
|
char fname[PATH_MAX]; |
|
|
|
if (NULL != p->chapters) { |
|
snprintf(fname, sizeof(fname), "%s/node%zu.7", |
|
p->chapters, ++p->chapnum); |
|
p->outfile = fopen(fname, "w"); |
|
if (NULL == p->outfile) |
|
texiabort(p, fname); |
|
} |
|
|
|
/* |
|
* Here we print our standard mdoc(7) prologue. |
|
* We use the title set with @settitle for the `Nd' description |
|
* and the source document filename (the first one as invoked on |
|
* the command line) for the title. |
|
* The date is set to the current date. |
|
*/ |
|
t = time(NULL); |
|
strftime(date, sizeof(date), "%F", localtime(&t)); |
|
|
|
p->seenvs = -1; |
p->seenvs = -1; |
teximacroopen(p, "Dd"); |
teximacroopen(p, "Dd"); |
texiputchars(p, date); |
texiputchars(p, p->date); |
teximacroclose(p); |
teximacroclose(p); |
teximacroopen(p, "Dt"); |
teximacroopen(p, "Dt"); |
for (cp = p->title; '\0' != *cp; cp++) |
for (cp = p->title; '\0' != *cp; cp++) |