Loading lib/flex/flex.cpp +3 −1 Changes for lib/flex/flex.cpp: 3 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -1988,6 +1988,7 @@ std::string CodeGenerator::generateSource() { if (!o.noUnistd) out << "#ifndef YY_NO_UNISTD_H\n#include <unistd.h>\n#endif\n"; if (!o.extraType.empty()) out << "#define YY_EXTRA_TYPE " << o.extraType << "\n"; out << "#ifndef YY_EXTRA_TYPE\n#define YY_EXTRA_TYPE void *\n#endif\n\n"; // ---- scanner state ---- Loading Loading @@ -2021,7 +2022,8 @@ std::string CodeGenerator::generateSource() { // yywrap: without noyywrap the program brings its own, or -lfl would if (o.yywrap) { out << "int yywrap( FX_PROTO );\n"; if (!hasWord(s.userCode, o.prefix == "yy" ? "yywrap" : o.prefix + "wrap") && !hasWord(s.userCode, "yywrap")) const std::string wrap = o.prefix + "wrap", code = s.prologue + s.userCode; if (!hasWord(code, wrap) && !hasWord(code, "yywrap")) out << "#if defined(__GNUC__) || defined(__clang__)\n__attribute__((weak))\n#endif\n" "int yywrap( FX_PROTO ) { FX_UNUSED; return 1; }\n"; } Loading lib/flex/test/run.sh 0 → 100644 +348 −0 Changes for lib/flex/test/run.sh: 348 added lines, 0 removed lines. Original line number Diff line number Diff line #!/bin/bash # flex test suite: usage: run.sh FLEX CC (FLEX: the fresh binary's flex applet) # Each case is a scanner, its input, and the output it has to print. FLEX=${1:-flex}; CC=${2:-cc} T=$(mktemp -d); trap 'rm -rf "$T"' EXIT pass=0; fail=0 # what -lfl would bring echo 'extern int yylex(); __attribute__((weak)) int main(void){ yylex(); return 0; }' > "$T/m0.c" # check NAME LFILE INPUT EXPECTED check() { local name=$1 l=$2 input=$3 want=$4 got if ! (cd "$T" && $FLEX -o s.c "$l" 2>err.txt && $CC -std=gnu99 -Wall -Werror=implicit-function-declaration -Wno-unused -o s s.c m0.c 2>>err.txt); then echo "FAIL $name (build)"; head -8 "$T/err.txt"; fail=$((fail+1)); return fi got=$(printf "$input" | "$T/s" 2>&1) if [ "$got" = "$want" ]; then pass=$((pass+1)); else echo "FAIL $name"; echo " want: $want"; echo " got: $got"; fail=$((fail+1)) fi } cat > "$T/basic.l" <<'E' %option noyywrap %% [0-9]+ printf("N(%s)", yytext); if|then { printf("K(%s)", yytext); } [a-z]+ printf("I(%s/%d)", yytext, yyleng); \n printf("|%d", yylineno); E check longest+priority basic.l 'if iff 12\nx\n' 'K(if) I(iff/3) N(12)|2I(x/1)|3' cat > "$T/alt.l" <<'E' %option noyywrap %% a | b | c printf("X"); .|\n ; E check bar-action alt.l 'abcd' 'XXX' cat > "$T/bol.l" <<'E' %option noyywrap %% ^a printf("B"); a$ printf("E"); a printf("M"); \n printf("|"); . ; E check bol+eol bol.l 'aa\nxa\naxa' 'BE|E|BM' cat > "$T/trail.l" <<'E' %option noyywrap %% foo/bar printf("[%s]", yytext); a*/a*b printf("<%s>", yytext); .|\n printf("%s", yytext); E check trailing trail.l 'foobar foo aab' '[foo]bar foo <aa>b' cat > "$T/more.l" <<'E' %option noyywrap %% mega- yymore(); kludge printf("[%s]", yytext); .|\n ; E check yymore more.l 'mega-kludge' '[mega-kludge]' cat > "$T/rej.l" <<'E' %option noyywrap %{ int n; %} %% frob n++; REJECT; [^ \t\n]+ n++; .|\n ; %% int main(void){ yylex(); printf("%d", n); return 0; } E check reject rej.l 'frob x' '3' cat > "$T/less.l" <<'E' %option noyywrap %% foobar { printf("[%s]", yytext); yyless(3); printf("[%s]", yytext); } bar printf("B"); \n ; E check yyless less.l 'foobar\n' '[foobar][foo]B' cat > "$T/putin.l" <<'E' %option noyywrap %% "(" { int c; while((c=input())!=')' && c) putchar(c); } x { unput('z'); unput('y'); } y printf("Y"); z printf("Z"); .|\n ; E check input+unput putin.l '(ab)x' 'abYZ' cat > "$T/array.l" <<'E' %array %option noyywrap %% [a-z]+ printf("[%s]", yytext); .|\n ; %% extern char yytext[]; E check array array.l 'ab cd' '[ab][cd]' cat > "$T/cond.l" <<'E' %option noyywrap stack %x C %s I %% "/*" { yy_push_state(C); } <C>"*/" { yy_pop_state(); } <C>.|\n ; <I,INITIAL>a printf("A"); <*>b printf("B"); .|\n ; <<EOF>> { printf("E%d", YY_START); yyterminate(); } <C><<EOF>> { printf("U"); yyterminate(); } E check conditions cond.l 'a/*ab*/b' 'ABBE0' check eof-in-condition cond.l 'a/*x' 'AU' cat > "$T/block.l" <<'E' %option noyywrap %x Q hex [0-9a-f] %% \" BEGIN(Q); <Q>{ /* comment */ \" BEGIN(INITIAL); {hex}+ printf("H%s", yytext); <<EOF>> { printf("!"); return 0; } .|\n ; } /* <Q> */ <Q>x printf("never"); .|\n ; E check condition-block block.l 'x"ag"x' 'Ha' cat > "$T/case.l" <<'E' %option noyywrap case-insensitive %% select printf("S"); [a-c]+ printf("C"); .|\n ; E check case-insensitive case.l 'SeLeCt ABC' 'SC' cat > "$T/flags.l" <<'E' %option noyywrap %% (?i:abc)def printf("1"); (?s:a.b) printf("2"); (?x: x y /* c */ z ) printf("3"); [a-z]{-}[aeiou]+q printf("4"); [[:^digit:]]{+}[0]q printf("5"); (?# nothing )w printf("6"); .|\n ; E check group-flags flags.l 'ABcdef a\nb xyz bcq 0q w' '12345 6' 2>/dev/null cat > "$T/rep.l" <<'E' %option noyywrap d [0-9] %% {d}{2,3}x printf("A"); {d}{4}y printf("B"); (ab)+ printf("C%d", yyleng); "lit*" printf("D"); \x41\101 printf("E"); .|\n ; E check repeat rep.l '12x 1234y ababab lit* AA' 'AB C6 D E' cat > "$T/echo.l" <<'E' %option noyywrap %% a ; E check default-echo echo.l 'xay\n' 'xy' cat > "$T/jam.l" <<'E' %option noyywrap nodefault %% a ; E check nodefault jam.l 'b' 'flex scanner jammed' cat > "$T/nul.l" <<'E' %option noyywrap 8bit %% \0 printf("N"); [\x80-\xff]+ printf("H%d", yyleng); .|\n ; E check binary nul.l 'a\0b\377\200' 'NH2' cat > "$T/big.l" <<'E' %option noyywrap %% a+ printf("%d\n", yyleng); \n printf("L%d\n", yylineno); . ; E input=$(head -c 100000 /dev/zero | tr '\0' a) check long-token big.l "$input\n" "100000 L2" cat > "$T/scan.l" <<'E' %option noyywrap %% [a-z]+ printf("[%s]", yytext); .|\n ; %% int main(void){ char b[8] = "ab cd\0\0"; YY_BUFFER_STATE h = yy_scan_string("xy zw"); yylex(); yy_delete_buffer(h); h = yy_scan_bytes("qr st", 2); yylex(); yy_delete_buffer(h); h = yy_scan_buffer(b, 7); yylex(); yy_delete_buffer(h); printf(" %d", b[0]=='a' && b[3]=='c'); yylex_destroy(); return 0; } E check scan-api scan.l '' '[xy][zw][qr][ab][cd] 1' cat > "$T/stack.l" <<'E' %option noyywrap %% "<" { yypush_buffer_state(yy_scan_string("in")); } <<EOF>> { yypop_buffer_state(); if(!YY_CURRENT_BUFFER) yyterminate(); } [a-z]+ printf("[%s]", yytext); .|\n ; E check buffer-stack stack.l 'a<b' '[a][in][b]' cat > "$T/wrap.l" <<'E' %{ static int files = 1; int yywrap(void){ if(files--){ yy_scan_string("more"); return 0; } return 1; } %} %% [a-z]+ printf("[%s]", yytext); .|\n ; E check yywrap wrap.l 'one' '[one][more]' cat > "$T/hooks.l" <<'E' %option noyywrap %{ static int col; #define YY_USER_ACTION col += yyleng; #define YY_USER_INIT printf("I"); #define YY_INPUT(buf,result,max) { static const char *s="abc"; result = *s ? (buf[0]=*s++, 1) : 0; } %} %% [a-z] printf("%d", col); E check hooks hooks.l '' 'I123' cat > "$T/re.l" <<'E' %option reentrant noyywrap prefix="core_yy" extra-type="int *" %% [a-z]+ { (*yyextra)++; printf("[%s:%d]", yytext, *yyextra); } x+y { BEGIN(INITIAL); yyless(1); } .|\n ; %% int main(void){ yyscan_t a, b; int na = 0, nb = 10; YY_BUFFER_STATE ha, hb; core_yylex_init_extra(&na, &a); core_yylex_init(&b); core_yyset_extra(&nb, b); ha = core_yy_scan_string("aa bb", a); hb = core_yy_scan_string("cc", b); core_yylex(a); core_yylex(b); core_yy_delete_buffer(ha, a); core_yy_delete_buffer(hb, b); printf(" %s", core_yyget_extra(a) == &na ? "ok" : "bad"); core_yylex_destroy(a); core_yylex_destroy(b); return 0; } E check reentrant+prefix re.l '' '[aa:1][bb:2][cc:11] ok' cat > "$T/bb.l" <<'E' %option reentrant bison-bridge bison-locations noyywrap %{ typedef int YYSTYPE; typedef struct { int first; } YYLTYPE; %} %% [0-9]+ { *yylval = atoi(yytext); yylloc->first = yytext - (char *) yyextra; return 1; } .|\n ; %% int main(void){ yyscan_t s; YYSTYPE v; YYLTYPE l; char buf[] = " 42\0"; yylex_init(&s); yyset_extra(buf, s); yy_scan_buffer(buf, sizeof(buf), s); while(yylex(&v, &l, s)) printf("%d@%d", v, l.first); yylex_destroy(s); return 0; } E check bison-bridge+text-in-buffer bb.l '' '42@2' cat > "$T/fatal.l" <<'E' %option noyywrap noyyalloc noyyrealloc noyyfree %{ #undef fprintf #define fprintf(file, fmt, msg) printf("fatal:%s", msg) %} %% a ; %% void *yyalloc(yy_size_t n){ static int once; if(!once++) printf("A"); return malloc(n); } void *yyrealloc(void *p, yy_size_t n){ return realloc(p, n); } void yyfree(void *p){ free(p); } int main(void){ yylex(); yy_fatal_error("x"); } E check own-alloc+fprintf-hook fatal.l '' 'Afatal:x' cat > "$T/hdr.l" <<'E' %option noyywrap reentrant header-file="h.h" prefix="p" %% .|\n ; E if (cd "$T" && $FLEX -o h.c hdr.l && printf '#include "h.h"\nint main(void){ yyscan_t s; plex_init(&s); plex_destroy(s); return 0; }\n' > m.c && $CC -c m.c 2>err.txt); then pass=$((pass+1)); else echo "FAIL header-file"; head -5 "$T/err.txt"; fail=$((fail+1)); fi (cd "$T" && $FLEX -t basic.l | grep -q yylex) && pass=$((pass+1)) || { echo "FAIL -t"; fail=$((fail+1)); } (cd "$T" && $FLEX basic.l && [ -s lex.yy.c ] && $FLEX -Pfoo basic.l && [ -s lex.foo.c ]) && pass=$((pass+1)) || { echo "FAIL default output"; fail=$((fail+1)); } (cd "$T" && echo '%option c++' > cc.l && echo '%%' >> cc.l && ! $FLEX -o /dev/null cc.l 2>/dev/null) && pass=$((pass+1)) || { echo "FAIL c++ must be an error"; fail=$((fail+1)); } echo "$pass passed, $fail failed" [ "$fail" = 0 ] Loading
lib/flex/flex.cpp +3 −1 Changes for lib/flex/flex.cpp: 3 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -1988,6 +1988,7 @@ std::string CodeGenerator::generateSource() { if (!o.noUnistd) out << "#ifndef YY_NO_UNISTD_H\n#include <unistd.h>\n#endif\n"; if (!o.extraType.empty()) out << "#define YY_EXTRA_TYPE " << o.extraType << "\n"; out << "#ifndef YY_EXTRA_TYPE\n#define YY_EXTRA_TYPE void *\n#endif\n\n"; // ---- scanner state ---- Loading Loading @@ -2021,7 +2022,8 @@ std::string CodeGenerator::generateSource() { // yywrap: without noyywrap the program brings its own, or -lfl would if (o.yywrap) { out << "int yywrap( FX_PROTO );\n"; if (!hasWord(s.userCode, o.prefix == "yy" ? "yywrap" : o.prefix + "wrap") && !hasWord(s.userCode, "yywrap")) const std::string wrap = o.prefix + "wrap", code = s.prologue + s.userCode; if (!hasWord(code, wrap) && !hasWord(code, "yywrap")) out << "#if defined(__GNUC__) || defined(__clang__)\n__attribute__((weak))\n#endif\n" "int yywrap( FX_PROTO ) { FX_UNUSED; return 1; }\n"; } Loading
lib/flex/test/run.sh 0 → 100644 +348 −0 Changes for lib/flex/test/run.sh: 348 added lines, 0 removed lines. Original line number Diff line number Diff line #!/bin/bash # flex test suite: usage: run.sh FLEX CC (FLEX: the fresh binary's flex applet) # Each case is a scanner, its input, and the output it has to print. FLEX=${1:-flex}; CC=${2:-cc} T=$(mktemp -d); trap 'rm -rf "$T"' EXIT pass=0; fail=0 # what -lfl would bring echo 'extern int yylex(); __attribute__((weak)) int main(void){ yylex(); return 0; }' > "$T/m0.c" # check NAME LFILE INPUT EXPECTED check() { local name=$1 l=$2 input=$3 want=$4 got if ! (cd "$T" && $FLEX -o s.c "$l" 2>err.txt && $CC -std=gnu99 -Wall -Werror=implicit-function-declaration -Wno-unused -o s s.c m0.c 2>>err.txt); then echo "FAIL $name (build)"; head -8 "$T/err.txt"; fail=$((fail+1)); return fi got=$(printf "$input" | "$T/s" 2>&1) if [ "$got" = "$want" ]; then pass=$((pass+1)); else echo "FAIL $name"; echo " want: $want"; echo " got: $got"; fail=$((fail+1)) fi } cat > "$T/basic.l" <<'E' %option noyywrap %% [0-9]+ printf("N(%s)", yytext); if|then { printf("K(%s)", yytext); } [a-z]+ printf("I(%s/%d)", yytext, yyleng); \n printf("|%d", yylineno); E check longest+priority basic.l 'if iff 12\nx\n' 'K(if) I(iff/3) N(12)|2I(x/1)|3' cat > "$T/alt.l" <<'E' %option noyywrap %% a | b | c printf("X"); .|\n ; E check bar-action alt.l 'abcd' 'XXX' cat > "$T/bol.l" <<'E' %option noyywrap %% ^a printf("B"); a$ printf("E"); a printf("M"); \n printf("|"); . ; E check bol+eol bol.l 'aa\nxa\naxa' 'BE|E|BM' cat > "$T/trail.l" <<'E' %option noyywrap %% foo/bar printf("[%s]", yytext); a*/a*b printf("<%s>", yytext); .|\n printf("%s", yytext); E check trailing trail.l 'foobar foo aab' '[foo]bar foo <aa>b' cat > "$T/more.l" <<'E' %option noyywrap %% mega- yymore(); kludge printf("[%s]", yytext); .|\n ; E check yymore more.l 'mega-kludge' '[mega-kludge]' cat > "$T/rej.l" <<'E' %option noyywrap %{ int n; %} %% frob n++; REJECT; [^ \t\n]+ n++; .|\n ; %% int main(void){ yylex(); printf("%d", n); return 0; } E check reject rej.l 'frob x' '3' cat > "$T/less.l" <<'E' %option noyywrap %% foobar { printf("[%s]", yytext); yyless(3); printf("[%s]", yytext); } bar printf("B"); \n ; E check yyless less.l 'foobar\n' '[foobar][foo]B' cat > "$T/putin.l" <<'E' %option noyywrap %% "(" { int c; while((c=input())!=')' && c) putchar(c); } x { unput('z'); unput('y'); } y printf("Y"); z printf("Z"); .|\n ; E check input+unput putin.l '(ab)x' 'abYZ' cat > "$T/array.l" <<'E' %array %option noyywrap %% [a-z]+ printf("[%s]", yytext); .|\n ; %% extern char yytext[]; E check array array.l 'ab cd' '[ab][cd]' cat > "$T/cond.l" <<'E' %option noyywrap stack %x C %s I %% "/*" { yy_push_state(C); } <C>"*/" { yy_pop_state(); } <C>.|\n ; <I,INITIAL>a printf("A"); <*>b printf("B"); .|\n ; <<EOF>> { printf("E%d", YY_START); yyterminate(); } <C><<EOF>> { printf("U"); yyterminate(); } E check conditions cond.l 'a/*ab*/b' 'ABBE0' check eof-in-condition cond.l 'a/*x' 'AU' cat > "$T/block.l" <<'E' %option noyywrap %x Q hex [0-9a-f] %% \" BEGIN(Q); <Q>{ /* comment */ \" BEGIN(INITIAL); {hex}+ printf("H%s", yytext); <<EOF>> { printf("!"); return 0; } .|\n ; } /* <Q> */ <Q>x printf("never"); .|\n ; E check condition-block block.l 'x"ag"x' 'Ha' cat > "$T/case.l" <<'E' %option noyywrap case-insensitive %% select printf("S"); [a-c]+ printf("C"); .|\n ; E check case-insensitive case.l 'SeLeCt ABC' 'SC' cat > "$T/flags.l" <<'E' %option noyywrap %% (?i:abc)def printf("1"); (?s:a.b) printf("2"); (?x: x y /* c */ z ) printf("3"); [a-z]{-}[aeiou]+q printf("4"); [[:^digit:]]{+}[0]q printf("5"); (?# nothing )w printf("6"); .|\n ; E check group-flags flags.l 'ABcdef a\nb xyz bcq 0q w' '12345 6' 2>/dev/null cat > "$T/rep.l" <<'E' %option noyywrap d [0-9] %% {d}{2,3}x printf("A"); {d}{4}y printf("B"); (ab)+ printf("C%d", yyleng); "lit*" printf("D"); \x41\101 printf("E"); .|\n ; E check repeat rep.l '12x 1234y ababab lit* AA' 'AB C6 D E' cat > "$T/echo.l" <<'E' %option noyywrap %% a ; E check default-echo echo.l 'xay\n' 'xy' cat > "$T/jam.l" <<'E' %option noyywrap nodefault %% a ; E check nodefault jam.l 'b' 'flex scanner jammed' cat > "$T/nul.l" <<'E' %option noyywrap 8bit %% \0 printf("N"); [\x80-\xff]+ printf("H%d", yyleng); .|\n ; E check binary nul.l 'a\0b\377\200' 'NH2' cat > "$T/big.l" <<'E' %option noyywrap %% a+ printf("%d\n", yyleng); \n printf("L%d\n", yylineno); . ; E input=$(head -c 100000 /dev/zero | tr '\0' a) check long-token big.l "$input\n" "100000 L2" cat > "$T/scan.l" <<'E' %option noyywrap %% [a-z]+ printf("[%s]", yytext); .|\n ; %% int main(void){ char b[8] = "ab cd\0\0"; YY_BUFFER_STATE h = yy_scan_string("xy zw"); yylex(); yy_delete_buffer(h); h = yy_scan_bytes("qr st", 2); yylex(); yy_delete_buffer(h); h = yy_scan_buffer(b, 7); yylex(); yy_delete_buffer(h); printf(" %d", b[0]=='a' && b[3]=='c'); yylex_destroy(); return 0; } E check scan-api scan.l '' '[xy][zw][qr][ab][cd] 1' cat > "$T/stack.l" <<'E' %option noyywrap %% "<" { yypush_buffer_state(yy_scan_string("in")); } <<EOF>> { yypop_buffer_state(); if(!YY_CURRENT_BUFFER) yyterminate(); } [a-z]+ printf("[%s]", yytext); .|\n ; E check buffer-stack stack.l 'a<b' '[a][in][b]' cat > "$T/wrap.l" <<'E' %{ static int files = 1; int yywrap(void){ if(files--){ yy_scan_string("more"); return 0; } return 1; } %} %% [a-z]+ printf("[%s]", yytext); .|\n ; E check yywrap wrap.l 'one' '[one][more]' cat > "$T/hooks.l" <<'E' %option noyywrap %{ static int col; #define YY_USER_ACTION col += yyleng; #define YY_USER_INIT printf("I"); #define YY_INPUT(buf,result,max) { static const char *s="abc"; result = *s ? (buf[0]=*s++, 1) : 0; } %} %% [a-z] printf("%d", col); E check hooks hooks.l '' 'I123' cat > "$T/re.l" <<'E' %option reentrant noyywrap prefix="core_yy" extra-type="int *" %% [a-z]+ { (*yyextra)++; printf("[%s:%d]", yytext, *yyextra); } x+y { BEGIN(INITIAL); yyless(1); } .|\n ; %% int main(void){ yyscan_t a, b; int na = 0, nb = 10; YY_BUFFER_STATE ha, hb; core_yylex_init_extra(&na, &a); core_yylex_init(&b); core_yyset_extra(&nb, b); ha = core_yy_scan_string("aa bb", a); hb = core_yy_scan_string("cc", b); core_yylex(a); core_yylex(b); core_yy_delete_buffer(ha, a); core_yy_delete_buffer(hb, b); printf(" %s", core_yyget_extra(a) == &na ? "ok" : "bad"); core_yylex_destroy(a); core_yylex_destroy(b); return 0; } E check reentrant+prefix re.l '' '[aa:1][bb:2][cc:11] ok' cat > "$T/bb.l" <<'E' %option reentrant bison-bridge bison-locations noyywrap %{ typedef int YYSTYPE; typedef struct { int first; } YYLTYPE; %} %% [0-9]+ { *yylval = atoi(yytext); yylloc->first = yytext - (char *) yyextra; return 1; } .|\n ; %% int main(void){ yyscan_t s; YYSTYPE v; YYLTYPE l; char buf[] = " 42\0"; yylex_init(&s); yyset_extra(buf, s); yy_scan_buffer(buf, sizeof(buf), s); while(yylex(&v, &l, s)) printf("%d@%d", v, l.first); yylex_destroy(s); return 0; } E check bison-bridge+text-in-buffer bb.l '' '42@2' cat > "$T/fatal.l" <<'E' %option noyywrap noyyalloc noyyrealloc noyyfree %{ #undef fprintf #define fprintf(file, fmt, msg) printf("fatal:%s", msg) %} %% a ; %% void *yyalloc(yy_size_t n){ static int once; if(!once++) printf("A"); return malloc(n); } void *yyrealloc(void *p, yy_size_t n){ return realloc(p, n); } void yyfree(void *p){ free(p); } int main(void){ yylex(); yy_fatal_error("x"); } E check own-alloc+fprintf-hook fatal.l '' 'Afatal:x' cat > "$T/hdr.l" <<'E' %option noyywrap reentrant header-file="h.h" prefix="p" %% .|\n ; E if (cd "$T" && $FLEX -o h.c hdr.l && printf '#include "h.h"\nint main(void){ yyscan_t s; plex_init(&s); plex_destroy(s); return 0; }\n' > m.c && $CC -c m.c 2>err.txt); then pass=$((pass+1)); else echo "FAIL header-file"; head -5 "$T/err.txt"; fail=$((fail+1)); fi (cd "$T" && $FLEX -t basic.l | grep -q yylex) && pass=$((pass+1)) || { echo "FAIL -t"; fail=$((fail+1)); } (cd "$T" && $FLEX basic.l && [ -s lex.yy.c ] && $FLEX -Pfoo basic.l && [ -s lex.foo.c ]) && pass=$((pass+1)) || { echo "FAIL default output"; fail=$((fail+1)); } (cd "$T" && echo '%option c++' > cc.l && echo '%%' >> cc.l && ! $FLEX -o /dev/null cc.l 2>/dev/null) && pass=$((pass+1)) || { echo "FAIL c++ must be an error"; fail=$((fail+1)); } echo "$pass passed, $fail failed" [ "$fail" = 0 ]