3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. 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()
32 #include "Exceptions.h"
35 #include "EfiUtilityMsgs.h"
36 #include "TianoBind.h"
38 // Disable warning for while(1) code
40 #pragma warning(disable : 4127)
42 // Disable warning for unreferenced function parameters
44 #pragma warning(disable : 4100)
48 #define PROGRAM_NAME "ProcessDsc"
51 // Common symbol name definitions. For example, the user can reference
52 // $(BUILD_DIR) in their DSC file and we will expand it for them (usually).
53 // I've defined the equivalents here in case we want to change the name the
54 // user references, in which case we just change the string value here and
55 // our code still works.
57 #define BUILD_DIR "BUILD_DIR"
58 #define EFI_SOURCE "EFI_SOURCE"
59 #define DEST_DIR "DEST_DIR"
60 #define SOURCE_DIR "SOURCE_DIR"
61 #define LIB_DIR "LIB_DIR"
62 #define BIN_DIR "BIN_DIR"
63 #define OUT_DIR "OUT_DIR"
64 #define INF_FILENAME "INF_FILENAME"
65 #define SOURCE_RELATIVE_PATH "SOURCE_RELATIVE_PATH"
66 #define SOURCE_BASE_NAME "SOURCE_BASE_NAME"
67 #define SOURCE_FILE_NAME "SOURCE_FILE_NAME" // c:\FullPath\File.c
68 #define PROCESSOR "PROCESSOR"
70 #define BASE_NAME "BASE_NAME"
72 #define FILE_GUID "FILE_GUID"
73 #define COMPONENT_TYPE_FILE "FILE"
74 #define BUILD_TYPE "BUILD_TYPE"
75 #define FFS_EXT "FFS_EXT" // FV_EXT is deprecated -- extension of FFS file
76 #define MAKEFILE_NAME "MAKEFILE_NAME" // name of component's output makefile
77 #define PLATFORM "PLATFORM" // for more granularity
78 #define PACKAGE_FILENAME "PACKAGE_FILENAME"
79 #define PACKAGE "PACKAGE"
80 #define PACKAGE_TAG "PACKAGE_TAG" // alternate name to PACKAGE
81 #define SHORT_NAMES "SHORT_NAMES" // for 8.3 names of symbols
82 #define APRIORI "APRIORI" // to add to apriori list
83 #define OPTIONAL_COMPONENT "OPTIONAL" // define as non-zero for optional INF files
84 #define SOURCE_SELECT "SOURCE_SELECT" // say SOURCE_SELECT=smm,common to select INF sources
85 #define NONFFS_FV "NONFFS_FV" // for non-FFS FV such as working & spare block FV
86 #define SKIP_FV_NULL "SKIP_FV_NULL" // define as nonzero to not build components with FV=NULL
87 #define SOURCE_COMPILE_TYPE "SOURCE_COMPILE_TYPE" // to build a source using a custom build section in the DSC file
88 #define SOURCE_FILE_EXTENSION "SOURCE_FILE_EXTENSION"
89 #define COMPILE_SELECT "COMPILE_SELECT"
90 #define SOURCE_OVERRIDE_PATH "SOURCE_OVERRIDE_PATH" // get source files from here first
91 #define MAKEFILE_OUT_SECTION_NAME "makefile.out"
92 #define COMMON_SECTION_NAME "common" // shared files or functionality
93 #define NMAKE_SECTION_NAME "nmake"
94 #define SOURCES_SECTION_NAME "sources"
95 #define COMPONENTS_SECTION_NAME "components"
96 #define INCLUDE_SECTION_NAME "includes"
97 #define DEFINES_SECTION_NAME "defines"
98 #define LIBRARIES_SECTION_NAME "libraries"
99 #define LIBRARIES_PLATFORM_SECTION_NAME "libraries.platform"
100 #define MAKEFILE_SECTION_NAME "makefile"
101 #define COMPONENT_TYPE "component_type"
102 #define PLATFORM_STR "\\platform\\" // to determine EFI_SOURCE
103 #define MAKEFILE_OUT_NAME "makefile.out" // if not specified on command line
104 #define MODULE_MAKEFILE_NAME "module.mak" // record all module makefile targets
105 #define MODULE_NAME_FILE "module.list" // record all module names defined in the dsc file
106 #define GLOBAL_LINK_LIB_NAME "CompilerStub" // Lib added in link option, maybe removed in the future
107 #define MODULE_BASE_NAME_WIDTH 25 // Width for module name output
110 // When a symbol is defined as "NULL", it gets saved in the symbol table as a 0-length
111 // string. Use this macro to detect if a symbol has been defined this way.
113 #define IS_NULL_SYMBOL_VALUE(var) ((var != NULL) && (strlen (var) == 0))
116 // Defines for file types
118 #define FILETYPE_UNKNOWN 0
120 #define FILETYPE_ASM 2
122 #define FILETYPE_VFR 4
123 #define FILETYPE_INC 5
129 INT8
*Extension
; // file extension
130 INT8
*BuiltExtension
;
136 // Define masks for the FileFlags field
138 #define FILE_FLAG_INCLUDE 0x01
139 #define FILE_FLAG_SOURCE 0x02
142 // This table describes a from-to list of files. For
143 // example, when a ".c" is built, it results in a ".obj" file.
145 static const FILETYPE mFileTypes
[] = {
169 }, // actually *.vfr -> *.c -> *.obj
197 // Structure to split up a file into its different parts.
208 // Maximum length for any line in any file after symbol expansion
210 #define MAX_EXP_LINE_LEN (MAX_LINE_LEN * 2)
213 // Linked list to keep track of all symbols
215 typedef struct _SYMBOL
{
216 struct _SYMBOL
*Next
;
217 int Type
; // local or global symbol
223 // Define new SYMBOL list to record all module name used in the platform.dsc file.
225 SYMBOL
*gModuleList
= NULL
;
228 // This structure is used to save globals
233 INT8 MakefileName
[MAX_PATH
]; // output makefile name
234 INT8 XRefFileName
[MAX_PATH
];
235 INT8 GuidDatabaseFileName
[MAX_PATH
];
236 INT8 ModuleMakefileName
[MAX_PATH
];
238 FILE *ModuleMakefileFptr
;
245 // This gets dumped to the head of makefile.out
247 static const INT8
*MakefileHeader
[] = {
251 "# File auto-generated by build utility",
259 "# Auto-generated makefile for building of EFI components/libraries",
267 // Function prototypes
290 ParseGuidDatabaseFile (
294 #define DSC_SECTION_TYPE_COMPONENTS 0
295 #define DSC_SECTION_TYPE_LIBRARIES 1
296 #define DSC_SECTION_TYPE_PLATFORM_LIBRARIES 2
300 ProcessSectionComponents (
307 ProcessComponentFile (
315 ProcessIncludeFiles (
316 DSC_FILE
*ComponentFile
,
322 ProcessIncludeFilesSingle (
323 DSC_FILE
*ComponentFile
,
329 // Mode flags for processing source files
331 #define SOURCE_MODE_BUILD_COMMANDS 0x01
332 #define SOURCE_MODE_SOURCE_FILES 0x02
338 DSC_FILE
*ComponentFile
,
345 ProcessSourceFilesSection (
347 DSC_FILE
*ComponentFile
,
356 DSC_FILE
*ComponentFile
,
362 ProcessObjectsSingle (
363 DSC_FILE
*ComponentFile
,
371 DSC_FILE
*ComponentFile
,
378 DSC_FILE
*ComponentFile
,
385 ProcessIncludesSection (
386 DSC_FILE
*ComponentFile
,
392 ProcessIncludesSectionSingle (
393 DSC_FILE
*ComponentFile
,
400 ProcessINFNMakeSection (
401 DSC_FILE
*ComponentFile
,
407 ProcessINFDefinesSection (
408 DSC_FILE
*ComponentFile
413 ProcessINFDefinesSectionSingle (
414 DSC_FILE
*ComponentFile
,
420 ProcessSectionLibraries (
427 ProcessDSCDefinesSection (
478 WriteCompileCommands (
487 WriteCommonMakefile (
495 WriteComponentTypeBuildCommands (
503 StripTrailingSpaces (
546 SMART_FILE
*SmartFile
563 /*****************************************************************************/
573 Main utility entry point.
577 Argc - Standard app entry point args.
578 Argv - Standard app entry point args.
590 INT8 Line
[MAX_LINE_LEN
];
591 INT8 ExpLine
[MAX_LINE_LEN
];
596 SetUtilityName (PROGRAM_NAME
);
600 DSCFileInit (&DSCFile
);
602 // Initialize the firmware volume data
606 // Exception handling for this block of code.
610 // Process command-line options.
612 if (ProcessOptions (Argc
, Argv
)) {
613 EMsg
= CatchException ();
615 fprintf (stderr
, "%s\n", EMsg
);
621 // Parse the GUID database file if specified
623 if (gGlobals
.GuidDatabaseFileName
[0] != 0) {
624 ParseGuidDatabaseFile (gGlobals
.GuidDatabaseFileName
);
627 // Set the output cross-reference file if applicable
629 if (gGlobals
.XRefFileName
[0]) {
630 CFVSetXRefFileName (gGlobals
.XRefFileName
);
634 // Now get the EFI_SOURCE directory which we use everywhere.
636 if (GetEfiSource ()) {
641 // Pre-process the DSC file to get section info.
643 if (DSCFileSetFile (&DSCFile
, gGlobals
.DscFilename
) != 0) {
644 goto ProcessingError
;
648 // Set output makefile name for single module build
650 strcpy (gGlobals
.ModuleMakefileName
, MODULE_MAKEFILE_NAME
);
653 // Try to open all final output makefiles
655 if ((gGlobals
.MakefileFptr
= fopen (gGlobals
.MakefileName
, "w")) == NULL
) {
656 Error (NULL
, 0, 0, gGlobals
.MakefileName
, "failed to open output makefile for writing");
657 goto ProcessingError
;
659 if ((gGlobals
.ModuleMakefileFptr
= fopen (gGlobals
.ModuleMakefileName
, "w")) == NULL
) {
660 Error (NULL
, 0, 0, gGlobals
.ModuleMakefileName
, "failed to open output makefile for writing");
661 goto ProcessingError
;
665 // Write the header out to the makefiles
667 for (i
= 0; MakefileHeader
[i
] != NULL
; i
++) {
668 fprintf (gGlobals
.MakefileFptr
, "%s\n", MakefileHeader
[i
]);
669 fprintf (gGlobals
.ModuleMakefileFptr
, "%s\n", MakefileHeader
[i
]);
673 // Init global potint = NULL
675 gGlobals
.ModuleList
= NULL
;
676 gGlobals
.OutdirList
= NULL
;
679 // Process the [defines] section in the DSC file to get any defines we need
682 ProcessDSCDefinesSection (&DSCFile
);
683 if (ExceptionThrown ()) {
684 goto ProcessingError
;
687 // Write out the [makefile.out] section data to the output makefiles
689 Sect
= DSCFileFindSection (&DSCFile
, MAKEFILE_OUT_SECTION_NAME
);
691 while (DSCFileGetLine (&DSCFile
, Line
, sizeof (Line
)) != NULL
) {
692 ExpandSymbols (Line
, ExpLine
, sizeof (ExpLine
), 0);
694 // Write the line to the output makefiles
696 fprintf (gGlobals
.MakefileFptr
, ExpLine
);
697 fprintf (gGlobals
.ModuleMakefileFptr
, ExpLine
);
702 // Add a pseudo target for GLOBAL_LINK_LIB_NAME to avoid single module build
703 // failure when this lib is not used.
705 fprintf (gGlobals
.ModuleMakefileFptr
, "%sbuild ::\n\n", GLOBAL_LINK_LIB_NAME
);
707 fprintf (gGlobals
.MakefileFptr
, "libraries : \n");
709 // Process [libraries] section in the DSC file
711 Sect
= DSCFileFindSection (&DSCFile
, LIBRARIES_SECTION_NAME
);
713 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_LIBRARIES
, 0);
716 if (ExceptionThrown ()) {
717 goto ProcessingError
;
720 // Process [libraries.platform] section in the DSC file
722 Sect
= DSCFileFindSection (&DSCFile
, LIBRARIES_PLATFORM_SECTION_NAME
);
724 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_PLATFORM_LIBRARIES
, 0);
727 fprintf (gGlobals
.MakefileFptr
, "\n");
728 if (ExceptionThrown ()) {
729 goto ProcessingError
;
733 // Process [components] section in the DSC file
735 Sect
= DSCFileFindSection (&DSCFile
, COMPONENTS_SECTION_NAME
);
737 fprintf (gGlobals
.MakefileFptr
, "components_0 : \n");
738 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_COMPONENTS
, 0);
739 fprintf (gGlobals
.MakefileFptr
, "\n");
742 if (ExceptionThrown ()) {
743 goto ProcessingError
;
746 // Now cycle through all [components.1], [components.2], ....[components.n].
747 // This is necessary to support building of firmware volumes that may contain
748 // other encapsulated firmware volumes (ala capsules).
752 RemoveSymbol (FV
, SYM_GLOBAL
);
753 sprintf (Line
, "%s.%d", COMPONENTS_SECTION_NAME
, i
);
754 Sect
= DSCFileFindSection (&DSCFile
, Line
);
756 fprintf (gGlobals
.MakefileFptr
, "components_%d : \n", i
);
757 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_COMPONENTS
, i
);
758 fprintf (gGlobals
.MakefileFptr
, "\n");
763 if (ExceptionThrown ()) {
764 goto ProcessingError
;
771 EMsg
= CatchException ();
773 fprintf (stderr
, "%s\n", EMsg
);
774 fprintf (stderr
, "Processing aborted\n");
779 // Create the FV files if no fatal errors or errors
781 if (GetUtilityStatus () < STATUS_ERROR
) {
782 CFVWriteInfFiles (&DSCFile
, gGlobals
.MakefileFptr
);
786 // Write all module name into MODULE_NAME_FILE file.
788 if ((FpModule
= fopen (MODULE_NAME_FILE
, "w")) != NULL
) {
789 TempSymbol
= gGlobals
.ModuleList
;
790 while (TempSymbol
!= NULL
) {
791 fprintf (FpModule
, " %-*s %s \n", MODULE_BASE_NAME_WIDTH
, TempSymbol
->Name
, TempSymbol
->Value
);
792 TempSymbol
= TempSymbol
->Next
;
799 // Close the all the output makefiles
801 if (gGlobals
.MakefileFptr
!= NULL
) {
802 fclose (gGlobals
.MakefileFptr
);
803 gGlobals
.MakefileFptr
= NULL
;
806 if (gGlobals
.ModuleMakefileFptr
!= NULL
) {
807 fclose (gGlobals
.ModuleMakefileFptr
);
808 gGlobals
.ModuleMakefileFptr
= NULL
;
814 FreeSymbols (gGlobals
.ModuleList
);
815 FreeSymbols (gGlobals
.OutdirList
);
816 FreeSymbols (gGlobals
.Symbol
);
817 gGlobals
.Symbol
= NULL
;
819 DSCFileDestroy (&DSCFile
);
821 EMsg
= CatchException ();
823 fprintf (stderr
, "%s\n", EMsg
);
824 fprintf (stderr
, "Processing aborted\n");
827 return GetUtilityStatus ();
832 ProcessSectionComponents (
841 Process the [components] or [libraries] section in the description file. We
842 use this function for both since they're very similar. Here we just
843 read each line from the section, and if it's valid, call a function to
844 do the actual processing of the component description file.
848 DSCFile - structure containing section info on the description file
849 DscSectionType - type of description section
857 INT8 Line
[MAX_LINE_LEN
];
858 INT8 Line2
[MAX_EXP_LINE_LEN
];
862 // Read lines while they're valid
864 while (DSCFileGetLine (DSCFile
, Line
, sizeof (Line
)) != NULL
) {
866 // Expand symbols on the line
868 if (ExpandSymbols (Line
, Line2
, sizeof (Line2
), 0)) {
874 Cptr
= StripLine (Line2
);
876 Message (2, "Processing component line: %s", Line2
);
877 if (ProcessComponentFile (DSCFile
, Line2
, DscSectionType
, Instance
) != 0) {
888 ProcessComponentFile (
898 Given a line from the [components] or [libraries] section of the description
899 file, process the line to extract the component's INF filename and
900 parameters. Then open the INF file and process it to create a corresponding
905 DSCFile The project DSC file info structure.
906 Libs Indicates whether we're processing the [components]
907 section or the [libraries] section.
908 ArgLine The actual line from the DSC file. Looks something like
909 one of the following:
911 dxe\drivers\vm\vm.dsc PROCESSOR=IA32 DEST_DIR=$(DEST_DIR)\xxx FV=FV1,FV2
912 $(BUILD_DIR).\FvVariable.ffs COMPONENT_TYPE=FILE
913 .\FvVariable.ffs COMPONENT_TYPE=FILE
914 define VAR1=value1 VAR2=value2
928 INT8 FileName
[MAX_PATH
];
929 INT8 ComponentFilePath
[MAX_PATH
];
930 INT8 InLine
[MAX_LINE_LEN
];
931 INT8 Line
[MAX_LINE_LEN
];
935 int ComponentCreated
;
936 int ComponentFilePathAbsolute
;
938 DSC_FILE ComponentFile
;
939 INT8 ComponentMakefileName
[MAX_PATH
];
943 // Now remove all local symbols
945 RemoveLocalSymbols ();
947 // Null out the file pointer in case we take an exception somewhere
948 // and we need to close it only if we opened it.
951 ComponentFilePathAbsolute
= 0;
952 ComponentCreated
= 0;
954 // Skip preceeding spaces on the line
956 while (isspace (*ArgLine
) && (*ArgLine
)) {
960 // Find the end of the component's filename and truncate the line at that
961 // point. From here on out ArgLine is the name of the component filename.
964 while (!isspace (*Cptr
) && *Cptr
) {
974 // Exception-handle processing of this component description file
979 // We also allow a component line format for defines of global symbols
980 // instead of a component filename. In this case, the line looks like:
981 // defines x=abc y=yyy. Be nice and accept "define" and "defines" in a
982 // case-insensitive manner. If it's defines, then make the symbols global.
984 if ((_stricmp (ArgLine
, "define") == 0) || (_stricmp (ArgLine
, "defines") == 0)) {
985 SymType
= SYM_OVERWRITE
| SYM_GLOBAL
;
988 SymType
= SYM_OVERWRITE
| SYM_LOCAL
;
992 // The rest of the component line from the DSC file should be defines
995 End
= StripLine (End
);
998 // If we're processing a "define abc=1 xyz=2" line, then set symbols
999 // as globals per the SymType set above.
1001 Len
= AddSymbol (End
, NULL
, SymType
);
1005 Warning (NULL
, 0, 0, ArgLine
, "unrecognized option in description file");
1012 // If DEBUG_BREAK or EFI_BREAKPOINT is defined, then do a debug breakpoint.
1014 if ((GetSymbolValue ("DEBUG_BREAK") != NULL
) || (GetSymbolValue ("EFI_BREAKPOINT") != NULL
)) {
1019 // If it's a define line, then we're done
1023 // If there is NonFFS_FV, create the FVxxx.inf file
1024 // and include it in makefile.out. Remove the symbol
1025 // in order not to process it again next time
1027 Cptr
= GetSymbolValue (NONFFS_FV
);
1029 NonFFSFVWriteInfFiles (DSCFile
, Cptr
);
1030 RemoveSymbol (NONFFS_FV
, SYM_GLOBAL
);
1037 // Expand symbols in the component description filename to expand the newly
1038 // added local symbols
1040 ExpandSymbols (ArgLine
, Line
, sizeof (Line
), EXPANDMODE_NO_UNDEFS
);
1043 // If we have "c:\path\filename"
1045 ReplaceSlash (Line
);
1046 if (IsAbsolutePath (Line
)) {
1047 ComponentFilePathAbsolute
= 1;
1048 } else if (Line
[0] == '.') {
1050 // or if the path starts with ".", then it's build-dir relative.
1051 // Prepend $(BUILD_DIR) on the file name
1053 sprintf (InLine
, "%s\\%s", GetSymbolValue (BUILD_DIR
), Line
);
1054 strcpy (Line
, InLine
);
1055 ComponentFilePathAbsolute
= 1;
1059 // Save the path from the component name for later. It may be relative or
1062 strcpy (ComponentFilePath
, Line
);
1063 Cptr
= ComponentFilePath
+ strlen (ComponentFilePath
) - 1;
1064 while ((*Cptr
!= '\\') && (Cptr
!= ComponentFilePath
)) {
1068 // Terminate the path.
1073 // Typically the given line is a component description filename. However we
1074 // also allow a FV filename (fvvariable.ffs COMPONENT_TYPE=FILE). If the
1075 // component type is "FILE", then add it to the FV list, create a package
1076 // file, and we're done.
1078 Cptr
= GetSymbolValue (COMPONENT_TYPE
);
1079 if ((Cptr
!= NULL
) && (strncmp (
1081 COMPONENT_TYPE_FILE
,
1082 strlen (COMPONENT_TYPE_FILE
)
1084 if (ComponentFilePathAbsolute
) {
1085 strcpy (InLine
, Line
);
1087 sprintf (InLine
, "%s\\%s", GetSymbolValue (EFI_SOURCE
), Line
);
1092 GetSymbolValue (FV
),
1096 GetSymbolValue (APRIORI
),
1104 // Better have defined processor by this point.
1106 Processor
= GetSymbolValue (PROCESSOR
);
1107 if (Processor
== NULL
) {
1108 Error (NULL
, 0, 0, NULL
, "PROCESSOR not defined for component %s", Line
);
1109 return STATUS_ERROR
;
1113 // The bin, out, and lib dirs are now = $(BUILD_DIR)/$(PROCESSOR). Set them.
1114 // Don't flag them as file paths (required for short 8.3 filenames) since
1115 // they're defined using the BUILD_DIR macro.
1117 sprintf (InLine
, "$(BUILD_DIR)\\%s", Processor
);
1118 AddSymbol (BIN_DIR
, InLine
, SYM_LOCAL
);
1119 AddSymbol (OUT_DIR
, InLine
, SYM_LOCAL
);
1120 AddSymbol (LIB_DIR
, InLine
, SYM_LOCAL
);
1122 // See if it's been destined for an FV. It's possible to not be in an
1123 // FV if they just want to build it.
1125 Cptr
= GetSymbolValue (FV
);
1126 if ((Cptr
!= NULL
) && !IS_NULL_SYMBOL_VALUE (Cptr
)) {
1132 // As an optimization, if they've defined SKIP_FV_NULL as non-zero, and
1133 // the component is not destined for an FV, then skip it.
1134 // Since libraries are never intended for firmware volumes, we have to
1135 // build all of them.
1137 if ((DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) && (IsForFv
== FALSE
)) {
1138 if ((GetSymbolValue (SKIP_FV_NULL
) != NULL
) && (atoi (GetSymbolValue (SKIP_FV_NULL
)) != 0)) {
1139 Message (0, "%s not being built (FV=NULL)", FileName
);
1144 // Prepend EFI_SOURCE to the component description file to get the
1145 // full path. Only do this if the path is not a full path already.
1147 if (ComponentFilePathAbsolute
== 0) {
1148 name
= GetSymbolValue (EFI_SOURCE
);
1149 sprintf (FileName
, "%s\\%s", name
, Line
);
1151 strcpy (FileName
, Line
);
1154 // Print a message, depending on verbose level.
1156 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1157 Message (1, "Processing component %s", FileName
);
1159 Message (1, "Processing library %s", FileName
);
1162 // Open the component's description file and get the sections. If we fail
1163 // to open it, see if they defined "OPTIONAL=1, in which case we'll just
1164 // ignore the component.
1166 TempFptr
= fopen (FileName
, "r");
1167 if (TempFptr
== NULL
) {
1169 // Better have defined OPTIONAL
1171 if (GetSymbolValue (OPTIONAL_COMPONENT
) != NULL
) {
1172 if (atoi (GetSymbolValue (OPTIONAL_COMPONENT
)) != 0) {
1173 Message (0, "Optional component '%s' not found", FileName
);
1178 ParserError (0, FileName
, "failed to open component file");
1179 return STATUS_ERROR
;
1184 DSCFileInit (&ComponentFile
);
1185 ComponentCreated
= 1;
1186 if (DSCFileSetFile (&ComponentFile
, FileName
)) {
1187 Error (NULL
, 0, 0, NULL
, "failed to preprocess component file '%s'", FileName
);
1188 return STATUS_ERROR
;
1191 // Add a symbol for the INF filename so users can create dependencies
1194 AddSymbol (INF_FILENAME
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILENAME
);
1196 // Process the [defines], [defines.$(PROCESSOR)], and [defines.$(PROCESSOR).$(PLATFORM)]
1197 // sections in the INF file
1199 ProcessINFDefinesSection (&ComponentFile
);
1201 // Better have defined FILE_GUID if not a library
1203 if ((GetSymbolValue (GUID
) == NULL
) &&
1204 (GetSymbolValue (FILE_GUID
) == NULL
) &&
1205 (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
)
1207 Error (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "missing FILE_GUID definition in component file");
1208 DSCFileDestroy (&ComponentFile
);
1209 return STATUS_ERROR
;
1212 // Better have defined base name
1214 if (GetSymbolValue (BASE_NAME
) == NULL
) {
1215 Error (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "missing BASE_NAME definition in INF file");
1216 DSCFileDestroy (&ComponentFile
);
1217 return STATUS_ERROR
;
1220 // Better have defined COMPONENT_TYPE, since it's used to find named sections.
1222 if (GetSymbolValue (COMPONENT_TYPE
) == NULL
) {
1223 Error (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "missing COMPONENT_TYPE definition in INF file");
1224 DSCFileDestroy (&ComponentFile
);
1225 return STATUS_ERROR
;
1229 // Create the source directory path from the component file's path. If the component
1230 // file's path is absolute, we may have problems here. Try to account for it though.
1232 if (ComponentFilePathAbsolute
== 0) {
1236 GetSymbolValue (EFI_SOURCE
),
1240 strcpy (FileName
, ComponentFilePath
);
1242 AddSymbol (SOURCE_DIR
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILEPATH
);
1245 // Create the destination path.
1246 // They may have defined DEST_DIR on the component INF line, so it's already
1247 // been defined, If that's the case, then don't set it to the path of this file.
1249 TempCptr
= GetSymbolValue (DEST_DIR
);
1250 if (TempCptr
== NULL
) {
1251 if (ComponentFilePathAbsolute
== 0) {
1253 // The destination path is $(BUILD_DIR)\$(PROCESSOR)\component_path
1258 GetSymbolValue (BUILD_DIR
),
1264 // The destination path is $(BUILD_DIR)\$(PROCESSOR)\$(BASE_NAME)
1269 GetSymbolValue (BUILD_DIR
),
1271 GetSymbolValue (BASE_NAME
)
1274 AddSymbol (DEST_DIR
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILEPATH
);
1276 ReplaceSlash (TempCptr
);
1280 // Create the output directory, then open the output component's makefile
1281 // we're going to create. Allow them to override the makefile name.
1283 TempCptr
= GetSymbolValue (MAKEFILE_NAME
);
1284 if (TempCptr
!= NULL
) {
1285 ExpandSymbols (TempCptr
, ComponentMakefileName
, sizeof (ComponentMakefileName
), EXPANDMODE_NO_UNDEFS
);
1286 TempCptr
= ComponentMakefileName
;
1288 TempCptr
= "makefile";
1291 sprintf (FileName
, "%s\\%s", GetSymbolValue (DEST_DIR
), TempCptr
);
1293 // Save it now with path info
1295 AddSymbol (MAKEFILE_NAME
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILENAME
);
1297 if (MakeFilePath (FileName
)) {
1298 return STATUS_ERROR
;
1301 if ((MakeFptr
= fopen (FileName
, "w")) == NULL
) {
1302 Error (NULL
, 0, 0, FileName
, "could not create makefile");
1303 return STATUS_ERROR
;
1306 // At this point we should have all the info we need to create a package
1307 // file if setup to do so. Libraries don't use package files, so
1308 // don't do this for libs.
1310 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1311 CreatePackageFile (DSCFile
);
1315 // Add Module name to the global module list
1317 AddModuleName (&gGlobals
.ModuleList
, GetSymbolValue (BASE_NAME
), GetSymbolValue (INF_FILENAME
));
1319 // Write an nmake line to makefile.out
1321 fprintf (gGlobals
.MakefileFptr
, " @cd %s\n", Processor
);
1322 fprintf (gGlobals
.MakefileFptr
, " $(MAKE) -f %s all\n", FileName
);
1323 fprintf (gGlobals
.MakefileFptr
, " @cd ..\n");
1326 // Copy the common makefile section from the description file to
1327 // the component's makefile
1329 WriteCommonMakefile (DSCFile
, MakeFptr
, Processor
);
1331 // Process the component's [nmake.common] and [nmake.$(PROCESSOR)] sections
1333 ProcessINFNMakeSection (&ComponentFile
, MakeFptr
);
1335 // Create the SOURCE_FILES macro that includes the names of all source
1336 // files in this component. This macro can then be used elsewhere to
1337 // process all the files making up the component. Required for scanning
1338 // files for string localization.
1340 ProcessSourceFiles (DSCFile
, &ComponentFile
, MakeFptr
, SOURCE_MODE_SOURCE_FILES
);
1342 // Create the include paths. Process [includes.common] and
1343 // [includes.$(PROCESSOR)] and [includes.$(PROCESSOR).$(PLATFORM)] sections.
1345 ProcessIncludesSection (&ComponentFile
, MakeFptr
);
1347 // Process all include source files to create a dependency list that can
1348 // be used in the makefile.
1350 ProcessIncludeFiles (&ComponentFile
, MakeFptr
);
1352 // Process the [sources.common], [sources.$(PROCESSOR)], and
1353 // [sources.$(PROCESSOR).$(PLATFORM)] files and emit their build commands
1355 ProcessSourceFiles (DSCFile
, &ComponentFile
, MakeFptr
, SOURCE_MODE_BUILD_COMMANDS
);
1357 // Process sources again to create an OBJECTS macro
1359 ProcessObjects (&ComponentFile
, MakeFptr
);
1362 // Add Single Module target : build and clean in top level makefile
1364 fprintf (gGlobals
.ModuleMakefileFptr
, "%sbuild ::", GetSymbolValue (BASE_NAME
));
1365 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1366 fprintf (gGlobals
.ModuleMakefileFptr
, " %sbuild", GLOBAL_LINK_LIB_NAME
);
1370 // Process all the libraries to define "LIBS = x.lib y.lib..."
1371 // Be generous and append ".lib" if they forgot.
1372 // Make a macro definition: LIBS = $(LIBS) xlib.lib ylib.lib...
1373 // Also add libs dependency for single module build: basenamebuild :: xlibbuild ylibbuild ...
1375 ProcessLibs (&ComponentFile
, MakeFptr
);
1377 fprintf (gGlobals
.ModuleMakefileFptr
, "\n");
1379 fprintf (gGlobals
.ModuleMakefileFptr
, " @cd %s\n", Processor
);
1380 fprintf (gGlobals
.ModuleMakefileFptr
, " $(MAKE) -f %s all\n", FileName
);
1381 fprintf (gGlobals
.ModuleMakefileFptr
, " @cd ..\n\n");
1383 fprintf (gGlobals
.ModuleMakefileFptr
, "%sclean ::\n", GetSymbolValue (BASE_NAME
));
1384 fprintf (gGlobals
.ModuleMakefileFptr
, " $(MAKE) -f %s clean\n\n", FileName
);
1387 // Emit commands to create the component. These are simply copied from
1388 // the description file to the component's makefile. First look for
1389 // [build.$(PROCESSOR).$(BUILD_TYPE)]. If not found, then look for if
1390 // find a [build.$(PROCESSOR).$(COMPONENT_TYPE)] line.
1392 Cptr
= GetSymbolValue (BUILD_TYPE
);
1394 sprintf (InLine
, "build.%s.%s", Processor
, Cptr
);
1395 WriteComponentTypeBuildCommands (DSCFile
, MakeFptr
, InLine
);
1397 sprintf (InLine
, "build.%s.%s", Processor
, GetSymbolValue (COMPONENT_TYPE
));
1398 WriteComponentTypeBuildCommands (DSCFile
, MakeFptr
, InLine
);
1401 // Add it to the FV if not a library
1403 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1405 // Create the FV filename and add it to the FV.
1406 // By this point we know it's in FV.
1408 Cptr
= GetSymbolValue (FILE_GUID
);
1410 Cptr
= GetSymbolValue (GUID
);
1413 sprintf (InLine
, "%s-%s", Cptr
, GetSymbolValue (BASE_NAME
));
1415 // We've deprecated FV_EXT, which should be FFS_EXT, the extension
1416 // of the FFS file generated by GenFFSFile.
1418 TempCptr
= GetSymbolValue (FFS_EXT
);
1419 if (TempCptr
== NULL
) {
1420 TempCptr
= GetSymbolValue ("FV_EXT");
1425 GetSymbolValue (COMPONENT_TYPE
),
1426 GetSymbolValue (FV
),
1430 GetSymbolValue (APRIORI
),
1431 GetSymbolValue (BASE_NAME
),
1436 // Catch any failures and print the name of the component file
1437 // being processed to assist debugging.
1441 Cptr
= CatchException ();
1443 fprintf (stderr
, "%s\n", Cptr
);
1444 sprintf (InLine
, "Processing of component %s failed", ArgLine
);
1445 ThrowException (InLine
);
1448 if (MakeFptr
!= NULL
) {
1452 if (ComponentCreated
) {
1453 DSCFileDestroy (&ComponentFile
);
1456 return STATUS_SUCCESS
;
1467 INT8 Str
[MAX_LINE_LEN
];
1468 INT8 StrExpanded
[MAX_LINE_LEN
];
1469 SMART_FILE
*PkgFptr
;
1475 // First find out if PACKAGE_FILENAME or PACKAGE is defined. PACKAGE_FILENAME
1476 // is used to specify the exact package file to use. PACKAGE is used to
1477 // specify the package section name.
1479 Package
= GetSymbolValue (PACKAGE_FILENAME
);
1480 if (Package
!= NULL
) {
1482 // Use existing file. We're done.
1484 return STATUS_SUCCESS
;
1487 // See if PACKAGE or PACKAGE_TAG is defined
1489 Package
= GetSymbolValue (PACKAGE
);
1490 if (Package
== NULL
) {
1491 Package
= GetSymbolValue (PACKAGE_TAG
);
1494 if (Package
== NULL
) {
1496 // Not defined either. Assume they are not using the package functionality
1497 // of this utility. However define the PACKAGE_FILENAME macro to the
1498 // best-guess value.
1503 GetSymbolValue (SOURCE_DIR
),
1504 GetSymbolValue (BASE_NAME
)
1508 // Expand symbols in the package filename
1510 ExpandSymbols (Str
, StrExpanded
, sizeof (StrExpanded
), EXPANDMODE_NO_UNDEFS
);
1512 AddSymbol (PACKAGE_FILENAME
, StrExpanded
, SYM_LOCAL
| SYM_FILENAME
);
1513 return STATUS_SUCCESS
;
1516 // Save the position in the DSC file.
1517 // Find the [package.$(COMPONENT_TYPE).$(PACKAGE)] section in the DSC file
1519 Status
= STATUS_SUCCESS
;
1520 DSCFileSavePosition (DSCFile
);
1521 sprintf (Str
, "%s.%s.%s", PACKAGE
, GetSymbolValue (COMPONENT_TYPE
), Package
);
1522 TempSect
= DSCFileFindSection (DSCFile
, Str
);
1523 if (TempSect
!= NULL
) {
1525 // So far so good. Create the name of the package file, then open it up
1526 // for writing. File name is c:\...\oem\platform\nt32\ia32\...\BaseName.pkg.
1531 GetSymbolValue (DEST_DIR
),
1532 GetSymbolValue (BASE_NAME
)
1536 // Expand symbols in the package filename
1538 ExpandSymbols (Str
, StrExpanded
, sizeof (StrExpanded
), EXPANDMODE_NO_UNDEFS
);
1541 // Try to open the file, then save the file name as the PACKAGE_FILENAME
1542 // symbol for use elsewhere.
1544 if ((PkgFptr
= SmartOpen (StrExpanded
)) == NULL
) {
1545 Error (NULL
, 0, 0, Str
, "could not open package file for writing");
1546 Status
= STATUS_ERROR
;
1550 AddSymbol (PACKAGE_FILENAME
, StrExpanded
, SYM_LOCAL
| SYM_FILENAME
);
1552 // Now read lines in from the DSC file and write them back out to the
1553 // package file (with string substitution).
1555 while (DSCFileGetLine (DSCFile
, Str
, sizeof (Str
)) != NULL
) {
1557 // Expand symbols, then write the line out to the package file
1559 ExpandSymbols (Str
, StrExpanded
, sizeof (StrExpanded
), EXPANDMODE_RECURSIVE
);
1560 SmartWrite (PkgFptr
, StrExpanded
);
1568 "cannot locate package section [%s] in DSC file for %s",
1570 GetSymbolValue (INF_FILENAME
)
1572 Status
= STATUS_WARNING
;
1576 if (PkgFptr
!= NULL
) {
1577 SmartClose (PkgFptr
);
1582 // Restore the position in the DSC file
1584 DSCFileRestorePosition (DSCFile
);
1586 return STATUS_SUCCESS
;
1591 ProcessINFDefinesSection (
1592 DSC_FILE
*ComponentFile
1596 Routine Description:
1598 Process the [defines.xxx] sections of the component description file. Process
1599 platform first, then processor. In this way, if a platform wants and override,
1600 that one gets parsed first, and later assignments do not overwrite the value.
1604 ComponentFile - section info on the component file being processed
1612 INT8 Str
[MAX_LINE_LEN
];
1615 // Find a [defines.$(PROCESSOR).$(PLATFORM)] section and process it
1617 Cptr
= GetSymbolValue (PLATFORM
);
1622 DEFINES_SECTION_NAME
,
1623 GetSymbolValue (PROCESSOR
),
1626 ProcessINFDefinesSectionSingle (ComponentFile
, Str
);
1629 // Find a [defines.$(PROCESSOR)] section and process it
1631 sprintf (Str
, "%s.%s", DEFINES_SECTION_NAME
, GetSymbolValue (PROCESSOR
));
1632 ProcessINFDefinesSectionSingle (ComponentFile
, Str
);
1635 // Find a [defines] section and process it
1637 if (ProcessINFDefinesSectionSingle (ComponentFile
, DEFINES_SECTION_NAME
) != STATUS_SUCCESS
) {
1638 Error (NULL
, 0, 0, NULL
, "missing [defines] section in component file %s", GetSymbolValue (INF_FILENAME
));
1639 return STATUS_ERROR
;
1642 return STATUS_SUCCESS
;
1647 ProcessINFDefinesSectionSingle (
1648 DSC_FILE
*ComponentFile
,
1653 INT8 Str
[MAX_LINE_LEN
];
1654 INT8 ExpandedLine
[MAX_LINE_LEN
];
1657 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
1658 if (TempSect
!= NULL
) {
1659 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1660 ExpandSymbols (Str
, ExpandedLine
, sizeof (ExpandedLine
), 0);
1661 Cptr
= StripLine (ExpandedLine
);
1663 // Don't process blank lines.
1667 // Add without overwriting macros specified on the component line
1668 // in the description file
1670 AddSymbol (Cptr
, NULL
, SYM_LOCAL
);
1674 return STATUS_WARNING
;
1677 return STATUS_SUCCESS
;
1682 ProcessINFNMakeSection (
1683 DSC_FILE
*ComponentFile
,
1688 Routine Description:
1690 Process the [nmake.common] and [nmake.$(PROCESSOR)] sections of the component
1691 description file and write and copy them to the component's makefile.
1695 ComponentFile - section info on the component file being processed
1696 MakeFptr - file pointer to the component' makefile we're creating
1700 Always STATUS_SUCCESS right now, since the sections are optional.
1705 INT8 Str
[MAX_LINE_LEN
];
1706 INT8 ExpandedLine
[MAX_LINE_LEN
];
1710 // Copy the [nmake.common] and [nmake.$(PROCESSOR)] sections from the
1711 // component file directly to the output file.
1712 // The line will be stripped and don't print blank lines
1714 sprintf (Str
, "%s.%s", NMAKE_SECTION_NAME
, COMMON_SECTION_NAME
);
1715 TempSect
= DSCFileFindSection (ComponentFile
, Str
);
1716 if (TempSect
!= NULL
) {
1717 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1721 sizeof (ExpandedLine
),
1722 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
1724 Cptr
= StripLine (ExpandedLine
);
1726 fprintf (MakeFptr
, "%s\n", Cptr
);
1730 fprintf (MakeFptr
, "\n");
1732 Error (GetSymbolValue (INF_FILENAME
), 1, 0, Str
, "section not found in component INF file");
1735 sprintf (Str
, "%s.%s", NMAKE_SECTION_NAME
, GetSymbolValue (PROCESSOR
));
1736 TempSect
= DSCFileFindSection (ComponentFile
, Str
);
1737 if (TempSect
!= NULL
) {
1738 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1742 sizeof (ExpandedLine
),
1743 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
1745 Cptr
= StripLine (ExpandedLine
);
1747 fprintf (MakeFptr
, "%s\n", Cptr
);
1751 fprintf (MakeFptr
, "\n");
1754 // Do the same for [nmake.$(PROCESSOR).$(PLATFORM)]
1756 Cptr
= GetSymbolValue (PLATFORM
);
1758 sprintf (Str
, "%s.%s.%s", NMAKE_SECTION_NAME
, GetSymbolValue (PROCESSOR
), Cptr
);
1759 TempSect
= DSCFileFindSection (ComponentFile
, Str
);
1760 if (TempSect
!= NULL
) {
1761 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1765 sizeof (ExpandedLine
),
1766 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
1768 Cptr
= StripLine (ExpandedLine
);
1770 fprintf (MakeFptr
, "%s\n", Cptr
);
1774 fprintf (MakeFptr
, "\n");
1778 return STATUS_SUCCESS
;
1783 ProcessIncludesSection (
1784 DSC_FILE
*ComponentFile
,
1789 Routine Description:
1791 Process the [includes.common], [includes.processor], and
1792 [includes.processor.platform] section of the component description file
1793 and write the appropriate macros to the component's makefile.
1795 Process in reverse order to allow overrides on platform basis.
1799 ComponentFile - section info on the component file being processed
1800 MakeFptr - file pointer to the component' makefile we're creating
1804 Always STATUS_SUCCESS right now, since the sections are optional.
1809 INT8 Str
[MAX_LINE_LEN
];
1814 // Write a useful comment to the output makefile so the user knows where
1815 // the data came from.
1817 fprintf (MakeFptr
, "#\n# Tool-generated list of include paths that are created\n");
1818 fprintf (MakeFptr
, "# from the list of include paths in the [includes.*] sections\n");
1819 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
1822 // We use this a lot here, so get the value only once.
1824 Processor
= GetSymbolValue (PROCESSOR
);
1826 // If they're using an override source path, then add OverridePath and
1827 // OverridePath\$(PROCESSOR) to the list of include paths.
1829 OverridePath
= GetSymbolValue (SOURCE_OVERRIDE_PATH
);
1830 if (OverridePath
!= NULL
) {
1831 ReplaceSlash (OverridePath
);
1832 fprintf (MakeFptr
, "INC = $(INC) -I %s\n", OverridePath
);
1833 fprintf (MakeFptr
, "INC = $(INC) -I %s\\%s \n", OverridePath
, Processor
);
1836 // Try for an [includes.$(PROCESSOR).$(PLATFORM)]
1838 Cptr
= GetSymbolValue (PLATFORM
);
1840 sprintf (Str
, "%s.%s.%s", INCLUDE_SECTION_NAME
, Processor
, Cptr
);
1841 ProcessIncludesSectionSingle (ComponentFile
, MakeFptr
, Str
);
1844 // Now the [includes.$(PROCESSOR)] section
1846 sprintf (Str
, "%s.%s", INCLUDE_SECTION_NAME
, Processor
);
1847 ProcessIncludesSectionSingle (ComponentFile
, MakeFptr
, Str
);
1850 // Now the [includes.common] section
1852 sprintf (Str
, "%s.%s", INCLUDE_SECTION_NAME
, COMMON_SECTION_NAME
);
1853 ProcessIncludesSectionSingle (ComponentFile
, MakeFptr
, Str
);
1858 fprintf (MakeFptr
, "\n");
1859 return STATUS_SUCCESS
;
1862 // Process one of the [includes.xxx] sections to create a list of all
1863 // the include paths.
1867 ProcessIncludesSectionSingle (
1868 DSC_FILE
*ComponentFile
,
1875 INT8 Str
[MAX_LINE_LEN
];
1876 INT8 ExpandedLine
[MAX_LINE_LEN
];
1879 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
1880 if (TempSect
!= NULL
) {
1882 // Add processor subdirectory on every include path
1884 Processor
= GetSymbolValue (PROCESSOR
);
1886 // Copy lines directly
1888 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1889 ExpandSymbols (Str
, ExpandedLine
, sizeof (ExpandedLine
), 0);
1890 Cptr
= StripLine (ExpandedLine
);
1892 // Don't process blank lines
1895 ReplaceSlash (Cptr
);
1897 // Strip off trailing slash
1899 if (Cptr
[strlen (Cptr
) - 1] == '\\') {
1900 Cptr
[strlen (Cptr
) - 1] = 0;
1903 // Special case of ".". Replace it with source path
1904 // and the rest of the line (for .\$(PROCESSOR))
1908 // Handle case of just a "."
1911 fprintf (MakeFptr
, "INC = $(INC) -I $(SOURCE_DIR)\n");
1914 "INC = $(INC) -I $(SOURCE_DIR)\\%s \n",
1919 // Handle case of ".\path\path\path" or "..\path\path\path"
1923 "INC = $(INC) -I $(SOURCE_DIR)\\%s \n",
1928 "INC = $(INC) -I $(SOURCE_DIR)\\%s\\%s \n",
1933 } else if ((Cptr
[1] != ':') && isalpha (*Cptr
)) {
1934 fprintf (MakeFptr
, "INC = $(INC) -I $(EFI_SOURCE)\\%s \n", Cptr
);
1937 "INC = $(INC) -I $(EFI_SOURCE)\\%s\\%s \n",
1943 // The line is something like: $(EFI_SOURCE)\dxe\include. Add it to
1944 // the existing $(INC) definition. Add user includes before any
1945 // other existing paths.
1947 fprintf (MakeFptr
, "INC = $(INC) -I %s \n", Cptr
);
1948 fprintf (MakeFptr
, "INC = $(INC) -I %s\\%s \n", Cptr
, Processor
);
1954 return STATUS_SUCCESS
;
1959 ProcessSourceFiles (
1961 DSC_FILE
*ComponentFile
,
1967 Routine Description:
1969 Process the [sources.common], [sources.$(PROCESSOR)], and
1970 [sources.$(PROCESSOR).$(PLATFORM] sections of the component
1971 description file and write the appropriate build commands out to the
1972 component's makefile. If $(SOURCE_SELECT) is defined, then it overrides
1973 the source selections. We use this functionality for SMM.
1977 ComponentFile - section info on the component file being processed
1978 MakeFptr - file pointer to the component' makefile we're creating
1979 DSCFile - section info on the description file we're processing
1980 Mode - to write build commands, or just create a list
1985 Always STATUS_SUCCESS right now, since the sections are optional.
1989 INT8 Str
[MAX_LINE_LEN
];
1996 INT8
*CopySourceSelect
;
1998 if (Mode
& SOURCE_MODE_SOURCE_FILES
) {
2000 // Write a useful comment to the output makefile so the user knows where
2001 // the data came from.
2003 fprintf (MakeFptr
, "#\n# Tool-generated list of source files that are created\n");
2004 fprintf (MakeFptr
, "# from the list of source files in the [sources.*] sections\n");
2005 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2009 // We use this a lot here, so get the value only once.
2011 Processor
= GetSymbolValue (PROCESSOR
);
2013 // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll
2014 // select each [sources.xxx] and [sources.yyy] files and process
2017 SourceSelect
= GetSymbolValue (SOURCE_SELECT
);
2019 if (SourceSelect
!= NULL
) {
2021 // Make a copy of the string and break it up (comma-separated) and
2022 // select each [sources.*] file from the INF.
2024 CopySourceSelect
= (INT8
*) malloc (strlen (SourceSelect
) + 1);
2025 if (CopySourceSelect
== NULL
) {
2026 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2027 return STATUS_ERROR
;
2030 strcpy (CopySourceSelect
, SourceSelect
);
2031 CStart
= CopySourceSelect
;
2035 while (*CEnd
&& *CEnd
!= ',') {
2041 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, CStart
);
2042 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2044 // Restore the terminator and advance
2053 free (CopySourceSelect
);
2057 // Process all the [sources.common] source files to make them build
2059 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, COMMON_SECTION_NAME
);
2060 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2062 // Now process the [sources.$(PROCESSOR)] files.
2064 sprintf (Str
, "sources.%s", Processor
);
2065 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2067 // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files.
2069 Platform
= GetSymbolValue (PLATFORM
);
2070 if (Platform
!= NULL
) {
2071 sprintf (Str
, "sources.%s.%s", Processor
, Platform
);
2072 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2076 fprintf (MakeFptr
, "\n");
2077 return STATUS_SUCCESS
;
2082 Routine Description:
2083 Given a source file line from an INF file, parse it to see if there are
2084 any defines on it. If so, then add them to the symbol table.
2085 Also, terminate the line after the file name.
2088 SourceFileLine - a line from a [sources.?] section of the INF file. Likely
2091 MySourceFile.c BUILT_NAME=$(BUILD_DIR)\MySourceFile.obj
2100 INT8
*SourceFileLine
2107 for (; *SourceFileLine
&& isspace (*SourceFileLine
); SourceFileLine
++)
2109 for (; *SourceFileLine
&& !isspace (*SourceFileLine
); SourceFileLine
++)
2111 if (*SourceFileLine
) {
2112 *SourceFileLine
= 0;
2115 // AddSymbol() will parse it for us, and return the length. Keep calling
2116 // it until it reports an error or is done.
2119 Len
= AddSymbol (SourceFileLine
, NULL
, SYM_FILE
);
2120 SourceFileLine
+= Len
;
2125 // Process a single section of source files in the component INF file
2129 ProcessSourceFilesSection (
2131 DSC_FILE
*ComponentFile
,
2138 INT8 FileName
[MAX_EXP_LINE_LEN
];
2139 INT8 FilePath
[MAX_PATH
];
2140 INT8 TempFileName
[MAX_PATH
];
2142 INT8 Str
[MAX_LINE_LEN
];
2147 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2148 if (TempSect
!= NULL
) {
2149 Processor
= GetSymbolValue (PROCESSOR
);
2150 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2151 Cptr
= StripLine (Str
);
2153 // Don't process blank lines
2157 // Expand symbols in the filename, then parse the line for symbol
2158 // definitions. AddFileSymbols() will null-terminate the line
2159 // after the file name. Save a copy for override purposes, in which
2160 // case we'll need to know the file name and path (in case it's in
2163 ExpandSymbols (Cptr
, FileName
, sizeof (FileName
), 0);
2164 AddFileSymbols (FileName
);
2165 ReplaceSlash (FileName
);
2167 // Set the SOURCE_FILE_NAME symbol. What we have now is the name of
2168 // the file, relative to the location of the INF file. So prepend
2169 // $(SOURCE_DIR) to it first.
2171 if (IsAbsolutePath (FileName
)) {
2172 strcpy (TempFileName
, FileName
);
2174 strcpy (TempFileName
, "$(SOURCE_DIR)\\");
2175 strcat (TempFileName
, FileName
);
2177 AddSymbol (SOURCE_FILE_NAME
, TempFileName
, SYM_FILE
| SYM_OVERWRITE
);
2179 // Extract path information from the source file and set internal
2180 // variable SOURCE_RELATIVE_PATH. Only do this if the path
2181 // contains a backslash.
2183 strcpy (FilePath
, FileName
);
2184 for (Cptr
= FilePath
+ strlen (FilePath
) - 1; (Cptr
> FilePath
) && (*Cptr
!= '\\'); Cptr
--)
2186 if (*Cptr
== '\\') {
2188 AddSymbol (SOURCE_RELATIVE_PATH
, FilePath
, SYM_FILE
);
2191 // Define another internal symbol for the name of the file without
2192 // the path and extension.
2194 for (Cptr
= FileName
+ strlen (FileName
) - 1; (Cptr
> FileName
) && (*Cptr
!= '\\'); Cptr
--)
2196 if (*Cptr
== '\\') {
2200 strcpy (FilePath
, Cptr
);
2202 // We now have a file name with no path information. Before we do anything else,
2203 // see if OVERRIDE_PATH is set, and if so, see if file $(OVERRIDE_PATH)FileName
2204 // exists. If it does, then recursive call this function to use the override file
2205 // instead of the one from the INF file.
2207 if (IsAbsolutePath (FileName
)) {
2208 OverridePath
= NULL
;
2210 OverridePath
= GetSymbolValue (SOURCE_OVERRIDE_PATH
);
2212 if (OverridePath
!= NULL
) {
2213 ReplaceSlash (OverridePath
);
2215 // See if the file exists. If it does, reset the SOURCE_FILE_NAME symbol.
2217 strcpy (TempFileName
, OverridePath
);
2218 strcat (TempFileName
, "\\");
2219 strcat (TempFileName
, FileName
);
2220 if ((FPtr
= fopen (TempFileName
, "rb")) != NULL
) {
2222 AddSymbol (SOURCE_FILE_NAME
, TempFileName
, SYM_FILE
| SYM_OVERWRITE
);
2224 // Print a message. This function is called to create build commands
2225 // for source files, and to create a macro of all source files. Therefore
2226 // do this check so we don't print the override message multiple times.
2228 if (Mode
& SOURCE_MODE_BUILD_COMMANDS
) {
2229 fprintf (stdout
, "Override: %s\n", TempFileName
);
2233 // Set override path to null to use as a flag below
2235 OverridePath
= NULL
;
2240 // Start at the end and work back
2242 for (Cptr
= FilePath
+ strlen (FilePath
) - 1; (Cptr
> FilePath
) && (*Cptr
!= '\\') && (*Cptr
!= '.'); Cptr
--)
2246 AddSymbol (SOURCE_FILE_EXTENSION
, Cptr
+ 1, SYM_FILE
);
2249 AddSymbol (SOURCE_BASE_NAME
, FilePath
, SYM_FILE
);
2251 // If we're just creating the SOURCE_FILES macro, then write the
2252 // file name out to the makefile.
2254 if (Mode
& SOURCE_MODE_SOURCE_FILES
) {
2256 // If we're processing an override file, then use the file name as-is
2258 if (OverridePath
!= NULL
) {
2260 // SOURCE_FILES = $(SOURCE_FILES) c:\Path\ThisFile.c
2262 fprintf (MakeFptr
, "SOURCE_FILES = $(SOURCE_FILES) %s\n", TempFileName
);
2263 } else if (IsAbsolutePath (FileName
)) {
2265 // For Absolute path, don't print $(SOURCE_FILE) directory.
2267 fprintf (MakeFptr
, "SOURCE_FILES = $(SOURCE_FILES) %s\n", FileName
);
2270 // SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\ThisFile.c
2272 fprintf (MakeFptr
, "SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\\%s\n", FileName
);
2274 } else if (Mode
& SOURCE_MODE_BUILD_COMMANDS
) {
2276 // Write the build commands for this file per the build commands
2277 // for this file type as defined in the description file.
2278 // Also create the directory for it in the build path.
2280 WriteCompileCommands (DSCFile
, MakeFptr
, FileName
, Processor
);
2281 if (!IsAbsolutePath (FileName
)) {
2282 sprintf (Str
, "%s\\%s", GetSymbolValue (DEST_DIR
), FileName
);
2285 // Get all output directory for build output files.
2287 Cptr
= FileName
+ strlen (FileName
) - 1;
2288 for (; (Cptr
> FileName
) && (*Cptr
!= '\\'); Cptr
--);
2289 if (*Cptr
== '\\') {
2291 AddModuleName (&gGlobals
.OutdirList
, FileName
, NULL
);
2296 // Remove file-level symbols
2298 RemoveFileSymbols ();
2303 return STATUS_SUCCESS
;
2306 // Process the INF [sources.*] sections and emit the OBJECTS = .....
2307 // lines to the component's makefile.
2312 DSC_FILE
*ComponentFile
,
2316 INT8 Str
[MAX_LINE_LEN
];
2323 INT8
*CopySourceSelect
;
2327 // Write a useful comment to the output makefile so the user knows where
2328 // the data came from.
2330 fprintf (MakeFptr
, "#\n# Tool-generated list of object files that are created\n");
2331 fprintf (MakeFptr
, "# from the list of source files in the [sources.*] sections\n");
2332 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2334 // We use this a lot here, so get the value only once.
2336 Processor
= GetSymbolValue (PROCESSOR
);
2338 // Now define the OBJECTS variable and assign it to be all the object files we're going
2339 // to create. Afterwards create a pseudo-target objects to let the user quickly just compile
2340 // the source files. This means we need to process all the common objects and
2341 // processor-specific objects again.
2343 fprintf (MakeFptr
, "OBJECTS = $(OBJECTS) ");
2345 // See if they defined SOURCE_SELECT=xxx,yyy in which case well
2346 // select each [sources.xxx] and [sources.yyy] files and process
2349 SourceSelect
= GetSymbolValue (SOURCE_SELECT
);
2351 if (SourceSelect
!= NULL
) {
2353 // Make a copy of the string and break it up (comma-separated) and
2354 // select each [sources.*] file from the INF.
2356 CopySourceSelect
= (INT8
*) malloc (strlen (SourceSelect
) + 1);
2357 if (CopySourceSelect
== NULL
) {
2358 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2359 return STATUS_ERROR
;
2362 strcpy (CopySourceSelect
, SourceSelect
);
2363 CStart
= CopySourceSelect
;
2367 while (*CEnd
&& *CEnd
!= ',') {
2373 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, CStart
);
2374 ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
);
2376 // Restore the terminator and advance
2385 free (CopySourceSelect
);
2389 // Now process all the [sources.common] files and emit build commands for them
2391 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, COMMON_SECTION_NAME
);
2392 if (ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
) != STATUS_SUCCESS
) {
2393 Warning (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "no [%s] section found in component description", Str
);
2396 // Now process any processor-specific source files in [sources.$(PROCESSOR)]
2398 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, Processor
);
2399 ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
);
2402 // Now process any [sources.$(PROCESSOR).$(PLATFORM)] files
2404 Platform
= GetSymbolValue (PLATFORM
);
2405 if (Platform
!= NULL
) {
2406 sprintf (Str
, "sources.%s.%s", Processor
, Platform
);
2407 ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
);
2411 fprintf (MakeFptr
, "\n\n");
2414 // Write a useful comment to the output makefile so the user knows where
2415 // the data came from.
2417 fprintf (MakeFptr
, "#\n# Tool-generated list of dest output dirs that are created\n");
2418 fprintf (MakeFptr
, "# from the list of source files in the [sources.*] sections\n");
2419 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2421 // Create output directory list
2422 // for clean target to delete all build output files.
2424 fprintf (MakeFptr
, "DEST_OUTPUT_DIRS = $(%s) ", DEST_DIR
);
2426 TempSymbol
= gGlobals
.OutdirList
;
2427 while (TempSymbol
!= NULL
) {
2428 fprintf (MakeFptr
, "\\\n $(%s)\\%s ",
2429 DEST_DIR
, TempSymbol
->Name
);
2430 TempSymbol
= TempSymbol
->Next
;
2432 fprintf (MakeFptr
, "\n\n");
2435 // clean up for the next module
2437 FreeSymbols (gGlobals
.OutdirList
);
2438 gGlobals
.OutdirList
= NULL
;
2440 return STATUS_SUCCESS
;
2445 BuiltFileExtension (
2446 INT8
*SourceFileName
2452 // Find the dot in the filename extension
2454 for (Cptr
= SourceFileName
+ strlen (SourceFileName
) - 1;
2455 (Cptr
> SourceFileName
) && (*Cptr
!= '\\') && (*Cptr
!= '.');
2467 // Look through our list of known file types and return a pointer to
2468 // its built file extension.
2470 for (i
= 0; mFileTypes
[i
].Extension
!= NULL
; i
++) {
2471 if (_stricmp (Cptr
, mFileTypes
[i
].Extension
) == 0) {
2472 return mFileTypes
[i
].BuiltExtension
;
2480 ProcessObjectsSingle (
2481 DSC_FILE
*ComponentFile
,
2488 INT8 Str
[MAX_LINE_LEN
];
2489 INT8 FileName
[MAX_EXP_LINE_LEN
];
2492 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2493 if (TempSect
!= NULL
) {
2494 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2495 Cptr
= StripLine (Str
);
2497 // Don't process blank lines
2501 // Expand symbols then create the output filename. We'll do a lookup
2502 // on the source file's extension to determine what the extension of
2503 // the built version of the file is. For example, .c -> .obj.
2505 if (!IsIncludeFile (Cptr
)) {
2506 ExpandSymbols (Cptr
, FileName
, sizeof (FileName
), 0);
2507 ReplaceSlash (FileName
);
2508 Cptr2
= BuiltFileExtension (FileName
);
2509 if (Cptr2
!= NULL
) {
2510 SetFileExtension (FileName
, Cptr2
);
2511 if (!IsAbsolutePath (FileName
)) {
2512 fprintf (MakeFptr
, "\\\n $(%s)\\%s ", DEST_DIR
, FileName
);
2514 fprintf (MakeFptr
, "\\\n %s ", FileName
);
2521 return STATUS_WARNING
;
2524 return STATUS_SUCCESS
;
2527 // Process all [libraries.*] sections in the component INF file to create a
2528 // macro to the component's output makefile: LIBS = Lib1 Lib2, ...
2533 DSC_FILE
*ComponentFile
,
2537 INT8 Str
[MAX_LINE_LEN
];
2542 // Print a useful comment to the component's makefile so the user knows
2543 // where the data came from.
2545 fprintf (MakeFptr
, "#\n# Tool-generated list of libraries that are generated\n");
2546 fprintf (MakeFptr
, "# from the list of libraries listed in the [libraries.*] sections\n");
2547 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2549 fprintf (MakeFptr
, "LIBS = $(LIBS) ");
2551 Processor
= GetSymbolValue (PROCESSOR
);
2553 // Process [libraries.common] files
2555 sprintf (Str
, "%s.%s", LIBRARIES_SECTION_NAME
, COMMON_SECTION_NAME
);
2556 ProcessLibsSingle (ComponentFile
, MakeFptr
, Str
);
2558 // Process the [libraries.$(PROCESSOR)] libraries to define "LIBS = x.lib y.lib..."
2560 sprintf (Str
, "%s.%s", LIBRARIES_SECTION_NAME
, Processor
);
2561 ProcessLibsSingle (ComponentFile
, MakeFptr
, Str
);
2563 // Now process any [libraries.$(PROCESSOR).$(PLATFORM)] files
2565 Platform
= GetSymbolValue (PLATFORM
);
2566 if (Platform
!= NULL
) {
2567 sprintf (Str
, "%s.%s.%s", LIBRARIES_SECTION_NAME
, Processor
, Platform
);
2568 ProcessLibsSingle (ComponentFile
, MakeFptr
, Str
);
2571 // Process any [libraries.platform] files
2573 ProcessLibsSingle (ComponentFile
, MakeFptr
, LIBRARIES_PLATFORM_SECTION_NAME
);
2575 fprintf (MakeFptr
, "\n\n");
2576 return STATUS_SUCCESS
;
2582 DSC_FILE
*ComponentFile
,
2588 INT8 Str
[MAX_LINE_LEN
];
2589 INT8 ExpandedLine
[MAX_LINE_LEN
];
2592 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2593 if (TempSect
!= NULL
) {
2594 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2595 ExpandSymbols (Str
, ExpandedLine
, sizeof (ExpandedLine
), 0);
2596 Cptr
= StripLine (ExpandedLine
);
2598 // Don't process blank lines
2601 if (Cptr
[strlen (Cptr
) - 4] != '.') {
2602 fprintf (MakeFptr
, " \\\n $(LIB_DIR)\\%s.lib", Cptr
);
2604 // Add lib dependency for single module build
2606 fprintf (gGlobals
.ModuleMakefileFptr
, " %sbuild", Cptr
);
2608 fprintf (MakeFptr
, " \\\n $(LIB_DIR)\\%s", Cptr
);
2610 // Add lib dependency for single module build
2612 Cptr
[strlen (Cptr
) - 4] = 0;
2613 fprintf (gGlobals
.ModuleMakefileFptr
, " %sbuild", Cptr
);
2619 return STATUS_SUCCESS
;
2624 ProcessIncludeFiles (
2625 DSC_FILE
*ComponentFile
,
2629 INT8 Str
[MAX_LINE_LEN
];
2636 INT8
*CopySourceSelect
;
2639 // Print a useful comment to the output makefile so the user knows where
2640 // the info came from
2642 //fprintf (MakeFptr, "#\n# Tool-generated include dependencies from any include files in the\n");
2643 //fprintf (MakeFptr, "# [sources.*] sections of the component INF file\n#\n");
2645 Processor
= GetSymbolValue (PROCESSOR
);
2648 // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll
2649 // select each [sources.xxx] and [sources.yyy] files and process
2652 SourceSelect
= GetSymbolValue (SOURCE_SELECT
);
2654 if (SourceSelect
!= NULL
) {
2656 // Make a copy of the string and break it up (comma-separated) and
2657 // select each [sources.*] file from the INF.
2659 CopySourceSelect
= (INT8
*) malloc (strlen (SourceSelect
) + 1);
2660 if (CopySourceSelect
== NULL
) {
2661 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2662 return STATUS_ERROR
;
2665 strcpy (CopySourceSelect
, SourceSelect
);
2666 CStart
= CopySourceSelect
;
2670 while (*CEnd
&& *CEnd
!= ',') {
2676 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, CStart
);
2677 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2679 // Restore the terminator and advance
2688 free (CopySourceSelect
);
2692 // Find all the include files in the [sources.common] sections.
2694 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, COMMON_SECTION_NAME
);
2695 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2697 // Now process the [sources.$(PROCESSOR)] files.
2699 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, Processor
);
2700 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2702 // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files.
2704 Platform
= GetSymbolValue (PLATFORM
);
2705 if (Platform
!= NULL
) {
2706 sprintf (Str
, "sources.%s.%s", Processor
, Platform
);
2707 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2711 fprintf (MakeFptr
, "\n");
2712 return STATUS_SUCCESS
;
2716 ProcessIncludeFilesSingle (
2717 DSC_FILE
*ComponentFile
,
2723 INT8 FileName
[MAX_EXP_LINE_LEN
];
2724 INT8 TempFileName
[MAX_PATH
];
2726 INT8 Str
[MAX_LINE_LEN
];
2730 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2731 if (TempSect
!= NULL
) {
2733 // See if the SOURCE_OVERRIDE_PATH has been set. If it has, and
2734 // they have an include file that is overridden, then add the path
2735 // to it to the list of include paths (prepend).
2737 OverridePath
= GetSymbolValue (SOURCE_OVERRIDE_PATH
);
2738 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2739 Cptr
= StripLine (Str
);
2741 // Don't process blank lines
2745 // Expand symbols in the filename, then get its parts
2747 ExpandSymbols (Cptr
, FileName
, sizeof (FileName
), 0);
2748 AddFileSymbols (FileName
);
2749 ReplaceSlash (FileName
);
2750 if (IsIncludeFile (FileName
)) {
2751 if ((OverridePath
!= NULL
) && (!IsAbsolutePath (FileName
))) {
2752 ReplaceSlash (OverridePath
);
2753 strcpy (TempFileName
, OverridePath
);
2754 strcat (TempFileName
, "\\");
2755 strcat (TempFileName
, FileName
);
2756 if ((FPtr
= fopen (TempFileName
, "rb")) != NULL
) {
2759 // Null-terminate the file name at the last backslash and add that
2760 // to the beginning of the list of include paths.
2762 for (Cptr
= TempFileName
+ strlen (TempFileName
) - 1;
2763 (Cptr
>= TempFileName
) && (*Cptr
!= '\\');
2767 if (Cptr
>= TempFileName
) {
2771 fprintf (MakeFptr
, "INC = -I %s $(INC)\n", TempFileName
);
2775 // If absolute path already, don't prepend source directory
2777 // if (IsAbsolutePath (FileName)) {
2778 // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) %s\n", FileName);
2780 // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) $(SOURCE_DIR)\\%s\n", FileName);
2784 RemoveFileSymbols ();
2789 return STATUS_SUCCESS
;
2799 if (FP
->Path
!= NULL
) {
2803 if (FP
->BaseName
!= NULL
) {
2804 free (FP
->BaseName
);
2807 if (FP
->Extension
!= NULL
) {
2808 free (FP
->Extension
);
2819 FILE_NAME_PARTS
*FP
;
2821 INT8 CopyFileName
[MAX_PATH
];
2824 strcpy (CopyFileName
, FileName
);
2825 FP
= (FILE_NAME_PARTS
*) malloc (sizeof (FILE_NAME_PARTS
));
2827 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2831 memset ((INT8
*) FP
, 0, sizeof (FILE_NAME_PARTS
));
2833 // Get extension code
2835 FP
->ExtensionCode
= GetSourceFileType (CopyFileName
);
2837 // Get drive if there
2839 FileNamePtr
= CopyFileName
;
2840 if (FileNamePtr
[1] == ':') {
2841 FP
->Drive
[0] = FileNamePtr
[0];
2846 // Start at the end and work back
2848 for (Cptr
= FileNamePtr
+ strlen (FileNamePtr
) - 1; (Cptr
> FileNamePtr
) && (*Cptr
!= '.'); Cptr
--)
2853 // Don't copy the dot
2855 FP
->Extension
= (char *) malloc (strlen (Cptr
));
2856 strcpy (FP
->Extension
, Cptr
+ 1);
2859 StripTrailingSpaces (FP
->Extension
);
2862 // Create empty string for extension
2864 FP
->Extension
= (char *) malloc (1);
2865 FP
->Extension
[0] = 0;
2868 // Now back up and get the base name (include the preceding '\')
2870 for (; (Cptr
> FileNamePtr
) && (*Cptr
!= '\\'); Cptr
--)
2872 FP
->BaseName
= (char *) malloc (strlen (Cptr
) + 1);
2873 strcpy (FP
->BaseName
, Cptr
);
2879 if (Cptr
>= FileNamePtr
) {
2881 FP
->Path
= (char *) malloc (strlen (Cptr
) + 1);
2882 strcpy (FP
->Path
, Cptr
);
2884 FP
->Path
= (char *) malloc (1);
2891 /*****************************************************************************
2892 ******************************************************************************/
2895 WriteCommonMakefile (
2901 INT8 InLine
[MAX_LINE_LEN
];
2902 INT8 OutLine
[MAX_EXP_LINE_LEN
];
2907 // Don't mess up the original file pointer, since we're processing it at a higher
2910 DSCFileSavePosition (DSCFile
);
2912 // Write the header to the file
2914 for (i
= 0; MakefileHeader
[i
] != NULL
; i
++) {
2915 fprintf (MakeFptr
, "%s\n", MakefileHeader
[i
]);
2918 fprintf (MakeFptr
, "#\n# Hard-coded defines output by the tool\n#\n");
2920 // First write the basics to the component's makefile. These includes
2921 // EFI_SOURCE, BIN_DIR, OUT_DIR, LIB_DIR, SOURCE_DIR, DEST_DIR.
2923 Sym
= GetSymbolValue (EFI_SOURCE
);
2924 fprintf (MakeFptr
, "%s = %s\n", EFI_SOURCE
, Sym
);
2925 Sym
= GetSymbolValue (BUILD_DIR
);
2926 fprintf (MakeFptr
, "%s = %s\n", BUILD_DIR
, Sym
);
2927 Sym
= GetSymbolValue (BIN_DIR
);
2928 fprintf (MakeFptr
, "%s = %s\n", BIN_DIR
, Sym
);
2929 Sym
= GetSymbolValue (OUT_DIR
);
2930 fprintf (MakeFptr
, "%s = %s\n", OUT_DIR
, Sym
);
2931 Sym
= GetSymbolValue (LIB_DIR
);
2932 fprintf (MakeFptr
, "%s = %s\n", LIB_DIR
, Sym
);
2933 Sym
= GetSymbolValue (SOURCE_DIR
);
2934 fprintf (MakeFptr
, "%s = %s\n", SOURCE_DIR
, Sym
);
2935 Sym
= GetSymbolValue (DEST_DIR
);
2936 fprintf (MakeFptr
, "%s = %s\n", DEST_DIR
, Sym
);
2937 fprintf (MakeFptr
, "\n");
2939 // If there was a [makefile.common] section in the description file,
2940 // copy it (after symbol expansion) to the output file.
2942 sprintf (InLine
, "%s.%s", MAKEFILE_SECTION_NAME
, COMMON_SECTION_NAME
);
2943 Sect
= DSCFileFindSection (DSCFile
, InLine
);
2946 // fprintf (MakeFptr, "# From the [makefile.common] section of the DSC file\n");
2947 // Read lines, expand, then dump out
2949 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
2953 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
2954 fprintf (MakeFptr
, OutLine
);
2958 // If there was a [makefile.platform] section in the description file,
2959 // copy it (after symbol expansion) to the output file.
2961 sprintf (InLine
, "%s.%s", MAKEFILE_SECTION_NAME
, "Platform");
2962 Sect
= DSCFileFindSection (DSCFile
, InLine
);
2965 // Read lines, expand, then dump out
2967 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
2971 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
2972 fprintf (MakeFptr
, OutLine
);
2976 // Do the same for any [makefile.$(PROCESSOR)]
2978 sprintf (InLine
, "%s.%s", MAKEFILE_SECTION_NAME
, Processor
);
2979 Sect
= DSCFileFindSection (DSCFile
, InLine
);
2982 // Read lines, expand, then dump out
2984 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
2985 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
2986 fprintf (MakeFptr
, OutLine
);
2990 // Same thing for [makefile.$(PROCESSOR).$(PLATFORM)]
2992 Sym
= GetSymbolValue (PLATFORM
);
2994 sprintf (InLine
, "%s.%s.%s", MAKEFILE_SECTION_NAME
, Processor
, Sym
);
2995 Sect
= DSCFileFindSection (DSCFile
, InLine
);
2998 // Read lines, expand, then dump out
3000 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
3001 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
3002 fprintf (MakeFptr
, OutLine
);
3007 fprintf (MakeFptr
, "\n");
3008 DSCFileRestorePosition (DSCFile
);
3014 WriteComponentTypeBuildCommands (
3021 Routine Description:
3023 Given a section name such as [build.ia32.library], find the section in
3024 the description file and copy the build commands.
3028 DSCFile - section information on the main description file
3029 MakeFptr - file pointer to the makefile we're writing to
3030 SectionName - name of the section we're to copy out to the makefile.
3034 Always successful, since the section may be optional.
3039 INT8 InLine
[MAX_LINE_LEN
];
3040 INT8 OutLine
[MAX_EXP_LINE_LEN
];
3043 // Don't mess up the original file pointer, since we're processing it at a higher
3046 DSCFileSavePosition (DSCFile
);
3047 Sect
= DSCFileFindSection (DSCFile
, SectionName
);
3050 // Read lines, expand, then dump out
3052 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
3057 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
3059 fprintf (MakeFptr
, OutLine
);
3066 GetSymbolValue (INF_FILENAME
),
3067 "no [%s] build commands found in DSC file for component",
3072 DSCFileRestorePosition (DSCFile
);
3073 return STATUS_SUCCESS
;
3076 /*****************************************************************************
3078 ******************************************************************************/
3081 WriteCompileCommands (
3088 FILE_NAME_PARTS
*File
;
3090 INT8 BuildSectionName
[40];
3091 INT8 InLine
[MAX_LINE_LEN
];
3092 INT8 OutLine
[MAX_EXP_LINE_LEN
];
3093 INT8
*SourceCompileType
;
3097 // Determine the filename, then chop it up into its parts
3099 File
= GetFileParts (FileName
);
3102 // Don't mess up the original file pointer, since we're processing it at a higher
3105 DSCFileSavePosition (DscFile
);
3107 // Option 1: SOURCE_COMPILE_TYPE=MyCompileSection
3108 // Find a section of that name from which to get the compile
3109 // commands for this source file.
3110 // Look for [compile.$(PROCESSOR).$(SOURCE_COMPILE_TYPE]
3111 // Option 2: COMPILE_SELECT=.c=MyCCompile,.asm=MyAsm
3112 // Find a [compile.$(PROCESSOR).MyCompile] section from which to
3113 // get the compile commands for this source file.
3114 // Look for [compile.$(PROCESSOR).MyCompile]
3115 // Option 3: Look for standard section types to compile the file by extension.
3116 // Look for [compile.$(PROCESSOR).<extension>]
3120 // Option 1 - use SOURCE_COMPILE_TYPE variable
3122 SourceCompileType
= GetSymbolValue (SOURCE_COMPILE_TYPE
);
3123 if (SourceCompileType
!= NULL
) {
3124 sprintf (BuildSectionName
, "compile.%s.%s", Processor
, SourceCompileType
);
3125 Sect
= DSCFileFindSection (DscFile
, BuildSectionName
);
3128 // Option 2 - use COMPILE_SELECT variable
3131 SourceCompileType
= GetSymbolValue (COMPILE_SELECT
);
3132 if (SourceCompileType
!= NULL
) {
3134 // Parse the variable, which looks like COMPILE_SELECT=.c=MyCCompiler;.asm=MyAsm;
3135 // to find an entry with a matching file name extension. If you find one,
3136 // then use that name to find the section name.
3138 CPtr
= SourceCompileType
;
3139 while (*CPtr
&& (Sect
== NULL
)) {
3141 // See if we found a match with this source file name extension. File->Extension
3142 // does not include the dot, so skip the dot in the COMPILE_SELECT variable if there
3149 if (_strnicmp (CPtr
, File
->Extension
, strlen (File
->Extension
)) == 0) {
3151 // Found a file name extension match -- extract the name from the variable, for
3152 // example "MyCCompiler"
3154 while (*CPtr
&& (*CPtr
!= '=')) {
3158 if ((*CPtr
!= '=') || (CPtr
[1] == 0)) {
3159 Error (NULL
, 0, 0, SourceCompileType
, "malformed COMPILE_SELECT variable");
3164 sprintf (BuildSectionName
, "compile.%s.", Processor
);
3165 for (CPtr2
= BuildSectionName
+ strlen (BuildSectionName
);
3166 *CPtr
&& (*CPtr
!= ',') && (*CPtr
!= ';');
3174 Sect
= DSCFileFindSection (DscFile
, BuildSectionName
);
3179 "could not find section in DSC file - selected by COMPILE_SELECT variable"
3185 // Skip to next file name extension in the COMPILE_SELECT variable
3187 while (*CPtr
&& (*CPtr
!= ';') && (*CPtr
!= ',')) {
3198 // Option 3 - use "Compile.$(PROCESSOR).<Extension>" section
3201 sprintf (BuildSectionName
, "compile.%s.%s", Processor
, File
->Extension
);
3202 Sect
= DSCFileFindSection (DscFile
, BuildSectionName
);
3205 // Should have found something by now unless it's an include (.h) file
3209 // Temporarily add a FILE variable to the global symbol table. Omit the
3212 sprintf (InLine
, "%s%s%s", File
->Drive
, File
->Path
, File
->BaseName
);
3213 AddSymbol ("FILE", InLine
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILENAME
);
3215 // Read lines, expand (except SOURCE_DIR and DEST_DIR), then dump out
3217 while (DSCFileGetLine (DscFile
, InLine
, sizeof (InLine
)) != NULL
) {
3222 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
3224 fprintf (MakeFptr
, OutLine
);
3226 fprintf (MakeFptr
, "\n");
3229 // Be nice and ignore include files
3231 if (!IsIncludeFile (FileName
)) {
3237 "no compile commands section [%s] found in DSC file for %s",
3244 DSCFileRestorePosition (DscFile
);
3245 FreeFileParts (File
);
3248 return STATUS_SUCCESS
;
3251 /*****************************************************************************
3252 ******************************************************************************/
3262 Cptr
= FileName
+ strlen (FileName
) - 1;
3263 while ((Cptr
> FileName
) && (*Cptr
!= '.')) {
3271 Message (2, "Missing filename extension: %s", FileName
);
3272 return STATUS_WARNING
;
3276 if (*Extension
== '.') {
3280 strcpy (Cptr
, Extension
);
3281 return STATUS_SUCCESS
;
3284 /*****************************************************************************
3285 ******************************************************************************/
3293 INT8 BuildDir
[MAX_PATH
];
3294 INT8 CopyFileName
[MAX_PATH
];
3297 // Expand symbols in the filename
3299 if (ExpandSymbols (FileName
, CopyFileName
, sizeof (CopyFileName
), EXPANDMODE_NO_UNDEFS
)) {
3300 Error (NULL
, 0, 0, NULL
, "undefined symbols in file path: %s", FileName
);
3301 return STATUS_ERROR
;
3306 strcpy (FileName
, CopyFileName
);
3308 // To avoid creating $(BUILD_DIR) path, see if this path is the same as
3309 // $(BUILD_DIR), and if it is, see if build dir exists and skip over that
3310 // portion if it does
3312 Cptr
= GetSymbolValue (BUILD_DIR
);
3314 if (_strnicmp (Cptr
, FileName
, strlen (Cptr
)) == 0) {
3316 // BUILD_DIR path. See if it exists
3318 strcpy (BuildDir
, FileName
);
3319 BuildDir
[strlen (Cptr
)] = 0;
3320 if ((_mkdir (BuildDir
) != 0) && (errno
!= EEXIST
)) {
3324 // Already done. Shortcut. Skip to next path so that we don't create
3325 // the BUILD_DIR as well.
3327 Cptr
= FileName
+ strlen (Cptr
);
3328 if (*Cptr
== '\\') {
3342 // Create directories until done. Skip over "c:\" in the path if it exists
3344 if (*Cptr
&& (*(Cptr
+ 1) == ':') && (*(Cptr
+ 2) == '\\')) {
3349 for (; *Cptr
&& (*Cptr
!= '\\'); Cptr
++)
3354 if ((_mkdir (FileName
) != 0)) {
3356 // Error (NULL, 0, 0, FileName, "failed to create directory");
3368 return STATUS_SUCCESS
;
3371 /*****************************************************************************
3372 ******************************************************************************/
3381 static int NestDepth
= 0;
3389 INT8
*LocalDestLine
;
3394 Status
= STATUS_SUCCESS
;
3395 LocalDestLine
= (INT8
*) malloc (LineLen
);
3396 if (LocalDestLine
== NULL
) {
3397 Error (__FILE__
, __LINE__
, 0, "application error", "memory allocation failed");
3399 return STATUS_ERROR
;
3402 FromPtr
= SourceLine
;
3403 ToPtr
= LocalDestLine
;
3405 // Walk the entire line, replacing $(SYMBOL_NAME).
3407 LocalLineLen
= LineLen
;
3409 while (*FromPtr
&& (LocalLineLen
> 0)) {
3410 if ((*FromPtr
== '$') && (*(FromPtr
+ 1) == '(')) {
3412 // Save the start in case it's undefined, in which case we copy it as-is.
3414 SaveStart
= FromPtr
;
3417 // Symbol expansion time. Find the end (no spaces allowed)
3420 for (Cptr
= FromPtr
; *Cptr
&& (*Cptr
!= ')'); Cptr
++)
3424 // Truncate the string at the closing parenthesis for ease-of-use.
3425 // Then copy the string directly to the destination line in case we don't find
3426 // a definition for it.
3429 strcpy (ToPtr
, SaveStart
);
3430 if ((_stricmp (SOURCE_DIR
, FromPtr
) == 0) && (ExpandMode
& EXPANDMODE_NO_SOURCEDIR
)) {
3432 // excluded this expansion
3434 } else if ((_stricmp (DEST_DIR
, FromPtr
) == 0) && (ExpandMode
& EXPANDMODE_NO_DESTDIR
)) {
3436 // excluded this expansion
3438 } else if ((value
= GetSymbolValue (FromPtr
)) != NULL
) {
3439 strcpy (ToPtr
, value
);
3440 LocalLineLen
-= strlen (value
);
3441 ToPtr
+= strlen (value
);
3444 } else if (ExpandMode
& EXPANDMODE_NO_UNDEFS
) {
3445 Error (NULL
, 0, 0, "undefined symbol", "$(%s)", FromPtr
);
3446 Status
= STATUS_ERROR
;
3451 // Restore closing parenthesis, and advance to next character
3455 FromPtr
= SaveStart
+ 1;
3461 Error (NULL
, 0, 0, SourceLine
, "missing closing parenthesis on symbol");
3462 strcpy (ToPtr
, FromPtr
);
3463 Status
= STATUS_WARNING
;
3474 if (*FromPtr
== 0) {
3479 // If we're in recursive mode, and we expanded at least one string successfully,
3480 // then make a recursive call to try again.
3482 if ((ExpandedCount
!= 0) && (Status
== STATUS_SUCCESS
) && (ExpandMode
& EXPANDMODE_RECURSIVE
) && (NestDepth
< 2)) {
3483 Status
= ExpandSymbols (LocalDestLine
, DestLine
, LineLen
, ExpandMode
);
3484 free (LocalDestLine
);
3490 if (Status
!= STATUS_ERROR
) {
3491 strcpy (DestLine
, LocalDestLine
);
3495 free (LocalDestLine
);
3505 Routine Description:
3507 Look up a symbol in our symbol table.
3511 SymbolName - The name of symbol.
3515 Pointer to the value of the symbol if found
3516 NULL if the symbol is not found
3523 // Scan once for file-level symbols
3525 Symbol
= gGlobals
.Symbol
;
3527 if ((_stricmp (SymbolName
, Symbol
->Name
) == 0) && (Symbol
->Type
& SYM_FILE
)) {
3528 return Symbol
->Value
;
3531 Symbol
= Symbol
->Next
;
3534 // Scan once for local symbols
3536 Symbol
= gGlobals
.Symbol
;
3538 if ((_stricmp (SymbolName
, Symbol
->Name
) == 0) && (Symbol
->Type
& SYM_LOCAL
)) {
3539 return Symbol
->Value
;
3542 Symbol
= Symbol
->Next
;
3545 // No local value found. Scan for globals.
3547 Symbol
= gGlobals
.Symbol
;
3549 if ((_stricmp (SymbolName
, Symbol
->Name
) == 0) && (Symbol
->Type
& SYM_GLOBAL
)) {
3550 return Symbol
->Value
;
3553 Symbol
= Symbol
->Next
;
3556 // For backwards-compatibility, if it's "GUID", return FILE_GUID value
3558 if (_stricmp (SymbolName
, GUID
) == 0) {
3559 return GetSymbolValue (FILE_GUID
);
3567 RemoveLocalSymbols (
3572 Routine Description:
3574 Remove all local symbols from the symbol table. Local symbols are those
3575 that are defined typically by the component's INF file.
3583 Right now, never fails.
3592 Sym
= gGlobals
.Symbol
;
3594 if (Sym
->Type
& SYM_LOCAL
) {
3596 // Going to delete it out from under ourselves, so break and restart
3599 RemoveSymbol (Sym
->Name
, SYM_LOCAL
);
3606 return STATUS_SUCCESS
;
3616 Routine Description:
3618 Remove all file-level symbols from the symbol table. File-level symbols are
3619 those that are defined on a source file line in an INF file.
3627 Right now, never fails.
3636 Sym
= gGlobals
.Symbol
;
3638 if (Sym
->Type
& SYM_FILE
) {
3640 // Going to delete it out from under ourselves, so break and restart
3643 RemoveSymbol (Sym
->Name
, SYM_FILE
);
3650 return STATUS_SUCCESS
;
3655 ParseGuidDatabaseFile (
3660 Routine Description:
3661 This function parses a GUID-to-basename text file (perhaps output by
3662 the GuidChk utility) to define additional symbols. The format of the
3665 7BB28B99-61BB-11D5-9A5D-0090273FC14D EFI_DEFAULT_BMP_LOGO_GUID gEfiDefaultBmpLogoGuid
3667 This function parses the line and defines global symbol:
3669 EFI_DEFAULT_BMP_LOGO_GUID=7BB28B99-61BB-11D5-9A5D-0090273FC14D
3671 This symbol (rather than the actual GUID) can then be used in INF files to
3675 FileName - the name of the file to parse.
3678 STATUS_ERROR - could not open FileName
3679 STATUS_SUCCESS - we opened the file
3686 INT8 DefineName
[80];
3688 Fptr
= fopen (FileName
, "r");
3690 Error (NULL
, 0, 0, FileName
, "failed to open input GUID database input file");
3691 return STATUS_ERROR
;
3694 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
3696 // Get the GUID string, skip the defined name (EFI_XXX_GUID), and get the
3697 // variable name (gWhateverProtocolGuid)
3699 if (sscanf (Line
, "%s %s %*s", Guid
, DefineName
) == 2) {
3700 AddSymbol (DefineName
, Guid
, SYM_GLOBAL
);
3705 return STATUS_SUCCESS
;
3708 /*****************************************************************************
3711 0 if successful standard add
3712 length of the parsed string if passed in " name = value "
3715 ******************************************************************************/
3732 INT8 ShortName
[MAX_PATH
];
3742 // Mode better be local or global symbol
3744 if ((Mode
& (SYM_LOCAL
| SYM_GLOBAL
| SYM_FILE
)) == 0) {
3745 Error (NULL
, 0, 0, "APP ERROR", "adding symbol '%s' that is not local, global, nor file level", Name
);
3749 // If value pointer is null, then they passed us a line something like:
3750 // varname = value, or simply var =
3752 if (Value
== NULL
) {
3754 while (*Name
&& isspace (*Name
)) {
3763 // Find the end of the name. Either space or a '='.
3765 for (Value
= Name
; *Value
&& !isspace (*Value
) && (*Value
!= '='); Value
++)
3774 while (*Value
&& (*Value
!= '=')) {
3783 // Now truncate the name
3790 // Skip over the = and then any spaces
3793 while (*Value
&& isspace (*Value
)) {
3798 // Find end of string, checking for quoted string
3800 if (*Value
== '\"') {
3802 for (Cptr
= Value
; *Cptr
&& *Cptr
!= '\"'; Cptr
++)
3805 for (Cptr
= Value
; *Cptr
&& !isspace (*Cptr
); Cptr
++)
3809 // Null terminate the value string
3812 Len
= (int) (Cptr
- Start
) + 1;
3817 Len
= (int) (Cptr
- Start
);
3822 // If file name or file path, and we're shortening, then print it
3824 if ((Mode
& (SYM_FILEPATH
| SYM_FILENAME
)) && (GetSymbolValue (SHORT_NAMES
) != NULL
)) {
3825 if (GetShortPathName (Value
, ShortName
, sizeof (ShortName
)) > 0) {
3827 // fprintf (stdout, "String value '%s' shortened to '%s'\n",
3828 // Value, ShortName);
3833 // fprintf (stdout, "WARNING: Failed to get short name for %s\n", Value);
3838 // We now have a symbol name and a value. Look for an existing variable of
3839 // the same type (global or local) and overwrite it.
3841 Symbol
= gGlobals
.Symbol
;
3844 // Check for symbol name match
3846 if (_stricmp (Name
, Symbol
->Name
) == 0) {
3848 // See if this symbol is of the same type (global or local) as what
3849 // they're requesting
3851 if ((Symbol
->Type
& (SYM_LOCAL
| SYM_GLOBAL
)) == (Mode
& (SYM_LOCAL
| SYM_GLOBAL
))) {
3853 // Did they say we could overwrite it?
3855 if (Mode
& SYM_OVERWRITE
) {
3856 free (Symbol
->Value
);
3857 Symbol
->Value
= (INT8
*) malloc (strlen (Value
) + 1);
3858 if (Symbol
->Value
== NULL
) {
3859 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
3863 strcpy (Symbol
->Value
, Value
);
3865 // If value == "NULL", then make it a 0-length string
3867 if (_stricmp (Symbol
->Value
, "NULL") == 0) {
3868 Symbol
->Value
[0] = 0;
3873 return STATUS_ERROR
;
3878 Symbol
= Symbol
->Next
;
3881 // Does not exist, create a new one
3883 NewSymbol
= (SYMBOL
*) malloc (sizeof (SYMBOL
));
3884 if (NewSymbol
== NULL
) {
3885 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
3889 memset ((INT8
*) NewSymbol
, 0, sizeof (SYMBOL
));
3890 NewSymbol
->Name
= (INT8
*) malloc (strlen (Name
) + 1);
3891 NewSymbol
->Value
= (INT8
*) malloc (strlen (Value
) + 1);
3893 // Simply use the mode bits as the type.
3895 NewSymbol
->Type
= Mode
;
3896 if ((NewSymbol
->Name
== NULL
) || (NewSymbol
->Value
== NULL
)) {
3897 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
3901 strcpy (NewSymbol
->Name
, Name
);
3902 strcpy (NewSymbol
->Value
, Value
);
3904 // Remove trailing spaces
3906 Cptr
= NewSymbol
->Value
+ strlen (NewSymbol
->Value
) - 1;
3907 while (Cptr
> NewSymbol
->Value
) {
3908 if (isspace (*Cptr
)) {
3916 // Add it to the head of the list.
3918 NewSymbol
->Next
= gGlobals
.Symbol
;
3919 gGlobals
.Symbol
= NewSymbol
;
3921 // If value == "NULL", then make it a 0-length string
3923 if (_stricmp (NewSymbol
->Value
, "NULL") == 0) {
3924 NewSymbol
->Value
[0] = 0;
3927 // Restore the terminator we inserted if they passed in var=value
3929 if (SaveCptr1
!= NULL
) {
3930 *SaveCptr1
= CSave1
;
3932 if (SaveCptr2
!= NULL
) {
3933 *SaveCptr2
= CSave2
;
3939 /*****************************************************************************
3940 ******************************************************************************/
3952 Symbol
= gGlobals
.Symbol
;
3954 if ((_stricmp (Name
, Symbol
->Name
) == 0) && (Symbol
->Type
& SymbolType
)) {
3955 if (Symbol
->Value
) {
3956 free (Symbol
->Value
);
3959 free (Symbol
->Name
);
3961 PrevSymbol
->Next
= Symbol
->Next
;
3963 gGlobals
.Symbol
= Symbol
->Next
;
3967 return STATUS_SUCCESS
;
3970 PrevSymbol
= Symbol
;
3971 Symbol
= Symbol
->Next
;
3974 return STATUS_WARNING
;
3979 /*****************************************************************************
3980 ******************************************************************************/
3989 while (Sect
!= NULL
) {
3991 if (Sect
->Name
!= NULL
) {
3992 delete[] Sect
->Name
;
4001 /*****************************************************************************
4002 ******************************************************************************/
4014 // Look for '#' comments in first character of line
4021 while (isspace (*Cptr
)) {
4025 // Hack off newlines
4027 Len
= strlen (Cptr
);
4028 if ((Len
> 0) && (Cptr
[Len
- 1] == '\n')) {
4032 // Hack off trailing spaces
4034 StripTrailingSpaces (Cptr
);
4038 /*****************************************************************************
4039 FUNCTION: ProcessOptions()
4041 DESCRIPTION: Process the command-line options.
4042 ******************************************************************************/
4051 Routine Description:
4053 Process the command line options to this utility.
4057 Argc - Standard Argc.
4058 Argv[] - Standard Argv.
4068 // Clear out the options
4070 memset ((INT8
*) &gGlobals
, 0, sizeof (gGlobals
));
4077 return STATUS_ERROR
;
4080 // Now process the arguments
4084 if ((Argv
[0][0] == '-') || (Argv
[0][0] == '/')) {
4085 switch (Argv
[0][1]) {
4087 // -? or -h help option
4093 return STATUS_ERROR
;
4107 Error (NULL
, 0, 0, NULL
, "missing symbol definition with %c%c", Argv
[0][0], Argv
[0][1]);
4108 return STATUS_ERROR
;
4110 if (AddSymbol (Argv
[0], NULL
, SYM_OVERWRITE
| SYM_GLOBAL
) <= 0) {
4111 Warning (NULL
, 0, 0, Argv
[0], "failed to add symbol: %s");
4117 // output makefile name
4128 Error (NULL
, 0, 0, Argv
[0], "missing output makefile name with option");
4130 return STATUS_ERROR
;
4132 strcpy (gGlobals
.MakefileName
, Argv
[0]);
4137 // Print a cross-reference file containing guid/basename/processor
4148 Error (NULL
, 0, 0, Argv
[0], "missing cross-reference output filename with option");
4150 return STATUS_ERROR
;
4152 strcpy (gGlobals
.XRefFileName
, Argv
[0]);
4157 // GUID database file to preparse
4168 Error (NULL
, 0, 0, Argv
[0], "missing input GUID database filename with option");
4170 return STATUS_ERROR
;
4172 strcpy (gGlobals
.GuidDatabaseFileName
, Argv
[0]);
4178 gGlobals
.Verbose
= 1;
4182 Error (NULL
, 0, 0, Argv
[0], "unrecognized option");
4183 return STATUS_ERROR
;
4193 // Must be at least one arg left
4196 gGlobals
.DscFilename
= Argv
[0];
4199 if (gGlobals
.DscFilename
== NULL
) {
4200 Error (NULL
, 0, 0, NULL
, "must specify DSC filename on command line");
4201 return STATUS_ERROR
;
4204 // Make a global symbol for the DSC filename
4206 AddSymbol (DSC_FILENAME
, gGlobals
.DscFilename
, SYM_GLOBAL
| SYM_FILENAME
);
4208 // If no output makefile specified, take the default
4210 if (gGlobals
.MakefileName
[0] == 0) {
4211 strcpy (gGlobals
.MakefileName
, MAKEFILE_OUT_NAME
);
4214 // Get the current working directory and use it for the build directory.
4215 // Only do this if they have not defined it on the command line. Do the
4216 // same for the bin dir, output dir, and library directory.
4218 Cptr
= GetSymbolValue (BUILD_DIR
);
4220 Cptr
= _getcwd (NULL
, 0);
4222 AddSymbol (BUILD_DIR
, Cptr
, SYM_OVERWRITE
| SYM_GLOBAL
| SYM_FILEPATH
);
4224 ReplaceSlash (Cptr
);
4235 /*****************************************************************************
4236 ******************************************************************************/
4246 if (Syms
->Name
!= NULL
) {
4250 if (Syms
->Value
!= NULL
) {
4262 /*****************************************************************************
4263 ******************************************************************************/
4274 len
= strlen (FileName
);
4276 return FILETYPE_UNKNOWN
;
4280 Cptr
= FileName
+ len
- 1;
4281 while ((*Cptr
!= '.') && (Cptr
>= FileName
)) {
4288 for (i
= 0; mFileTypes
[i
].Extension
!= NULL
; i
++) {
4289 len
= strlen (mFileTypes
[i
].Extension
);
4290 if (_strnicmp (mFileTypes
[i
].Extension
, Cptr
, len
) == 0) {
4291 if ((*(Cptr
+ len
) == 0) || isspace (*(Cptr
+ len
))) {
4292 return mFileTypes
[i
].FileType
;
4298 return FILETYPE_UNKNOWN
;
4301 // Determine if a given file is a standard include file. If we don't know,
4302 // then assume it's not.
4314 len
= strlen (FileName
);
4319 Cptr
= FileName
+ len
- 1;
4320 while ((*Cptr
!= '.') && (Cptr
>= FileName
)) {
4326 // Now go through the list of filename extensions and try to find
4327 // a match for this file extension.
4329 for (i
= 0; mFileTypes
[i
].Extension
!= NULL
; i
++) {
4330 len
= strlen (mFileTypes
[i
].Extension
);
4331 if (_strnicmp (mFileTypes
[i
].Extension
, Cptr
, len
) == 0) {
4333 // Make sure that's all there is to the filename extension.
4335 if ((*(Cptr
+ len
) == 0) || isspace (*(Cptr
+ len
))) {
4336 return mFileTypes
[i
].FileFlags
& FILE_FLAG_INCLUDE
;
4345 /*****************************************************************************
4346 ******************************************************************************/
4349 StripTrailingSpaces (
4354 Cptr
= Str
+ strlen (Str
) - 1;
4355 while (Cptr
> Str
) {
4356 if (isspace (*Cptr
)) {
4365 /*****************************************************************************
4366 ******************************************************************************/
4376 // Don't set it if the user specified it on the command line.
4378 EfiSource
= GetSymbolValue (EFI_SOURCE
);
4379 if ( EfiSource
!= NULL
) {
4380 ReplaceSlash (EfiSource
);
4381 if (EfiSource
[strlen (EfiSource
) - 1] == '\\') {
4382 EfiSource
[strlen (EfiSource
) - 1] = 0;
4384 return STATUS_SUCCESS
;
4388 // Get the environmental variable setting of EFI_SOURCE.
4390 EfiSource
= getenv (EFI_SOURCE
);
4391 if (EfiSource
!= NULL
) {
4392 ReplaceSlash (EfiSource
);
4393 if (EfiSource
[strlen (EfiSource
) - 1] == '\\') {
4394 EfiSource
[strlen (EfiSource
) - 1] = 0;
4396 AddSymbol (EFI_SOURCE
, EfiSource
, SYM_GLOBAL
| SYM_FILEPATH
);
4397 return STATUS_SUCCESS
;
4400 Error (NULL
, 0, 0, NULL
, "could not determine EFI_SOURCE");
4401 return STATUS_ERROR
;
4411 INT8 Line
[MAX_LINE_LEN
];
4414 va_start (List
, Fmt
);
4415 vsprintf (Line
, Fmt
, List
);
4416 if (PrintMask
& gGlobals
.Verbose
) {
4417 fprintf (stdout
, "%s\n", Line
);
4430 static const INT8
*Help
[] = {
4431 "Usage: ProcessDsc {options} [Dsc Filename]",
4433 " -d var=value to define symbol 'var' to 'value'",
4434 " -v for verbose mode",
4435 " -g filename to preparse GUID listing file",
4436 " -x filename to create a cross-reference file",
4439 for (i
= 0; Help
[i
] != NULL
; i
++) {
4440 fprintf (stdout
, "%s\n", Help
[i
]);
4446 Routine Description:
4448 Process the [defines] section in the DSC file.
4452 DscFile - pointer to the DSCFile class that contains the relevant info.
4456 0 if not necessarily an absolute path
4462 ProcessDSCDefinesSection (
4466 INT8 Line
[MAX_LINE_LEN
];
4467 INT8 Line2
[MAX_EXP_LINE_LEN
];
4472 // Look for a [defines] section and process it
4474 Sect
= DSCFileFindSection (DscFile
, DEFINES_SECTION_NAME
);
4476 return STATUS_ERROR
;
4479 // Read lines while they're valid
4481 while (DSCFileGetLine (DscFile
, Line
, sizeof (Line
)) != NULL
) {
4483 // Expand symbols on the line
4485 if (ExpandSymbols (Line
, Line2
, sizeof (Line2
), 0)) {
4486 return STATUS_ERROR
;
4491 Cptr
= StripLine (Line2
);
4494 // Make the assignment
4496 AddSymbol (Line2
, NULL
, SYM_OVERWRITE
| SYM_GLOBAL
);
4500 return STATUS_SUCCESS
;
4509 Routine Description:
4511 Determine if a given filename contains the full path information.
4515 FileName - the name of the file, with symbol expanded.
4519 0 if not necessarily an absolute path
4525 // If the first character is a-z, and the second character is a colon, then
4526 // it is an absolute path.
4528 if (isalpha (FileName
[0]) && (FileName
[1] == ':')) {
4540 SMART_FILE
*SmartFile
;
4544 SmartFile
= malloc (sizeof (SMART_FILE
));
4545 if (SmartFile
== NULL
) {
4548 memset (SmartFile
, 0, sizeof (SMART_FILE
));
4550 SmartFile
->FileName
= malloc (strlen (FileName
) + 1);
4551 if (SmartFile
->FileName
== NULL
){
4552 SmartFree (SmartFile
);
4555 strcpy (SmartFile
->FileName
, FileName
);
4557 if ((Fptr
= fopen (FileName
, "r")) != NULL
) {
4558 fseek (Fptr
, 0, SEEK_END
);
4559 FileSize
= ftell (Fptr
);
4560 fseek (Fptr
, 0, SEEK_SET
);
4561 SmartFile
->FileContent
= malloc (FileSize
+ 1);
4562 if (SmartFile
->FileContent
!= NULL
) {
4563 memset (SmartFile
->FileContent
, 0, FileSize
+ 1);
4565 // Usually FileLength < FileSize, because in text mode, carriage return¨Clinefeed
4566 // combinations are translated into single linefeeds on input
4568 SmartFile
->FileLength
= fread (SmartFile
->FileContent
, sizeof(char), FileSize
, Fptr
);
4574 // No previous output file content, re-create the file
4576 if (SmartFile
->FileContent
== NULL
) {
4577 if ((SmartFile
->FilePtr
= fopen (FileName
, "w")) == NULL
) {
4578 SmartFree (SmartFile
);
4588 SMART_FILE
*SmartFile
,
4594 if (SmartFile
->FilePtr
!= NULL
) {
4595 return fprintf (SmartFile
->FilePtr
, "%s", String
);
4597 StrLen
= strlen (String
);
4598 if ((StrLen
> SmartFile
->FileLength
- SmartFile
->FilePosition
) ||
4599 (_strnicmp (&SmartFile
->FileContent
[SmartFile
->FilePosition
], String
, StrLen
) != 0)) {
4601 // file changed, need to re-create.
4603 if ((SmartFile
->FilePtr
= fopen (SmartFile
->FileName
, "w")) == NULL
) {
4604 Error (NULL
, 0, 0, SmartFile
->FileName
, "could not open file for writing when SmartWrite");
4607 SmartFile
->FileContent
[SmartFile
->FilePosition
] = 0;
4608 fprintf (SmartFile
->FilePtr
, "%s%s", SmartFile
->FileContent
, String
);
4612 SmartFile
->FilePosition
+= StrLen
;
4620 SMART_FILE
*SmartFile
4623 if ((SmartFile
->FilePtr
== NULL
) && (SmartFile
->FilePosition
< SmartFile
->FileLength
)) {
4625 // The new file is smaller than before, re-create it.
4627 if ((SmartFile
->FilePtr
= fopen (SmartFile
->FileName
, "w")) == NULL
) {
4628 Error (NULL
, 0, 0, SmartFile
->FileName
, "could not open file for writing when SmartClose");
4630 SmartFile
->FileContent
[SmartFile
->FilePosition
] = 0;
4631 fprintf (SmartFile
->FilePtr
, "%s", SmartFile
->FileContent
);
4635 SmartFree(SmartFile
);
4641 SMART_FILE
*SmartFile
4644 if (SmartFile
== NULL
) {
4648 if (SmartFile
->FileName
!= NULL
) {
4649 free (SmartFile
->FileName
);
4652 if (SmartFile
->FileContent
!= NULL
) {
4653 free (SmartFile
->FileContent
);
4656 if (SmartFile
->FilePtr
!= NULL
) {
4657 fclose (SmartFile
->FilePtr
);
4668 SYMBOL
**SymbolList
,
4674 Routine Description:
4676 Add module name in the global module list.
4677 For the same module names, it is only added once.
4680 SymbolList : add name into this list
4681 ModuleName : point to one module name char string.
4682 InfName : point to this module inf file name with path.
4686 0 : Successfully add input name into the global list.
4687 other value : allocate memory failed.
4691 SYMBOL
*CurrentSymbol
;
4695 // Get the global module list.
4697 CurrentSymbol
= *SymbolList
;
4698 LastSymbol
= *SymbolList
;
4701 // Search whether this module name has been added into the global list.
4703 while (CurrentSymbol
!= NULL
) {
4704 if (_stricmp (CurrentSymbol
->Name
, ModuleName
) == 0) {
4705 if ((CurrentSymbol
->Value
== NULL
) && (InfName
== NULL
)) {
4707 } else if ((CurrentSymbol
->Value
!= NULL
) && (InfName
!= NULL
) && \
4708 (_stricmp (CurrentSymbol
->Value
, InfName
) == 0)) {
4712 LastSymbol
= CurrentSymbol
;
4713 CurrentSymbol
= CurrentSymbol
->Next
;
4717 // Add new module name in list.
4719 if (CurrentSymbol
== NULL
) {
4720 CurrentSymbol
= (SYMBOL
*) malloc (sizeof (SYMBOL
));
4721 if (CurrentSymbol
== NULL
) {
4722 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
4725 memset ((INT8
*) CurrentSymbol
, 0, sizeof (SYMBOL
));
4727 if (ModuleName
!= NULL
) {
4728 CurrentSymbol
->Name
= (INT8
*) malloc (strlen (ModuleName
) + 1);
4729 strcpy (CurrentSymbol
->Name
, ModuleName
);
4732 if (InfName
!= NULL
) {
4733 CurrentSymbol
->Value
= (INT8
*) malloc (strlen (InfName
) + 1);
4734 strcpy (CurrentSymbol
->Value
, InfName
);
4737 if (LastSymbol
== NULL
) {
4738 *SymbolList
= CurrentSymbol
;
4740 LastSymbol
->Next
= CurrentSymbol
;
4755 Routine Description:
4757 Replace '/' with '\\'