From b19fd012b09fa0c750262318073d03e34ec84993 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 29 Mar 2007 01:44:45 +0000 Subject: [PATCH] Lemon change: compile the resulting parser with -DYYSTACKDEPTH=0 or set the "%stack_size" parameter to 0 in the grammar and the parser stack will be dynamically allocated using realloc() and free(). The default behavior is to have a finite depth stack. (CVS 3738) FossilOrigin-Name: 06719b741ab1a2df0371f6d587563cc81eb8880a --- manifest | 14 ++++----- manifest.uuid | 2 +- tool/lemon.c | 7 ----- tool/lempar.c | 85 ++++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 78 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index 945b021d54..c269d4e71c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Patch\sso\sthe\sthe\scode\scompiles\swith\s-DSQLITE_OMIT_CHECK=1.\s(CVS\s3737) -D 2007-03-29T00:08:25 +C Lemon\schange:\scompile\sthe\sresulting\sparser\swith\s-DYYSTACKDEPTH=0\sor\sset\nthe\s"%stack_size"\sparameter\sto\s0\sin\sthe\sgrammar\sand\sthe\sparser\sstack\nwill\sbe\sdynamically\sallocated\susing\srealloc()\sand\sfree().\s\sThe\sdefault\nbehavior\sis\sto\shave\sa\sfinite\sdepth\sstack.\s(CVS\s3738) +D 2007-03-29T01:44:46 F Makefile.in 1fe3d0b46e40fd684e1e61f8e8056cefed16de9f F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -370,8 +370,8 @@ F test/where3.test 0a30fe9808b0fa01c46d0fcf4fac0bf6cf75bb30 F test/where4.test b68496500bff496e83e76ae4ffb493b99064eac6 F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439 -F tool/lemon.c d3dff81e31c459dd18784d024a759b7229f66297 -F tool/lempar.c fdc1672e97f72f72e76553038501da40fec9d251 +F tool/lemon.c 3ac82886bff8096379fa4bfe5ea188e242bbaa47 +F tool/lempar.c 1c08d864e18ac4f146554c2fb76ae1ab751f776f F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133 F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8 F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf @@ -442,7 +442,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 53fff7d1f2f829010a2641c7738538b3155da4b2 -R a8b7b84401a648f00168521d709f0ebb +P 72cea358da4bd38af322f18f2a753171f7decaf8 +R 19096804931fc69bc6361fcf0c3ff22e U drh -Z 604fd965906231b9b5400c42a321a29e +Z 85e0303fabdca8721ceddd77f2f883b6 diff --git a/manifest.uuid b/manifest.uuid index 959e41a0e3..65ebd6e9e7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -72cea358da4bd38af322f18f2a753171f7decaf8 \ No newline at end of file +06719b741ab1a2df0371f6d587563cc81eb8880a \ No newline at end of file diff --git a/tool/lemon.c b/tool/lemon.c index bcb81e9271..dda4f007fc 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -3514,13 +3514,6 @@ int mhflag; /* Output in makeheaders format if true */ print_stack_union(out,lemp,&lineno,mhflag); fprintf(out, "#ifndef YYSTACKDEPTH\n"); lineno++; if( lemp->stacksize ){ - if( atoi(lemp->stacksize)<=0 ){ - ErrorMsg(lemp->filename,0, -"Illegal stack size: [%s]. The stack size should be an integer constant.", - lemp->stacksize); - lemp->errorcnt++; - lemp->stacksize = "100"; - } fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++; }else{ fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++; diff --git a/tool/lempar.c b/tool/lempar.c index 916b575127..5c0714be48 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -44,7 +44,8 @@ ** This is typically a union of many types, one of ** which is ParseTOKENTYPE. The entry in the union ** for base tokens is called "yy0". -** YYSTACKDEPTH is the maximum depth of the parser's stack. +** YYSTACKDEPTH is the maximum depth of the parser's stack. If +** zero the stack is dynamically sized using realloc() ** ParseARG_SDECL A static variable declaration for the %extra_argument ** ParseARG_PDECL A parameter declaration for the %extra_argument ** ParseARG_STORE Code to store %extra_argument into yypParser @@ -152,7 +153,12 @@ struct yyParser { int yyidx; /* Index of top element in stack */ int yyerrcnt; /* Shifts left before out of the error */ ParseARG_SDECL /* A place to hold %extra_argument */ +#if YYSTACKDEPTH<=0 + int yystksz; /* Current side of the stack */ + yyStackEntry *yystack; /* The parser's stack */ +#else yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ +#endif }; typedef struct yyParser yyParser; @@ -220,6 +226,29 @@ const char *ParseTokenName(int tokenType){ #endif } +#if YYSTACKDEPTH<=0 +/* +** Try to increase the size of the parser stack. +*/ +static void yyGrowStack(yyParser *p){ + int newSize; + yyStackEntry *pNew; + + newSize = p->yystksz*2 + 100; + pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); + if( pNew ){ + p->yystack = pNew; + p->yystksz = newSize; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack grows to %d entries!\n", + yyTracePrompt, p->yystksz); + } +#endif + } +} +#endif + /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like @@ -237,6 +266,9 @@ void *ParseAlloc(void *(*mallocProc)(size_t)){ pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); if( pParser ){ pParser->yyidx = -1; +#if YYSTACKDEPTH<=0 + yyGrowStack(pParser); +#endif } return pParser; } @@ -308,6 +340,9 @@ void ParseFree( yyParser *pParser = (yyParser*)p; if( pParser==0 ) return; while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); +#if YYSTACKDEPTH<=0 + free(pParser->yystack); +#endif (*freeProc)((void*)pParser); } @@ -399,6 +434,24 @@ static int yy_find_reduce_action( } } +/* +** The following routine is called if the stack overflows. +*/ +static void yyStackOverflow(yyParser *yypParser){ + ParseARG_FETCH; + yypParser->yyidx--; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); + } +#endif + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will execute if the parser + ** stack every overflows */ +%% + ParseARG_STORE; /* Suppress warning about unused %extra_argument var */ +} + /* ** Perform a shift action. */ @@ -410,21 +463,20 @@ static void yy_shift( ){ yyStackEntry *yytos; yypParser->yyidx++; +#if YYSTACKDEPTH>0 if( yypParser->yyidx>=YYSTACKDEPTH ){ - ParseARG_FETCH; - yypParser->yyidx--; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will execute if the parser - ** stack every overflows */ -%% - ParseARG_STORE; /* Suppress warning about unused %extra_argument var */ - return; + yyStackOverflow(yypParser); + return; } +#else + if( yypParser->yyidx>=yypParser->yystksz ){ + yyGrowStack(yypParser); + if( yypParser->yyidx>=yypParser->yystksz ){ + yyStackOverflow(yypParser); + return; + } + } +#endif yytos = &yypParser->yystack[yypParser->yyidx]; yytos->stateno = yyNewState; yytos->major = yyMajor; @@ -616,7 +668,10 @@ void Parse( /* (re)initialize the parser, if necessary */ yypParser = (yyParser*)yyp; if( yypParser->yyidx<0 ){ - /* if( yymajor==0 ) return; // not sure why this was here... */ + if( yypParser->yystksz <=0 ){ + yyStackOverflow(yypParser); + return; + } yypParser->yyidx = 0; yypParser->yyerrcnt = -1; yypParser->yystack[0].stateno = 0;