/************************************************************************** html_lex.yy ============================================================= Project : Tools for the CC manual writing task around cc_manual.sty. Function : lexical scanner for TeX and C++ code mixed files. Taylored for HTML manual generation. System : flex, bison, C++ (g++) Author : (c) 1996 Lutz Kettner as of version 3.3 (Sept. 1999) maintained by Susan Hert Revision : $Id$ Date : $Date$ **************************************************************************/ %{ #include #include #include #include #include #include #include #include #include #include #include #include int old_state = 0; // Old parser state before param. parsing. // Used to communicate with the parser for DEFWITHARGS's tokens. int number_of_args = 0; string yy_string; // Used like yytext, if we need a temp. string. bool small_caps_mode = false; // Special treatment of small caps conversion. // Used to parse {} nested expressions as (La)TeX macro parameters // using ParameterMode. string current_macro; // Current macro to be expanded int parameter_nesting = 0; int parameter_count = 0; // used to collect params during macro expansion. // Changing from 1 to 0 stops parameter parsing. string parameters[36]; // Parameter list incl. optional parameters string parameter_format; // String describing the parameter format // m = mandatory, o = optional parameter int parameter_index = 0; // Index in parameter list. Incr. from 0. int parameter_options = 0; // counts number of optional parameters. int parameter_endopt = 0; // number of optional parameters at end. bool parameter_option = false; // indicates whether we parse an opt.param. bool is_parameter_parsing_done( bool optional, bool more); bool expand_macro(); // Used to pass the parameter from IfParameterParsing to // is_parameter_parsing_done. string current_parameter; // String to collect the result of a CCParameterMode parameter. string cc_string; // String to store the filename of ccReferenceFile intermediately // The filename is already processed to not contain illegal characters anymore. string cc_filename; /* Set this flag to 1 to switch back to old_state. */ int set_old_state = 0; /* remember the necessary stop character for \verb"..." */ /* or stop environment for \begin{verbatim} */ char stop_character; string stop_envir; void count_newlines( const char* s); #define skipspaces() if ( skipspaces_eof()) yyterminate() bool skipspaces_eof(); #define skipseparator() if ( skipseparator_eof()) yyterminate() bool skipseparator_eof(); #define skiplimitedspaces() if ( skiplimitedspaces_eof()) yyterminate() bool skiplimitedspaces_eof(); int skiplimitedspaces_param(); #define skiplimitedsepspaces() if ( skiplimitedsepspaces_eof()) yyterminate() bool skiplimitedsepspaces_eof(); #define skipnonspaces() if ( skipnonspaces_eof()) yyterminate() bool skipnonspaces_eof(); size_t removespaces( char* s); void inc_line(); #define IfParameterParsing( option) \ bool more_param = false; \ if ( (option && (parameter_count == 0) && (parameter_endopt > 1)) \ || (!option && (parameter_count == 1) && (parameter_endopt > 0))) {\ skiplimitedsepspaces(); \ int c = yyinput(); \ if ( c == EOF) \ yyterminate(); \ if ( c == '[') { \ more_param = true; \ } else \ unput( c); \ } \ if ( is_parameter_parsing_done( (option), more_param)) #define BeginParameterStart() \ if ( YY_START == AllttMode) \ BEGIN( AllttParameterStart); \ else \ BEGIN( ParameterStart) #define BeginParameterMode() \ if ( YY_START == AllttMode) \ BEGIN( AllttParameterMode); \ else \ BEGIN( ParameterMode) // Some inline function to process yytext. inline char* next_char( char* s, char c) { while ( *s != c) ++s; return s; } inline char* next_alpha( char* s) { while ( ! isalpha(*s)) ++s; return s; } inline char* next_non_alpha( char* s) { while ( isalpha(*s)) ++s; return s; } inline char* next_digit( char* s) { while ( ! isdigit(*s)) ++s; return s; } #define CC_Special(x) count_newlines(yytext); cc_string+=x; break #define YY_BREAK /* a do nothing */ /* -------------------------------------------------------------------- Parsing Modes: -- INITIAL: parses (La)TeX -- AllttMode: Parses alltt environments. Copies all characters literally except \macros and {}. -- DelimiterMode parses LaTeX \verb"..." statements until a stop character occurs. Another example is \path. -- EndTokenMode parses LaTeX verbose environments until an \end{envir} occurs. Another example is cprog. -- IncludeMode parses lciInclude filename, -- ParameterStart: starts a (La)TeX macro parameter, i.e. comments, braces, brackets, and escaped symbols, are recognized. White spaces are removed. A brace starts a normal parameter, a bracket starts an optional parameter, both change then to ParameterMode. All other inputs (macro or single symbols) are returned as single token parameter. -- ParameterMode: parses (La)TeX macro parameters body, i.e. comments, braces and escaped braces are recognized. All other characters are literally copied and at the end returned as PARAMETER, the surrounding {} stripped off. In case of [] a PARAMETER_OPTION is returned. -- AllttParameterStart: same as ParameterStart, but in AllttMode -- AllttParameterMode: same as ParameterMode, but in AllttMode -- CCParameterMode: Parses C++ parameters, similar to ParameterMode. Counts only parantheses. Does not treat escaped parantheses or TeX comments (%). Expands the few macros known for CC style (e.g. \tt). -------------------------------------------------------------------- */ %} %x AllttMode %x IncludeMode %x ParameterStart %x ParameterMode %x AllttParameterStart %x AllttParameterMode %x CCParameterMode %x DelimiterMode %x EndTokenMode sep [\001] sepsp [\t \001] seps {sepsp}* sepnls [\t \n\r\001]* letter [a-zA-Z] digit [0-9] CCletter [a-zA-Z_] idfier {letter}+ envir [a-zA-Z0-9*]+ envirmacro (("\\begin@")|("\\end")){envir} texmacro ([\\]((.)|([\\]"*")|({idfier}"*"?)))|{envirmacro} deftexmacro {texmacro}(("@"[mo]+)?) texmacroskip [\\]{idfier}"*"? filename [^ \t\n\\\{\}\[\]()\001]+ space [\t ] w {space}* ws {space}+ number {digit}+ %% /* Mode switching can be triggered from the parser */ /* ----------------------------------------------- */ if (set_old_state) { BEGIN( old_state); set_old_state = 0; } /* Separator, Newlines, paragraphs, comments, and EOF */ /* --------------------------------------------------------- */ {sep} { break; /* ignore separator */ } /* Count line numbers in all modes for better error messages */ {w}"\n"{w}("\n"{w})+ { /* create a TeX paragraph */ count_newlines( yytext); yylval.text = "\n

\n\n"; return STRING; } [\n] { inc_line(); yylval.character = yytext[0]; return CHAR; } [\\]"\n" { inc_line(); yylval.character = ' '; return CHAR; } "%".*[\n]{w} { /* Match one line TeX comments remove spaces in next line */ inc_line(); break; } "%".*[\n]{w}("\n"{w})+ { /* Match comments with an empty line -> par */ count_newlines( yytext); yylval.text = "\n

\n\n"; return STRING; } "%".* { /* Match TeX comments at the last line in a file (EOF) */ break;} <> { if ( YY_START != INITIAL) printErrorMessage( ParsingStateError); yyterminate(); } /* Handle include files */ /* ------------------------- */ [\\](lciInclude){seps}[\{]{seps} { old_state = YY_START; BEGIN ( IncludeMode); break; } {filename} { /* remove remaining characters before the '}' */ int c = yyinput(); while( c != EOF && c != '}') { if ( c == '\n') inc_line(); c = yyinput(); } if ( c == EOF) { printErrorMessage( EOFInIncludeFilenameError); yyterminate(); } BEGIN( old_state); include_stack.push_file( yytext ); break; } /* TeX Macro Definitions */ /* LaTeX newcommand is as internal macro defined */ /* --------------------------------------------- */ [\\]lciBeginGroup { return '{'; } [\\]lciEndGroup { return '}'; } [\\]def{seps}{deftexmacro}{seps}([#][0-9])+ { number_of_args = atoi( yytext + yyleng - 1); old_state = YY_START; BeginParameterStart(); char* s = yytext + 1; s = next_char(s, '\\'); char* p = s; ++s; s = next_non_alpha( s); *s = '\0'; yylval.text = newstr( p); return DEFWITHARGS; } [\\]gdef{seps}{deftexmacro}{seps}([#][0-9])+ { number_of_args = atoi( yytext + yyleng - 1); old_state = YY_START; BeginParameterStart(); char* s = yytext + 1; s = next_char(s, '\\'); char* p = s; ++s; s = next_non_alpha( s); *s = '\0'; yylval.text = newstr( p); return GDEFWITHARGS; } [\\]g?def{seps}{deftexmacro}{seps}[#][^\{]* { old_state = YY_START; BeginParameterStart(); int i = 1; while ( yytext[i] != '\\') ++i; yylval.text = newstr( yytext+i); return DEFWITHUNKNOWNARGS; } /* Macro Parameter Parsing */ /* ------------------------- */ [\\]"\n" { inc_line(); current_parameter = yytext; IfParameterParsing( false) return PARAMETER; break; } "\n" | "%".*[\n]{w} { /* Match one line TeX comments */ /* remove spaces in next line */ inc_line(); break; } {sepsp}+ { break;} /* ignore seps + sp before parameters */ "%".* { break;} /* Match one line TeX comments */ /* at the last line in file */ "\{" { current_parameter = string(); ++parameter_nesting; BeginParameterMode(); break; } "\[" { current_parameter = string(); ++parameter_nesting; parameter_option = true; BeginParameterMode(); break; } {texmacroskip} { current_parameter = yytext; int c = skiplimitedspaces_param(); if ( c == EOF) yyterminate(); if ( isalpha(c) || c == '*' || c == '#') current_parameter += SEPARATOR; IfParameterParsing( false) return PARAMETER; break; } {deftexmacro} | . { current_parameter = yytext; IfParameterParsing( false) return PARAMETER; break; } [\\]"\n" | "\n" { /* keep newlines */ current_parameter += yytext; inc_line(); break; } "%".*[\n]{w}("\n"{w})+ { /* Match comments with an empty line -> par */ current_parameter += "\n\n"; count_newlines( yytext); break; } "%".*[\n]{w} { /* Match one line TeX comments */ /* remove spaces in next line */ current_parameter += SEPARATOR; inc_line(); break; } "%".* { /* Match one line TeX comments */ /* at the last line in file */ current_parameter += SEPARATOR; break; } "\{" { current_parameter += yytext; ++parameter_nesting; break; } "\}" { if ( --parameter_nesting == 0) { IfParameterParsing( false) { if ( parameter_option) { printErrorMessage( ParameterOptionError); parameter_option = false; return PARAMETER_OPTION; } return PARAMETER; } } else current_parameter += yytext; break; } "]" { if ( parameter_nesting == 1 && parameter_option) { parameter_nesting--; parameter_option = false; IfParameterParsing( true) return PARAMETER_OPTION; } else current_parameter += yytext; break; } {texmacroskip} { current_parameter += yytext; int c = skiplimitedspaces_param(); if ( c == EOF) yyterminate(); if ( isalpha(c) || c == '*' || c == '#') current_parameter += SEPARATOR; break; } {deftexmacro} | [^\\\{\}%\]\n]+ | . { current_parameter += yytext; break; } /* Macro Parameter Parsing in AllttMode */ /* ------------------------------------- */ [\\]"\n" | "\n" { inc_line(); current_parameter = yytext; IfParameterParsing( false) return PARAMETER; break; } {sep}+ { break;} /* ignore seps before parameters */ "\{" { current_parameter = string(); ++parameter_nesting; BEGIN( AllttParameterMode); break; } "\[" { current_parameter = string(); ++parameter_nesting; parameter_option = true; BEGIN( AllttParameterMode); break; } {deftexmacro} | . { current_parameter = yytext; IfParameterParsing( false) return PARAMETER; break; } [\\]"\n" | "\n" { /* keep newlines */ current_parameter += yytext; inc_line(); break; } "\{" { current_parameter += yytext; ++parameter_nesting; break; } "\}" { if ( --parameter_nesting == 0) { IfParameterParsing( false) { if ( parameter_option) { printErrorMessage( ParameterOptionError); parameter_option = false; return PARAMETER_OPTION; } return PARAMETER; } } else current_parameter += yytext; break; } "]" { if ( parameter_nesting == 1 && parameter_option) { parameter_nesting--; parameter_option = false; IfParameterParsing( true) return PARAMETER_OPTION; } else current_parameter += yytext; break; } {deftexmacro} | [^\\\{\}%\]\n]+ | . { current_parameter += yytext; break; } /* C++ Parameter Parsing */ /* ------------------------- */ [\\]"\n" | "\n" { inc_line(); cc_string += ' '; break; } "\{" { if ( parameter_nesting++ > 0) cc_string += yytext; break; } "\}" { if ( --parameter_nesting == 0) { BEGIN( old_state); include_stack.push_string( in_string->name(), current_macro, in_string->line()); current_macro = string(); } else cc_string += yytext; break; } /* Special treatment of several macros in C++ text */ [\\][^a-zA-Z] { /* capture all quoted special symbols */ cc_string += yytext[1]; break; } [\\]"tt"{sepnls} { CC_Special("|T|");} [\\]"bf"{sepnls} { CC_Special("|B|");} [\\]"em"{sepnls} { CC_Special("|I|");} [\\]"it"{sepnls} { CC_Special("|I|");} [\\]"sl"{sepnls} { CC_Special("|I|");} [\\]"ccFont"{sepnls} { CC_Special("|I|"); } [\\]"l"?"dots"{sepnls} { CC_Special("..."); } {deftexmacro} { printErrorMessage( MacroInCModeError); cc_string += yytext; break; } {sep} { break; /* ignore separator */ } [^\n\{\}\\\001]+ | . { cc_string += yytext; break; } [\\]lciParseCC{seps}[\{][^\}]*[\}] { count_newlines(yytext); yytext[ yyleng - 1] = '\0'; char* s = yytext + 1; s = next_char(s, '{'); current_macro = s + 1; skiplimitedsepspaces(); int c = yyinput(); if ( c != '{') { printErrorMessage( ParseCCError); current_macro = string(); } else { old_state = YY_START; BEGIN( CCParameterMode); parameter_nesting = 1; cc_string = string(); } break; } /* Special Parser Modes */ /* ------------------------- */ [\\]lciBeginAlltt { skiplimitedspaces(); BEGIN( AllttMode); break; } [\\]lciEndAlltt { BEGIN( INITIAL); skiplimitedspaces(); break; } [\\]lciParseUntilDelimiter{seps}[\{]{seps}{texmacro}{seps}[\}] { old_state = YY_START; BEGIN( DelimiterMode); char* s = yytext + 1; s = next_char(s, '\\'); char* p = s; ++s; s = next_non_alpha( s); *s = '\0'; current_macro = p; skipseparator(); while ( (stop_character = yyinput()) == '\n') inc_line(); break; } "\n" { inc_line(); yymore(); break; } . { if ( yytext[yyleng-1] == stop_character) { BEGIN( old_state); yytext[yyleng-1] = '\0'; Macro_item item = fetchMacro( current_macro); parameters[0] = yytext; include_stack.push_string( current_macro + " in " +item.filename, expandMacro(current_macro, item, parameters, 1, 0), item.line); parameters[0] = string(); current_macro = string(); } else { yymore(); } break; } [\\]lciParseFile{seps}[\{]{seps}{texmacro}{seps}[\}]{seps}[\{][^\}]+[\}] { count_newlines(yytext); yytext[ yyleng - 1] = '\0'; char* s = yytext + 1; s = next_char(s, '\\'); char* p = s; ++s; s = next_non_alpha(s); *s = '\0'; while ( *s++ != '{'); string filename(s); crop_string(filename); remove_separator(filename); parameters[0] = string(); append_file_to_string( filename, parameters[0]); Macro_item item = fetchMacro( p); include_stack.push_string( string(p)+" in " +item.filename, expandMacro(p, item, parameters, 1, 0), item.line); parameters[0] = string(); break; } [\\]lciParseUntilEndToken{seps}[\{]{seps}{texmacro}{seps}[\}]{seps}[\{]{seps}{envir}{seps}[\}] { old_state = YY_START; BEGIN( EndTokenMode); char* s = yytext + 1; s = next_char(s, '\\'); char* p = s; ++s; s = next_non_alpha(s); *s = '\0'; current_macro = p; s = next_alpha(s); p = s; s = next_non_alpha(s); *s = '\0'; stop_envir = p; break; } "\n" { parameters[0] += yytext[0]; inc_line(); break; } {sep} { break; /* ignore separator */ } . { parameters[0] += yytext[0]; break; } [\\]end{seps}[\{]{seps}{envir}{seps}[\}] { parameters[1] = yytext; char* s = yytext + 5; s = next_alpha(s); char* p = s; s = next_non_alpha(s); *s = '\0'; if ( stop_envir == p) { BEGIN( old_state); include_stack.push_string( in_string->name(), string("\\end{") + p + '}', in_string->line()); Macro_item item = fetchMacro( current_macro); include_stack.push_string( current_macro + " in " +item.filename, expandMacro(current_macro, item, parameters, 1, 0), item.line); current_macro = string(); stop_envir = string(); parameters[0] = string(); } else { parameters[0] += parameters[1]; } parameters[1] = string(); break; } [\\]lcAsciiToHtml { old_state = YY_START; BeginParameterStart(); return ASCIITOHTML; } [\\]lciRawOutput { old_state = YY_START; BeginParameterStart(); return RAWOUTPUT; } [\\]lciRawOutputN{seps}[\{]{seps}{number}{seps}[\}] { char* s = yytext + 1; while ( *s && ! isdigit(*s)) ++s; int n = atoi( s); if ( n > 0) { s = new char[n+1]; yylval.text = s; while (n--) if ( (*(s++) = yyinput()) == '\n') inc_line(); *s = '\0'; return RAWOUTPUTN; } break; } [\\]lciAsciiOutputN{seps}[\{]{seps}{number}{seps}[\}] { char* s = yytext + 1; while ( *s && ! isdigit(*s)) ++s; int n = atoi( s); if ( n > 0) { s = new char[n+1]; char* p = s; while (n--) if ( (*(s++) = yyinput()) == '\n') inc_line(); *s = '\0'; yylval.text = convert_ascii_to_html( p); delete[] p; return RAWOUTPUTN; } break; } [\\]lciRawSkipN{seps}[\{]{seps}{number}{seps}[\}] { char* s = yytext + 1; while ( *s && ! isdigit(*s)) ++s; int n = atoi( s); if ( n > 0) { while (n--) if ( yyinput() == '\n') inc_line(); } break; } /* Index */ /* ---------------------- */ [\\]lciOpenFileforIndex { OpenFileforIndex(); break; } [\\]lciCloseFileforIndex { CloseFileforIndex(); break; } [\\]lciIndex { handleIndex(); break; } [\\]lciIndexTraitsClass { handleIndexTraitsClass(); break; } [\\]lciIndexRefName { handleIndexRefName(); break; } /* Special multicharacter sequences */ /* -------------------------------- */ "---" { yylval.text = " - "; return STRING; } "--" { yylval.text = "-"; return STRING; } /* Skip unwished tokens */ /* -------------------- */ [\\]lciSkipWhiteSpace { skipspaces(); break; } [\\]lciSkipNonWhiteSpace { skipspaces(); skipnonspaces(); break; } /* Single letter quotes that cannot be put in the style file */ /* --------------------------------------------------------- */ [\\][\{\}%] { yylval.character = yytext[1]; return CHAR; } [\\]{space} { yylval.character = ' '; return CHAR; } /* Small Caps Treatment */ /* -------------------------------------- */ [\\]lciBeginSmallCaps { skiplimitedspaces(); small_caps_mode = true; break; } [\\]lciEndSmallCaps { skiplimitedspaces(); small_caps_mode = false; break; } /* TeX macro expansion */ /* -------------------------------------- */ {texmacro} { yyleng = removespaces( yytext); if ( ! expand_macro()) { return STRING; } break; } /* Specials TeX sequence macro expansion: */ /* see also below for active char expansion */ /* ----------------------------------------- */ "$$" { yyleng = removespaces( yytext); if ( ! expand_macro()) return STRING; break; } /* The rest: spaces and single characters */ /* -------------------------------------- */ [\\]?{ws} { if ( *yytext == '\\') yylval.text = yytext + 1; else yylval.text = yytext; return STRING; } {ws} { yylval.text = yytext; return STRING; } /* Speed up for the usual case of plain text, numbers and spaces */ [a-zA-Z0-9 \t]+ { if ( small_caps_mode) { yy_string = convert_to_small_caps( yytext); yylval.text = yy_string.c_str(); return STRING; } yylval.text = yytext; return STRING; } [\{\}] | . { if ( is_active_char( yytext[0])) { if ( ! expand_macro()) return STRING; } else { yylval.character = yytext[0]; if ( is_html_multi_character( yylval.character)) { yylval.text = html_multi_character( yylval.character); return STRING; } return CHAR; } break; } . { yylval.character = yytext[0]; if ( is_html_multi_character( yylval.character)) { yylval.text = html_multi_character( yylval.character); return STRING; } return CHAR; } %% /* returns true if EOF has been detected */ bool skipspaces_eof() { int c = yyinput(); while( c != EOF && (isspace(c) || c == SEPARATOR)) { if ( c == '\n') inc_line(); c = yyinput(); } if (c == EOF) { printErrorMessage( EOFInMacroExpansionError); return true; } yyunput( c, yytext ); return false; } /* returns true if EOF has been detected */ bool skipseparator_eof() { int c = yyinput(); while( c != EOF && c == SEPARATOR) { c = yyinput(); } if (c == EOF) { printErrorMessage( EOFInMacroExpansionError); return true; } yyunput( c, yytext ); return false; } /* returns true if EOF has been detected */ bool skiplimitedspaces_eof() { if ( YY_START == AllttMode) return false; int nl_count = 0; int c = yyinput(); while( c != EOF && isspace(c) && c != SEPARATOR) { if ( c == '\n') { if ( nl_count > 0) { yyunput( c, yytext ); yyunput( c, yytext ); return false; } else nl_count++; } c = yyinput(); } if ( nl_count > 0) inc_line(); if (c == EOF) { printErrorMessage( EOFInMacroExpansionError); return true; } yyunput( c, yytext ); return false; } /* returns last character read. If its EOF, terminate, */ /* else the char has been put back to the input stream. */ int skiplimitedspaces_param() { int nl_count = 0; int c = yyinput(); while( c != EOF && isspace(c) && c != SEPARATOR) { if ( c == '\n') { if ( nl_count > 0) { yyunput( c, yytext ); yyunput( c, yytext ); return '\n'; } else nl_count++; } c = yyinput(); } if ( nl_count > 0) inc_line(); if (c == EOF) { printErrorMessage( EOFInMacroExpansionError); return c; } yyunput( c, yytext ); return c; } /* returns true if EOF has been detected */ bool skiplimitedsepspaces_eof() { if ( YY_START == AllttMode) return skipseparator_eof(); int nl_count = 0; int c = yyinput(); while( c != EOF && (isspace(c) || c == SEPARATOR)) { if ( c == '\n') { if ( nl_count > 0) { yyunput( c, yytext ); yyunput( c, yytext ); return false; } else nl_count++; } c = yyinput(); } if ( nl_count > 0) inc_line(); if (c == EOF) { printErrorMessage( EOFInMacroExpansionError); return true; } yyunput( c, yytext ); return false; } /* returns true if EOF has been detected */ bool skipnonspaces_eof() { int c = yyinput(); while( c != EOF && ( ! isspace(c) || c == SEPARATOR)) { c = yyinput(); } if (c == EOF) { printErrorMessage( EOFInMacroExpansionError); return true; } yyunput( c, yytext ); return false; } size_t removespaces( char* s) { char* begin = s; char* p = s; while ( *s) { if ( isspace( *s) || *s == SEPARATOR) ++s; else *p++ = *s++; } *p = '\0'; return p - begin; } void inc_line() { in_string->line() ++; if ( line_switch) cerr << in_string->name() << " line " << in_string->line() << endl; } void count_newlines( const char* s) { while ( *s) { if ( *s == '\n') inc_line(); ++s; } } bool is_parameter_parsing_done( bool option, bool more_param) { BEGIN( old_state); if ( parameter_count == 0 && parameter_endopt == 0) { // Evaluation strategy for scanner defined commands yylval.text = newstr( current_parameter.c_str()); current_parameter = string(); BeginParameterStart(); return true; } // Evaluation strategy for user defined commands parameter_format += ( option ? 'o' : 'm'); parameters[ parameter_index + parameter_options] = current_parameter; current_parameter = string(); if ( option) { parameter_options++; if ( parameter_endopt > 0 && parameter_count == 0) parameter_endopt--; } else { parameter_index++; parameter_count--; } if ((parameter_count == 0) && (parameter_endopt > 0)) { if ( more_param) { parameter_nesting = 1; parameter_option = true; BeginParameterMode(); return false; } parameter_endopt = 0; } if ( parameter_count == 0 && parameter_endopt == 0) { string macro = current_macro; if ( parameter_options > 0) { macro += '@'; macro += parameter_format; } Macro_item item = fetchMacro( macro); include_stack.push_string( current_macro + " in "+item.filename, expandMacro(macro, item, parameters, parameter_index, parameter_options), item.line); current_macro = string(); for ( int i = 0; i < parameter_index + parameter_options; ++i) { parameters[i] = string(); } parameter_index = 0; parameter_options = 0; parameter_format = string(); } else BeginParameterStart(); return false; } // returns true if all went well. Return-value == false means return STRING. bool expand_macro() { if ( ! definedMacro( yytext)) { printErrorMessage( MacroUndefinedError, yytext); yylval.text = yytext; return false; } Macro_item item = fetchMacro( yytext); if ( item.n_param > 0 || item.n_opt_at_end > 0) { parameter_count = item.n_param; parameter_index = 0; parameter_options = 0; parameter_option = false; old_state = YY_START; if ( item.n_param == 0) { string s( yytext); if ( yytext[yyleng-1] == '*' || isalpha( yytext[yyleng-1])) skiplimitedsepspaces_eof(); int c = yyinput(); if ( c == '[') { parameter_nesting = 1; parameter_option = true; parameter_endopt = item.n_opt_at_end; current_macro = s; BeginParameterMode(); } else { if (c != EOF) yyunput( c, yytext ); include_stack.push_string( s + " in " + item.filename, item.body, item.line); } } else { parameter_endopt = item.n_opt_at_end; current_macro = yytext; BeginParameterStart(); } } else { string s( yytext); if ( yytext[yyleng-1] == '*' || isalpha( yytext[yyleng-1])) skiplimitedspaces_eof(); if ( item.fct) { if ( macro_exp_switch) { string repl = item.fct( s, parameters, 0, 0); cerr << '`' << s << "' Internally replaced with `" << repl << "'" <"; } }