More moves for Tool Packages
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1676 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
648
Tools/CCode/Source/FlashMap/Symbols.c
Normal file
648
Tools/CCode/Source/FlashMap/Symbols.c
Normal file
@ -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;
|
||||
}
|
Reference in New Issue
Block a user