mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-03 21:17:23 +01:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1006 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			649 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			649 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
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;
 | 
						|
}
 |