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