Edit

kc3-lang/angle/src/compiler/glslang.l

Branch :

  • Show log

    Commit

  • Author : alokp@chromium.org
    Date : 2010-09-23 17:53:56
    Hash : 07620a58
    Message : - Moved the implementation for ShCompile to the compiler class so that internal details about compiler can be encapsulated. Now we do not need to expose built-in symbol table. - Fixed a few const violations. - Added CollectAttribsUniforms class. BUG=26 Review URL: http://codereview.appspot.com/2263041 git-svn-id: https://angleproject.googlecode.com/svn/trunk@437 736b8ea6-26fd-11df-bfd4-992fa37f6226

  • src/compiler/glslang.l
  • /*
    //
    // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    */
    /* Based on
    ANSI C grammar, Lex specification
    
    In 1985, Jeff Lee published this Lex specification together with a Yacc 
    grammar for the April 30, 1985 ANSI C draft.  Tom Stockfisch reposted 
    both to net.sources in 1987; that original, as mentioned in the answer 
    to question 17.25 of the comp.lang.c FAQ, can be ftp'ed from ftp.uu.net, 
    file usenet/net.sources/ansi.c.grammar.Z. 
    
    I intend to keep this version as close to the current C Standard grammar 
    as possible; please let me know if you discover discrepancies. 
    
    Jutta Degener, 1995 
    */
    
    D           [0-9]
    L           [a-zA-Z_]
    H           [a-fA-F0-9]
    E           [Ee][+-]?{D}+
    O           [0-7]
    
    %option nounput 
    %{
    #include <stdio.h>
    #include <stdlib.h>
    
    #include "compiler/ParseHelper.h"
    #include "glslang_tab.h"
    
    /* windows only pragma */
    #ifdef _MSC_VER
    #pragma warning(disable : 4102)
    #endif
    
    int yy_input(char* buf, int max_size);
    
    extern int yyparse(void*);
    #define YY_DECL int yylex(YYSTYPE* pyylval, void* parseContextLocal)
    #define parseContext (*((TParseContext*)(parseContextLocal)))
     
    #define YY_INPUT(buf,result,max_size) (result = yy_input(buf, max_size))
    
    %}
    
    /*
    TODO(alokp): yylineno is only here to support old flex.exe in compiler/tools.
    Remove it when we can exclusively use the newer version.
    */
    %option yylineno
    
    %option noyywrap
    %option never-interactive
    %x FIELDS
    
    
    %%
    <*>"//"[^\n]*"\n"     { /* ?? carriage and/or line-feed? */ };
    
    "invariant"    {  pyylval->lex.line = yylineno; return(INVARIANT); }
    "highp"        {  pyylval->lex.line = yylineno; return(HIGH_PRECISION); }
    "mediump"      {  pyylval->lex.line = yylineno; return(MEDIUM_PRECISION); }
    "lowp"         {  pyylval->lex.line = yylineno; return(LOW_PRECISION); }
    "precision"    {  pyylval->lex.line = yylineno; return(PRECISION); }
    
    "attribute"    {  pyylval->lex.line = yylineno; return(ATTRIBUTE); }
    "const"        {  pyylval->lex.line = yylineno; return(CONST_QUAL); }
    "uniform"      {  pyylval->lex.line = yylineno; return(UNIFORM); }
    "varying"      {  pyylval->lex.line = yylineno; return(VARYING); }
    
    "break"        {  pyylval->lex.line = yylineno; return(BREAK); }
    "continue"     {  pyylval->lex.line = yylineno; return(CONTINUE); }
    "do"           {  pyylval->lex.line = yylineno; return(DO); }
    "for"          {  pyylval->lex.line = yylineno; return(FOR); }
    "while"        {  pyylval->lex.line = yylineno; return(WHILE); }
    
    "if"           {  pyylval->lex.line = yylineno; return(IF); }
    "else"         {  pyylval->lex.line = yylineno; return(ELSE); }
    
    "in"           {  pyylval->lex.line = yylineno; return(IN_QUAL); }
    "out"          {  pyylval->lex.line = yylineno; return(OUT_QUAL); }
    "inout"        {  pyylval->lex.line = yylineno; return(INOUT_QUAL); }
    
    "float"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(FLOAT_TYPE); }
    "int"          {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(INT_TYPE); }
    "void"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(VOID_TYPE); }
    "bool"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(BOOL_TYPE); }
    "true"         {  pyylval->lex.line = yylineno; pyylval->lex.b = true;  return(BOOLCONSTANT); }
    "false"        {  pyylval->lex.line = yylineno; pyylval->lex.b = false; return(BOOLCONSTANT); }
    
    "discard"      {  pyylval->lex.line = yylineno; return(DISCARD); }
    "return"       {  pyylval->lex.line = yylineno; return(RETURN); }
    
    "mat2"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX2); }
    "mat3"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX3); }
    "mat4"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(MATRIX4); }
    
    "vec2"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC2); }
    "vec3"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC3); }
    "vec4"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (VEC4); }
    "ivec2"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC2); }
    "ivec3"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC3); }
    "ivec4"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (IVEC4); }
    "bvec2"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC2); }
    "bvec3"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC3); }
    "bvec4"        {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return (BVEC4); }
    
    "sampler2D"       {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLER2D; }
    "samplerCube"     {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return SAMPLERCUBE; }
    
    "struct"       {  pyylval->lex.line = yylineno; parseContext.lexAfterType = true; return(STRUCT); }
    
    "asm"          {  PaReservedWord(); return 0; }
    
    "class"        {  PaReservedWord(); return 0; }
    "union"        {  PaReservedWord(); return 0; }
    "enum"         {  PaReservedWord(); return 0; }
    "typedef"      {  PaReservedWord(); return 0; }
    "template"     {  PaReservedWord(); return 0; }
    "this"         {  PaReservedWord(); return 0; }
    "packed"       {  PaReservedWord(); return 0; }
    
    "goto"         {  PaReservedWord(); return 0; }
    "switch"       {  PaReservedWord(); return 0; }
    "default"      {  PaReservedWord(); return 0; }
    
    "inline"       {  PaReservedWord(); return 0; }
    "noinline"     {  PaReservedWord(); return 0; }
    "volatile"     {  PaReservedWord(); return 0; }
    "public"       {  PaReservedWord(); return 0; }
    "static"       {  PaReservedWord(); return 0; }
    "extern"       {  PaReservedWord(); return 0; }
    "external"     {  PaReservedWord(); return 0; }
    "interface"    {  PaReservedWord(); return 0; }
    
    "long"         {  PaReservedWord(); return 0; }
    "short"        {  PaReservedWord(); return 0; }
    "double"       {  PaReservedWord(); return 0; }
    "half"         {  PaReservedWord(); return 0; }
    "fixed"        {  PaReservedWord(); return 0; }
    "unsigned"     {  PaReservedWord(); return 0; }
    
    "input"        {  PaReservedWord(); return 0; }
    "output"       {  PaReservedWord(); return 0; }
    
    "hvec2"        {  PaReservedWord(); return 0; }
    "hvec3"        {  PaReservedWord(); return 0; }
    "hvec4"        {  PaReservedWord(); return 0; }
    "fvec2"        {  PaReservedWord(); return 0; }
    "fvec3"        {  PaReservedWord(); return 0; }
    "fvec4"        {  PaReservedWord(); return 0; }
    "dvec2"        {  PaReservedWord(); return 0; }
    "dvec3"        {  PaReservedWord(); return 0; }
    "dvec4"        {  PaReservedWord(); return 0; }
    
    "sizeof"       {  PaReservedWord(); return 0; }
    "cast"         {  PaReservedWord(); return 0; }
    
    "namespace"    {  PaReservedWord(); return 0; }
    "using"        {  PaReservedWord(); return 0; }
    
    {L}({L}|{D})*       {  
       pyylval->lex.line = yylineno; 
       pyylval->lex.string = NewPoolTString(yytext); 
       return PaIdentOrType(*pyylval->lex.string, parseContext, pyylval->lex.symbol); 
    }
    
    0[xX]{H}+         { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
    0{O}+             { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
    0{D}+             { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;}
    {D}+              { pyylval->lex.line = yylineno; pyylval->lex.i = strtol(yytext, 0, 0); return(INTCONSTANT); }
    
    {D}+{E}           { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
    {D}+"."{D}*({E})? { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
    "."{D}+({E})?     { pyylval->lex.line = yylineno; pyylval->lex.f = static_cast<float>(atof(yytext)); return(FLOATCONSTANT); }
    
    "/*"            {  int ret = PaParseComment(pyylval->lex.line, parseContext); if (!ret) return ret; }   
    
    "+="            {  pyylval->lex.line = yylineno; return(ADD_ASSIGN); }
    "-="            {  pyylval->lex.line = yylineno; return(SUB_ASSIGN); }
    "*="            {  pyylval->lex.line = yylineno; return(MUL_ASSIGN); }
    "/="            {  pyylval->lex.line = yylineno; return(DIV_ASSIGN); }
    "%="            {  pyylval->lex.line = yylineno; return(MOD_ASSIGN); }
    "<<="           {  pyylval->lex.line = yylineno; return(LEFT_ASSIGN); }
    ">>="           {  pyylval->lex.line = yylineno; return(RIGHT_ASSIGN); }
    "&="            {  pyylval->lex.line = yylineno; return(AND_ASSIGN); }
    "^="            {  pyylval->lex.line = yylineno; return(XOR_ASSIGN); }
    "|="            {  pyylval->lex.line = yylineno; return(OR_ASSIGN); }
    
    "++"            {  pyylval->lex.line = yylineno; return(INC_OP); }
    "--"            {  pyylval->lex.line = yylineno; return(DEC_OP); }
    "&&"            {  pyylval->lex.line = yylineno; return(AND_OP); }
    "||"            {  pyylval->lex.line = yylineno; return(OR_OP); }
    "^^"            {  pyylval->lex.line = yylineno; return(XOR_OP); }
    "<="            {  pyylval->lex.line = yylineno; return(LE_OP); }
    ">="            {  pyylval->lex.line = yylineno; return(GE_OP); }
    "=="            {  pyylval->lex.line = yylineno; return(EQ_OP); }
    "!="            {  pyylval->lex.line = yylineno; return(NE_OP); }
    "<<"            {  pyylval->lex.line = yylineno; return(LEFT_OP); }
    ">>"            {  pyylval->lex.line = yylineno; return(RIGHT_OP); }
    ";"         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(SEMICOLON); }
    ("{"|"<%")      {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(LEFT_BRACE); }
    ("}"|"%>")      {  pyylval->lex.line = yylineno; return(RIGHT_BRACE); }
    ","         {  pyylval->lex.line = yylineno; if (parseContext.inTypeParen) parseContext.lexAfterType = false; return(COMMA); }
    ":"         {  pyylval->lex.line = yylineno; return(COLON); }
    "="         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; return(EQUAL); }
    "("         {  pyylval->lex.line = yylineno; parseContext.lexAfterType = false; parseContext.inTypeParen = true; return(LEFT_PAREN); }
    ")"         {  pyylval->lex.line = yylineno; parseContext.inTypeParen = false; return(RIGHT_PAREN); }
    ("["|"<:")      {  pyylval->lex.line = yylineno; return(LEFT_BRACKET); }
    ("]"|":>")      {  pyylval->lex.line = yylineno; return(RIGHT_BRACKET); }
    "."         { BEGIN(FIELDS);  return(DOT); }
    "!"         {  pyylval->lex.line = yylineno; return(BANG); }
    "-"         {  pyylval->lex.line = yylineno; return(DASH); }
    "~"         {  pyylval->lex.line = yylineno; return(TILDE); }
    "+"         {  pyylval->lex.line = yylineno; return(PLUS); }
    "*"         {  pyylval->lex.line = yylineno; return(STAR); }
    "/"         {  pyylval->lex.line = yylineno; return(SLASH); }
    "%"         {  pyylval->lex.line = yylineno; return(PERCENT); }
    "<"         {  pyylval->lex.line = yylineno; return(LEFT_ANGLE); }
    ">"         {  pyylval->lex.line = yylineno; return(RIGHT_ANGLE); }
    "|"         {  pyylval->lex.line = yylineno; return(VERTICAL_BAR); }
    "^"         {  pyylval->lex.line = yylineno; return(CARET); }
    "&"         {  pyylval->lex.line = yylineno; return(AMPERSAND); }
    "?"         {  pyylval->lex.line = yylineno; return(QUESTION); }
    
    <FIELDS>{L}({L}|{D})* { 
    BEGIN(INITIAL);      
        pyylval->lex.line = yylineno;     
        pyylval->lex.string = NewPoolTString(yytext); 
        return FIELD_SELECTION; }
    <FIELDS>[ \t\v\f\r] {}
    
    [ \t\v\n\f\r]   {  }
    <*><<EOF>> { (&parseContext)->AfterEOF = true; yy_delete_buffer(YY_CURRENT_BUFFER); yyterminate();}
    <*>.    { parseContext.infoSink.info << "FLEX: Unknown char " << yytext << "\n";
              return 0; }
    
    %%
    
    
    //Including Pre-processor.
    extern "C" {
      #include "compiler/preprocessor/preprocess.h"
    } 
    
    //
    // The YY_INPUT macro just calls this.  Maybe this could be just put into
    // the macro directly.
    //
    
    int yy_input(char* buf, int max_size)
    {
        int len;
    
        if ((len = yylex_CPP(buf, max_size)) == 0)
            return 0;
        if (len >= max_size) 
            YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
    
        buf[len] = ' ';
    	return len+1;
    }
    
    
    //
    // Parse an array of strings using yyparse.  We set up globals used by
    // yywrap.
    //
    // Returns 0 for success, as per yyparse().
    //
    int PaParseStrings(const char* const argv[], const int strLen[], int argc, TParseContext& parseContextLocal)
    {
        int argv0len;
        
        ScanFromString(argv[0]); 
        
        //Storing the Current Compiler Parse context into the cpp structure.
    	cpp->pC = (void*)&parseContextLocal;
    	
    	if (!argv || argc == 0)
            return 1;
        
        for (int i = 0; i < argc; ++i) {
            if (!argv[i]) {
                parseContextLocal.error(0, "Null shader source string", "", "");
                parseContextLocal.recover();
                return 1;
            }
        }
        
        if (!strLen) {
            argv0len = (int) strlen(argv[0]);
            strLen   = &argv0len;
        }
        yyrestart(0);
        (&parseContextLocal)->AfterEOF = false;
        cpp->PaWhichStr = 0;
        cpp->PaArgv     = argv;
        cpp->PaArgc     = argc;
        cpp->PaStrLen   = strLen;
        cpp->pastFirstStatement = 0;
        yylineno   = 1;
       
        if (*cpp->PaStrLen >= 0) {    
            int ret = yyparse((void*)(&parseContextLocal));
            if (ret || cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0)
                 return 1;
            else
                 return 0;
        }
        else
            return 0;
    }
    
    void yyerror(const char *s) 
    {
        if (((TParseContext *)cpp->pC)->AfterEOF) {
            if (cpp->tokensBeforeEOF == 1) {
                GlobalParseContext->error(yylineno, "syntax error", "pre-mature EOF", s, "");
                GlobalParseContext->recover();
            }
        } else {
            GlobalParseContext->error(yylineno, "syntax error", yytext, s, "");
            GlobalParseContext->recover();
        }            
    }
    
    void PaReservedWord()
    {
        GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", "");
        GlobalParseContext->recover();
    }
    
    int PaIdentOrType(TString& id, TParseContext& parseContextLocal, TSymbol*& symbol)
    {
        symbol = parseContextLocal.symbolTable.find(id);
        if (parseContextLocal.lexAfterType == false && symbol && symbol->isVariable()) {
            TVariable* variable = static_cast<TVariable*>(symbol);
            if (variable->isUserType()) {
                parseContextLocal.lexAfterType = true;
                return TYPE_NAME;
            }
        }
        
        return IDENTIFIER;
    }
    
    int PaParseComment(int &lineno, TParseContext& parseContextLocal)
    {
        int transitionFlag = 0;
        int nextChar;
        
        while (transitionFlag != 2) {
            nextChar = yyinput();
            if (nextChar == '\n')
                 lineno++;
            switch (nextChar) {
            case '*' :
                transitionFlag = 1;
                break;
            case '/' :  /* if star is the previous character, then it is the end of comment */
                if (transitionFlag == 1) {
                    return 1 ;
                }
                break;
            case EOF :
                /* Raise error message here */
                parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", "");
                GlobalParseContext->recover();
                return YY_NULL; 
            default :  /* Any other character will be a part of the comment */
                transitionFlag = 0;
            }
        }
        return 1;
    }
    
    extern "C" {
    
    void CPPDebugLogMsg(const char *msg)
    {
        ((TParseContext *)cpp->pC)->infoSink.debug.message(EPrefixNone, msg);
    }
    
    void CPPWarningToInfoLog(const char *msg)
    {
        ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg, yylineno); 
    }
    
    void CPPShInfoLogMsg(const char *msg)
    {
        ((TParseContext *)cpp->pC)->error(yylineno,"", "",msg,"");
        GlobalParseContext->recover();
    }
    
    void CPPErrorToInfoLog(char *msg)
    {
        ((TParseContext *)cpp->pC)->error(yylineno,"syntax error", "",msg,"");
        GlobalParseContext->recover();
    }
    
    void SetLineNumber(int line)
    {
        yylineno &= ~SourceLocLineMask;
        yylineno |= line;
    }
    
    void SetStringNumber(int string)
    {
        yylineno = (string << SourceLocStringShift) | (yylineno & SourceLocLineMask);
    }
    
    int GetStringNumber(void)
    {
        return yylineno >> 16;
    }
    
    int GetLineNumber(void)
    {
        return yylineno & SourceLocLineMask;
    }
    
    void IncLineNumber(void)
    {
        if ((yylineno & SourceLocLineMask) <= SourceLocLineMask)
            ++yylineno;
    }
    
    void DecLineNumber(void)
    {
        if ((yylineno & SourceLocLineMask) > 0)
            --yylineno;
    }
    
    void HandlePragma(const char **tokens, int numTokens)
    {    
        if (!strcmp(tokens[0], "optimize")) {
            if (numTokens != 4) {
                CPPShInfoLogMsg("optimize pragma syntax is incorrect");
                return;
            }
            
            if (strcmp(tokens[1], "(")) {
                CPPShInfoLogMsg("\"(\" expected after 'optimize' keyword");
                return;
            }
                
            if (!strcmp(tokens[2], "on"))
                ((TParseContext *)cpp->pC)->contextPragma.optimize = true;
            else if (!strcmp(tokens[2], "off"))
                ((TParseContext *)cpp->pC)->contextPragma.optimize = false;
            else {
                CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'optimize' pragma");
                return;
            }
            
            if (strcmp(tokens[3], ")")) {
                CPPShInfoLogMsg("\")\" expected to end 'optimize' pragma");
                return;
            }
        } else if (!strcmp(tokens[0], "debug")) {
            if (numTokens != 4) {
                CPPShInfoLogMsg("debug pragma syntax is incorrect");
                return;
            }
            
            if (strcmp(tokens[1], "(")) {
                CPPShInfoLogMsg("\"(\" expected after 'debug' keyword");
                return;
            }
                
            if (!strcmp(tokens[2], "on"))
                ((TParseContext *)cpp->pC)->contextPragma.debug = true;
            else if (!strcmp(tokens[2], "off"))
                ((TParseContext *)cpp->pC)->contextPragma.debug = false;
            else {
                CPPShInfoLogMsg("\"on\" or \"off\" expected after '(' for 'debug' pragma");
                return;
            }
            
            if (strcmp(tokens[3], ")")) {
                CPPShInfoLogMsg("\")\" expected to end 'debug' pragma");
                return;
            }
        } else {
    
    #ifdef PRAGMA_TABLE
            //
            // implementation specific pragma
            // use ((TParseContext *)cpp->pC)->contextPragma.pragmaTable to store the information about pragma
            // For now, just ignore the pragma that the implementation cannot recognize
            // An Example of one such implementation for a pragma that has a syntax like
            // #pragma pragmaname(pragmavalue)
            // This implementation stores the current pragmavalue against the pragma name in pragmaTable.
            //        
            if (numTokens == 4 && !strcmp(tokens[1], "(") && !strcmp(tokens[3], ")")) {              
                TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable;
                TPragmaTable::iterator iter;
                iter = pragmaTable.find(TString(tokens[0]));
                if (iter != pragmaTable.end()) {
                    iter->second = tokens[2];
                } else {
                    pragmaTable[ tokens[0] ] = tokens[2];
                }        
            } else if (numTokens >= 2) {
                TPragmaTable& pragmaTable = ((TParseContext *)cpp->pC)->contextPragma.pragmaTable;
                TPragmaTable::iterator iter;
                iter = pragmaTable.find(TString(tokens[0]));
                if (iter != pragmaTable.end()) {
                    iter->second = tokens[1];
                } else {
                    pragmaTable[ tokens[0] ] = tokens[1];
                }
            }
    #endif // PRAGMA_TABLE
        }
    }
    
    void StoreStr(char *string)
    {
        TString strSrc;
        strSrc = TString(string);
    
        ((TParseContext *)cpp->pC)->HashErrMsg = ((TParseContext *)cpp->pC)->HashErrMsg + " " + strSrc;
    }
    
    const char* GetStrfromTStr(void)
    {
        cpp->ErrMsg = (((TParseContext *)cpp->pC)->HashErrMsg).c_str();
        return cpp->ErrMsg;
    }
    
    void ResetTString(void)
    {
        ((TParseContext *)cpp->pC)->HashErrMsg = "";
    }
    
    TBehavior GetBehavior(const char* behavior)
    {
        if (!strcmp("require", behavior))
            return EBhRequire;
        else if (!strcmp("enable", behavior))
            return EBhEnable;
        else if (!strcmp("disable", behavior))
            return EBhDisable;
        else if (!strcmp("warn", behavior))
            return EBhWarn;
        else {
            CPPShInfoLogMsg((TString("behavior '") + behavior + "' is not supported").c_str());
            return EBhDisable;
        }        
    }
    
    void  updateExtensionBehavior(const char* extName, const char* behavior)
    {
        TBehavior behaviorVal = GetBehavior(behavior);
        TMap<TString, TBehavior>:: iterator iter;
        TString msg;
        
        // special cased for all extension
        if (!strcmp(extName, "all")) {
            if (behaviorVal == EBhRequire || behaviorVal == EBhEnable) {
                CPPShInfoLogMsg("extension 'all' cannot have 'require' or 'enable' behavior");  
                return;
            } else {
                for (iter =  ((TParseContext *)cpp->pC)->extensionBehavior.begin(); iter != ((TParseContext *)cpp->pC)->extensionBehavior.end(); ++iter)
                    iter->second = behaviorVal;
            }        
        } else {
            iter = ((TParseContext *)cpp->pC)->extensionBehavior.find(TString(extName));
            if (iter == ((TParseContext *)cpp->pC)->extensionBehavior.end()) {
                switch (behaviorVal) {
                case EBhRequire:
                    CPPShInfoLogMsg((TString("extension '") + extName + "' is not supported").c_str());  
                    break;
                case EBhEnable:
                case EBhWarn:
                case EBhDisable:
                    msg = TString("extension '") + extName + "' is not supported";
                    ((TParseContext *)cpp->pC)->infoSink.info.message(EPrefixWarning, msg.c_str(), yylineno); 
                    break;
                }
                return;
            } else
                iter->second = behaviorVal;
        }
    }
            
    }  // extern "C"
    
    void setInitialState()
    {
        yy_start = 1;
    }