]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Tools/Source/TianoTools/FlashMap/Symbols.c
Adding Additional Tools that are needed for Platform Image creation.
[mirror_edk2.git] / Tools / Source / TianoTools / FlashMap / Symbols.c
diff --git a/Tools/Source/TianoTools/FlashMap/Symbols.c b/Tools/Source/TianoTools/FlashMap/Symbols.c
new file mode 100644 (file)
index 0000000..471128a
--- /dev/null
@@ -0,0 +1,647 @@
+/*++\r
+\r
+Copyright (c)  2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\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 "Tiano.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