From 3d2ae2103e4a3cc400d557e282d39e864d7aa52c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=8Ddiohabara=E5=8D=8D?= Date: Wed, 2 Aug 2023 13:30:12 -0500 Subject: [PATCH] wip --- .gitignore | 6 +- .vscode/settings.json | 14 - Makefile | 73 ++--- ccc.h | 63 +++++ parse.c | 147 +++++----- test/helper.c | 5 + tests => test/test.c | 621 +++++++++--------------------------------- tokenize.c | 2 +- 8 files changed, 323 insertions(+), 608 deletions(-) delete mode 100644 .vscode/settings.json create mode 100644 test/helper.c rename tests => test/test.c (67%) diff --git a/.gitignore b/.gitignore index fa3a3af..9fb6287 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,10 @@ tmp* *.vsix # for debug -test +.vscode/ +tests ext -test.* +test.s ext.* .gdb_history @@ -26,3 +27,4 @@ ext.* stage1/ stage2/ stage3/ +Makefile diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 0ca462a..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "files.associations": { - "*.v": "coq", - "*.asm": "gas", - "*.ts": "typescript", - "*.pl": "prolog", - "*.plt": "prolog", - "stdbool.h": "c", - "tests": "cpp", - "initializer_list": "c", - "string.h": "c" - }, - "C_Cpp.default.configurationProvider": "ms-vscode.makefile-tools" -} \ No newline at end of file diff --git a/Makefile b/Makefile index d6d05bc..e04da48 100644 --- a/Makefile +++ b/Makefile @@ -19,20 +19,12 @@ lint: clang-format -i ./*.c clang-format -i ./*.h -lintx: - docker run --platform=linux/amd64 -v "${PWD}:/src" -w/src ccc make lint - test: ccc - ./ccc tests > tmp.s - echo 'int char_fn() { return 257; }' | gcc -xc -c -o tmp2.o - - echo 'int ext1 = 5; int *ext2 = &ext1;' | gcc -xc -c -o tmp3.o - - echo 'int ext_fn1(int x) { return x; }; int ext_fn2(int x) { return x;}' | gcc -xc -c -o tmp4.o - - gcc -static -o tmp tmp.s tmp2.o tmp3.o tmp4.o + ./ccc test/test.c > tmp.s + cat test/helper.c | gcc -xc -c -o tmp2.o - + gcc -static -o tmp tmp.s tmp2.o ./tmp -testx: - docker run --platform=linux/amd64 -v "${PWD}:/src" -w/src ccc make test - clean: rm -f ccc *.o *~ tmp* stage*/* @@ -43,25 +35,42 @@ clean: # stage2: ccc on X86-64 machine generated by stage1 # stage3: ccc on X86-64 machine generated by stage2 -STAGES = stage1 stage2 stage3 - -define PROCESS_STAGE_RULE -$(1)/%.c: %.c - mkdir -p $(1) - gcc -E -P $$< -o $$@ -endef - -$(foreach stage,$(STAGES),$(eval $(call PROCESS_STAGE_RULE,$(stage)))) - -PROCESSED_SRCS = $(foreach stage,$(STAGES),$(addprefix $(stage)/,$(SRCS))) - -process: $(PROCESSED_SRCS) - ccc-stage1: $(OBJS) - $(CC) -o $@ $(OBJS) $(CFLAGS) - -ccc-stage2: - @echo TODO - -ccc-stage3: - @echo TODO \ No newline at end of file + @rm -rf stage1 + @mkdir stage1 + $(CC) -o stage1/$@ $(OBJS) $(CFLAGS) + +ccc-stage2: ccc-stage1 $(SRCS) + @rm -rf stage2 + @mkdir stage2 + $(CC) -D__ccc_self__ -E -P codegen.c -o stage2/codegen.c + $(CC) -D__ccc_self__ -E -P main.c -o stage2/main.c + $(CC) -D__ccc_self__ -E -P parse.c -o stage2/parse.c + $(CC) -D__ccc_self__ -E -P tokenize.c -o stage2/tokenize.c + $(CC) -D__ccc_self__ -E -P type.c -o stage2/type.c + stage1/ccc-stage1 stage2/codegen.c > stage2/codegen.s + stage1/ccc-stage1 stage2/main.c > stage2/main.s + stage1/ccc-stage1 stage2/parse.c > stage2/parse.s + stage1/ccc-stage1 stage2/tokenize.c > stage2/tokenize.s + stage1/ccc-stage1 stage2/type.c > stage2/type.s + $(CC) -o stage2/$@ + +ccc-stage3: ccc-stage2 $(SRCS) + @rm -rf stage3 + @mkdir stage3 + $(CC) -D__ccc_self__ -E -P type.c -o stage3/type.c + $(CC) -D__ccc_self__ -E -P codegen.c -o stage3/codegen.c + $(CC) -D__ccc_self__ -E -P main.c -o stage3/main.c + $(CC) -D__ccc_self__ -E -P parse.c -o stage3/parse.c + $(CC) -D__ccc_self__ -E -P tokenize.c -o stage3/tokenize.c + stage2/ccc-stage2 stage3/codegen.c > stage3/codegen.s + stage2/ccc-stage2 stage3/main.c > stage3/main.s + stage2/ccc-stage2 stage3/parse.c > stage3/parse.s + stage2/ccc-stage2 stage3/tokenize.c > stage3/tokenize.s + stage2/ccc-stage2 stage3/type.c > stage3/type.s + $(CC) -o stage3/$@ + +test-self-host: ccc-stage1 ccc-stage2 ccc-stage3 + strip stage2/ccc-stage2 + strip stage3/ccc-stage3 + diff -s stage2/ccc-stage2 stage3/ccc-stage3 \ No newline at end of file diff --git a/ccc.h b/ccc.h index f866c4b..142f807 100644 --- a/ccc.h +++ b/ccc.h @@ -1,3 +1,64 @@ +#ifdef __ccc_self__ + +typedef int bool; +typedef int size_t; +typedef void FILE; +typedef void *va_list; + +#define SEEK_SET 0 +#define SEEK_END 2 + +// struct _reent { +// int _errno; +// void *_stdin; +// void *_stdout; +// void *_stderr; +// }; + +extern struct _reent *_impure_ptr; + +#define stdin (_impure_ptr->_stdin) +#define stderr (_impure_ptr->_stderr) + +extern int errno; + +#define __attribute__(x) +#define noreturn + +#define NULL (0) +#define true (1) +#define false (0) +#define static + +#define assert(x) 1 + +int printf(); +int fopen(); +int strncmp(); +int strlen(); +int fprintf(); +char *strerror(); +int vsnprintf(); +int vfprintf(); +void *calloc(); +int isalnum(); +int isspace(); +int snprintf(); +int strstr(); +int strchr(); +int isdigit(); +int strtol(); +void exit(); +int fseek(); +int ftell(); +int fread(); +int fclose(); +int realloc(); +int ferror(); +int feof(); + +#else + #include #include #include @@ -7,6 +68,8 @@ #include #include #include + +#endif typedef struct Type Type; typedef struct Member Member; typedef struct Initializer Initializer; diff --git a/parse.c b/parse.c index abff39f..88ffee0 100644 --- a/parse.c +++ b/parse.c @@ -217,6 +217,78 @@ Program *program() { return prog; } +// global-var +// = type-specifier declarator type-suffix ("=" gvar-initializer)? ";" +void global_var() { + Type *ty = type_specifier(); + bool is_extern = ty->is_extern; + char *name = NULL; + Token *tok = token; + ty = declarator(ty, &name); + ty = type_suffix(ty); + ty->is_extern = is_extern; + + // TODO: write tyepdef here + if (ty->is_typedef) { + expect(";"); + ty->is_typedef = false; + push_scope(name)->type_def = ty; + return; + } + + Var *var = push_var(name, ty, false, tok); + push_scope(name)->var = var; + + if (consume("=")) { + Initializer head; + head.next = NULL; + gvar_initializer(&head, ty); + var->initializer = head.next; + } + expect(";"); +} + +// function = type-specifier declarator "(" params? ")" ("{" stmt* "}" | ";") +// params = param ("," param)* | "void" +// param = type-specifier declarator type-suffix +Function *function() { + locals = NULL; + + Type *ty = type_specifier(); + char *name = NULL; + Token *tok = token; + ty = declarator(ty, &name); + + // Add a function type to the scope + Var *var = push_var(name, func_type(ty), false, tok); + push_scope(name)->var = var; + + // construct a function object + Function *fn = calloc(1, sizeof(Function)); + fn->name = name; + fn->is_static = ty->is_static; + expect("("); + fn->params = read_func_params(); + + if (consume(";")) { + return NULL; + } + + // read function body + Node head; + head.next = NULL; + Node *cur = &head; + expect("{"); + while (!consume("}")) { + cur->next = stmt(); + cur = cur->next; + } + + fn->node = head.next; + fn->locals = locals; + return fn; +} + // type-specifier = builtin-type | struct-decl | typedef-name | enum-specifier // builtin-type = "void" // | "_Bool" @@ -238,6 +310,7 @@ Type *type_specifier() { SHORT = 1 << 7, INT = 1 << 9, LONG = 1 << 11, + UNSIGNED = 1 << 13, }; int base_type = 0; @@ -256,6 +329,8 @@ Type *type_specifier() { is_static = true; } else if (consume("extern")) { is_extern = true; + } else if (consume("const")) { + continue; } else if (consume("void")) { base_type += VOID; } else if (consume("_Bool")) { @@ -268,6 +343,8 @@ Type *type_specifier() { base_type += INT; } else if (consume("long")) { base_type += LONG; + } else if (consume("unsigned")) { + base_type += UNSIGNED; } else if (peek("struct")) { if (base_type || user_type) { break; @@ -575,47 +652,6 @@ VarList *read_func_params() { return head; } -// function = type-specifier declarator "(" params? ")" ("{" stmt* "}" | ";") -// params = param ("," param)* | "void" -// param = type-specifier declarator type-suffix -Function *function() { - locals = NULL; - - Type *ty = type_specifier(); - char *name = NULL; - Token *tok = token; - ty = declarator(ty, &name); - - // Add a function type to the scope - Var *var = push_var(name, func_type(ty), false, tok); - push_scope(name)->var = var; - - // construct a function object - Function *fn = calloc(1, sizeof(Function)); - fn->name = name; - fn->is_static = ty->is_static; - expect("("); - fn->params = read_func_params(); - - if (consume(";")) { - return NULL; - } - - // read function body - Node head; - head.next = NULL; - Node *cur = &head; - expect("{"); - while (!consume("}")) { - cur->next = stmt(); - cur = cur->next; - } - - fn->node = head.next; - fn->locals = locals; - return fn; -} - // Initializer list can end either with "}" or "," followed by "}" to allow a // trailing comm. This function returns true if it looks like we are at the end // of an initializer list @@ -773,29 +809,6 @@ Initializer *gvar_initializer(Initializer *cur, Type *ty) { return new_init_val(cur, size_of(ty, token), addend); } -// global-var -// = type-specifier declarator type-suffix ("=" gvar-initializer)? ";" -void global_var() { - Type *ty = type_specifier(); - bool is_extern = ty->is_extern; - char *name = NULL; - Token *tok = token; - ty = declarator(ty, &name); - ty = type_suffix(ty); - ty->is_extern = is_extern; - - Var *var = push_var(name, ty, false, tok); - push_scope(name)->var = var; - - if (consume("=")) { - Initializer head; - head.next = NULL; - gvar_initializer(&head, ty); - var->initializer = head.next; - } - expect(";"); -} - typedef struct Designator Designator; struct Designator { @@ -995,9 +1008,9 @@ Node *read_expr_stmt() { bool is_typename() { return peek("typedef") || peek("void") || peek("_Bool") || peek("char") || - peek("short") || peek("int") || peek("long") || peek("struct") || - peek("enum") || peek("static") || peek("extern") || - find_typedef(token); + peek("unsigned") || peek("short") || peek("int") || peek("long") || + peek("struct") || peek("enum") || peek("static") || peek("extern") || + peek("const") || find_typedef(token); } // stmt = "return" expr ";" diff --git a/test/helper.c b/test/helper.c new file mode 100644 index 0000000..61e1e2b --- /dev/null +++ b/test/helper.c @@ -0,0 +1,5 @@ +int char_fn() { return 257; } +int ext1 = 5; +int *ext2 = &ext1; +int ext_fn1(int x) { return x; }; +int ext_fn2(int x) { return x; }; \ No newline at end of file diff --git a/tests b/test/test.c similarity index 67% rename from tests rename to test/test.c index 1e5e83e..0af356e 100644 --- a/tests +++ b/test/test.c @@ -99,461 +99,119 @@ int ext_fn1(int x); extern int ext_fn2(int x); int main() { - assert(8, ({ - int a = 3; - int z = 5; - a + z; - }), - "int a=3; int z=5; a+z;"); + assert(8, ({ int a=3; int z=5; a+z; }), "int a=3; int z=5; a+z;"); assert(0, 0, "0"); assert(42, 42, "42"); assert(5, 5, "0"); - assert(41, 12 + 34 - 5, " 12 + 34 - 5 "); + assert(41, 12 + 34 - 5 , " 12 + 34 - 5 "); assert(5, 5, "0"); - assert(15, 5 * (9 - 6), "5*(9-6)"); - assert(4, (3 + 5) / 2, "(3+5)/2"); + assert(15, 5*(9-6), "5*(9-6)"); + assert(4, (3+5)/2, "(3+5)/2"); assert(-10, -10, "0"); assert(10, - -10, "- -10"); - assert(10, - -+10, "- - +10"); - - assert(0, 0 == 1, "0==1"); - assert(1, 42 == 42, "42==42"); - assert(1, 0 != 1, "0!=1"); - assert(0, 42 != 42, "42!=42"); - - assert(1, 0 < 1, "0<1"); - assert(0, 1 < 1, "1<1"); - assert(0, 2 < 1, "2<1"); - assert(1, 0 <= 1, "0<=1"); - assert(1, 1 <= 1, "1<=1"); - assert(0, 2 <= 1, "2<=1"); - - assert(1, 1 > 0, "1>0"); - assert(0, 1 > 1, "1>1"); - assert(0, 1 > 2, "1>2"); - assert(1, 1 >= 0, "1>=0"); - assert(1, 1 >= 1, "1>=1"); - assert(0, 1 >= 2, "1>=2"); - - assert(3, ({ - int a; - a = 3; - a; - }), - "int a; a=3; a;"); - assert(8, ({ - int a; - int z; - a = 3; - z = 5; - a + z; - }), - "int a; int z; a=3; z=5; a+z;"); - assert(3, ({ - int a = 3; - a; - }), - "int a=3; a;"); - assert(8, ({ - int a = 3; - int z = 5; - a + z; - }), - "int a=3; int z=5; a+z;"); - - assert(3, ({ - int foo = 3; - foo; - }), - "int foo=3; foo;"); - assert(8, ({ - int foo123 = 3; - int bar = 5; - foo123 + bar; - }), - "int foo123=3; int bar=5; foo123+bar;"); + assert(10, - - +10, "- - +10"); + + assert(0, 0==1, "0==1"); + assert(1, 42==42, "42==42"); + assert(1, 0!=1, "0!=1"); + assert(0, 42!=42, "42!=42"); + + assert(1, 0<1, "0<1"); + assert(0, 1<1, "1<1"); + assert(0, 2<1, "2<1"); + assert(1, 0<=1, "0<=1"); + assert(1, 1<=1, "1<=1"); + assert(0, 2<=1, "2<=1"); + + assert(1, 1>0, "1>0"); + assert(0, 1>1, "1>1"); + assert(0, 1>2, "1>2"); + assert(1, 1>=0, "1>=0"); + assert(1, 1>=1, "1>=1"); + assert(0, 1>=2, "1>=2"); + + assert(3, ({ int a; a=3; a; }), "int a; a=3; a;"); + assert(8, ({ int a; int z; a=3; z=5; a+z; }), "int a; int z; a=3; z=5; a+z;"); + assert(3, ({ int a=3; a; }), "int a=3; a;"); + assert(8, ({ int a=3; int z=5; a+z; }), "int a=3; int z=5; a+z;"); + + assert(3, ({ int foo=3; foo; }), "int foo=3; foo;"); + assert(8, ({ int foo123=3; int bar=5; foo123+bar; }), "int foo123=3; int bar=5; foo123+bar;"); assert(3, ret3(), "ret3();"); - assert(3, ({ - int x = 0; - if (0) - x = 2; - else - x = 3; - x; - }), - "int x=0; if (0) x=2; else x=3; x;"); - assert(3, ({ - int x = 0; - if (1 - 1) - x = 2; - else - x = 3; - x; - }), - "int x=0; if (1-1) x=2; else x=3; x;"); - assert(2, ({ - int x = 0; - if (1) - x = 2; - else - x = 3; - x; - }), - "int x=0; if (1) x=2; else x=3; x;"); - assert(2, ({ - int x = 0; - if (2 - 1) - x = 2; - else - x = 3; - x; - }), - "int x=0; if (2-1) x=2; else x=3; x;"); - - assert(3, ({ - 1; - { 2; } - 3; - }), - "1; {2;} 3;"); - assert(10, ({ - int i = 0; - i = 0; - while (i < 10) i = i + 1; - i; - }), - "int i=0; i=0; while(i<10) i=i+1; i;"); - assert(55, ({ - int i = 0; - int j = 0; - while (i <= 10) { - j = i + j; - i = i + 1; - } - j; - }), - "int i=0; int j=0; while(i<=10) {j=i+j; i=i+1;} j;"); - assert(55, ({ - int i = 0; - int j = 0; - for (i = 0; i <= 10; i = i + 1) j = i + j; - j; - }), - "int i=0; int j=0; for (i=0; i<=10; i=i+1) j=i+j; j;"); + assert(3, ({ int x=0; if (0) x=2; else x=3; x; }), "int x=0; if (0) x=2; else x=3; x;"); + assert(3, ({ int x=0; if (1-1) x=2; else x=3; x; }), "int x=0; if (1-1) x=2; else x=3; x;"); + assert(2, ({ int x=0; if (1) x=2; else x=3; x; }), "int x=0; if (1) x=2; else x=3; x;"); + assert(2, ({ int x=0; if (2-1) x=2; else x=3; x; }), "int x=0; if (2-1) x=2; else x=3; x;"); + + assert(3, ({ 1; {2;} 3; }), "1; {2;} 3;"); + assert(10, ({ int i=0; i=0; while(i<10) i=i+1; i; }), "int i=0; i=0; while(i<10) i=i+1; i;"); + assert(55, ({ int i=0; int j=0; while(i<=10) {j=i+j; i=i+1;} j; }), "int i=0; int j=0; while(i<=10) {j=i+j; i=i+1;} j;"); + assert(55, ({ int i=0; int j=0; for (i=0; i<=10; i=i+1) j=i+j; j; }), "int i=0; int j=0; for (i=0; i<=10; i=i+1) j=i+j; j;"); assert(8, add2(3, 5), "add(3, 5)"); assert(2, sub2(5, 3), "sub(5, 3)"); - assert(21, add6(1, 2, 3, 4, 5, 6), "add6(1,2,3,4,5,6)"); + assert(21, add6(1,2,3,4,5,6), "add6(1,2,3,4,5,6)"); assert(55, fib(9), "fib(9)"); - assert(3, ({ - int x = 3; - *&x; - }), - "int x=3; *&x;"); - assert(3, ({ - int x = 3; - int *y = &x; - int **z = &y; - **z; - }), - "int x=3; int *y=&x; int **z=&y; **z;"); - assert(5, ({ - int x = 3; - int y = 5; - *(&x + 1); - }), - "int x=3; int y=5; *(&x+1);"); - assert(5, ({ - int x = 3; - int y = 5; - *(1 + &x); - }), - "int x=3; int y=5; *(1+&x);"); - assert(3, ({ - int x = 3; - int y = 5; - *(&y - 1); - }), - "int x=3; int y=5; *(&y-1);"); - assert(5, ({ - int x = 3; - int y = 5; - int *z = &x; - *(z + 1); - }), - "int x=3; int y=5; int *z=&x; *(z+1);"); - assert(3, ({ - int x = 3; - int y = 5; - int *z = &y; - *(z - 1); - }), - "int x=3; int y=5; int *z=&y; *(z-1);"); - assert(5, ({ - int x = 3; - int *y = &x; - *y = 5; - x; - }), - "int x=3; int *y=&x; *y=5; x;"); - assert(7, ({ - int x = 3; - int y = 5; - *(&x + 1) = 7; - y; - }), - "int x=3; int y=5; *(&x+1)=7; y;"); - assert(7, ({ - int x = 3; - int y = 5; - *(&y - 1) = 7; - x; - }), - "int x=3; int y=5; *(&y-1)=7; x;"); - assert(8, ({ - int x = 3; - int y = 5; - addx(&x, y); - }), - "int x=3; int y=5; addx(&x, y);"); - - assert(3, ({ - int x[2]; - int *y = &x; - *y = 3; - *x; - }), - "int x[2]; int *y=&x; *y=3; *x;"); - - assert(3, ({ - int x[3]; - *x = 3; - *(x + 1) = 4; - *(x + 2) = 5; - *x; - }), - "int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *x;"); - assert(4, ({ - int x[3]; - *x = 3; - *(x + 1) = 4; - *(x + 2) = 5; - *(x + 1); - }), - "int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *(x+1);"); - assert(5, ({ - int x[3]; - *x = 3; - *(x + 1) = 4; - *(x + 2) = 5; - *(x + 2); - }), - "int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *(x+2);"); - - assert(0, ({ - int x[2][3]; - int *y = x; - *y = 0; - **x; - }), - "int x[2][3]; int *y=x; *y=0; **x;"); - assert(1, ({ - int x[2][3]; - int *y = x; - *(y + 1) = 1; - *(*x + 1); - }), - "int x[2][3]; int *y=x; *(y+1)=1; *(*x+1);"); - assert(2, ({ - int x[2][3]; - int *y = x; - *(y + 2) = 2; - *(*x + 2); - }), - "int x[2][3]; int *y=x; *(y+2)=2; *(*x+2);"); - assert(3, ({ - int x[2][3]; - int *y = x; - *(y + 3) = 3; - **(x + 1); - }), - "int x[2][3]; int *y=x; *(y+3)=3; **(x+1);"); - assert(4, ({ - int x[2][3]; - int *y = x; - *(y + 4) = 4; - *(*(x + 1) + 1); - }), - "int x[2][3]; int *y=x; *(y+4)=4; *(*(x+1)+1);"); - assert(5, ({ - int x[2][3]; - int *y = x; - *(y + 5) = 5; - *(*(x + 1) + 2); - }), - "int x[2][3]; int *y=x; *(y+5)=5; *(*(x+1)+2);"); - assert(6, ({ - int x[2][3]; - int *y = x; - *(y + 6) = 6; - **(x + 2); - }), - "int x[2][3]; int *y=x; *(y+6)=6; **(x+2);"); - - assert(3, ({ - int x[3]; - *x = 3; - x[1] = 4; - x[2] = 5; - *x; - }), - "int x[3]; *x=3; x[1]=4; x[2]=5; *x;"); - assert(4, ({ - int x[3]; - *x = 3; - x[1] = 4; - x[2] = 5; - *(x + 1); - }), - "int x[3]; *x=3; x[1]=4; x[2]=5; *(x+1);"); - assert(5, ({ - int x[3]; - *x = 3; - x[1] = 4; - x[2] = 5; - *(x + 2); - }), - "int x[3]; *x=3; x[1]=4; x[2]=5; *(x+2);"); - assert(5, ({ - int x[3]; - *x = 3; - x[1] = 4; - x[2] = 5; - *(x + 2); - }), - "int x[3]; *x=3; x[1]=4; x[2]=5; *(x+2);"); - assert(5, ({ - int x[3]; - *x = 3; - x[1] = 4; - 2 [x] = 5; - *(x + 2); - }), - "int x[3]; *x=3; x[1]=4; 2[x]=5; *(x+2);"); - - assert(0, ({ - int x[2][3]; - int *y = x; - y[0] = 0; - x[0][0]; - }), - "int x[2][3]; int *y=x; y[0]=0; x[0][0];"); - assert(1, ({ - int x[2][3]; - int *y = x; - y[1] = 1; - x[0][1]; - }), - "int x[2][3]; int *y=x; y[1]=1; x[0][1];"); - assert(2, ({ - int x[2][3]; - int *y = x; - y[2] = 2; - x[0][2]; - }), - "int x[2][3]; int *y=x; y[2]=2; x[0][2];"); - assert(3, ({ - int x[2][3]; - int *y = x; - y[3] = 3; - x[1][0]; - }), - "int x[2][3]; int *y=x; y[3]=3; x[1][0];"); - assert(4, ({ - int x[2][3]; - int *y = x; - y[4] = 4; - x[1][1]; - }), - "int x[2][3]; int *y=x; y[4]=4; x[1][1];"); - assert(5, ({ - int x[2][3]; - int *y = x; - y[5] = 5; - x[1][2]; - }), - "int x[2][3]; int *y=x; y[5]=5; x[1][2];"); - assert(6, ({ - int x[2][3]; - int *y = x; - y[6] = 6; - x[2][0]; - }), - "int x[2][3]; int *y=x; y[6]=6; x[2][0];"); - - assert(4, ({ - int x; - sizeof(x); - }), - "int x; sizeof(x);"); - assert(4, ({ - int x; - sizeof x; - }), - "int x; sizeof x;"); - assert(8, ({ - int *x; - sizeof(x); - }), - "int *x; sizeof(x);"); - assert(16, ({ - int x[4]; - sizeof(x); - }), - "int x[4]; sizeof(x);"); - assert(48, ({ - int x[3][4]; - sizeof(x); - }), - "int x[3][4]; sizeof(x);"); - assert(16, ({ - int x[3][4]; - sizeof(*x); - }), - "int x[3][4]; sizeof(*x);"); - assert(4, ({ - int x[3][4]; - sizeof(**x); - }), - "int x[3][4]; sizeof(**x);"); - assert(5, ({ - int x[3][4]; - sizeof(**x) + 1; - }), - "int x[3][4]; sizeof(**x) + 1;"); - assert(5, ({ - int x[3][4]; - sizeof **x + 1; - }), - "int x[3][4]; sizeof **x + 1;"); - assert(4, ({ - int x[3][4]; - sizeof(**x + 1); - }), - "int x[3][4]; sizeof(**x + 1);"); + assert(3, ({ int x=3; *&x; }), "int x=3; *&x;"); + assert(3, ({ int x=3; int *y=&x; int **z=&y; **z; }), "int x=3; int *y=&x; int **z=&y; **z;"); + assert(5, ({ int x=3; int y=5; *(&x+1); }), "int x=3; int y=5; *(&x+1);"); + assert(5, ({ int x=3; int y=5; *(1+&x); }), "int x=3; int y=5; *(1+&x);"); + assert(3, ({ int x=3; int y=5; *(&y-1); }), "int x=3; int y=5; *(&y-1);"); + assert(5, ({ int x=3; int y=5; int *z=&x; *(z+1); }), "int x=3; int y=5; int *z=&x; *(z+1);"); + assert(3, ({ int x=3; int y=5; int *z=&y; *(z-1); }), "int x=3; int y=5; int *z=&y; *(z-1);"); + assert(5, ({ int x=3; int *y=&x; *y=5; x; }), "int x=3; int *y=&x; *y=5; x;"); + assert(7, ({ int x=3; int y=5; *(&x+1)=7; y; }), "int x=3; int y=5; *(&x+1)=7; y;"); + assert(7, ({ int x=3; int y=5; *(&y-1)=7; x; }), "int x=3; int y=5; *(&y-1)=7; x;"); + assert(8, ({ int x=3; int y=5; addx(&x, y); }), "int x=3; int y=5; addx(&x, y);"); + + assert(3, ({ int x[2]; int *y=&x; *y=3; *x; }), "int x[2]; int *y=&x; *y=3; *x;"); + + assert(3, ({ int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *x; }), "int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *x;"); + assert(4, ({ int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *(x+1); }), "int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *(x+1);"); + assert(5, ({ int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *(x+2); }), "int x[3]; *x=3; *(x+1)=4; *(x+2)=5; *(x+2);"); + + assert(0, ({ int x[2][3]; int *y=x; *y=0; **x; }), "int x[2][3]; int *y=x; *y=0; **x;"); + assert(1, ({ int x[2][3]; int *y=x; *(y+1)=1; *(*x+1); }), "int x[2][3]; int *y=x; *(y+1)=1; *(*x+1);"); + assert(2, ({ int x[2][3]; int *y=x; *(y+2)=2; *(*x+2); }), "int x[2][3]; int *y=x; *(y+2)=2; *(*x+2);"); + assert(3, ({ int x[2][3]; int *y=x; *(y+3)=3; **(x+1); }), "int x[2][3]; int *y=x; *(y+3)=3; **(x+1);"); + assert(4, ({ int x[2][3]; int *y=x; *(y+4)=4; *(*(x+1)+1); }), "int x[2][3]; int *y=x; *(y+4)=4; *(*(x+1)+1);"); + assert(5, ({ int x[2][3]; int *y=x; *(y+5)=5; *(*(x+1)+2); }), "int x[2][3]; int *y=x; *(y+5)=5; *(*(x+1)+2);"); + assert(6, ({ int x[2][3]; int *y=x; *(y+6)=6; **(x+2); }), "int x[2][3]; int *y=x; *(y+6)=6; **(x+2);"); + + assert(3, ({ int x[3]; *x=3; x[1]=4; x[2]=5; *x; }), "int x[3]; *x=3; x[1]=4; x[2]=5; *x;"); + assert(4, ({ int x[3]; *x=3; x[1]=4; x[2]=5; *(x+1); }), "int x[3]; *x=3; x[1]=4; x[2]=5; *(x+1);"); + assert(5, ({ int x[3]; *x=3; x[1]=4; x[2]=5; *(x+2); }), "int x[3]; *x=3; x[1]=4; x[2]=5; *(x+2);"); + assert(5, ({ int x[3]; *x=3; x[1]=4; x[2]=5; *(x+2); }), "int x[3]; *x=3; x[1]=4; x[2]=5; *(x+2);"); + assert(5, ({ int x[3]; *x=3; x[1]=4; 2[x]=5; *(x+2); }), "int x[3]; *x=3; x[1]=4; 2[x]=5; *(x+2);"); + + assert(0, ({ int x[2][3]; int *y=x; y[0]=0; x[0][0]; }), "int x[2][3]; int *y=x; y[0]=0; x[0][0];"); + assert(1, ({ int x[2][3]; int *y=x; y[1]=1; x[0][1]; }), "int x[2][3]; int *y=x; y[1]=1; x[0][1];"); + assert(2, ({ int x[2][3]; int *y=x; y[2]=2; x[0][2]; }), "int x[2][3]; int *y=x; y[2]=2; x[0][2];"); + assert(3, ({ int x[2][3]; int *y=x; y[3]=3; x[1][0]; }), "int x[2][3]; int *y=x; y[3]=3; x[1][0];"); + assert(4, ({ int x[2][3]; int *y=x; y[4]=4; x[1][1]; }), "int x[2][3]; int *y=x; y[4]=4; x[1][1];"); + assert(5, ({ int x[2][3]; int *y=x; y[5]=5; x[1][2]; }), "int x[2][3]; int *y=x; y[5]=5; x[1][2];"); + assert(6, ({ int x[2][3]; int *y=x; y[6]=6; x[2][0]; }), "int x[2][3]; int *y=x; y[6]=6; x[2][0];"); + + assert(4, ({ int x; sizeof(x); }), "int x; sizeof(x);"); + assert(4, ({ int x; sizeof x; }), "int x; sizeof x;"); + assert(8, ({ int *x; sizeof(x); }), "int *x; sizeof(x);"); + assert(16, ({ int x[4]; sizeof(x); }), "int x[4]; sizeof(x);"); + assert(48, ({ int x[3][4]; sizeof(x); }), "int x[3][4]; sizeof(x);"); + assert(16, ({ int x[3][4]; sizeof(*x); }), "int x[3][4]; sizeof(*x);"); + assert(4, ({ int x[3][4]; sizeof(**x); }), "int x[3][4]; sizeof(**x);"); + assert(5, ({ int x[3][4]; sizeof(**x) + 1; }), "int x[3][4]; sizeof(**x) + 1;"); + assert(5, ({ int x[3][4]; sizeof **x + 1; }), "int x[3][4]; sizeof **x + 1;"); + assert(4, ({ int x[3][4]; sizeof(**x + 1); }), "int x[3][4]; sizeof(**x + 1);"); assert(0, g1, "g1"); - g1 = 3; + g1=3; assert(3, g1, "g1"); - g2[0] = 0; - g2[1] = 1; - g2[2] = 2; - g2[3] = 3; + g2[0]=0; g2[1]=1; g2[2]=2; g2[3]=3; assert(0, g2[0], "g2[0]"); assert(1, g2[1], "g2[1]"); assert(2, g2[2], "g2[2]"); @@ -562,34 +220,12 @@ int main() { assert(4, sizeof(g1), "sizeof(g1)"); assert(16, sizeof(g2), "sizeof(g2)"); - assert(1, ({ - char x = 1; - x; - }), - "char x=1; x;"); - assert(1, ({ - char x = 1; - char y = 2; - x; - }), - "char x=1; char y=2; x;"); - assert(2, ({ - char x = 1; - char y = 2; - y; - }), - "char x=1; char y=2; y;"); - - assert(1, ({ - char x; - sizeof(x); - }), - "char x; sizeof(x);"); - assert(10, ({ - char x[10]; - sizeof(x); - }), - "char x[10]; sizeof(x);"); + assert(1, ({ char x=1; x; }), "char x=1; x;"); + assert(1, ({ char x=1; char y=2; x; }), "char x=1; char y=2; x;"); + assert(2, ({ char x=1; char y=2; y; }), "char x=1; char y=2; y;"); + + assert(1, ({ char x; sizeof(x); }), "char x; sizeof(x);"); + assert(10, ({ char x[10]; sizeof(x); }), "char x[10]; sizeof(x);"); assert(1, sub_char(7, 3, 3), "sub_char(7, 3, 3)"); assert(97, "abc"[0], "\"abc\"[0]"); @@ -612,25 +248,10 @@ int main() { assert(107, "\k"[0], "\"\\k\"[0]"); assert(108, "\l"[0], "\"\\l\"[0]"); - assert(2, ({ - int x = 2; - { int x = 3; } - x; - }), - "int x=2; { int x=3; } x;"); - assert(2, ({ - int x = 2; - { int x = 3; } - int y = 4; - x; - }), - "int x=2; { int x=3; } int y=4; x;"); - assert(3, ({ - int x = 2; - { x = 3; } - x; - }), - "int x=2; { x=3; } x;"); + assert(2, ({ int x=2; { int x=3; } x; }), "int x=2; { int x=3; } x;"); + assert(2, ({ int x=2; { int x=3; } int y=4; x; }), "int x=2; { int x=3; } int y=4; x;"); + assert(3, ({ int x=2; { x=3; } x; }), "int x=2; { x=3; } x;"); + assert(1, ({ struct {int a; int b;} x; x.a=1; x.b=2; x.a; }), "struct {int a; int b;} x; x.a=1; x.b=2; x.a;"); assert(2, ({ struct {int a; int b;} x; x.a=1; x.b=2; x.b; }), "struct {int a; int b;} x; x.a=1; x.b=2; x.b;"); assert(1, ({ struct {char a; int b; char c;} x; x.a=1; x.b=2; x.c=3; x.a; }), "struct {char a; int b; char c;} x; x.a=1; x.b=2; x.c=3; x.a;"); @@ -656,8 +277,8 @@ int main() { assert(8, ({ struct {char a; int b;} x; sizeof(x); }), "struct {char a; int b;} x; sizeof(x);"); assert(8, ({ struct {int a; char b;} x; sizeof(x); }), "struct {int a; char b;} x; sizeof(x);"); - assert(7, ({int x; char y; int a = &x; int b = &y; b-a; }), "int x; char y; int a = &x; int b = &y; b-a;"); - assert(1, ({char x; int y; int a = &x; int b = &y; b-a; }), "int x; char y; int a = &x; int b = &y; b-a;"); + assert(7, ({ int x; char y; int a=&x; int b=&y; b-a; }), "int x; char y; int a=&x; int b=&y; b-a;"); + assert(1, ({ char x; int y; int a=&x; int b=&y; b-a; }), "char x; int y; int a=&x; int b=&y; b-a;"); assert(2, ({ struct t {char a[2];}; { struct t {char a[4];}; } struct t y; sizeof(y); }), "struct t {char a[2];}; { struct t {char a[4];}; } struct t y; sizeof(y);"); assert(3, ({ struct t {int x;}; int t=1; struct t y; y.x=2; t+y.x; }), "struct t {int x;}; int t=1; struct t y; y.x=2; t+y.x;"); @@ -669,6 +290,7 @@ int main() { assert(1, ({ typedef struct {int a;} t; t x; x.a=1; x.a; }), "typedef struct {int a;} t; t x; x.a=1; x.a;"); assert(1, ({ typedef int t; t t=1; t; }), "typedef int t; t t=1; t;"); assert(2, ({ typedef struct {int a;} t; { typedef int t; } t x; x.a=2; x.a; }), "typedef struct {int a;} t; { typedef int t; } t x; x.a=2; x.a;"); + assert(3, ({ typedef struct Token Token; struct Token { Token *next; int x; }; Token t; t.x=3; t.x; }), "edef struct Token Token; struct Token {Token* next; int x}; Token t; t.x=3; t.x; "); assert(8, ({ struct t {int a; int b;} x; struct t y; sizeof(y); }), "struct t {int a; int b;} x; struct t y; sizeof(y);"); assert(8, ({ struct t {int a; int b;}; struct t y; sizeof(y); }), "struct t {int a; int b;}; struct t y; sizeof(y);"); @@ -750,6 +372,9 @@ int main() { assert(4, ({ enum { zero, five=5, three=3, four }; four; }), "enum { zero, five=5, three=3, four }; four;"); assert(4, ({ enum { zero, one, two } x; sizeof(x); }), "enum { zero, one, two } x; sizeof(x);"); assert(4, ({ enum t { zero, one, two }; enum t y; sizeof(y); }), "enum t { zero, one, two }; enum t y; sizeof(y);"); + assert(4, ({ typedef enum { zero, one, two} t; t y; sizeof(y); }), "typedef enum { zero, one, two} t; enum t y; sizeof(y);"); + assert(1, ({ typedef enum { TK_RESERVED, } TokenKind; typedef struct Token Token; struct Token { TokenKind kind; Token *next; int x; }; Token t; t.x=1; t.x; }), + "typedef enum { TK_RESERVED, } TokenKind; typedef struct Token Token; struct Token { TokenKind kind; Token *next; int x; }; Token t; t.x=1; t.x;"); assert(1, count(), "count()"); assert(2, count(), "count()"); @@ -758,7 +383,7 @@ int main() { assert(55, ({ int j=0; for (int i=0; i<=10; i=i+1) j=j+i; j; }), "int j=0; for (int i=0; i<=10; i=i+1) j=j+i; j;"); assert(3, ({ int i=3; int j=0; for (int i=0; i<=10; i=i+1) j=j+i; i; }), "int i=3; int j=0; for (int i=0; i<=10; i=i+1) j=j+i; i;"); - assert(3, (1, 2, 3), "(1, 2, 3)"); + assert(3, (1,2,3), "(1,2,3)"); assert(3, ({ int i=2; ++i; }), "int i=2; ++i;"); assert(1, ({ int i=2; --i; }), "int i=2; --i;"); @@ -817,6 +442,10 @@ int main() { assert(3, ({ int x[2]; x[0]=3; param_decay(x); }), "int x[2]; x[0]=3; param_decay(x);"); + assert(8, ({ struct *foo; sizeof(foo); }), "struct *foo; sizeof(foo);"); + assert(4, ({ struct T *foo; struct T {int x;}; sizeof(struct T); }), "struct T *foo; struct T {int x;}; sizeof(struct T);"); + assert(1, ({ struct T { struct T *next; int x; } a; struct T b; b.x=1; a.next=&b; a.next->x; }), "struct T { struct T *next; int x; } a; struct T b; b.x=1; a.next=&b; a.next->x;"); + assert(3, ({ int i=0; for(;i<10;i++) { if (i == 3) break; } i; }), "int i=0; for(;i<10;i++) { if (i == 3) break; } i;"); assert(4, ({ int i=0; while (1) { if (i++ == 3) break; } i; }), "int i=0; while { if (i == 3) break; } i;"); assert(3, ({ int i=0; for(;i<10;i++) { for (;;) break; if (i == 3) break; } i; }), "int i=0; for(;i<10;i++) { if (i == 3) break; } i;"); @@ -840,12 +469,8 @@ int main() { assert(5, ({ int i=0; switch(0) { case 0:i=5;break; default:i=7; } i; }), "int i=0; switch(0) { case 0:i=5;break; default:i=7; } i;"); assert(7, ({ int i=0; switch(1) { case 0:i=5;break; default:i=7; } i; }), "int i=0; switch(1) { case 0:i=5;break; default:i=7; } i;"); - assert(8, ({ struct *foo; sizeof(foo); }), "struct *foo; sizeof(foo);"); - assert(4, ({ struct T *foo; struct T {int x;}; sizeof(struct T); }), "struct T *foo; struct T {int x;}; sizeof(struct T);"); - assert(1, ({ struct T { struct T *next; int x; } a; struct T b; b.x=1; a.next=&b; a.next->x; }), "struct T { struct T *next; int x; } a; struct T b; b.x=1; a.next=&b; a.next->x;"); - voidfn(); - + assert(1, 1<<0, "1<<0"); assert(8, 1<<3, "1<<3"); assert(10, 5<<1, "5<<1"); @@ -872,6 +497,7 @@ int main() { assert(2, ({ int x[3]={1,2,3}; x[1]; }), "int x[3]={1,2,3}; x[0];"); assert(3, ({ int x[3]={1,2,3}; x[2]; }), "int x[3]={1,2,3}; x[0];"); assert(3, ({ int x[3]={1,2,3,}; x[2]; }), "int x[3]={1,2,3}; x[0];"); + assert(2, ({ int x[2][3]={{1,2,3},{4,5,6}}; x[0][1]; }), "int x[2][3]={{1,2,3},{4,5,6}}; x[0][1];"); assert(4, ({ int x[2][3]={{1,2,3},{4,5,6}}; x[1][0]; }), "int x[2][3]={{1,2,3},{4,5,6}}; x[1][0];"); assert(6, ({ int x[2][3]={{1,2,3},{4,5,6}}; x[1][2]; }), "int x[2][3]={{1,2,3},{4,5,6}}; x[1][2];"); @@ -887,7 +513,7 @@ int main() { assert(0, ({ char x[2][4]={"abc","def"}; x[0][3]; }), "char x[2][4]=\"abc\",\"def\"}; x[0][3]; }"); assert('d', ({ char x[2][4]={"abc","def"}; x[1][0]; }), "char x[2][4]=\"abc\",\"def\"}; x[1][0]; }"); assert('f', ({ char x[2][4]={"abc","def"}; x[1][2]; }), "char x[2][4]=\"abc\",\"def\"}; x[1][2]; }"); - + assert(4, ({ int x[]={1,2,3,4}; x[3]; }), "int x[]={1,2,3,4}; x[3];"); assert(16, ({ int x[]={1,2,3,4}; sizeof(x); }), "int x[]={1,2,3,4}; sizeof(x);"); assert(4, ({ char x[]="foo"; sizeof(x); }), "char x[]=\"foo\"; sizeof(x); }"); @@ -898,10 +524,12 @@ int main() { assert(1, ({ struct {int a; int b; int c;} x={1}; x.a; }), "struct {int a; int b; int c;} x={1}; x.a;"); assert(0, ({ struct {int a; int b; int c;} x={1}; x.b; }), "struct {int a; int b; int c;} x={1}; x.b;"); assert(0, ({ struct {int a; int b; int c;} x={1}; x.c; }), "struct {int a; int b; int c;} x={1}; x.c;"); + assert(1, ({ struct {int a; int b;} x[2]={{1,2},{3,4}}; x[0].a; }), "struct {int a; int b;} x[2]={{1,2},{3,4}}; x[0].a;"); assert(2, ({ struct {int a; int b;} x[2]={{1,2},{3,4}}; x[0].b; }), "struct {int a; int b;} x[2]={{1,2},{3,4}}; x[0].b;"); assert(3, ({ struct {int a; int b;} x[2]={{1,2},{3,4}}; x[1].a; }), "struct {int a; int b;} x[2]={{1,2},{3,4}}; x[1].a;"); assert(4, ({ struct {int a; int b;} x[2]={{1,2},{3,4}}; x[1].b; }), "struct {int a; int b;} x[2]={{1,2},{3,4}}; x[1].b;"); + assert(0, ({ struct {int a; int b;} x[2]={{1,2}}; x[1].b; }), "struct {int a; int b;} x[2]={{1,2}}; x[1].b;"); assert(3, g3, "g3"); @@ -914,14 +542,17 @@ int main() { assert(0, g9[0], "g9[0]"); assert(1, g9[1], "g9[1]"); assert(2, g9[2], "g9[2]"); + assert(0, strcmp(g10[0], "foo"), "strcmp(g10[0], \"foo\")"); assert(0, strcmp(g10[1], "bar"), "strcmp(g10[1], \"bar\")"); assert(0, g10[1][3], "g10[1][3]"); assert(2, sizeof(g10) / sizeof(*g10), "sizeof(g10) / sizeof(*g10)"); + assert(1, g11[0].a, "g11[0].a"); assert(2, g11[0].b, "g11[0].b"); assert(3, g11[1].a, "g11[1].a"); assert(4, g11[1].b, "g11[1].b"); + assert(1, g12[0].a[0], "g12[0].a[0]"); assert(2, g12[0].a[1], "g12[0].a[1]"); assert(3, g12[1].a[0], "g12[1].a[0]"); @@ -931,14 +562,18 @@ int main() { assert(2, g13[0].a[1], "g13[0].a[1]"); assert(3, g13[1].a[0], "g13[1].a[0]"); assert(4, g13[1].a[1], "g13[1].a[1]"); + assert(1, g14[0].a[0], "g14[0].a[0]"); assert(2, g14[0].a[1], "g14[0].a[1]"); assert(3, g14[1].a[0], "g14[1].a[0]"); assert(4, g14[1].a[1], "g14[1].a[1]"); + assert(0, ({ int x[2][3]={0,1,2,3,4,5,}; x[0][0]; }), "int x[2][3]={0,1,2,3,4,5,}; x[0][0];"); assert(3, ({ int x[2][3]={0,1,2,3,4,5,}; x[1][0]; }), "int x[2][3]={0,1,2,3,4,5,}; x[1][0];"); + assert(0, ({ struct {int a; int b;} x[2]={0,1,2,3}; x[0].a; }), "struct {int a; int b;} x[2]={0,1,2,3}; x[0].a;"); assert(2, ({ struct {int a; int b;} x[2]={0,1,2,3}; x[1].a; }), "struct {int a; int b;} x[2]={0,1,2,3}; x[1].a;"); + assert(0, strcmp(g15, "foo"), "strcmp(g15, \"foo\")"); assert(0, strcmp(g16[0], "foo"), "strcmp(g16[0], \"foo\")"); assert(0, strcmp(g16[1], "bar"), "strcmp(g16[1], \"bar\")"); @@ -946,6 +581,7 @@ int main() { assert(7, sizeof(g17), "sizeof(g17)"); assert(10, sizeof(g18), "sizeof(g18)"); assert(3, sizeof(g19), "sizeof(g19)"); + assert(0, memcmp(g17, "foobar", 7), "memcmp(g17, \"foobar\", 7)"); assert(0, memcmp(g18, "foobar\0\0\0", 10), "memcmp(g18, \"foobar\\0\\0\\0\", 10)"); assert(0, memcmp(g19, "foo", 3), "memcmp(g19, \"foo\", 3)"); @@ -953,6 +589,7 @@ int main() { assert(0, strcmp(g20, "foobar"), "strcmp(g20, \"foobar\")"); assert(0, strcmp(g21, "bar"), "strcmp(g21, \"bar\")"); assert(0, strcmp(g22+3, "foobar"), "strcmp(g22+3, \"foobar\")"); + assert(3, g23, "g23"); assert(3, *g24, "*g24"); diff --git a/tokenize.c b/tokenize.c index 060282a..22c7e39 100644 --- a/tokenize.c +++ b/tokenize.c @@ -165,7 +165,7 @@ char *starts_with_reserved(char *p) { "char", "int", "sizeof", "struct", "typedef", "short", "long", "void", "_Bool", "enum", "static", "break", "continue", "goto", "switch", - "case", "default", "extern"}; + "case", "default", "extern", "const", "unsigned"}; for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++) { int len = strlen(kw[i]); if (startswith(p, kw[i]) && !is_alnum(p[len])) {