add config support

This commit is contained in:
2026-07-30 13:18:41 +02:00
parent 215ed9705e
commit dc1aa5e5b6
124 changed files with 7402 additions and 8 deletions
@@ -0,0 +1,2 @@
/driver
/out
@@ -0,0 +1,21 @@
CFLAGS := -O0 -g -fsanitize=address,undefined -std=c17 -Wmissing-declarations -Wall -Wextra -MMD
all: driver
driver: scankey.c
$(CC) $(CFLAGS) -o $@ scankey.c
test: all
bash run.sh
-include driver.d
clean:
rm -f *.o *.d driver
distclean: clean
format:
clang-format -i *.[ch]
.PHONY: all clean distclean format test
@@ -0,0 +1,5 @@
str1 =
# comment
str2 #comment
@@ -0,0 +1,6 @@
"title" =
'title' =
bare_key =
bare-key =
1234 =
@@ -0,0 +1,4 @@
apple.type =
3.14159 =
1.2 .3 . 4 =
@@ -0,0 +1,7 @@
[table-1]
[dog."tater.man"]
[a.b.c] # this is best practice
[ d.e.f ] # same as [d.e.f]
[ g . h . i ] # same as [g.h.i]
[ j . "ʞ" . 'l' ] # same as [j."ʞ".'l']
@@ -0,0 +1,7 @@
# [x] you
# [x.y] don't
# [x.y.z] need these
[x.y.z.w] # for this to work
[x] # defining a super-table afterward is ok
@@ -0,0 +1,5 @@
name { # error
name } # error
name [ # error
name ] # error
@@ -0,0 +1,3 @@
[[products.1]]
[[products.2]]
@@ -0,0 +1,3 @@
café =
ñoño =
日本語 =
@@ -0,0 +1,20 @@
#!/bin/bash
mkdir -p out
echo
echo =========================
echo == scankey test
echo =========================
for fname in {1..100}; do
IN="in/$fname"
if [ -f $IN ]; then
echo test $fname
OUT="out/$fname.out"
GOOD="good/$fname.out"
./driver $IN &> $OUT
diff $GOOD $OUT || { echo '--- FAILED ---'; exit 1; }
fi
done
echo DONE
@@ -0,0 +1,127 @@
#include "../../src/tomlc17.c"
#include <stdlib.h>
const char **g_argv = 0;
int g_argc = 0;
static void usage() {
fprintf(stderr, "Usage: %s fname\n", g_argv[0]);
exit(1);
}
static void printspecial(const char *p, int n) {
for (int i = 0; i < n; i++, p++) {
int ch = (*p == '\n') ? '_' : *p;
putchar(ch);
}
}
static void printtok(char *content, const token_t tok) {
// clang-format off
#define CASESTR(x) case TOK_ ## x: s = #x; break
// clang-format on
char *s = 0;
switch (tok.toktyp) {
CASESTR(DOT);
CASESTR(EQUAL);
CASESTR(COMMA);
CASESTR(LBRACK);
CASESTR(LLBRACK);
CASESTR(RBRACK);
CASESTR(RRBRACK);
CASESTR(LBRACE);
CASESTR(RBRACE);
CASESTR(STRING);
CASESTR(MLSTRING);
CASESTR(LITSTRING);
CASESTR(MLLITSTRING);
CASESTR(TIME);
CASESTR(DATE);
CASESTR(DATETIME);
CASESTR(DATETIMETZ);
CASESTR(INTEGER);
CASESTR(FLOAT);
CASESTR(BOOL);
CASESTR(LIT);
CASESTR(ENDL);
CASESTR(FIN);
}
printf("%s %ld %d ", s, tok.str.ptr - content, tok.str.len);
printspecial(tok.str.ptr, tok.str.len);
printf("\n");
}
static char *readfile(const char *fname, int *ret_len) {
FILE *fp = fopen(fname, "r");
if (!fp) {
perror("fopen");
exit(1);
}
// Seek to the end of the file to determine its size
if (fseek(fp, 0, SEEK_END) != 0) {
perror("fseek");
exit(1);
}
long file_size = ftell(fp);
if (file_size == -1) {
perror("ftell");
exit(1);
}
rewind(fp); // Go back to the beginning of the file
// Allocate memory for the file content, plus one for the null terminator
char *content = malloc(file_size + 1);
if (!content) {
perror("out of memory");
exit(1);
}
// Read the file into the buffer
size_t read_size = fread(content, 1, file_size, fp);
if (read_size != (size_t)file_size) {
perror("fread");
exit(1);
}
content[file_size] = '\0'; // Null-terminate the string
fclose(fp);
*ret_len = file_size;
return content;
}
int main(int argc, const char *argv[]) {
g_argc = argc;
g_argv = argv;
if (argc != 2) {
usage();
}
int len;
char *content = readfile(argv[1], &len);
char errbuf[200];
scanner_t scanner;
scanner_t *sp = &scanner;
scan_init(sp, content, len, errbuf, sizeof(errbuf));
for (;;) {
(void)scan_value; // silent compiler
token_t tok;
if (scan_key(sp, &tok)) {
break;
}
if (tok.toktyp == TOK_FIN) {
break;
}
printtok(content, tok);
}
if (sp->errmsg) {
printf("ERROR: %s (line %d)\n", sp->errmsg, sp->lineno);
exit(1);
}
free(content);
return 0;
}