%option prefix="vs10_" %x INCLUDE DEFINE DEFSTR DEFSPACE SKIPLINE EATCOMMENT EATSTRING SAVELINE %x MACRONAME MACROBODY MACROPARM EATMACRO EATDEFINE MODIFIER MACROPARMSTART %x IFDEFNAME IFDEFBODY ENDMACRO MACROPARMEND %{ #include #include #ifdef _WIN32 #include # ifdef __GNUC__ # include # include # endif #else #include #include #define _stat stat #define _open open #define _O_RDONLY O_RDONLY #define _fstat fstat #define _close close #define stricmp strcasecmp #endif #include #include #include #include "macro.h" #include "nvparse_errors.h" #include "vs1.0_inst_list.h" #include "_vs1.0_parser.h" #define yylineno line_number #include "nvparse_externs.h" #define yylineno line_number int line_incr; void LexError(char *format, ...); void LexWarning(char *format, ...); char *ReadTextFile(const char * filename); unsigned int MakeRegisterMask(char *findName); unsigned int FindSwizzleValue(char *swizzleText); enum ERROR_VALUES { ERROR_NONE = 0, ERROR_MEMORY_ALLOC, ERROR_FILE_OPEN, ERROR_UNSUCCESSFUL_ASSEMBLE, ERROR_TOO_MANY_PARMS, ERROR_DEST_WRITE, ERROR_LIST_OPEN, ERROR_DEST_OPEN, ERROR_NO_ARGUMENTS, ERROR_MACRO_OVERRUN }; //extern void GenSwitchFileNames(char *fileName); //extern unsigned int gLinesAssembled; unsigned int gLinesAssembled; #define YY_INPUT(buf,result,max_size) \ { \ int c = *myin++; \ result = (c == 0) ? YY_NULL : (buf[0] = c, 1); \ } #define SAFEDELETEARRAY(x) if ((x) != NULL) \ delete [] (x) #define SAFEFREE(x) if ((x) != NULL) \ free((x)) #define MAXREPLACESTRING 255 char gReplaceText[MAXREPLACESTRING+1]; // // forward prototypes for macro functions // void MacroIncFunction(char *, unsigned int *, char **); void MacroDecFunction(char *, unsigned int *, char **); void MacroAddFunction(char *, unsigned int *, char **); void MacroSubFunction(char *, unsigned int *, char **); MACROFUNCTIONS gMacroFunctions[] = { { "inc(", MacroIncFunction }, { "dec(", MacroDecFunction }, { "add(", MacroAddFunction }, { "sub(", MacroSubFunction } }; #define NUM_MACRO_FUNCTIONS (sizeof(gMacroFunctions) / sizeof(MACROFUNCTIONS)) #define MAX_INCLUDE_DEPTH 1024 typedef struct INCLUDEINFO { char *fileName; unsigned int lineNo; YY_BUFFER_STATE buffer; MACROENTRY *lastInvokeMacro; // save off in case nested macros. MACROENTRY *lastParseMacro; // recursive macros MACROTEXT *lastMacroLineParse; // save off for recursive lines of macros working on. bool lastbInsideMacro; // save off for recursive macros bool lastbInsideDefine; // save off for recursive macros/defines bool lastbInsideInclude; bool lastbProcessingIFDEF; // save off #define information // FILE *fileHandle; char *prevString; char *nextString; } INCLUDEINFO; INCLUDEINFO gIncludeStack[MAX_INCLUDE_DEPTH]; int gIncludeStackIndex = 0; IFDEFINFO gIfDefStack[MAX_IFDEF_DEPTH]; int gIfDefStackIndex = 0; unsigned int &base_linenumber = gIncludeStack[0].lineNo; bool gbInsideInclude = false; bool gbProcessingBuiltIn = false; bool gbProcessingDefine = false; unsigned int gCountParen = 0; bool gbProcessingIFDEF = false; bool gbIFDEF = false; bool gbCompareDefine = false; unsigned int gIfDefStartLine; MACROENTRY *gLastMacro; MACROENTRY *gInvokeMacro; MACROENTRY *gTempMacro; // until all the parameters are read MACROENTRY *FindMacro(char *macroName); MACROENTRY *FindNMacro(char *macroName, unsigned int sLen); MACROFUNCTIONPTR gMacroCallFunction; char *builtInMacros = "macro m3x2 reg1, reg2, reg3\n" " dp3 %reg1.x, %reg2, %reg3\n" " dp3 %reg1.y, %reg2, %inc(%reg3)\n" "endm"; // // local prototypes // void CleanUp(); void ReplaceMacroParms(char *srcLine, char *destLine, MACROENTRY *srcParms, MACROENTRY *invParms); MACROTEXT *SaveMacroText(char *srcText, MACROTEXT *lastMacroText); void FreeMacroEntry(MACROENTRY *macEntry); void EndMacroParms(); char *FindAlphaNum(char *srcStr, unsigned int *sLen); void DebugUnhandledState(); unsigned int gCommentStartLine; unsigned int gMacroStartLine; char *gCurFileName = NULL; #define MAXSAVELINE 4095 char gSaveLine[MAXSAVELINE+1]; char gMacroLine[MAXSAVELINE+1]; #if 1 #ifdef _DEBUG #define ECHO DebugUnhandledState(); #else #define ECHO #endif #endif bool gbInsideMacro = false; // flag if we are doing a macro replace or not. bool gbTempInsideMacro = false; unsigned int gInvokeState = INITIAL; MACROENTRY *gParseMacro; // which source macro entry we are using MACROENTRY *gTempParseMacro; // temporary holder until parameters are received. MACROTEXT *gMacroLineParse; // which line we are currently parsing inside the macro invocation typedef enum OPCODETYPE { TYPE_NONE = 0, TYPE_VERTEX_SHADER = 1, TYPE_PIXEL_SHADER = 2 }; typedef struct OPCODEMAP { char *string; // string for opcode int tokenName; // name of the corresponding token int numArguments; // number of arguments for opcode float version; // minimum version supported in. int opcodeTypeFlags; // whether opcode can be used in vertex shader or pixel shader bool opcodeModify; // if opcode modifiers can be used bool textureOpcode; // only outputs to the texture unit } OPCODEMAP; #ifndef TRUE #define TRUE true #endif #ifndef FALSE #define FALSE false #endif OPCODEMAP theOpcodes[] = { { "add", ADD_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER | TYPE_PIXEL_SHADER, TRUE, FALSE }, { "dp3", DP3_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER | TYPE_PIXEL_SHADER, TRUE, FALSE }, { "dp4", DP4_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "dst", DST_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "exp", EXP_INSTR, 2, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "expp", EXPP_INSTR, 2, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "frc", FRC_INSTR, 2, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "lit", LIT_INSTR, 2, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "log", LOG_INSTR, 2, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "logp", LOGP_INSTR, 2, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "m3x2", M3X2_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "m3x3", M3X3_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "m3x4", M3X4_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "m4x3", M4X3_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "m4x4", M4X4_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "mad", MAD_INSTR, 4, 1.0f, TYPE_VERTEX_SHADER | TYPE_PIXEL_SHADER, TRUE, FALSE }, { "max", MAX_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "min", MIN_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "mov", MOV_INSTR, 2, 1.0f, TYPE_VERTEX_SHADER | TYPE_PIXEL_SHADER, TRUE, FALSE }, { "mul", MUL_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER | TYPE_PIXEL_SHADER, TRUE, FALSE }, { "nop", NOP_INSTR, 0, 1.0f, TYPE_VERTEX_SHADER | TYPE_PIXEL_SHADER, TRUE, FALSE }, { "rcp", RCP_INSTR, 2, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "rsq", RSQ_INSTR, 2, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "sge", SGE_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "slt", SLT_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER, FALSE, FALSE }, { "sub", SUB_INSTR, 3, 1.0f, TYPE_VERTEX_SHADER | TYPE_PIXEL_SHADER, TRUE, FALSE }, }; #define NUMOPCODES (sizeof(theOpcodes) / sizeof(OPCODEMAP)) OPCODEMAP *FindOpcode(char *findName); %} digits ([0-9]+) digit ([0-9]) pt "." sign [+-]? exponent ([eE]{sign}{digits}) alpha [a-zA-Z_] alphadigs [a-zA-Z0-9_] notAlphaDigs ([^a-zA-Z0-9_]) identifier {alpha}{alphadigs}* %% .*\n { gbProcessingDefine = false; gSaveLine[0] = '\0'; strncat(gSaveLine, yytext, MAXSAVELINE); // GenDebugLine(); if (gbProcessingIFDEF && (gbCompareDefine != gbIFDEF)) { BEGIN(IFDEFBODY); } else { BEGIN(INITIAL); } yyless(0); } .* { gbProcessingDefine = false; gSaveLine[0] = '\0'; strncat(gSaveLine, yytext, MAXSAVELINE); // GenDebugLine(); if (gbProcessingIFDEF && (gbCompareDefine != gbIFDEF)) { BEGIN(IFDEFBODY); } else { BEGIN(INITIAL); } yyless(0); } a{digits}[ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); vs10_lval.reg.type = TYPE_ADDRESS_REG; vs10_lval.reg.index = atoi(&yytext[1]); if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return REGISTER; } v{digits}[ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); vs10_lval.reg.type = TYPE_VERTEX_ATTRIB_REG; vs10_lval.reg.index = atoi(&yytext[1]); if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return REGISTER; } r{digits}[ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); vs10_lval.reg.type = TYPE_TEMPORARY_REG; vs10_lval.reg.index = atoi(&yytext[1]); if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return REGISTER; } c{digits}[ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); vs10_lval.reg.type = TYPE_CONSTANT_MEM_REG; vs10_lval.reg.index = atoi(&yytext[1]); if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return REGISTER; } oT{digits}[ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); vs10_lval.reg.type = TYPE_TEXTURE_RESULT_REG; vs10_lval.reg.index = atoi(&yytext[2]); if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return REGISTER; } oD{digits}[ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); vs10_lval.reg.type = TYPE_COLOR_RESULT_REG; vs10_lval.reg.index = atoi(&yytext[2]); if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return REGISTER; } oFog[ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); vs10_lval.reg.type = TYPE_FOG_RESULT_REG; if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return REGISTER; } oPos[ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); vs10_lval.reg.type = TYPE_POSITION_RESULT_REG; if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return REGISTER; } oPts[ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); vs10_lval.reg.type = TYPE_POINTS_RESULT_REG; if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return REGISTER; } [a-zA-Z][a-zA-Z0-9]+[ \t\n_] { unsigned int offset; offset = strcspn(yytext, " \t\n_"); yyless(offset); OPCODEMAP *opcodeMap = FindOpcode(yytext); if ( opcodeMap != NULL ) { // fprintf( stderr, "%s\t", opcodeMap->string ); return( opcodeMap->tokenName ); } else { gTempParseMacro = FindMacro(yytext); if (gTempParseMacro != NULL) { if (gIncludeStackIndex >= MAX_INCLUDE_DEPTH ) { LexError("macros nested too deeply"); exit( 1 ); } if (gTempParseMacro->firstMacroLines != NULL) { gTempMacro = (MACROENTRY *)malloc(sizeof(MACROENTRY)); if (gTempMacro == NULL) { LexError("Out of memory allocating MACROENTRY structure.\n"); } else { gTempMacro->next = NULL; gTempMacro->prev = NULL; gTempMacro->macroName = NULL; gTempMacro->firstMacroParms = NULL; gTempMacro->lastMacroParms = NULL; gTempMacro->firstMacroLines = NULL; gTempMacro->lastMacroLines = NULL; gTempMacro->numParms = 0; gTempMacro->nLines = 0; gbTempInsideMacro = true; // flag we are currently doing a macro replace. gInvokeState = YYSTATE; if (gTempParseMacro->numParms > 0) { BEGIN(MACROPARMSTART); } else { EndMacroParms(); gbTempInsideMacro = false; // no longer waiting for macro invocation } } } } else { // fprintf( stderr, "Opcode: \"%s\" not found\n", yytext ); REJECT; } } //unsigned int offset; // //INSTRMAP *opcodeMap; // //offset = strcspn(yytext, " \t\n_"); //yyless(offset); //opcodeMap = FindInstruction(yytext); //if (opcodeMap == NULL) //{ // REJECT; //} // //yylval.opcodeInfo.opcodeMap = opcodeMap; // //return OPCODE; } ";".* { // fprintf( stderr, "%s", yytext ); char *cmt = new char[yyleng+1]; strncpy( cmt, yytext, yyleng ); cmt[0] = '#'; cmt[yyleng] = '\0'; vs10_lval.comment = cmt; return COMMENT; } "//".* { // fprintf( stderr, "%s", yytext ); char *cmt = new char[yyleng+1]; strncpy( cmt+1, yytext+1, yyleng-1 ); cmt[0] = '#'; cmt[1] = ' '; cmt[yyleng] = '\0'; vs10_lval.comment = cmt; return COMMENT; } "+"[ \t]*\n { fprintf( stderr, "COISSUE found\n" ); yyless(yyleng-1); //return COISSUE; } ^[ \t]*"+"[ \t]* { fprintf( stderr, "COISSUE found\n" ); //return COISSUE; } "/*" { gCommentStartLine = yylineno; yyless(0); BEGIN(EATCOMMENT); } "#include"[ \t]+ { BEGIN(INCLUDE); } [^ \t].*\n { /* got the include file name */ // FILE *newyyin; char *newyyin; char incFileName[1024]; unsigned long sLen; bool validFileName; if ( gIncludeStackIndex >= MAX_INCLUDE_DEPTH ) { LexError("Includes nested too deeply, aborting\n"); exit( 1 ); } // GenDebugLine(); // GenListString(); yylineno++; gLinesAssembled++; validFileName = true; // zap "" and <> if ((yytext[0] == '"') || (yytext[0] == '<')) { char *endQuote; endQuote = strchr(&yytext[1], yytext[0]); sLen = (endQuote - yytext)-1; if (endQuote == NULL) { LexError("Unable to open include file %s\n", incFileName); BEGIN(INITIAL); validFileName = false; } else { incFileName[0] ='\0'; strncat(incFileName, &yytext[1], sLen); } } else { strcpy(incFileName, yytext); } if (validFileName) { sLen = strlen(incFileName); if ((incFileName[sLen-1] == '"') || (incFileName[sLen-1] == '>')) { incFileName[sLen-1] = '\0'; } newyyin = ReadTextFile( incFileName ); // newyyin = fopen( incFileName, "r" ); if ( ! newyyin ) { LexError("Unable to open include file %s\n", incFileName); BEGIN(SAVELINE); } else { gIncludeStack[gIncludeStackIndex].fileName = gCurFileName; gIncludeStack[gIncludeStackIndex].lineNo = yylineno; // gIncludeStack[gIncludeStackIndex].fileHandle = yyin; gIncludeStack[gIncludeStackIndex].prevString = myin; gIncludeStack[gIncludeStackIndex].nextString = newyyin; gIncludeStack[gIncludeStackIndex].lastInvokeMacro = gInvokeMacro; gIncludeStack[gIncludeStackIndex].lastParseMacro = gParseMacro; gIncludeStack[gIncludeStackIndex].lastMacroLineParse = gMacroLineParse; gIncludeStack[gIncludeStackIndex].lastbInsideMacro = gbInsideMacro; gIncludeStack[gIncludeStackIndex].lastbInsideInclude = gbInsideInclude; gIncludeStack[gIncludeStackIndex].buffer = YY_CURRENT_BUFFER; gIncludeStack[gIncludeStackIndex].lastbProcessingIFDEF = gbProcessingIFDEF; gIncludeStackIndex++; gbProcessingIFDEF = false; gCurFileName = strdup(incFileName); // yyin = newyyin; myin = newyyin; // GenSwitchFileNames(gCurFileName); yylineno = 1; yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) ); gbInsideInclude = true; BEGIN(SAVELINE); } } } <> { LexError("End of file reached before end of comment started on line %d.\n", gCommentStartLine); BEGIN(INITIAL); } .*\n { char *endComment; unsigned int keepSize; strcpy(gSaveLine, yytext); endComment = strstr(yytext, "*/"); char *cmt; if (endComment != NULL) { keepSize = (endComment - yytext+2); yyless(keepSize); BEGIN(INITIAL); if ( yytext[0] == '/' && yytext[1] == '*' ) { cmt = new char[yyleng]; strncpy( cmt+3, yytext+2, yyleng-2 ); cmt[0] = '#'; cmt[1] = ' '; cmt[2] = ' '; cmt[yyleng-1] = '\0'; } else { cmt = new char[yyleng]; strncpy( cmt+1, yytext, yyleng-2 ); cmt[0] = '#'; cmt[yyleng-1] = '\0'; } vs10_lval.comment = cmt; return COMMENT; } else { // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; if ( yytext[0] == '/' && yytext[1] == '*' ) { cmt = new char[yyleng+2]; strncpy( cmt+3, yytext+2, yyleng-2 ); cmt[0] = '#'; cmt[1] = ' '; cmt[2] = ' '; cmt[yyleng+1] = '\0'; } else { cmt = new char[yyleng+2]; strncpy( cmt+1, yytext, yyleng ); cmt[0] = '#'; cmt[yyleng+1] = '\0'; } vs10_lval.comment = cmt; return COMMENT; } } <> { LexError("#define was incomplete before end of file\n"); BEGIN(INITIAL); } <> { LexError("#define was incomplete before end of file\n"); BEGIN(INITIAL); } <> { LexError("#define was incomplete before end of file\n"); BEGIN(INITIAL); } <> { LexError("#include was incomplete before end of file\n"); BEGIN(INITIAL); } <> { LexError("End of file reached before end of #define or endm was found, macro started on line %d.\n", gMacroStartLine); BEGIN(INITIAL); } <> { LexError("End of file reached before #endif found, macro started on line %d.\n", gIfDefStartLine); BEGIN(INITIAL); } \n { LexError("#define was incomplete before end of line\n"); BEGIN(SAVELINE); // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; } \n { LexError("#define was incomplete before end of line\n"); BEGIN(SAVELINE); // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; } \n { LexError("#define was incomplete before end of line\n"); BEGIN(SAVELINE); // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; } "#ifdef"[ \t]+ { if (gIfDefStackIndex >= MAX_IFDEF_DEPTH) { LexError("Out of stack space for #ifdef, aborting.\n"); exit( 1 ); } else { gIfDefStack[gIfDefStackIndex].lastbProcessingIFDEF = gbProcessingIFDEF; gIfDefStack[gIfDefStackIndex].lastbIFDEF = gbIFDEF; gIfDefStack[gIfDefStackIndex].lastbCompareDefine = gbCompareDefine; gIfDefStack[gIfDefStackIndex].lastIfDefStartLine = gIfDefStartLine; gIfDefStackIndex++; gIfDefStartLine = yylineno; gbCompareDefine = true; BEGIN(IFDEFNAME); } } "#ifndef"[ \t]+ { if (gIfDefStackIndex >= MAX_IFDEF_DEPTH) { LexError("Out of stack space for #ifdef, aborting.\n"); exit( 1 ); } else { gIfDefStack[gIfDefStackIndex].lastbProcessingIFDEF = gbProcessingIFDEF; gIfDefStack[gIfDefStackIndex].lastbIFDEF = gbIFDEF; gIfDefStack[gIfDefStackIndex].lastbCompareDefine = gbCompareDefine; gIfDefStack[gIfDefStackIndex].lastIfDefStartLine = gIfDefStartLine; gIfDefStackIndex++; gIfDefStartLine = yylineno; gbCompareDefine = false; BEGIN(IFDEFNAME); } } "#else"[ \t]*((";"|"//").*)* { if (!gbProcessingIFDEF) { LexError("Unexpected #else found at line %d, skipping.\n", yylineno); } else { gbCompareDefine = !gbCompareDefine; BEGIN(INITIAL); } } .*\n { char *defineName; unsigned int sLen; defineName = FindAlphaNum(yytext, &sLen); if (defineName == NULL) { defineName = strdup(yytext); defineName[yyleng-1] = '\0'; // kill \n LexWarning("Mangled name (%s) for #ifdef, assuming not defined.\n", defineName); free(defineName); gbIFDEF = false; } else { if (FindNMacro(defineName, sLen) != NULL) { gbIFDEF = true; } else { gbIFDEF = false; } } gbProcessingIFDEF = true; if (gbIFDEF != gbCompareDefine) { BEGIN(IFDEFBODY); } else { BEGIN(SAVELINE); } // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; } [ \t]*"#endif"[ \t]*((";"|"//").*)* { if (!gbProcessingIFDEF) { LexError("Unexpected #endif found at line %d, skipping.\n", yylineno); } else { gIfDefStackIndex--; gbProcessingIFDEF = gIfDefStack[gIfDefStackIndex].lastbProcessingIFDEF; gbIFDEF = gIfDefStack[gIfDefStackIndex].lastbIFDEF; gbCompareDefine = gIfDefStack[gIfDefStackIndex].lastbCompareDefine; gIfDefStartLine = gIfDefStack[gIfDefStackIndex].lastIfDefStartLine; } if (YYSTATE == IFDEFBODY) { strncpy(gSaveLine, yytext, MAXSAVELINE); } BEGIN(ENDMACRO); } .* { LexWarning("Garbage at end of #endif or endm will be ignored.\n"); } \n { BEGIN(SAVELINE); return '\n'; } <> { BEGIN(INITIAL); } .* { // eat line, because we are not in a TRUE #ifdef, or FALSE #ifndef strncpy(gSaveLine, yytext, MAXSAVELINE); } \n { strcat(gSaveLine, yytext); // GenDebugLine(); // GenListString(); yylineno++; gLinesAssembled++; } "#define"[ \t]+ { gbProcessingDefine = true; gMacroStartLine = yylineno; gCountParen = 0; BEGIN(MACRONAME); } .*\n { BEGIN(SAVELINE); // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; } "vs."{digits}"."{digits}[ \t]*[\n]? { // unsigned int majorVersion; // unsigned int minorVersion; // int minorOffset; // // // majorVersion = (unsigned int)(atoi(&yytext[3])); // // skip "ps." + second '.' // minorOffset = strcspn(&yytext[3], ".")+4; // minorVersion = (unsigned int)(atoi(&yytext[minorOffset])); // yylval.ival = D3DVS_VERSION(majorVersion, minorVersion); // // fprintf( stderr, "%s", yytext ); if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return VERTEX_SHADER; } {digits} { // fprintf( stderr, "%s", yytext ); vs10_lval.ival = atoi(yytext); return INTVAL; } {pt} { BEGIN(MODIFIER); //fprintf( stderr, "." ); return yytext[0]; } [w-z][w-z][w-z][w-z][ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); BEGIN(INITIAL); vs10_lval.mask[0] = tolower(yytext[0]); vs10_lval.mask[1] = tolower(yytext[1]); vs10_lval.mask[2] = tolower(yytext[2]); vs10_lval.mask[3] = tolower(yytext[3]); if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return XYZW_MODIFIER; #if 0 char temp[6]; temp[0] = '\0'; strncat(temp, yytext, 4); strlwr(temp); vs10_lval.lval = FindSwizzleValue(temp); BEGIN(INITIAL); return SWIZZLE_MODIFIER; #endif } [w-z][w-z]?[w-z]?[w-z]?[ \t]*[\n]? { // fprintf( stderr, "%s", yytext ); BEGIN(INITIAL); int validLen = strspn(yytext, "xyzw"); int i; for ( i = 0; i < validLen; i++ ) vs10_lval.mask[i] = tolower( yytext[i] ); while ( i < 4 ) { vs10_lval.mask[i] = 0; i++; } if ( yytext[yyleng-1] == '\n' ) line_incr = 1; return XYZW_MODIFIER; #if 0 //char temp[6]; char *temp = new char[6]; unsigned int registerMask; unsigned int validLen; temp[0] = '\0'; validLen = strspn(yytext, "xyzw"); strncat(temp, yytext, validLen); for ( int i = 0; i < validLen; i++ ) temp[i] = tolower( temp[i] ); registerMask = MakeRegisterMask(temp); if (registerMask != 0) { //vs10_lval.sval = temp; vs10_lval.lval = registerMask; BEGIN(INITIAL); return XYZW_MODIFIER; } else { //vs10_lval.sval = temp; vs10_lval.lval = FindSwizzleValue(temp); BEGIN(INITIAL); return SWIZZLE_MODIFIER; } #endif } . { BEGIN(INITIAL); yyless(0); } [^ \t(]+ { /* setup and save off #define/macro name */ if (FindMacro(yytext) != NULL) { LexWarning("Redefinition of #define/macro %s, ignoring.\n", yytext); if (gbProcessingDefine) { BEGIN(EATDEFINE); } else { BEGIN(EATMACRO); } } else { BEGIN(MACROPARMSTART); // %%%%% This should be setup to use memory pools gTempMacro = (MACROENTRY *)malloc(sizeof(MACROENTRY)); if (gTempMacro == NULL) { LexError("Out of memory for macro table.\n"); if (gbProcessingDefine) { BEGIN(EATDEFINE); } else { BEGIN(EATMACRO); } } else { gTempMacro->prev = gLastMacro; gTempMacro->next = NULL; gTempMacro->firstMacroParms = NULL; gTempMacro->lastMacroParms = NULL; gTempMacro->firstMacroLines = NULL; gTempMacro->lastMacroLines = NULL; gTempMacro->numParms = 0; gTempMacro->bIsDefine = gbProcessingDefine; gTempMacro->nLines = 0; if (gCurFileName != NULL) { gTempMacro->fileName = strdup(gCurFileName); } else { gTempMacro->fileName = NULL; } gTempMacro->lineNo = yylineno; /* %%%%% this should be set up in memory pools. */ gTempMacro->macroName = (char *)malloc(strlen(yytext)+1); if (gTempMacro->macroName == NULL) { LexError("Out of memory for string table.\n"); SAFEFREE(gTempMacro); if (gbProcessingDefine) { BEGIN(EATDEFINE); } else { BEGIN(EATMACRO); } } else { strcpy(gTempMacro->macroName, yytext); } } } } \n { LexError("No macro name specified, skipping macro definition.\n"); SAFEFREE(gTempMacro->fileName); SAFEFREE(gTempMacro); if (gbProcessingDefine) { BEGIN(EATDEFINE); } else { BEGIN(EATMACRO); } // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; } "(" { gCountParen++; } [ \t]+ {} . { if (gbProcessingDefine && (gCountParen == 0)) { EndMacroParms(); } else { BEGIN(MACROPARM); } yyless(0); } [ \t]* { if ((gCountParen == 0) && gbProcessingDefine) { EndMacroParms(); } } (";"|"//").* { if (gCountParen == 0) { EndMacroParms(); } } "," {} <> { EndMacroParms(); // GenDebugLine(); // GenListString(); yylineno++; gLinesAssembled++; BEGIN(INITIAL); } \n { if (gbProcessingDefine && (gCountParen > 0)) { LexError("Malformed #define, skipping.\n"); BEGIN(SAVELINE); } else { EndMacroParms(); // GenDebugLine(); // GenListString(); yylineno++; gLinesAssembled++; if (gbProcessingDefine) { gbProcessingDefine = false; BEGIN(SAVELINE); } } } [^\n,]+ { MACROTEXT *tMacro; char *macroParmEnd; unsigned int startOffset; bool bFoundEndParen; unsigned int leftParenCount; unsigned int rightParenCount; bFoundEndParen = false; // sheesh, we gotta count the parenthesis.... macroParmEnd = yytext; leftParenCount = 0; rightParenCount = 0; while (*macroParmEnd) { if (*macroParmEnd == ')') { rightParenCount++; } if (*macroParmEnd == '(') { leftParenCount++; } macroParmEnd++; } // if we found the last right parenthesis. if (rightParenCount == leftParenCount+1) { // find if we got the last parenthesis on this line macroParmEnd = strrchr(yytext, ')'); yyless((macroParmEnd - yytext)); BEGIN(MACROPARMEND); } startOffset = strspn(yytext, " \t"); tMacro = SaveMacroText(&yytext[startOffset], gTempMacro->lastMacroParms); if (tMacro == NULL) { LexError("Out of memory for string table for macro parameter(s).\n"); FreeMacroEntry(gTempMacro); BEGIN(EATMACRO); } else { // if first one wasn't set then set it if (gTempMacro->firstMacroParms == NULL) { gTempMacro->firstMacroParms = tMacro; } gTempMacro->lastMacroParms = tMacro; gTempMacro->numParms++; } } ")"[ \t]*"\\"*\n* { if (!gbProcessingDefine && !gbTempInsideMacro) { LexError("Malformed macro, skipping.\n"); BEGIN(EATMACRO); } else { gCountParen--; // we can get multiple \n's here while (yytext[yyleng-2] == '\n') { yyleng--; } yyless(yyleng); // if there isn't a \n on this line, macro starts on this line, // not next, like in a macro definition if (yytext[yyleng-1] != '\n') { EndMacroParms(); } else { if (yytext[yyleng-1] == '\n') { gTempMacro->lineNo++; } // count this line gTempMacro->nLines++; // GenDebugLine(); // GenListString(); EndMacroParms(); if (!gbInsideMacro) { yylineno++; } gLinesAssembled++; } } } ")"[ \t]*(";"|"//").*\n { if (!gbProcessingDefine && !gbTempInsideMacro) { LexError("Malformed macro, skipping.\n"); BEGIN(EATMACRO); } else { // no matter what count this line gTempMacro->nLines++; gCountParen--; EndMacroParms(); if (!gbInsideMacro) { yylineno++; } gLinesAssembled++; } } ")"[ \t]+ { if (!gbProcessingDefine && !gbTempInsideMacro) { LexError("Malformed macro, skipping.\n"); BEGIN(EATMACRO); } else { gCountParen--; if (gCountParen == 0) { // no matter what count this line gTempMacro->nLines++; EndMacroParms(); if (!gbInsideMacro) { yylineno++; } gLinesAssembled++; } else { REJECT; } } } .*"\\"[ \t]*\n { MACROTEXT *tMacro; unsigned int copyLen; char *endLine; gSaveLine[0] ='\0'; endLine = strchr(yytext, '\\'); copyLen = (endLine - yytext); if (copyLen > MAXSAVELINE) { copyLen = MAXSAVELINE; } strncat(gSaveLine, yytext, copyLen); strcat(gSaveLine, "\n"); tMacro = SaveMacroText(gSaveLine, gLastMacro->lastMacroLines); if (tMacro == NULL) { LexError("Out of memory for string table for macro parameter(s).\n"); BEGIN(EATDEFINE); } else { gLastMacro->nLines++; // if first one wasn't set then set it if (gLastMacro->firstMacroLines == NULL) { gLastMacro->firstMacroLines = tMacro; } gLastMacro->lastMacroLines = tMacro; } // GenDebugLine(); // GenListString(); yylineno++; gLinesAssembled++; } [ \t]*"endm"[ \t]*((";"|"//").*)* { strncpy(gSaveLine, yytext, MAXSAVELINE); if (gbProcessingDefine) { LexError("Malformed #define, skipping.\n"); } BEGIN(ENDMACRO); } [^\n]* { MACROTEXT *tMacro; // check if processing #define and only one line, if not then append \n if (!gbProcessingDefine || (gLastMacro->nLines >= 1)) { gSaveLine[0] = '\0'; strncat(gSaveLine, yytext, MAXSAVELINE); strcat(gSaveLine, "\n"); tMacro = SaveMacroText(gSaveLine, gLastMacro->lastMacroLines); gLastMacro->nLines++; } else if (gLastMacro->numParms > 0) // check if parameters were there { // if so, we need the '\n' appended gMacroLine[0] = '\0'; strncat(gMacroLine, yytext, MAXSAVELINE); strcat(gMacroLine, "\n"); tMacro = SaveMacroText(gMacroLine, gLastMacro->lastMacroLines); gLastMacro->nLines++; } else // straight no newline macro replace { tMacro = SaveMacroText(yytext, gLastMacro->lastMacroLines); } if (tMacro == NULL) { LexError("Out of memory for string table for macro parameter(s).\n"); BEGIN(EATMACRO); } else { // if first one wasn't set then set it if (gLastMacro->firstMacroLines == NULL) { gLastMacro->firstMacroLines = tMacro; } gLastMacro->lastMacroLines = tMacro; } } \n { MACROTEXT *tMacro; // GenDebugLine(); // GenListString(); yylineno++; gLinesAssembled++; if (gbProcessingDefine) { gbProcessingDefine = false; BEGIN(SAVELINE); } else { // this means \n by itself inside macro body if (((yylineno-1) - gLastMacro->lineNo) != gLastMacro->nLines) { strcpy(gMacroLine, "\n"); tMacro = SaveMacroText(gMacroLine, gLastMacro->lastMacroLines); gLastMacro->nLines++; if (tMacro == NULL) { LexError("Out of memory for string table for macro parameter(s).\n"); BEGIN(EATMACRO); } else { // if first one wasn't set then set it if (gLastMacro->firstMacroLines == NULL) { gLastMacro->firstMacroLines = tMacro; } gLastMacro->lastMacroLines = tMacro; } } } } [ \t]*"endm"[ \t]*\n { BEGIN(SAVELINE); // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; } .*\n { strncpy(gSaveLine, yytext, MAXSAVELINE); // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; } .*"\\"\n { strncpy(gSaveLine, yytext, MAXSAVELINE); // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; } .*\n { strncpy(gSaveLine, yytext, MAXSAVELINE); // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; BEGIN(SAVELINE); } {alpha}{alphadigs}* { gTempParseMacro = FindMacro(yytext); if (gTempParseMacro != NULL) { if (gIncludeStackIndex >= MAX_INCLUDE_DEPTH ) { LexError("macros nested too deeply"); exit( 1 ); } if (gTempParseMacro->firstMacroLines != NULL) { gTempMacro = (MACROENTRY *)malloc(sizeof(MACROENTRY)); if (gTempMacro == NULL) { LexError("Out of memory allocating MACROENTRY structure.\n"); } else { gTempMacro->next = NULL; gTempMacro->prev = NULL; gTempMacro->macroName = NULL; gTempMacro->firstMacroParms = NULL; gTempMacro->lastMacroParms = NULL; gTempMacro->firstMacroLines = NULL; gTempMacro->lastMacroLines = NULL; gTempMacro->numParms = 0; gTempMacro->nLines = 0; gbTempInsideMacro = true; // flag we are currently doing a macro replace. gInvokeState = YYSTATE; if (gTempParseMacro->numParms > 0) { BEGIN(MACROPARMSTART); } else { EndMacroParms(); gbTempInsideMacro = false; // no longer waiting for macro invocation } } } } else { BEGIN(INITIAL); REJECT; } } [,\[\]\-\+\(\)\*\<\>\/\%_\.] { // fprintf( stderr, "%c ", yytext[0] ); return yytext[0]; } [ \t]+ {} \n { LexError("Didn't find label string for #define.\n"); BEGIN(SAVELINE); // return '\n'; } "\n" { //fprintf(stderr, "\n"); // line_incr = 1; line_incr++; BEGIN(SAVELINE); return '\n'; } {alphadigs}+ { BEGIN(INITIAL); // fprintf( stderr, "%s", yytext ); if (yyleng == 1) return yytext[0]; else LexError("Unrecognized Token: %s\n", yytext); return UNKNOWN_STRING; } [\001-\040] { // vs10_lval.ival = yytext[0]; LexError("Illegal character: %d decimal.\n", yytext[0]); return(ILLEGAL); } [\001-\040] { // vs10_lval.ival = yytext[0]; LexError("Illegal character: %d decimal.\n", yytext[0]); return(ILLEGAL); } . { return yytext[0]; } . { BEGIN(EATSTRING); yyless(0); } <> { bool wasInMacro; bool oneLiner; char *macroText; wasInMacro = gbInsideMacro; oneLiner = false; // if we are inside the macro then do next line until their are no more if (gbInsideMacro) { oneLiner = (gParseMacro->nLines == 0); // free the temporary parameter replaced line we were working on. // get next line in macro text, if any gMacroLineParse = gMacroLineParse->next; // more lines to parse? if (gMacroLineParse != NULL) { macroText = gMacroLine; // if no replacement text, just use source line if (gParseMacro->firstMacroParms == NULL) { macroText = gMacroLineParse->macroText; } else { // replace the macro parameters ReplaceMacroParms(gMacroLineParse->macroText, gMacroLine, gParseMacro, gInvokeMacro); } // if (gExpandMacros) // { // strcpy(gSaveLine, macroText); // } BEGIN(INITIAL); // and lex it. yy_scan_string(macroText); } else { // no more lines in this macro, so free the working macro SAFEFREE(gInvokeMacro); // shut off flag for inside a macro replacement state. gbInsideMacro = false; } } if (gbProcessingIFDEF && !wasInMacro) { LexError("End of file reached before #endif found, macro started on line %d.\n", gIfDefStartLine); } if (!gbInsideMacro) { if ( gIncludeStackIndex == 0 ) { if (!gbProcessingBuiltIn) CleanUp(); return 0; // return TOKEN_EOF; } else { yy_delete_buffer( YY_CURRENT_BUFFER ); SAFEFREE(gCurFileName); // SAFEDELETE(myin); // SAFECLOSE(yyin); } gIncludeStackIndex--; SAFEDELETEARRAY( gIncludeStack[gIncludeStackIndex].nextString ); yy_switch_to_buffer(gIncludeStack[gIncludeStackIndex].buffer ); gCurFileName = gIncludeStack[gIncludeStackIndex].fileName; // yyin = gIncludeStack[gIncludeStackIndex].fileHandle; myin = gIncludeStack[gIncludeStackIndex].prevString; yylineno = gIncludeStack[gIncludeStackIndex].lineNo; gInvokeMacro = gIncludeStack[gIncludeStackIndex].lastInvokeMacro; gParseMacro = gIncludeStack[gIncludeStackIndex].lastParseMacro; gMacroLineParse = gIncludeStack[gIncludeStackIndex].lastMacroLineParse; gbInsideInclude = gIncludeStack[gIncludeStackIndex].lastbInsideInclude; gbInsideMacro = gIncludeStack[gIncludeStackIndex].lastbInsideMacro; gbProcessingIFDEF = gIncludeStack[gIncludeStackIndex].lastbProcessingIFDEF; if (!gbInsideMacro && !oneLiner) { // GenSwitchFileNames(gCurFileName); BEGIN(SAVELINE); } else { BEGIN(INITIAL); } // gSaveLine was last line saved, before macro invocation if (wasInMacro && !gbInsideMacro && !oneLiner) { // GenDebugLine(); // GenListString(); gLinesAssembled++; yylineno++; } } } %% //===================================================================== // Function: FindNMacro // Description: Look through macros and see if it had been predefined // Parameters: findName = name to lookup // sLen = # characters valid in source (findName) // Returns: MACROENTRY * = pointer to macro entry if found //===================================================================== MACROENTRY *FindNMacro(char *findName, unsigned int sLen) { MACROENTRY *curEntry; curEntry = gLastMacro; while (curEntry != NULL) { if (strlen(curEntry->macroName) == sLen) { if (!strncmp(curEntry->macroName, findName, sLen)) { break; } } curEntry = curEntry->prev; } return curEntry; } //===================================================================== // Function: FindMacro // Description: Look through macros and see if it had been predefined // Parameters: findName = name to lookup // Returns: MACROENTRY * = pointer to macro entry if found //===================================================================== MACROENTRY *FindMacro(char *findName) { MACROENTRY *curEntry; curEntry = gLastMacro; while (curEntry != NULL) { if (!strcmp(curEntry->macroName, findName)) { break; } curEntry = curEntry->prev; } return curEntry; } //===================================================================== // Function: CleanUp // Description: Clean up the #define strings // Parameters: . // Returns: . //===================================================================== void CleanUp() { void *tPtr; // free up the macros that were alloced while (gLastMacro != NULL) { FreeMacroEntry(gLastMacro); tPtr = gLastMacro; gLastMacro = gLastMacro->prev; SAFEFREE(tPtr); } } //===================================================================== // Function: FreeMacroEntry // Description: Frees up the macro entry data, (parms, lines of text) // Parameters: macEntry = pointer to the MACROENTRY structure // Returns: . //===================================================================== void FreeMacroEntry(MACROENTRY *macEntry) { MACROTEXT *tText; MACROTEXT *tNext; SAFEFREE(macEntry->macroName); SAFEFREE(macEntry->fileName); // free the macro lines that were alloced tText = macEntry->lastMacroLines; while (tText != NULL) { tNext = tText->prev; SAFEFREE(tText); tText = tNext; } // free the text of the macro parms that were alloced tText = macEntry->lastMacroParms; while (tText != NULL) { tNext = tText->prev; SAFEFREE(tText); tText = tNext; } } //===================================================================== // Function: CheckMacroFunctions // Description: Find if this text is a builtin macro function // Parameters: lookString = non-null terminated string of possible // and if found set global macro function call // Returns: . //===================================================================== void CheckMacroFunctions(char *lookString, unsigned int *recognizedLen, char **invString) { unsigned int i; unsigned int sLen; for (i=0; i< NUM_MACRO_FUNCTIONS; i++) { sLen = strlen(gMacroFunctions[i].name); if (!strncmp(gMacroFunctions[i].name, lookString, sLen)) { gMacroCallFunction = gMacroFunctions[i].function; *recognizedLen = sLen; *invString = NULL; return; } } } //===================================================================== // Function: FindAlphaNum // Description: Find a whole alpha numeric string, ie consists of // [A-Za-z0-9_] only // Parameters: srcStr = source string to search through. // sLen = unsinged int pointer to length of string found // Returns: pointer to found start of string. // NULL if none. //===================================================================== char *FindAlphaNum(char *srcStr, unsigned int *sLen) { char curChar; char *foundStr; while (*srcStr != '\0') { curChar = toupper(*srcStr); if ((curChar >= 'A') && (curChar <= 'Z')) break; if ((curChar >= '0') && (curChar <='9')) break; if (curChar == '_') break; srcStr++; } if (*srcStr == '\0') { return NULL; } foundStr = srcStr; *sLen = 0; // now search for end of string of [A-Za-z0-9_] while (*srcStr != '\0') { curChar = toupper(*srcStr); if ((curChar < 'A') || (curChar > 'Z')) { if ((curChar < '0') || (curChar > '9')) { if (curChar != '_') break; } } (*sLen)++; srcStr++; } return foundStr; } //===================================================================== // Function: FindDefineParm // Description: Find if the MACROENTRY->macroText linked list contains // replaceable parameters. // Parameters: srcParms = pointer to MACROENTRY structure for source // parameters // invParms = MACROENTRY pointer to invocation parameters // lookString = non-null terminated string of possible // replaceable string // recognizedLen = replacement string matched length // invString = invocation string to replace with // Returns: pointer to first character found in lookstring //===================================================================== char *FindDefineParm(MACROENTRY *srcParms, MACROENTRY *invParms, char *lookString, unsigned int *recognizedLen, char **invString) { MACROTEXT *srcText; MACROTEXT *invText; char *checkStr; unsigned int checkLen; unsigned int sLen; checkStr = lookString; *invString = NULL; // first search for first [A-Za-z0-9_] only string checkStr = FindAlphaNum(lookString, &checkLen); while (checkStr != NULL) { // check all the #define parameters for match srcText = srcParms->firstMacroParms; invText = invParms->firstMacroParms; while (srcText) { sLen = strlen(srcText->macroText); // lengths should match if (sLen == checkLen) { if (!strncmp(checkStr, srcText->macroText, checkLen)) { // it matched so return replacement text *invString = invText->macroText; // and length that we reconized *recognizedLen = checkLen; return checkStr; } } srcText = srcText->next; invText = invText->next; } // not found yet, so go to next string. checkStr = FindAlphaNum(checkStr+checkLen, &checkLen); } return NULL; } //===================================================================== // Function: FindReplaceParm // Description: Find if the MACROENTRY->macroText linked list contains // a replaceable parameters. // Parameters: srcParms = pointer to MACROENTRY structure for source // parameters // invParms = MACROENTRY pointer to invocation parameters // lookString = non-null terminated string of possible // replaceable string // recognizedLen = replacement string matched length // invString = invocation string to replace with // Returns: . //===================================================================== void FindReplaceParm(MACROENTRY *srcParms, MACROENTRY *invParms, char *lookString, unsigned int *recognizedLen, char **invString) { unsigned int sLen; MACROTEXT *srcText; MACROTEXT *invText; *recognizedLen = 0; *invString = NULL; srcText = srcParms->firstMacroParms; invText = invParms->firstMacroParms; if (srcText != NULL) { // go until srcText # strings ends while (srcText != NULL) { sLen = strlen(srcText->macroText); if (!strncmp(srcText->macroText, lookString, sLen)) { // found it so return src, replacement string *recognizedLen = strlen(srcText->macroText); *invString = invText->macroText; // call function macro if it was invoked prior. if (gMacroCallFunction != NULL) { gMacroCallFunction(lookString, recognizedLen, invString); gMacroCallFunction = NULL; } return; } srcText = srcText->next; invText = invText->next; } } // ok, it wasn't found, look through builtin macro functions CheckMacroFunctions(lookString, recognizedLen, invString); } //===================================================================== // Function: ReplaceMacroParms // Description: Replace macro parameters when macro was defined, with // those specified on the macro invocation line // Parameters: srcLine = source line to replace src macro parms with // destLine = destination line save to. // invocation macro parameters. // parseMacro = currently parsing macro entry // invParms = invocation macro entry // Returns: . //===================================================================== void ReplaceMacroParms(char *srcLine, char *destLine, MACROENTRY *srcParms, MACROENTRY *invParms) { char *findReplace; char *invString; unsigned int sLen; unsigned int dLen; unsigned int copyLen; unsigned int subLen; unsigned int recognizedLen; destLine[0]= '\0'; sLen = strlen(srcLine); dLen = 0; while (sLen > 0) { // strtok might work better except it modifies the string, so // kind of do my own.... if (!srcParms->bIsDefine) { findReplace = strchr(srcLine, '%'); if (findReplace != NULL) { // bypass % sign in findReplacement findReplace++; // figure out length of source before % copyLen = (findReplace - srcLine)-1; // check if there is a replacement string FindReplaceParm(srcParms, invParms, findReplace, &recognizedLen, &invString); } else { strcat(destLine, srcLine); return; } } else { findReplace = FindDefineParm(srcParms, invParms, srcLine, &recognizedLen, &invString); if (findReplace != NULL) { // figure out length of source before % copyLen = findReplace - srcLine; } else { strcat(destLine, srcLine); return; } } if (invString != NULL) { // figure out how much we are going to substitute subLen = strlen(invString); } else { subLen = 0; } if ((dLen + copyLen + subLen) > MAXSAVELINE) { LexError("Macro string overrun.\n"); CleanUp(); exit(ERROR_MACRO_OVERRUN); } if (copyLen > 0) { strncat(destLine, srcLine, copyLen); dLen += copyLen; } srcLine += copyLen; sLen -= copyLen; // in macro so skip % part of variable if (!srcParms->bIsDefine) { // skip %, also srcLine++; sLen--; } if (invString != NULL) { strcat(destLine, invString); dLen += strlen(invString); } srcLine += recognizedLen; sLen -= recognizedLen; } } //===================================================================== // Function: SaveMacroText // Description: Adds a string to a linked list of MACROTEXT structures // Parameters: srcText = pointer to source text to save // lastMacroText = last allocated, or NULL // Returns: newly allocated MACROTEXT structure, or NULL //===================================================================== MACROTEXT *SaveMacroText(char *srcText, MACROTEXT *lastMacroText) { MACROTEXT *curMacroText; curMacroText = (MACROTEXT *)malloc(sizeof(MACROTEXT)); if (curMacroText == NULL) { return NULL; } else { // no next entry but set up previous with previously alloced macro parameter curMacroText->next = NULL; curMacroText->prev = lastMacroText; // if the macroParm pointer is null then we are the first allocated // so if not set the last one allocate next pointer to newly allocated structure if (lastMacroText != NULL) { lastMacroText->next = curMacroText; } /* %%%%% this should be set up in memory pools. */ curMacroText->macroText = strdup(srcText); if (curMacroText->macroText == NULL) { SAFEFREE(curMacroText); return NULL; } } return curMacroText; } //===================================================================== // Function: ParseBuiltInMacroParms // Description: parse parameters of string and fill in MACROENTRY // structure. // Parameters: parsedMacro = pointer to MACROENTRY structure that gets // filled in with parameter pointers and count // parmStr = string to parse parameters from // Returns: false if error //===================================================================== bool ParseBuiltInMacroParms(MACROENTRY *parsedMacro, char *parmStr) { char *endStr; char *foundParm; MACROTEXT *prevMT; MACROTEXT *curMT; parsedMacro->numParms = 0; parsedMacro->firstMacroParms = NULL; foundParm = strdup(parmStr); if (foundParm == NULL) { LexError("Out of memory parsing bultin macro parameters.\n"); return false; } // assume a ')' is on the end. endStr = strrchr(foundParm, ')'); if (endStr == NULL) { LexWarning("Ending parenthesis not found for macro %s.\n", parsedMacro->macroName); endStr = foundParm + strlen(foundParm); } prevMT = NULL; // strip out and seperate parameters while (foundParm < endStr) { // allocate a macro text structure curMT = (MACROTEXT *)malloc(sizeof(MACROTEXT)); if (curMT == NULL) { free(parmStr); LexError("Out of memory parsing bultin macro parameters.\n"); return false; } curMT->next = NULL; curMT->prev = prevMT; parsedMacro->numParms++; if (prevMT != NULL) { prevMT->next = curMT; } else { parsedMacro->firstMacroParms = curMT; } curMT->macroText = foundParm; // search for next parameters, delimited by comma foundParm = strchr(foundParm, ','); if (foundParm == NULL) { foundParm = endStr; *foundParm = '\0'; } else { // skip comma *foundParm = '\0'; foundParm++; } prevMT = curMT; } return true; } //===================================================================== // Function: MacroMathFunction // Description: Comes here after macro replacement is done to perform // some mathematic function on parameter (macro replacement // string (ie, register)) // Parameters: invMacro = macroentry pointer containing macro information // recognizedLen = # characters recoginized so far // invStr = invoked replacement string so far // mathStr = "-", "+", etc for mathematic function // Returns: new recognizedLen, invStr, with incremented # //===================================================================== void MacroMathFunction(MACROENTRY *invMacro, unsigned int *recognizedLen, char **invStr, char *mathStr) { char *numStartStr; unsigned int sLen; char numberStr[256]; unsigned int number; char *operand; // verify enough paramters to complete operation if (invMacro->numParms != 2) { LexError("Two parameters are required for %s macro\n", invMacro->macroName); return; } // get second macro parm, which is add by amount. operand = invMacro->firstMacroParms->next->macroText; // first find inner most bracket if any numStartStr = strrchr(*invStr, ']'); if (numStartStr == NULL) { numStartStr = strrchr(*invStr, ')'); } if (numStartStr != NULL) { if ((strlen(*invStr)+strlen(operand)+1) > MAXREPLACESTRING) { LexError("Out of Temporary string replacement memory inside builtin macro %s\n", invMacro->macroName); } else { sLen = (numStartStr - *invStr); gReplaceText[0] = '\0'; strncat(gReplaceText, *invStr, sLen); strcat(gReplaceText, mathStr); strcat(gReplaceText, operand); strcat(gReplaceText, numStartStr); *invStr = gReplaceText; } } else { numStartStr = strpbrk(*invStr, "0123456789"); if (numStartStr != NULL) { // put up to number we found sLen = numStartStr - *invStr; if (sLen > MAXREPLACESTRING) goto ErrOut; gReplaceText[0] = '\0'; strncat(gReplaceText, *invStr, sLen); switch (mathStr[0]) { case '-': number = atoi(numStartStr)-atoi(operand); break; case '+': number = atoi(numStartStr)+atoi(operand); break; } sprintf(numberStr, "%d", number); if ((strlen(gReplaceText) + strlen(numberStr)) > MAXREPLACESTRING) goto ErrOut; strcat(gReplaceText, numberStr); while ((*numStartStr != '\0') && (*numStartStr >= '0' && *numStartStr <= '9')) numStartStr++; if ((strlen(gReplaceText) + strlen(numStartStr)) > MAXREPLACESTRING) goto ErrOut; strcat(gReplaceText, numStartStr); *invStr = gReplaceText; } else { if ((strlen(*invStr)+strlen(operand)+1) > MAXREPLACESTRING) { LexError("Out of Temporary string replacement memory inside builtin macro %s\n", invMacro->macroName); } else { sprintf(gReplaceText, "%s%s%s", *invStr, mathStr, operand); *invStr = gReplaceText; } } } return; ErrOut: LexError("Out of Temporary string replacement memory inside builtin macro %s\n", invMacro->macroName); // skip ')' (*recognizedLen)++; } //===================================================================== // Function: MacroIncFunction // Description: Comes here after macro replacement is done to increment // macro replacement string (ie, register) // Parameters: lookStr = string after '(', so we can get parameters // recognizedLen = # characters recoginized so far // invStr = invoked replacement string so far // Returns: new recognizedLen, invStr, with incremented # //===================================================================== void MacroIncFunction(char *lookStr, unsigned int *recognizedLen, char **invStr) { MACROENTRY tMEntry; MACROTEXT parm1; MACROTEXT parm2; tMEntry.macroName = "%inc()"; tMEntry.numParms = 2; tMEntry.firstMacroParms = &parm1; parm1.prev = NULL; parm1.next = &parm2; parm1.macroText = *invStr; parm2.prev = &parm1; parm2.next = NULL; parm2.macroText = "1"; MacroMathFunction(&tMEntry, recognizedLen, invStr, "+"); // skip ')' (*recognizedLen)++; } //===================================================================== // Function: MacroDecFunction // Description: Comes here after macro replacement is done to decrement // macro replacement string (ie, register) // Parameters: lookStr = string after '(', so we can get parameters // recognizedLen = # characters recoginized so far // invStr = invoked replacement string so far // Returns: new recognizedLen, invStr, with decremented # //===================================================================== void MacroDecFunction(char *lookStr, unsigned int *recognizedLen, char **invStr) { MACROENTRY tMEntry; MACROTEXT parm1; MACROTEXT parm2; tMEntry.macroName = "%dec()"; tMEntry.numParms = 2; tMEntry.firstMacroParms = &parm1; parm1.prev = NULL; parm1.next = &parm2; parm1.macroText = *invStr; parm2.prev = &parm1; parm2.next = NULL; parm2.macroText = "1"; MacroMathFunction(&tMEntry, recognizedLen, invStr, "-"); // skip ')' (*recognizedLen)++; } //===================================================================== // Function: MacroAddFunction // Description: Comes here after macro replacement is done to add // macro replacement string (ie, register) // Parameters: lookStr = string after '(', so we can get parameters // recognizedLen = # characters recoginized so far // invStr = invoked replacement string so far // Returns: new recognizedLen, invStr, with incremented # //===================================================================== void MacroAddFunction(char *lookStr, unsigned int *recognizedLen, char **invStr) { MACROENTRY tMEntry; MACROTEXT *curMT; MACROTEXT *nextMT; unsigned int i; tMEntry.macroName = "%add()"; if (strlen(lookStr) > MAXREPLACESTRING) { LexError("Out of Temporary string replacement memory inside builtin macro %add()\n"); return; } if (ParseBuiltInMacroParms(&tMEntry, lookStr)) { MacroMathFunction(&tMEntry, recognizedLen, invStr, "+"); // skip ',' strlen(parm2)+ ')' (*recognizedLen) += strlen(tMEntry.firstMacroParms->next->macroText)+2; } curMT = tMEntry.firstMacroParms; // in this case only one string was allocated free(curMT->macroText); for (i=0; inext; free(curMT); curMT = nextMT; } } //===================================================================== // Function: MacroSubFunction // Description: Comes here after macro replacement is done to subtract // macro replacement string (ie, register) // Parameters: invParms, parameters that macro was invoked with // recognizedLen = # characters recoginized so far // invStr = invoked replacement string so far // Returns: new recognizedLen, invStr, with incremented # //===================================================================== void MacroSubFunction(char *lookStr, unsigned int *recognizedLen, char **invStr) { MACROENTRY tMEntry; MACROTEXT *curMT; MACROTEXT *nextMT; unsigned int i; tMEntry.macroName = "%sub()"; if (ParseBuiltInMacroParms(&tMEntry, lookStr)) { MacroMathFunction(&tMEntry, recognizedLen, invStr, "-"); // skip ',' strlen(parm2)+ ')' (*recognizedLen) += strlen(tMEntry.firstMacroParms->next->macroText)+2; } curMT = tMEntry.firstMacroParms; // in this case only one string was allocated free(curMT->macroText); for (i=0; inext; free(curMT); curMT = nextMT; } } //===================================================================== // Function: EndMacroParms // Description: Does update and cleanup one end of macro parameters // is reached // Parameters: . // Returns: . //===================================================================== void EndMacroParms() { char *curFileName; char *macroFileName; char tempStr[1024]; char *macroText; if (gbTempInsideMacro) { if (gTempParseMacro->numParms != gTempMacro->numParms) { LexError("Macro invocation number of parameters do not match macro definition, skipping\n"); BEGIN(INITIAL); SAFEFREE(gTempMacro); } else { // we got all the parameters for the MACRO invocation, so start inside // the macro now, by saving off current state on stack gIncludeStack[gIncludeStackIndex].lineNo = yylineno; gIncludeStack[gIncludeStackIndex].fileName = gCurFileName; // gIncludeStack[gIncludeStackIndex].fileHandle = yyin; //fprintf( stderr, "Chris fix this code with myin stuff\n" ); gIncludeStack[gIncludeStackIndex].prevString = myin; gIncludeStack[gIncludeStackIndex].nextString = NULL; gIncludeStack[gIncludeStackIndex].lastInvokeMacro = gInvokeMacro; gIncludeStack[gIncludeStackIndex].lastParseMacro = gParseMacro; gIncludeStack[gIncludeStackIndex].lastMacroLineParse = gMacroLineParse; gIncludeStack[gIncludeStackIndex].lastbInsideMacro = gbInsideMacro; gIncludeStack[gIncludeStackIndex].lastbInsideInclude = gbInsideInclude; gIncludeStack[gIncludeStackIndex].buffer = YY_CURRENT_BUFFER; gIncludeStack[gIncludeStackIndex].lastbProcessingIFDEF = gbProcessingIFDEF; gIncludeStackIndex++; gParseMacro = gTempParseMacro; gInvokeMacro = gTempMacro; gbInsideMacro = gbTempInsideMacro; gbTempInsideMacro = false; // yyin = NULL; myin = NULL; curFileName = gCurFileName; if (curFileName == NULL) curFileName = ""; macroFileName = gParseMacro->fileName; if (macroFileName == NULL) macroFileName = ""; sprintf(tempStr, "%s(%d) : References ->\n%s", curFileName, yylineno, macroFileName); gCurFileName = strdup(tempStr); gMacroLineParse = gParseMacro->firstMacroLines; macroText = gMacroLine; // if no replacement text, just use source line if (gParseMacro->firstMacroParms == NULL) { macroText = gMacroLineParse->macroText; } else { // replace the macro parameters ReplaceMacroParms(gMacroLineParse->macroText, gMacroLine, gParseMacro, gInvokeMacro); } yylineno = gParseMacro->lineNo; if (gParseMacro->nLines >= 1) { strcpy(gSaveLine, macroText); } // if (gExpandMacros && (gParseMacro->nLines >= 1)) // { // // in case there is anything there dump it out // GenDebugLine(); // GenListString(); // if (gInvokeMacro->nLines >= 1) // GenSwitchFileNames(macroFileName); // } BEGIN(gInvokeState); yy_scan_string(macroText); gInvokeState = INITIAL; } } else { if (gLastMacro != NULL) { gLastMacro->next = gTempMacro; } gLastMacro = gTempMacro; BEGIN(MACROBODY); } } //===================================================================== // Function: FindSwizzleValue // Description: see if valid swizzle value and return the bits // Parameters: swizzleTex = pointer to characters to analyze // Returns: unsigned int = bits for swizzle values, or 0 for error //===================================================================== unsigned int FindSwizzleValue(char *swizzleText) { unsigned int swizzleBits; unsigned int sLen; unsigned int i; unsigned int lastMask; sLen = strlen(swizzleText); swizzleBits = 0; lastMask = 0; for (i=0; i