]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / ProcessDsc / DscFile.c
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c
new file mode 100644 (file)
index 0000000..345e1a9
--- /dev/null
@@ -0,0 +1,534 @@
+/*++\r
+\r
+Copyright (c) 2004 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this 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
+    DscFile.c\r
+\r
+  Abstract:\r
+\r
+    This module is used to process description files at a high level. For the\r
+    most part, it pre-parses the file to find and save off positions of all\r
+    the sections ([section.subsection.subsection]) in a linked list, then\r
+    provides services to find the sections by name, and read the lines from\r
+    the section until you run into the next section.\r
+\r
+  NOTE: DSC file is synonomous with section file. A DSC file is simply a file\r
+    containing bracketed section names [section.subsection.subsection...]\r
+\r
+--*/\r
+\r
+#include <stdio.h>  // for file ops\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <stdlib.h> // for malloc\r
+#include "Common.h"\r
+#include "DSCFile.h"\r
+\r
+#define MAX_INCLUDE_NEST_LEVEL  20\r
+\r
+static\r
+void\r
+DSCFileFree (\r
+  DSC_FILE *DSC\r
+  );\r
+\r
+static\r
+STATUS\r
+DSCParseInclude (\r
+  DSC_FILE  *DSC,\r
+  char      *FileName,\r
+  int       NestLevel\r
+  );\r
+\r
+//\r
+// Constructor for a DSC file\r
+//\r
+int\r
+DSCFileInit (\r
+  DSC_FILE *DSC\r
+  )\r
+{\r
+  memset ((char *) DSC, 0, sizeof (DSC_FILE));\r
+  DSC->SavedPositionIndex = -1;\r
+  return STATUS_SUCCESS;\r
+}\r
+//\r
+// Destructor for a DSC file\r
+//\r
+int\r
+DSCFileDestroy (\r
+  DSC_FILE *DSC\r
+  )\r
+{\r
+  DSC->SavedPositionIndex = -1;\r
+  DSCFileFree (DSC);\r
+  return STATUS_SUCCESS;\r
+}\r
+//\r
+// Get the next line from a DSC file.\r
+//\r
+char *\r
+DSCFileGetLine (\r
+  DSC_FILE  *DSC,\r
+  char      *Line,\r
+  int       LineLen\r
+  )\r
+{\r
+  char  *Cptr;\r
+\r
+  if (DSC->CurrentLine == NULL) {\r
+    return NULL;\r
+  }\r
+  //\r
+  // Check for running into next section\r
+  //\r
+  if (DSC->CurrentLine->Line[0] == '[') {\r
+    return NULL;\r
+  }\r
+  //\r
+  // Allow special case where the line starts with backslash-bracket. If we\r
+  // see this, then shift everything left one character.\r
+  //\r
+  if ((DSC->CurrentLine->Line[0] == '\\') && (DSC->CurrentLine->Line[1] == '[')) {\r
+    Cptr = DSC->CurrentLine->Line + 1;\r
+  } else {\r
+    Cptr = DSC->CurrentLine->Line;\r
+  }\r
+\r
+  strncpy (Line, Cptr, LineLen);\r
+  ParserSetPosition (DSC->CurrentLine->FileName, DSC->CurrentLine->LineNum);\r
+  DSC->CurrentLine = DSC->CurrentLine->Next;\r
+  return Line;\r
+}\r
+\r
+int\r
+DSCFileSetFile (\r
+  DSC_FILE  *DSC,\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Pre-scan a section file to find all the sections. Then we can speed up\r
+  searching for the different sections.\r
+\r
+Arguments:\r
+\r
+  DSC       - pointer to a DSC structure (this pointer)\r
+  FileName  - name of the file to process\r
+\r
+Returns:\r
+\r
+  STATUS_SUCCESS if everything went well.\r
+\r
+--*/\r
+{\r
+  STATUS  Status;\r
+\r
+  //\r
+  // Called to open a new sectioned file.\r
+  //\r
+  Status = DSCParseInclude (DSC, FileName, 1);\r
+  return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+DSCParseInclude (\r
+  DSC_FILE    *DSC,\r
+  char        *FileName,\r
+  int         NestLevel\r
+  )\r
+{\r
+  SECTION       *NewSect;\r
+  SECTION_LINE  *NewLine;\r
+  DSC_FILE_NAME *NewDscFileName;\r
+  char          Line[MAX_LINE_LEN];\r
+  char          *Start;\r
+  char          *End;\r
+  char          SaveChar;\r
+  char          *TempCptr;\r
+  char          ShortHandSectionName[MAX_LINE_LEN];\r
+  char          ThisSectionName[MAX_LINE_LEN];\r
+  SECTION       *CurrSect;\r
+  SECTION       *TempSect;\r
+  FILE          *FilePtr;\r
+  STATUS        Status;\r
+  UINT32        LineNum;\r
+\r
+  //\r
+  // Make sure we haven't exceeded our maximum nesting level\r
+  //\r
+  if (NestLevel > MAX_INCLUDE_NEST_LEVEL) {\r
+    Error (NULL, 0, 0, "application error", "maximum !include nesting level exceeded");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Try to open the file\r
+  //\r
+  if ((FilePtr = fopen (FileName, "r")) == NULL) {\r
+    //\r
+    // This function is called to handle the DSC file from the command line too,\r
+    // so differentiate whether this file is an include file or the main file\r
+    // by examining the nest level.\r
+    //\r
+    if (NestLevel == 1) {\r
+      Error (NULL, 0, 0, FileName, "could not open DSC file for reading");\r
+    } else {\r
+      Error (NULL, 0, 0, FileName, "could not open !include DSC file for reading");\r
+    }\r
+\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // We keep a linked list of files we parse for error reporting purposes.\r
+  //\r
+  NewDscFileName = malloc (sizeof (DSC_FILE_NAME));\r
+  if (NewDscFileName == NULL) {\r
+    Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  memset (NewDscFileName, 0, sizeof (DSC_FILE_NAME));\r
+  NewDscFileName->FileName = (INT8 *) malloc (strlen (FileName) + 1);\r
+  if (NewDscFileName->FileName == NULL) {\r
+    Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  strcpy (NewDscFileName->FileName, FileName);\r
+  if (DSC->FileName == NULL) {\r
+    DSC->FileName = NewDscFileName;\r
+  } else {\r
+    DSC->LastFileName->Next = NewDscFileName;\r
+  }\r
+\r
+  DSC->LastFileName = NewDscFileName;\r
+  //\r
+  // Read lines and process until done\r
+  //\r
+  Status  = STATUS_SUCCESS;\r
+  LineNum = 0;\r
+  for (;;) {\r
+    if (fgets (Line, sizeof (Line), FilePtr) == NULL) {\r
+      break;\r
+    }\r
+\r
+    LineNum++;\r
+    ParserSetPosition (FileName, LineNum);\r
+    //\r
+    // Add the line to our list if it's not a !include line\r
+    //\r
+    if ((strncmp (Line, "!include", 8) == 0) && (isspace (Line[8]))) {\r
+      Start = Line + 9;\r
+      while (*Start && (*Start != '"')) {\r
+        Start++;\r
+      }\r
+\r
+      if (*Start != '"') {\r
+        Error (FileName, LineNum, 0, NULL, "invalid format for !include");\r
+        Status = STATUS_ERROR;\r
+        goto Done;\r
+      }\r
+\r
+      Start++;\r
+      for (End = Start; *End && (*End != '"'); End++)\r
+        ;\r
+      if (*End != '"') {\r
+        Error (FileName, LineNum, 0, NULL, "invalid format for !include");\r
+        Status = STATUS_ERROR;\r
+        goto Done;\r
+      }\r
+\r
+      *End = 0;\r
+      //\r
+      // Expand symbols. Use 'ThisSectionName' as scratchpad\r
+      //\r
+      ExpandSymbols (Start, ThisSectionName, sizeof (ThisSectionName), EXPANDMODE_NO_UNDEFS);\r
+      Status = DSCParseInclude (DSC, ThisSectionName, NestLevel + 1);\r
+      if (Status != STATUS_SUCCESS) {\r
+        Error (FileName, LineNum, 0, NULL, "failed to parse !include file");\r
+        goto Done;\r
+      }\r
+    } else {\r
+      NewLine = (SECTION_LINE *) malloc (sizeof (SECTION_LINE));\r
+      if (NewLine == NULL) {\r
+        Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
+        Status = STATUS_ERROR;\r
+        goto Done;\r
+      }\r
+\r
+      memset ((char *) NewLine, 0, sizeof (SECTION_LINE));\r
+      NewLine->LineNum  = LineNum;\r
+      NewLine->FileName = NewDscFileName->FileName;\r
+      NewLine->Line     = (char *) malloc (strlen (Line) + 1);\r
+      if (NewLine->Line == NULL) {\r
+        Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
+        Status = STATUS_ERROR;\r
+        goto Done;\r
+      }\r
+\r
+      strcpy (NewLine->Line, Line);\r
+      if (DSC->Lines == NULL) {\r
+        DSC->Lines = NewLine;\r
+      } else {\r
+        DSC->LastLine->Next = NewLine;\r
+      }\r
+\r
+      DSC->LastLine = NewLine;\r
+      //\r
+      // Parse the line for []. Ignore [] and [----] delimiters. The\r
+      // line may have multiple definitions separated by commas, so\r
+      // take each separately\r
+      //\r
+      Start = Line;\r
+      if ((Line[0] == '[') && ((Line[1] != ']') && (Line[1] != '-'))) {\r
+        //\r
+        // Skip over open bracket and preceeding spaces\r
+        //\r
+        Start++;\r
+        ShortHandSectionName[0] = 0;\r
+\r
+        while (*Start && (*Start != ']')) {\r
+          while (isspace (*Start)) {\r
+            Start++;\r
+          }\r
+          //\r
+          // Hack off closing bracket or trailing spaces or comma separator.\r
+          // Also allow things like [section.subsection1|subsection2], which\r
+          // is shorthand for [section.subsection1,section.subsection2]\r
+          //\r
+          End = Start;\r
+          while (*End && (*End != ']') && !isspace (*End) && (*End != ',') && (*End != '|')) {\r
+            End++;\r
+          }\r
+          //\r
+          // Save the character and null-terminate the string\r
+          //\r
+          SaveChar  = *End;\r
+          *End      = 0;\r
+          //\r
+          // Now allocate space for a new section and add it to the linked list.\r
+          // If the previous section ended with the shorthand indicator, then\r
+          // the section name was saved off. Append this section name to it.\r
+          //\r
+          strcpy (ThisSectionName, ShortHandSectionName);\r
+          if (*Start == '.') {\r
+            strcat (ThisSectionName, Start + 1);\r
+          } else {\r
+            strcat (ThisSectionName, Start);\r
+          }\r
+          //\r
+          // Allocate memory for the section. Then clear it out.\r
+          //\r
+          NewSect = (SECTION *) malloc (sizeof (SECTION));\r
+          if (NewSect == NULL) {\r
+            Error (NULL, 0, 0, NULL, "failed to allocation memory for sections");\r
+            Status = STATUS_ERROR;\r
+            goto Done;\r
+          }\r
+\r
+          memset ((char *) NewSect, 0, sizeof (SECTION));\r
+          NewSect->FirstLine  = NewLine;\r
+          NewSect->Name       = (char *) malloc (strlen (ThisSectionName) + 1);\r
+          if (NewSect->Name == NULL) {\r
+            Error (NULL, 0, 0, NULL, "failed to allocation memory for sections");\r
+            Status = STATUS_ERROR;\r
+            goto Done;\r
+          }\r
+\r
+          strcpy (NewSect->Name, ThisSectionName);\r
+          if (DSC->Sections == NULL) {\r
+            DSC->Sections = NewSect;\r
+          } else {\r
+            DSC->LastSection->Next = NewSect;\r
+          }\r
+\r
+          DSC->LastSection  = NewSect;\r
+          *End              = SaveChar;\r
+          //\r
+          // If the name ended in a shorthand indicator, then save the\r
+          // section name and truncate it at the last dot.\r
+          //\r
+          if (SaveChar == '|') {\r
+            strcpy (ShortHandSectionName, ThisSectionName);\r
+            for (TempCptr = ShortHandSectionName + strlen (ShortHandSectionName) - 1;\r
+                 (TempCptr != ShortHandSectionName) && (*TempCptr != '.');\r
+                 TempCptr--\r
+                )\r
+              ;\r
+            //\r
+            // If we didn't find a dot, then hopefully they have [name1|name2]\r
+            // instead of [name1,name2].\r
+            //\r
+            if (TempCptr == ShortHandSectionName) {\r
+              ShortHandSectionName[0] = 0;\r
+            } else {\r
+              //\r
+              // Truncate after the dot\r
+              //\r
+              *(TempCptr + 1) = 0;\r
+            }\r
+          } else {\r
+            //\r
+            // Kill the shorthand string\r
+            //\r
+            ShortHandSectionName[0] = 0;\r
+          }\r
+          //\r
+          // Skip to next section name or closing bracket\r
+          //\r
+          while (*End && ((*End == ',') || isspace (*End) || (*End == '|'))) {\r
+            End++;\r
+          }\r
+\r
+          Start = End;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  //\r
+  // Look through all the sections to make sure we don't have any duplicates.\r
+  // Allow [----] and [====] section separators\r
+  //\r
+  CurrSect = DSC->Sections;\r
+  while (CurrSect != NULL) {\r
+    TempSect = CurrSect->Next;\r
+    while (TempSect != NULL) {\r
+      if (isalpha (CurrSect->Name[0]) && (_stricmp (CurrSect->Name, TempSect->Name) == 0)) {\r
+        Error (\r
+          TempSect->FirstLine->FileName,\r
+          TempSect->FirstLine->LineNum,\r
+          0,\r
+          TempSect->Name,\r
+          "duplicate section found"\r
+          );\r
+        Error (\r
+          CurrSect->FirstLine->FileName,\r
+          CurrSect->FirstLine->LineNum,\r
+          0,\r
+          TempSect->Name,\r
+          "first definition of duplicate section"\r
+          );\r
+        Status = STATUS_ERROR;\r
+        goto Done;\r
+      }\r
+\r
+      TempSect = TempSect->Next;\r
+    }\r
+\r
+    CurrSect = CurrSect->Next;\r
+  }\r
+\r
+Done:\r
+  fclose (FilePtr);\r
+  return Status;\r
+}\r
+//\r
+// Free up memory allocated for DSC file handling.\r
+//\r
+static\r
+void\r
+DSCFileFree (\r
+  DSC_FILE *DSC\r
+  )\r
+{\r
+  SECTION       *NextSection;\r
+  SECTION_LINE  *NextLine;\r
+  DSC_FILE_NAME *NextName;\r
+\r
+  while (DSC->Sections != NULL) {\r
+    NextSection = DSC->Sections->Next;\r
+    if (DSC->Sections->Name != NULL) {\r
+      free (DSC->Sections->Name);\r
+    }\r
+\r
+    free (DSC->Sections);\r
+    DSC->Sections = NextSection;\r
+  }\r
+\r
+  while (DSC->Lines != NULL) {\r
+    NextLine = DSC->Lines->Next;\r
+    free (DSC->Lines->Line);\r
+    free (DSC->Lines);\r
+    DSC->Lines = NextLine;\r
+  }\r
+\r
+  while (DSC->FileName != NULL) {\r
+    NextName = DSC->FileName->Next;\r
+    free (DSC->FileName->FileName);\r
+    free (DSC->FileName);\r
+    DSC->FileName = NextName;\r
+  }\r
+}\r
+\r
+SECTION *\r
+DSCFileFindSection (\r
+  DSC_FILE  *DSC,\r
+  char      *Name\r
+  )\r
+{\r
+  SECTION *Sect;\r
+\r
+  //\r
+  // Look through all the sections to find one with this name (case insensitive)\r
+  //\r
+  Sect = DSC->Sections;\r
+  while (Sect != NULL) {\r
+    if (_stricmp (Name, Sect->Name) == 0) {\r
+      //\r
+      // Position within file\r
+      //\r
+      DSC->CurrentLine = Sect->FirstLine->Next;\r
+      return Sect;\r
+    }\r
+\r
+    Sect = Sect->Next;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+int\r
+DSCFileSavePosition (\r
+  DSC_FILE *DSC\r
+  )\r
+{\r
+  //\r
+  // Advance to next slot\r
+  //\r
+  DSC->SavedPositionIndex++;\r
+  if (DSC->SavedPositionIndex >= MAX_SAVES) {\r
+    DSC->SavedPositionIndex--;\r
+    Error (NULL, 0, 0, "APP ERROR", "max nesting of saved section file positions exceeded");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  DSC->SavedPosition[DSC->SavedPositionIndex] = DSC->CurrentLine;\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+int\r
+DSCFileRestorePosition (\r
+  DSC_FILE *DSC\r
+  )\r
+{\r
+  if (DSC->SavedPositionIndex < 0) {\r
+    Error (NULL, 0, 0, "APP ERROR", "underflow of saved positions in section file");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  DSC->CurrentLine = DSC->SavedPosition[DSC->SavedPositionIndex];\r
+  DSC->SavedPositionIndex--;\r
+  return STATUS_SUCCESS;\r
+}\r