WORD CMacroList::ImportMacro(WORD wMacroId, CMacroList* pSrcList) { /* Find the macro in the source list. */ CMacro* pSrcMacro = pSrcList->FindMacro(wMacroId); ASSERT(pSrcMacro != NULL); // It must be there. if (pSrcMacro != NULL) { /* First, see if this macro exists in our list. */ CMacro* pOurMacro = FindMacro(pSrcMacro->Name()); if (pOurMacro == NULL) { /* We need to create it. */ pOurMacro = AddMacro(pSrcMacro->Name(), ""); if (pOurMacro == NULL) { return 0; } else { /* Copy over the data. Don't change the new id. */ pOurMacro->AssignData(pSrcMacro); return pOurMacro->Id(); } } else { /* It exists. Just reference it. */ return pOurMacro->Id(); } } /* Macro is missing from the source. */ return 0; }
CMacro* CMacroList::AddMacroAt(int nIndex, LPCSTR pName, LPCSTR pValue) { CMacro* pMacro = FindMacro(pName); if (pMacro == NULL) { // Safe 'new'... TRY pMacro = new CMacro; END_TRY WORD wID; if ((wID = UniqueID()) == 0) { /* Should never happen, but who knows? */ return NULL; } if (pMacro != NULL) { pMacro->Id(wID); pMacro->Name(pName); pMacro->Value(pValue); InsertAt(nIndex, pMacro); } } return pMacro; // And return it in case anybody cares. }
/* * ParseDirective * Note: macro directives are handled before recording */ void ParseDirective(const char *cline) { char *line = strdup(strltrim(cline) + 1); // skip '.' and allow strtok //printf("'%s'\n", file->line); //printf("'%s'\n", line); bool valid_directive = false; //bool done_directive = true; //printf("Line: [%s]\n", cline); /* * macro ending directives */ if (DIRECTIVE("endm", PARSE_MACRO_DIRECTIVES)) { current_macro = 0; parse_directives = PARSE_ALL_DIRECTIVES; } else if (DIRECTIVE("endr", PARSE_REPT_DIRECTIVES)) { current_macro = 0; parse_directives = PARSE_ALL_DIRECTIVES; while (repeat-- > 0) MacroExecute("_rept"); } /* * record to macro */ if (current_macro) { MacroLine(cline); // record full line goto exit; // only process macro ending directives } /* * macro starting directives */ if (DIRECTIVE("macro", PARSE_MACRO_DIRECTIVES) || DIRECTIVE("macroicase", PARSE_MACRO_DIRECTIVES)) { char *name = strtok((char *)strskipspace(line), delim_chars); current_macro = FindMacro(name); if (pass != PASS_ASM) { if (current_macro) { eprintf("Macro name already defined.\n"); eexit(); } current_macro = NewMacro(name, DIRECTIVE("macroicase", PARSE_MACRO_DIRECTIVES)); EEKS{printf("new macro at %p\n", current_macro);} char *paramname; while ((paramname = strtok(0, delim_chars))) { if (isspace2(paramname[0])) paramname = strskipspace(paramname); if (strchr(endline_chars, *paramname)) break; current_macro->AddParameter(paramname); } } parse_directives = PARSE_MACRO_DIRECTIVES; }
void queryMacroList::AddOrUpdateMacro(const wxString &key, const wxString &name, const wxString &query) { queryMacroItem *item = FindMacro(key); if (item != NULL) { item->Update(name, query); } else { AddNewMacro(key, name, query); } }
WORD CMacroList::UniqueID(void) { // Brute force method. Start at 1 and look... // Look for an open ID. If we hit the max, fail... WORD wID = 1; while (wID < MACRO_Max) { if (FindMacro(wID) == NULL) { break; } wID++; } // Return what we found. return (wID == MACRO_Max) ? 0 : wID; }
static void MacroReplacement (StrBuf* Source, StrBuf* Target) /* Perform macro replacement. */ { ident Ident; Macro* M; /* Remember the current input and switch to Source */ StrBuf* OldSource = InitLine (Source); /* Loop substituting macros */ while (CurC != '\0') { /* If we have an identifier, check if it's a macro */ if (IsSym (Ident)) { /* Check if it's a macro */ if ((M = FindMacro (Ident)) != 0 && !M->Expanding) { /* It's a macro, expand it */ ExpandMacro (Target, M); } else { /* An identifier, keep it */ SB_AppendStr (Target, Ident); } } else if (IsQuote (CurC)) { CopyQuotedString (Target); } else if (IsSpace (CurC)) { if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, CurC); } NextChar (); } else { SB_AppendChar (Target, CurC); NextChar (); } } /* Switch back the input */ InitLine (OldSource); }
static void DefineMacro (void) /* Handle a macro definition. */ { ident Ident; Macro* M; Macro* Existing; int C89; /* Read the macro name */ SkipWhitespace (0); if (!MacName (Ident)) { return; } /* Remember if we're in C89 mode */ C89 = (IS_Get (&Standard) == STD_C89); /* Get an existing macro definition with this name */ Existing = FindMacro (Ident); /* Create a new macro definition */ M = NewMacro (Ident); /* Check if this is a function like macro */ if (CurC == '(') { /* Skip the left paren */ NextChar (); /* Set the marker that this is a function like macro */ M->ArgCount = 0; /* Read the formal parameter list */ while (1) { /* Skip white space and check for end of parameter list */ SkipWhitespace (0); if (CurC == ')') { break; } /* The next token must be either an identifier, or - if not in * C89 mode - the ellipsis. */ if (!C89 && CurC == '.') { /* Ellipsis */ NextChar (); if (CurC != '.' || NextC != '.') { PPError ("`...' expected"); ClearLine (); return; } NextChar (); NextChar (); /* Remember that the macro is variadic and use __VA_ARGS__ as * the argument name. */ AddMacroArg (M, "__VA_ARGS__"); M->Variadic = 1; } else { /* Must be macro argument name */ if (MacName (Ident) == 0) { return; } /* __VA_ARGS__ is only allowed in C89 mode */ if (!C89 && strcmp (Ident, "__VA_ARGS__") == 0) { PPWarning ("`__VA_ARGS__' can only appear in the expansion " "of a C99 variadic macro"); } /* Add the macro argument */ AddMacroArg (M, Ident); } /* If we had an ellipsis, or the next char is not a comma, we've * reached the end of the macro argument list. */ SkipWhitespace (0); if (M->Variadic || CurC != ',') { break; } NextChar (); } /* Check for a right paren and eat it if we find one */ if (CurC != ')') { PPError ("`)' expected"); ClearLine (); return; } NextChar (); } /* Skip whitespace before the macro replacement */ SkipWhitespace (0); /* Insert the macro into the macro table and allocate the ActualArgs array */ InsertMacro (M); /* Remove whitespace and comments from the line, store the preprocessed * line into the macro replacement buffer. */ Pass1 (Line, &M->Replacement); /* Remove whitespace from the end of the line */ while (IsSpace (SB_LookAtLast (&M->Replacement))) { SB_Drop (&M->Replacement, 1); } #if 0 printf ("%s: <%.*s>\n", M->Name, SB_GetLen (&M->Replacement), SB_GetConstBuf (&M->Replacement)); #endif /* If we have an existing macro, check if the redefinition is identical. * Print a diagnostic if not. */ if (Existing && MacroCmp (M, Existing) != 0) { PPError ("Macro redefinition is not identical"); } }
static long DoStructInternal (long Offs, unsigned Type) /* Handle the .STRUCT command */ { long Size = 0; /* Outside of other structs, we need a name. Inside another struct or ** union, the struct may be anonymous, in which case no new lexical level ** is started. */ int Anon = (CurTok.Tok != TOK_IDENT); if (!Anon) { /* Enter a new scope, then skip the name */ SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0); NextTok (); /* Start at zero offset in the new scope */ Offs = 0; } /* Test for end of line */ ConsumeSep (); /* Read until end of struct */ while (CurTok.Tok != TOK_ENDSTRUCT && CurTok.Tok != TOK_ENDUNION && CurTok.Tok != TOK_EOF) { long MemberSize; SymTable* Struct; SymEntry* Sym; /* Allow empty and comment lines */ if (CurTok.Tok == TOK_SEP) { NextTok (); continue; } /* The format is "[identifier] storage-allocator [, multiplicator]" */ Sym = 0; if (CurTok.Tok == TOK_IDENT) { /* Beware: An identifier may also be a macro, in which case we have ** to start over. */ Macro* M = FindMacro (&CurTok.SVal); if (M) { MacExpandStart (M); continue; } /* We have an identifier, generate a symbol */ Sym = SymFind (CurrentScope, &CurTok.SVal, SYM_ALLOC_NEW); /* Assign the symbol the offset of the current member */ SymDef (Sym, GenLiteralExpr (Offs), ADDR_SIZE_DEFAULT, SF_NONE); /* Skip the member name */ NextTok (); } /* Read storage allocators */ MemberSize = 0; /* In case of errors, use zero */ switch (CurTok.Tok) { case TOK_BYTE: NextTok (); MemberSize = Member (1); break; case TOK_DBYT: case TOK_WORD: case TOK_ADDR: NextTok (); MemberSize = Member (2); break; case TOK_FARADDR: NextTok (); MemberSize = Member (3); break; case TOK_DWORD: NextTok (); MemberSize = Member (4); break; case TOK_RES: NextTok (); if (CurTok.Tok == TOK_SEP) { ErrorSkip ("Size is missing"); } else { MemberSize = Member (1); } break; case TOK_TAG: NextTok (); Struct = ParseScopedSymTable (); if (Struct == 0) { ErrorSkip ("Unknown struct/union"); } else if (GetSymTabType (Struct) != SCOPE_STRUCT) { ErrorSkip ("Not a struct/union"); } else { SymEntry* SizeSym = GetSizeOfScope (Struct); if (!SymIsDef (SizeSym) || !SymIsConst (SizeSym, &MemberSize)) { ErrorSkip ("Size of struct/union is unknown"); } } MemberSize = Member (MemberSize); break; case TOK_STRUCT: NextTok (); MemberSize = DoStructInternal (Offs, STRUCT); break; case TOK_UNION: NextTok (); MemberSize = DoStructInternal (Offs, UNION); break; default: if (!CheckConditionals ()) { /* Not a conditional directive */ ErrorSkip ("Invalid storage allocator in struct/union"); } } /* Assign the size to the member if it has a name */ if (Sym) { DefSizeOfSymbol (Sym, MemberSize); } /* Next member */ if (Type == STRUCT) { /* Struct */ Offs += MemberSize; Size += MemberSize; } else { /* Union */ if (MemberSize > Size) { Size = MemberSize; } } /* Expect end of line */ ConsumeSep (); } /* If this is not a anon struct, enter a special symbol named ".size" ** into the symbol table of the struct that holds the size of the ** struct. Since the symbol starts with a dot, it cannot be accessed ** by user code. ** Leave the struct scope level. */ if (!Anon) { /* Add a symbol */ SymEntry* SizeSym = GetSizeOfScope (CurrentScope); SymDef (SizeSym, GenLiteralExpr (Size), ADDR_SIZE_DEFAULT, SF_NONE); /* Close the struct scope */ SymLeaveLevel (); } /* End of struct/union definition */ if (Type == STRUCT) { Consume (TOK_ENDSTRUCT, "'.ENDSTRUCT' expected"); } else { Consume (TOK_ENDUNION, "'.ENDUNION' expected"); } /* Return the size of the struct */ return Size; }