Add in the 1st version of ECP.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2832 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
534
EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c
Normal file
534
EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c
Normal file
@ -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;
|
||||
}
|
Reference in New Issue
Block a user