version 1.1, 2015/02/20 09:58:50 |
version 1.6, 2015/02/21 22:01:32 |
Line 67 texiexit(struct texi *p) |
|
Line 67 texiexit(struct texi *p) |
|
for (i = 0; i < p->dirsz; i++) |
for (i = 0; i < p->dirsz; i++) |
free(p->dirs[i]); |
free(p->dirs[i]); |
|
|
|
for (i = 0; i < p->indexsz; i++) |
|
free(p->indexs[i]); |
|
|
for (i = 0; i < p->valsz; i++) { |
for (i = 0; i < p->valsz; i++) { |
free(p->vals[i].value); |
free(p->vals[i].value); |
free(p->vals[i].key); |
free(p->vals[i].key); |
} |
} |
|
|
free(p->vals); |
free(p->vals); |
|
free(p->indexs); |
free(p->dirs); |
free(p->dirs); |
free(p->subtitle); |
free(p->subtitle); |
free(p->title); |
free(p->title); |
|
|
texivspace(struct texi *p) |
texivspace(struct texi *p) |
{ |
{ |
|
|
if (p->seenvs) |
if (p->seenvs || TEXILIST_TABLE == p->list) |
return; |
return; |
teximacro(p, "Pp"); |
teximacro(p, "Pp"); |
p->seenvs = 1; |
p->seenvs = 1; |
|
|
texicmd(struct texi *p, const char *buf, |
texicmd(struct texi *p, const char *buf, |
size_t pos, size_t sz, size_t *end) |
size_t pos, size_t sz, size_t *end) |
{ |
{ |
size_t i, len; |
size_t i, len, toksz; |
|
|
assert('@' == buf[pos]); |
assert('@' == buf[pos]); |
|
|
Line 452 texicmd(struct texi *p, const char *buf, |
|
Line 456 texicmd(struct texi *p, const char *buf, |
|
return(TEXICMD__MAX); |
return(TEXICMD__MAX); |
} |
} |
|
|
|
/* Scan to the end of the possible command name. */ |
for (*end = pos; *end < sz && ! ismspace(buf[*end]); (*end)++) |
for (*end = pos; *end < sz && ! ismspace(buf[*end]); (*end)++) |
if ((*end > pos && ('@' == buf[*end] || |
if ((*end > pos && ('@' == buf[*end] || |
'{' == buf[*end] || '}' == buf[*end]))) |
'{' == buf[*end] || '}' == buf[*end]))) |
break; |
break; |
|
|
|
/* Look for the command. */ |
len = *end - pos; |
len = *end - pos; |
for (i = 0; i < TEXICMD__MAX; i++) { |
for (i = 0; i < TEXICMD__MAX; i++) { |
if (len != texitoks[i].len) |
if (len != texitoks[i].len) |
Line 465 texicmd(struct texi *p, const char *buf, |
|
Line 471 texicmd(struct texi *p, const char *buf, |
|
return(i); |
return(i); |
} |
} |
|
|
|
/* Look for it in our indices. */ |
|
for (i = 0; i < p->indexsz; i++) { |
|
toksz = strlen(p->indexs[i]); |
|
if (len != 5 + toksz) |
|
continue; |
|
if (strncmp(&buf[pos], p->indexs[i], toksz)) |
|
continue; |
|
if (0 == strncmp(&buf[pos + toksz], "index", 5)) |
|
return(TEXICMD_INDEX); |
|
} |
|
|
texiwarn(p, "bad command: @%.*s", (int)len, &buf[pos]); |
texiwarn(p, "bad command: @%.*s", (int)len, &buf[pos]); |
return(TEXICMD__MAX); |
return(TEXICMD__MAX); |
} |
} |
Line 667 parselinearg(struct texi *p, const char *buf, size_t s |
|
Line 684 parselinearg(struct texi *p, const char *buf, size_t s |
|
|
|
if (*pos < sz && '{' == buf[*pos]) |
if (*pos < sz && '{' == buf[*pos]) |
parsebracket(p, buf, sz, pos); |
parsebracket(p, buf, sz, pos); |
else if ('\n' != buf[*pos]) |
else if (*pos < sz && '\n' != buf[*pos]) |
parsesingle(p, buf, sz, pos); |
parsesingle(p, buf, sz, pos); |
else |
else |
return(0); |
return(0); |
Line 760 parsefile(struct texi *p, const char *fname, int parse |
|
Line 777 parsefile(struct texi *p, const char *fname, int parse |
|
struct stat st; |
struct stat st; |
size_t i; |
size_t i; |
|
|
assert(p->filepos < 64); |
if (64 == p->filepos) |
|
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 801 parsefile(struct texi *p, const char *fname, int parse |
|
Line 819 parsefile(struct texi *p, const char *fname, int parse |
|
texifilepop(p); |
texifilepop(p); |
} |
} |
|
|
|
/* |
|
* Look up the value to a stored pair's value starting in "buf" from |
|
* start to end. |
|
* Return the pointer to the value memory, which can be NULL if the |
|
* pointer key does not exist. |
|
* The pointer can point to NULL if the value has been unset. |
|
*/ |
|
static char ** |
|
valuequery(const struct texi *p, |
|
const char *buf, size_t start, size_t end) |
|
{ |
|
size_t i, sz, len; |
|
|
|
assert(end >= start); |
|
/* Ignore zero-length. */ |
|
if (0 == (len = (end - start))) |
|
return(NULL); |
|
for (i = 0; i < p->valsz; i++) { |
|
sz = strlen(p->vals[i].key); |
|
if (sz != len) |
|
continue; |
|
if (0 == strncmp(p->vals[i].key, &buf[start], len)) |
|
return(&p->vals[i].value); |
|
} |
|
return(NULL); |
|
} |
|
|
|
/* |
|
* Parse a key until the end of line, e.g., @clear foo\n, and return the |
|
* pointer to its value via valuequery(). |
|
*/ |
|
static char ** |
|
valuelquery(struct texi *p, const char *buf, size_t sz, size_t *pos) |
|
{ |
|
size_t start, end; |
|
char **ret; |
|
|
|
while (*pos < sz && isws(buf[*pos])) |
|
advance(p, buf, pos); |
|
if (*pos == sz) |
|
return(NULL); |
|
for (start = end = *pos; end < sz; end++) |
|
if ('\n' == buf[end]) |
|
break; |
|
advanceto(p, buf, pos, end); |
|
if (*pos < sz) { |
|
assert('\n' == buf[*pos]); |
|
advance(p, buf, pos); |
|
} |
|
if (NULL == (ret = valuequery(p, buf, start, end))) |
|
return(NULL); |
|
return(ret); |
|
} |
|
|
|
void |
|
valuelclear(struct texi *p, const char *buf, size_t sz, size_t *pos) |
|
{ |
|
char **ret; |
|
|
|
if (NULL == (ret = valuelquery(p, buf, sz, pos))) |
|
return; |
|
free(*ret); |
|
*ret = NULL; |
|
} |
|
|
|
const char * |
|
valuellookup(struct texi *p, const char *buf, size_t sz, size_t *pos) |
|
{ |
|
char **ret; |
|
|
|
if (NULL == (ret = valuelquery(p, buf, sz, pos))) |
|
return(NULL); |
|
return(*ret); |
|
} |
|
|
|
/* |
|
* Parse a key from a bracketed string, e.g., @value{foo}, and return |
|
* the pointer to its value. |
|
* If the returned pointer is NULL, either there was no string within |
|
* the brackets (or no brackets), or the value was not found, or the |
|
* value had previously been unset. |
|
*/ |
|
const char * |
|
valueblookup(struct texi *p, const char *buf, size_t sz, size_t *pos) |
|
{ |
|
size_t start, end; |
|
char **ret; |
|
|
|
while (*pos < sz && isws(buf[*pos])) |
|
advance(p, buf, pos); |
|
if (*pos == sz || '{' != buf[*pos]) |
|
return(NULL); |
|
advance(p, buf, pos); |
|
for (start = end = *pos; end < sz; end++) |
|
if ('}' == buf[end]) |
|
break; |
|
advanceto(p, buf, pos, end); |
|
if (*pos < sz) { |
|
assert('}' == buf[*pos]); |
|
advance(p, buf, pos); |
|
} |
|
if (NULL == (ret = valuequery(p, buf, start, end))) |
|
return(NULL); |
|
return(*ret); |
|
} |
|
|
|
void |
|
valueadd(struct texi *p, char *key, char *val) |
|
{ |
|
size_t i; |
|
|
|
assert(NULL != key); |
|
assert(NULL != val); |
|
|
|
for (i = 0; i < p->valsz; i++) |
|
if (0 == strcmp(p->vals[i].key, key)) |
|
break; |
|
|
|
if (i < p->valsz) { |
|
free(key); |
|
free(p->vals[i].value); |
|
p->vals[i].value = val; |
|
} else { |
|
/* FIXME: reallocarray() */ |
|
p->vals = realloc(p->vals, |
|
(p->valsz + 1) * |
|
sizeof(struct texivalue)); |
|
if (NULL == p->vals) |
|
texiabort(p, NULL); |
|
p->vals[p->valsz].key = key; |
|
p->vals[p->valsz].value = val; |
|
p->valsz++; |
|
} |
|
} |