27#define _POSIX_C_SOURCE 200809L
38static void *(*ppmalloc)(size_t) =
malloc;
48#define ALIGN8(sz) (((sz) + 7) & ~7)
49#define MALLOC(a) ppmalloc(a)
50#define FREE(a) ppfree(a)
52#define malloc(x) error - forbidden - use MALLOC instead
53#define free(x) error - forbidden - use FREE instead
54#define calloc(x, y) error - forbidden - use CALLOC instead
56static void *
CALLOC(
size_t nmemb,
size_t sz) {
57 int nb =
ALIGN8(sz) * nmemb;
67#define strdup(x) error - forbidden - use STRDUP instead
81#define strndup(x) error - forbiden - use STRNDUP instead
83static char *
STRNDUP(
const char *s,
size_t n) {
84 size_t len = strnlen(s, n);
98 const unsigned char *buf = (
const unsigned char *)orig;
114 if (0x6 == (i >> 5)) {
118 for (
int j = 0; j < 1; j++) {
122 v = (v << 6) | (i & 0x3f);
124 return *ret = v, (
const char *)buf - orig;
130 if (0xE == (i >> 4)) {
134 for (
int j = 0; j < 2; j++) {
138 v = (v << 6) | (i & 0x3f);
140 return *ret = v, (
const char *)buf - orig;
146 if (0x1E == (i >> 3)) {
150 for (
int j = 0; j < 3; j++) {
154 v = (v << 6) | (i & 0x3f);
156 return *ret = v, (
const char *)buf - orig;
162 if (0x3E == (i >> 2)) {
166 for (
int j = 0; j < 4; j++) {
170 v = (v << 6) | (i & 0x3f);
172 return *ret = v, (
const char *)buf - orig;
178 if (0x7e == (i >> 1)) {
182 for (
int j = 0; j < 5; j++) {
186 v = (v << 6) | (i & 0x3f);
188 return *ret = v, (
const char *)buf - orig;
205 if (0xd800 <= code && code <= 0xdfff)
207 if (0xfffe <= code && code <= 0xffff)
216 buf[0] = (
unsigned char)code;
223 if (code <= 0x000007FF) {
224 buf[0] = (
unsigned char)(0xc0 | (code >> 6));
225 buf[1] = (
unsigned char)(0x80 | (code & 0x3f));
232 if (code <= 0x0000FFFF) {
233 buf[0] = (
unsigned char)(0xe0 | (code >> 12));
234 buf[1] = (
unsigned char)(0x80 | ((code >> 6) & 0x3f));
235 buf[2] = (
unsigned char)(0x80 | (code & 0x3f));
242 if (code <= 0x001FFFFF) {
243 buf[0] = (
unsigned char)(0xf0 | (code >> 18));
244 buf[1] = (
unsigned char)(0x80 | ((code >> 12) & 0x3f));
245 buf[2] = (
unsigned char)(0x80 | ((code >> 6) & 0x3f));
246 buf[3] = (
unsigned char)(0x80 | (code & 0x3f));
253 if (code <= 0x03FFFFFF) {
254 buf[0] = (
unsigned char)(0xf8 | (code >> 24));
255 buf[1] = (
unsigned char)(0x80 | ((code >> 18) & 0x3f));
256 buf[2] = (
unsigned char)(0x80 | ((code >> 12) & 0x3f));
257 buf[3] = (
unsigned char)(0x80 | ((code >> 6) & 0x3f));
258 buf[4] = (
unsigned char)(0x80 | (code & 0x3f));
265 if (code <= 0x7FFFFFFF) {
266 buf[0] = (
unsigned char)(0xfc | (code >> 30));
267 buf[1] = (
unsigned char)(0x80 | ((code >> 24) & 0x3f));
268 buf[2] = (
unsigned char)(0x80 | ((code >> 18) & 0x3f));
269 buf[3] = (
unsigned char)(0x80 | ((code >> 12) & 0x3f));
270 buf[4] = (
unsigned char)(0x80 | ((code >> 6) & 0x3f));
271 buf[5] = (
unsigned char)(0x80 | (code & 0x3f));
325static inline void xfree(
const void *x) {
327 FREE((
void *)(intptr_t)x);
371#define STRINGIFY(x) #x
372#define TOSTRING(x) STRINGIFY(x)
373#define FLINE __FILE__ ":" TOSTRING(__LINE__)
381 snprintf(ctx->
errbuf, ctx->
errbufsz,
"ERROR: out of memory (%s)", fline);
386 snprintf(ctx->
errbuf, ctx->
errbufsz,
"internal error (%s)", fline);
401 snprintf(ctx->
errbuf, ctx->
errbufsz,
"line %d: key exists", lineno);
410static void *
expand(
void *p,
int sz,
int newsz) {
423 void **s =
MALLOC((n + 1) *
sizeof(
void *));
429 memcpy(s, p, n *
sizeof(
void *));
440 memset(&pp[n], 0,
sizeof(pp[n]));
445 char *errbuf,
int errbufsz) {
449 const char *sp = src;
450 const char *sq = src + srclen;
455 if (off >= max - 10) {
456 int newmax = max + 50;
457 char *x =
expand(dst, max, newmax);
460 snprintf(errbuf, errbufsz,
"out of memory");
473 if ((0 <= ch && ch <= 0x08) || (0x0a <= ch && ch <= 0x1f) || (ch == 0x7f)) {
474 if (!(multiline && (ch ==
'\r' || ch ==
'\n'))) {
476 snprintf(errbuf, errbufsz,
"invalid char U+%04x", ch);
494 char *errbuf,
int errbufsz) {
498 const char *sp = src;
499 const char *sq = src + srclen;
504 if (off >= max - 10) {
505 int newmax = max + 50;
506 char *x =
expand(dst, max, newmax);
509 snprintf(errbuf, errbufsz,
"out of memory");
524 if ((0 <= ch && ch <= 0x08) || (0x0a <= ch && ch <= 0x1f) ||
526 if (!(multiline && (ch ==
'\r' || ch ==
'\n'))) {
528 snprintf(errbuf, errbufsz,
"invalid char U+%04x", ch);
540 snprintf(errbuf, errbufsz,
"last backslash is invalid");
549 if (sp[strspn(sp,
" \t\r")] ==
'\n') {
551 sp += strspn(sp,
" \t\r\n");
562 int nhex = (ch ==
'u' ? 4 : 8);
563 for (
int i = 0; i < nhex; i++) {
565 snprintf(errbuf, errbufsz,
"\\%c expects %d hex chars", ch, nhex);
570 int v = (
'0' <= ch && ch <=
'9')
572 : ((
'A' <= ch && ch <=
'F') ? ch -
'A' + 10 : -1);
574 snprintf(errbuf, errbufsz,
"invalid hex chars for \\u or \\U");
582 snprintf(errbuf, errbufsz,
"illegal ucs code in \\u or \\U");
612 snprintf(errbuf, errbufsz,
"illegal escape char \\%c", ch);
627 const char *sp = strtok.
ptr;
628 const char *sq = strtok.
ptr + strtok.
len;
629 int lineno = strtok.
lineno;
635 if (ch ==
'\'' || ch ==
'\"') {
638 if (sp[1] == ch && sp[2] == ch) {
646 if (!(ret =
STRNDUP(sp, sq - sp))) {
660 if (strchr(ret,
'\n')) {
670 for (xp = sp; xp != sq; xp++) {
674 if (k ==
'_' || k ==
'-')
681 if (!(ret =
STRNDUP(sp, sq - sp))) {
709 for (i = 0; i < tab->
nkval; i++) {
710 if (0 == strcmp(key, tab->
kval[i]->
key)) {
711 *ret_val = tab->
kval[i];
715 for (i = 0; i < tab->
narr; i++) {
716 if (0 == strcmp(key, tab->
arr[i]->
key)) {
717 *ret_arr = tab->
arr[i];
721 for (i = 0; i < tab->
ntab; i++) {
722 if (0 == strcmp(key, tab->
tab[i]->
key)) {
723 *ret_tab = tab->
tab[i];
788 if (
check_key(tab, newkey, 0, 0, &dest)) {
866 const int n = parent->
nitem;
874 return &parent->
item[n];
881 const int n = parent->
nitem;
902 int n = parent->
nitem;
952 "newline not allowed in inline table");
966 "newline not allowed in inline table");
987 if (*val ==
'\'' || *val ==
'"')
1023 else if (arr->
kind !=
'v')
1026 char *val = ctx->
tok.
ptr;
1040 if (arr->
nitem == 1)
1054 else if (arr->
kind !=
'a')
1069 else if (arr->
kind !=
't')
1109 "cannot insert new entry into existing table");
1157 assert(keyval->
val == 0);
1206 for (i = 0; i < ctx->
tpath.
top; i++) {
1216 "table path is too deep; max allowed is 10.");
1219 return e_syntax(ctx, lineno,
"invalid or missing key");
1235 return e_syntax(ctx, lineno,
"invalid key");
1242 return e_syntax(ctx, lineno,
"empty table selector");
1254 for (
int i = 0; i < ctx->
tpath.
top; i++) {
1255 const char *key = ctx->
tpath.
key[i];
1260 switch (
check_key(curtab, key, &nextval, &nextarr, &nexttab)) {
1267 if (nextarr->
kind !=
't')
1270 if (nextarr->
nitem == 0)
1280 int n = curtab->
ntab;
1291 if (0 == (base[n]->key =
STRDUP(key)))
1294 nexttab = curtab->
tab[curtab->
ntab++];
1363 if (arr->
kind !=
't')
1412 memset(&ctx, 0,
sizeof(ctx));
1462 e_syntax(&ctx, tok.lineno,
"syntax error");
1468 for (
int i = 0; i < ctx.
tpath.
top; i++)
1474 for (
int i = 0; i < ctx.
tpath.
top; i++)
1489 int xsz = bufsz + 1000;
1490 char *x =
expand(buf, bufsz, xsz);
1492 snprintf(errbuf, errbufsz,
"out of memory");
1501 int n = fread(buf + off, 1, bufsz - off, fp);
1503 snprintf(errbuf, errbufsz,
"%s",
1504 errno ? strerror(errno) :
"Error reading file");
1513 int xsz = bufsz + 1;
1514 char *x =
expand(buf, bufsz, xsz);
1516 snprintf(errbuf, errbufsz,
"out of memory");
1546 const int n = p->
nitem;
1547 for (
int i = 0; i < n; i++) {
1568 for (i = 0; i < p->
nkval; i++)
1572 for (i = 0; i < p->
narr; i++)
1576 for (i = 0; i < p->
ntab; i++)
1604 for (; n > 0 && isdigit(*p); n--, p++) {
1605 ret = 10 * ret + (*p -
'0');
1607 return n ? -1 : ret;
1610static int scan_date(
const char *p,
int *YY,
int *MM,
int *DD) {
1611 int year, month, day;
1613 month = (year >= 0 && p[4] ==
'-') ?
scan_digits(p + 5, 2) : -1;
1614 day = (month >= 0 && p[7] ==
'-') ?
scan_digits(p + 8, 2) : -1;
1621 return (year >= 0 && month >= 0 && day >= 0) ? 0 : -1;
1624static int scan_time(
const char *p,
int *hh,
int *mm,
int *ss) {
1625 int hour, minute, second;
1627 minute = (hour >= 0 && p[2] ==
':') ?
scan_digits(p + 3, 2) : -1;
1628 second = (minute >= 0 && p[5] ==
':') ?
scan_digits(p + 6, 2) : -1;
1635 return (hour >= 0 && minute >= 0 && second >= 0) ? 0 : -1;
1640 if (0 == strncmp(p,
"'''", 3)) {
1644 q = strstr(q,
"'''");
1646 return e_syntax(ctx, lineno,
"unterminated triple-s-quote");
1648 while (q[3] ==
'\'')
1657 if (0 == strncmp(p,
"\"\"\"", 3)) {
1661 q = strstr(q,
"\"\"\"");
1663 return e_syntax(ctx, lineno,
"unterminated triple-d-quote");
1665 if (q[-1] ==
'\\') {
1669 while (q[3] ==
'\"')
1678 for (p += 3; p < q; p++) {
1681 if (strchr(
"btnfr\"\\", *p))
1691 if (p[strspn(p,
" \t\r")] ==
'\n')
1693 return e_syntax(ctx, lineno,
"bad escape char");
1697 if (strchr(
"0123456789ABCDEF", *p))
1699 return e_syntax(ctx, lineno,
"expect hex char");
1707 return e_syntax(ctx, lineno,
"expect an escape char");
1709 return e_syntax(ctx, lineno,
"expected more hex char");
1716 for (p++; *p && *p !=
'\n' && *p !=
'\''; p++)
1719 return e_syntax(ctx, lineno,
"unterminated s-quote");
1729 for (p++; *p; p++) {
1732 if (strchr(
"btnfr\"\\", *p))
1742 return e_syntax(ctx, lineno,
"bad escape char");
1746 if (strchr(
"0123456789ABCDEF", *p))
1748 return e_syntax(ctx, lineno,
"expect hex char");
1755 if (p[1] ==
'\'' && p[2] ==
'\'') {
1756 return e_syntax(ctx, lineno,
"triple-s-quote inside string lit");
1766 return e_syntax(ctx, lineno,
"unterminated quote");
1776 p += strspn(p,
"0123456789.:+-Tt Zz");
1778 for (; p[-1] ==
' '; p--)
1786 for (; *p && *p !=
'\n'; p++) {
1788 if (ch ==
'.' && dotisspecial)
1790 if (
'A' <= ch && ch <=
'Z')
1792 if (
'a' <= ch && ch <=
'z')
1794 if (strchr(
"0123456789+-_.", ch))
1809 for (i = 0; i < ctx->
tok.
len; i++) {
1815 while (p < ctx->stop) {
1818 for (p++; p < ctx->
stop && *p !=
'\n'; p++)
1823 if (dotisspecial && *p ==
'.') {
1866 if (keyidx < tab->nkval)
1867 return tab->
kval[keyidx]->
key;
1869 keyidx -= tab->
nkval;
1870 if (keyidx < tab->narr)
1871 return tab->
arr[keyidx]->
key;
1873 keyidx -= tab->
narr;
1874 if (keyidx < tab->ntab)
1875 return tab->
tab[keyidx]->
key;
1882 for (i = 0; i < tab->
nkval; i++) {
1883 if (0 == strcmp(key, tab->
kval[i]->
key))
1886 for (i = 0; i < tab->
narr; i++) {
1887 if (0 == strcmp(key, tab->
arr[i]->
key))
1890 for (i = 0; i < tab->
ntab; i++) {
1891 if (0 == strcmp(key, tab->
tab[i]->
key))
1899 for (i = 0; i < tab->
nkval; i++) {
1900 if (0 == strcmp(key, tab->
kval[i]->
key))
1908 for (i = 0; i < tab->
narr; i++) {
1909 if (0 == strcmp(key, tab->
arr[i]->
key))
1917 for (i = 0; i < tab->
ntab; i++) {
1918 if (0 == strcmp(key, tab->
tab[i]->
key))
1925 return (0 <= idx && idx < arr->
nitem) ? arr->
item[idx].
val : 0;
1931 if (arr->
kind !=
'v')
1934 if (arr->
nitem == 0)
1943 return arr ? arr->
key : (
const char *)NULL;
1953 return tab ? tab->
key : (
const char *)NULL;
1957 return (0 <= idx && idx < arr->
nitem) ? arr->
item[idx].
arr : 0;
1961 return (0 <= idx && idx < arr->
nitem) ? arr->
item[idx].
tab : 0;
1970 const char *p = src_;
1971 int must_parse_time = 0;
1973 memset(ret, 0,
sizeof(*ret));
1984 if (0 ==
scan_date(p, year, month, day)) {
1992 if (*p !=
'T' && *p !=
't' && *p !=
' ')
1994 must_parse_time = 1;
2000 if (0 ==
scan_time(p, hour, minute, second)) {
2019 if (*p ==
'Z' || *p ==
'z') {
2024 }
else if (*p ==
'+' || *p ==
'-') {
2027 if (!(isdigit(p[0]) && isdigit(p[1])))
2035 if (!(isdigit(p[0]) && isdigit(p[1])))
2048 if (must_parse_time && !ret->
hour)
2059 int *ret = ret_ ? ret_ : &dummy;
2061 if (0 == strcmp(src,
"true")) {
2065 if (0 == strcmp(src,
"false")) {
2079 char *q = p +
sizeof(buf);
2080 const char *s = src;
2083 int64_t *ret = ret_ ? ret_ : &dummy;
2086 if (s[0] ==
'+' || s[0] ==
'-')
2118 while (*s && p < q) {
2142 *ret = strtoll(buf, &endp, base);
2143 return (errno || *endp) ? -1 : 0;
2151 char *q = p + buflen;
2152 const char *s = src;
2154 double *ret = ret_ ? ret_ : &dummy;
2157 if (s[0] ==
'+' || s[0] ==
'-')
2167 char *
dot = strchr(s,
'.');
2169 if (
dot == s || !isdigit(
dot[-1]) || !isdigit(
dot[1]))
2175 if (s[0] ==
'0' && s[1] && !strchr(
"eE.", s[1]))
2179 while (*s && p < q) {
2201 *ret = strtod(buf, &endp);
2202 return (errno || *endp) ? -1 : 0;
2221 int srclen = strlen(src);
2222 if (!(qchar ==
'\'' || qchar ==
'"')) {
2227 if (qchar == src[1] && qchar == src[2]) {
2230 sq = src + srclen - 3;
2232 if (!(sp <= sq && sq[0] == qchar && sq[1] == qchar && sq[2] == qchar)) {
2240 else if (sp[0] ==
'\r' && sp[1] ==
'\n')
2245 sq = src + srclen - 1;
2246 if (!(sp <= sq && *sq == qchar)) {
2256 if (qchar ==
'\'') {
2262 return *ret ? 0 : -1;
2267 memset(&ret, 0,
sizeof(ret));
2274 memset(&ret, 0,
sizeof(ret));
2281 memset(&ret, 0,
sizeof(ret));
2288 memset(&ret, 0,
sizeof(ret));
2296 memset(&ret, 0,
sizeof(ret));
2325 memset(&ret, 0,
sizeof(ret));
2335 memset(&ret, 0,
sizeof(ret));
2342 memset(&ret, 0,
sizeof(ret));
2349 memset(&ret, 0,
sizeof(ret));
2357 memset(&ret, 0,
sizeof(ret));
2387 for (;
'0' <= *p && *p <=
'9'; p++, unit /= 10) {
2388 ret += (*p -
'0') * unit;
static int nitem(const double *range)
double dot(const double *a, const double *b, int n)
Inner product of vectors.
struct context_t::@343266115336034272003212003032200377137064012210 tpath
union toml_datum_t::@034014057205341050151107111126247137201246022032 u
struct toml_timestamp_t::@140140272151246031144276257317172000233346153225 __buffer
static int e_forbid(context_t *ctx, int lineno, const char *msg)
toml_table_t * toml_table_at(const toml_array_t *arr, int idx)
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 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)
static int skip_newlines(context_t *ctx, int isdotspecial)
static int parse_select(context_t *ctx)
static void ** expand_ptrarr(void **p, int n)
static void xfree(const void *x)
static void *(* ppmalloc)(size_t)
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)
char toml_array_type(const toml_array_t *arr)
static char * STRDUP(const char *s)
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)
static int walk_tabpath(context_t *ctx)
static int key_kind(toml_table_t *tab, const char *key)
toml_array_t * toml_array_in(const 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)
char toml_array_kind(const toml_array_t *arr)
static toml_array_t * create_keyarray_in_table(context_t *ctx, toml_table_t *tab, token_t keytok, char kind)
static toml_table_t * create_keytable_in_table(context_t *ctx, toml_table_t *tab, token_t keytok)
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)
static toml_arritem_t * expand_arritem(toml_arritem_t *p, int n)
int toml_rtos(toml_raw_t src, char **ret)
static void * CALLOC(size_t nmemb, size_t sz)
static void * expand(void *p, int sz, int newsz)
const char * toml_table_key(const toml_table_t *tab)
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_array_in_array(context_t *ctx, toml_array_t *parent)
const char * toml_key_in(const toml_table_t *tab, int keyidx)
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 char * STRNDUP(const char *s, size_t n)
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)
const char * toml_array_key(const toml_array_t *arr)
int toml_key_exists(const toml_table_t *tab, const char *key)
toml_table_t * toml_table_in(const toml_table_t *tab, const char *key)
static int scan_date(const char *p, int *YY, int *MM, int *DD)
int toml_ucs_to_utf8(int64_t code, char buf[6])
static toml_table_t * create_table_in_array(context_t *ctx, toml_array_t *parent)
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 * 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)
toml_raw_t toml_raw_in(const toml_table_t *tab, const char *key)
static toml_keyval_t * create_keyval_in_table(context_t *ctx, toml_table_t *tab, token_t keytok)
static int scan_time(const char *p, int *hh, int *mm, int *ss)
void toml_free(toml_table_t *tab)
static int e_badkey(context_t *ctx, int lineno)
static char * norm_basic_str(const char *src, int srclen, int multiline, char *errbuf, int errbufsz)
static toml_arritem_t * create_value_in_array(context_t *ctx, toml_array_t *parent)
static int parse_inline_table(context_t *ctx, toml_table_t *tab)
toml_table_t * toml_parse_file(FILE *fp, char *errbuf, int errbufsz)
toml_table_t * toml_parse(char *conf, char *errbuf, int errbufsz)
static char * norm_lit_str(const char *src, int srclen, int multiline, char *errbuf, int errbufsz)
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)
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)
int toml_rtod(toml_raw_t src, double *ret_)
int toml_utf8_to_ucs(const char *orig, int len, int64_t *ret)
toml_array_t * toml_array_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)
static void xfree_tab(toml_table_t *p)
toml_datum_t toml_timestamp_at(const toml_array_t *arr, int idx)