+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2004-2006 Intel Corporation. All rights reserved\r
-This program and the accompanying materials are licensed and made available \r
-under the terms and conditions of the BSD License which accompanies this \r
-distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- Symbol.c\r
-\r
-Abstract:\r
-\r
- Class-like implementation for a symbol table.\r
-\r
---*/\r
-\r
-// GC_TODO: fix comment to set correct module name: Symbols.c\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <stdlib.h>\r
-//\r
-// for isspace()\r
-//\r
-#include <ctype.h>\r
-\r
-#include <Common/UefiBaseTypes.h>\r
-\r
-#include "CommonLib.h"\r
-#include "EfiUtilityMsgs.h"\r
-#include "Symbols.h"\r
-\r
-#define MAX_LINE_LEN 512\r
-\r
-//\r
-// Linked list to keep track of all symbols\r
-//\r
-typedef struct _SYMBOL {\r
- struct _SYMBOL *Next;\r
- int Type;\r
- char *Name;\r
- char *Value;\r
-} SYMBOL;\r
-\r
-static\r
-SYMBOL *\r
-FreeSymbols (\r
- SYMBOL *Syms\r
- );\r
-\r
-static\r
-int\r
-ExpandMacros (\r
- char *SourceLine,\r
- char *DestLine,\r
- int LineLen\r
- );\r
-\r
-static SYMBOL *mSymbolTable = NULL;\r
-\r
-void\r
-SymbolsConstructor (\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- None\r
-\r
-Returns:\r
-\r
- GC_TODO: add return values\r
-\r
---*/\r
-{\r
- SymbolsDestructor ();\r
-}\r
-\r
-void\r
-SymbolsDestructor (\r
- VOID\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- None\r
-\r
-Returns:\r
-\r
- GC_TODO: add return values\r
-\r
---*/\r
-{\r
- mSymbolTable = FreeSymbols (mSymbolTable);\r
-}\r
-\r
-char *\r
-GetSymbolValue (\r
- char *SymbolName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- \r
- Look up a symbol in our symbol table.\r
-\r
-Arguments:\r
-\r
- SymbolName\r
-\r
-Returns:\r
-\r
- Pointer to the value of the symbol if found\r
- NULL if the symbol is not found\r
-\r
---*/\r
-// GC_TODO: SymbolName - add argument and description to function comment\r
-{\r
- SYMBOL *Symbol;\r
- //\r
- // Walk the symbol table\r
- //\r
- Symbol = mSymbolTable;\r
- while (Symbol) {\r
- if (stricmp (SymbolName, Symbol->Name) == 0) {\r
- return Symbol->Value;\r
- }\r
-\r
- Symbol = Symbol->Next;\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-int\r
-SymbolAdd (\r
- char *Name,\r
- char *Value,\r
- int Mode\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- \r
- Add a symbol name/value to the symbol table\r
-\r
-Arguments:\r
-\r
- Name - name of symbol to add\r
- Value - value of symbol to add\r
- Mode - currrently unused\r
-\r
-Returns:\r
-\r
- Length of symbol added.\r
-\r
-Notes:\r
- If Value == NULL, then this routine will assume that the Name field\r
- looks something like "MySymName = MySymValue", and will try to parse\r
- it that way and add the symbol name/pair from the string.\r
-\r
---*/\r
-{\r
- SYMBOL *Symbol;\r
-\r
- SYMBOL *NewSymbol;\r
- int Len;\r
- char *Start;\r
- char *Cptr;\r
- char CSave;\r
- char *SaveCptr;\r
-\r
- Len = 0;\r
- SaveCptr = NULL;\r
- CSave = 0;\r
- //\r
- // If value pointer is null, then they passed us a line something like:\r
- // varname = value, or simply var =\r
- //\r
- if (Value == NULL) {\r
- Start = Name;\r
- while (*Name && isspace (*Name)) {\r
- Name++;\r
- }\r
-\r
- if (Name == NULL) {\r
- return -1;\r
- }\r
- //\r
- // Find the end of the name. Either space or a '='.\r
- //\r
- for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++)\r
- ;\r
- if (Value == NULL) {\r
- return -1;\r
- }\r
- //\r
- // Look for the '='\r
- //\r
- Cptr = Value;\r
- while (*Value && (*Value != '=')) {\r
- Value++;\r
- }\r
-\r
- if (Value == NULL) {\r
- return -1;\r
- }\r
- //\r
- // Now truncate the name\r
- //\r
- *Cptr = 0;\r
- //\r
- // Skip over the = and then any spaces\r
- //\r
- Value++;\r
- while (*Value && isspace (*Value)) {\r
- Value++;\r
-\r
- }\r
- //\r
- // Find end of string, checking for quoted string\r
- //\r
- if (*Value == '\"') {\r
- Value++;\r
- for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++)\r
- ;\r
- } else {\r
- for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++)\r
- ;\r
- }\r
- //\r
- // Null terminate the value string\r
- //\r
- CSave = *Cptr;\r
- SaveCptr = Cptr;\r
- *Cptr = 0;\r
- Len = (int) (Cptr - Start);\r
- }\r
- //\r
- // We now have a symbol name and a value. Look for an existing variable\r
- // and overwrite it.\r
- //\r
- Symbol = mSymbolTable;\r
- while (Symbol) {\r
- //\r
- // Check for symbol name match\r
- //\r
- if (stricmp (Name, Symbol->Name) == 0) {\r
- _free (Symbol->Value);\r
- Symbol->Value = (char *) _malloc (strlen (Value) + 1);\r
- if (Symbol->Value == NULL) {\r
- Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
- return -1;\r
- }\r
-\r
- strcpy (Symbol->Value, Value);\r
- //\r
- // If value == "NULL", then make it a 0-length string\r
- //\r
- if (stricmp (Symbol->Value, "NULL") == 0) {\r
- Symbol->Value[0] = 0;\r
- }\r
-\r
- return Len;\r
- }\r
-\r
- Symbol = Symbol->Next;\r
- }\r
- //\r
- // Does not exist, create a new one\r
- //\r
- NewSymbol = (SYMBOL *) _malloc (sizeof (SYMBOL));\r
- if (NewSymbol == NULL) {\r
- Error (NULL, 0, 0, NULL, "memory allocation failure");\r
- return -1;\r
- }\r
-\r
- memset ((char *) NewSymbol, 0, sizeof (SYMBOL));\r
- NewSymbol->Name = (char *) _malloc (strlen (Name) + 1);\r
- if (NewSymbol->Name == NULL) {\r
- Error (NULL, 0, 0, NULL, "memory allocation failure");\r
- _free (NewSymbol);\r
- return -1;\r
- }\r
-\r
- NewSymbol->Value = (char *) _malloc (strlen (Value) + 1);\r
- if (NewSymbol->Value == NULL) {\r
- Error (NULL, 0, 0, NULL, "memory allocation failure");\r
- _free (NewSymbol->Name);\r
- _free (NewSymbol);\r
- return -1;\r
- }\r
-\r
- strcpy (NewSymbol->Name, Name);\r
- strcpy (NewSymbol->Value, Value);\r
- //\r
- // Remove trailing spaces\r
- //\r
- Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1;\r
- while (Cptr > NewSymbol->Value) {\r
- if (isspace (*Cptr)) {\r
- *Cptr = 0;\r
- Cptr--;\r
- } else {\r
- break;\r
- }\r
- }\r
- //\r
- // Add it to the head of the list.\r
- //\r
- NewSymbol->Next = mSymbolTable;\r
- mSymbolTable = NewSymbol;\r
- //\r
- // If value == "NULL", then make it a 0-length string\r
- //\r
- if (stricmp (NewSymbol->Value, "NULL") == 0) {\r
- NewSymbol->Value[0] = 0;\r
- }\r
- //\r
- // Restore the terminator we inserted if they passed in var=value\r
- //\r
- if (SaveCptr != NULL) {\r
- *SaveCptr = CSave;\r
- }\r
- _free (NewSymbol->Value);\r
- _free (NewSymbol->Name);\r
- _free (NewSymbol);\r
- return Len;\r
-}\r
-\r
-static\r
-STATUS\r
-RemoveSymbol (\r
- char *Name,\r
- char SymbolType\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- \r
- Remove a symbol name/value from the symbol table\r
-\r
-Arguments:\r
-\r
- Name - name of symbol to remove\r
- SymbolType - type of symbol to remove\r
-\r
-Returns:\r
-\r
- STATUS_SUCCESS - matching symbol found and removed\r
- STATUS_ERROR - matching symbol not found in symbol table\r
-\r
---*/\r
-{\r
- SYMBOL *Symbol;\r
-\r
- SYMBOL *PrevSymbol;\r
-\r
- PrevSymbol = NULL;\r
- Symbol = mSymbolTable;\r
- //\r
- // Walk the linked list of symbols in the symbol table looking\r
- // for a match of both symbol name and type.\r
- //\r
- while (Symbol) {\r
- if ((stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) {\r
- //\r
- // If the symbol has a value associated with it, free the memory\r
- // allocated for the value.\r
- // Then free the memory allocated for the symbols string name.\r
- //\r
- if (Symbol->Value) {\r
- _free (Symbol->Value);\r
- }\r
-\r
- _free (Symbol->Name);\r
- //\r
- // Link the previous symbol to the next symbol to effectively\r
- // remove this symbol from the linked list.\r
- //\r
- if (PrevSymbol) {\r
- PrevSymbol->Next = Symbol->Next;\r
- } else {\r
- mSymbolTable = Symbol->Next;\r
- }\r
-\r
- _free (Symbol);\r
- return STATUS_SUCCESS;\r
- }\r
-\r
- PrevSymbol = Symbol;\r
- Symbol = Symbol->Next;\r
- }\r
-\r
- return STATUS_WARNING;\r
-}\r
-\r
-static\r
-SYMBOL *\r
-FreeSymbols (\r
- SYMBOL *Syms\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Syms - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- GC_TODO: add return values\r
-\r
---*/\r
-{\r
- SYMBOL *Next;\r
- while (Syms) {\r
- if (Syms->Name != NULL) {\r
- _free (Syms->Name);\r
- }\r
-\r
- if (Syms->Value != NULL) {\r
- _free (Syms->Value);\r
- }\r
-\r
- Next = Syms->Next;\r
- _free (Syms);\r
- Syms = Next;\r
- }\r
-\r
- return Syms;\r
-}\r
-\r
-static\r
-int\r
-ExpandMacros (\r
- char *SourceLine,\r
- char *DestLine,\r
- int LineLen\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- \r
- Given a line of text, replace all variables of format $(NAME) with values\r
- from our symbol table.\r
-\r
-Arguments:\r
-\r
- SourceLine - input line of text to do symbol replacements on\r
- DestLine - on output, SourceLine with symbols replaced\r
- LineLen - length of DestLine, so we don't exceed its allocated length\r
-\r
-Returns:\r
-\r
- STATUS_SUCCESS - no problems encountered\r
- STATUS_WARNING - missing closing parenthesis on a symbol reference in SourceLine\r
- STATUS_ERROR - memory allocation failure\r
-\r
---*/\r
-{\r
- static int NestDepth = 0;\r
- char *FromPtr;\r
- char *ToPtr;\r
- char *SaveStart;\r
- char *Cptr;\r
- char *value;\r
- int Expanded;\r
- int ExpandedCount;\r
- INT8 *LocalDestLine;\r
- STATUS Status;\r
- int LocalLineLen;\r
-\r
- NestDepth++;\r
- Status = STATUS_SUCCESS;\r
- LocalDestLine = (char *) _malloc (LineLen);\r
- if (LocalDestLine == NULL) {\r
- Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);\r
- return STATUS_ERROR;\r
- }\r
-\r
- FromPtr = SourceLine;\r
- ToPtr = LocalDestLine;\r
- //\r
- // Walk the entire line, replacing $(MACRO_NAME).\r
- //\r
- LocalLineLen = LineLen;\r
- ExpandedCount = 0;\r
- while (*FromPtr && (LocalLineLen > 0)) {\r
- if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) {\r
- //\r
- // Save the start in case it's undefined, in which case we copy it as-is.\r
- //\r
- SaveStart = FromPtr;\r
- Expanded = 0;\r
- //\r
- // Macro expansion time. Find the end (no spaces allowed)\r
- //\r
- FromPtr += 2;\r
- for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++)\r
- ;\r
- if (*Cptr) {\r
- //\r
- // Truncate the string at the closing parenthesis for ease-of-use.\r
- // Then copy the string directly to the destination line in case we don't find\r
- // a definition for it.\r
- //\r
- *Cptr = 0;\r
- strcpy (ToPtr, SaveStart);\r
- if ((value = GetSymbolValue (FromPtr)) != NULL) {\r
- strcpy (ToPtr, value);\r
- LocalLineLen -= strlen (value);\r
- ToPtr += strlen (value);\r
- Expanded = 1;\r
- ExpandedCount++;\r
- }\r
-\r
- if (!Expanded) {\r
- //\r
- // Restore closing parenthesis, and advance to next character\r
- //\r
- *Cptr = ')';\r
- FromPtr = SaveStart + 1;\r
- ToPtr++;\r
- } else {\r
- FromPtr = Cptr + 1;\r
- }\r
- } else {\r
- Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on macro");\r
- strcpy (ToPtr, FromPtr);\r
- Status = STATUS_WARNING;\r
- goto Done;\r
- }\r
- } else {\r
- *ToPtr = *FromPtr;\r
- FromPtr++;\r
- ToPtr++;\r
- LocalLineLen--;\r
- }\r
- }\r
-\r
- if (*FromPtr == 0) {\r
- *ToPtr = 0;\r
- }\r
-\r
- //\r
- // If we expanded at least one string successfully, then make a recursive call to try again.\r
- //\r
- if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (NestDepth < 10)) {\r
- Status = ExpandMacros (LocalDestLine, DestLine, LineLen);\r
- _free (LocalDestLine);\r
- NestDepth = 0;\r
- return Status;\r
- }\r
-\r
-Done:\r
- if (Status != STATUS_ERROR) {\r
- strcpy (DestLine, LocalDestLine);\r
- }\r
-\r
- NestDepth = 0;\r
- _free (LocalDestLine);\r
- return Status;\r
-}\r
-\r
-STATUS\r
-SymbolsFileStringsReplace (\r
- char *InFileName,\r
- char *OutFileName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- \r
- Given input and output file names, read in the input file, replace variable\r
- references of format $(NAME) with appropriate values from our symbol table,\r
- and write the result out to the output file.\r
-\r
-Arguments:\r
-\r
- InFileName - name of input text file to replace variable references\r
- OutFileName - name of output text file to write results to\r
-\r
-Returns:\r
-\r
- STATUS_SUCCESS - no problems encountered\r
- STATUS_ERROR - failed to open input or output file\r
-\r
---*/\r
-{\r
- STATUS Status;\r
- FILE *InFptr;\r
- FILE *OutFptr;\r
- char Line[MAX_LINE_LEN];\r
- char OutLine[MAX_LINE_LEN];\r
-\r
- Status = STATUS_ERROR;\r
- //\r
- // Open input and output files\r
- //\r
- InFptr = NULL;\r
- OutFptr = NULL;\r
- if ((InFptr = fopen (InFileName, "r")) == NULL) {\r
- Error (NULL, 0, 0, InFileName, "failed to open input file for reading");\r
- goto Done;\r
- }\r
-\r
- if ((OutFptr = fopen (OutFileName, "w")) == NULL) {\r
- Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
- goto Done;\r
- }\r
- //\r
- // Read lines from input file until done\r
- //\r
- while (fgets (Line, sizeof (Line), InFptr) != NULL) {\r
- ExpandMacros (Line, OutLine, sizeof (OutLine));\r
- fprintf (OutFptr, OutLine);\r
- }\r
-\r
- Status = STATUS_SUCCESS;\r
-Done:\r
- if (InFptr != NULL) {\r
- fclose (InFptr);\r
- }\r
-\r
- if (OutFptr != NULL) {\r
- fclose (OutFptr);\r
- }\r
-\r
- return Status;\r
-}\r