3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Main module for the ProcessDsc utility.
22 #include <windows.h> // for GetShortPathName()
27 #include <direct.h> // for _mkdir()
29 #include <stdlib.h> // for getenv()
30 #include <shlwapi.h> // for PathCanonicalize()
32 #include "MultiThread.h"
34 #include "Exceptions.h"
37 #include "EfiUtilityMsgs.h"
38 #include "TianoBind.h"
40 #define UTILITY_NAME "ProcessDsc"
41 #define UTILITY_VERSION "v1.0"
44 // Common symbol name definitions. For example, the user can reference
45 // $(BUILD_DIR) in their DSC file and we will expand it for them (usually).
46 // I've defined the equivalents here in case we want to change the name the
47 // user references, in which case we just change the string value here and
48 // our code still works.
50 #define BUILD_DIR "BUILD_DIR"
51 #define EFI_SOURCE "EFI_SOURCE"
52 #define DEST_DIR "DEST_DIR"
53 #define SOURCE_DIR "SOURCE_DIR"
54 #define LIB_DIR "LIB_DIR"
55 #define BIN_DIR "BIN_DIR"
56 #define OUT_DIR "OUT_DIR"
57 #define INF_FILENAME "INF_FILENAME"
58 #define SOURCE_RELATIVE_PATH "SOURCE_RELATIVE_PATH"
59 #define SOURCE_BASE_NAME "SOURCE_BASE_NAME"
60 #define SOURCE_FILE_NAME "SOURCE_FILE_NAME" // c:\FullPath\File.c
61 #define PROCESSOR "PROCESSOR"
63 #define BASE_NAME "BASE_NAME"
65 #define FILE_GUID "FILE_GUID"
66 #define COMPONENT_TYPE_FILE "FILE"
67 #define BUILD_TYPE "BUILD_TYPE"
68 #define FFS_EXT "FFS_EXT" // FV_EXT is deprecated -- extension of FFS file
69 #define MAKEFILE_NAME "MAKEFILE_NAME" // name of component's output makefile
70 #define PLATFORM "PLATFORM" // for more granularity
71 #define PACKAGE_FILENAME "PACKAGE_FILENAME"
72 #define PACKAGE "PACKAGE"
73 #define PACKAGE_TAG "PACKAGE_TAG" // alternate name to PACKAGE
74 #define SHORT_NAMES "SHORT_NAMES" // for 8.3 names of symbols
75 #define APRIORI "APRIORI" // to add to apriori list
76 #define OPTIONAL_COMPONENT "OPTIONAL" // define as non-zero for optional INF files
77 #define SOURCE_SELECT "SOURCE_SELECT" // say SOURCE_SELECT=smm,common to select INF sources
78 #define NONFFS_FV "NONFFS_FV" // for non-FFS FV such as working & spare block FV
79 #define SKIP_FV_NULL "SKIP_FV_NULL" // define as nonzero to not build components with FV=NULL
80 #define SOURCE_COMPILE_TYPE "SOURCE_COMPILE_TYPE" // to build a source using a custom build section in the DSC file
81 #define SOURCE_FILE_EXTENSION "SOURCE_FILE_EXTENSION"
82 #define COMPILE_SELECT "COMPILE_SELECT"
83 #define SOURCE_OVERRIDE_PATH "SOURCE_OVERRIDE_PATH" // get source files from here first
84 #define MAKEFILE_OUT_SECTION_NAME "makefile.out"
85 #define COMMON_SECTION_NAME "common" // shared files or functionality
86 #define NMAKE_SECTION_NAME "nmake"
87 #define SOURCES_SECTION_NAME "sources"
88 #define COMPONENTS_SECTION_NAME "components"
89 #define INCLUDE_SECTION_NAME "includes"
90 #define DEFINES_SECTION_NAME "defines"
91 #define LIBRARIES_SECTION_NAME "libraries"
92 #define LIBRARIES_PLATFORM_SECTION_NAME "libraries.platform"
93 #define MAKEFILE_SECTION_NAME "makefile"
94 #define COMPONENT_TYPE "component_type"
95 #define PLATFORM_STR "\\platform\\" // to determine EFI_SOURCE
96 #define MAKEFILE_OUT_NAME "makefile.out" // if not specified on command line
97 #define MODULE_MAKEFILE_NAME "module.mak" // record all module makefile targets
98 #define MODULE_NAME_FILE "module.list" // record all module names defined in the dsc file
99 #define GLOBAL_LINK_LIB_NAME "CompilerStub" // Lib added in link option, maybe removed in the future
100 #define MODULE_BASE_NAME_WIDTH 25 // Width for module name output
103 // When a symbol is defined as "NULL", it gets saved in the symbol table as a 0-length
104 // string. Use this macro to detect if a symbol has been defined this way.
106 #define IS_NULL_SYMBOL_VALUE(var) ((var != NULL) && (strlen (var) == 0))
109 // Defines for file types
111 #define FILETYPE_UNKNOWN 0
113 #define FILETYPE_ASM 2
115 #define FILETYPE_VFR 4
116 #define FILETYPE_INC 5
122 INT8
*Extension
; // file extension
123 INT8
*BuiltExtension
;
129 // Define masks for the FileFlags field
131 #define FILE_FLAG_INCLUDE 0x01
132 #define FILE_FLAG_SOURCE 0x02
135 // This table describes a from-to list of files. For
136 // example, when a ".c" is built, it results in a ".obj" file.
138 static const FILETYPE mFileTypes
[] = {
162 }, // actually *.vfr -> *.c -> *.obj
190 // Structure to split up a file into its different parts.
201 // Maximum length for any line in any file after symbol expansion
203 #define MAX_EXP_LINE_LEN (MAX_LINE_LEN * 2)
206 // Linked list to keep track of all symbols
208 typedef struct _SYMBOL
{
209 struct _SYMBOL
*Next
;
210 int Type
; // local or global symbol
216 // Module globals for multi-thread build
218 static BUILD_ITEM
**mCurrentBuildList
; // build list currently handling
219 static BUILD_ITEM
*mCurrentBuildItem
; // build item currently handling
222 // Define masks for the build targets
224 #define BUILD_TARGET_COMPONENTS 0x01
225 #define BUILD_TARGET_LIBRARIES 0x02
226 #define BUILD_TARGET_FVS 0x04
227 #define BUILD_TARGET_ALL 0xff
231 // This structure is used to save globals
236 INT8 MakefileName
[MAX_PATH
]; // output makefile name
237 INT8 XRefFileName
[MAX_PATH
];
238 INT8 GuidDatabaseFileName
[MAX_PATH
];
239 INT8 ModuleMakefileName
[MAX_PATH
];
241 FILE *ModuleMakefileFptr
;
247 BUILD_ITEM
*LibraryList
;
248 COMPONENTS_ITEM
*ComponentsList
;
252 // This gets dumped to the head of makefile.out
254 static const INT8
*MakefileHeader
[] = {
258 "# File auto-generated by build utility",
266 "# Auto-generated makefile for building of EFI components/libraries",
274 // Function prototypes
297 ParseGuidDatabaseFile (
301 #define DSC_SECTION_TYPE_COMPONENTS 0
302 #define DSC_SECTION_TYPE_LIBRARIES 1
303 #define DSC_SECTION_TYPE_PLATFORM_LIBRARIES 2
307 ProcessSectionComponents (
314 ProcessComponentFile (
322 ProcessIncludeFiles (
323 DSC_FILE
*ComponentFile
,
329 ProcessIncludeFilesSingle (
330 DSC_FILE
*ComponentFile
,
336 // Mode flags for processing source files
338 #define SOURCE_MODE_BUILD_COMMANDS 0x01
339 #define SOURCE_MODE_SOURCE_FILES 0x02
345 DSC_FILE
*ComponentFile
,
352 ProcessSourceFilesSection (
354 DSC_FILE
*ComponentFile
,
363 DSC_FILE
*ComponentFile
,
369 ProcessObjectsSingle (
370 DSC_FILE
*ComponentFile
,
378 DSC_FILE
*ComponentFile
,
385 DSC_FILE
*ComponentFile
,
392 ProcessIncludesSection (
393 DSC_FILE
*ComponentFile
,
399 ProcessIncludesSectionSingle (
400 DSC_FILE
*ComponentFile
,
407 ProcessINFNMakeSection (
408 DSC_FILE
*ComponentFile
,
414 ProcessINFDefinesSection (
415 DSC_FILE
*ComponentFile
420 ProcessINFDefinesSectionSingle (
421 DSC_FILE
*ComponentFile
,
427 ProcessSectionLibraries (
434 ProcessDSCDefinesSection (
485 WriteCompileCommands (
494 WriteCommonMakefile (
502 WriteComponentTypeBuildCommands (
510 StripTrailingSpaces (
553 SMART_FILE
*SmartFile
570 /*****************************************************************************/
580 Main utility entry point.
584 Argc - Standard app entry point args.
585 Argv - Standard app entry point args.
597 INT8 Line
[MAX_LINE_LEN
];
598 INT8 ExpLine
[MAX_LINE_LEN
];
603 COMPONENTS_ITEM
*TempComponents
;
605 SetUtilityName (UTILITY_NAME
);
609 DSCFileInit (&DSCFile
);
611 // Initialize the firmware volume data
615 // Exception handling for this block of code.
619 // Process command-line options.
621 if (ProcessOptions (Argc
, Argv
)) {
622 EMsg
= CatchException ();
624 fprintf (stderr
, "%s\n", EMsg
);
630 // Parse the GUID database file if specified
632 if (gGlobals
.GuidDatabaseFileName
[0] != 0) {
633 ParseGuidDatabaseFile (gGlobals
.GuidDatabaseFileName
);
636 // Set the output cross-reference file if applicable
638 if (gGlobals
.XRefFileName
[0]) {
639 CFVSetXRefFileName (gGlobals
.XRefFileName
);
643 // Now get the EFI_SOURCE directory which we use everywhere.
645 if (GetEfiSource ()) {
650 // Pre-process the DSC file to get section info.
652 if (DSCFileSetFile (&DSCFile
, gGlobals
.DscFilename
) != 0) {
653 goto ProcessingError
;
657 // Set output makefile name for single module build
659 strcpy (gGlobals
.ModuleMakefileName
, MODULE_MAKEFILE_NAME
);
662 // Try to open all final output makefiles
664 if ((gGlobals
.MakefileFptr
= fopen (gGlobals
.MakefileName
, "w")) == NULL
) {
665 Error (NULL
, 0, 0, gGlobals
.MakefileName
, "failed to open output makefile for writing");
666 goto ProcessingError
;
668 if ((gGlobals
.ModuleMakefileFptr
= fopen (gGlobals
.ModuleMakefileName
, "w")) == NULL
) {
669 Error (NULL
, 0, 0, gGlobals
.ModuleMakefileName
, "failed to open output makefile for writing");
670 goto ProcessingError
;
674 // Write the header out to the makefiles
676 for (i
= 0; MakefileHeader
[i
] != NULL
; i
++) {
677 fprintf (gGlobals
.MakefileFptr
, "%s\n", MakefileHeader
[i
]);
678 fprintf (gGlobals
.ModuleMakefileFptr
, "%s\n", MakefileHeader
[i
]);
682 // Init global potint = NULL
684 gGlobals
.ModuleList
= NULL
;
685 gGlobals
.OutdirList
= NULL
;
688 // Process the [defines] section in the DSC file to get any defines we need
691 ProcessDSCDefinesSection (&DSCFile
);
692 if (ExceptionThrown ()) {
693 goto ProcessingError
;
696 // Write out the [makefile.out] section data to the output makefiles
698 Sect
= DSCFileFindSection (&DSCFile
, MAKEFILE_OUT_SECTION_NAME
);
700 while (DSCFileGetLine (&DSCFile
, Line
, sizeof (Line
)) != NULL
) {
701 ExpandSymbols (Line
, ExpLine
, sizeof (ExpLine
), 0);
703 // Write the line to the output makefiles
705 fprintf (gGlobals
.MakefileFptr
, ExpLine
);
706 fprintf (gGlobals
.ModuleMakefileFptr
, ExpLine
);
711 // Add a pseudo target for GLOBAL_LINK_LIB_NAME to avoid single module build
712 // failure when this lib is not used.
714 fprintf (gGlobals
.ModuleMakefileFptr
, "%sbuild ::\n\n", GLOBAL_LINK_LIB_NAME
);
716 fprintf (gGlobals
.MakefileFptr
, "libraries : \n");
718 // Process [libraries] section in the DSC file
720 Sect
= DSCFileFindSection (&DSCFile
, LIBRARIES_SECTION_NAME
);
722 mCurrentBuildList
= &gGlobals
.LibraryList
;
723 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_LIBRARIES
, 0);
726 if (ExceptionThrown ()) {
727 goto ProcessingError
;
730 // Process [libraries.platform] section in the DSC file
732 Sect
= DSCFileFindSection (&DSCFile
, LIBRARIES_PLATFORM_SECTION_NAME
);
734 mCurrentBuildList
= &gGlobals
.LibraryList
;
735 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_PLATFORM_LIBRARIES
, 0);
738 fprintf (gGlobals
.MakefileFptr
, "\n");
739 if (ExceptionThrown ()) {
740 goto ProcessingError
;
744 // Process [components] section in the DSC file
746 Sect
= DSCFileFindSection (&DSCFile
, COMPONENTS_SECTION_NAME
);
748 fprintf (gGlobals
.MakefileFptr
, "components_0 : \n");
749 TempComponents
= AddComponentsItem (&gGlobals
.ComponentsList
);
750 mCurrentBuildList
= &TempComponents
->BuildList
;
751 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_COMPONENTS
, 0);
752 fprintf (gGlobals
.MakefileFptr
, "\n");
755 if (ExceptionThrown ()) {
756 goto ProcessingError
;
759 // Now cycle through all [components.1], [components.2], ....[components.n].
760 // This is necessary to support building of firmware volumes that may contain
761 // other encapsulated firmware volumes (ala capsules).
765 RemoveSymbol (FV
, SYM_GLOBAL
);
766 sprintf (Line
, "%s.%d", COMPONENTS_SECTION_NAME
, i
);
767 Sect
= DSCFileFindSection (&DSCFile
, Line
);
769 fprintf (gGlobals
.MakefileFptr
, "components_%d : \n", i
);
770 TempComponents
= AddComponentsItem (&gGlobals
.ComponentsList
);
771 mCurrentBuildList
= &TempComponents
->BuildList
;
772 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_COMPONENTS
, i
);
773 fprintf (gGlobals
.MakefileFptr
, "\n");
778 if (ExceptionThrown ()) {
779 goto ProcessingError
;
786 EMsg
= CatchException ();
788 fprintf (stderr
, "%s\n", EMsg
);
789 fprintf (stderr
, "Processing aborted\n");
794 // Create the FV files if no fatal errors or errors
796 if (GetUtilityStatus () < STATUS_ERROR
) {
797 CFVWriteInfFiles (&DSCFile
, gGlobals
.MakefileFptr
);
801 // Write all module name into MODULE_NAME_FILE file.
803 if ((FpModule
= fopen (MODULE_NAME_FILE
, "w")) != NULL
) {
804 TempSymbol
= gGlobals
.ModuleList
;
805 while (TempSymbol
!= NULL
) {
806 fprintf (FpModule
, " %-*s %s \n", MODULE_BASE_NAME_WIDTH
, TempSymbol
->Name
, TempSymbol
->Value
);
807 TempSymbol
= TempSymbol
->Next
;
814 // Close the all the output makefiles
816 if (gGlobals
.MakefileFptr
!= NULL
) {
817 fclose (gGlobals
.MakefileFptr
);
818 gGlobals
.MakefileFptr
= NULL
;
821 if (gGlobals
.ModuleMakefileFptr
!= NULL
) {
822 fclose (gGlobals
.ModuleMakefileFptr
);
823 gGlobals
.ModuleMakefileFptr
= NULL
;
827 // Start multi-thread build if ThreadNumber is specified and no error status
829 if ((gGlobals
.ThreadNumber
!= 0) && (GetUtilityStatus () < STATUS_ERROR
)) {
830 BuildDir
= GetSymbolValue (BUILD_DIR
);
831 if (gGlobals
.BuildTarget
& BUILD_TARGET_LIBRARIES
) {
832 if (StartMultiThreadBuild (&gGlobals
.LibraryList
, gGlobals
.ThreadNumber
, BuildDir
) != 0) {
833 Error (NULL
, 0, 0, NULL
, "Multi-thread build libraries failure");
838 TempComponents
= gGlobals
.ComponentsList
;
839 while (TempComponents
!= NULL
) {
840 if (gGlobals
.BuildTarget
& BUILD_TARGET_COMPONENTS
) {
841 if (StartMultiThreadBuild (&TempComponents
->BuildList
, gGlobals
.ThreadNumber
, BuildDir
) != 0) {
842 Error (NULL
, 0, 0, NULL
, "Multi-thread build components %d failure", i
);
846 if (gGlobals
.BuildTarget
& BUILD_TARGET_FVS
) {
847 sprintf (ExpLine
, "nmake -nologo -f %s fvs_%d", gGlobals
.MakefileName
, i
);
849 if (system (ExpLine
)) {
850 Error (NULL
, 0, 0, NULL
, "Build FVs for components %d failure", i
);
855 TempComponents
= TempComponents
->Next
;
863 FreeBuildList (gGlobals
.LibraryList
);
864 gGlobals
.LibraryList
= NULL
;
865 FreeComponentsList (gGlobals
.ComponentsList
);
866 gGlobals
.ComponentsList
= NULL
;
867 FreeSymbols (gGlobals
.ModuleList
);
868 gGlobals
.ModuleList
= NULL
;
869 FreeSymbols (gGlobals
.OutdirList
);
870 gGlobals
.OutdirList
= NULL
;
871 FreeSymbols (gGlobals
.Symbol
);
872 gGlobals
.Symbol
= NULL
;
874 DSCFileDestroy (&DSCFile
);
876 EMsg
= CatchException ();
878 fprintf (stderr
, "%s\n", EMsg
);
879 fprintf (stderr
, "Processing aborted\n");
882 return GetUtilityStatus ();
887 ProcessSectionComponents (
896 Process the [components] or [libraries] section in the description file. We
897 use this function for both since they're very similar. Here we just
898 read each line from the section, and if it's valid, call a function to
899 do the actual processing of the component description file.
903 DSCFile - structure containing section info on the description file
904 DscSectionType - type of description section
912 INT8 Line
[MAX_LINE_LEN
];
913 INT8 Line2
[MAX_EXP_LINE_LEN
];
917 // Read lines while they're valid
919 while (DSCFileGetLine (DSCFile
, Line
, sizeof (Line
)) != NULL
) {
921 // Expand symbols on the line
923 if (ExpandSymbols (Line
, Line2
, sizeof (Line2
), 0)) {
929 Cptr
= StripLine (Line2
);
931 Message (2, "Processing component line: %s", Line2
);
932 if (ProcessComponentFile (DSCFile
, Line2
, DscSectionType
, Instance
) != 0) {
943 ProcessComponentFile (
953 Given a line from the [components] or [libraries] section of the description
954 file, process the line to extract the component's INF filename and
955 parameters. Then open the INF file and process it to create a corresponding
960 DSCFile The project DSC file info structure.
961 Libs Indicates whether we're processing the [components]
962 section or the [libraries] section.
963 ArgLine The actual line from the DSC file. Looks something like
964 one of the following:
966 dxe\drivers\vm\vm.dsc PROCESSOR=IA32 DEST_DIR=$(DEST_DIR)\xxx FV=FV1,FV2
967 $(BUILD_DIR).\FvVariable.ffs COMPONENT_TYPE=FILE
968 .\FvVariable.ffs COMPONENT_TYPE=FILE
969 define VAR1=value1 VAR2=value2
983 INT8 FileName
[MAX_PATH
];
984 INT8 ComponentFilePath
[MAX_PATH
];
985 INT8 InLine
[MAX_LINE_LEN
];
986 INT8 Line
[MAX_LINE_LEN
];
990 int ComponentCreated
;
991 int ComponentFilePathAbsolute
;
993 DSC_FILE ComponentFile
;
994 INT8 ComponentMakefileName
[MAX_PATH
];
998 // Now remove all local symbols
1000 RemoveLocalSymbols ();
1002 // Null out the file pointer in case we take an exception somewhere
1003 // and we need to close it only if we opened it.
1006 ComponentFilePathAbsolute
= 0;
1007 ComponentCreated
= 0;
1009 // Skip preceeding spaces on the line
1011 while (isspace (*ArgLine
) && (*ArgLine
)) {
1015 // Find the end of the component's filename and truncate the line at that
1016 // point. From here on out ArgLine is the name of the component filename.
1019 while (!isspace (*Cptr
) && *Cptr
) {
1029 // Exception-handle processing of this component description file
1034 // We also allow a component line format for defines of global symbols
1035 // instead of a component filename. In this case, the line looks like:
1036 // defines x=abc y=yyy. Be nice and accept "define" and "defines" in a
1037 // case-insensitive manner. If it's defines, then make the symbols global.
1039 if ((_stricmp (ArgLine
, "define") == 0) || (_stricmp (ArgLine
, "defines") == 0)) {
1040 SymType
= SYM_OVERWRITE
| SYM_GLOBAL
;
1043 SymType
= SYM_OVERWRITE
| SYM_LOCAL
;
1047 // The rest of the component line from the DSC file should be defines
1050 End
= StripLine (End
);
1053 // If we're processing a "define abc=1 xyz=2" line, then set symbols
1054 // as globals per the SymType set above.
1056 Len
= AddSymbol (End
, NULL
, SymType
);
1060 Warning (NULL
, 0, 0, ArgLine
, "unrecognized option in description file");
1067 // If DEBUG_BREAK or EFI_BREAKPOINT is defined, then do a debug breakpoint.
1069 if ((GetSymbolValue ("DEBUG_BREAK") != NULL
) || (GetSymbolValue ("EFI_BREAKPOINT") != NULL
)) {
1074 // If it's a define line, then we're done
1078 // If there is NonFFS_FV, create the FVxxx.inf file
1079 // and include it in makefile.out. Remove the symbol
1080 // in order not to process it again next time
1082 Cptr
= GetSymbolValue (NONFFS_FV
);
1084 NonFFSFVWriteInfFiles (DSCFile
, Cptr
);
1085 RemoveSymbol (NONFFS_FV
, SYM_GLOBAL
);
1092 // Expand symbols in the component description filename to expand the newly
1093 // added local symbols
1095 ExpandSymbols (ArgLine
, Line
, sizeof (Line
), EXPANDMODE_NO_UNDEFS
);
1098 // If we have "c:\path\filename"
1100 ReplaceSlash (Line
);
1101 if (IsAbsolutePath (Line
)) {
1102 ComponentFilePathAbsolute
= 1;
1103 } else if (Line
[0] == '.') {
1105 // or if the path starts with ".", then it's build-dir relative.
1106 // Prepend $(BUILD_DIR) on the file name
1108 sprintf (InLine
, "%s\\%s", GetSymbolValue (BUILD_DIR
), Line
);
1109 strcpy (Line
, InLine
);
1110 ComponentFilePathAbsolute
= 1;
1114 // Save the path from the component name for later. It may be relative or
1117 strcpy (ComponentFilePath
, Line
);
1118 Cptr
= ComponentFilePath
+ strlen (ComponentFilePath
) - 1;
1119 while ((*Cptr
!= '\\') && (Cptr
!= ComponentFilePath
)) {
1123 // Terminate the path.
1128 // Typically the given line is a component description filename. However we
1129 // also allow a FV filename (fvvariable.ffs COMPONENT_TYPE=FILE). If the
1130 // component type is "FILE", then add it to the FV list, create a package
1131 // file, and we're done.
1133 Cptr
= GetSymbolValue (COMPONENT_TYPE
);
1134 if ((Cptr
!= NULL
) && (strncmp (
1136 COMPONENT_TYPE_FILE
,
1137 strlen (COMPONENT_TYPE_FILE
)
1139 if (ComponentFilePathAbsolute
) {
1140 strcpy (InLine
, Line
);
1142 sprintf (InLine
, "%s\\%s", GetSymbolValue (EFI_SOURCE
), Line
);
1147 GetSymbolValue (FV
),
1151 GetSymbolValue (APRIORI
),
1159 // Better have defined processor by this point.
1161 Processor
= GetSymbolValue (PROCESSOR
);
1162 if (Processor
== NULL
) {
1163 Error (NULL
, 0, 0, NULL
, "PROCESSOR not defined for component %s", Line
);
1164 return STATUS_ERROR
;
1168 // The bin, out, and lib dirs are now = $(BUILD_DIR)/$(PROCESSOR). Set them.
1169 // Don't flag them as file paths (required for short 8.3 filenames) since
1170 // they're defined using the BUILD_DIR macro.
1172 sprintf (InLine
, "$(BUILD_DIR)\\%s", Processor
);
1173 AddSymbol (BIN_DIR
, InLine
, SYM_LOCAL
);
1174 AddSymbol (OUT_DIR
, InLine
, SYM_LOCAL
);
1175 AddSymbol (LIB_DIR
, InLine
, SYM_LOCAL
);
1177 // See if it's been destined for an FV. It's possible to not be in an
1178 // FV if they just want to build it.
1180 Cptr
= GetSymbolValue (FV
);
1181 if ((Cptr
!= NULL
) && !IS_NULL_SYMBOL_VALUE (Cptr
)) {
1187 // As an optimization, if they've defined SKIP_FV_NULL as non-zero, and
1188 // the component is not destined for an FV, then skip it.
1189 // Since libraries are never intended for firmware volumes, we have to
1190 // build all of them.
1192 if ((DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) && (IsForFv
== FALSE
)) {
1193 if ((GetSymbolValue (SKIP_FV_NULL
) != NULL
) && (atoi (GetSymbolValue (SKIP_FV_NULL
)) != 0)) {
1194 Message (0, "%s not being built (FV=NULL)", FileName
);
1199 // Prepend EFI_SOURCE to the component description file to get the
1200 // full path. Only do this if the path is not a full path already.
1202 if (ComponentFilePathAbsolute
== 0) {
1203 name
= GetSymbolValue (EFI_SOURCE
);
1204 sprintf (FileName
, "%s\\%s", name
, Line
);
1206 strcpy (FileName
, Line
);
1209 // Print a message, depending on verbose level.
1211 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1212 Message (1, "Processing component %s", FileName
);
1214 Message (1, "Processing library %s", FileName
);
1217 // Open the component's description file and get the sections. If we fail
1218 // to open it, see if they defined "OPTIONAL=1, in which case we'll just
1219 // ignore the component.
1221 TempFptr
= fopen (FileName
, "r");
1222 if (TempFptr
== NULL
) {
1224 // Better have defined OPTIONAL
1226 if (GetSymbolValue (OPTIONAL_COMPONENT
) != NULL
) {
1227 if (atoi (GetSymbolValue (OPTIONAL_COMPONENT
)) != 0) {
1228 Message (0, "Optional component '%s' not found", FileName
);
1233 ParserError (0, FileName
, "failed to open component file");
1234 return STATUS_ERROR
;
1239 DSCFileInit (&ComponentFile
);
1240 ComponentCreated
= 1;
1241 if (DSCFileSetFile (&ComponentFile
, FileName
)) {
1242 Error (NULL
, 0, 0, NULL
, "failed to preprocess component file '%s'", FileName
);
1243 return STATUS_ERROR
;
1246 // Add a symbol for the INF filename so users can create dependencies
1249 AddSymbol (INF_FILENAME
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILENAME
);
1251 // Process the [defines], [defines.$(PROCESSOR)], and [defines.$(PROCESSOR).$(PLATFORM)]
1252 // sections in the INF file
1254 ProcessINFDefinesSection (&ComponentFile
);
1256 // Better have defined FILE_GUID if not a library
1258 if ((GetSymbolValue (GUID
) == NULL
) &&
1259 (GetSymbolValue (FILE_GUID
) == NULL
) &&
1260 (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
)
1262 Error (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "missing FILE_GUID definition in component file");
1263 DSCFileDestroy (&ComponentFile
);
1264 return STATUS_ERROR
;
1267 // Better have defined base name
1269 if (GetSymbolValue (BASE_NAME
) == NULL
) {
1270 Error (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "missing BASE_NAME definition in INF file");
1271 DSCFileDestroy (&ComponentFile
);
1272 return STATUS_ERROR
;
1275 // Better have defined COMPONENT_TYPE, since it's used to find named sections.
1277 if (GetSymbolValue (COMPONENT_TYPE
) == NULL
) {
1278 Error (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "missing COMPONENT_TYPE definition in INF file");
1279 DSCFileDestroy (&ComponentFile
);
1280 return STATUS_ERROR
;
1284 // Create the source directory path from the component file's path. If the component
1285 // file's path is absolute, we may have problems here. Try to account for it though.
1287 if (ComponentFilePathAbsolute
== 0) {
1291 GetSymbolValue (EFI_SOURCE
),
1295 strcpy (FileName
, ComponentFilePath
);
1297 AddSymbol (SOURCE_DIR
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILEPATH
);
1300 // Create the destination path.
1301 // They may have defined DEST_DIR on the component INF line, so it's already
1302 // been defined, If that's the case, then don't set it to the path of this file.
1304 TempCptr
= GetSymbolValue (DEST_DIR
);
1305 if (TempCptr
== NULL
) {
1306 if (ComponentFilePathAbsolute
== 0) {
1308 // The destination path is $(BUILD_DIR)\$(PROCESSOR)\component_path
1313 GetSymbolValue (BUILD_DIR
),
1319 // The destination path is $(BUILD_DIR)\$(PROCESSOR)\$(BASE_NAME)
1324 GetSymbolValue (BUILD_DIR
),
1326 GetSymbolValue (BASE_NAME
)
1329 AddSymbol (DEST_DIR
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILEPATH
);
1331 ReplaceSlash (TempCptr
);
1335 // Create the output directory, then open the output component's makefile
1336 // we're going to create. Allow them to override the makefile name.
1338 TempCptr
= GetSymbolValue (MAKEFILE_NAME
);
1339 if (TempCptr
!= NULL
) {
1340 ExpandSymbols (TempCptr
, ComponentMakefileName
, sizeof (ComponentMakefileName
), EXPANDMODE_NO_UNDEFS
);
1341 TempCptr
= ComponentMakefileName
;
1343 TempCptr
= "makefile";
1346 sprintf (FileName
, "%s\\%s", GetSymbolValue (DEST_DIR
), TempCptr
);
1348 // Save it now with path info
1350 AddSymbol (MAKEFILE_NAME
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILENAME
);
1352 if (MakeFilePath (FileName
)) {
1353 return STATUS_ERROR
;
1356 if ((MakeFptr
= fopen (FileName
, "w")) == NULL
) {
1357 Error (NULL
, 0, 0, FileName
, "could not create makefile");
1358 return STATUS_ERROR
;
1361 // At this point we should have all the info we need to create a package
1362 // file if setup to do so. Libraries don't use package files, so
1363 // don't do this for libs.
1365 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1366 CreatePackageFile (DSCFile
);
1370 // Add a new build item to mCurrentBuildList
1372 mCurrentBuildItem
= AddBuildItem (mCurrentBuildList
, GetSymbolValue (BASE_NAME
), Processor
, FileName
);
1374 // ProcessDsc allows duplicate base name libraries. Make sure the duplicate
1375 // base name libraries will be built in the same order as listed in DSC file.
1377 AddDependency (*mCurrentBuildList
, mCurrentBuildItem
, mCurrentBuildItem
->BaseName
, 1);
1380 // Add Module name to the global module list
1382 AddModuleName (&gGlobals
.ModuleList
, GetSymbolValue (BASE_NAME
), GetSymbolValue (INF_FILENAME
));
1384 // Write an nmake line to makefile.out
1386 fprintf (gGlobals
.MakefileFptr
, " @cd %s\n", Processor
);
1387 fprintf (gGlobals
.MakefileFptr
, " $(MAKE) -f %s all\n", FileName
);
1388 fprintf (gGlobals
.MakefileFptr
, " @cd ..\n");
1391 // Copy the common makefile section from the description file to
1392 // the component's makefile
1394 WriteCommonMakefile (DSCFile
, MakeFptr
, Processor
);
1396 // Process the component's [nmake.common] and [nmake.$(PROCESSOR)] sections
1398 ProcessINFNMakeSection (&ComponentFile
, MakeFptr
);
1400 // Create the SOURCE_FILES macro that includes the names of all source
1401 // files in this component. This macro can then be used elsewhere to
1402 // process all the files making up the component. Required for scanning
1403 // files for string localization.
1404 // Also add source files to mCurrentBuildItem.
1406 ProcessSourceFiles (DSCFile
, &ComponentFile
, MakeFptr
, SOURCE_MODE_SOURCE_FILES
);
1408 // Create the include paths. Process [includes.common] and
1409 // [includes.$(PROCESSOR)] and [includes.$(PROCESSOR).$(PLATFORM)] sections.
1411 ProcessIncludesSection (&ComponentFile
, MakeFptr
);
1413 // Process all include source files to create a dependency list that can
1414 // be used in the makefile.
1416 ProcessIncludeFiles (&ComponentFile
, MakeFptr
);
1418 // Process the [sources.common], [sources.$(PROCESSOR)], and
1419 // [sources.$(PROCESSOR).$(PLATFORM)] files and emit their build commands
1421 ProcessSourceFiles (DSCFile
, &ComponentFile
, MakeFptr
, SOURCE_MODE_BUILD_COMMANDS
);
1423 // Process sources again to create an OBJECTS macro
1425 ProcessObjects (&ComponentFile
, MakeFptr
);
1428 // Add Single Module target : build and clean in top level makefile
1430 fprintf (gGlobals
.ModuleMakefileFptr
, "%sbuild ::", GetSymbolValue (BASE_NAME
));
1431 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1432 fprintf (gGlobals
.ModuleMakefileFptr
, " %sbuild", GLOBAL_LINK_LIB_NAME
);
1436 // Process all the libraries to define "LIBS = x.lib y.lib..."
1437 // Be generous and append ".lib" if they forgot.
1438 // Make a macro definition: LIBS = $(LIBS) xlib.lib ylib.lib...
1439 // Add libs dependency for single module build: basenamebuild :: xlibbuild ylibbuild ...
1440 // Also add libs dependency to mCurrentBuildItem.
1442 ProcessLibs (&ComponentFile
, MakeFptr
);
1444 fprintf (gGlobals
.ModuleMakefileFptr
, "\n");
1446 fprintf (gGlobals
.ModuleMakefileFptr
, " @cd %s\n", Processor
);
1447 fprintf (gGlobals
.ModuleMakefileFptr
, " $(MAKE) -f %s all\n", FileName
);
1448 fprintf (gGlobals
.ModuleMakefileFptr
, " @cd ..\n\n");
1450 fprintf (gGlobals
.ModuleMakefileFptr
, "%sclean ::\n", GetSymbolValue (BASE_NAME
));
1451 fprintf (gGlobals
.ModuleMakefileFptr
, " $(MAKE) -f %s clean\n\n", FileName
);
1454 // Emit commands to create the component. These are simply copied from
1455 // the description file to the component's makefile. First look for
1456 // [build.$(PROCESSOR).$(BUILD_TYPE)]. If not found, then look for if
1457 // find a [build.$(PROCESSOR).$(COMPONENT_TYPE)] line.
1459 Cptr
= GetSymbolValue (BUILD_TYPE
);
1461 sprintf (InLine
, "build.%s.%s", Processor
, Cptr
);
1462 WriteComponentTypeBuildCommands (DSCFile
, MakeFptr
, InLine
);
1464 sprintf (InLine
, "build.%s.%s", Processor
, GetSymbolValue (COMPONENT_TYPE
));
1465 WriteComponentTypeBuildCommands (DSCFile
, MakeFptr
, InLine
);
1468 // Add it to the FV if not a library
1470 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1472 // Create the FV filename and add it to the FV.
1473 // By this point we know it's in FV.
1475 Cptr
= GetSymbolValue (FILE_GUID
);
1477 Cptr
= GetSymbolValue (GUID
);
1480 sprintf (InLine
, "%s-%s", Cptr
, GetSymbolValue (BASE_NAME
));
1482 // We've deprecated FV_EXT, which should be FFS_EXT, the extension
1483 // of the FFS file generated by GenFFSFile.
1485 TempCptr
= GetSymbolValue (FFS_EXT
);
1486 if (TempCptr
== NULL
) {
1487 TempCptr
= GetSymbolValue ("FV_EXT");
1492 GetSymbolValue (COMPONENT_TYPE
),
1493 GetSymbolValue (FV
),
1497 GetSymbolValue (APRIORI
),
1498 GetSymbolValue (BASE_NAME
),
1503 // Catch any failures and print the name of the component file
1504 // being processed to assist debugging.
1508 Cptr
= CatchException ();
1510 fprintf (stderr
, "%s\n", Cptr
);
1511 sprintf (InLine
, "Processing of component %s failed", ArgLine
);
1512 ThrowException (InLine
);
1515 if (MakeFptr
!= NULL
) {
1519 if (ComponentCreated
) {
1520 DSCFileDestroy (&ComponentFile
);
1523 return STATUS_SUCCESS
;
1534 INT8 Str
[MAX_LINE_LEN
];
1535 INT8 StrExpanded
[MAX_LINE_LEN
];
1536 SMART_FILE
*PkgFptr
;
1542 // First find out if PACKAGE_FILENAME or PACKAGE is defined. PACKAGE_FILENAME
1543 // is used to specify the exact package file to use. PACKAGE is used to
1544 // specify the package section name.
1546 Package
= GetSymbolValue (PACKAGE_FILENAME
);
1547 if (Package
!= NULL
) {
1549 // Use existing file. We're done.
1551 return STATUS_SUCCESS
;
1554 // See if PACKAGE or PACKAGE_TAG is defined
1556 Package
= GetSymbolValue (PACKAGE
);
1557 if (Package
== NULL
) {
1558 Package
= GetSymbolValue (PACKAGE_TAG
);
1561 if (Package
== NULL
) {
1563 // Not defined either. Assume they are not using the package functionality
1564 // of this utility. However define the PACKAGE_FILENAME macro to the
1565 // best-guess value.
1570 GetSymbolValue (SOURCE_DIR
),
1571 GetSymbolValue (BASE_NAME
)
1575 // Expand symbols in the package filename
1577 ExpandSymbols (Str
, StrExpanded
, sizeof (StrExpanded
), EXPANDMODE_NO_UNDEFS
);
1579 AddSymbol (PACKAGE_FILENAME
, StrExpanded
, SYM_LOCAL
| SYM_FILENAME
);
1580 return STATUS_SUCCESS
;
1583 // Save the position in the DSC file.
1584 // Find the [package.$(COMPONENT_TYPE).$(PACKAGE)] section in the DSC file
1586 Status
= STATUS_SUCCESS
;
1587 DSCFileSavePosition (DSCFile
);
1588 sprintf (Str
, "%s.%s.%s", PACKAGE
, GetSymbolValue (COMPONENT_TYPE
), Package
);
1589 TempSect
= DSCFileFindSection (DSCFile
, Str
);
1590 if (TempSect
!= NULL
) {
1592 // So far so good. Create the name of the package file, then open it up
1593 // for writing. File name is c:\...\oem\platform\nt32\ia32\...\BaseName.pkg.
1598 GetSymbolValue (DEST_DIR
),
1599 GetSymbolValue (BASE_NAME
)
1603 // Expand symbols in the package filename
1605 ExpandSymbols (Str
, StrExpanded
, sizeof (StrExpanded
), EXPANDMODE_NO_UNDEFS
);
1608 // Try to open the file, then save the file name as the PACKAGE_FILENAME
1609 // symbol for use elsewhere.
1611 if ((PkgFptr
= SmartOpen (StrExpanded
)) == NULL
) {
1612 Error (NULL
, 0, 0, Str
, "could not open package file for writing");
1613 Status
= STATUS_ERROR
;
1617 AddSymbol (PACKAGE_FILENAME
, StrExpanded
, SYM_LOCAL
| SYM_FILENAME
);
1619 // Now read lines in from the DSC file and write them back out to the
1620 // package file (with string substitution).
1622 while (DSCFileGetLine (DSCFile
, Str
, sizeof (Str
)) != NULL
) {
1624 // Expand symbols, then write the line out to the package file
1626 ExpandSymbols (Str
, StrExpanded
, sizeof (StrExpanded
), EXPANDMODE_RECURSIVE
);
1627 SmartWrite (PkgFptr
, StrExpanded
);
1635 "cannot locate package section [%s] in DSC file for %s",
1637 GetSymbolValue (INF_FILENAME
)
1639 Status
= STATUS_WARNING
;
1643 if (PkgFptr
!= NULL
) {
1644 SmartClose (PkgFptr
);
1649 // Restore the position in the DSC file
1651 DSCFileRestorePosition (DSCFile
);
1653 return STATUS_SUCCESS
;
1658 ProcessINFDefinesSection (
1659 DSC_FILE
*ComponentFile
1663 Routine Description:
1665 Process the [defines.xxx] sections of the component description file. Process
1666 platform first, then processor. In this way, if a platform wants and override,
1667 that one gets parsed first, and later assignments do not overwrite the value.
1671 ComponentFile - section info on the component file being processed
1679 INT8 Str
[MAX_LINE_LEN
];
1682 // Find a [defines.$(PROCESSOR).$(PLATFORM)] section and process it
1684 Cptr
= GetSymbolValue (PLATFORM
);
1689 DEFINES_SECTION_NAME
,
1690 GetSymbolValue (PROCESSOR
),
1693 ProcessINFDefinesSectionSingle (ComponentFile
, Str
);
1696 // Find a [defines.$(PROCESSOR)] section and process it
1698 sprintf (Str
, "%s.%s", DEFINES_SECTION_NAME
, GetSymbolValue (PROCESSOR
));
1699 ProcessINFDefinesSectionSingle (ComponentFile
, Str
);
1702 // Find a [defines] section and process it
1704 if (ProcessINFDefinesSectionSingle (ComponentFile
, DEFINES_SECTION_NAME
) != STATUS_SUCCESS
) {
1705 Error (NULL
, 0, 0, NULL
, "missing [defines] section in component file %s", GetSymbolValue (INF_FILENAME
));
1706 return STATUS_ERROR
;
1709 return STATUS_SUCCESS
;
1714 ProcessINFDefinesSectionSingle (
1715 DSC_FILE
*ComponentFile
,
1720 INT8 Str
[MAX_LINE_LEN
];
1721 INT8 ExpandedLine
[MAX_LINE_LEN
];
1724 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
1725 if (TempSect
!= NULL
) {
1726 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1727 ExpandSymbols (Str
, ExpandedLine
, sizeof (ExpandedLine
), 0);
1728 Cptr
= StripLine (ExpandedLine
);
1730 // Don't process blank lines.
1734 // Add without overwriting macros specified on the component line
1735 // in the description file
1737 AddSymbol (Cptr
, NULL
, SYM_LOCAL
);
1741 return STATUS_WARNING
;
1744 return STATUS_SUCCESS
;
1749 ProcessINFNMakeSection (
1750 DSC_FILE
*ComponentFile
,
1755 Routine Description:
1757 Process the [nmake.common] and [nmake.$(PROCESSOR)] sections of the component
1758 description file and write and copy them to the component's makefile.
1762 ComponentFile - section info on the component file being processed
1763 MakeFptr - file pointer to the component' makefile we're creating
1767 Always STATUS_SUCCESS right now, since the sections are optional.
1772 INT8 Str
[MAX_LINE_LEN
];
1773 INT8 ExpandedLine
[MAX_LINE_LEN
];
1777 // Copy the [nmake.common] and [nmake.$(PROCESSOR)] sections from the
1778 // component file directly to the output file.
1779 // The line will be stripped and don't print blank lines
1781 sprintf (Str
, "%s.%s", NMAKE_SECTION_NAME
, COMMON_SECTION_NAME
);
1782 TempSect
= DSCFileFindSection (ComponentFile
, Str
);
1783 if (TempSect
!= NULL
) {
1784 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1788 sizeof (ExpandedLine
),
1789 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
1791 Cptr
= StripLine (ExpandedLine
);
1793 fprintf (MakeFptr
, "%s\n", Cptr
);
1797 fprintf (MakeFptr
, "\n");
1799 Error (GetSymbolValue (INF_FILENAME
), 1, 0, Str
, "section not found in component INF file");
1802 sprintf (Str
, "%s.%s", NMAKE_SECTION_NAME
, GetSymbolValue (PROCESSOR
));
1803 TempSect
= DSCFileFindSection (ComponentFile
, Str
);
1804 if (TempSect
!= NULL
) {
1805 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1809 sizeof (ExpandedLine
),
1810 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
1812 Cptr
= StripLine (ExpandedLine
);
1814 fprintf (MakeFptr
, "%s\n", Cptr
);
1818 fprintf (MakeFptr
, "\n");
1821 // Do the same for [nmake.$(PROCESSOR).$(PLATFORM)]
1823 Cptr
= GetSymbolValue (PLATFORM
);
1825 sprintf (Str
, "%s.%s.%s", NMAKE_SECTION_NAME
, GetSymbolValue (PROCESSOR
), Cptr
);
1826 TempSect
= DSCFileFindSection (ComponentFile
, Str
);
1827 if (TempSect
!= NULL
) {
1828 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1832 sizeof (ExpandedLine
),
1833 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
1835 Cptr
= StripLine (ExpandedLine
);
1837 fprintf (MakeFptr
, "%s\n", Cptr
);
1841 fprintf (MakeFptr
, "\n");
1845 return STATUS_SUCCESS
;
1850 ProcessIncludesSection (
1851 DSC_FILE
*ComponentFile
,
1856 Routine Description:
1858 Process the [includes.common], [includes.processor], and
1859 [includes.processor.platform] section of the component description file
1860 and write the appropriate macros to the component's makefile.
1862 Process in reverse order to allow overrides on platform basis.
1866 ComponentFile - section info on the component file being processed
1867 MakeFptr - file pointer to the component' makefile we're creating
1871 Always STATUS_SUCCESS right now, since the sections are optional.
1876 INT8 Str
[MAX_LINE_LEN
];
1881 // Write a useful comment to the output makefile so the user knows where
1882 // the data came from.
1884 fprintf (MakeFptr
, "#\n# Tool-generated list of include paths that are created\n");
1885 fprintf (MakeFptr
, "# from the list of include paths in the [includes.*] sections\n");
1886 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
1889 // We use this a lot here, so get the value only once.
1891 Processor
= GetSymbolValue (PROCESSOR
);
1893 // If they're using an override source path, then add OverridePath and
1894 // OverridePath\$(PROCESSOR) to the list of include paths.
1896 OverridePath
= GetSymbolValue (SOURCE_OVERRIDE_PATH
);
1897 if (OverridePath
!= NULL
) {
1898 ReplaceSlash (OverridePath
);
1899 fprintf (MakeFptr
, "!IF EXIST(%s)\n", OverridePath
);
1900 fprintf (MakeFptr
, "INC = $(INC) -I %s\n", OverridePath
);
1901 fprintf (MakeFptr
, "!IF EXIST(%s\\%s)\n", OverridePath
, Processor
);
1902 fprintf (MakeFptr
, "INC = $(INC) -I %s\\%s\n", OverridePath
, Processor
);
1903 fprintf (MakeFptr
, "!ENDIF\n");
1904 fprintf (MakeFptr
, "!ELSE\n");
1905 fprintf (MakeFptr
, "!MESSAGE Warning: include dir %s does not exist\n", OverridePath
);
1906 fprintf (MakeFptr
, "!ENDIF\n");
1909 // Try for an [includes.$(PROCESSOR).$(PLATFORM)]
1911 Cptr
= GetSymbolValue (PLATFORM
);
1913 sprintf (Str
, "%s.%s.%s", INCLUDE_SECTION_NAME
, Processor
, Cptr
);
1914 ProcessIncludesSectionSingle (ComponentFile
, MakeFptr
, Str
);
1917 // Now the [includes.$(PROCESSOR)] section
1919 sprintf (Str
, "%s.%s", INCLUDE_SECTION_NAME
, Processor
);
1920 ProcessIncludesSectionSingle (ComponentFile
, MakeFptr
, Str
);
1923 // Now the [includes.common] section
1925 sprintf (Str
, "%s.%s", INCLUDE_SECTION_NAME
, COMMON_SECTION_NAME
);
1926 ProcessIncludesSectionSingle (ComponentFile
, MakeFptr
, Str
);
1931 fprintf (MakeFptr
, "\n");
1932 return STATUS_SUCCESS
;
1935 // Process one of the [includes.xxx] sections to create a list of all
1936 // the include paths.
1940 ProcessIncludesSectionSingle (
1941 DSC_FILE
*ComponentFile
,
1948 INT8 Str
[MAX_LINE_LEN
];
1949 INT8 ExpandedLine
[MAX_LINE_LEN
];
1952 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
1953 if (TempSect
!= NULL
) {
1955 // Add processor subdirectory on every include path
1957 Processor
= GetSymbolValue (PROCESSOR
);
1959 // Copy lines directly
1961 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1962 ExpandSymbols (Str
, ExpandedLine
, sizeof (ExpandedLine
), 0);
1963 Cptr
= StripLine (ExpandedLine
);
1965 // Don't process blank lines
1968 ReplaceSlash (Cptr
);
1970 // Strip off trailing slash
1972 if (Cptr
[strlen (Cptr
) - 1] == '\\') {
1973 Cptr
[strlen (Cptr
) - 1] = 0;
1976 // Special case of ".". Replace it with source path
1977 // and the rest of the line (for .\$(PROCESSOR))
1981 // Handle case of just a "."
1984 fprintf (MakeFptr
, "INC = $(INC) -I $(SOURCE_DIR)\n");
1985 fprintf (MakeFptr
, "!IF EXIST($(SOURCE_DIR)\\%s)\n", Processor
);
1986 fprintf (MakeFptr
, "INC = $(INC) -I $(SOURCE_DIR)\\%s\n", Processor
);
1987 fprintf (MakeFptr
, "!ENDIF\n");
1990 // Handle case of ".\path\path\path" or "..\path\path\path"
1992 fprintf (MakeFptr
, "!IF EXIST($(SOURCE_DIR)\\%s)\n", Cptr
);
1993 fprintf (MakeFptr
, "INC = $(INC) -I $(SOURCE_DIR)\\%s\n", Cptr
);
1994 fprintf (MakeFptr
, "!IF EXIST($(SOURCE_DIR)\\%s\\%s)\n", Cptr
, Processor
);
1995 fprintf (MakeFptr
, "INC = $(INC) -I $(SOURCE_DIR)\\%s\\%s\n", Cptr
, Processor
);
1996 fprintf (MakeFptr
, "!ENDIF\n");
1997 fprintf (MakeFptr
, "!ELSE\n");
1998 fprintf (MakeFptr
, "!MESSAGE Warning: include dir $(SOURCE_DIR)\\%s does not exist\n", Cptr
);
1999 fprintf (MakeFptr
, "!ENDIF\n");
2001 } else if ((Cptr
[1] != ':') && isalpha (*Cptr
)) {
2002 fprintf (MakeFptr
, "!IF EXIST($(EFI_SOURCE)\\%s)\n", Cptr
);
2003 fprintf (MakeFptr
, "INC = $(INC) -I $(EFI_SOURCE)\\%s\n", Cptr
);
2004 fprintf (MakeFptr
, "!IF EXIST($(EFI_SOURCE)\\%s\\%s)\n", Cptr
, Processor
);
2005 fprintf (MakeFptr
, "INC = $(INC) -I $(EFI_SOURCE)\\%s\\%s\n", Cptr
, Processor
);
2006 fprintf (MakeFptr
, "!ENDIF\n");
2007 fprintf (MakeFptr
, "!ELSE\n");
2008 fprintf (MakeFptr
, "!MESSAGE Warning: include dir $(EFI_SOURCE)\\%s does not exist\n", Cptr
);
2009 fprintf (MakeFptr
, "!ENDIF\n");
2012 // The line is something like: $(EFI_SOURCE)\dxe\include. Add it to
2013 // the existing $(INC) definition. Add user includes before any
2014 // other existing paths.
2016 fprintf (MakeFptr
, "!IF EXIST(%s)\n", Cptr
);
2017 fprintf (MakeFptr
, "INC = $(INC) -I %s\n", Cptr
);
2018 fprintf (MakeFptr
, "!IF EXIST(%s\\%s)\n", Cptr
, Processor
);
2019 fprintf (MakeFptr
, "INC = $(INC) -I %s\\%s\n", Cptr
, Processor
);
2020 fprintf (MakeFptr
, "!ENDIF\n");
2021 fprintf (MakeFptr
, "!ELSE\n");
2022 fprintf (MakeFptr
, "!MESSAGE Warning: include dir %s does not exist\n", Cptr
);
2023 fprintf (MakeFptr
, "!ENDIF\n");
2029 return STATUS_SUCCESS
;
2034 ProcessSourceFiles (
2036 DSC_FILE
*ComponentFile
,
2042 Routine Description:
2044 Process the [sources.common], [sources.$(PROCESSOR)], and
2045 [sources.$(PROCESSOR).$(PLATFORM] sections of the component
2046 description file and write the appropriate build commands out to the
2047 component's makefile. If $(SOURCE_SELECT) is defined, then it overrides
2048 the source selections. We use this functionality for SMM.
2052 ComponentFile - section info on the component file being processed
2053 MakeFptr - file pointer to the component' makefile we're creating
2054 DSCFile - section info on the description file we're processing
2055 Mode - to write build commands, or just create a list
2060 Always STATUS_SUCCESS right now, since the sections are optional.
2064 INT8 Str
[MAX_LINE_LEN
];
2071 INT8
*CopySourceSelect
;
2073 if (Mode
& SOURCE_MODE_SOURCE_FILES
) {
2075 // Write a useful comment to the output makefile so the user knows where
2076 // the data came from.
2078 fprintf (MakeFptr
, "#\n# Tool-generated list of source files that are created\n");
2079 fprintf (MakeFptr
, "# from the list of source files in the [sources.*] sections\n");
2080 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2084 // We use this a lot here, so get the value only once.
2086 Processor
= GetSymbolValue (PROCESSOR
);
2088 // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll
2089 // select each [sources.xxx] and [sources.yyy] files and process
2092 SourceSelect
= GetSymbolValue (SOURCE_SELECT
);
2094 if (SourceSelect
!= NULL
) {
2096 // Make a copy of the string and break it up (comma-separated) and
2097 // select each [sources.*] file from the INF.
2099 CopySourceSelect
= (INT8
*) malloc (strlen (SourceSelect
) + 1);
2100 if (CopySourceSelect
== NULL
) {
2101 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2102 return STATUS_ERROR
;
2105 strcpy (CopySourceSelect
, SourceSelect
);
2106 CStart
= CopySourceSelect
;
2110 while (*CEnd
&& *CEnd
!= ',') {
2116 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, CStart
);
2117 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2119 // Restore the terminator and advance
2128 free (CopySourceSelect
);
2132 // Process all the [sources.common] source files to make them build
2134 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, COMMON_SECTION_NAME
);
2135 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2137 // Now process the [sources.$(PROCESSOR)] files.
2139 sprintf (Str
, "sources.%s", Processor
);
2140 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2142 // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files.
2144 Platform
= GetSymbolValue (PLATFORM
);
2145 if (Platform
!= NULL
) {
2146 sprintf (Str
, "sources.%s.%s", Processor
, Platform
);
2147 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2151 fprintf (MakeFptr
, "\n");
2152 return STATUS_SUCCESS
;
2157 Routine Description:
2158 Given a source file line from an INF file, parse it to see if there are
2159 any defines on it. If so, then add them to the symbol table.
2160 Also, terminate the line after the file name.
2163 SourceFileLine - a line from a [sources.?] section of the INF file. Likely
2166 MySourceFile.c BUILT_NAME=$(BUILD_DIR)\MySourceFile.obj
2175 INT8
*SourceFileLine
2182 for (; *SourceFileLine
&& isspace (*SourceFileLine
); SourceFileLine
++)
2184 for (; *SourceFileLine
&& !isspace (*SourceFileLine
); SourceFileLine
++)
2186 if (*SourceFileLine
) {
2187 *SourceFileLine
= 0;
2190 // AddSymbol() will parse it for us, and return the length. Keep calling
2191 // it until it reports an error or is done.
2194 Len
= AddSymbol (SourceFileLine
, NULL
, SYM_FILE
);
2195 SourceFileLine
+= Len
;
2200 // Process a single section of source files in the component INF file
2204 ProcessSourceFilesSection (
2206 DSC_FILE
*ComponentFile
,
2213 INT8 FileName
[MAX_EXP_LINE_LEN
];
2214 INT8 FilePath
[MAX_PATH
];
2215 INT8 TempFileName
[MAX_PATH
];
2217 INT8 Str
[MAX_LINE_LEN
];
2222 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2223 if (TempSect
!= NULL
) {
2224 Processor
= GetSymbolValue (PROCESSOR
);
2225 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2226 Cptr
= StripLine (Str
);
2228 // Don't process blank lines
2232 // Expand symbols in the filename, then parse the line for symbol
2233 // definitions. AddFileSymbols() will null-terminate the line
2234 // after the file name. Save a copy for override purposes, in which
2235 // case we'll need to know the file name and path (in case it's in
2238 ExpandSymbols (Cptr
, FileName
, sizeof (FileName
), 0);
2239 AddFileSymbols (FileName
);
2240 ReplaceSlash (FileName
);
2242 // Set the SOURCE_FILE_NAME symbol. What we have now is the name of
2243 // the file, relative to the location of the INF file. So prepend
2244 // $(SOURCE_DIR) to it first.
2246 if (IsAbsolutePath (FileName
)) {
2247 strcpy (TempFileName
, FileName
);
2249 strcpy (TempFileName
, "$(SOURCE_DIR)\\");
2250 strcat (TempFileName
, FileName
);
2252 AddSymbol (SOURCE_FILE_NAME
, TempFileName
, SYM_FILE
| SYM_OVERWRITE
);
2254 // Extract path information from the source file and set internal
2255 // variable SOURCE_RELATIVE_PATH. Only do this if the path
2256 // contains a backslash.
2258 strcpy (FilePath
, FileName
);
2259 for (Cptr
= FilePath
+ strlen (FilePath
) - 1; (Cptr
> FilePath
) && (*Cptr
!= '\\'); Cptr
--)
2261 if (*Cptr
== '\\') {
2263 AddSymbol (SOURCE_RELATIVE_PATH
, FilePath
, SYM_FILE
);
2266 // Define another internal symbol for the name of the file without
2267 // the path and extension.
2269 for (Cptr
= FileName
+ strlen (FileName
) - 1; (Cptr
> FileName
) && (*Cptr
!= '\\'); Cptr
--)
2271 if (*Cptr
== '\\') {
2275 strcpy (FilePath
, Cptr
);
2277 // We now have a file name with no path information. Before we do anything else,
2278 // see if OVERRIDE_PATH is set, and if so, see if file $(OVERRIDE_PATH)FileName
2279 // exists. If it does, then recursive call this function to use the override file
2280 // instead of the one from the INF file.
2282 if (IsAbsolutePath (FileName
)) {
2283 OverridePath
= NULL
;
2285 OverridePath
= GetSymbolValue (SOURCE_OVERRIDE_PATH
);
2287 if (OverridePath
!= NULL
) {
2288 ReplaceSlash (OverridePath
);
2290 // See if the file exists. If it does, reset the SOURCE_FILE_NAME symbol.
2292 strcpy (TempFileName
, OverridePath
);
2293 strcat (TempFileName
, "\\");
2294 strcat (TempFileName
, FileName
);
2295 if ((FPtr
= fopen (TempFileName
, "rb")) != NULL
) {
2297 AddSymbol (SOURCE_FILE_NAME
, TempFileName
, SYM_FILE
| SYM_OVERWRITE
);
2299 // Print a message. This function is called to create build commands
2300 // for source files, and to create a macro of all source files. Therefore
2301 // do this check so we don't print the override message multiple times.
2303 if (Mode
& SOURCE_MODE_BUILD_COMMANDS
) {
2304 fprintf (stdout
, "Override: %s\n", TempFileName
);
2308 // Set override path to null to use as a flag below
2310 OverridePath
= NULL
;
2315 // Start at the end and work back
2317 for (Cptr
= FilePath
+ strlen (FilePath
) - 1; (Cptr
> FilePath
) && (*Cptr
!= '\\') && (*Cptr
!= '.'); Cptr
--)
2321 AddSymbol (SOURCE_FILE_EXTENSION
, Cptr
+ 1, SYM_FILE
);
2324 AddSymbol (SOURCE_BASE_NAME
, FilePath
, SYM_FILE
);
2326 // If we're just creating the SOURCE_FILES macro, then write the
2327 // file name out to the makefile.
2329 if (Mode
& SOURCE_MODE_SOURCE_FILES
) {
2331 // If we're processing an override file, then use the file name as-is
2333 if (OverridePath
!= NULL
) {
2335 // SOURCE_FILES = $(SOURCE_FILES) c:\Path\ThisFile.c
2337 fprintf (MakeFptr
, "SOURCE_FILES = $(SOURCE_FILES) %s\n", TempFileName
);
2339 // Save the source absolute path
2341 if (PathCanonicalize (FilePath
, TempFileName
)) {
2342 AddSourceFile (mCurrentBuildItem
, FilePath
);
2344 } else if (IsAbsolutePath (FileName
)) {
2346 // For Absolute path, don't print $(SOURCE_FILE) directory.
2348 fprintf (MakeFptr
, "SOURCE_FILES = $(SOURCE_FILES) %s\n", FileName
);
2350 // Save the source absolute path
2352 if (PathCanonicalize (FilePath
, FileName
)) {
2353 AddSourceFile (mCurrentBuildItem
, FilePath
);
2357 // SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\ThisFile.c
2359 fprintf (MakeFptr
, "SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\\%s\n", FileName
);
2361 // Save the source absolute path
2363 sprintf (Str
, "%s\\%s", GetSymbolValue (SOURCE_DIR
), FileName
);
2364 if (PathCanonicalize (FilePath
, Str
)) {
2365 AddSourceFile (mCurrentBuildItem
, FilePath
);
2368 } else if (Mode
& SOURCE_MODE_BUILD_COMMANDS
) {
2370 // Write the build commands for this file per the build commands
2371 // for this file type as defined in the description file.
2372 // Also create the directory for it in the build path.
2374 WriteCompileCommands (DSCFile
, MakeFptr
, FileName
, Processor
);
2375 if (!IsAbsolutePath (FileName
)) {
2376 sprintf (Str
, "%s\\%s", GetSymbolValue (DEST_DIR
), FileName
);
2379 // Get all output directory for build output files.
2381 Cptr
= FileName
+ strlen (FileName
) - 1;
2382 for (; (Cptr
> FileName
) && (*Cptr
!= '\\'); Cptr
--);
2383 if (*Cptr
== '\\') {
2385 AddModuleName (&gGlobals
.OutdirList
, FileName
, NULL
);
2390 // Remove file-level symbols
2392 RemoveFileSymbols ();
2397 return STATUS_SUCCESS
;
2400 // Process the INF [sources.*] sections and emit the OBJECTS = .....
2401 // lines to the component's makefile.
2406 DSC_FILE
*ComponentFile
,
2410 INT8 Str
[MAX_LINE_LEN
];
2417 INT8
*CopySourceSelect
;
2421 // Write a useful comment to the output makefile so the user knows where
2422 // the data came from.
2424 fprintf (MakeFptr
, "#\n# Tool-generated list of object files that are created\n");
2425 fprintf (MakeFptr
, "# from the list of source files in the [sources.*] sections\n");
2426 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2428 // We use this a lot here, so get the value only once.
2430 Processor
= GetSymbolValue (PROCESSOR
);
2432 // Now define the OBJECTS variable and assign it to be all the object files we're going
2433 // to create. Afterwards create a pseudo-target objects to let the user quickly just compile
2434 // the source files. This means we need to process all the common objects and
2435 // processor-specific objects again.
2437 fprintf (MakeFptr
, "OBJECTS = $(OBJECTS) ");
2439 // See if they defined SOURCE_SELECT=xxx,yyy in which case well
2440 // select each [sources.xxx] and [sources.yyy] files and process
2443 SourceSelect
= GetSymbolValue (SOURCE_SELECT
);
2445 if (SourceSelect
!= NULL
) {
2447 // Make a copy of the string and break it up (comma-separated) and
2448 // select each [sources.*] file from the INF.
2450 CopySourceSelect
= (INT8
*) malloc (strlen (SourceSelect
) + 1);
2451 if (CopySourceSelect
== NULL
) {
2452 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2453 return STATUS_ERROR
;
2456 strcpy (CopySourceSelect
, SourceSelect
);
2457 CStart
= CopySourceSelect
;
2461 while (*CEnd
&& *CEnd
!= ',') {
2467 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, CStart
);
2468 ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
);
2470 // Restore the terminator and advance
2479 free (CopySourceSelect
);
2483 // Now process all the [sources.common] files and emit build commands for them
2485 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, COMMON_SECTION_NAME
);
2486 if (ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
) != STATUS_SUCCESS
) {
2487 Warning (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "no [%s] section found in component description", Str
);
2490 // Now process any processor-specific source files in [sources.$(PROCESSOR)]
2492 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, Processor
);
2493 ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
);
2496 // Now process any [sources.$(PROCESSOR).$(PLATFORM)] files
2498 Platform
= GetSymbolValue (PLATFORM
);
2499 if (Platform
!= NULL
) {
2500 sprintf (Str
, "sources.%s.%s", Processor
, Platform
);
2501 ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
);
2505 fprintf (MakeFptr
, "\n\n");
2508 // Write a useful comment to the output makefile so the user knows where
2509 // the data came from.
2511 fprintf (MakeFptr
, "#\n# Tool-generated list of dest output dirs that are created\n");
2512 fprintf (MakeFptr
, "# from the list of source files in the [sources.*] sections\n");
2513 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2515 // Create output directory list
2516 // for clean target to delete all build output files.
2518 fprintf (MakeFptr
, "DEST_OUTPUT_DIRS = $(%s) ", DEST_DIR
);
2520 TempSymbol
= gGlobals
.OutdirList
;
2521 while (TempSymbol
!= NULL
) {
2522 fprintf (MakeFptr
, "\\\n $(%s)\\%s ",
2523 DEST_DIR
, TempSymbol
->Name
);
2524 TempSymbol
= TempSymbol
->Next
;
2526 fprintf (MakeFptr
, "\n\n");
2529 // clean up for the next module
2531 FreeSymbols (gGlobals
.OutdirList
);
2532 gGlobals
.OutdirList
= NULL
;
2534 return STATUS_SUCCESS
;
2539 BuiltFileExtension (
2540 INT8
*SourceFileName
2546 // Find the dot in the filename extension
2548 for (Cptr
= SourceFileName
+ strlen (SourceFileName
) - 1;
2549 (Cptr
> SourceFileName
) && (*Cptr
!= '\\') && (*Cptr
!= '.');
2561 // Look through our list of known file types and return a pointer to
2562 // its built file extension.
2564 for (i
= 0; mFileTypes
[i
].Extension
!= NULL
; i
++) {
2565 if (_stricmp (Cptr
, mFileTypes
[i
].Extension
) == 0) {
2566 return mFileTypes
[i
].BuiltExtension
;
2574 ProcessObjectsSingle (
2575 DSC_FILE
*ComponentFile
,
2582 INT8 Str
[MAX_LINE_LEN
];
2583 INT8 FileName
[MAX_EXP_LINE_LEN
];
2586 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2587 if (TempSect
!= NULL
) {
2588 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2589 Cptr
= StripLine (Str
);
2591 // Don't process blank lines
2595 // Expand symbols then create the output filename. We'll do a lookup
2596 // on the source file's extension to determine what the extension of
2597 // the built version of the file is. For example, .c -> .obj.
2599 if (!IsIncludeFile (Cptr
)) {
2600 ExpandSymbols (Cptr
, FileName
, sizeof (FileName
), 0);
2601 ReplaceSlash (FileName
);
2602 Cptr2
= BuiltFileExtension (FileName
);
2603 if (Cptr2
!= NULL
) {
2604 SetFileExtension (FileName
, Cptr2
);
2605 if (!IsAbsolutePath (FileName
)) {
2606 fprintf (MakeFptr
, "\\\n $(%s)\\%s ", DEST_DIR
, FileName
);
2608 fprintf (MakeFptr
, "\\\n %s ", FileName
);
2615 return STATUS_WARNING
;
2618 return STATUS_SUCCESS
;
2621 // Process all [libraries.*] sections in the component INF file to create a
2622 // macro to the component's output makefile: LIBS = Lib1 Lib2, ...
2627 DSC_FILE
*ComponentFile
,
2631 INT8 Str
[MAX_LINE_LEN
];
2636 // Print a useful comment to the component's makefile so the user knows
2637 // where the data came from.
2639 fprintf (MakeFptr
, "#\n# Tool-generated list of libraries that are generated\n");
2640 fprintf (MakeFptr
, "# from the list of libraries listed in the [libraries.*] sections\n");
2641 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2643 fprintf (MakeFptr
, "LIBS = $(LIBS) ");
2645 Processor
= GetSymbolValue (PROCESSOR
);
2647 // Process [libraries.common] files
2649 sprintf (Str
, "%s.%s", LIBRARIES_SECTION_NAME
, COMMON_SECTION_NAME
);
2650 ProcessLibsSingle (ComponentFile
, MakeFptr
, Str
);
2652 // Process the [libraries.$(PROCESSOR)] libraries to define "LIBS = x.lib y.lib..."
2654 sprintf (Str
, "%s.%s", LIBRARIES_SECTION_NAME
, Processor
);
2655 ProcessLibsSingle (ComponentFile
, MakeFptr
, Str
);
2657 // Now process any [libraries.$(PROCESSOR).$(PLATFORM)] files
2659 Platform
= GetSymbolValue (PLATFORM
);
2660 if (Platform
!= NULL
) {
2661 sprintf (Str
, "%s.%s.%s", LIBRARIES_SECTION_NAME
, Processor
, Platform
);
2662 ProcessLibsSingle (ComponentFile
, MakeFptr
, Str
);
2665 // Process any [libraries.platform] files
2667 ProcessLibsSingle (ComponentFile
, MakeFptr
, LIBRARIES_PLATFORM_SECTION_NAME
);
2669 fprintf (MakeFptr
, "\n\n");
2670 return STATUS_SUCCESS
;
2676 DSC_FILE
*ComponentFile
,
2682 INT8 Str
[MAX_LINE_LEN
];
2683 INT8 ExpandedLine
[MAX_LINE_LEN
];
2686 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2687 if (TempSect
!= NULL
) {
2688 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2689 ExpandSymbols (Str
, ExpandedLine
, sizeof (ExpandedLine
), 0);
2690 Cptr
= StripLine (ExpandedLine
);
2692 // Don't process blank lines
2695 if (Cptr
[strlen (Cptr
) - 4] != '.') {
2696 fprintf (MakeFptr
, " \\\n $(LIB_DIR)\\%s.lib", Cptr
);
2698 // Add lib dependency for single module build
2700 fprintf (gGlobals
.ModuleMakefileFptr
, " %sbuild", Cptr
);
2702 fprintf (MakeFptr
, " \\\n $(LIB_DIR)\\%s", Cptr
);
2704 // Add lib dependency for single module build
2706 Cptr
[strlen (Cptr
) - 4] = 0;
2707 fprintf (gGlobals
.ModuleMakefileFptr
, " %sbuild", Cptr
);
2710 // Add libs dependency for mCurrentBuildItem
2712 AddDependency (*mCurrentBuildList
, mCurrentBuildItem
, Cptr
, 0);
2717 return STATUS_SUCCESS
;
2722 ProcessIncludeFiles (
2723 DSC_FILE
*ComponentFile
,
2727 INT8 Str
[MAX_LINE_LEN
];
2734 INT8
*CopySourceSelect
;
2737 // Print a useful comment to the output makefile so the user knows where
2738 // the info came from
2740 //fprintf (MakeFptr, "#\n# Tool-generated include dependencies from any include files in the\n");
2741 //fprintf (MakeFptr, "# [sources.*] sections of the component INF file\n#\n");
2743 Processor
= GetSymbolValue (PROCESSOR
);
2746 // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll
2747 // select each [sources.xxx] and [sources.yyy] files and process
2750 SourceSelect
= GetSymbolValue (SOURCE_SELECT
);
2752 if (SourceSelect
!= NULL
) {
2754 // Make a copy of the string and break it up (comma-separated) and
2755 // select each [sources.*] file from the INF.
2757 CopySourceSelect
= (INT8
*) malloc (strlen (SourceSelect
) + 1);
2758 if (CopySourceSelect
== NULL
) {
2759 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2760 return STATUS_ERROR
;
2763 strcpy (CopySourceSelect
, SourceSelect
);
2764 CStart
= CopySourceSelect
;
2768 while (*CEnd
&& *CEnd
!= ',') {
2774 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, CStart
);
2775 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2777 // Restore the terminator and advance
2786 free (CopySourceSelect
);
2790 // Find all the include files in the [sources.common] sections.
2792 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, COMMON_SECTION_NAME
);
2793 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2795 // Now process the [sources.$(PROCESSOR)] files.
2797 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, Processor
);
2798 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2800 // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files.
2802 Platform
= GetSymbolValue (PLATFORM
);
2803 if (Platform
!= NULL
) {
2804 sprintf (Str
, "sources.%s.%s", Processor
, Platform
);
2805 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2809 fprintf (MakeFptr
, "\n");
2810 return STATUS_SUCCESS
;
2814 ProcessIncludeFilesSingle (
2815 DSC_FILE
*ComponentFile
,
2821 INT8 FileName
[MAX_EXP_LINE_LEN
];
2822 INT8 TempFileName
[MAX_PATH
];
2824 INT8 Str
[MAX_LINE_LEN
];
2828 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2829 if (TempSect
!= NULL
) {
2831 // See if the SOURCE_OVERRIDE_PATH has been set. If it has, and
2832 // they have an include file that is overridden, then add the path
2833 // to it to the list of include paths (prepend).
2835 OverridePath
= GetSymbolValue (SOURCE_OVERRIDE_PATH
);
2836 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2837 Cptr
= StripLine (Str
);
2839 // Don't process blank lines
2843 // Expand symbols in the filename, then get its parts
2845 ExpandSymbols (Cptr
, FileName
, sizeof (FileName
), 0);
2846 AddFileSymbols (FileName
);
2847 ReplaceSlash (FileName
);
2848 if (IsIncludeFile (FileName
)) {
2849 if ((OverridePath
!= NULL
) && (!IsAbsolutePath (FileName
))) {
2850 ReplaceSlash (OverridePath
);
2851 strcpy (TempFileName
, OverridePath
);
2852 strcat (TempFileName
, "\\");
2853 strcat (TempFileName
, FileName
);
2854 if ((FPtr
= fopen (TempFileName
, "rb")) != NULL
) {
2857 // Null-terminate the file name at the last backslash and add that
2858 // to the beginning of the list of include paths.
2860 for (Cptr
= TempFileName
+ strlen (TempFileName
) - 1;
2861 (Cptr
>= TempFileName
) && (*Cptr
!= '\\');
2865 if (Cptr
>= TempFileName
) {
2868 fprintf (MakeFptr
, "!IF EXIST(%s)\n", TempFileName
);
2869 fprintf (MakeFptr
, "INC = -I %s $(INC)\n", TempFileName
);
2870 fprintf (MakeFptr
, "!ENDIF\n");
2874 // If absolute path already, don't prepend source directory
2876 // if (IsAbsolutePath (FileName)) {
2877 // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) %s\n", FileName);
2879 // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) $(SOURCE_DIR)\\%s\n", FileName);
2883 RemoveFileSymbols ();
2888 return STATUS_SUCCESS
;
2898 if (FP
->Path
!= NULL
) {
2902 if (FP
->BaseName
!= NULL
) {
2903 free (FP
->BaseName
);
2906 if (FP
->Extension
!= NULL
) {
2907 free (FP
->Extension
);
2918 FILE_NAME_PARTS
*FP
;
2920 INT8 CopyFileName
[MAX_PATH
];
2923 strcpy (CopyFileName
, FileName
);
2924 FP
= (FILE_NAME_PARTS
*) malloc (sizeof (FILE_NAME_PARTS
));
2926 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2930 memset ((INT8
*) FP
, 0, sizeof (FILE_NAME_PARTS
));
2932 // Get extension code
2934 FP
->ExtensionCode
= GetSourceFileType (CopyFileName
);
2936 // Get drive if there
2938 FileNamePtr
= CopyFileName
;
2939 if (FileNamePtr
[1] == ':') {
2940 FP
->Drive
[0] = FileNamePtr
[0];
2945 // Start at the end and work back
2947 for (Cptr
= FileNamePtr
+ strlen (FileNamePtr
) - 1; (Cptr
> FileNamePtr
) && (*Cptr
!= '.'); Cptr
--)
2952 // Don't copy the dot
2954 FP
->Extension
= (char *) malloc (strlen (Cptr
));
2955 strcpy (FP
->Extension
, Cptr
+ 1);
2958 StripTrailingSpaces (FP
->Extension
);
2961 // Create empty string for extension
2963 FP
->Extension
= (char *) malloc (1);
2964 FP
->Extension
[0] = 0;
2967 // Now back up and get the base name (include the preceding '\')
2969 for (; (Cptr
> FileNamePtr
) && (*Cptr
!= '\\'); Cptr
--)
2971 FP
->BaseName
= (char *) malloc (strlen (Cptr
) + 1);
2972 strcpy (FP
->BaseName
, Cptr
);
2978 if (Cptr
>= FileNamePtr
) {
2980 FP
->Path
= (char *) malloc (strlen (Cptr
) + 1);
2981 strcpy (FP
->Path
, Cptr
);
2983 FP
->Path
= (char *) malloc (1);
2990 /*****************************************************************************
2991 ******************************************************************************/
2994 WriteCommonMakefile (
3000 INT8 InLine
[MAX_LINE_LEN
];
3001 INT8 OutLine
[MAX_EXP_LINE_LEN
];
3006 // Don't mess up the original file pointer, since we're processing it at a higher
3009 DSCFileSavePosition (DSCFile
);
3011 // Write the header to the file
3013 for (i
= 0; MakefileHeader
[i
] != NULL
; i
++) {
3014 fprintf (MakeFptr
, "%s\n", MakefileHeader
[i
]);
3017 fprintf (MakeFptr
, "#\n# Hard-coded defines output by the tool\n#\n");
3019 // First write the basics to the component's makefile. These includes
3020 // EFI_SOURCE, BIN_DIR, OUT_DIR, LIB_DIR, SOURCE_DIR, DEST_DIR.
3022 Sym
= GetSymbolValue (EFI_SOURCE
);
3023 fprintf (MakeFptr
, "%s = %s\n", EFI_SOURCE
, Sym
);
3024 Sym
= GetSymbolValue (BUILD_DIR
);
3025 fprintf (MakeFptr
, "%s = %s\n", BUILD_DIR
, Sym
);
3026 Sym
= GetSymbolValue (BIN_DIR
);
3027 fprintf (MakeFptr
, "%s = %s\n", BIN_DIR
, Sym
);
3028 Sym
= GetSymbolValue (OUT_DIR
);
3029 fprintf (MakeFptr
, "%s = %s\n", OUT_DIR
, Sym
);
3030 Sym
= GetSymbolValue (LIB_DIR
);
3031 fprintf (MakeFptr
, "%s = %s\n", LIB_DIR
, Sym
);
3032 Sym
= GetSymbolValue (SOURCE_DIR
);
3033 fprintf (MakeFptr
, "%s = %s\n", SOURCE_DIR
, Sym
);
3034 Sym
= GetSymbolValue (DEST_DIR
);
3035 fprintf (MakeFptr
, "%s = %s\n", DEST_DIR
, Sym
);
3036 fprintf (MakeFptr
, "\n");
3038 // If there was a [makefile.common] section in the description file,
3039 // copy it (after symbol expansion) to the output file.
3041 sprintf (InLine
, "%s.%s", MAKEFILE_SECTION_NAME
, COMMON_SECTION_NAME
);
3042 Sect
= DSCFileFindSection (DSCFile
, InLine
);
3045 // fprintf (MakeFptr, "# From the [makefile.common] section of the DSC file\n");
3046 // Read lines, expand, then dump out
3048 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
3052 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
3053 fprintf (MakeFptr
, OutLine
);
3057 // If there was a [makefile.platform] section in the description file,
3058 // copy it (after symbol expansion) to the output file.
3060 sprintf (InLine
, "%s.%s", MAKEFILE_SECTION_NAME
, "Platform");
3061 Sect
= DSCFileFindSection (DSCFile
, InLine
);
3064 // Read lines, expand, then dump out
3066 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
3070 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
3071 fprintf (MakeFptr
, OutLine
);
3075 // Do the same for any [makefile.$(PROCESSOR)]
3077 sprintf (InLine
, "%s.%s", MAKEFILE_SECTION_NAME
, Processor
);
3078 Sect
= DSCFileFindSection (DSCFile
, InLine
);
3081 // Read lines, expand, then dump out
3083 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
3084 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
3085 fprintf (MakeFptr
, OutLine
);
3089 // Same thing for [makefile.$(PROCESSOR).$(PLATFORM)]
3091 Sym
= GetSymbolValue (PLATFORM
);
3093 sprintf (InLine
, "%s.%s.%s", MAKEFILE_SECTION_NAME
, Processor
, Sym
);
3094 Sect
= DSCFileFindSection (DSCFile
, InLine
);
3097 // Read lines, expand, then dump out
3099 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
3100 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
3101 fprintf (MakeFptr
, OutLine
);
3106 fprintf (MakeFptr
, "\n");
3107 DSCFileRestorePosition (DSCFile
);
3113 WriteComponentTypeBuildCommands (
3120 Routine Description:
3122 Given a section name such as [build.ia32.library], find the section in
3123 the description file and copy the build commands.
3127 DSCFile - section information on the main description file
3128 MakeFptr - file pointer to the makefile we're writing to
3129 SectionName - name of the section we're to copy out to the makefile.
3133 Always successful, since the section may be optional.
3138 INT8 InLine
[MAX_LINE_LEN
];
3139 INT8 OutLine
[MAX_EXP_LINE_LEN
];
3142 // Don't mess up the original file pointer, since we're processing it at a higher
3145 DSCFileSavePosition (DSCFile
);
3146 Sect
= DSCFileFindSection (DSCFile
, SectionName
);
3149 // Read lines, expand, then dump out
3151 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
3156 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
3158 fprintf (MakeFptr
, OutLine
);
3165 GetSymbolValue (INF_FILENAME
),
3166 "no [%s] build commands found in DSC file for component",
3171 DSCFileRestorePosition (DSCFile
);
3172 return STATUS_SUCCESS
;
3175 /*****************************************************************************
3177 ******************************************************************************/
3180 WriteCompileCommands (
3187 FILE_NAME_PARTS
*File
;
3189 INT8 BuildSectionName
[40];
3190 INT8 InLine
[MAX_LINE_LEN
];
3191 INT8 OutLine
[MAX_EXP_LINE_LEN
];
3192 INT8
*SourceCompileType
;
3196 // Determine the filename, then chop it up into its parts
3198 File
= GetFileParts (FileName
);
3201 // Don't mess up the original file pointer, since we're processing it at a higher
3204 DSCFileSavePosition (DscFile
);
3206 // Option 1: SOURCE_COMPILE_TYPE=MyCompileSection
3207 // Find a section of that name from which to get the compile
3208 // commands for this source file.
3209 // Look for [compile.$(PROCESSOR).$(SOURCE_COMPILE_TYPE]
3210 // Option 2: COMPILE_SELECT=.c=MyCCompile,.asm=MyAsm
3211 // Find a [compile.$(PROCESSOR).MyCompile] section from which to
3212 // get the compile commands for this source file.
3213 // Look for [compile.$(PROCESSOR).MyCompile]
3214 // Option 3: Look for standard section types to compile the file by extension.
3215 // Look for [compile.$(PROCESSOR).<extension>]
3219 // Option 1 - use SOURCE_COMPILE_TYPE variable
3221 SourceCompileType
= GetSymbolValue (SOURCE_COMPILE_TYPE
);
3222 if (SourceCompileType
!= NULL
) {
3223 sprintf (BuildSectionName
, "compile.%s.%s", Processor
, SourceCompileType
);
3224 Sect
= DSCFileFindSection (DscFile
, BuildSectionName
);
3227 // Option 2 - use COMPILE_SELECT variable
3230 SourceCompileType
= GetSymbolValue (COMPILE_SELECT
);
3231 if (SourceCompileType
!= NULL
) {
3233 // Parse the variable, which looks like COMPILE_SELECT=.c=MyCCompiler;.asm=MyAsm;
3234 // to find an entry with a matching file name extension. If you find one,
3235 // then use that name to find the section name.
3237 CPtr
= SourceCompileType
;
3238 while (*CPtr
&& (Sect
== NULL
)) {
3240 // See if we found a match with this source file name extension. File->Extension
3241 // does not include the dot, so skip the dot in the COMPILE_SELECT variable if there
3248 if (_strnicmp (CPtr
, File
->Extension
, strlen (File
->Extension
)) == 0) {
3250 // Found a file name extension match -- extract the name from the variable, for
3251 // example "MyCCompiler"
3253 while (*CPtr
&& (*CPtr
!= '=')) {
3257 if ((*CPtr
!= '=') || (CPtr
[1] == 0)) {
3258 Error (NULL
, 0, 0, SourceCompileType
, "malformed COMPILE_SELECT variable");
3263 sprintf (BuildSectionName
, "compile.%s.", Processor
);
3264 for (CPtr2
= BuildSectionName
+ strlen (BuildSectionName
);
3265 *CPtr
&& (*CPtr
!= ',') && (*CPtr
!= ';');
3273 Sect
= DSCFileFindSection (DscFile
, BuildSectionName
);
3278 "could not find section in DSC file - selected by COMPILE_SELECT variable"
3284 // Skip to next file name extension in the COMPILE_SELECT variable
3286 while (*CPtr
&& (*CPtr
!= ';') && (*CPtr
!= ',')) {
3297 // Option 3 - use "Compile.$(PROCESSOR).<Extension>" section
3300 sprintf (BuildSectionName
, "compile.%s.%s", Processor
, File
->Extension
);
3301 Sect
= DSCFileFindSection (DscFile
, BuildSectionName
);
3304 // Should have found something by now unless it's an include (.h) file
3308 // Temporarily add a FILE variable to the global symbol table. Omit the
3311 sprintf (InLine
, "%s%s%s", File
->Drive
, File
->Path
, File
->BaseName
);
3312 AddSymbol ("FILE", InLine
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILENAME
);
3314 // Read lines, expand (except SOURCE_DIR and DEST_DIR), then dump out
3316 while (DSCFileGetLine (DscFile
, InLine
, sizeof (InLine
)) != NULL
) {
3321 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
3323 fprintf (MakeFptr
, OutLine
);
3325 fprintf (MakeFptr
, "\n");
3328 // Be nice and ignore include files
3330 if (!IsIncludeFile (FileName
)) {
3336 "no compile commands section [%s] found in DSC file for %s",
3343 DSCFileRestorePosition (DscFile
);
3344 FreeFileParts (File
);
3347 return STATUS_SUCCESS
;
3350 /*****************************************************************************
3351 ******************************************************************************/
3361 Cptr
= FileName
+ strlen (FileName
) - 1;
3362 while ((Cptr
> FileName
) && (*Cptr
!= '.')) {
3370 Message (2, "Missing filename extension: %s", FileName
);
3371 return STATUS_WARNING
;
3375 if (*Extension
== '.') {
3379 strcpy (Cptr
, Extension
);
3380 return STATUS_SUCCESS
;
3383 /*****************************************************************************
3384 ******************************************************************************/
3392 INT8 BuildDir
[MAX_PATH
];
3393 INT8 CopyFileName
[MAX_PATH
];
3396 // Expand symbols in the filename
3398 if (ExpandSymbols (FileName
, CopyFileName
, sizeof (CopyFileName
), EXPANDMODE_NO_UNDEFS
)) {
3399 Error (NULL
, 0, 0, NULL
, "undefined symbols in file path: %s", FileName
);
3400 return STATUS_ERROR
;
3405 strcpy (FileName
, CopyFileName
);
3407 // To avoid creating $(BUILD_DIR) path, see if this path is the same as
3408 // $(BUILD_DIR), and if it is, see if build dir exists and skip over that
3409 // portion if it does
3411 Cptr
= GetSymbolValue (BUILD_DIR
);
3413 if (_strnicmp (Cptr
, FileName
, strlen (Cptr
)) == 0) {
3415 // BUILD_DIR path. See if it exists
3417 strcpy (BuildDir
, FileName
);
3418 BuildDir
[strlen (Cptr
)] = 0;
3419 if ((_mkdir (BuildDir
) != 0) && (errno
!= EEXIST
)) {
3423 // Already done. Shortcut. Skip to next path so that we don't create
3424 // the BUILD_DIR as well.
3426 Cptr
= FileName
+ strlen (Cptr
);
3427 if (*Cptr
== '\\') {
3441 // Create directories until done. Skip over "c:\" in the path if it exists
3443 if (*Cptr
&& (*(Cptr
+ 1) == ':') && (*(Cptr
+ 2) == '\\')) {
3448 for (; *Cptr
&& (*Cptr
!= '\\'); Cptr
++)
3453 if ((_mkdir (FileName
) != 0)) {
3455 // Error (NULL, 0, 0, FileName, "failed to create directory");
3467 return STATUS_SUCCESS
;
3470 /*****************************************************************************
3471 ******************************************************************************/
3480 static int NestDepth
= 0;
3488 INT8
*LocalDestLine
;
3493 Status
= STATUS_SUCCESS
;
3494 LocalDestLine
= (INT8
*) malloc (LineLen
);
3495 if (LocalDestLine
== NULL
) {
3496 Error (__FILE__
, __LINE__
, 0, "application error", "memory allocation failed");
3498 return STATUS_ERROR
;
3501 FromPtr
= SourceLine
;
3502 ToPtr
= LocalDestLine
;
3504 // Walk the entire line, replacing $(SYMBOL_NAME).
3506 LocalLineLen
= LineLen
;
3508 while (*FromPtr
&& (LocalLineLen
> 0)) {
3509 if ((*FromPtr
== '$') && (*(FromPtr
+ 1) == '(')) {
3511 // Save the start in case it's undefined, in which case we copy it as-is.
3513 SaveStart
= FromPtr
;
3516 // Symbol expansion time. Find the end (no spaces allowed)
3519 for (Cptr
= FromPtr
; *Cptr
&& (*Cptr
!= ')'); Cptr
++)
3523 // Truncate the string at the closing parenthesis for ease-of-use.
3524 // Then copy the string directly to the destination line in case we don't find
3525 // a definition for it.
3528 strcpy (ToPtr
, SaveStart
);
3529 if ((_stricmp (SOURCE_DIR
, FromPtr
) == 0) && (ExpandMode
& EXPANDMODE_NO_SOURCEDIR
)) {
3531 // excluded this expansion
3533 } else if ((_stricmp (DEST_DIR
, FromPtr
) == 0) && (ExpandMode
& EXPANDMODE_NO_DESTDIR
)) {
3535 // excluded this expansion
3537 } else if ((value
= GetSymbolValue (FromPtr
)) != NULL
) {
3538 strcpy (ToPtr
, value
);
3539 LocalLineLen
-= strlen (value
);
3540 ToPtr
+= strlen (value
);
3543 } else if (ExpandMode
& EXPANDMODE_NO_UNDEFS
) {
3544 Error (NULL
, 0, 0, "undefined symbol", "$(%s)", FromPtr
);
3545 Status
= STATUS_ERROR
;
3550 // Restore closing parenthesis, and advance to next character
3554 FromPtr
= SaveStart
+ 1;
3560 Error (NULL
, 0, 0, SourceLine
, "missing closing parenthesis on symbol");
3561 strcpy (ToPtr
, FromPtr
);
3562 Status
= STATUS_WARNING
;
3573 if (*FromPtr
== 0) {
3578 // If we're in recursive mode, and we expanded at least one string successfully,
3579 // then make a recursive call to try again.
3581 if ((ExpandedCount
!= 0) && (Status
== STATUS_SUCCESS
) && (ExpandMode
& EXPANDMODE_RECURSIVE
) && (NestDepth
< 2)) {
3582 Status
= ExpandSymbols (LocalDestLine
, DestLine
, LineLen
, ExpandMode
);
3583 free (LocalDestLine
);
3589 if (Status
!= STATUS_ERROR
) {
3590 strcpy (DestLine
, LocalDestLine
);
3594 free (LocalDestLine
);
3604 Routine Description:
3606 Look up a symbol in our symbol table.
3610 SymbolName - The name of symbol.
3614 Pointer to the value of the symbol if found
3615 NULL if the symbol is not found
3622 // Scan once for file-level symbols
3624 Symbol
= gGlobals
.Symbol
;
3626 if ((_stricmp (SymbolName
, Symbol
->Name
) == 0) && (Symbol
->Type
& SYM_FILE
)) {
3627 return Symbol
->Value
;
3630 Symbol
= Symbol
->Next
;
3633 // Scan once for local symbols
3635 Symbol
= gGlobals
.Symbol
;
3637 if ((_stricmp (SymbolName
, Symbol
->Name
) == 0) && (Symbol
->Type
& SYM_LOCAL
)) {
3638 return Symbol
->Value
;
3641 Symbol
= Symbol
->Next
;
3644 // No local value found. Scan for globals.
3646 Symbol
= gGlobals
.Symbol
;
3648 if ((_stricmp (SymbolName
, Symbol
->Name
) == 0) && (Symbol
->Type
& SYM_GLOBAL
)) {
3649 return Symbol
->Value
;
3652 Symbol
= Symbol
->Next
;
3655 // For backwards-compatibility, if it's "GUID", return FILE_GUID value
3657 if (_stricmp (SymbolName
, GUID
) == 0) {
3658 return GetSymbolValue (FILE_GUID
);
3666 RemoveLocalSymbols (
3671 Routine Description:
3673 Remove all local symbols from the symbol table. Local symbols are those
3674 that are defined typically by the component's INF file.
3682 Right now, never fails.
3691 Sym
= gGlobals
.Symbol
;
3693 if (Sym
->Type
& SYM_LOCAL
) {
3695 // Going to delete it out from under ourselves, so break and restart
3698 RemoveSymbol (Sym
->Name
, SYM_LOCAL
);
3705 return STATUS_SUCCESS
;
3715 Routine Description:
3717 Remove all file-level symbols from the symbol table. File-level symbols are
3718 those that are defined on a source file line in an INF file.
3726 Right now, never fails.
3735 Sym
= gGlobals
.Symbol
;
3737 if (Sym
->Type
& SYM_FILE
) {
3739 // Going to delete it out from under ourselves, so break and restart
3742 RemoveSymbol (Sym
->Name
, SYM_FILE
);
3749 return STATUS_SUCCESS
;
3754 ParseGuidDatabaseFile (
3759 Routine Description:
3760 This function parses a GUID-to-basename text file (perhaps output by
3761 the GuidChk utility) to define additional symbols. The format of the
3764 7BB28B99-61BB-11D5-9A5D-0090273FC14D EFI_DEFAULT_BMP_LOGO_GUID gEfiDefaultBmpLogoGuid
3766 This function parses the line and defines global symbol:
3768 EFI_DEFAULT_BMP_LOGO_GUID=7BB28B99-61BB-11D5-9A5D-0090273FC14D
3770 This symbol (rather than the actual GUID) can then be used in INF files to
3774 FileName - the name of the file to parse.
3777 STATUS_ERROR - could not open FileName
3778 STATUS_SUCCESS - we opened the file
3785 INT8 DefineName
[80];
3787 Fptr
= fopen (FileName
, "r");
3789 Error (NULL
, 0, 0, FileName
, "failed to open input GUID database input file");
3790 return STATUS_ERROR
;
3793 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
3795 // Get the GUID string, skip the defined name (EFI_XXX_GUID), and get the
3796 // variable name (gWhateverProtocolGuid)
3798 if (sscanf (Line
, "%s %s %*s", Guid
, DefineName
) == 2) {
3799 AddSymbol (DefineName
, Guid
, SYM_GLOBAL
);
3804 return STATUS_SUCCESS
;
3807 /*****************************************************************************
3810 0 if successful standard add
3811 length of the parsed string if passed in " name = value "
3814 ******************************************************************************/
3831 INT8 ShortName
[MAX_PATH
];
3841 // Mode better be local or global symbol
3843 if ((Mode
& (SYM_LOCAL
| SYM_GLOBAL
| SYM_FILE
)) == 0) {
3844 Error (NULL
, 0, 0, "APP ERROR", "adding symbol '%s' that is not local, global, nor file level", Name
);
3848 // If value pointer is null, then they passed us a line something like:
3849 // varname = value, or simply var =
3851 if (Value
== NULL
) {
3853 while (*Name
&& isspace (*Name
)) {
3862 // Find the end of the name. Either space or a '='.
3864 for (Value
= Name
; *Value
&& !isspace (*Value
) && (*Value
!= '='); Value
++)
3873 while (*Value
&& (*Value
!= '=')) {
3882 // Now truncate the name
3889 // Skip over the = and then any spaces
3892 while (*Value
&& isspace (*Value
)) {
3897 // Find end of string, checking for quoted string
3899 if (*Value
== '\"') {
3901 for (Cptr
= Value
; *Cptr
&& *Cptr
!= '\"'; Cptr
++)
3904 for (Cptr
= Value
; *Cptr
&& !isspace (*Cptr
); Cptr
++)
3908 // Null terminate the value string
3911 Len
= (int) (Cptr
- Start
) + 1;
3916 Len
= (int) (Cptr
- Start
);
3921 // If file name or file path, and we're shortening, then print it
3923 if ((Mode
& (SYM_FILEPATH
| SYM_FILENAME
)) && (GetSymbolValue (SHORT_NAMES
) != NULL
)) {
3924 if (GetShortPathName (Value
, ShortName
, sizeof (ShortName
)) > 0) {
3926 // fprintf (stdout, "String value '%s' shortened to '%s'\n",
3927 // Value, ShortName);
3932 // fprintf (stdout, "WARNING: Failed to get short name for %s\n", Value);
3937 // We now have a symbol name and a value. Look for an existing variable of
3938 // the same type (global or local) and overwrite it.
3940 Symbol
= gGlobals
.Symbol
;
3943 // Check for symbol name match
3945 if (_stricmp (Name
, Symbol
->Name
) == 0) {
3947 // See if this symbol is of the same type (global or local) as what
3948 // they're requesting
3950 if ((Symbol
->Type
& (SYM_LOCAL
| SYM_GLOBAL
)) == (Mode
& (SYM_LOCAL
| SYM_GLOBAL
))) {
3952 // Did they say we could overwrite it?
3954 if (Mode
& SYM_OVERWRITE
) {
3955 free (Symbol
->Value
);
3956 Symbol
->Value
= (INT8
*) malloc (strlen (Value
) + 1);
3957 if (Symbol
->Value
== NULL
) {
3958 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
3962 strcpy (Symbol
->Value
, Value
);
3964 // If value == "NULL", then make it a 0-length string
3966 if (_stricmp (Symbol
->Value
, "NULL") == 0) {
3967 Symbol
->Value
[0] = 0;
3972 return STATUS_ERROR
;
3977 Symbol
= Symbol
->Next
;
3980 // Does not exist, create a new one
3982 NewSymbol
= (SYMBOL
*) malloc (sizeof (SYMBOL
));
3983 if (NewSymbol
== NULL
) {
3984 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
3988 memset ((INT8
*) NewSymbol
, 0, sizeof (SYMBOL
));
3989 NewSymbol
->Name
= (INT8
*) malloc (strlen (Name
) + 1);
3990 NewSymbol
->Value
= (INT8
*) malloc (strlen (Value
) + 1);
3992 // Simply use the mode bits as the type.
3994 NewSymbol
->Type
= Mode
;
3995 if ((NewSymbol
->Name
== NULL
) || (NewSymbol
->Value
== NULL
)) {
3996 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
4000 strcpy (NewSymbol
->Name
, Name
);
4001 strcpy (NewSymbol
->Value
, Value
);
4003 // Remove trailing spaces
4005 Cptr
= NewSymbol
->Value
+ strlen (NewSymbol
->Value
) - 1;
4006 while (Cptr
> NewSymbol
->Value
) {
4007 if (isspace (*Cptr
)) {
4015 // Add it to the head of the list.
4017 NewSymbol
->Next
= gGlobals
.Symbol
;
4018 gGlobals
.Symbol
= NewSymbol
;
4020 // If value == "NULL", then make it a 0-length string
4022 if (_stricmp (NewSymbol
->Value
, "NULL") == 0) {
4023 NewSymbol
->Value
[0] = 0;
4026 // Restore the terminator we inserted if they passed in var=value
4028 if (SaveCptr1
!= NULL
) {
4029 *SaveCptr1
= CSave1
;
4031 if (SaveCptr2
!= NULL
) {
4032 *SaveCptr2
= CSave2
;
4038 /*****************************************************************************
4039 ******************************************************************************/
4051 Symbol
= gGlobals
.Symbol
;
4053 if ((_stricmp (Name
, Symbol
->Name
) == 0) && (Symbol
->Type
& SymbolType
)) {
4054 if (Symbol
->Value
) {
4055 free (Symbol
->Value
);
4058 free (Symbol
->Name
);
4060 PrevSymbol
->Next
= Symbol
->Next
;
4062 gGlobals
.Symbol
= Symbol
->Next
;
4066 return STATUS_SUCCESS
;
4069 PrevSymbol
= Symbol
;
4070 Symbol
= Symbol
->Next
;
4073 return STATUS_WARNING
;
4078 /*****************************************************************************
4079 ******************************************************************************/
4088 while (Sect
!= NULL
) {
4090 if (Sect
->Name
!= NULL
) {
4091 delete[] Sect
->Name
;
4100 /*****************************************************************************
4101 ******************************************************************************/
4113 // Look for '#' comments in first character of line
4120 while (isspace (*Cptr
)) {
4124 // Hack off newlines
4126 Len
= strlen (Cptr
);
4127 if ((Len
> 0) && (Cptr
[Len
- 1] == '\n')) {
4131 // Hack off trailing spaces
4133 StripTrailingSpaces (Cptr
);
4137 /*****************************************************************************
4138 FUNCTION: ProcessOptions()
4140 DESCRIPTION: Process the command-line options.
4141 ******************************************************************************/
4150 Routine Description:
4152 Process the command line options to this utility.
4156 Argc - Standard Argc.
4157 Argv[] - Standard Argv.
4167 // Clear out the options
4169 memset ((INT8
*) &gGlobals
, 0, sizeof (gGlobals
));
4176 return STATUS_ERROR
;
4179 // Now process the arguments
4183 if ((Argv
[0][0] == '-') || (Argv
[0][0] == '/')) {
4184 switch (Argv
[0][1]) {
4186 // -? or -h help option
4192 return STATUS_ERROR
;
4206 Error (NULL
, 0, 0, NULL
, "missing symbol definition with %c%c", Argv
[0][0], Argv
[0][1]);
4207 return STATUS_ERROR
;
4209 if (AddSymbol (Argv
[0], NULL
, SYM_OVERWRITE
| SYM_GLOBAL
) <= 0) {
4210 Warning (NULL
, 0, 0, Argv
[0], "failed to add symbol: %s");
4216 // output makefile name
4227 Error (NULL
, 0, 0, Argv
[0], "missing output makefile name with option");
4229 return STATUS_ERROR
;
4231 strcpy (gGlobals
.MakefileName
, Argv
[0]);
4236 // Print a cross-reference file containing guid/basename/processor
4247 Error (NULL
, 0, 0, Argv
[0], "missing cross-reference output filename with option");
4249 return STATUS_ERROR
;
4251 strcpy (gGlobals
.XRefFileName
, Argv
[0]);
4256 // GUID database file to preparse
4267 Error (NULL
, 0, 0, Argv
[0], "missing input GUID database filename with option");
4269 return STATUS_ERROR
;
4271 strcpy (gGlobals
.GuidDatabaseFileName
, Argv
[0]);
4276 // Enable multi-thread build and specify the thread number
4287 Error (NULL
, 0, 0, Argv
[0], "missing input thread number with option");
4289 return STATUS_ERROR
;
4291 gGlobals
.ThreadNumber
= atoi (Argv
[0]);
4292 if (gGlobals
.ThreadNumber
== 0) {
4294 Error (NULL
, 0, 0, Argv
[0], "input thread number should not be %s", Argv
[1]);
4295 return STATUS_ERROR
;
4296 } else if (gGlobals
.ThreadNumber
> MAXIMUM_WAIT_OBJECTS
) {
4298 Error (NULL
, 0, 0, Argv
[0], "input thread number should not greater than %d", MAXIMUM_WAIT_OBJECTS
);
4299 return STATUS_ERROR
;
4305 // Specify the multi-thread build target
4316 Error (NULL
, 0, 0, Argv
[0], "missing input build target with option");
4318 return STATUS_ERROR
;
4319 } else if (_stricmp (Argv
[0], "all") == 0) {
4320 gGlobals
.BuildTarget
|= BUILD_TARGET_ALL
;
4321 } else if (_stricmp (Argv
[0], "libraries") == 0) {
4322 gGlobals
.BuildTarget
|= BUILD_TARGET_LIBRARIES
;
4323 } else if (_stricmp (Argv
[0], "components") == 0) {
4324 gGlobals
.BuildTarget
|= BUILD_TARGET_COMPONENTS
;
4327 Error (NULL
, 0, 0, Argv
[0], "input build target not supported");
4334 gGlobals
.Verbose
= 1;
4338 Error (NULL
, 0, 0, Argv
[0], "unrecognized option");
4339 return STATUS_ERROR
;
4349 // Must be at least one arg left
4352 gGlobals
.DscFilename
= Argv
[0];
4355 if (gGlobals
.DscFilename
== NULL
) {
4356 Error (NULL
, 0, 0, NULL
, "must specify DSC filename on command line");
4357 return STATUS_ERROR
;
4360 // Make a global symbol for the DSC filename
4362 AddSymbol (DSC_FILENAME
, gGlobals
.DscFilename
, SYM_GLOBAL
| SYM_FILENAME
);
4364 // If no output makefile specified, take the default
4366 if (gGlobals
.MakefileName
[0] == 0) {
4367 strcpy (gGlobals
.MakefileName
, MAKEFILE_OUT_NAME
);
4370 // Get the current working directory and use it for the build directory.
4371 // Only do this if they have not defined it on the command line. Do the
4372 // same for the bin dir, output dir, and library directory.
4374 Cptr
= GetSymbolValue (BUILD_DIR
);
4376 Cptr
= _getcwd (NULL
, 0);
4378 AddSymbol (BUILD_DIR
, Cptr
, SYM_OVERWRITE
| SYM_GLOBAL
| SYM_FILEPATH
);
4380 ReplaceSlash (Cptr
);
4389 // Default build target is all
4391 if (gGlobals
.BuildTarget
== 0) {
4392 gGlobals
.BuildTarget
= BUILD_TARGET_ALL
;
4398 /*****************************************************************************
4399 ******************************************************************************/
4409 if (Syms
->Name
!= NULL
) {
4413 if (Syms
->Value
!= NULL
) {
4425 /*****************************************************************************
4426 ******************************************************************************/
4437 len
= strlen (FileName
);
4439 return FILETYPE_UNKNOWN
;
4443 Cptr
= FileName
+ len
- 1;
4444 while ((*Cptr
!= '.') && (Cptr
>= FileName
)) {
4451 for (i
= 0; mFileTypes
[i
].Extension
!= NULL
; i
++) {
4452 len
= strlen (mFileTypes
[i
].Extension
);
4453 if (_strnicmp (mFileTypes
[i
].Extension
, Cptr
, len
) == 0) {
4454 if ((*(Cptr
+ len
) == 0) || isspace (*(Cptr
+ len
))) {
4455 return mFileTypes
[i
].FileType
;
4461 return FILETYPE_UNKNOWN
;
4464 // Determine if a given file is a standard include file. If we don't know,
4465 // then assume it's not.
4477 len
= strlen (FileName
);
4482 Cptr
= FileName
+ len
- 1;
4483 while ((*Cptr
!= '.') && (Cptr
>= FileName
)) {
4489 // Now go through the list of filename extensions and try to find
4490 // a match for this file extension.
4492 for (i
= 0; mFileTypes
[i
].Extension
!= NULL
; i
++) {
4493 len
= strlen (mFileTypes
[i
].Extension
);
4494 if (_strnicmp (mFileTypes
[i
].Extension
, Cptr
, len
) == 0) {
4496 // Make sure that's all there is to the filename extension.
4498 if ((*(Cptr
+ len
) == 0) || isspace (*(Cptr
+ len
))) {
4499 return mFileTypes
[i
].FileFlags
& FILE_FLAG_INCLUDE
;
4508 /*****************************************************************************
4509 ******************************************************************************/
4512 StripTrailingSpaces (
4517 Cptr
= Str
+ strlen (Str
) - 1;
4518 while (Cptr
> Str
) {
4519 if (isspace (*Cptr
)) {
4528 /*****************************************************************************
4529 ******************************************************************************/
4539 // Don't set it if the user specified it on the command line.
4541 EfiSource
= GetSymbolValue (EFI_SOURCE
);
4542 if ( EfiSource
!= NULL
) {
4543 ReplaceSlash (EfiSource
);
4544 if (EfiSource
[strlen (EfiSource
) - 1] == '\\') {
4545 EfiSource
[strlen (EfiSource
) - 1] = 0;
4547 return STATUS_SUCCESS
;
4551 // Get the environmental variable setting of EFI_SOURCE.
4553 EfiSource
= getenv (EFI_SOURCE
);
4554 if (EfiSource
!= NULL
) {
4555 ReplaceSlash (EfiSource
);
4556 if (EfiSource
[strlen (EfiSource
) - 1] == '\\') {
4557 EfiSource
[strlen (EfiSource
) - 1] = 0;
4559 AddSymbol (EFI_SOURCE
, EfiSource
, SYM_GLOBAL
| SYM_FILEPATH
);
4560 return STATUS_SUCCESS
;
4563 Error (NULL
, 0, 0, NULL
, "could not determine EFI_SOURCE");
4564 return STATUS_ERROR
;
4574 INT8 Line
[MAX_LINE_LEN
];
4577 va_start (List
, Fmt
);
4578 vsprintf (Line
, Fmt
, List
);
4579 if (PrintMask
& gGlobals
.Verbose
) {
4580 fprintf (stdout
, "%s\n", Line
);
4593 const char *Str
[] = {
4594 UTILITY_NAME
" "UTILITY_VERSION
" - Intel Process DSC File Utility",
4595 " Copyright (C), 2004 - 2008 Intel Corporation",
4597 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
4598 " Built from "UTILITY_BUILD
", project of "UTILITY_VENDOR
,
4602 " "UTILITY_NAME
" [OPTION]... DSCFILE",
4604 " -d var=value to define symbol 'var' to 'value'",
4605 " -v for verbose mode",
4606 " -g filename to preparse GUID listing file",
4607 " -x filename to create a cross-reference file",
4608 " -n threadnumber to build with multi-thread",
4609 " -t target to build the specified target:",
4610 " all, libraries or components",
4613 for (Index
= 0; Str
[Index
] != NULL
; Index
++) {
4614 fprintf (stdout
, "%s\n", Str
[Index
]);
4620 Routine Description:
4622 Process the [defines] section in the DSC file.
4626 DscFile - pointer to the DSCFile class that contains the relevant info.
4630 0 if not necessarily an absolute path
4636 ProcessDSCDefinesSection (
4640 INT8 Line
[MAX_LINE_LEN
];
4641 INT8 Line2
[MAX_EXP_LINE_LEN
];
4646 // Look for a [defines] section and process it
4648 Sect
= DSCFileFindSection (DscFile
, DEFINES_SECTION_NAME
);
4650 return STATUS_ERROR
;
4653 // Read lines while they're valid
4655 while (DSCFileGetLine (DscFile
, Line
, sizeof (Line
)) != NULL
) {
4657 // Expand symbols on the line
4659 if (ExpandSymbols (Line
, Line2
, sizeof (Line2
), 0)) {
4660 return STATUS_ERROR
;
4665 Cptr
= StripLine (Line2
);
4668 // Make the assignment
4670 AddSymbol (Line2
, NULL
, SYM_OVERWRITE
| SYM_GLOBAL
);
4674 return STATUS_SUCCESS
;
4683 Routine Description:
4685 Determine if a given filename contains the full path information.
4689 FileName - the name of the file, with symbol expanded.
4693 0 if not necessarily an absolute path
4699 // If the first character is a-z, and the second character is a colon, then
4700 // it is an absolute path.
4702 if (isalpha (FileName
[0]) && (FileName
[1] == ':')) {
4714 SMART_FILE
*SmartFile
;
4718 SmartFile
= malloc (sizeof (SMART_FILE
));
4719 if (SmartFile
== NULL
) {
4722 memset (SmartFile
, 0, sizeof (SMART_FILE
));
4724 SmartFile
->FileName
= malloc (strlen (FileName
) + 1);
4725 if (SmartFile
->FileName
== NULL
){
4726 SmartFree (SmartFile
);
4729 strcpy (SmartFile
->FileName
, FileName
);
4731 if ((Fptr
= fopen (FileName
, "r")) != NULL
) {
4732 fseek (Fptr
, 0, SEEK_END
);
4733 FileSize
= ftell (Fptr
);
4734 fseek (Fptr
, 0, SEEK_SET
);
4735 SmartFile
->FileContent
= malloc (FileSize
+ 1);
4736 if (SmartFile
->FileContent
!= NULL
) {
4737 memset (SmartFile
->FileContent
, 0, FileSize
+ 1);
4739 // Usually FileLength < FileSize, because in text mode, carriage return¨Clinefeed
4740 // combinations are translated into single linefeeds on input
4742 SmartFile
->FileLength
= fread (SmartFile
->FileContent
, sizeof(char), FileSize
, Fptr
);
4748 // No previous output file content, re-create the file
4750 if (SmartFile
->FileContent
== NULL
) {
4751 if ((SmartFile
->FilePtr
= fopen (FileName
, "w")) == NULL
) {
4752 SmartFree (SmartFile
);
4762 SMART_FILE
*SmartFile
,
4768 if (SmartFile
->FilePtr
!= NULL
) {
4769 return fprintf (SmartFile
->FilePtr
, "%s", String
);
4771 StrLen
= strlen (String
);
4772 if ((StrLen
> SmartFile
->FileLength
- SmartFile
->FilePosition
) ||
4773 (_strnicmp (&SmartFile
->FileContent
[SmartFile
->FilePosition
], String
, StrLen
) != 0)) {
4775 // file changed, need to re-create.
4777 if ((SmartFile
->FilePtr
= fopen (SmartFile
->FileName
, "w")) == NULL
) {
4778 Error (NULL
, 0, 0, SmartFile
->FileName
, "could not open file for writing when SmartWrite");
4781 SmartFile
->FileContent
[SmartFile
->FilePosition
] = 0;
4782 fprintf (SmartFile
->FilePtr
, "%s%s", SmartFile
->FileContent
, String
);
4786 SmartFile
->FilePosition
+= StrLen
;
4794 SMART_FILE
*SmartFile
4797 if ((SmartFile
->FilePtr
== NULL
) && (SmartFile
->FilePosition
< SmartFile
->FileLength
)) {
4799 // The new file is smaller than before, re-create it.
4801 if ((SmartFile
->FilePtr
= fopen (SmartFile
->FileName
, "w")) == NULL
) {
4802 Error (NULL
, 0, 0, SmartFile
->FileName
, "could not open file for writing when SmartClose");
4804 SmartFile
->FileContent
[SmartFile
->FilePosition
] = 0;
4805 fprintf (SmartFile
->FilePtr
, "%s", SmartFile
->FileContent
);
4809 SmartFree(SmartFile
);
4815 SMART_FILE
*SmartFile
4818 if (SmartFile
== NULL
) {
4822 if (SmartFile
->FileName
!= NULL
) {
4823 free (SmartFile
->FileName
);
4826 if (SmartFile
->FileContent
!= NULL
) {
4827 free (SmartFile
->FileContent
);
4830 if (SmartFile
->FilePtr
!= NULL
) {
4831 fclose (SmartFile
->FilePtr
);
4842 SYMBOL
**SymbolList
,
4848 Routine Description:
4850 Add module name in the global module list.
4851 For the same module names, it is only added once.
4854 SymbolList : add name into this list
4855 ModuleName : point to one module name char string.
4856 InfName : point to this module inf file name with path.
4860 0 : Successfully add input name into the global list.
4861 other value : allocate memory failed.
4865 SYMBOL
*CurrentSymbol
;
4869 // Get the global module list.
4871 CurrentSymbol
= *SymbolList
;
4872 LastSymbol
= *SymbolList
;
4875 // Search whether this module name has been added into the global list.
4877 while (CurrentSymbol
!= NULL
) {
4878 if (_stricmp (CurrentSymbol
->Name
, ModuleName
) == 0) {
4879 if ((CurrentSymbol
->Value
== NULL
) && (InfName
== NULL
)) {
4881 } else if ((CurrentSymbol
->Value
!= NULL
) && (InfName
!= NULL
) && \
4882 (_stricmp (CurrentSymbol
->Value
, InfName
) == 0)) {
4886 LastSymbol
= CurrentSymbol
;
4887 CurrentSymbol
= CurrentSymbol
->Next
;
4891 // Add new module name in list.
4893 if (CurrentSymbol
== NULL
) {
4894 CurrentSymbol
= (SYMBOL
*) malloc (sizeof (SYMBOL
));
4895 if (CurrentSymbol
== NULL
) {
4896 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
4899 memset ((INT8
*) CurrentSymbol
, 0, sizeof (SYMBOL
));
4901 if (ModuleName
!= NULL
) {
4902 CurrentSymbol
->Name
= (INT8
*) malloc (strlen (ModuleName
) + 1);
4903 strcpy (CurrentSymbol
->Name
, ModuleName
);
4906 if (InfName
!= NULL
) {
4907 CurrentSymbol
->Value
= (INT8
*) malloc (strlen (InfName
) + 1);
4908 strcpy (CurrentSymbol
->Value
, InfName
);
4911 if (LastSymbol
== NULL
) {
4912 *SymbolList
= CurrentSymbol
;
4914 LastSymbol
->Next
= CurrentSymbol
;
4929 Routine Description:
4931 Replace '/' with '\\'