Date: Thu, 22 Apr 2004 16:08:49 -0500 (CDT) From: Gilles Detillieux To: "ht://Dig developers list" Subject: [htdig-dev] PATCH: 3.2.0b5 config parser fixes Hi, folks. I was going to take another crack at the performance optimizations in HtRegexList, but before that, I got down to tackling some of the config parser bugs that had been nagging at us for quite some time. Please have a look at this patch, and test it as much as possible, to see if it causes any problems. The fixes in there are: - improved error handling, gives file name and correct line number, even if using include files - allows space before comment, because otherwise it would just complain about the "#" character and go on to parse the text after it as a definition - allows config file with an unterminated line at end of file, by pushing an extra newline token to the parser at EOF - parser correctly handles extra newline tokens, by moving this handling out of simple_expression, and into simple_expression_list and block, as simple_expression must return a new ConfigDefaults object and a newline token doesn't cut it (caused segfaults when dealing with fix above) Apply using "patch -p0 < this-message-file". -- Gilles R. Detillieux E-mail: Spinal Cord Research Centre WWW: http://www.scrc.umanitoba.ca/ Dept. Physiology, U. of Manitoba Winnipeg, MB R3E 3J7 (Canada) --- htcommon/conf_lexer.lxx.orig 2003-12-14 07:40:12.000000000 -0600 +++ htcommon/conf_lexer.lxx 2004-04-22 15:47:48.000000000 -0500 @@ -41,6 +41,7 @@ #define MAX_INCLUDE_DEPTH 10 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; String *name_stack[MAX_INCLUDE_DEPTH]; +int lineno_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr = 0; %} @@ -50,7 +51,7 @@ STRING [\x21-\xff]+ BR_STRING [^ \n\t<>]+ %% -^#.*\n /* Ignore comments */ +^[[:space:]]*#.*\n /* Ignore comments */ ^[[:space:]]*\n /* Ignore emty lines */ <*>[ \t]+ /* Ignore spaces */ include[ \t]*: BEGIN(incl); @@ -157,6 +158,8 @@ include[ \t]*: BEGIN(incl); } name_stack[include_stack_ptr-1] = new String(ParsedFilename.get()); + lineno_stack[include_stack_ptr-1] = yylineno; + yylineno = 1; yy_switch_to_buffer( yy_create_buffer( yyin, YY_BUF_SIZE ) ); BEGIN(INITIAL); @@ -164,10 +167,18 @@ include[ \t]*: BEGIN(incl); <> { if ( include_stack_ptr <= 0 ) + { + static int termnext = 0; + // fix to allow unterminated final line + if (++termnext <= 1) + return(T_NEWLINE); + termnext = 0; // in case we're called again yyterminate(); + } else { delete name_stack[include_stack_ptr-1]; + yylineno = lineno_stack[include_stack_ptr-1]; yy_delete_buffer( YY_CURRENT_BUFFER ); yy_switch_to_buffer( include_stack[--include_stack_ptr] ); @@ -183,7 +194,13 @@ include[ \t]*: BEGIN(incl); \n <*>.|\n { - fprintf(stderr,"Unknown char in line %d: %s",yylineno,yytext); - // exit(1); // Seems to harsh! + HtConfiguration* config= HtConfiguration::config(); + String str; + if (include_stack_ptr > 0) + str = *name_stack[include_stack_ptr-1]; + else // still at top level config + str = config->getFileName(); + fprintf(stderr,"Unknown char in file %s line %d: %s\n",str.get(),yylineno,yytext); + // exit(1); // Seems too harsh! } %% --- htcommon/conf_parser.yxx.orig 2003-11-22 07:40:17.000000000 -0600 +++ htcommon/conf_parser.yxx 2004-04-22 15:48:54.000000000 -0500 @@ -84,6 +84,7 @@ block: simple_expression { // ... : ... // } + | T_NEWLINE { /* Ignore empty lines */ } ; simple_expression: T_KEYWORD T_DELIMITER T_STRING T_NEWLINE { @@ -116,7 +117,6 @@ simple_expression: T_KEYWORD T_DELI $$->value=new char[1]; *$$->value='\0'; } - | T_NEWLINE { /* Ignore empty lines */ } ; complex_expression: T_LEFT_BR T_KEYWORD T_DELIMITER T_STRING T_RIGHT_BR T_NEWLINE simple_expression_list T_LEFT_BR T_SLASH T_KEYWORD T_RIGHT_BR T_NEWLINE { @@ -170,6 +170,7 @@ simple_expression_list: simple_express delete $2; //$$=$1; //I think $$==$1 } + | T_NEWLINE { /* Ignore empty lines */ } ; list: T_STRING T_STRING { @@ -253,8 +254,17 @@ list: T_STRING T_STRING { int yyerror (char *s) /* Called by yyparse on error */ { -extern int yylineno; // I don't know what about included files - fprintf (stderr, "%s\nIn line %d\n",s,yylineno); +extern int yylineno; +extern int include_stack_ptr; +extern String *name_stack[]; + HtConfiguration* config= HtConfiguration::config(); + String str; + if (include_stack_ptr > 0) + str = *name_stack[include_stack_ptr-1]; + else // still at top level config + str = config->getFileName(); + //fprintf (stderr, "%s\nIn line %d\n",s,yylineno); + fprintf(stderr,"Error in file %s line %d: %s\n",str.get(),yylineno,s); // exit(1); return -1; }