diff options
| author | Tyge Løvset <[email protected]> | 2021-12-27 15:47:17 +0100 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2021-12-28 17:06:24 +0100 |
| commit | dbeb998018ce3a739500f9a29e9b62639de2c49f (patch) | |
| tree | cc2cd5313fd84d9e9afdd9b1bbfea0fc19eb5a78 | |
| parent | d63d4a2a23dca342f418a5ccf8adf46e0d08d95a (diff) | |
| download | STC-modified-dbeb998018ce3a739500f9a29e9b62639de2c49f.tar.gz STC-modified-dbeb998018ce3a739500f9a29e9b62639de2c49f.zip | |
Added autocheck.l utility to check for wrong usage of c_auto*.
| -rw-r--r-- | autocheck.ll | 101 | ||||
| -rw-r--r-- | build_autocheck.sh | 5 | ||||
| -rw-r--r-- | examples/new_smap.c | 8 |
3 files changed, 111 insertions, 3 deletions
diff --git a/autocheck.ll b/autocheck.ll new file mode 100644 index 00000000..9b090b1c --- /dev/null +++ b/autocheck.ll @@ -0,0 +1,101 @@ +/* Check for illegal return/break/continue usage inside a STC-lib c_auto* block (RAII). + * Copyright Tyge Løvset, (c) 2021. + */ +%{ +#include <stdbool.h> +enum { LOOP=1<<0, AUTO=1<<1 }; +enum { NORMAL, BRACES, BRACESDONE }; +static int braces_lev = 0, block_lev = 0; +static int state = NORMAL; +static unsigned int block[64] = {0}, block_type = 0; +const char* fname; +%} + +ID [_a-zA-Z][_a-zA-Z0-9]* +STR \"([^"\\]|\\.)*\" + +%option never-interactive noyymore noyywrap nounistd +%x cmt +%x prep + +%% +\/\/.* ; // line cmt +\/\* BEGIN(cmt); +<cmt>\n ++yylineno; +<cmt>\*\/ BEGIN(INITIAL); +<cmt>. ; +^[ \t]*#.*\\\n { ++yylineno; BEGIN(prep); } +<prep>.*\\\n ++yylineno; +<prep>.*\n { ++yylineno; BEGIN(INITIAL); } +^[ \t]*#.* ; +{STR} ; +'\\?.' ; +c_foreach | +c_forrange | +for | +while | +switch { block_type |= LOOP; state = BRACES; } +do { block_type |= LOOP; state = BRACESDONE; } +if { state = BRACES; } +c_autovar | +c_autoscope | +c_autodefer | +c_auto { block_type = AUTO; state = BRACES; } +\( { if (state == BRACES) ++braces_lev; } +\) { if (state == BRACES && --braces_lev == 0) { + state = BRACESDONE; + } + } +;[ \t]*else ; +; { if (state == BRACESDONE) { + block_type = block[block_lev]; + state = NORMAL; + } + } +\{ { if (state != BRACES) { block[++block_lev] = block_type; state = NORMAL; } } +\} { if (state != BRACES) block_type = block[--block_lev]; } +return { if (block_type == AUTO) { + printf("%s:%d: error: 'return' used inside a c_auto* scope.\n" + " Use 'c_exitauto' to exit the current c_auto* scope.\n", fname, yylineno); + } else if (block_type & AUTO) { + printf("%s:%d: error: 'return' used in a loop inside a c_auto* scope.\n" + " Use 'break' to exit loops, then 'c_exitauto' to exit c_auto*.\n", fname, yylineno); + } + } +break { if (block_type == AUTO) + printf("%s:%d: error: 'break' used inside a c_auto* scope.\n" + " Use 'c_exitauto' to exit the current c_auto* scope.\n", fname, yylineno); + } +continue { if (block_type == AUTO) + printf("%s:%d: warning: 'continue' used inside a c_auto* scope.\n" + " It will only break out of the current c_auto* scope.\n" + " Use 'c_exitauto' instead to make it explicit.\n", fname, yylineno); + } +c_exitauto { if (block_type != AUTO) + printf("%s:%d: warning: 'c_exitauto' used outside a c_auto* scope.\n" + " Did you mean 'continue' instead?", fname, yylineno); + } +{ID} ; +\n ++yylineno; +. ; + +%% + +#include <string.h> + +int main(int argc, char **argv) +{ + if (argc == 1 || strcmp(argv[1], "--help") == 0) { + printf("usage: %s [--help] {C-file | -}\n", argv[0]); + return 0; + } + if (strcmp(argv[1], "-") == 0) { + fname = "<stdin>"; + yyin = stdin; + } else { + fname = argv[1]; + yyin = fopen(fname, "r"); + } + + yylex(); +} diff --git a/build_autocheck.sh b/build_autocheck.sh new file mode 100644 index 00000000..96ec7d4d --- /dev/null +++ b/build_autocheck.sh @@ -0,0 +1,5 @@ +if [ "$OS" = "Windows_NT" ]; then EXE=.exe; fi +flex autocheck.ll +gcc -O2 lex.yy.c -o autocheck$EXE +rm lex.yy.c +strip autocheck$EXE diff --git a/examples/new_smap.c b/examples/new_smap.c index 2cb35b99..e1a9b13a 100644 --- a/examples/new_smap.c +++ b/examples/new_smap.c @@ -43,9 +43,11 @@ int main() csmap_int_insert(&map, 123, 321);
c_auto (csmap_pnt, pmap) {
- csmap_pnt_insert(&pmap, (Point){42, 14}, 1);
- csmap_pnt_insert(&pmap, (Point){32, 94}, 2);
- csmap_pnt_insert(&pmap, (Point){62, 81}, 3);
+ c_apply(v, csmap_pnt_insert(&pmap, c_pair(v)), csmap_pnt_value, {
+ {{42, 14}, 1},
+ {{32, 94}, 2},
+ {{62, 81}, 3},
+ });
c_foreach (i, csmap_pnt, pmap)
printf(" (%d,%d: %d)", i.ref->first.x, i.ref->first.y, i.ref->second);
puts("");
|
