B 7a876209a678a34c198b54ceef9e3c041f128a14dc73357f6a57cadadaa6cf7b
-C Fix\sthe\spragma_foreign_key_check\svirtual\stable\sso\sthat\sit\saccepts\sarguments.
-D 2020-07-03T12:32:04.573
+C In\slemon,\sadd\s"%if"\sand\s"%else"\sand\sallow\sboolean\sexpressions\sas\sthe\nargument\sto\s"%if",\s"%ifdef",\sand\s"%ifndef".
+D 2020-07-03T15:41:08.646
F Makefile.in 19374a5db06c3199ec1bab71ab74a103d8abf21053c05e9389255dc58083f806
F Makefile.msc 48f5a3fc32672c09ad73795749f6253e406a31526935fbbffd8f021108d54574
F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8
F test/gencol1.test b05e6c5edb9b10d48efb634ed07342441bddc89d225043e17095c36e567521a0
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
F test/speedtest1.c a8b5afe72d78ff365012aba48d3f0c579e957facb7630f765f58a6ae4656d20d
+F tool/lemon.c 600a58b9d1b8ec5419373982428e927ca208826edacb91ca42ab94514d006039
F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
F tool/mkpragmatab.tcl ae5585ae76ca26e4d6ccd5ea9cdebaf5efefb318bf989497a0e846cd711d9ab1
F tool/mksqlite3c.tcl f4ef476510eca4124c874a72029f1e01bc54a896b1724e8f9eef0d8bfae0e84c
F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78fc4edf
F tool/showlocks.c 9cc5e66d4ebbf2d194f39db2527ece92077e86ae627ddd233ee48e16e8142564
F tool/speed-check.sh 615cbdf50f1409ef3bbf9f682e396df80f49d97ed93ed3e61c8e91fae6afde58
-P 81bc4b65ae2a68128b0be75a7a3d4f47f05cc588ff130ba56366ab9b16289228
-R 959518f214ac8fa04f9479823db88ae3
+P 07f849dee3d245ecf80ba3c3ce8dfc630e71ddb1e9c0bcc1f08cee22001fcb07
+R ab4092566c985aba1362a3a393cab635
U drh
-Z df6c0f239cac29280d3b9659da8bad1e
+Z abad44d232bcc4ccdddfa3cd71995651
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 */
char *argv0; /* Name of the program */
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."},
{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_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.)"},
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);
}
}
+/* 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; j<nDefine; j++){
+ if( strncmp(azDefine[j],&z[i],n)==0 && azDefine[j][n]==0 ){
+ res = 1;
+ break;
+ }
+ }
+ i = k-1;
+ if( neg ){
+ res = !res;
+ neg = 0;
+ }
+ okTerm = 0;
+ continue;
+ }
+ goto pp_syntax_error;
+ }
+ return res;
+
+pp_syntax_error:
+ if( lineno>0 ){
+ 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;
}
}
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; j<i; j++) if( z[j]!='\n' ) z[j] = ' ';
+ }else if( exclude==0 ){
+ exclude = 1;
+ start = i;
+ start_lineno = lineno;
+ }
+ for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' ';
+ }else if( strncmp(&z[i],"%ifdef ",7)==0
+ || strncmp(&z[i],"%if ",4)==0
+ || strncmp(&z[i],"%ifndef ",8)==0 ){
if( exclude ){
exclude++;
}else{
- for(j=i+7; ISSPACE(z[j]); j++){}
- for(n=0; z[j+n] && !ISSPACE(z[j+n]); n++){}
- exclude = 1;
- for(k=0; k<nDefine; k++){
- if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){
- exclude = 0;
- break;
- }
- }
- if( z[i+3]=='n' ) exclude = !exclude;
+ int isNot;
+ int iBool;
+ for(j=i; z[j] && !ISSPACE(z[j]); j++){}
+ iBool = j;
+ isNot = (j==i+7);
+ while( z[j] && z[j]!='\n' ){ j++; }
+ k = z[j];
+ z[j] = 0;
+ exclude = eval_preprocessor_boolean(&z[iBool], lineno);
+ z[j] = k;
+ if( !isNot ) exclude = !exclude;
if( exclude ){
start = i;
start_lineno = lineno;
/* Make an initial pass through the file to handle %ifdef and %ifndef */
preprocess_input(filebuf);
+ if( gp->printPreprocessed ){
+ printf("%s\n", filebuf);
+ return;
+ }
/* Now scan the text of the input file */
lineno = 1;