From 284f1fb0ba7c2a5de6439761f0df0cc74f96e8b8 Mon Sep 17 00:00:00 2001 From: Adrian Thurston Date: Thu, 23 Mar 2017 12:38:32 +0800 Subject: C codegen: test p VS pe in goto/call/ret in EOF actions If an fgoto, fcall or fret is issued in an EOF action check p VS pe before continuing. If at the end of the block then re-issue the eof test. If a program properly issues an fhold before the control flow the program won't be affected. If the user neglects to do this we won't run off the end of the buffer. --- ragel/cdcodegen.cpp | 8 +++ ragel/cdcodegen.h | 2 + ragel/cdflat.cpp | 52 ++++++++++++++++--- ragel/cdgoto.cpp | 56 +++++++++++++++++---- ragel/cdipgoto.cpp | 67 ++++++++++++++++++++++--- ragel/cdipgoto.h | 2 + ragel/cdtable.cpp | 54 ++++++++++++++++---- ragel/cstable.cpp | 41 +++++++++++---- test/eofcall1.rl | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/eofcall2.rl | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/eofgoto1.rl | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/eofgoto2.rl | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/eofret1.rl | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 930 insertions(+), 44 deletions(-) create mode 100644 test/eofcall1.rl create mode 100644 test/eofcall2.rl create mode 100644 test/eofgoto1.rl create mode 100644 test/eofgoto2.rl create mode 100644 test/eofret1.rl diff --git a/ragel/cdcodegen.cpp b/ragel/cdcodegen.cpp index c2f1381c..96d85010 100644 --- a/ragel/cdcodegen.cpp +++ b/ragel/cdcodegen.cpp @@ -361,6 +361,14 @@ string FsmCodeGen::WIDE_KEY( RedStateAp *state, Key key ) } } +void FsmCodeGen::EOF_CHECK( ostream &ret ) +{ + ret << + " if ( " << P() << " == " << PE() << " )\n" + " goto _test_eof;\n"; + + testEofUsed = true; +} void FsmCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish ) diff --git a/ragel/cdcodegen.h b/ragel/cdcodegen.h index d8fe62dd..b9a84906 100644 --- a/ragel/cdcodegen.h +++ b/ragel/cdcodegen.h @@ -131,6 +131,8 @@ protected: string FIRST_FINAL() { return DATA_PREFIX() + "first_final"; } string CTXDATA() { return DATA_PREFIX() + "ctxdata"; } + void EOF_CHECK( ostream &ret ); + void INLINE_LIST( ostream &ret, GenInlineList *inlineList, int targState, bool inFinish, bool csForced ); virtual void GOTO( ostream &ret, int gotoDest, bool inFinish ) = 0; diff --git a/ragel/cdflat.cpp b/ragel/cdflat.cpp index 6010f980..b28a95a6 100644 --- a/ragel/cdflat.cpp +++ b/ragel/cdflat.cpp @@ -454,15 +454,32 @@ void FlatCodeGen::LOCATE_TRANS() void FlatCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { - ret << "{" << vCS() << " = " << gotoDest << "; " << - CTRL_FLOW() << "goto _again;}"; + ret << "{"; + + ret << vCS() << " = " << gotoDest << ";"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void FlatCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { - ret << "{" << vCS() << " = ("; + ret << "{"; + + ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); - ret << "); " << CTRL_FLOW() << "goto _again;}"; + ret << "); "; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void FlatCodeGen::CURS( ostream &ret, bool inFinish ) @@ -494,8 +511,16 @@ void FlatCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish INLINE_LIST( ret, prePushExpr, 0, false, false ); } - ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << - callDest << "; " << CTRL_FLOW() << "goto _again;}"; + ret << "{"; + + ret << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << callDest << ";"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; if ( prePushExpr != 0 ) ret << "}"; @@ -511,7 +536,13 @@ void FlatCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, targState, inFinish, false ); - ret << "); " << CTRL_FLOW() << "goto _again;}"; + ret << ");"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + ret << "}"; if ( prePushExpr != 0 ) ret << "}"; @@ -528,7 +559,12 @@ void FlatCodeGen::RET( ostream &ret, bool inFinish ) ret << "}"; } - ret << CTRL_FLOW() << "goto _again;}"; + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void FlatCodeGen::BREAK( ostream &ret, int targState, bool csForced ) diff --git a/ragel/cdgoto.cpp b/ragel/cdgoto.cpp index e434143a..86b3d23f 100644 --- a/ragel/cdgoto.cpp +++ b/ragel/cdgoto.cpp @@ -543,15 +543,32 @@ std::ostream &GotoCodeGen::FINISH_CASES() void GotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { - ret << "{" << vCS() << " = " << gotoDest << "; " << - CTRL_FLOW() << "goto _again;}"; + ret << "{"; + + ret << vCS() << " = " << gotoDest << ";"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void GotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { - ret << "{" << vCS() << " = ("; + ret << "{"; + + ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); - ret << "); " << CTRL_FLOW() << "goto _again;}"; + ret << ");"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void GotoCodeGen::CURS( ostream &ret, bool inFinish ) @@ -583,8 +600,16 @@ void GotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish INLINE_LIST( ret, prePushExpr, 0, false, false ); } - ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << - callDest << "; " << CTRL_FLOW() << "goto _again;}"; + ret << "{"; + + ret << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << callDest << ";"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; if ( prePushExpr != 0 ) ret << "}"; @@ -597,9 +622,18 @@ void GotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, INLINE_LIST( ret, prePushExpr, 0, false, false ); } - ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; + ret << "{"; + + ret << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, targState, inFinish, false ); - ret << "); " << CTRL_FLOW() << "goto _again;}"; + ret << ");"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; if ( prePushExpr != 0 ) ret << "}"; @@ -615,7 +649,11 @@ void GotoCodeGen::RET( ostream &ret, bool inFinish ) ret << "}"; } - ret << CTRL_FLOW() << "goto _again;}"; + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + ret << "}"; } void GotoCodeGen::BREAK( ostream &ret, int targState, bool csForced ) diff --git a/ragel/cdipgoto.cpp b/ragel/cdipgoto.cpp index 3abbfbe2..05c92994 100644 --- a/ragel/cdipgoto.cpp +++ b/ragel/cdipgoto.cpp @@ -34,9 +34,25 @@ bool IpGotoCodeGen::useAgainLabel() redFsm->anyRegNextStmt(); } +void IpGotoCodeGen::EOF_CHECK( ostream &ret, int gotoDest ) +{ + ret << + " if ( " << P() << " == " << PE() << " )\n" + " goto _test_eof" << gotoDest << ";\n"; + + testEofUsed = true; +} + void IpGotoCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { - ret << "{" << CTRL_FLOW() << "goto st" << gotoDest << ";}"; + ret << "{"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret, gotoDest ); + + ret << CTRL_FLOW() << "goto st" << gotoDest << ";"; + + ret << "}"; } void IpGotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish ) @@ -46,8 +62,14 @@ void IpGotoCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFini INLINE_LIST( ret, prePushExpr, 0, false, false ); } - ret << "{" << STACK() << "[" << TOP() << "++] = " << targState << - "; " << CTRL_FLOW() << "goto st" << callDest << ";}"; + ret << "{" << STACK() << "[" << TOP() << "++] = " << targState << ";"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret, callDest ); + + ret << CTRL_FLOW() << "goto st" << callDest << ";"; + + ret << "}"; if ( prePushExpr != 0 ) ret << "}"; @@ -60,9 +82,18 @@ void IpGotoCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targStat INLINE_LIST( ret, prePushExpr, 0, false, false ); } - ret << "{" << STACK() << "[" << TOP() << "++] = " << targState << "; " << vCS() << " = ("; + ret << "{"; + + ret << STACK() << "[" << TOP() << "++] = " << targState << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); - ret << "); " << CTRL_FLOW() << "goto _again;}"; + ret << ");"; + + if ( inFinish && !noEnd ) + FsmCodeGen::EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; if ( prePushExpr != 0 ) ret << "}"; @@ -78,14 +109,27 @@ void IpGotoCodeGen::RET( ostream &ret, bool inFinish ) ret << "}"; } - ret << CTRL_FLOW() << "goto _again;}"; + if ( inFinish && !noEnd ) + FsmCodeGen::EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void IpGotoCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { - ret << "{" << vCS() << " = ("; + ret << "{"; + + ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); - ret << "); " << CTRL_FLOW() << "goto _again;}"; + ret << ");"; + + if ( inFinish && !noEnd ) + FsmCodeGen::EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + ret << "}"; } void IpGotoCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish ) @@ -350,6 +394,13 @@ void IpGotoCodeGen::setLabelsNeeded() } } } + + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { + if ( st->eofAction != 0 ) { + for ( GenActionTable::Iter item = st->eofAction->key; item.lte(); item++ ) + setLabelsNeeded( item->value->inlineList ); + } + } } if ( !noEnd ) { diff --git a/ragel/cdipgoto.h b/ragel/cdipgoto.h index c869e1f9..4e92926e 100644 --- a/ragel/cdipgoto.h +++ b/ragel/cdipgoto.h @@ -60,6 +60,8 @@ public: protected: bool useAgainLabel(); + void EOF_CHECK( ostream &ret, int gotoDest ); + /* Called from GotoCodeGen::STATE_GOTOS just before writing the gotos for * each state. */ bool IN_TRANS_ACTIONS( RedStateAp *state ); diff --git a/ragel/cdtable.cpp b/ragel/cdtable.cpp index 2218839e..6bcb79ea 100644 --- a/ragel/cdtable.cpp +++ b/ragel/cdtable.cpp @@ -666,15 +666,31 @@ void TabCodeGen::LOCATE_TRANS() void TabCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { - ret << "{" << vCS() << " = " << gotoDest << "; " << - CTRL_FLOW() << "goto _again;}"; + ret << "{"; + + ret << vCS() << " = " << gotoDest << ";"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void TabCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { - ret << "{" << vCS() << " = ("; + ret << "{"; + ret << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish, false ); - ret << "); " << CTRL_FLOW() << "goto _again;}"; + ret << "); "; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void TabCodeGen::CURS( ostream &ret, bool inFinish ) @@ -706,8 +722,14 @@ void TabCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish INLINE_LIST( ret, prePushExpr, 0, false, false ); } - ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << - callDest << "; " << CTRL_FLOW() << "goto _again;}"; + ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << callDest << ";"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; if ( prePushExpr != 0 ) ret << "}"; @@ -720,9 +742,18 @@ void TabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, INLINE_LIST( ret, prePushExpr, 0, false, false ); } - ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; + ret << "{"; + + ret << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, targState, inFinish, false ); - ret << "); " << CTRL_FLOW() << "goto _again;}"; + ret << ");"; + + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; if ( prePushExpr != 0 ) ret << "}"; @@ -739,7 +770,12 @@ void TabCodeGen::RET( ostream &ret, bool inFinish ) ret << "}"; } - ret << CTRL_FLOW() << "goto _again;}"; + if ( inFinish && !noEnd ) + EOF_CHECK( ret ); + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void TabCodeGen::BREAK( ostream &ret, int targState, bool csForced ) diff --git a/ragel/cstable.cpp b/ragel/cstable.cpp index 72df0a63..13c9e738 100644 --- a/ragel/cstable.cpp +++ b/ragel/cstable.cpp @@ -618,15 +618,22 @@ std::ostream &CSharpTabCodeGen::TRANS_ACTIONS_WI() void CSharpTabCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish ) { - ret << "{" << vCS() << " = " << gotoDest << "; " << - CTRL_FLOW() << "goto _again;}"; + ret << "{" << vCS() << " = " << gotoDest << ";"; + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void CSharpTabCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish ) { ret << "{" << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, 0, inFinish ); - ret << "); " << CTRL_FLOW() << "goto _again;}"; + ret << ");"; + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void CSharpTabCodeGen::CURS( ostream &ret, bool inFinish ) @@ -658,8 +665,13 @@ void CSharpTabCodeGen::CALL( ostream &ret, int callDest, int targState, bool inF INLINE_LIST( ret, prePushExpr, 0, false ); } - ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << - callDest << "; " << CTRL_FLOW() << "goto _again;}"; + ret << "{"; + + ret << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << callDest << ";"; + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; if ( prePushExpr != 0 ) ret << "}"; @@ -672,9 +684,15 @@ void CSharpTabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targS INLINE_LIST( ret, prePushExpr, 0, false ); } - ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; + ret << "{"; + + ret << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = ("; INLINE_LIST( ret, ilItem->children, targState, inFinish ); - ret << "); " << CTRL_FLOW() << "goto _again;}"; + ret << ");"; + + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; if ( prePushExpr != 0 ) ret << "}"; @@ -682,8 +700,9 @@ void CSharpTabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targS void CSharpTabCodeGen::RET( ostream &ret, bool inFinish ) { - ret << "{" << vCS() << " = " << STACK() << "[--" << - TOP() << "]; "; + ret << "{"; + + ret << vCS() << " = " << STACK() << "[--" << TOP() << "]; "; if ( postPopExpr != 0 ) { ret << "{"; @@ -691,7 +710,9 @@ void CSharpTabCodeGen::RET( ostream &ret, bool inFinish ) ret << "}"; } - ret << CTRL_FLOW() << "goto _again;}"; + ret << CTRL_FLOW() << "goto _again;"; + + ret << "}"; } void CSharpTabCodeGen::BREAK( ostream &ret, int targState ) diff --git a/test/eofcall1.rl b/test/eofcall1.rl new file mode 100644 index 00000000..598f8705 --- /dev/null +++ b/test/eofcall1.rl @@ -0,0 +1,138 @@ +/* + * @LANG: c + * + * Testing fcall in an EOF action. + */ + +#include +#include +#include + +int neg; +int value; + +%%{ + machine atoi; + + action begin { + neg = 0; + value = 0; + } + + action see_neg + { + neg = 1; + } + + action add_digit + { + value = value * 10 + ( int ) ( fc - 48 ); + } + + action finish + { + if ( neg != 0 ) { + value = -1 * value; + } + } + + action print + { + printf( "%d", value ); + printf( "%s", "\n" ); + } + + atoi = ( + ('-'@see_neg | '+')? (digit @add_digit)+ + ) >begin %finish; + + main := atoi '\n' @print %{ printf("goto extra\n"); fcall extra; }; + + extra := "" %{ printf("done: %d\n", (int)(p-data)); }; + +}%% + +%% write data; +int cs; +int blen; +char buffer[1024]; +int top, stack[1]; + +void init() +{ + value = 0; + neg = 0; + %% write init; +} + +void exec( char *data, int len ) +{ + char *p = data; + char *pe = data + len; + char *eof = pe; + %% write exec; +} + +void finish( ) +{ + if ( cs >= atoi_first_final ) + printf( "ACCEPT\n" ); + else + printf( "FAIL\n" ); + +} + +char *inp[] = { + "1\n", + "12\n", + "222222\n", + "+2123\n", + "213 3213\n", + "-12321\n", + "--123\n", + "-99\n", + " -3000\n", +}; + +int inplen = 9; + +int main( ) +{ + int i; + for ( i = 0; i < inplen; i++ ) { + init(); + exec( inp[i], strlen(inp[i]) ); + finish(); + } + return 0; +} + +#ifdef ___________OUTPUT___________ +1 +goto extra +done: 2 +ACCEPT +12 +goto extra +done: 3 +ACCEPT +222222 +goto extra +done: 7 +ACCEPT +2123 +goto extra +done: 6 +ACCEPT +FAIL +-12321 +goto extra +done: 7 +ACCEPT +FAIL +-99 +goto extra +done: 4 +ACCEPT +FAIL +#endif diff --git a/test/eofcall2.rl b/test/eofcall2.rl new file mode 100644 index 00000000..26fbf724 --- /dev/null +++ b/test/eofcall2.rl @@ -0,0 +1,138 @@ +/* + * @LANG: c + * + * Testing fcall * in an EOF action. + */ + +#include +#include +#include + +int neg; +int value; + +%%{ + machine atoi; + + action begin { + neg = 0; + value = 0; + } + + action see_neg + { + neg = 1; + } + + action add_digit + { + value = value * 10 + ( int ) ( fc - 48 ); + } + + action finish + { + if ( neg != 0 ) { + value = -1 * value; + } + } + + action print + { + printf( "%d", value ); + printf( "%s", "\n" ); + } + + atoi = ( + ('-'@see_neg | '+')? (digit @add_digit)+ + ) >begin %finish; + + main := atoi '\n' @print %{ printf("goto extra\n"); fcall *fentry(extra); }; + + extra := "" %{ printf("done: %d\n", (int)(p-data)); }; + +}%% + +%% write data; +int cs; +int blen; +char buffer[1024]; +int top, stack[1]; + +void init() +{ + value = 0; + neg = 0; + %% write init; +} + +void exec( char *data, int len ) +{ + char *p = data; + char *pe = data + len; + char *eof = pe; + %% write exec; +} + +void finish( ) +{ + if ( cs >= atoi_first_final ) + printf( "ACCEPT\n" ); + else + printf( "FAIL\n" ); + +} + +char *inp[] = { + "1\n", + "12\n", + "222222\n", + "+2123\n", + "213 3213\n", + "-12321\n", + "--123\n", + "-99\n", + " -3000\n", +}; + +int inplen = 9; + +int main( ) +{ + int i; + for ( i = 0; i < inplen; i++ ) { + init(); + exec( inp[i], strlen(inp[i]) ); + finish(); + } + return 0; +} + +#ifdef ___________OUTPUT___________ +1 +goto extra +done: 2 +ACCEPT +12 +goto extra +done: 3 +ACCEPT +222222 +goto extra +done: 7 +ACCEPT +2123 +goto extra +done: 6 +ACCEPT +FAIL +-12321 +goto extra +done: 7 +ACCEPT +FAIL +-99 +goto extra +done: 4 +ACCEPT +FAIL +#endif diff --git a/test/eofgoto1.rl b/test/eofgoto1.rl new file mode 100644 index 00000000..6ce530a9 --- /dev/null +++ b/test/eofgoto1.rl @@ -0,0 +1,137 @@ +/* + * @LANG: c + * + * Testing fgoto in an EOF action. + */ + +#include +#include +#include + +int neg; +int value; + +%%{ + machine atoi; + + action begin { + neg = 0; + value = 0; + } + + action see_neg + { + neg = 1; + } + + action add_digit + { + value = value * 10 + ( int ) ( fc - 48 ); + } + + action finish + { + if ( neg != 0 ) { + value = -1 * value; + } + } + + action print + { + printf( "%d", value ); + printf( "%s", "\n" ); + } + + atoi = ( + ('-'@see_neg | '+')? (digit @add_digit)+ + ) >begin %finish; + + extra := "" %{ printf("done: %d\n", (int)(p-data)); }; + + main := atoi '\n' @print %{ printf("goto extra\n"); fgoto extra; }; + +}%% + +%% write data; +int cs; +int blen; +char buffer[1024]; + +void init() +{ + value = 0; + neg = 0; + %% write init; +} + +void exec( char *data, int len ) +{ + char *p = data; + char *pe = data + len; + char *eof = pe; + %% write exec; +} + +void finish( ) +{ + if ( cs >= atoi_first_final ) + printf( "ACCEPT\n" ); + else + printf( "FAIL\n" ); + +} + +char *inp[] = { + "1\n", + "12\n", + "222222\n", + "+2123\n", + "213 3213\n", + "-12321\n", + "--123\n", + "-99\n", + " -3000\n", +}; + +int inplen = 9; + +int main( ) +{ + int i; + for ( i = 0; i < inplen; i++ ) { + init(); + exec( inp[i], strlen(inp[i]) ); + finish(); + } + return 0; +} + +#ifdef ___________OUTPUT___________ +1 +goto extra +done: 2 +ACCEPT +12 +goto extra +done: 3 +ACCEPT +222222 +goto extra +done: 7 +ACCEPT +2123 +goto extra +done: 6 +ACCEPT +FAIL +-12321 +goto extra +done: 7 +ACCEPT +FAIL +-99 +goto extra +done: 4 +ACCEPT +FAIL +#endif diff --git a/test/eofgoto2.rl b/test/eofgoto2.rl new file mode 100644 index 00000000..0d6096a5 --- /dev/null +++ b/test/eofgoto2.rl @@ -0,0 +1,138 @@ +/* + * @LANG: c + * + * Testing fgoto * in an EOF action. + */ + +#include +#include +#include + +int neg; +int value; + + +%%{ + machine atoi; + + action begin { + neg = 0; + value = 0; + } + + action see_neg + { + neg = 1; + } + + action add_digit + { + value = value * 10 + ( int ) ( fc - 48 ); + } + + action finish + { + if ( neg != 0 ) { + value = -1 * value; + } + } + + action print + { + printf( "%d", value ); + printf( "%s", "\n" ); + } + + atoi = ( + ('-'@see_neg | '+')? (digit @add_digit)+ + ) >begin %finish; + + main := atoi '\n' @print %{ printf("goto extra\n"); fgoto *fentry(extra); }; + + extra := "" %{ printf("done: %d\n", (int)(p-data)); }; + +}%% + +%% write data; +int cs; +int blen; +char buffer[1024]; + +void init() +{ + value = 0; + neg = 0; + %% write init; +} + +void exec( char *data, int len ) +{ + char *p = data; + char *pe = data + len; + char *eof = pe; + %% write exec; +} + +void finish( ) +{ + if ( cs >= atoi_first_final ) + printf( "ACCEPT\n" ); + else + printf( "FAIL\n" ); + +} + +char *inp[] = { + "1\n", + "12\n", + "222222\n", + "+2123\n", + "213 3213\n", + "-12321\n", + "--123\n", + "-99\n", + " -3000\n", +}; + +int inplen = 9; + +int main( ) +{ + int i; + for ( i = 0; i < inplen; i++ ) { + init(); + exec( inp[i], strlen(inp[i]) ); + finish(); + } + return 0; +} + +#ifdef ___________OUTPUT___________ +1 +goto extra +done: 2 +ACCEPT +12 +goto extra +done: 3 +ACCEPT +222222 +goto extra +done: 7 +ACCEPT +2123 +goto extra +done: 6 +ACCEPT +FAIL +-12321 +goto extra +done: 7 +ACCEPT +FAIL +-99 +goto extra +done: 4 +ACCEPT +FAIL +#endif diff --git a/test/eofret1.rl b/test/eofret1.rl new file mode 100644 index 00000000..5f90263f --- /dev/null +++ b/test/eofret1.rl @@ -0,0 +1,141 @@ +/* + * @LANG: c + * + * Testing fcall in an EOF action. + */ + +#include +#include +#include + +int neg; +int value; + +%%{ + machine atoi; + + action begin { + neg = 0; + value = 0; + } + + action see_neg + { + neg = 1; + } + + action add_digit + { + value = value * 10 + ( int ) ( fc - 48 ); + } + + action finish + { + if ( neg != 0 ) { + value = -1 * value; + } + } + + action print + { + printf( "%d", value ); + printf( "%s", "\n" ); + } + + atoi = ( + ('-'@see_neg | '+')? (digit @add_digit)+ + ) >begin %finish; + + main := atoi '\n' @print %{ printf("goto extra\n"); fret; }; + + extra := "" %{ printf("done: %d\n", (int)(p-data)); }; + +}%% + +%% write data; +int cs; +int blen; +char buffer[1024]; +int top, stack[1]; + +void init() +{ + value = 0; + neg = 0; + %% write init; + + stack[0] = atoi_en_extra; + top = 1; +} + +void exec( char *data, int len ) +{ + char *p = data; + char *pe = data + len; + char *eof = pe; + %% write exec; +} + +void finish( ) +{ + if ( cs >= atoi_first_final ) + printf( "ACCEPT\n" ); + else + printf( "FAIL\n" ); + +} + +char *inp[] = { + "1\n", + "12\n", + "222222\n", + "+2123\n", + "213 3213\n", + "-12321\n", + "--123\n", + "-99\n", + " -3000\n", +}; + +int inplen = 9; + +int main( ) +{ + int i; + for ( i = 0; i < inplen; i++ ) { + init(); + exec( inp[i], strlen(inp[i]) ); + finish(); + } + return 0; +} + +#ifdef ___________OUTPUT___________ +1 +goto extra +done: 2 +ACCEPT +12 +goto extra +done: 3 +ACCEPT +222222 +goto extra +done: 7 +ACCEPT +2123 +goto extra +done: 6 +ACCEPT +FAIL +-12321 +goto extra +done: 7 +ACCEPT +FAIL +-99 +goto extra +done: 4 +ACCEPT +FAIL +#endif -- cgit v1.2.1