summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-12-27 15:47:17 +0100
committerTyge Løvset <[email protected]>2021-12-28 17:06:24 +0100
commitdbeb998018ce3a739500f9a29e9b62639de2c49f (patch)
treecc2cd5313fd84d9e9afdd9b1bbfea0fc19eb5a78
parentd63d4a2a23dca342f418a5ccf8adf46e0d08d95a (diff)
downloadSTC-modified-dbeb998018ce3a739500f9a29e9b62639de2c49f.tar.gz
STC-modified-dbeb998018ce3a739500f9a29e9b62639de2c49f.zip
Added autocheck.l utility to check for wrong usage of c_auto*.
-rw-r--r--autocheck.ll101
-rw-r--r--build_autocheck.sh5
-rw-r--r--examples/new_smap.c8
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("");