27 #define _POSIX_C_SOURCE 200809L
38 static void *(*ppmalloc)(size_t) =
malloc;
48 #define MALLOC(a) ppmalloc(a)
49 #define FREE(a) ppfree(a)
51 #define malloc(x) error - forbidden - use MALLOC instead
52 #define free(x) error - forbidden - use FREE instead
53 #define calloc(x, y) error - forbidden - use CALLOC instead
55 static void *
CALLOC(
size_t nmemb,
size_t sz) {
66 #define strdup(x) error - forbidden - use STRDUP instead
80 #define strndup(x) error - forbiden - use STRNDUP instead
82 static char *
STRNDUP(
const char *s,
size_t n) {
83 size_t len = strnlen(s, n);
97 const unsigned char *buf = (
const unsigned char *)orig;
113 if (0x6 == (i >> 5)) {
117 for (
int j = 0; j < 1; j++) {
121 v = (v << 6) | (i & 0x3f);
123 return *ret = v, (
const char *)buf - orig;
129 if (0xE == (i >> 4)) {
133 for (
int j = 0; j < 2; j++) {
137 v = (v << 6) | (i & 0x3f);
139 return *ret = v, (
const char *)buf - orig;
145 if (0x1E == (i >> 3)) {
149 for (
int j = 0; j < 3; j++) {
153 v = (v << 6) | (i & 0x3f);
155 return *ret = v, (
const char *)buf - orig;
161 if (0x3E == (i >> 2)) {
165 for (
int j = 0; j < 4; j++) {
169 v = (v << 6) | (i & 0x3f);
171 return *ret = v, (
const char *)buf - orig;
177 if (0x7e == (i >> 1)) {
181 for (
int j = 0; j < 5; j++) {
185 v = (v << 6) | (i & 0x3f);
187 return *ret = v, (
const char *)buf - orig;
204 if (0xd800 <= code && code <= 0xdfff)
206 if (0xfffe <= code && code <= 0xffff)
215 buf[0] = (
unsigned char)code;
222 if (code <= 0x000007FF) {
223 buf[0] = (
unsigned char) (0xc0 | (code >> 6));
224 buf[1] = (
unsigned char) (0x80 | (code & 0x3f));
231 if (code <= 0x0000FFFF) {
232 buf[0] = (
unsigned char) (0xe0 | (code >> 12));
233 buf[1] = (
unsigned char) (0x80 | ((code >> 6) & 0x3f));
234 buf[2] = (
unsigned char) (0x80 | (code & 0x3f));
241 if (code <= 0x001FFFFF) {
242 buf[0] = (
unsigned char) (0xf0 | (code >> 18));
243 buf[1] = (
unsigned char) (0x80 | ((code >> 12) & 0x3f));
244 buf[2] = (
unsigned char) (0x80 | ((code >> 6) & 0x3f));
245 buf[3] = (
unsigned char) (0x80 | (code & 0x3f));
252 if (code <= 0x03FFFFFF) {
253 buf[0] = (
unsigned char) (0xf8 | (code >> 24));
254 buf[1] = (
unsigned char) (0x80 | ((code >> 18) & 0x3f));
255 buf[2] = (
unsigned char) (0x80 | ((code >> 12) & 0x3f));
256 buf[3] = (
unsigned char) (0x80 | ((code >> 6) & 0x3f));
257 buf[4] = (
unsigned char) (0x80 | (code & 0x3f));
264 if (code <= 0x7FFFFFFF) {
265 buf[0] = (
unsigned char) (0xfc | (code >> 30));
266 buf[1] = (
unsigned char) (0x80 | ((code >> 24) & 0x3f));
267 buf[2] = (
unsigned char) (0x80 | ((code >> 18) & 0x3f));
268 buf[3] = (
unsigned char) (0x80 | ((code >> 12) & 0x3f));
269 buf[4] = (
unsigned char) (0x80 | ((code >> 6) & 0x3f));
270 buf[5] = (
unsigned char) (0x80 | (code & 0x3f));
324 static inline void xfree(
const void *x) {
326 FREE((
void *)(intptr_t)x);
370 #define STRINGIFY(x) #x
371 #define TOSTRING(x) STRINGIFY(x)
372 #define FLINE __FILE__ ":" TOSTRING(__LINE__)
380 snprintf(ctx->
errbuf, ctx->
errbufsz,
"ERROR: out of memory (%s)", fline);
385 snprintf(ctx->
errbuf, ctx->
errbufsz,
"internal error (%s)", fline);
400 snprintf(ctx->
errbuf, ctx->
errbufsz,
"line %d: key exists", lineno);
409 static void *
expand(
void *p,
int sz,
int newsz) {
420 void **s =
MALLOC((n + 1) *
sizeof(
void *));
425 memcpy(s, p, n *
sizeof(
void *));
435 memset(&pp[n], 0,
sizeof(pp[n]));
440 char *errbuf,
int errbufsz) {
444 const char *sp = src;
445 const char *sq = src + srclen;
450 if (off >= max - 10) {
451 int newmax = max + 50;
452 char *x =
expand(dst, max, newmax);
455 snprintf(errbuf, errbufsz,
"out of memory");
468 if ((0 <= ch && ch <= 0x08) || (0x0a <= ch && ch <= 0x1f) || (ch == 0x7f)) {
469 if (!(multiline && (ch ==
'\r' || ch ==
'\n'))) {
471 snprintf(errbuf, errbufsz,
"invalid char U+%04x", ch);
489 char *errbuf,
int errbufsz) {
493 const char *sp = src;
494 const char *sq = src + srclen;
499 if (off >= max - 10) {
500 int newmax = max + 50;
501 char *x =
expand(dst, max, newmax);
504 snprintf(errbuf, errbufsz,
"out of memory");
519 if ((0 <= ch && ch <= 0x08) || (0x0a <= ch && ch <= 0x1f) ||
521 if (!(multiline && (ch ==
'\r' || ch ==
'\n'))) {
523 snprintf(errbuf, errbufsz,
"invalid char U+%04x", ch);
535 snprintf(errbuf, errbufsz,
"last backslash is invalid");
544 if (sp[strspn(sp,
" \t\r")] ==
'\n') {
546 sp += strspn(sp,
" \t\r\n");
557 int nhex = (ch ==
'u' ? 4 : 8);
558 for (
int i = 0; i < nhex; i++) {
560 snprintf(errbuf, errbufsz,
"\\%c expects %d hex chars", ch, nhex);
565 int v = (
'0' <= ch && ch <=
'9')
567 : ((
'A' <= ch && ch <=
'F') ? ch -
'A' + 10 : -1);
569 snprintf(errbuf, errbufsz,
"invalid hex chars for \\u or \\U");
577 snprintf(errbuf, errbufsz,
"illegal ucs code in \\u or \\U");
607 snprintf(errbuf, errbufsz,
"illegal escape char \\%c", ch);
622 const char *sp = strtok.
ptr;
623 const char *sq = strtok.
ptr + strtok.
len;
624 int lineno = strtok.
lineno;
630 if (ch ==
'\'' || ch ==
'\"') {
633 if (sp[1] == ch && sp[2] == ch) {
641 if (!(ret =
STRNDUP(sp, sq - sp))) {
655 if (strchr(ret,
'\n')) {
665 for (xp = sp; xp != sq; xp++) {
669 if (k ==
'_' || k ==
'-')
676 if (!(ret =
STRNDUP(sp, sq - sp))) {
704 for (i = 0; i < tab->
nkval; i++) {
705 if (0 == strcmp(key, tab->
kval[i]->
key)) {
706 *ret_val = tab->
kval[i];
710 for (i = 0; i < tab->
narr; i++) {
711 if (0 == strcmp(key, tab->
arr[i]->
key)) {
712 *ret_arr = tab->
arr[i];
716 for (i = 0; i < tab->
ntab; i++) {
717 if (0 == strcmp(key, tab->
tab[i]->
key)) {
718 *ret_tab = tab->
tab[i];
783 if (
check_key(tab, newkey, 0, 0, &dest)) {
861 const int n = parent->
nitem;
869 return &parent->
item[n];
876 const int n = parent->
nitem;
897 int n = parent->
nitem;
947 "newline not allowed in inline table");
961 "newline not allowed in inline table");
982 if (*val ==
'\'' || *val ==
'"')
1018 else if (arr->
kind !=
'v')
1021 char *val = ctx->
tok.
ptr;
1035 if (arr->
nitem == 1)
1049 else if (arr->
kind !=
'a')
1064 else if (arr->
kind !=
't')
1104 "cannot insert new entry into existing table");
1152 assert(keyval->
val == 0);
1201 for (i = 0; i < ctx->
tpath.
top; i++) {
1211 "table path is too deep; max allowed is 10.");
1214 return e_syntax(ctx, lineno,
"invalid or missing key");
1230 return e_syntax(ctx, lineno,
"invalid key");
1237 return e_syntax(ctx, lineno,
"empty table selector");
1249 for (
int i = 0; i < ctx->
tpath.
top; i++) {
1250 const char *key = ctx->
tpath.
key[i];
1255 switch (
check_key(curtab, key, &nextval, &nextarr, &nexttab)) {
1262 if (nextarr->
kind !=
't')
1265 if (nextarr->
nitem == 0)
1275 int n = curtab->
ntab;
1286 if (0 == (base[n]->key =
STRDUP(key)))
1289 nexttab = curtab->
tab[curtab->
ntab++];
1358 if (arr->
kind !=
't')
1407 memset(&ctx, 0,
sizeof(ctx));
1457 e_syntax(&ctx, tok.lineno,
"syntax error");
1463 for (
int i = 0; i < ctx.
tpath.
top; i++)
1469 for (
int i = 0; i < ctx.
tpath.
top; i++)
1484 int xsz = bufsz + 1000;
1485 char *x =
expand(buf, bufsz, xsz);
1487 snprintf(errbuf, errbufsz,
"out of memory");
1496 int n = fread(buf + off, 1, bufsz - off, fp);
1498 snprintf(errbuf, errbufsz,
"%s",
1499 errno ? strerror(errno) :
"Error reading file");
1508 int xsz = bufsz + 1;
1509 char *x =
expand(buf, bufsz, xsz);
1511 snprintf(errbuf, errbufsz,
"out of memory");
1541 const int n = p->
nitem;
1542 for (
int i = 0; i < n; i++) {
1563 for (i = 0; i < p->
nkval; i++)
1567 for (i = 0; i < p->
narr; i++)
1571 for (i = 0; i < p->
ntab; i++)
1599 for (; n > 0 && isdigit(*p); n--, p++) {
1600 ret = 10 * ret + (*p -
'0');
1602 return n ? -1 : ret;
1605 static int scan_date(
const char *p,
int *YY,
int *MM,
int *DD) {
1606 int year, month, day;
1608 month = (year >= 0 && p[4] ==
'-') ?
scan_digits(p + 5, 2) : -1;
1609 day = (month >= 0 && p[7] ==
'-') ?
scan_digits(p + 8, 2) : -1;
1616 return (year >= 0 && month >= 0 && day >= 0) ? 0 : -1;
1619 static int scan_time(
const char *p,
int *hh,
int *mm,
int *ss) {
1620 int hour, minute, second;
1622 minute = (hour >= 0 && p[2] ==
':') ?
scan_digits(p + 3, 2) : -1;
1623 second = (minute >= 0 && p[5] ==
':') ?
scan_digits(p + 6, 2) : -1;
1630 return (hour >= 0 && minute >= 0 && second >= 0) ? 0 : -1;
1635 if (0 == strncmp(p,
"'''", 3)) {
1639 q = strstr(q,
"'''");
1641 return e_syntax(ctx, lineno,
"unterminated triple-s-quote");
1643 while (q[3] ==
'\'')
1652 if (0 == strncmp(p,
"\"\"\"", 3)) {
1656 q = strstr(q,
"\"\"\"");
1658 return e_syntax(ctx, lineno,
"unterminated triple-d-quote");
1660 if (q[-1] ==
'\\') {
1664 while (q[3] ==
'\"')
1673 for (p += 3; p < q; p++) {
1676 if (strchr(
"btnfr\"\\", *p))
1686 if (p[strspn(p,
" \t\r")] ==
'\n')
1688 return e_syntax(ctx, lineno,
"bad escape char");
1692 if (strchr(
"0123456789ABCDEF", *p))
1694 return e_syntax(ctx, lineno,
"expect hex char");
1702 return e_syntax(ctx, lineno,
"expect an escape char");
1704 return e_syntax(ctx, lineno,
"expected more hex char");
1711 for (p++; *p && *p !=
'\n' && *p !=
'\''; p++)
1714 return e_syntax(ctx, lineno,
"unterminated s-quote");
1724 for (p++; *p; p++) {
1727 if (strchr(
"btnfr\"\\", *p))
1737 return e_syntax(ctx, lineno,
"bad escape char");
1741 if (strchr(
"0123456789ABCDEF", *p))
1743 return e_syntax(ctx, lineno,
"expect hex char");
1750 if (p[1] ==
'\'' && p[2] ==
'\'') {
1751 return e_syntax(ctx, lineno,
"triple-s-quote inside string lit");
1761 return e_syntax(ctx, lineno,
"unterminated quote");
1771 p += strspn(p,
"0123456789.:+-Tt Zz");
1773 for (; p[-1] ==
' '; p--)
1781 for (; *p && *p !=
'\n'; p++) {
1783 if (ch ==
'.' && dotisspecial)
1785 if (
'A' <= ch && ch <=
'Z')
1787 if (
'a' <= ch && ch <=
'z')
1789 if (strchr(
"0123456789+-_.", ch))
1804 for (i = 0; i < ctx->
tok.
len; i++) {
1810 while (p < ctx->stop) {
1813 for (p++; p < ctx->
stop && *p !=
'\n'; p++)
1818 if (dotisspecial && *p ==
'.') {
1861 if (keyidx < tab->nkval)
1862 return tab->
kval[keyidx]->
key;
1864 keyidx -= tab->
nkval;
1865 if (keyidx < tab->narr)
1866 return tab->
arr[keyidx]->
key;
1868 keyidx -= tab->
narr;
1869 if (keyidx < tab->ntab)
1870 return tab->
tab[keyidx]->
key;
1877 for (i = 0; i < tab->
nkval; i++) {
1878 if (0 == strcmp(key, tab->
kval[i]->
key))
1881 for (i = 0; i < tab->
narr; i++) {
1882 if (0 == strcmp(key, tab->
arr[i]->
key))
1885 for (i = 0; i < tab->
ntab; i++) {
1886 if (0 == strcmp(key, tab->
tab[i]->
key))
1894 for (i = 0; i < tab->
nkval; i++) {
1895 if (0 == strcmp(key, tab->
kval[i]->
key))
1903 for (i = 0; i < tab->
narr; i++) {
1904 if (0 == strcmp(key, tab->
arr[i]->
key))
1912 for (i = 0; i < tab->
ntab; i++) {
1913 if (0 == strcmp(key, tab->
tab[i]->
key))
1920 return (0 <= idx && idx < arr->nitem) ? arr->
item[idx].
val : 0;
1926 if (arr->
kind !=
'v')
1929 if (arr->
nitem == 0)
1938 return arr ? arr->
key : (
const char *)NULL;
1948 return tab ? tab->
key : (
const char *)NULL;
1952 return (0 <= idx && idx < arr->nitem) ? arr->
item[idx].
arr : 0;
1956 return (0 <= idx && idx < arr->nitem) ? arr->
item[idx].
tab : 0;
1965 const char *p = src_;
1966 int must_parse_time = 0;
1968 memset(ret, 0,
sizeof(*ret));
1979 if (0 ==
scan_date(p, year, month, day)) {
1987 if (*p !=
'T' && *p !=
't' && *p !=
' ')
1989 must_parse_time = 1;
1995 if (0 ==
scan_time(p, hour, minute, second)) {
2014 if (*p ==
'Z' || *p ==
'z') {
2019 }
else if (*p ==
'+' || *p ==
'-') {
2022 if (!(isdigit(p[0]) && isdigit(p[1])))
2030 if (!(isdigit(p[0]) && isdigit(p[1])))
2043 if (must_parse_time && !ret->
hour)
2054 int *ret = ret_ ? ret_ : &dummy;
2056 if (0 == strcmp(src,
"true")) {
2060 if (0 == strcmp(src,
"false")) {
2074 char *q = p +
sizeof(buf);
2075 const char *s = src;
2078 int64_t *ret = ret_ ? ret_ : &dummy;
2081 if (s[0] ==
'+' || s[0] ==
'-')
2113 while (*s && p < q) {
2137 *ret = strtoll(buf, &endp, base);
2138 return (errno || *endp) ? -1 : 0;
2146 char *q = p + buflen;
2147 const char *s = src;
2149 double *ret = ret_ ? ret_ : &dummy;
2152 if (s[0] ==
'+' || s[0] ==
'-')
2162 char *dot = strchr(s,
'.');
2164 if (dot == s || !isdigit(dot[-1]) || !isdigit(dot[1]))
2170 if (s[0] ==
'0' && s[1] && !strchr(
"eE.", s[1]))
2174 while (*s && p < q) {
2196 *ret = strtod(buf, &endp);
2197 return (errno || *endp) ? -1 : 0;
2215 int srclen = strlen(src);
2216 if (!(qchar ==
'\'' || qchar ==
'"')) {
2221 if (qchar == src[1] && qchar == src[2]) {
2224 sq = src + srclen - 3;
2226 if (!(sp <= sq && sq[0] == qchar && sq[1] == qchar && sq[2] == qchar))
2232 else if (sp[0] ==
'\r' && sp[1] ==
'\n')
2237 sq = src + srclen - 1;
2239 if (!(sp <= sq && *sq == qchar))
2243 if (qchar ==
'\'') {
2249 return *ret ? 0 : -1;
2254 memset(&ret, 0,
sizeof(ret));
2261 memset(&ret, 0,
sizeof(ret));
2268 memset(&ret, 0,
sizeof(ret));
2275 memset(&ret, 0,
sizeof(ret));
2283 memset(&ret, 0,
sizeof(ret));
2312 memset(&ret, 0,
sizeof(ret));
2322 memset(&ret, 0,
sizeof(ret));
2329 memset(&ret, 0,
sizeof(ret));
2336 memset(&ret, 0,
sizeof(ret));
2344 memset(&ret, 0,
sizeof(ret));
2374 for (;
'0' <= *p && *p <=
'9'; p++, unit /= 10) {
2375 ret += (*p -
'0') * unit;
struct context_t::@2 tpath
struct toml_timestamp_t::@0 __buffer
static int e_forbid(context_t *ctx, int lineno, const char *msg)
int toml_table_ntab(const toml_table_t *tab)
toml_datum_t toml_bool_at(const toml_array_t *arr, int idx)
static void xfree_arr(toml_array_t *p)
static void(* ppfree)(void *)
static void * CALLOC(size_t nmemb, size_t sz)
static int valtype(const char *val)
static int e_keyexists(context_t *ctx, int lineno)
static int parse_array(context_t *ctx, toml_array_t *arr)
toml_table_t * toml_parse_file(FILE *fp, char *errbuf, int errbufsz)
static int skip_newlines(context_t *ctx, int isdotspecial)
static int parse_select(context_t *ctx)
static toml_table_t * create_table_in_array(context_t *ctx, toml_array_t *parent)
static void xfree(const void *x)
static int check_key(toml_table_t *tab, const char *key, toml_keyval_t **ret_val, toml_array_t **ret_arr, toml_table_t **ret_tab)
static toml_array_t * create_array_in_array(context_t *ctx, toml_array_t *parent)
char toml_array_type(const toml_array_t *arr)
void toml_set_memutil(void *(*xxmalloc)(size_t), void(*xxfree)(void *))
toml_datum_t toml_string_in(const toml_table_t *arr, const char *key)
toml_datum_t toml_int_at(const toml_array_t *arr, int idx)
toml_array_t * toml_array_in(const toml_table_t *tab, const char *key)
static int walk_tabpath(context_t *ctx)
static int key_kind(toml_table_t *tab, const char *key)
toml_datum_t toml_double_at(const toml_array_t *arr, int idx)
int toml_table_nkval(const toml_table_t *tab)
const char * toml_array_key(const toml_array_t *arr)
char toml_array_kind(const toml_array_t *arr)
int toml_rtob(toml_raw_t src, int *ret_)
static int next_token(context_t *ctx, int dotisspecial)
static int scan_string(context_t *ctx, char *p, int lineno, int dotisspecial)
static int scan_digits(const char *p, int n)
int toml_rtos(toml_raw_t src, char **ret)
static char * STRDUP(const char *s)
int toml_array_nelem(const toml_array_t *arr)
static int eat_token(context_t *ctx, tokentype_t typ, int isdotspecial, const char *fline)
toml_raw_t toml_raw_at(const toml_array_t *arr, int idx)
static toml_array_t * create_keyarray_in_table(context_t *ctx, toml_table_t *tab, token_t keytok, char kind)
static void *(* ppmalloc)(size_t)
toml_datum_t toml_double_in(const toml_table_t *arr, const char *key)
toml_datum_t toml_int_in(const toml_table_t *arr, const char *key)
static int parse_keyval(context_t *ctx, toml_table_t *tab)
static void set_eof(context_t *ctx, int lineno)
static void xfree_kval(toml_keyval_t *p)
int toml_key_exists(const toml_table_t *tab, const char *key)
static char * STRNDUP(const char *s, size_t n)
static int scan_date(const char *p, int *YY, int *MM, int *DD)
const char * toml_table_key(const toml_table_t *tab)
int toml_ucs_to_utf8(int64_t code, char buf[6])
static int e_internal(context_t *ctx, const char *fline)
toml_datum_t toml_bool_in(const toml_table_t *arr, const char *key)
int toml_rtoi(toml_raw_t src, int64_t *ret_)
static char * norm_lit_str(const char *src, int srclen, int multiline, char *errbuf, int errbufsz)
static char * normalize_key(context_t *ctx, token_t strtok)
int toml_table_narr(const toml_table_t *tab)
static int fill_tabpath(context_t *ctx)
static int parse_millisec(const char *p, const char **endp)
static void * expand(void *p, int sz, int newsz)
toml_raw_t toml_raw_in(const toml_table_t *tab, const char *key)
toml_table_t * toml_parse(char *conf, char *errbuf, int errbufsz)
static int scan_time(const char *p, int *hh, int *mm, int *ss)
const char * toml_key_in(const toml_table_t *tab, int keyidx)
void toml_free(toml_table_t *tab)
static int e_badkey(context_t *ctx, int lineno)
static int parse_inline_table(context_t *ctx, toml_table_t *tab)
toml_table_t * toml_table_in(const toml_table_t *tab, const char *key)
static toml_arritem_t * expand_arritem(toml_arritem_t *p, int n)
int toml_rtots(toml_raw_t src_, toml_timestamp_t *ret)
static void set_token(context_t *ctx, tokentype_t tok, int lineno, char *ptr, int len)
static toml_table_t * create_keytable_in_table(context_t *ctx, toml_table_t *tab, token_t keytok)
toml_datum_t toml_timestamp_in(const toml_table_t *arr, const char *key)
int toml_rtod_ex(toml_raw_t src, double *ret_, char *buf, int buflen)
static int e_syntax(context_t *ctx, int lineno, const char *msg)
static toml_arritem_t * create_value_in_array(context_t *ctx, toml_array_t *parent)
int toml_rtod(toml_raw_t src, double *ret_)
int toml_utf8_to_ucs(const char *orig, int len, int64_t *ret)
static char * norm_basic_str(const char *src, int srclen, int multiline, char *errbuf, int errbufsz)
static toml_keyval_t * create_keyval_in_table(context_t *ctx, toml_table_t *tab, token_t keytok)
toml_table_t * toml_table_at(const toml_array_t *arr, int idx)
static int e_outofmemory(context_t *ctx, const char *fline)
toml_datum_t toml_string_at(const toml_array_t *arr, int idx)
toml_array_t * toml_array_at(const toml_array_t *arr, int idx)
static void ** expand_ptrarr(void **p, int n)
static void xfree_tab(toml_table_t *p)
toml_datum_t toml_timestamp_at(const toml_array_t *arr, int idx)