=== modified file 'src/ConfigParser.cc' --- src/ConfigParser.cc 2013-07-22 01:26:09 +0000 +++ src/ConfigParser.cc 2013-07-29 23:56:52 +0000 @@ -54,7 +54,7 @@ if (!CfgFiles.empty()) { std::ostringstream message; CfgFile *f = CfgFiles.top(); - message << "Bungled " << f->filePath << " line " << f->lineNo << + message << "Bungled (#1) " << f->filePath << " line " << f->lineNo << ": " << f->currentLine << std::endl; CfgFiles.pop(); delete f; @@ -70,7 +70,7 @@ std::string msg = message.str(); fatalf("%s", msg.c_str()); } else - fatalf("Bungled %s line %d: %s", + fatalf("Bungled (#2) %s line %d: %s", cfg_filename, config_lineno, config_input_line); } @@ -183,9 +183,11 @@ if (*s == '\\' && isalnum(*( s + 1))) { debugs(3, DBG_CRITICAL, "Unsupported escape sequence: " << s); self_destruct(); +#if 0 // ${macro} are evaluated before this code and this breaks parsing of regex tokens } else if (*s == '$' && quoteChar == '"') { debugs(3, DBG_CRITICAL, "Unsupported cfg macro: " << s); self_destruct(); +#endif } else if (*s == '%' && quoteChar == '"' && (!AllowMacros_ )) { debugs(3, DBG_CRITICAL, "Macros are not supported here: " << s); self_destruct(); @@ -232,8 +234,13 @@ const char *sep; if (legacy) sep = w_space; - else + else { sep = w_space "("; + // NP: '(' is delimiter for function() name elements + // ignore detecting any '(' without a prefix + while (*nextToken == '(') + ++nextToken; + } nextToken += strcspn(nextToken, sep); if (!legacy && *nextToken == '(') @@ -262,8 +269,10 @@ char * ConfigParser::NextToken() { - if ((LastToken = ConfigParser::Undo())) + if ((LastToken = ConfigParser::Undo())) { + debugs(3, 6, "TOKEN (undone): " << LastToken); return LastToken; + } char *token = NULL; do { @@ -273,6 +282,7 @@ if (!token) { assert(!wordfile->isOpen()); CfgFiles.pop(); + debugs(3, 4, "CfgFiles.pop " << wordfile->filePath); delete wordfile; } } @@ -280,7 +290,8 @@ if (!token) token = NextElement(LastTokenType); - if (token && LastTokenType == ConfigParser::FunctionNameToken && strcmp("parameters", token) == 0) { + if (token && LastTokenType == ConfigParser::FunctionNameToken) { + if (strcmp("parameters", token) == 0) { char *path = NextToken(); if (LastTokenType != ConfigParser::QuotedToken) { debugs(3, DBG_CRITICAL, "Quoted filename missing: " << token); @@ -309,15 +320,26 @@ self_destruct(); return NULL; } + debugs(3, 4, "CfgFiles.push " << wordfile->filePath); CfgFiles.push(wordfile); token = NULL; - } else if (token && LastTokenType == ConfigParser::FunctionNameToken) { - debugs(3, DBG_CRITICAL, "Unknown cfg function: " << token); - self_destruct(); - return NULL; + } else { + debugs(3, 5, "Unknown cfg function: " << token); + + // we have determined tha the whole of this token is not a built-in function() style token + // ignore any further '(' as well + // concatenate this token, the '('-delimiter which confused things and next token. + // send to the undo queue for better processing next time around + LOCAL_ARRAY(char, tbuf, CONFIG_LINE_LIMIT); + const char *temp = NextElement(LastTokenType, false); + snprintf(tbuf, sizeof(tbuf)-1, "%s(%s", token, temp); + debugs(3, 6, "TOKEN (reconstruct): " << tbuf); + return (LastToken = tbuf); } + } } while (token == NULL && !CfgFiles.empty()); + debugs(3, 6, "TOKEN: " << token); return (LastToken = token); } @@ -344,6 +366,7 @@ LastTokenType = ConfigParser::SimpleToken; CfgPos = NULL; + debugs(3, 6, "TOKEN (to eol): " << token); return (LastToken = token); } @@ -375,6 +398,7 @@ ConfigParser::CfgFile::startParse(char *path) { assert(wordFile == NULL); + debugs(3, 3, "Parsing from " << path); if ((wordFile = fopen(path, "r")) == NULL) { debugs(3, DBG_CRITICAL, "file :" << path << " not found"); return false;