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