diff --git a/src/OpenFOAM/expressions/fields/fieldExprLemonParser.lyy-m4 b/src/OpenFOAM/expressions/fields/fieldExprLemonParser.lyy-m4 index b5054395c5..13b8f76470 100644 --- a/src/OpenFOAM/expressions/fields/fieldExprLemonParser.lyy-m4 +++ b/src/OpenFOAM/expressions/fields/fieldExprLemonParser.lyy-m4 @@ -7,7 +7,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -120,7 +120,8 @@ tmp_management() // ------------------------------------------------------------------------- // -%namespace {} +// File-scope visibility for exposed Lemon parser routines +%static // Use extra argument for the return value %extra_context { Foam::expressions::fieldExpr::parseDriver* driver } diff --git a/src/finiteVolume/expressions/patch/patchExprLemonParser.lyy-m4 b/src/finiteVolume/expressions/patch/patchExprLemonParser.lyy-m4 index 57a9e5eb63..8c5c613cc5 100644 --- a/src/finiteVolume/expressions/patch/patchExprLemonParser.lyy-m4 +++ b/src/finiteVolume/expressions/patch/patchExprLemonParser.lyy-m4 @@ -7,7 +7,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -66,7 +66,8 @@ tmp_management() // ------------------------------------------------------------------------- // -%namespace {} +// File-scope visibility for exposed Lemon parser routines +%static // Use extra argument for the return value %extra_context { Foam::expressions::patchExpr::parseDriver* driver } diff --git a/src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 b/src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 index 57a1f2144d..67c71a82d4 100644 --- a/src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 +++ b/src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 @@ -7,7 +7,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2019 OpenCFD Ltd. + Copyright (C) 2019-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -99,7 +99,8 @@ dnl // ------------------------------------------------------------------------- // -%namespace {} +// File-scope visibility for exposed Lemon parser routines +%static // Use extra argument for the return value %extra_context { Foam::expressions::volumeExpr::parseDriver* driver } diff --git a/wmake/etc/lempar.c b/wmake/etc/lempar.c index 819e0f61fd..d0819063b4 100644 --- a/wmake/etc/lempar.c +++ b/wmake/etc/lempar.c @@ -93,6 +93,12 @@ /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) +/* Default linkage for exposed parser routines is global +*/ +#ifndef YYFUNCAPI +# define YYFUNCAPI +#endif + /* Define the yytestcase() macro to be a no-op if is not already defined ** otherwise. ** @@ -251,14 +257,13 @@ static char *yyTracePrompt = 0; ** Outputs: ** None. */ -%namespace_begin +YYFUNCAPI void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ yyTraceFILE = TraceFILE; yyTracePrompt = zTracePrompt; if( yyTraceFILE==0 ) yyTracePrompt = 0; else if( yyTracePrompt==0 ) yyTraceFILE = 0; } -%namespace_end #endif /* NDEBUG */ #if defined(YYCOVERAGE) || !defined(NDEBUG) @@ -322,7 +327,7 @@ static int yyGrowStack(yyParser *p){ /* Initialize a new parser that has already been allocated. */ -%namespace_begin +YYFUNCAPI void ParseInit(void *yypRawParser ParseCTX_PDECL){ yyParser *yypParser = (yyParser*)yypRawParser; ParseCTX_STORE @@ -348,7 +353,6 @@ void ParseInit(void *yypRawParser ParseCTX_PDECL){ yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; #endif } -%namespace_end #ifndef Parse_ENGINEALWAYSONSTACK /* @@ -363,7 +367,7 @@ void ParseInit(void *yypRawParser ParseCTX_PDECL){ ** A pointer to a parser. This pointer is used in subsequent calls ** to Parse and ParseFree. */ -%namespace_begin +YYFUNCAPI void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){ yyParser *yypParser; yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); @@ -373,7 +377,6 @@ void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){ } return (void*)yypParser; } -%namespace_end #endif /* Parse_ENGINEALWAYSONSTACK */ @@ -433,7 +436,7 @@ static void yy_pop_parser_stack(yyParser *pParser){ /* ** Clear all secondary memory allocations from the parser */ -%namespace_begin +YYFUNCAPI void ParseFinalize(void *p){ yyParser *pParser = (yyParser*)p; while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser); @@ -441,7 +444,6 @@ void ParseFinalize(void *p){ if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack); #endif } -%namespace_end #ifndef Parse_ENGINEALWAYSONSTACK /* @@ -452,7 +454,7 @@ void ParseFinalize(void *p){ ** is defined in a %include section of the input grammar) then it is ** assumed that the input pointer is never NULL. */ -%namespace_begin +YYFUNCAPI void ParseFree( void *p, /* The parser to be deleted */ void (*freeProc)(void*) /* Function used to reclaim memory */ @@ -463,19 +465,17 @@ void ParseFree( ParseFinalize(p); (*freeProc)(p); } -%namespace_end #endif /* Parse_ENGINEALWAYSONSTACK */ /* ** Return the peak depth of the stack for a parser. */ #ifdef YYTRACKMAXSTACKDEPTH -%namespace_begin +YYFUNCAPI int ParseStackPeak(void *p){ yyParser *pParser = (yyParser*)p; return pParser->yyhwm; } -%namespace_end #endif /* This array of booleans keeps track of the parser statement @@ -496,7 +496,7 @@ static unsigned char yycoverage[YYNSTATE][YYNTOKEN]; ** Return the number of missed state/lookahead combinations. */ #if defined(YYCOVERAGE) -%namespace_begin +YYFUNCAPI int ParseCoverage(FILE *out){ int stateno, iLookAhead, i; int nMissed = 0; @@ -514,7 +514,6 @@ int ParseCoverage(FILE *out){ } return nMissed; } -%namespace_end #endif /* @@ -905,7 +904,7 @@ static void yy_accept( ** Outputs: ** None. */ -%namespace_begin +YYFUNCAPI void Parse( void *yyp, /* The parser */ int yymajor, /* The major token code number */ @@ -1075,13 +1074,12 @@ void Parse( #endif return; } -%namespace_end /* ** Return the fallback token corresponding to canonical token iToken, or ** 0 if iToken has no fallback. */ -%namespace_begin +YYFUNCAPI int ParseFallback(int iToken){ #ifdef YYFALLBACK assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); @@ -1091,4 +1089,3 @@ int ParseFallback(int iToken){ return 0; #endif } -%namespace_end diff --git a/wmake/etc/lempar.c.patch b/wmake/etc/lempar.c.patch index 06ceee114f..86dd2c78b6 100644 --- a/wmake/etc/lempar.c.patch +++ b/wmake/etc/lempar.c.patch @@ -1,136 +1,87 @@ ---- lempar.c.orig 2020-01-10 14:08:55.225662130 +0100 -+++ lempar.c 2020-01-10 14:31:25.891656998 +0100 -@@ -251,12 +251,14 @@ +--- lempar.c.orig 2020-07-09 14:55:42.000000000 +0200 ++++ lempar.c 2020-07-10 11:04:51.991472607 +0200 +@@ -93,6 +93,12 @@ + /************* End control #defines *******************************************/ + #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) + ++/* Default linkage for exposed parser routines is global ++*/ ++#ifndef YYFUNCAPI ++# define YYFUNCAPI ++#endif ++ + /* Define the yytestcase() macro to be a no-op if is not already defined + ** otherwise. + ** +@@ -251,6 +257,7 @@ ** Outputs: ** None. */ -+%namespace_begin ++YYFUNCAPI void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ yyTraceFILE = TraceFILE; yyTracePrompt = zTracePrompt; - if( yyTraceFILE==0 ) yyTracePrompt = 0; - else if( yyTracePrompt==0 ) yyTraceFILE = 0; - } -+%namespace_end - #endif /* NDEBUG */ - - #if defined(YYCOVERAGE) || !defined(NDEBUG) -@@ -320,6 +322,7 @@ +@@ -320,6 +327,7 @@ /* Initialize a new parser that has already been allocated. */ -+%namespace_begin ++YYFUNCAPI void ParseInit(void *yypRawParser ParseCTX_PDECL){ yyParser *yypParser = (yyParser*)yypRawParser; ParseCTX_STORE -@@ -345,6 +348,7 @@ - yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1]; - #endif - } -+%namespace_end - - #ifndef Parse_ENGINEALWAYSONSTACK - /* -@@ -359,6 +363,7 @@ +@@ -359,6 +367,7 @@ ** A pointer to a parser. This pointer is used in subsequent calls ** to Parse and ParseFree. */ -+%namespace_begin ++YYFUNCAPI void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) ParseCTX_PDECL){ yyParser *yypParser; yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); -@@ -368,6 +373,7 @@ - } - return (void*)yypParser; - } -+%namespace_end - #endif /* Parse_ENGINEALWAYSONSTACK */ - - -@@ -427,6 +433,7 @@ +@@ -427,6 +436,7 @@ /* ** Clear all secondary memory allocations from the parser */ -+%namespace_begin ++YYFUNCAPI void ParseFinalize(void *p){ yyParser *pParser = (yyParser*)p; while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser); -@@ -434,6 +441,7 @@ - if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack); - #endif - } -+%namespace_end - - #ifndef Parse_ENGINEALWAYSONSTACK - /* -@@ -444,6 +452,7 @@ +@@ -444,6 +454,7 @@ ** is defined in a %include section of the input grammar) then it is ** assumed that the input pointer is never NULL. */ -+%namespace_begin ++YYFUNCAPI void ParseFree( void *p, /* The parser to be deleted */ void (*freeProc)(void*) /* Function used to reclaim memory */ -@@ -454,16 +463,19 @@ - ParseFinalize(p); - (*freeProc)(p); - } -+%namespace_end - #endif /* Parse_ENGINEALWAYSONSTACK */ - - /* +@@ -460,6 +471,7 @@ ** Return the peak depth of the stack for a parser. */ #ifdef YYTRACKMAXSTACKDEPTH -+%namespace_begin ++YYFUNCAPI int ParseStackPeak(void *p){ yyParser *pParser = (yyParser*)p; return pParser->yyhwm; - } -+%namespace_end - #endif - - /* This array of booleans keeps track of the parser statement @@ -484,6 +496,7 @@ ** Return the number of missed state/lookahead combinations. */ #if defined(YYCOVERAGE) -+%namespace_begin ++YYFUNCAPI int ParseCoverage(FILE *out){ int stateno, iLookAhead, i; int nMissed = 0; -@@ -501,6 +514,7 @@ - } - return nMissed; - } -+%namespace_end - #endif - - /* -@@ -891,6 +905,7 @@ +@@ -891,6 +904,7 @@ ** Outputs: ** None. */ -+%namespace_begin ++YYFUNCAPI void Parse( void *yyp, /* The parser */ int yymajor, /* The major token code number */ -@@ -1060,11 +1075,13 @@ - #endif - return; - } -+%namespace_end - - /* +@@ -1065,6 +1079,7 @@ ** Return the fallback token corresponding to canonical token iToken, or ** 0 if iToken has no fallback. */ -+%namespace_begin ++YYFUNCAPI int ParseFallback(int iToken){ #ifdef YYFALLBACK assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); -@@ -1074,3 +1091,4 @@ - return 0; - #endif - } -+%namespace_end diff --git a/wmake/src/README.txt b/wmake/src/README.txt index cb18a237f9..852983023b 100644 --- a/wmake/src/README.txt +++ b/wmake/src/README.txt @@ -1,23 +1,21 @@ Minimal changes to lemon for C++ integration. -- New '-e' command line option to define the code extension. +- Additional '-e' command line option to define the code extension. By default this is 'c', but with this option can define something - like -ecxx etc for using a C++ compiler. + like '-ecxx' etc for using a C++ compiler. -- New '%namespace' directive. This can be used to embed the 'Parse*' - routines into a C++ namespace. The namespace can be anonymous or - contain multiple nested namespaces. For example, +- Additional '%static' Lemon directive, which is boolean-like: - %namespace {} - %namespace {ns1::ns2::ns3} + %static - - One simple means to encapsulate code is to use an anonymous - namespace for the Lemon code and place all C++ interface code with - the %code block in the same translation unit. + This adds a 'static' qualifier to all of the 'Parse*' routines that + would otherwise have global linkage, thus making them only visible + in the same file-scope. + Can subsequently place all of the C++ interface code within a %code + block in the same translation unit. This allows good encapsulation without fundamentally changing how Lemon works. -- -2019-09-27 +2020-07-10 diff --git a/wmake/src/lemon.c b/wmake/src/lemon.c index b73dba1f70..8950d88293 100644 --- a/wmake/src/lemon.c +++ b/wmake/src/lemon.c @@ -1,7 +1,6 @@ -/* - * Part of check-in [https://www.sqlite.org/src/info/fccfb8a9ed3c1df9] - * artifact: - * https://www.sqlite.org/src/raw/tool/lemon.c?name=a361b85fa230560b783006ac002a6a8bad214c3b9d7fa48980aecc2b691ddcad +/* https://sqlite.org/src/artifact/600a58b9 + * Artifact 600a58b9d1b8ec5419373982428e927ca208826edacb91ca42ab94514d006039: + * File tool/lemon.c part of check-in [951d22b7] at 2020-07-03 */ /* ** This file contains all sources (including headers) to the LEMON @@ -406,7 +405,6 @@ struct lemon { struct symbol *errsym; /* The error symbol */ struct symbol *wildcard; /* Token that matches anything */ char *name; /* Name of the generated parser */ - char *namesp; /* Surrounding namespace for generated parser */ char *arg; /* Declaration of the 3th argument to parser */ char *ctx; /* Declaration of 2nd argument to constructor */ char *tokentype; /* Type of terminal symbols in the parser stack */ @@ -429,8 +427,10 @@ struct lemon { int nlookaheadtab; /* Number of entries in yy_lookahead[] */ int tablesize; /* Total table size of all tables in bytes */ int basisflag; /* Print only basis configurations */ + int printPreprocessed; /* Show preprocessor output on stdout */ int has_fallback; /* True if any %fallback is seen in the grammar */ int nolinenosflag; /* True if #line statements should not be printed */ + int linkage; /* 1 if %static provided (use static linkage) */ char *argv0; /* Name of the program */ }; @@ -1561,8 +1561,9 @@ static void handle_d_option(char *z){ } /* Remember the name of the code extension (automatically prefix '.') +** default is "c" extension */ -static char *code_ext = NULL; +static char *code_ext = ".c"; static void handle_e_option(char *z){ code_ext = (char *) malloc( lemonStrlen(z)+2 ); if( code_ext==0 ){ @@ -1659,6 +1660,7 @@ int main(int argc, char **argv) static int nolinenosflag = 0; static int noResort = 0; static int sqlFlag = 0; + static int printPP = 0; static struct s_options options[] = { {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."}, @@ -1666,6 +1668,7 @@ int main(int argc, char **argv) {OPT_FSTR, "d", (char*)&handle_d_option, "Output directory. Default '.'"}, {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."}, {OPT_FSTR, "e", (char*)&handle_e_option, "Output code extension. Default 'c'"}, + {OPT_FLAG, "E", (char*)&printPP, "Print input file after preprocessing."}, {OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"}, {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, {OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"}, @@ -1710,11 +1713,12 @@ int main(int argc, char **argv) lem.filename = OptArg(0); lem.basisflag = basisflag; lem.nolinenosflag = nolinenosflag; + lem.printPreprocessed = printPP; Symbol_new("$"); /* Parse the input file */ Parse(&lem); - if( lem.errorcnt ) exit(lem.errorcnt); + if( lem.printPreprocessed || lem.errorcnt ) exit(lem.errorcnt); if( lem.nrule==0 ){ fprintf(stderr,"Empty grammar.\n"); exit(1); @@ -2286,6 +2290,7 @@ static void parseonetoken(struct pstate *psp) psp->preccounter = 0; psp->firstrule = psp->lastrule = 0; psp->gp->nrule = 0; + psp->gp->linkage = 0; /* Fall thru to next case */ case WAITING_FOR_DECL_OR_RULE: if( x[0]=='%' ){ @@ -2509,9 +2514,6 @@ static void parseonetoken(struct pstate *psp) if( strcmp(x,"name")==0 ){ psp->declargslot = &(psp->gp->name); psp->insertLineMacro = 0; - }else if( strcmp(x,"namespace")==0 ){ - psp->declargslot = &(psp->gp->namesp); - psp->insertLineMacro = 0; }else if( strcmp(x,"include")==0 ){ psp->declargslot = &(psp->gp->include); }else if( strcmp(x,"code")==0 ){ @@ -2574,6 +2576,11 @@ static void parseonetoken(struct pstate *psp) psp->state = WAITING_FOR_WILDCARD_ID; }else if( strcmp(x,"token_class")==0 ){ psp->state = WAITING_FOR_CLASS_ID; + }else if( strcmp(x,"static")==0 ){ + /* %static is boolean-like */ + psp->gp->linkage = 1; /* 1 = static (True) */ + psp->insertLineMacro = 0; + psp->state = WAITING_FOR_DECL_OR_RULE; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Unknown declaration keyword: \"%%%s\".",x); @@ -2806,13 +2813,108 @@ static void parseonetoken(struct pstate *psp) } } +/* The text in the input is part of the argument to an %ifdef or %ifndef. +** Evaluate the text as a boolean expression. Return true or false. +*/ +static int eval_preprocessor_boolean(char *z, int lineno){ + int neg = 0; + int res = 0; + int okTerm = 1; + int i; + for(i=0; z[i]!=0; i++){ + if( ISSPACE(z[i]) ) continue; + if( z[i]=='!' ){ + if( !okTerm ) goto pp_syntax_error; + neg = !neg; + continue; + } + if( z[i]=='|' && z[i+1]=='|' ){ + if( okTerm ) goto pp_syntax_error; + if( res ) return 1; + i++; + okTerm = 1; + continue; + } + if( z[i]=='&' && z[i+1]=='&' ){ + if( okTerm ) goto pp_syntax_error; + if( !res ) return 0; + i++; + okTerm = 1; + continue; + } + if( z[i]=='(' ){ + int k; + int n = 1; + if( !okTerm ) goto pp_syntax_error; + for(k=i+1; z[k]; k++){ + if( z[k]==')' ){ + n--; + if( n==0 ){ + z[k] = 0; + res = eval_preprocessor_boolean(&z[i+1], -1); + z[k] = ')'; + if( res<0 ){ + i = i-res; + goto pp_syntax_error; + } + i = k; + break; + } + }else if( z[k]=='(' ){ + n++; + }else if( z[k]==0 ){ + i = k; + goto pp_syntax_error; + } + } + if( neg ){ + res = !res; + neg = 0; + } + okTerm = 0; + continue; + } + if( ISALPHA(z[i]) ){ + int j, k, n; + if( !okTerm ) goto pp_syntax_error; + for(k=i+1; ISALNUM(z[k]) || z[k]=='_'; k++){} + n = k - i; + res = 0; + for(j=0; j0 ){ + fprintf(stderr, "%%if syntax error on line %d.\n", lineno); + fprintf(stderr, " %.*s <-- syntax error here\n", i+1, z); + exit(1); + }else{ + return -(i+1); + } +} + /* Run the preprocessor over the input file text. The global variables ** azDefine[0] through azDefine[nDefine-1] contains the names of all defined ** macros. This routine looks for "%ifdef" and "%ifndef" and "%endif" and ** comments them out. Text in between is also commented out as appropriate. */ static void preprocess_input(char *z){ - int i, j, k, n; + int i, j, k; int exclude = 0; int start = 0; int lineno = 1; @@ -2828,21 +2930,33 @@ static void preprocess_input(char *z){ } } for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' '; - }else if( (strncmp(&z[i],"%ifdef",6)==0 && ISSPACE(z[i+6])) - || (strncmp(&z[i],"%ifndef",7)==0 && ISSPACE(z[i+7])) ){ + }else if( strncmp(&z[i],"%else",5)==0 && ISSPACE(z[i+5]) ){ + if( exclude==1){ + exclude = 0; + for(j=start; jprintPreprocessed ){ + printf("%s\n", filebuf); + return; + } /* Now scan the text of the input file */ lineno = 1; @@ -3499,83 +3617,20 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap) #define LINESIZE 1000 /* The next cluster of routines are for reading the template file ** and writing the results to the generated parser */ - -/* Helper function to emit begin of namespace when namesp!=0 -** Converts "ns1::ns2" to "namespace ns1 { namespace ns2 {" -*/ -PRIVATE void tplt_namespace_begin(char *namesp, FILE *out) -{ - if(!namesp) return; - while (ISSPACE(*namesp)) ++namesp; - - char *cp = namesp; - do { - fprintf(out,"namespace "); - cp = strchr(namesp, ':'); - if (cp) { - while (namesp != cp) { - fputc(*namesp,out); - ++namesp; - } - while(*namesp == ':') ++namesp; - } - else { - while (*namesp && !ISSPACE(*namesp)) { - fputc(*namesp,out); - ++namesp; - } - } - fprintf(out, " {"); - } while (cp); - fputc('\n',out); -} - -/* Helper function to emit end of namespace when namesp!=0 -** Converts "ns1::ns2" to "}} // End namespace" -*/ -PRIVATE void tplt_namespace_end(char *namesp, FILE *out) -{ - if(!namesp) return; - while (ISSPACE(*namesp)) ++namesp; - - char *cp = namesp; - do { - cp = strchr(cp, ':'); - if (cp) { - while(*cp == ':') ++cp; - } - fputc('}',out); - } while (cp); - - fprintf(out," // End namespace %s\n", namesp); -} - /* The first function transfers data from "in" to "out" until ** a line is seen which begins with "%%". The line number is ** tracked. ** ** if name!=0, then any word that begin with "Parse" is changed to ** begin with *name instead. -** -** if namesp!=0, then replace %namespace_begin / %namespace_end */ -PRIVATE void tplt_xfer(char *name, char *namesp, FILE *in, FILE *out, int *lineno) +PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno) { int i, iStart; char line[LINESIZE]; while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){ (*lineno)++; iStart = 0; - if(line[0]=='%' && line[1]=='n'){ - if(strncmp(&line[1],"namespace_begin",15)==0){ - tplt_namespace_begin(namesp, out); - continue; - }else if(strncmp(&line[1],"namespace_end",13)==0){ - tplt_namespace_end(namesp, out); - continue; - } - } - if( name ){ for(i=0; line[i]; i++){ if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0 @@ -4272,8 +4327,7 @@ void ReportTable( in = tplt_open(lemp); if( in==0 ) return; - if(code_ext) out = file_open(lemp,code_ext,"wb"); - else out = file_open(lemp,".c","wb"); + out = file_open(lemp,code_ext,"wb"); if( out==0 ){ fclose(in); return; @@ -4351,7 +4405,7 @@ void ReportTable( fprintf(sql, "COMMIT;\n"); } lineno = 1; - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate the include code, if any */ tplt_print(out,lemp,lemp->include,&lineno); @@ -4360,7 +4414,7 @@ void ReportTable( fprintf(out,"#include \"%s\"\n", incName); lineno++; free(incName); } - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate #defines for all tokens */ if( mhflag ){ @@ -4374,9 +4428,12 @@ void ReportTable( } fprintf(out,"#endif\n"); lineno++; } - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate the defines */ + if( lemp->linkage ){ + fprintf(out,"#define YYFUNCAPI static\n"); lineno++; + } fprintf(out,"#define YYCODETYPE %s\n", minimum_size_type(0, lemp->nsymbol, &szCodeType)); lineno++; fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol); lineno++; @@ -4539,7 +4596,7 @@ void ReportTable( fprintf(out,"#define YY_MIN_REDUCE %d\n", lemp->minReduce); lineno++; i = lemp->minReduce + lemp->nrule; fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++; - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Now output the action table and its associates: ** @@ -4677,7 +4734,7 @@ void ReportTable( } } fprintf(out, "};\n"); lineno++; - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate the table of fallback tokens. */ @@ -4698,7 +4755,7 @@ void ReportTable( lineno++; } } - tplt_xfer(lemp->name,lemp->namesp, in, out, &lineno); + tplt_xfer(lemp->name, in, out, &lineno); /* Generate a table containing the symbolic name of every symbol */ @@ -4706,7 +4763,7 @@ void ReportTable( lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name); fprintf(out," /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++; } - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate a table containing a text string that describes every ** rule in the rule set of the grammar. This information is used @@ -4718,7 +4775,7 @@ void ReportTable( writeRuleText(out, rp); fprintf(out,"\",\n"); lineno++; } - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes every time a symbol is popped from ** the stack while processing errors or while destroying the parser. @@ -4781,11 +4838,11 @@ void ReportTable( emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); fprintf(out," break;\n"); lineno++; } - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes whenever the parser stack overflows */ tplt_print(out,lemp,lemp->overflow,&lineno); - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate the tables of rule information. yyRuleInfoLhs[] and ** yyRuleInfoNRhs[]. @@ -4798,13 +4855,13 @@ void ReportTable( rule_print(out, rp); fprintf(out," */\n"); lineno++; } - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ fprintf(out," %3d, /* (%d) ", -rp->nrhs, i); rule_print(out, rp); fprintf(out," */\n"); lineno++; } - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which execution during each REDUCE action */ i = 0; @@ -4857,19 +4914,19 @@ void ReportTable( } } fprintf(out," break;\n"); lineno++; - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes if a parse fails */ tplt_print(out,lemp,lemp->failure,&lineno); - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes when a syntax error occurs */ tplt_print(out,lemp,lemp->error,&lineno); - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes when the parser accepts its input */ tplt_print(out,lemp,lemp->accept,&lineno); - tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); + tplt_xfer(lemp->name,in,out,&lineno); /* Append any addition code the user desires */ tplt_print(out,lemp,lemp->extracode,&lineno); diff --git a/wmake/src/lemon.c.patch b/wmake/src/lemon.c.patch index 3a76c48d87..074c1ee483 100644 --- a/wmake/src/lemon.c.patch +++ b/wmake/src/lemon.c.patch @@ -1,20 +1,21 @@ ---- lemon.c.orig 2020-01-10 14:08:19.181711107 +0100 -+++ lemon.c 2020-01-10 14:12:00.621402133 +0100 -@@ -406,6 +406,7 @@ - struct symbol *errsym; /* The error symbol */ - struct symbol *wildcard; /* Token that matches anything */ - char *name; /* Name of the generated parser */ -+ char *namesp; /* Surrounding namespace for generated parser */ - char *arg; /* Declaration of the 3th argument to parser */ - char *ctx; /* Declaration of 2nd argument to constructor */ - char *tokentype; /* Type of terminal symbols in the parser stack */ -@@ -1559,6 +1560,23 @@ +--- lemon.c.orig 2020-07-09 14:54:53.871102972 +0200 ++++ lemon.c 2020-07-10 12:01:05.488791973 +0200 +@@ -426,6 +426,7 @@ + int printPreprocessed; /* Show preprocessor output on stdout */ + int has_fallback; /* True if any %fallback is seen in the grammar */ + int nolinenosflag; /* True if #line statements should not be printed */ ++ int linkage; /* 1 if %static provided (use static linkage) */ + char *argv0; /* Name of the program */ + }; + +@@ -1555,6 +1556,24 @@ lemon_strcpy(outputDir, z); } +/* Remember the name of the code extension (automatically prefix '.') ++** default is "c" extension +*/ -+static char *code_ext = NULL; ++static char *code_ext = ".c"; +static void handle_e_option(char *z){ + code_ext = (char *) malloc( lemonStrlen(z)+2 ); + if( code_ext==0 ){ @@ -32,242 +33,50 @@ static char *user_templatename = NULL; static void handle_T_option(char *z){ user_templatename = (char *) malloc( lemonStrlen(z)+1 ); -@@ -1647,6 +1665,7 @@ +@@ -1644,6 +1663,7 @@ {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."}, {OPT_FSTR, "d", (char*)&handle_d_option, "Output directory. Default '.'"}, {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."}, + {OPT_FSTR, "e", (char*)&handle_e_option, "Output code extension. Default 'c'"}, + {OPT_FLAG, "E", (char*)&printPP, "Print input file after preprocessing."}, {OPT_FSTR, "f", 0, "Ignored. (Placeholder for -f compiler options.)"}, {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, - {OPT_FSTR, "I", 0, "Ignored. (Placeholder for '-I' compiler options.)"}, -@@ -2490,6 +2509,9 @@ - if( strcmp(x,"name")==0 ){ - psp->declargslot = &(psp->gp->name); - psp->insertLineMacro = 0; -+ }else if( strcmp(x,"namespace")==0 ){ -+ psp->declargslot = &(psp->gp->namesp); +@@ -2266,6 +2286,7 @@ + psp->preccounter = 0; + psp->firstrule = psp->lastrule = 0; + psp->gp->nrule = 0; ++ psp->gp->linkage = 0; + /* Fall thru to next case */ + case WAITING_FOR_DECL_OR_RULE: + if( x[0]=='%' ){ +@@ -2551,6 +2572,11 @@ + psp->state = WAITING_FOR_WILDCARD_ID; + }else if( strcmp(x,"token_class")==0 ){ + psp->state = WAITING_FOR_CLASS_ID; ++ }else if( strcmp(x,"static")==0 ){ ++ /* %static is boolean-like */ ++ psp->gp->linkage = 1; /* 1 = static (True) */ + psp->insertLineMacro = 0; - }else if( strcmp(x,"include")==0 ){ - psp->declargslot = &(psp->gp->include); - }else if( strcmp(x,"code")==0 ){ -@@ -3477,20 +3499,83 @@ - #define LINESIZE 1000 - /* The next cluster of routines are for reading the template file - ** and writing the results to the generated parser */ -+ -+/* Helper function to emit begin of namespace when namesp!=0 -+** Converts "ns1::ns2" to "namespace ns1 { namespace ns2 {" -+*/ -+PRIVATE void tplt_namespace_begin(char *namesp, FILE *out) -+{ -+ if(!namesp) return; -+ while (ISSPACE(*namesp)) ++namesp; -+ -+ char *cp = namesp; -+ do { -+ fprintf(out,"namespace "); -+ cp = strchr(namesp, ':'); -+ if (cp) { -+ while (namesp != cp) { -+ fputc(*namesp,out); -+ ++namesp; -+ } -+ while(*namesp == ':') ++namesp; -+ } -+ else { -+ while (*namesp && !ISSPACE(*namesp)) { -+ fputc(*namesp,out); -+ ++namesp; -+ } -+ } -+ fprintf(out, " {"); -+ } while (cp); -+ fputc('\n',out); -+} -+ -+/* Helper function to emit end of namespace when namesp!=0 -+** Converts "ns1::ns2" to "}} // End namespace" -+*/ -+PRIVATE void tplt_namespace_end(char *namesp, FILE *out) -+{ -+ if(!namesp) return; -+ while (ISSPACE(*namesp)) ++namesp; -+ -+ char *cp = namesp; -+ do { -+ cp = strchr(cp, ':'); -+ if (cp) { -+ while(*cp == ':') ++cp; -+ } -+ fputc('}',out); -+ } while (cp); -+ -+ fprintf(out," // End namespace %s\n", namesp); -+} -+ - /* The first function transfers data from "in" to "out" until - ** a line is seen which begins with "%%". The line number is - ** tracked. - ** - ** if name!=0, then any word that begin with "Parse" is changed to - ** begin with *name instead. -+** -+** if namesp!=0, then replace %namespace_begin / %namespace_end - */ --PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno) -+PRIVATE void tplt_xfer(char *name, char *namesp, FILE *in, FILE *out, int *lineno) - { - int i, iStart; - char line[LINESIZE]; - while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){ - (*lineno)++; - iStart = 0; -+ if(line[0]=='%' && line[1]=='n'){ -+ if(strncmp(&line[1],"namespace_begin",15)==0){ -+ tplt_namespace_begin(namesp, out); -+ continue; -+ }else if(strncmp(&line[1],"namespace_end",13)==0){ -+ tplt_namespace_end(namesp, out); -+ continue; -+ } -+ } -+ - if( name ){ - for(i=0; line[i]; i++){ - if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0 -@@ -4187,7 +4272,8 @@ ++ psp->state = WAITING_FOR_DECL_OR_RULE; + }else{ + ErrorMsg(psp->filename,psp->tokenlineno, + "Unknown declaration keyword: \"%%%s\".",x); +@@ -4297,7 +4323,7 @@ in = tplt_open(lemp); if( in==0 ) return; - out = file_open(lemp,".c","wb"); -+ if(code_ext) out = file_open(lemp,code_ext,"wb"); -+ else out = file_open(lemp,".c","wb"); ++ out = file_open(lemp,code_ext,"wb"); if( out==0 ){ fclose(in); return; -@@ -4265,7 +4351,7 @@ - fprintf(sql, "COMMIT;\n"); - } - lineno = 1; -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate the include code, if any */ - tplt_print(out,lemp,lemp->include,&lineno); -@@ -4274,7 +4360,7 @@ - fprintf(out,"#include \"%s\"\n", incName); lineno++; - free(incName); - } -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate #defines for all tokens */ - if( mhflag ){ -@@ -4288,7 +4374,7 @@ - } - fprintf(out,"#endif\n"); lineno++; - } -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); +@@ -4401,6 +4427,9 @@ + tplt_xfer(lemp->name,in,out,&lineno); /* Generate the defines */ ++ if( lemp->linkage ){ ++ fprintf(out,"#define YYFUNCAPI static\n"); lineno++; ++ } fprintf(out,"#define YYCODETYPE %s\n", -@@ -4453,7 +4539,7 @@ - fprintf(out,"#define YY_MIN_REDUCE %d\n", lemp->minReduce); lineno++; - i = lemp->minReduce + lemp->nrule; - fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++; -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Now output the action table and its associates: - ** -@@ -4591,7 +4677,7 @@ - } - } - fprintf(out, "};\n"); lineno++; -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate the table of fallback tokens. - */ -@@ -4612,7 +4698,7 @@ - lineno++; - } - } -- tplt_xfer(lemp->name, in, out, &lineno); -+ tplt_xfer(lemp->name,lemp->namesp, in, out, &lineno); - - /* Generate a table containing the symbolic name of every symbol - */ -@@ -4620,7 +4706,7 @@ - lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name); - fprintf(out," /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++; - } -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate a table containing a text string that describes every - ** rule in the rule set of the grammar. This information is used -@@ -4632,7 +4718,7 @@ - writeRuleText(out, rp); - fprintf(out,"\",\n"); lineno++; - } -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate code which executes every time a symbol is popped from - ** the stack while processing errors or while destroying the parser. -@@ -4695,11 +4781,11 @@ - emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); - fprintf(out," break;\n"); lineno++; - } -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate code which executes whenever the parser stack overflows */ - tplt_print(out,lemp,lemp->overflow,&lineno); -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate the tables of rule information. yyRuleInfoLhs[] and - ** yyRuleInfoNRhs[]. -@@ -4712,13 +4798,13 @@ - rule_print(out, rp); - fprintf(out," */\n"); lineno++; - } -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ - fprintf(out," %3d, /* (%d) ", -rp->nrhs, i); - rule_print(out, rp); - fprintf(out," */\n"); lineno++; - } -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate code which execution during each REDUCE action */ - i = 0; -@@ -4771,19 +4857,19 @@ - } - } - fprintf(out," break;\n"); lineno++; -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate code which executes if a parse fails */ - tplt_print(out,lemp,lemp->failure,&lineno); -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate code which executes when a syntax error occurs */ - tplt_print(out,lemp,lemp->error,&lineno); -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Generate code which executes when the parser accepts its input */ - tplt_print(out,lemp,lemp->accept,&lineno); -- tplt_xfer(lemp->name,in,out,&lineno); -+ tplt_xfer(lemp->name,lemp->namesp,in,out,&lineno); - - /* Append any addition code the user desires */ - tplt_print(out,lemp,lemp->extracode,&lineno); + minimum_size_type(0, lemp->nsymbol, &szCodeType)); lineno++; + fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol); lineno++;