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
557 /*****************************************************************************/
567 Main utility entry point.
571 Argc - Standard app entry point args.
572 Argv - Standard app entry point args.
584 INT8 Line
[MAX_LINE_LEN
];
585 INT8 ExpLine
[MAX_LINE_LEN
];
590 SetUtilityName (PROGRAM_NAME
);
594 DSCFileInit (&DSCFile
);
596 // Initialize the firmware volume data
600 // Exception handling for this block of code.
604 // Process command-line options.
606 if (ProcessOptions (Argc
, Argv
)) {
607 EMsg
= CatchException ();
609 fprintf (stderr
, "%s\n", EMsg
);
615 // Parse the GUID database file if specified
617 if (gGlobals
.GuidDatabaseFileName
[0] != 0) {
618 ParseGuidDatabaseFile (gGlobals
.GuidDatabaseFileName
);
621 // Set the output cross-reference file if applicable
623 if (gGlobals
.XRefFileName
[0]) {
624 CFVSetXRefFileName (gGlobals
.XRefFileName
);
628 // Now get the EFI_SOURCE directory which we use everywhere.
630 if (GetEfiSource ()) {
635 // Pre-process the DSC file to get section info.
637 if (DSCFileSetFile (&DSCFile
, gGlobals
.DscFilename
) != 0) {
638 goto ProcessingError
;
642 // Set output makefile name for single module build
644 strcpy (gGlobals
.ModuleMakefileName
, MODULE_MAKEFILE_NAME
);
647 // Try to open all final output makefiles
649 if ((gGlobals
.MakefileFptr
= fopen (gGlobals
.MakefileName
, "w")) == NULL
) {
650 Error (NULL
, 0, 0, gGlobals
.MakefileName
, "failed to open output makefile for writing");
651 goto ProcessingError
;
653 if ((gGlobals
.ModuleMakefileFptr
= fopen (gGlobals
.ModuleMakefileName
, "w")) == NULL
) {
654 Error (NULL
, 0, 0, gGlobals
.ModuleMakefileName
, "failed to open output makefile for writing");
655 goto ProcessingError
;
659 // Write the header out to the makefiles
661 for (i
= 0; MakefileHeader
[i
] != NULL
; i
++) {
662 fprintf (gGlobals
.MakefileFptr
, "%s\n", MakefileHeader
[i
]);
663 fprintf (gGlobals
.ModuleMakefileFptr
, "%s\n", MakefileHeader
[i
]);
667 // Init global potint = NULL
669 gGlobals
.ModuleList
= NULL
;
670 gGlobals
.OutdirList
= NULL
;
673 // Process the [defines] section in the DSC file to get any defines we need
676 ProcessDSCDefinesSection (&DSCFile
);
677 if (ExceptionThrown ()) {
678 goto ProcessingError
;
681 // Write out the [makefile.out] section data to the output makefiles
683 Sect
= DSCFileFindSection (&DSCFile
, MAKEFILE_OUT_SECTION_NAME
);
685 while (DSCFileGetLine (&DSCFile
, Line
, sizeof (Line
)) != NULL
) {
686 ExpandSymbols (Line
, ExpLine
, sizeof (ExpLine
), 0);
688 // Write the line to the output makefiles
690 fprintf (gGlobals
.MakefileFptr
, ExpLine
);
691 fprintf (gGlobals
.ModuleMakefileFptr
, ExpLine
);
696 // Add a pseudo target for GLOBAL_LINK_LIB_NAME to avoid single module build
697 // failure when this lib is not used.
699 fprintf (gGlobals
.ModuleMakefileFptr
, "%sbuild ::\n\n", GLOBAL_LINK_LIB_NAME
);
701 fprintf (gGlobals
.MakefileFptr
, "libraries : \n");
703 // Process [libraries] section in the DSC file
705 Sect
= DSCFileFindSection (&DSCFile
, LIBRARIES_SECTION_NAME
);
707 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_LIBRARIES
, 0);
710 if (ExceptionThrown ()) {
711 goto ProcessingError
;
714 // Process [libraries.platform] section in the DSC file
716 Sect
= DSCFileFindSection (&DSCFile
, LIBRARIES_PLATFORM_SECTION_NAME
);
718 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_PLATFORM_LIBRARIES
, 0);
721 fprintf (gGlobals
.MakefileFptr
, "\n");
722 if (ExceptionThrown ()) {
723 goto ProcessingError
;
727 // Process [components] section in the DSC file
729 Sect
= DSCFileFindSection (&DSCFile
, COMPONENTS_SECTION_NAME
);
731 fprintf (gGlobals
.MakefileFptr
, "components_0 : \n");
732 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_COMPONENTS
, 0);
733 fprintf (gGlobals
.MakefileFptr
, "\n");
736 if (ExceptionThrown ()) {
737 goto ProcessingError
;
740 // Now cycle through all [components.1], [components.2], ....[components.n].
741 // This is necessary to support building of firmware volumes that may contain
742 // other encapsulated firmware volumes (ala capsules).
746 RemoveSymbol (FV
, SYM_GLOBAL
);
747 sprintf (Line
, "%s.%d", COMPONENTS_SECTION_NAME
, i
);
748 Sect
= DSCFileFindSection (&DSCFile
, Line
);
750 fprintf (gGlobals
.MakefileFptr
, "components_%d : \n", i
);
751 ProcessSectionComponents (&DSCFile
, DSC_SECTION_TYPE_COMPONENTS
, i
);
752 fprintf (gGlobals
.MakefileFptr
, "\n");
757 if (ExceptionThrown ()) {
758 goto ProcessingError
;
765 EMsg
= CatchException ();
767 fprintf (stderr
, "%s\n", EMsg
);
768 fprintf (stderr
, "Processing aborted\n");
773 // Create the FV files if no fatal errors or errors
775 if (GetUtilityStatus () < STATUS_ERROR
) {
776 CFVWriteInfFiles (&DSCFile
, gGlobals
.MakefileFptr
);
780 // Write all module name into MODULE_NAME_FILE file.
782 if ((FpModule
= fopen (MODULE_NAME_FILE
, "w")) != NULL
) {
783 TempSymbol
= gGlobals
.ModuleList
;
784 while (TempSymbol
!= NULL
) {
785 fprintf (FpModule
, " %-*s %s \n", MODULE_BASE_NAME_WIDTH
, TempSymbol
->Name
, TempSymbol
->Value
);
786 TempSymbol
= TempSymbol
->Next
;
793 // Close the all the output makefiles
795 if (gGlobals
.MakefileFptr
!= NULL
) {
796 fclose (gGlobals
.MakefileFptr
);
797 gGlobals
.MakefileFptr
= NULL
;
800 if (gGlobals
.ModuleMakefileFptr
!= NULL
) {
801 fclose (gGlobals
.ModuleMakefileFptr
);
802 gGlobals
.ModuleMakefileFptr
= NULL
;
808 FreeSymbols (gGlobals
.ModuleList
);
809 FreeSymbols (gGlobals
.OutdirList
);
810 FreeSymbols (gGlobals
.Symbol
);
811 gGlobals
.Symbol
= NULL
;
813 DSCFileDestroy (&DSCFile
);
815 EMsg
= CatchException ();
817 fprintf (stderr
, "%s\n", EMsg
);
818 fprintf (stderr
, "Processing aborted\n");
821 return GetUtilityStatus ();
826 ProcessSectionComponents (
835 Process the [components] or [libraries] section in the description file. We
836 use this function for both since they're very similar. Here we just
837 read each line from the section, and if it's valid, call a function to
838 do the actual processing of the component description file.
842 DSCFile - structure containing section info on the description file
843 DscSectionType - type of description section
851 INT8 Line
[MAX_LINE_LEN
];
852 INT8 Line2
[MAX_EXP_LINE_LEN
];
856 // Read lines while they're valid
858 while (DSCFileGetLine (DSCFile
, Line
, sizeof (Line
)) != NULL
) {
860 // Expand symbols on the line
862 if (ExpandSymbols (Line
, Line2
, sizeof (Line2
), 0)) {
868 Cptr
= StripLine (Line2
);
870 Message (2, "Processing component line: %s", Line2
);
871 if (ProcessComponentFile (DSCFile
, Line2
, DscSectionType
, Instance
) != 0) {
882 ProcessComponentFile (
892 Given a line from the [components] or [libraries] section of the description
893 file, process the line to extract the component's INF filename and
894 parameters. Then open the INF file and process it to create a corresponding
899 DSCFile The project DSC file info structure.
900 Libs Indicates whether we're processing the [components]
901 section or the [libraries] section.
902 ArgLine The actual line from the DSC file. Looks something like
903 one of the following:
905 dxe\drivers\vm\vm.dsc PROCESSOR=IA32 DEST_DIR=$(DEST_DIR)\xxx FV=FV1,FV2
906 $(BUILD_DIR).\FvVariable.ffs COMPONENT_TYPE=FILE
907 .\FvVariable.ffs COMPONENT_TYPE=FILE
908 define VAR1=value1 VAR2=value2
922 INT8 FileName
[MAX_PATH
];
923 INT8 ComponentFilePath
[MAX_PATH
];
924 INT8 InLine
[MAX_LINE_LEN
];
925 INT8 Line
[MAX_LINE_LEN
];
929 int ComponentCreated
;
930 int ComponentFilePathAbsolute
;
932 DSC_FILE ComponentFile
;
933 INT8 ComponentMakefileName
[MAX_PATH
];
937 // Now remove all local symbols
939 RemoveLocalSymbols ();
941 // Null out the file pointer in case we take an exception somewhere
942 // and we need to close it only if we opened it.
945 ComponentFilePathAbsolute
= 0;
946 ComponentCreated
= 0;
948 // Skip preceeding spaces on the line
950 while (isspace (*ArgLine
) && (*ArgLine
)) {
954 // Find the end of the component's filename and truncate the line at that
955 // point. From here on out ArgLine is the name of the component filename.
958 while (!isspace (*Cptr
) && *Cptr
) {
968 // Exception-handle processing of this component description file
973 // We also allow a component line format for defines of global symbols
974 // instead of a component filename. In this case, the line looks like:
975 // defines x=abc y=yyy. Be nice and accept "define" and "defines" in a
976 // case-insensitive manner. If it's defines, then make the symbols global.
978 if ((_stricmp (ArgLine
, "define") == 0) || (_stricmp (ArgLine
, "defines") == 0)) {
979 SymType
= SYM_OVERWRITE
| SYM_GLOBAL
;
982 SymType
= SYM_OVERWRITE
| SYM_LOCAL
;
986 // The rest of the component line from the DSC file should be defines
989 End
= StripLine (End
);
992 // If we're processing a "define abc=1 xyz=2" line, then set symbols
993 // as globals per the SymType set above.
995 Len
= AddSymbol (End
, NULL
, SymType
);
999 Warning (NULL
, 0, 0, ArgLine
, "unrecognized option in description file");
1006 // If DEBUG_BREAK or EFI_BREAKPOINT is defined, then do a debug breakpoint.
1008 if ((GetSymbolValue ("DEBUG_BREAK") != NULL
) || (GetSymbolValue ("EFI_BREAKPOINT") != NULL
)) {
1013 // If it's a define line, then we're done
1017 // If there is NonFFS_FV, create the FVxxx.inf file
1018 // and include it in makefile.out. Remove the symbol
1019 // in order not to process it again next time
1021 Cptr
= GetSymbolValue (NONFFS_FV
);
1023 NonFFSFVWriteInfFiles (DSCFile
, Cptr
);
1024 RemoveSymbol (NONFFS_FV
, SYM_GLOBAL
);
1031 // Expand symbols in the component description filename to expand the newly
1032 // added local symbols
1034 ExpandSymbols (ArgLine
, Line
, sizeof (Line
), EXPANDMODE_NO_UNDEFS
);
1037 // If we have "c:\path\filename"
1039 if (IsAbsolutePath (Line
)) {
1040 ComponentFilePathAbsolute
= 1;
1041 } else if (Line
[0] == '.') {
1043 // or if the path starts with ".", then it's build-dir relative.
1044 // Prepend $(BUILD_DIR) on the file name
1046 sprintf (InLine
, "%s\\%s", GetSymbolValue (BUILD_DIR
), Line
);
1047 strcpy (Line
, InLine
);
1048 ComponentFilePathAbsolute
= 1;
1052 // Save the path from the component name for later. It may be relative or
1055 strcpy (ComponentFilePath
, Line
);
1056 Cptr
= ComponentFilePath
+ strlen (ComponentFilePath
) - 1;
1057 while ((*Cptr
!= '\\') && (*Cptr
!= '/') && (Cptr
!= ComponentFilePath
)) {
1061 // Terminate the path.
1066 // Typically the given line is a component description filename. However we
1067 // also allow a FV filename (fvvariable.ffs COMPONENT_TYPE=FILE). If the
1068 // component type is "FILE", then add it to the FV list, create a package
1069 // file, and we're done.
1071 Cptr
= GetSymbolValue (COMPONENT_TYPE
);
1072 if ((Cptr
!= NULL
) && (strncmp (
1074 COMPONENT_TYPE_FILE
,
1075 strlen (COMPONENT_TYPE_FILE
)
1077 if (ComponentFilePathAbsolute
) {
1078 strcpy (InLine
, Line
);
1080 sprintf (InLine
, "%s\\%s", GetSymbolValue (EFI_SOURCE
), Line
);
1085 GetSymbolValue (FV
),
1089 GetSymbolValue (APRIORI
),
1097 // Better have defined processor by this point.
1099 Processor
= GetSymbolValue (PROCESSOR
);
1100 if (Processor
== NULL
) {
1101 Error (NULL
, 0, 0, NULL
, "PROCESSOR not defined for component %s", Line
);
1102 return STATUS_ERROR
;
1106 // The bin, out, and lib dirs are now = $(BUILD_DIR)/$(PROCESSOR). Set them.
1107 // Don't flag them as file paths (required for short 8.3 filenames) since
1108 // they're defined using the BUILD_DIR macro.
1110 sprintf (InLine
, "$(BUILD_DIR)\\%s", Processor
);
1111 AddSymbol (BIN_DIR
, InLine
, SYM_LOCAL
);
1112 AddSymbol (OUT_DIR
, InLine
, SYM_LOCAL
);
1113 AddSymbol (LIB_DIR
, InLine
, SYM_LOCAL
);
1115 // See if it's been destined for an FV. It's possible to not be in an
1116 // FV if they just want to build it.
1118 Cptr
= GetSymbolValue (FV
);
1119 if ((Cptr
!= NULL
) && !IS_NULL_SYMBOL_VALUE (Cptr
)) {
1125 // As an optimization, if they've defined SKIP_FV_NULL as non-zero, and
1126 // the component is not destined for an FV, then skip it.
1127 // Since libraries are never intended for firmware volumes, we have to
1128 // build all of them.
1130 if ((DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) && (IsForFv
== FALSE
)) {
1131 if ((GetSymbolValue (SKIP_FV_NULL
) != NULL
) && (atoi (GetSymbolValue (SKIP_FV_NULL
)) != 0)) {
1132 Message (0, "%s not being built (FV=NULL)", FileName
);
1137 // Prepend EFI_SOURCE to the component description file to get the
1138 // full path. Only do this if the path is not a full path already.
1140 if (ComponentFilePathAbsolute
== 0) {
1141 name
= GetSymbolValue (EFI_SOURCE
);
1142 sprintf (FileName
, "%s\\%s", name
, Line
);
1144 strcpy (FileName
, Line
);
1147 // Print a message, depending on verbose level.
1149 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1150 Message (1, "Processing component %s", FileName
);
1152 Message (1, "Processing library %s", FileName
);
1155 // Open the component's description file and get the sections. If we fail
1156 // to open it, see if they defined "OPTIONAL=1, in which case we'll just
1157 // ignore the component.
1159 TempFptr
= fopen (FileName
, "r");
1160 if (TempFptr
== NULL
) {
1162 // Better have defined OPTIONAL
1164 if (GetSymbolValue (OPTIONAL_COMPONENT
) != NULL
) {
1165 if (atoi (GetSymbolValue (OPTIONAL_COMPONENT
)) != 0) {
1166 Message (0, "Optional component '%s' not found", FileName
);
1171 ParserError (0, FileName
, "failed to open component file");
1172 return STATUS_ERROR
;
1177 DSCFileInit (&ComponentFile
);
1178 ComponentCreated
= 1;
1179 if (DSCFileSetFile (&ComponentFile
, FileName
)) {
1180 Error (NULL
, 0, 0, NULL
, "failed to preprocess component file '%s'", FileName
);
1181 return STATUS_ERROR
;
1184 // Add a symbol for the INF filename so users can create dependencies
1187 AddSymbol (INF_FILENAME
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILENAME
);
1189 // Process the [defines], [defines.$(PROCESSOR)], and [defines.$(PROCESSOR).$(PLATFORM)]
1190 // sections in the INF file
1192 ProcessINFDefinesSection (&ComponentFile
);
1194 // Better have defined FILE_GUID if not a library
1196 if ((GetSymbolValue (GUID
) == NULL
) &&
1197 (GetSymbolValue (FILE_GUID
) == NULL
) &&
1198 (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
)
1200 Error (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "missing FILE_GUID definition in component file");
1201 DSCFileDestroy (&ComponentFile
);
1202 return STATUS_ERROR
;
1205 // Better have defined base name
1207 if (GetSymbolValue (BASE_NAME
) == NULL
) {
1208 Error (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "missing BASE_NAME definition in INF file");
1209 DSCFileDestroy (&ComponentFile
);
1210 return STATUS_ERROR
;
1213 // Better have defined COMPONENT_TYPE, since it's used to find named sections.
1215 if (GetSymbolValue (COMPONENT_TYPE
) == NULL
) {
1216 Error (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "missing COMPONENT_TYPE definition in INF file");
1217 DSCFileDestroy (&ComponentFile
);
1218 return STATUS_ERROR
;
1222 // Create the source directory path from the component file's path. If the component
1223 // file's path is absolute, we may have problems here. Try to account for it though.
1225 if (ComponentFilePathAbsolute
== 0) {
1229 GetSymbolValue (EFI_SOURCE
),
1233 strcpy (FileName
, ComponentFilePath
);
1235 AddSymbol (SOURCE_DIR
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILEPATH
);
1238 // Create the destination path.
1239 // They may have defined DEST_DIR on the component INF line, so it's already
1240 // been defined, If that's the case, then don't set it to the path of this file.
1242 if (GetSymbolValue (DEST_DIR
) == NULL
) {
1243 if (ComponentFilePathAbsolute
== 0) {
1245 // The destination path is $(BUILD_DIR)\$(PROCESSOR)\component_path
1250 GetSymbolValue (BUILD_DIR
),
1256 // The destination path is $(BUILD_DIR)\$(PROCESSOR)\$(BASE_NAME)
1261 GetSymbolValue (BUILD_DIR
),
1263 GetSymbolValue (BASE_NAME
)
1266 AddSymbol (DEST_DIR
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILEPATH
);
1270 // Create the output directory, then open the output component's makefile
1271 // we're going to create. Allow them to override the makefile name.
1273 TempCptr
= GetSymbolValue (MAKEFILE_NAME
);
1274 if (TempCptr
!= NULL
) {
1275 ExpandSymbols (TempCptr
, ComponentMakefileName
, sizeof (ComponentMakefileName
), EXPANDMODE_NO_UNDEFS
);
1276 TempCptr
= ComponentMakefileName
;
1278 TempCptr
= "makefile";
1281 sprintf (FileName
, "%s\\%s", GetSymbolValue (DEST_DIR
), TempCptr
);
1283 // Save it now with path info
1285 AddSymbol (MAKEFILE_NAME
, FileName
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILENAME
);
1287 if (MakeFilePath (FileName
)) {
1288 return STATUS_ERROR
;
1291 if ((MakeFptr
= fopen (FileName
, "w")) == NULL
) {
1292 Error (NULL
, 0, 0, FileName
, "could not create makefile");
1293 return STATUS_ERROR
;
1296 // At this point we should have all the info we need to create a package
1297 // file if setup to do so. Libraries don't use package files, so
1298 // don't do this for libs.
1300 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1301 CreatePackageFile (DSCFile
);
1305 // Add Module name to the global module list
1307 AddModuleName (&gGlobals
.ModuleList
, GetSymbolValue (BASE_NAME
), GetSymbolValue (INF_FILENAME
));
1309 // Write an nmake line to makefile.out
1311 fprintf (gGlobals
.MakefileFptr
, " @cd %s\n", Processor
);
1312 fprintf (gGlobals
.MakefileFptr
, " $(MAKE) -f %s all\n", FileName
);
1313 fprintf (gGlobals
.MakefileFptr
, " @cd ..\n");
1316 // Copy the common makefile section from the description file to
1317 // the component's makefile
1319 WriteCommonMakefile (DSCFile
, MakeFptr
, Processor
);
1321 // Process the component's [nmake.common] and [nmake.$(PROCESSOR)] sections
1323 ProcessINFNMakeSection (&ComponentFile
, MakeFptr
);
1325 // Create the SOURCE_FILES macro that includes the names of all source
1326 // files in this component. This macro can then be used elsewhere to
1327 // process all the files making up the component. Required for scanning
1328 // files for string localization.
1330 ProcessSourceFiles (DSCFile
, &ComponentFile
, MakeFptr
, SOURCE_MODE_SOURCE_FILES
);
1332 // Create the include paths. Process [includes.common] and
1333 // [includes.$(PROCESSOR)] and [includes.$(PROCESSOR).$(PLATFORM)] sections.
1335 ProcessIncludesSection (&ComponentFile
, MakeFptr
);
1337 // Process all include source files to create a dependency list that can
1338 // be used in the makefile.
1340 ProcessIncludeFiles (&ComponentFile
, MakeFptr
);
1342 // Process the [sources.common], [sources.$(PROCESSOR)], and
1343 // [sources.$(PROCESSOR).$(PLATFORM)] files and emit their build commands
1345 ProcessSourceFiles (DSCFile
, &ComponentFile
, MakeFptr
, SOURCE_MODE_BUILD_COMMANDS
);
1347 // Process sources again to create an OBJECTS macro
1349 ProcessObjects (&ComponentFile
, MakeFptr
);
1352 // Add Single Module target : build and clean in top level makefile
1354 fprintf (gGlobals
.ModuleMakefileFptr
, "%sbuild ::", GetSymbolValue (BASE_NAME
));
1355 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1356 fprintf (gGlobals
.ModuleMakefileFptr
, " %sbuild", GLOBAL_LINK_LIB_NAME
);
1360 // Process all the libraries to define "LIBS = x.lib y.lib..."
1361 // Be generous and append ".lib" if they forgot.
1362 // Make a macro definition: LIBS = $(LIBS) xlib.lib ylib.lib...
1363 // Also add libs dependency for single module build: basenamebuild :: xlibbuild ylibbuild ...
1365 ProcessLibs (&ComponentFile
, MakeFptr
);
1367 fprintf (gGlobals
.ModuleMakefileFptr
, "\n");
1369 fprintf (gGlobals
.ModuleMakefileFptr
, " @cd %s\n", Processor
);
1370 fprintf (gGlobals
.ModuleMakefileFptr
, " $(MAKE) -f %s all\n", FileName
);
1371 fprintf (gGlobals
.ModuleMakefileFptr
, " @cd ..\n\n");
1373 fprintf (gGlobals
.ModuleMakefileFptr
, "%sclean ::\n", GetSymbolValue (BASE_NAME
));
1374 fprintf (gGlobals
.ModuleMakefileFptr
, " $(MAKE) -f %s clean\n\n", FileName
);
1377 // Emit commands to create the component. These are simply copied from
1378 // the description file to the component's makefile. First look for
1379 // [build.$(PROCESSOR).$(BUILD_TYPE)]. If not found, then look for if
1380 // find a [build.$(PROCESSOR).$(COMPONENT_TYPE)] line.
1382 Cptr
= GetSymbolValue (BUILD_TYPE
);
1384 sprintf (InLine
, "build.%s.%s", Processor
, Cptr
);
1385 WriteComponentTypeBuildCommands (DSCFile
, MakeFptr
, InLine
);
1387 sprintf (InLine
, "build.%s.%s", Processor
, GetSymbolValue (COMPONENT_TYPE
));
1388 WriteComponentTypeBuildCommands (DSCFile
, MakeFptr
, InLine
);
1391 // Add it to the FV if not a library
1393 if (DscSectionType
== DSC_SECTION_TYPE_COMPONENTS
) {
1395 // Create the FV filename and add it to the FV.
1396 // By this point we know it's in FV.
1398 Cptr
= GetSymbolValue (FILE_GUID
);
1400 Cptr
= GetSymbolValue (GUID
);
1403 sprintf (InLine
, "%s-%s", Cptr
, GetSymbolValue (BASE_NAME
));
1405 // We've deprecated FV_EXT, which should be FFS_EXT, the extension
1406 // of the FFS file generated by GenFFSFile.
1408 TempCptr
= GetSymbolValue (FFS_EXT
);
1409 if (TempCptr
== NULL
) {
1410 TempCptr
= GetSymbolValue ("FV_EXT");
1415 GetSymbolValue (COMPONENT_TYPE
),
1416 GetSymbolValue (FV
),
1420 GetSymbolValue (APRIORI
),
1421 GetSymbolValue (BASE_NAME
),
1426 // Catch any failures and print the name of the component file
1427 // being processed to assist debugging.
1431 Cptr
= CatchException ();
1433 fprintf (stderr
, "%s\n", Cptr
);
1434 sprintf (InLine
, "Processing of component %s failed", ArgLine
);
1435 ThrowException (InLine
);
1438 if (MakeFptr
!= NULL
) {
1442 if (ComponentCreated
) {
1443 DSCFileDestroy (&ComponentFile
);
1446 return STATUS_SUCCESS
;
1457 INT8 Str
[MAX_LINE_LEN
];
1458 INT8 StrExpanded
[MAX_LINE_LEN
];
1459 SMART_FILE
*PkgFptr
;
1465 // First find out if PACKAGE_FILENAME or PACKAGE is defined. PACKAGE_FILENAME
1466 // is used to specify the exact package file to use. PACKAGE is used to
1467 // specify the package section name.
1469 Package
= GetSymbolValue (PACKAGE_FILENAME
);
1470 if (Package
!= NULL
) {
1472 // Use existing file. We're done.
1474 return STATUS_SUCCESS
;
1477 // See if PACKAGE or PACKAGE_TAG is defined
1479 Package
= GetSymbolValue (PACKAGE
);
1480 if (Package
== NULL
) {
1481 Package
= GetSymbolValue (PACKAGE_TAG
);
1484 if (Package
== NULL
) {
1486 // Not defined either. Assume they are not using the package functionality
1487 // of this utility. However define the PACKAGE_FILENAME macro to the
1488 // best-guess value.
1493 GetSymbolValue (SOURCE_DIR
),
1494 GetSymbolValue (BASE_NAME
)
1498 // Expand symbols in the package filename
1500 ExpandSymbols (Str
, StrExpanded
, sizeof (StrExpanded
), EXPANDMODE_NO_UNDEFS
);
1502 AddSymbol (PACKAGE_FILENAME
, StrExpanded
, SYM_LOCAL
| SYM_FILENAME
);
1503 return STATUS_SUCCESS
;
1506 // Save the position in the DSC file.
1507 // Find the [package.$(COMPONENT_TYPE).$(PACKAGE)] section in the DSC file
1509 Status
= STATUS_SUCCESS
;
1510 DSCFileSavePosition (DSCFile
);
1511 sprintf (Str
, "%s.%s.%s", PACKAGE
, GetSymbolValue (COMPONENT_TYPE
), Package
);
1512 TempSect
= DSCFileFindSection (DSCFile
, Str
);
1513 if (TempSect
!= NULL
) {
1515 // So far so good. Create the name of the package file, then open it up
1516 // for writing. File name is c:\...\oem\platform\nt32\ia32\...\BaseName.pkg.
1521 GetSymbolValue (DEST_DIR
),
1522 GetSymbolValue (BASE_NAME
)
1526 // Expand symbols in the package filename
1528 ExpandSymbols (Str
, StrExpanded
, sizeof (StrExpanded
), EXPANDMODE_NO_UNDEFS
);
1531 // Try to open the file, then save the file name as the PACKAGE_FILENAME
1532 // symbol for use elsewhere.
1534 if ((PkgFptr
= SmartOpen (StrExpanded
)) == NULL
) {
1535 Error (NULL
, 0, 0, Str
, "could not open package file for writing");
1536 Status
= STATUS_ERROR
;
1540 AddSymbol (PACKAGE_FILENAME
, StrExpanded
, SYM_LOCAL
| SYM_FILENAME
);
1542 // Now read lines in from the DSC file and write them back out to the
1543 // package file (with string substitution).
1545 while (DSCFileGetLine (DSCFile
, Str
, sizeof (Str
)) != NULL
) {
1547 // Expand symbols, then write the line out to the package file
1549 ExpandSymbols (Str
, StrExpanded
, sizeof (StrExpanded
), EXPANDMODE_RECURSIVE
);
1550 SmartWrite (PkgFptr
, StrExpanded
);
1558 "cannot locate package section [%s] in DSC file for %s",
1560 GetSymbolValue (INF_FILENAME
)
1562 Status
= STATUS_WARNING
;
1566 if (PkgFptr
!= NULL
) {
1567 SmartClose (PkgFptr
);
1572 // Restore the position in the DSC file
1574 DSCFileRestorePosition (DSCFile
);
1576 return STATUS_SUCCESS
;
1581 ProcessINFDefinesSection (
1582 DSC_FILE
*ComponentFile
1586 Routine Description:
1588 Process the [defines.xxx] sections of the component description file. Process
1589 platform first, then processor. In this way, if a platform wants and override,
1590 that one gets parsed first, and later assignments do not overwrite the value.
1594 ComponentFile - section info on the component file being processed
1602 INT8 Str
[MAX_LINE_LEN
];
1605 // Find a [defines.$(PROCESSOR).$(PLATFORM)] section and process it
1607 Cptr
= GetSymbolValue (PLATFORM
);
1612 DEFINES_SECTION_NAME
,
1613 GetSymbolValue (PROCESSOR
),
1616 ProcessINFDefinesSectionSingle (ComponentFile
, Str
);
1619 // Find a [defines.$(PROCESSOR)] section and process it
1621 sprintf (Str
, "%s.%s", DEFINES_SECTION_NAME
, GetSymbolValue (PROCESSOR
));
1622 ProcessINFDefinesSectionSingle (ComponentFile
, Str
);
1625 // Find a [defines] section and process it
1627 if (ProcessINFDefinesSectionSingle (ComponentFile
, DEFINES_SECTION_NAME
) != STATUS_SUCCESS
) {
1628 Error (NULL
, 0, 0, NULL
, "missing [defines] section in component file %s", GetSymbolValue (INF_FILENAME
));
1629 return STATUS_ERROR
;
1632 return STATUS_SUCCESS
;
1637 ProcessINFDefinesSectionSingle (
1638 DSC_FILE
*ComponentFile
,
1643 INT8 Str
[MAX_LINE_LEN
];
1644 INT8 ExpandedLine
[MAX_LINE_LEN
];
1647 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
1648 if (TempSect
!= NULL
) {
1649 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1650 ExpandSymbols (Str
, ExpandedLine
, sizeof (ExpandedLine
), 0);
1651 Cptr
= StripLine (ExpandedLine
);
1653 // Don't process blank lines.
1657 // Add without overwriting macros specified on the component line
1658 // in the description file
1660 AddSymbol (Cptr
, NULL
, SYM_LOCAL
);
1664 return STATUS_WARNING
;
1667 return STATUS_SUCCESS
;
1672 ProcessINFNMakeSection (
1673 DSC_FILE
*ComponentFile
,
1678 Routine Description:
1680 Process the [nmake.common] and [nmake.$(PROCESSOR)] sections of the component
1681 description file and write and copy them to the component's makefile.
1685 ComponentFile - section info on the component file being processed
1686 MakeFptr - file pointer to the component' makefile we're creating
1690 Always STATUS_SUCCESS right now, since the sections are optional.
1695 INT8 Str
[MAX_LINE_LEN
];
1696 INT8 ExpandedLine
[MAX_LINE_LEN
];
1700 // Copy the [nmake.common] and [nmake.$(PROCESSOR)] sections from the
1701 // component file directly to the output file.
1702 // The line will be stripped and don't print blank lines
1704 sprintf (Str
, "%s.%s", NMAKE_SECTION_NAME
, COMMON_SECTION_NAME
);
1705 TempSect
= DSCFileFindSection (ComponentFile
, Str
);
1706 if (TempSect
!= NULL
) {
1707 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1711 sizeof (ExpandedLine
),
1712 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
1714 Cptr
= StripLine (ExpandedLine
);
1716 fprintf (MakeFptr
, "%s\n", Cptr
);
1720 fprintf (MakeFptr
, "\n");
1722 Error (GetSymbolValue (INF_FILENAME
), 1, 0, Str
, "section not found in component INF file");
1725 sprintf (Str
, "%s.%s", NMAKE_SECTION_NAME
, GetSymbolValue (PROCESSOR
));
1726 TempSect
= DSCFileFindSection (ComponentFile
, Str
);
1727 if (TempSect
!= NULL
) {
1728 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1732 sizeof (ExpandedLine
),
1733 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
1735 Cptr
= StripLine (ExpandedLine
);
1737 fprintf (MakeFptr
, "%s\n", Cptr
);
1741 fprintf (MakeFptr
, "\n");
1744 // Do the same for [nmake.$(PROCESSOR).$(PLATFORM)]
1746 Cptr
= GetSymbolValue (PLATFORM
);
1748 sprintf (Str
, "%s.%s.%s", NMAKE_SECTION_NAME
, GetSymbolValue (PROCESSOR
), Cptr
);
1749 TempSect
= DSCFileFindSection (ComponentFile
, Str
);
1750 if (TempSect
!= NULL
) {
1751 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1755 sizeof (ExpandedLine
),
1756 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
1758 Cptr
= StripLine (ExpandedLine
);
1760 fprintf (MakeFptr
, "%s\n", Cptr
);
1764 fprintf (MakeFptr
, "\n");
1768 return STATUS_SUCCESS
;
1773 ProcessIncludesSection (
1774 DSC_FILE
*ComponentFile
,
1779 Routine Description:
1781 Process the [includes.common], [includes.processor], and
1782 [includes.processor.platform] section of the component description file
1783 and write the appropriate macros to the component's makefile.
1785 Process in reverse order to allow overrides on platform basis.
1789 ComponentFile - section info on the component file being processed
1790 MakeFptr - file pointer to the component' makefile we're creating
1794 Always STATUS_SUCCESS right now, since the sections are optional.
1799 INT8 Str
[MAX_LINE_LEN
];
1804 // Write a useful comment to the output makefile so the user knows where
1805 // the data came from.
1807 fprintf (MakeFptr
, "#\n# Tool-generated list of include paths that are created\n");
1808 fprintf (MakeFptr
, "# from the list of include paths in the [includes.*] sections\n");
1809 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
1812 // We use this a lot here, so get the value only once.
1814 Processor
= GetSymbolValue (PROCESSOR
);
1816 // If they're using an override source path, then add OverridePath and
1817 // OverridePath\$(PROCESSOR) to the list of include paths.
1819 OverridePath
= GetSymbolValue (SOURCE_OVERRIDE_PATH
);
1820 if (OverridePath
!= NULL
) {
1821 fprintf (MakeFptr
, "INC = $(INC) -I %s\n", OverridePath
);
1822 fprintf (MakeFptr
, "INC = $(INC) -I %s\\%s \n", OverridePath
, Processor
);
1825 // Try for an [includes.$(PROCESSOR).$(PLATFORM)]
1827 Cptr
= GetSymbolValue (PLATFORM
);
1829 sprintf (Str
, "%s.%s.%s", INCLUDE_SECTION_NAME
, Processor
, Cptr
);
1830 ProcessIncludesSectionSingle (ComponentFile
, MakeFptr
, Str
);
1833 // Now the [includes.$(PROCESSOR)] section
1835 sprintf (Str
, "%s.%s", INCLUDE_SECTION_NAME
, Processor
);
1836 ProcessIncludesSectionSingle (ComponentFile
, MakeFptr
, Str
);
1839 // Now the [includes.common] section
1841 sprintf (Str
, "%s.%s", INCLUDE_SECTION_NAME
, COMMON_SECTION_NAME
);
1842 ProcessIncludesSectionSingle (ComponentFile
, MakeFptr
, Str
);
1847 fprintf (MakeFptr
, "\n");
1848 return STATUS_SUCCESS
;
1851 // Process one of the [includes.xxx] sections to create a list of all
1852 // the include paths.
1856 ProcessIncludesSectionSingle (
1857 DSC_FILE
*ComponentFile
,
1864 INT8 Str
[MAX_LINE_LEN
];
1865 INT8 ExpandedLine
[MAX_LINE_LEN
];
1868 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
1869 if (TempSect
!= NULL
) {
1871 // Add processor subdirectory on every include path
1873 Processor
= GetSymbolValue (PROCESSOR
);
1875 // Copy lines directly
1877 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
1878 ExpandSymbols (Str
, ExpandedLine
, sizeof (ExpandedLine
), 0);
1879 Cptr
= StripLine (ExpandedLine
);
1881 // Don't process blank lines
1885 // Strip off trailing slash
1887 if (Cptr
[strlen (Cptr
) - 1] == '\\') {
1888 Cptr
[strlen (Cptr
) - 1] = 0;
1891 // Special case of ".". Replace it with source path
1892 // and the rest of the line (for .\$(PROCESSOR))
1896 // Handle case of just a "."
1899 fprintf (MakeFptr
, "INC = $(INC) -I $(SOURCE_DIR)\n");
1902 "INC = $(INC) -I $(SOURCE_DIR)\\%s \n",
1907 // Handle case of ".\path\path\path" or "..\path\path\path"
1911 "INC = $(INC) -I $(SOURCE_DIR)\\%s \n",
1916 "INC = $(INC) -I $(SOURCE_DIR)\\%s\\%s \n",
1921 } else if ((Cptr
[1] != ':') && isalpha (*Cptr
)) {
1922 fprintf (MakeFptr
, "INC = $(INC) -I $(EFI_SOURCE)\\%s \n", Cptr
);
1925 "INC = $(INC) -I $(EFI_SOURCE)\\%s\\%s \n",
1931 // The line is something like: $(EFI_SOURCE)\dxe\include. Add it to
1932 // the existing $(INC) definition. Add user includes before any
1933 // other existing paths.
1935 fprintf (MakeFptr
, "INC = $(INC) -I %s \n", Cptr
);
1936 fprintf (MakeFptr
, "INC = $(INC) -I %s\\%s \n", Cptr
, Processor
);
1942 return STATUS_SUCCESS
;
1947 ProcessSourceFiles (
1949 DSC_FILE
*ComponentFile
,
1955 Routine Description:
1957 Process the [sources.common], [sources.$(PROCESSOR)], and
1958 [sources.$(PROCESSOR).$(PLATFORM] sections of the component
1959 description file and write the appropriate build commands out to the
1960 component's makefile. If $(SOURCE_SELECT) is defined, then it overrides
1961 the source selections. We use this functionality for SMM.
1965 ComponentFile - section info on the component file being processed
1966 MakeFptr - file pointer to the component' makefile we're creating
1967 DSCFile - section info on the description file we're processing
1968 Mode - to write build commands, or just create a list
1973 Always STATUS_SUCCESS right now, since the sections are optional.
1977 INT8 Str
[MAX_LINE_LEN
];
1984 INT8
*CopySourceSelect
;
1986 if (Mode
& SOURCE_MODE_SOURCE_FILES
) {
1988 // Write a useful comment to the output makefile so the user knows where
1989 // the data came from.
1991 fprintf (MakeFptr
, "#\n# Tool-generated list of source files that are created\n");
1992 fprintf (MakeFptr
, "# from the list of source files in the [sources.*] sections\n");
1993 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
1997 // We use this a lot here, so get the value only once.
1999 Processor
= GetSymbolValue (PROCESSOR
);
2001 // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll
2002 // select each [sources.xxx] and [sources.yyy] files and process
2005 SourceSelect
= GetSymbolValue (SOURCE_SELECT
);
2007 if (SourceSelect
!= NULL
) {
2009 // Make a copy of the string and break it up (comma-separated) and
2010 // select each [sources.*] file from the INF.
2012 CopySourceSelect
= (INT8
*) malloc (strlen (SourceSelect
) + 1);
2013 if (CopySourceSelect
== NULL
) {
2014 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2015 return STATUS_ERROR
;
2018 strcpy (CopySourceSelect
, SourceSelect
);
2019 CStart
= CopySourceSelect
;
2023 while (*CEnd
&& *CEnd
!= ',') {
2029 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, CStart
);
2030 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2032 // Restore the terminator and advance
2041 free (CopySourceSelect
);
2045 // Process all the [sources.common] source files to make them build
2047 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, COMMON_SECTION_NAME
);
2048 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2050 // Now process the [sources.$(PROCESSOR)] files.
2052 sprintf (Str
, "sources.%s", Processor
);
2053 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2055 // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files.
2057 Platform
= GetSymbolValue (PLATFORM
);
2058 if (Platform
!= NULL
) {
2059 sprintf (Str
, "sources.%s.%s", Processor
, Platform
);
2060 ProcessSourceFilesSection (DSCFile
, ComponentFile
, MakeFptr
, Str
, Mode
);
2064 fprintf (MakeFptr
, "\n");
2065 return STATUS_SUCCESS
;
2070 Routine Description:
2071 Given a source file line from an INF file, parse it to see if there are
2072 any defines on it. If so, then add them to the symbol table.
2073 Also, terminate the line after the file name.
2076 SourceFileLine - a line from a [sources.?] section of the INF file. Likely
2079 MySourceFile.c BUILT_NAME=$(BUILD_DIR)\MySourceFile.obj
2088 INT8
*SourceFileLine
2095 for (; *SourceFileLine
&& isspace (*SourceFileLine
); SourceFileLine
++)
2097 for (; *SourceFileLine
&& !isspace (*SourceFileLine
); SourceFileLine
++)
2099 if (*SourceFileLine
) {
2100 *SourceFileLine
= 0;
2103 // AddSymbol() will parse it for us, and return the length. Keep calling
2104 // it until it reports an error or is done.
2107 Len
= AddSymbol (SourceFileLine
, NULL
, SYM_FILE
);
2108 SourceFileLine
+= Len
;
2113 // Process a single section of source files in the component INF file
2117 ProcessSourceFilesSection (
2119 DSC_FILE
*ComponentFile
,
2126 INT8 FileName
[MAX_EXP_LINE_LEN
];
2127 INT8 FilePath
[MAX_PATH
];
2128 INT8 TempFileName
[MAX_PATH
];
2130 INT8 Str
[MAX_LINE_LEN
];
2135 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2136 if (TempSect
!= NULL
) {
2137 Processor
= GetSymbolValue (PROCESSOR
);
2138 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2139 Cptr
= StripLine (Str
);
2141 // Don't process blank lines
2145 // Expand symbols in the filename, then parse the line for symbol
2146 // definitions. AddFileSymbols() will null-terminate the line
2147 // after the file name. Save a copy for override purposes, in which
2148 // case we'll need to know the file name and path (in case it's in
2151 ExpandSymbols (Cptr
, FileName
, sizeof (FileName
), 0);
2152 AddFileSymbols (FileName
);
2154 // Set the SOURCE_FILE_NAME symbol. What we have now is the name of
2155 // the file, relative to the location of the INF file. So prepend
2156 // $(SOURCE_DIR) to it first.
2158 if (IsAbsolutePath (FileName
)) {
2159 strcpy (TempFileName
, FileName
);
2161 strcpy (TempFileName
, "$(SOURCE_DIR)\\");
2162 strcat (TempFileName
, FileName
);
2164 AddSymbol (SOURCE_FILE_NAME
, TempFileName
, SYM_FILE
| SYM_OVERWRITE
);
2166 // Extract path information from the source file and set internal
2167 // variable SOURCE_RELATIVE_PATH. Only do this if the path
2168 // contains a backslash.
2170 strcpy (FilePath
, FileName
);
2171 for (Cptr
= FilePath
+ strlen (FilePath
) - 1; (Cptr
> FilePath
) && (*Cptr
!= '\\'); Cptr
--)
2173 if (*Cptr
== '\\') {
2175 AddSymbol (SOURCE_RELATIVE_PATH
, FilePath
, SYM_FILE
);
2178 // Define another internal symbol for the name of the file without
2179 // the path and extension.
2181 for (Cptr
= FileName
+ strlen (FileName
) - 1; (Cptr
> FileName
) && (*Cptr
!= '\\'); Cptr
--)
2183 if (*Cptr
== '\\') {
2187 strcpy (FilePath
, Cptr
);
2189 // We now have a file name with no path information. Before we do anything else,
2190 // see if OVERRIDE_PATH is set, and if so, see if file $(OVERRIDE_PATH)FileName
2191 // exists. If it does, then recursive call this function to use the override file
2192 // instead of the one from the INF file.
2194 if (IsAbsolutePath (FileName
)) {
2195 OverridePath
= NULL
;
2197 OverridePath
= GetSymbolValue (SOURCE_OVERRIDE_PATH
);
2199 if (OverridePath
!= NULL
) {
2201 // See if the file exists. If it does, reset the SOURCE_FILE_NAME symbol.
2203 strcpy (TempFileName
, OverridePath
);
2204 strcat (TempFileName
, "\\");
2205 strcat (TempFileName
, FileName
);
2206 if ((FPtr
= fopen (TempFileName
, "rb")) != NULL
) {
2208 AddSymbol (SOURCE_FILE_NAME
, TempFileName
, SYM_FILE
| SYM_OVERWRITE
);
2210 // Print a message. This function is called to create build commands
2211 // for source files, and to create a macro of all source files. Therefore
2212 // do this check so we don't print the override message multiple times.
2214 if (Mode
& SOURCE_MODE_BUILD_COMMANDS
) {
2215 fprintf (stdout
, "Override: %s\n", TempFileName
);
2219 // Set override path to null to use as a flag below
2221 OverridePath
= NULL
;
2226 // Start at the end and work back
2228 for (Cptr
= FilePath
+ strlen (FilePath
) - 1; (Cptr
> FilePath
) && (*Cptr
!= '\\') && (*Cptr
!= '.'); Cptr
--)
2232 AddSymbol (SOURCE_FILE_EXTENSION
, Cptr
+ 1, SYM_FILE
);
2235 AddSymbol (SOURCE_BASE_NAME
, FilePath
, SYM_FILE
);
2237 // If we're just creating the SOURCE_FILES macro, then write the
2238 // file name out to the makefile.
2240 if (Mode
& SOURCE_MODE_SOURCE_FILES
) {
2242 // If we're processing an override file, then use the file name as-is
2244 if (OverridePath
!= NULL
) {
2246 // SOURCE_FILES = $(SOURCE_FILES) c:\Path\ThisFile.c
2248 fprintf (MakeFptr
, "SOURCE_FILES = $(SOURCE_FILES) %s\n", TempFileName
);
2249 } else if (IsAbsolutePath (FileName
)) {
2251 // For Absolute path, don't print $(SOURCE_FILE) directory.
2253 fprintf (MakeFptr
, "SOURCE_FILES = $(SOURCE_FILES) %s\n", FileName
);
2256 // SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\ThisFile.c
2258 fprintf (MakeFptr
, "SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\\%s\n", FileName
);
2260 } else if (Mode
& SOURCE_MODE_BUILD_COMMANDS
) {
2262 // Write the build commands for this file per the build commands
2263 // for this file type as defined in the description file.
2264 // Also create the directory for it in the build path.
2266 WriteCompileCommands (DSCFile
, MakeFptr
, FileName
, Processor
);
2267 if (!IsAbsolutePath (FileName
)) {
2268 sprintf (Str
, "%s\\%s", GetSymbolValue (DEST_DIR
), FileName
);
2271 // Get all output directory for build output files.
2273 Cptr
= FileName
+ strlen (FileName
) - 1;
2274 for (; (Cptr
> FileName
) && (*Cptr
!= '\\'); Cptr
--);
2275 if (*Cptr
== '\\') {
2277 AddModuleName (&gGlobals
.OutdirList
, FileName
, NULL
);
2282 // Remove file-level symbols
2284 RemoveFileSymbols ();
2289 return STATUS_SUCCESS
;
2292 // Process the INF [sources.*] sections and emit the OBJECTS = .....
2293 // lines to the component's makefile.
2298 DSC_FILE
*ComponentFile
,
2302 INT8 Str
[MAX_LINE_LEN
];
2309 INT8
*CopySourceSelect
;
2313 // Write a useful comment to the output makefile so the user knows where
2314 // the data came from.
2316 fprintf (MakeFptr
, "#\n# Tool-generated list of object files that are created\n");
2317 fprintf (MakeFptr
, "# from the list of source files in the [sources.*] sections\n");
2318 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2320 // We use this a lot here, so get the value only once.
2322 Processor
= GetSymbolValue (PROCESSOR
);
2324 // Now define the OBJECTS variable and assign it to be all the object files we're going
2325 // to create. Afterwards create a pseudo-target objects to let the user quickly just compile
2326 // the source files. This means we need to process all the common objects and
2327 // processor-specific objects again.
2329 fprintf (MakeFptr
, "OBJECTS = $(OBJECTS) ");
2331 // See if they defined SOURCE_SELECT=xxx,yyy in which case well
2332 // select each [sources.xxx] and [sources.yyy] files and process
2335 SourceSelect
= GetSymbolValue (SOURCE_SELECT
);
2337 if (SourceSelect
!= NULL
) {
2339 // Make a copy of the string and break it up (comma-separated) and
2340 // select each [sources.*] file from the INF.
2342 CopySourceSelect
= (INT8
*) malloc (strlen (SourceSelect
) + 1);
2343 if (CopySourceSelect
== NULL
) {
2344 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2345 return STATUS_ERROR
;
2348 strcpy (CopySourceSelect
, SourceSelect
);
2349 CStart
= CopySourceSelect
;
2353 while (*CEnd
&& *CEnd
!= ',') {
2359 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, CStart
);
2360 ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
);
2362 // Restore the terminator and advance
2371 free (CopySourceSelect
);
2375 // Now process all the [sources.common] files and emit build commands for them
2377 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, COMMON_SECTION_NAME
);
2378 if (ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
) != STATUS_SUCCESS
) {
2379 Warning (GetSymbolValue (INF_FILENAME
), 1, 0, NULL
, "no [%s] section found in component description", Str
);
2382 // Now process any processor-specific source files in [sources.$(PROCESSOR)]
2384 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, Processor
);
2385 ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
);
2388 // Now process any [sources.$(PROCESSOR).$(PLATFORM)] files
2390 Platform
= GetSymbolValue (PLATFORM
);
2391 if (Platform
!= NULL
) {
2392 sprintf (Str
, "sources.%s.%s", Processor
, Platform
);
2393 ProcessObjectsSingle (ComponentFile
, MakeFptr
, Str
);
2397 fprintf (MakeFptr
, "\n\n");
2400 // Write a useful comment to the output makefile so the user knows where
2401 // the data came from.
2403 fprintf (MakeFptr
, "#\n# Tool-generated list of dest output dirs that are created\n");
2404 fprintf (MakeFptr
, "# from the list of source files in the [sources.*] sections\n");
2405 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2407 // Create output directory list
2408 // for clean target to delete all build output files.
2410 fprintf (MakeFptr
, "DEST_OUTPUT_DIRS = $(%s) ", DEST_DIR
);
2412 TempSymbol
= gGlobals
.OutdirList
;
2413 while (TempSymbol
!= NULL
) {
2414 fprintf (MakeFptr
, "\\\n $(%s)\\%s ",
2415 DEST_DIR
, TempSymbol
->Name
);
2416 TempSymbol
= TempSymbol
->Next
;
2418 fprintf (MakeFptr
, "\n\n");
2421 // clean up for the next module
2423 FreeSymbols (gGlobals
.OutdirList
);
2424 gGlobals
.OutdirList
= NULL
;
2426 return STATUS_SUCCESS
;
2431 BuiltFileExtension (
2432 INT8
*SourceFileName
2438 // Find the dot in the filename extension
2440 for (Cptr
= SourceFileName
+ strlen (SourceFileName
) - 1;
2441 (Cptr
> SourceFileName
) && (*Cptr
!= '\\') && (*Cptr
!= '.');
2453 // Look through our list of known file types and return a pointer to
2454 // its built file extension.
2456 for (i
= 0; mFileTypes
[i
].Extension
!= NULL
; i
++) {
2457 if (_stricmp (Cptr
, mFileTypes
[i
].Extension
) == 0) {
2458 return mFileTypes
[i
].BuiltExtension
;
2466 ProcessObjectsSingle (
2467 DSC_FILE
*ComponentFile
,
2474 INT8 Str
[MAX_LINE_LEN
];
2475 INT8 FileName
[MAX_EXP_LINE_LEN
];
2478 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2479 if (TempSect
!= NULL
) {
2480 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2481 Cptr
= StripLine (Str
);
2483 // Don't process blank lines
2487 // Expand symbols then create the output filename. We'll do a lookup
2488 // on the source file's extension to determine what the extension of
2489 // the built version of the file is. For example, .c -> .obj.
2491 if (!IsIncludeFile (Cptr
)) {
2492 ExpandSymbols (Cptr
, FileName
, sizeof (FileName
), 0);
2493 Cptr2
= BuiltFileExtension (FileName
);
2494 if (Cptr2
!= NULL
) {
2495 SetFileExtension (FileName
, Cptr2
);
2496 if (!IsAbsolutePath (FileName
)) {
2497 fprintf (MakeFptr
, "\\\n $(%s)\\%s ", DEST_DIR
, FileName
);
2499 fprintf (MakeFptr
, "\\\n %s ", FileName
);
2506 return STATUS_WARNING
;
2509 return STATUS_SUCCESS
;
2512 // Process all [libraries.*] sections in the component INF file to create a
2513 // macro to the component's output makefile: LIBS = Lib1 Lib2, ...
2518 DSC_FILE
*ComponentFile
,
2522 INT8 Str
[MAX_LINE_LEN
];
2527 // Print a useful comment to the component's makefile so the user knows
2528 // where the data came from.
2530 fprintf (MakeFptr
, "#\n# Tool-generated list of libraries that are generated\n");
2531 fprintf (MakeFptr
, "# from the list of libraries listed in the [libraries.*] sections\n");
2532 fprintf (MakeFptr
, "# of the component INF file.\n#\n");
2534 fprintf (MakeFptr
, "LIBS = $(LIBS) ");
2536 Processor
= GetSymbolValue (PROCESSOR
);
2538 // Process [libraries.common] files
2540 sprintf (Str
, "%s.%s", LIBRARIES_SECTION_NAME
, COMMON_SECTION_NAME
);
2541 ProcessLibsSingle (ComponentFile
, MakeFptr
, Str
);
2543 // Process the [libraries.$(PROCESSOR)] libraries to define "LIBS = x.lib y.lib..."
2545 sprintf (Str
, "%s.%s", LIBRARIES_SECTION_NAME
, Processor
);
2546 ProcessLibsSingle (ComponentFile
, MakeFptr
, Str
);
2548 // Now process any [libraries.$(PROCESSOR).$(PLATFORM)] files
2550 Platform
= GetSymbolValue (PLATFORM
);
2551 if (Platform
!= NULL
) {
2552 sprintf (Str
, "%s.%s.%s", LIBRARIES_SECTION_NAME
, Processor
, Platform
);
2553 ProcessLibsSingle (ComponentFile
, MakeFptr
, Str
);
2556 // Process any [libraries.platform] files
2558 ProcessLibsSingle (ComponentFile
, MakeFptr
, LIBRARIES_PLATFORM_SECTION_NAME
);
2560 fprintf (MakeFptr
, "\n\n");
2561 return STATUS_SUCCESS
;
2567 DSC_FILE
*ComponentFile
,
2573 INT8 Str
[MAX_LINE_LEN
];
2574 INT8 ExpandedLine
[MAX_LINE_LEN
];
2577 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2578 if (TempSect
!= NULL
) {
2579 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2580 ExpandSymbols (Str
, ExpandedLine
, sizeof (ExpandedLine
), 0);
2581 Cptr
= StripLine (ExpandedLine
);
2583 // Don't process blank lines
2586 if (Cptr
[strlen (Cptr
) - 4] != '.') {
2587 fprintf (MakeFptr
, " \\\n $(LIB_DIR)\\%s.lib", Cptr
);
2589 // Add lib dependency for single module build
2591 fprintf (gGlobals
.ModuleMakefileFptr
, " %sbuild", Cptr
);
2593 fprintf (MakeFptr
, " \\\n $(LIB_DIR)\\%s", Cptr
);
2595 // Add lib dependency for single module build
2597 Cptr
[strlen (Cptr
) - 4] = 0;
2598 fprintf (gGlobals
.ModuleMakefileFptr
, " %sbuild", Cptr
);
2604 return STATUS_SUCCESS
;
2609 ProcessIncludeFiles (
2610 DSC_FILE
*ComponentFile
,
2614 INT8 Str
[MAX_LINE_LEN
];
2621 INT8
*CopySourceSelect
;
2624 // Print a useful comment to the output makefile so the user knows where
2625 // the info came from
2627 //fprintf (MakeFptr, "#\n# Tool-generated include dependencies from any include files in the\n");
2628 //fprintf (MakeFptr, "# [sources.*] sections of the component INF file\n#\n");
2630 Processor
= GetSymbolValue (PROCESSOR
);
2633 // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll
2634 // select each [sources.xxx] and [sources.yyy] files and process
2637 SourceSelect
= GetSymbolValue (SOURCE_SELECT
);
2639 if (SourceSelect
!= NULL
) {
2641 // Make a copy of the string and break it up (comma-separated) and
2642 // select each [sources.*] file from the INF.
2644 CopySourceSelect
= (INT8
*) malloc (strlen (SourceSelect
) + 1);
2645 if (CopySourceSelect
== NULL
) {
2646 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2647 return STATUS_ERROR
;
2650 strcpy (CopySourceSelect
, SourceSelect
);
2651 CStart
= CopySourceSelect
;
2655 while (*CEnd
&& *CEnd
!= ',') {
2661 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, CStart
);
2662 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2664 // Restore the terminator and advance
2673 free (CopySourceSelect
);
2677 // Find all the include files in the [sources.common] sections.
2679 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, COMMON_SECTION_NAME
);
2680 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2682 // Now process the [sources.$(PROCESSOR)] files.
2684 sprintf (Str
, "%s.%s", SOURCES_SECTION_NAME
, Processor
);
2685 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2687 // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files.
2689 Platform
= GetSymbolValue (PLATFORM
);
2690 if (Platform
!= NULL
) {
2691 sprintf (Str
, "sources.%s.%s", Processor
, Platform
);
2692 ProcessIncludeFilesSingle (ComponentFile
, MakeFptr
, Str
);
2696 fprintf (MakeFptr
, "\n");
2697 return STATUS_SUCCESS
;
2701 ProcessIncludeFilesSingle (
2702 DSC_FILE
*ComponentFile
,
2708 INT8 FileName
[MAX_EXP_LINE_LEN
];
2709 INT8 TempFileName
[MAX_PATH
];
2711 INT8 Str
[MAX_LINE_LEN
];
2715 TempSect
= DSCFileFindSection (ComponentFile
, SectionName
);
2716 if (TempSect
!= NULL
) {
2718 // See if the SOURCE_OVERRIDE_PATH has been set. If it has, and
2719 // they have an include file that is overridden, then add the path
2720 // to it to the list of include paths (prepend).
2722 OverridePath
= GetSymbolValue (SOURCE_OVERRIDE_PATH
);
2723 while (DSCFileGetLine (ComponentFile
, Str
, sizeof (Str
)) != NULL
) {
2724 Cptr
= StripLine (Str
);
2726 // Don't process blank lines
2730 // Expand symbols in the filename, then get its parts
2732 ExpandSymbols (Cptr
, FileName
, sizeof (FileName
), 0);
2733 AddFileSymbols (FileName
);
2734 if (IsIncludeFile (FileName
)) {
2735 if ((OverridePath
!= NULL
) && (!IsAbsolutePath (FileName
))) {
2736 strcpy (TempFileName
, OverridePath
);
2737 strcat (TempFileName
, "\\");
2738 strcat (TempFileName
, FileName
);
2739 if ((FPtr
= fopen (TempFileName
, "rb")) != NULL
) {
2742 // Null-terminate the file name at the last backslash and add that
2743 // to the beginning of the list of include paths.
2745 for (Cptr
= TempFileName
+ strlen (TempFileName
) - 1;
2746 (Cptr
>= TempFileName
) && (*Cptr
!= '\\') && (*Cptr
!= '/');
2750 if (Cptr
>= TempFileName
) {
2754 fprintf (MakeFptr
, "INC = -I %s $(INC)\n", TempFileName
);
2758 // If absolute path already, don't prepend source directory
2760 // if (IsAbsolutePath (FileName)) {
2761 // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) %s\n", FileName);
2763 // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) $(SOURCE_DIR)\\%s\n", FileName);
2767 RemoveFileSymbols ();
2772 return STATUS_SUCCESS
;
2782 if (FP
->Path
!= NULL
) {
2786 if (FP
->BaseName
!= NULL
) {
2787 free (FP
->BaseName
);
2790 if (FP
->Extension
!= NULL
) {
2791 free (FP
->Extension
);
2802 FILE_NAME_PARTS
*FP
;
2804 INT8 CopyFileName
[MAX_PATH
];
2807 strcpy (CopyFileName
, FileName
);
2808 FP
= (FILE_NAME_PARTS
*) malloc (sizeof (FILE_NAME_PARTS
));
2810 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
2814 memset ((INT8
*) FP
, 0, sizeof (FILE_NAME_PARTS
));
2816 // Get extension code
2818 FP
->ExtensionCode
= GetSourceFileType (CopyFileName
);
2820 // Get drive if there
2822 FileNamePtr
= CopyFileName
;
2823 if (FileNamePtr
[1] == ':') {
2824 FP
->Drive
[0] = FileNamePtr
[0];
2829 // Start at the end and work back
2831 for (Cptr
= FileNamePtr
+ strlen (FileNamePtr
) - 1; (Cptr
> FileNamePtr
) && (*Cptr
!= '.'); Cptr
--)
2836 // Don't copy the dot
2838 FP
->Extension
= (char *) malloc (strlen (Cptr
));
2839 strcpy (FP
->Extension
, Cptr
+ 1);
2842 StripTrailingSpaces (FP
->Extension
);
2845 // Create empty string for extension
2847 FP
->Extension
= (char *) malloc (1);
2848 FP
->Extension
[0] = 0;
2851 // Now back up and get the base name (include the preceding '\' or '/')
2853 for (; (Cptr
> FileNamePtr
) && (*Cptr
!= '\\') && (*Cptr
!= '/'); Cptr
--)
2855 FP
->BaseName
= (char *) malloc (strlen (Cptr
) + 1);
2856 strcpy (FP
->BaseName
, Cptr
);
2862 if (Cptr
>= FileNamePtr
) {
2864 FP
->Path
= (char *) malloc (strlen (Cptr
) + 1);
2865 strcpy (FP
->Path
, Cptr
);
2867 FP
->Path
= (char *) malloc (1);
2874 /*****************************************************************************
2875 ******************************************************************************/
2878 WriteCommonMakefile (
2884 INT8 InLine
[MAX_LINE_LEN
];
2885 INT8 OutLine
[MAX_EXP_LINE_LEN
];
2890 // Don't mess up the original file pointer, since we're processing it at a higher
2893 DSCFileSavePosition (DSCFile
);
2895 // Write the header to the file
2897 for (i
= 0; MakefileHeader
[i
] != NULL
; i
++) {
2898 fprintf (MakeFptr
, "%s\n", MakefileHeader
[i
]);
2901 fprintf (MakeFptr
, "#\n# Hard-coded defines output by the tool\n#\n");
2903 // First write the basics to the component's makefile. These includes
2904 // EFI_SOURCE, BIN_DIR, OUT_DIR, LIB_DIR, SOURCE_DIR, DEST_DIR.
2906 Sym
= GetSymbolValue (EFI_SOURCE
);
2907 fprintf (MakeFptr
, "%s = %s\n", EFI_SOURCE
, Sym
);
2908 Sym
= GetSymbolValue (BUILD_DIR
);
2909 fprintf (MakeFptr
, "%s = %s\n", BUILD_DIR
, Sym
);
2910 Sym
= GetSymbolValue (BIN_DIR
);
2911 fprintf (MakeFptr
, "%s = %s\n", BIN_DIR
, Sym
);
2912 Sym
= GetSymbolValue (OUT_DIR
);
2913 fprintf (MakeFptr
, "%s = %s\n", OUT_DIR
, Sym
);
2914 Sym
= GetSymbolValue (LIB_DIR
);
2915 fprintf (MakeFptr
, "%s = %s\n", LIB_DIR
, Sym
);
2916 Sym
= GetSymbolValue (SOURCE_DIR
);
2917 fprintf (MakeFptr
, "%s = %s\n", SOURCE_DIR
, Sym
);
2918 Sym
= GetSymbolValue (DEST_DIR
);
2919 fprintf (MakeFptr
, "%s = %s\n", DEST_DIR
, Sym
);
2920 fprintf (MakeFptr
, "\n");
2922 // If there was a [makefile.common] section in the description file,
2923 // copy it (after symbol expansion) to the output file.
2925 sprintf (InLine
, "%s.%s", MAKEFILE_SECTION_NAME
, COMMON_SECTION_NAME
);
2926 Sect
= DSCFileFindSection (DSCFile
, InLine
);
2929 // fprintf (MakeFptr, "# From the [makefile.common] section of the DSC file\n");
2930 // Read lines, expand, then dump out
2932 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
2936 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
2937 fprintf (MakeFptr
, OutLine
);
2941 // If there was a [makefile.platform] section in the description file,
2942 // copy it (after symbol expansion) to the output file.
2944 sprintf (InLine
, "%s.%s", MAKEFILE_SECTION_NAME
, "Platform");
2945 Sect
= DSCFileFindSection (DSCFile
, InLine
);
2948 // Read lines, expand, then dump out
2950 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
2954 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
2955 fprintf (MakeFptr
, OutLine
);
2959 // Do the same for any [makefile.$(PROCESSOR)]
2961 sprintf (InLine
, "%s.%s", MAKEFILE_SECTION_NAME
, Processor
);
2962 Sect
= DSCFileFindSection (DSCFile
, InLine
);
2965 // Read lines, expand, then dump out
2967 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
2968 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
2969 fprintf (MakeFptr
, OutLine
);
2973 // Same thing for [makefile.$(PROCESSOR).$(PLATFORM)]
2975 Sym
= GetSymbolValue (PLATFORM
);
2977 sprintf (InLine
, "%s.%s.%s", MAKEFILE_SECTION_NAME
, Processor
, Sym
);
2978 Sect
= DSCFileFindSection (DSCFile
, InLine
);
2981 // Read lines, expand, then dump out
2983 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
2984 ExpandSymbols (InLine
, OutLine
, sizeof (OutLine
), EXPANDMODE_RECURSIVE
);
2985 fprintf (MakeFptr
, OutLine
);
2990 fprintf (MakeFptr
, "\n");
2991 DSCFileRestorePosition (DSCFile
);
2997 WriteComponentTypeBuildCommands (
3004 Routine Description:
3006 Given a section name such as [build.ia32.library], find the section in
3007 the description file and copy the build commands.
3011 DSCFile - section information on the main description file
3012 MakeFptr - file pointer to the makefile we're writing to
3013 SectionName - name of the section we're to copy out to the makefile.
3017 Always successful, since the section may be optional.
3022 INT8 InLine
[MAX_LINE_LEN
];
3023 INT8 OutLine
[MAX_EXP_LINE_LEN
];
3026 // Don't mess up the original file pointer, since we're processing it at a higher
3029 DSCFileSavePosition (DSCFile
);
3030 Sect
= DSCFileFindSection (DSCFile
, SectionName
);
3033 // Read lines, expand, then dump out
3035 while (DSCFileGetLine (DSCFile
, InLine
, sizeof (InLine
)) != NULL
) {
3040 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
3042 fprintf (MakeFptr
, OutLine
);
3049 GetSymbolValue (INF_FILENAME
),
3050 "no [%s] build commands found in DSC file for component",
3055 DSCFileRestorePosition (DSCFile
);
3056 return STATUS_SUCCESS
;
3059 /*****************************************************************************
3061 ******************************************************************************/
3064 WriteCompileCommands (
3071 FILE_NAME_PARTS
*File
;
3073 INT8 BuildSectionName
[40];
3074 INT8 InLine
[MAX_LINE_LEN
];
3075 INT8 OutLine
[MAX_EXP_LINE_LEN
];
3076 INT8
*SourceCompileType
;
3080 // Determine the filename, then chop it up into its parts
3082 File
= GetFileParts (FileName
);
3085 // Don't mess up the original file pointer, since we're processing it at a higher
3088 DSCFileSavePosition (DscFile
);
3090 // Option 1: SOURCE_COMPILE_TYPE=MyCompileSection
3091 // Find a section of that name from which to get the compile
3092 // commands for this source file.
3093 // Look for [compile.$(PROCESSOR).$(SOURCE_COMPILE_TYPE]
3094 // Option 2: COMPILE_SELECT=.c=MyCCompile,.asm=MyAsm
3095 // Find a [compile.$(PROCESSOR).MyCompile] section from which to
3096 // get the compile commands for this source file.
3097 // Look for [compile.$(PROCESSOR).MyCompile]
3098 // Option 3: Look for standard section types to compile the file by extension.
3099 // Look for [compile.$(PROCESSOR).<extension>]
3103 // Option 1 - use SOURCE_COMPILE_TYPE variable
3105 SourceCompileType
= GetSymbolValue (SOURCE_COMPILE_TYPE
);
3106 if (SourceCompileType
!= NULL
) {
3107 sprintf (BuildSectionName
, "compile.%s.%s", Processor
, SourceCompileType
);
3108 Sect
= DSCFileFindSection (DscFile
, BuildSectionName
);
3111 // Option 2 - use COMPILE_SELECT variable
3114 SourceCompileType
= GetSymbolValue (COMPILE_SELECT
);
3115 if (SourceCompileType
!= NULL
) {
3117 // Parse the variable, which looks like COMPILE_SELECT=.c=MyCCompiler;.asm=MyAsm;
3118 // to find an entry with a matching file name extension. If you find one,
3119 // then use that name to find the section name.
3121 CPtr
= SourceCompileType
;
3122 while (*CPtr
&& (Sect
== NULL
)) {
3124 // See if we found a match with this source file name extension. File->Extension
3125 // does not include the dot, so skip the dot in the COMPILE_SELECT variable if there
3132 if (_strnicmp (CPtr
, File
->Extension
, strlen (File
->Extension
)) == 0) {
3134 // Found a file name extension match -- extract the name from the variable, for
3135 // example "MyCCompiler"
3137 while (*CPtr
&& (*CPtr
!= '=')) {
3141 if ((*CPtr
!= '=') || (CPtr
[1] == 0)) {
3142 Error (NULL
, 0, 0, SourceCompileType
, "malformed COMPILE_SELECT variable");
3147 sprintf (BuildSectionName
, "compile.%s.", Processor
);
3148 for (CPtr2
= BuildSectionName
+ strlen (BuildSectionName
);
3149 *CPtr
&& (*CPtr
!= ',') && (*CPtr
!= ';');
3157 Sect
= DSCFileFindSection (DscFile
, BuildSectionName
);
3162 "could not find section in DSC file - selected by COMPILE_SELECT variable"
3168 // Skip to next file name extension in the COMPILE_SELECT variable
3170 while (*CPtr
&& (*CPtr
!= ';') && (*CPtr
!= ',')) {
3181 // Option 3 - use "Compile.$(PROCESSOR).<Extension>" section
3184 sprintf (BuildSectionName
, "compile.%s.%s", Processor
, File
->Extension
);
3185 Sect
= DSCFileFindSection (DscFile
, BuildSectionName
);
3188 // Should have found something by now unless it's an include (.h) file
3192 // Temporarily add a FILE variable to the global symbol table. Omit the
3195 sprintf (InLine
, "%s%s%s", File
->Drive
, File
->Path
, File
->BaseName
);
3196 AddSymbol ("FILE", InLine
, SYM_OVERWRITE
| SYM_LOCAL
| SYM_FILENAME
);
3198 // Read lines, expand (except SOURCE_DIR and DEST_DIR), then dump out
3200 while (DSCFileGetLine (DscFile
, InLine
, sizeof (InLine
)) != NULL
) {
3205 EXPANDMODE_NO_DESTDIR
| EXPANDMODE_NO_SOURCEDIR
3207 fprintf (MakeFptr
, OutLine
);
3209 fprintf (MakeFptr
, "\n");
3212 // Be nice and ignore include files
3214 if (!IsIncludeFile (FileName
)) {
3220 "no compile commands section [%s] found in DSC file for %s",
3227 DSCFileRestorePosition (DscFile
);
3228 FreeFileParts (File
);
3231 return STATUS_SUCCESS
;
3234 /*****************************************************************************
3235 ******************************************************************************/
3245 Cptr
= FileName
+ strlen (FileName
) - 1;
3246 while ((Cptr
> FileName
) && (*Cptr
!= '.')) {
3254 Message (2, "Missing filename extension: %s", FileName
);
3255 return STATUS_WARNING
;
3259 if (*Extension
== '.') {
3263 strcpy (Cptr
, Extension
);
3264 return STATUS_SUCCESS
;
3267 /*****************************************************************************
3268 ******************************************************************************/
3276 INT8 BuildDir
[MAX_PATH
];
3277 INT8 CopyFileName
[MAX_PATH
];
3280 // Expand symbols in the filename
3282 if (ExpandSymbols (FileName
, CopyFileName
, sizeof (CopyFileName
), EXPANDMODE_NO_UNDEFS
)) {
3283 Error (NULL
, 0, 0, NULL
, "undefined symbols in file path: %s", FileName
);
3284 return STATUS_ERROR
;
3289 strcpy (FileName
, CopyFileName
);
3291 // To avoid creating $(BUILD_DIR) path, see if this path is the same as
3292 // $(BUILD_DIR), and if it is, see if build dir exists and skip over that
3293 // portion if it does
3295 Cptr
= GetSymbolValue (BUILD_DIR
);
3297 if (_strnicmp (Cptr
, FileName
, strlen (Cptr
)) == 0) {
3299 // BUILD_DIR path. See if it exists
3301 strcpy (BuildDir
, FileName
);
3302 BuildDir
[strlen (Cptr
)] = 0;
3303 if ((_mkdir (BuildDir
) != 0) && (errno
!= EEXIST
)) {
3307 // Already done. Shortcut. Skip to next path so that we don't create
3308 // the BUILD_DIR as well.
3310 Cptr
= FileName
+ strlen (Cptr
);
3311 if (*Cptr
== '\\') {
3325 // Create directories until done. Skip over "c:\" in the path if it exists
3327 if (*Cptr
&& (*(Cptr
+ 1) == ':') && (*(Cptr
+ 2) == '\\')) {
3332 for (; *Cptr
&& (*Cptr
!= '/') && (*Cptr
!= '\\'); Cptr
++)
3337 if ((_mkdir (FileName
) != 0)) {
3339 // Error (NULL, 0, 0, FileName, "failed to create directory");
3351 return STATUS_SUCCESS
;
3354 /*****************************************************************************
3355 ******************************************************************************/
3364 static int NestDepth
= 0;
3372 INT8
*LocalDestLine
;
3377 Status
= STATUS_SUCCESS
;
3378 LocalDestLine
= (INT8
*) malloc (LineLen
);
3379 if (LocalDestLine
== NULL
) {
3380 Error (__FILE__
, __LINE__
, 0, "application error", "memory allocation failed");
3382 return STATUS_ERROR
;
3385 FromPtr
= SourceLine
;
3386 ToPtr
= LocalDestLine
;
3388 // Walk the entire line, replacing $(SYMBOL_NAME).
3390 LocalLineLen
= LineLen
;
3392 while (*FromPtr
&& (LocalLineLen
> 0)) {
3393 if ((*FromPtr
== '$') && (*(FromPtr
+ 1) == '(')) {
3395 // Save the start in case it's undefined, in which case we copy it as-is.
3397 SaveStart
= FromPtr
;
3400 // Symbol expansion time. Find the end (no spaces allowed)
3403 for (Cptr
= FromPtr
; *Cptr
&& (*Cptr
!= ')'); Cptr
++)
3407 // Truncate the string at the closing parenthesis for ease-of-use.
3408 // Then copy the string directly to the destination line in case we don't find
3409 // a definition for it.
3412 strcpy (ToPtr
, SaveStart
);
3413 if ((_stricmp (SOURCE_DIR
, FromPtr
) == 0) && (ExpandMode
& EXPANDMODE_NO_SOURCEDIR
)) {
3415 // excluded this expansion
3417 } else if ((_stricmp (DEST_DIR
, FromPtr
) == 0) && (ExpandMode
& EXPANDMODE_NO_DESTDIR
)) {
3419 // excluded this expansion
3421 } else if ((value
= GetSymbolValue (FromPtr
)) != NULL
) {
3422 strcpy (ToPtr
, value
);
3423 LocalLineLen
-= strlen (value
);
3424 ToPtr
+= strlen (value
);
3427 } else if (ExpandMode
& EXPANDMODE_NO_UNDEFS
) {
3428 Error (NULL
, 0, 0, "undefined symbol", "$(%s)", FromPtr
);
3429 Status
= STATUS_ERROR
;
3434 // Restore closing parenthesis, and advance to next character
3438 FromPtr
= SaveStart
+ 1;
3444 Error (NULL
, 0, 0, SourceLine
, "missing closing parenthesis on symbol");
3445 strcpy (ToPtr
, FromPtr
);
3446 Status
= STATUS_WARNING
;
3457 if (*FromPtr
== 0) {
3462 // If we're in recursive mode, and we expanded at least one string successfully,
3463 // then make a recursive call to try again.
3465 if ((ExpandedCount
!= 0) && (Status
== STATUS_SUCCESS
) && (ExpandMode
& EXPANDMODE_RECURSIVE
) && (NestDepth
< 2)) {
3466 Status
= ExpandSymbols (LocalDestLine
, DestLine
, LineLen
, ExpandMode
);
3467 free (LocalDestLine
);
3473 if (Status
!= STATUS_ERROR
) {
3474 strcpy (DestLine
, LocalDestLine
);
3478 free (LocalDestLine
);
3488 Routine Description:
3490 Look up a symbol in our symbol table.
3494 SymbolName - The name of symbol.
3498 Pointer to the value of the symbol if found
3499 NULL if the symbol is not found
3506 // Scan once for file-level symbols
3508 Symbol
= gGlobals
.Symbol
;
3510 if ((_stricmp (SymbolName
, Symbol
->Name
) == 0) && (Symbol
->Type
& SYM_FILE
)) {
3511 return Symbol
->Value
;
3514 Symbol
= Symbol
->Next
;
3517 // Scan once for local symbols
3519 Symbol
= gGlobals
.Symbol
;
3521 if ((_stricmp (SymbolName
, Symbol
->Name
) == 0) && (Symbol
->Type
& SYM_LOCAL
)) {
3522 return Symbol
->Value
;
3525 Symbol
= Symbol
->Next
;
3528 // No local value found. Scan for globals.
3530 Symbol
= gGlobals
.Symbol
;
3532 if ((_stricmp (SymbolName
, Symbol
->Name
) == 0) && (Symbol
->Type
& SYM_GLOBAL
)) {
3533 return Symbol
->Value
;
3536 Symbol
= Symbol
->Next
;
3539 // For backwards-compatibility, if it's "GUID", return FILE_GUID value
3541 if (_stricmp (SymbolName
, GUID
) == 0) {
3542 return GetSymbolValue (FILE_GUID
);
3550 RemoveLocalSymbols (
3555 Routine Description:
3557 Remove all local symbols from the symbol table. Local symbols are those
3558 that are defined typically by the component's INF file.
3566 Right now, never fails.
3575 Sym
= gGlobals
.Symbol
;
3577 if (Sym
->Type
& SYM_LOCAL
) {
3579 // Going to delete it out from under ourselves, so break and restart
3582 RemoveSymbol (Sym
->Name
, SYM_LOCAL
);
3589 return STATUS_SUCCESS
;
3599 Routine Description:
3601 Remove all file-level symbols from the symbol table. File-level symbols are
3602 those that are defined on a source file line in an INF file.
3610 Right now, never fails.
3619 Sym
= gGlobals
.Symbol
;
3621 if (Sym
->Type
& SYM_FILE
) {
3623 // Going to delete it out from under ourselves, so break and restart
3626 RemoveSymbol (Sym
->Name
, SYM_FILE
);
3633 return STATUS_SUCCESS
;
3638 ParseGuidDatabaseFile (
3643 Routine Description:
3644 This function parses a GUID-to-basename text file (perhaps output by
3645 the GuidChk utility) to define additional symbols. The format of the
3648 7BB28B99-61BB-11D5-9A5D-0090273FC14D EFI_DEFAULT_BMP_LOGO_GUID gEfiDefaultBmpLogoGuid
3650 This function parses the line and defines global symbol:
3652 EFI_DEFAULT_BMP_LOGO_GUID=7BB28B99-61BB-11D5-9A5D-0090273FC14D
3654 This symbol (rather than the actual GUID) can then be used in INF files to
3658 FileName - the name of the file to parse.
3661 STATUS_ERROR - could not open FileName
3662 STATUS_SUCCESS - we opened the file
3669 INT8 DefineName
[80];
3671 Fptr
= fopen (FileName
, "r");
3673 Error (NULL
, 0, 0, FileName
, "failed to open input GUID database input file");
3674 return STATUS_ERROR
;
3677 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
3679 // Get the GUID string, skip the defined name (EFI_XXX_GUID), and get the
3680 // variable name (gWhateverProtocolGuid)
3682 if (sscanf (Line
, "%s %s %*s", Guid
, DefineName
) == 2) {
3683 AddSymbol (DefineName
, Guid
, SYM_GLOBAL
);
3688 return STATUS_SUCCESS
;
3691 /*****************************************************************************
3694 0 if successful standard add
3695 length of the parsed string if passed in " name = value "
3698 ******************************************************************************/
3715 INT8 ShortName
[MAX_PATH
];
3725 // Mode better be local or global symbol
3727 if ((Mode
& (SYM_LOCAL
| SYM_GLOBAL
| SYM_FILE
)) == 0) {
3728 Error (NULL
, 0, 0, "APP ERROR", "adding symbol '%s' that is not local, global, nor file level", Name
);
3732 // If value pointer is null, then they passed us a line something like:
3733 // varname = value, or simply var =
3735 if (Value
== NULL
) {
3737 while (*Name
&& isspace (*Name
)) {
3746 // Find the end of the name. Either space or a '='.
3748 for (Value
= Name
; *Value
&& !isspace (*Value
) && (*Value
!= '='); Value
++)
3757 while (*Value
&& (*Value
!= '=')) {
3766 // Now truncate the name
3773 // Skip over the = and then any spaces
3776 while (*Value
&& isspace (*Value
)) {
3781 // Find end of string, checking for quoted string
3783 if (*Value
== '\"') {
3785 for (Cptr
= Value
; *Cptr
&& *Cptr
!= '\"'; Cptr
++)
3788 for (Cptr
= Value
; *Cptr
&& !isspace (*Cptr
); Cptr
++)
3792 // Null terminate the value string
3795 Len
= (int) (Cptr
- Start
) + 1;
3800 Len
= (int) (Cptr
- Start
);
3805 // If file name or file path, and we're shortening, then print it
3807 if ((Mode
& (SYM_FILEPATH
| SYM_FILENAME
)) && (GetSymbolValue (SHORT_NAMES
) != NULL
)) {
3808 if (GetShortPathName (Value
, ShortName
, sizeof (ShortName
)) > 0) {
3810 // fprintf (stdout, "String value '%s' shortened to '%s'\n",
3811 // Value, ShortName);
3816 // fprintf (stdout, "WARNING: Failed to get short name for %s\n", Value);
3821 // We now have a symbol name and a value. Look for an existing variable of
3822 // the same type (global or local) and overwrite it.
3824 Symbol
= gGlobals
.Symbol
;
3827 // Check for symbol name match
3829 if (_stricmp (Name
, Symbol
->Name
) == 0) {
3831 // See if this symbol is of the same type (global or local) as what
3832 // they're requesting
3834 if ((Symbol
->Type
& (SYM_LOCAL
| SYM_GLOBAL
)) == (Mode
& (SYM_LOCAL
| SYM_GLOBAL
))) {
3836 // Did they say we could overwrite it?
3838 if (Mode
& SYM_OVERWRITE
) {
3839 free (Symbol
->Value
);
3840 Symbol
->Value
= (INT8
*) malloc (strlen (Value
) + 1);
3841 if (Symbol
->Value
== NULL
) {
3842 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
3846 strcpy (Symbol
->Value
, Value
);
3848 // If value == "NULL", then make it a 0-length string
3850 if (_stricmp (Symbol
->Value
, "NULL") == 0) {
3851 Symbol
->Value
[0] = 0;
3856 return STATUS_ERROR
;
3861 Symbol
= Symbol
->Next
;
3864 // Does not exist, create a new one
3866 NewSymbol
= (SYMBOL
*) malloc (sizeof (SYMBOL
));
3867 if (NewSymbol
== NULL
) {
3868 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
3872 memset ((INT8
*) NewSymbol
, 0, sizeof (SYMBOL
));
3873 NewSymbol
->Name
= (INT8
*) malloc (strlen (Name
) + 1);
3874 NewSymbol
->Value
= (INT8
*) malloc (strlen (Value
) + 1);
3876 // Simply use the mode bits as the type.
3878 NewSymbol
->Type
= Mode
;
3879 if ((NewSymbol
->Name
== NULL
) || (NewSymbol
->Value
== NULL
)) {
3880 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
3884 strcpy (NewSymbol
->Name
, Name
);
3885 strcpy (NewSymbol
->Value
, Value
);
3887 // Remove trailing spaces
3889 Cptr
= NewSymbol
->Value
+ strlen (NewSymbol
->Value
) - 1;
3890 while (Cptr
> NewSymbol
->Value
) {
3891 if (isspace (*Cptr
)) {
3899 // Add it to the head of the list.
3901 NewSymbol
->Next
= gGlobals
.Symbol
;
3902 gGlobals
.Symbol
= NewSymbol
;
3904 // If value == "NULL", then make it a 0-length string
3906 if (_stricmp (NewSymbol
->Value
, "NULL") == 0) {
3907 NewSymbol
->Value
[0] = 0;
3910 // Restore the terminator we inserted if they passed in var=value
3912 if (SaveCptr1
!= NULL
) {
3913 *SaveCptr1
= CSave1
;
3915 if (SaveCptr2
!= NULL
) {
3916 *SaveCptr2
= CSave2
;
3922 /*****************************************************************************
3923 ******************************************************************************/
3935 Symbol
= gGlobals
.Symbol
;
3937 if ((_stricmp (Name
, Symbol
->Name
) == 0) && (Symbol
->Type
& SymbolType
)) {
3938 if (Symbol
->Value
) {
3939 free (Symbol
->Value
);
3942 free (Symbol
->Name
);
3944 PrevSymbol
->Next
= Symbol
->Next
;
3946 gGlobals
.Symbol
= Symbol
->Next
;
3950 return STATUS_SUCCESS
;
3953 PrevSymbol
= Symbol
;
3954 Symbol
= Symbol
->Next
;
3957 return STATUS_WARNING
;
3962 /*****************************************************************************
3963 ******************************************************************************/
3972 while (Sect
!= NULL
) {
3974 if (Sect
->Name
!= NULL
) {
3975 delete[] Sect
->Name
;
3984 /*****************************************************************************
3985 ******************************************************************************/
3997 // Look for '#' comments in first character of line
4004 while (isspace (*Cptr
)) {
4008 // Hack off newlines
4010 Len
= strlen (Cptr
);
4011 if ((Len
> 0) && (Cptr
[Len
- 1] == '\n')) {
4015 // Hack off trailing spaces
4017 StripTrailingSpaces (Cptr
);
4021 /*****************************************************************************
4022 FUNCTION: ProcessOptions()
4024 DESCRIPTION: Process the command-line options.
4025 ******************************************************************************/
4034 Routine Description:
4036 Process the command line options to this utility.
4040 Argc - Standard Argc.
4041 Argv[] - Standard Argv.
4051 // Clear out the options
4053 memset ((INT8
*) &gGlobals
, 0, sizeof (gGlobals
));
4060 return STATUS_ERROR
;
4063 // Now process the arguments
4067 if ((Argv
[0][0] == '-') || (Argv
[0][0] == '/')) {
4068 switch (Argv
[0][1]) {
4070 // -? or -h help option
4076 return STATUS_ERROR
;
4090 Error (NULL
, 0, 0, NULL
, "missing symbol definition with %c%c", Argv
[0][0], Argv
[0][1]);
4091 return STATUS_ERROR
;
4093 if (AddSymbol (Argv
[0], NULL
, SYM_OVERWRITE
| SYM_GLOBAL
) <= 0) {
4094 Warning (NULL
, 0, 0, Argv
[0], "failed to add symbol: %s");
4100 // output makefile name
4111 Error (NULL
, 0, 0, Argv
[0], "missing output makefile name with option");
4113 return STATUS_ERROR
;
4115 strcpy (gGlobals
.MakefileName
, Argv
[0]);
4120 // Print a cross-reference file containing guid/basename/processor
4131 Error (NULL
, 0, 0, Argv
[0], "missing cross-reference output filename with option");
4133 return STATUS_ERROR
;
4135 strcpy (gGlobals
.XRefFileName
, Argv
[0]);
4140 // GUID database file to preparse
4151 Error (NULL
, 0, 0, Argv
[0], "missing input GUID database filename with option");
4153 return STATUS_ERROR
;
4155 strcpy (gGlobals
.GuidDatabaseFileName
, Argv
[0]);
4161 gGlobals
.Verbose
= 1;
4165 Error (NULL
, 0, 0, Argv
[0], "unrecognized option");
4166 return STATUS_ERROR
;
4176 // Must be at least one arg left
4179 gGlobals
.DscFilename
= Argv
[0];
4182 if (gGlobals
.DscFilename
== NULL
) {
4183 Error (NULL
, 0, 0, NULL
, "must specify DSC filename on command line");
4184 return STATUS_ERROR
;
4187 // Make a global symbol for the DSC filename
4189 AddSymbol (DSC_FILENAME
, gGlobals
.DscFilename
, SYM_GLOBAL
| SYM_FILENAME
);
4191 // If no output makefile specified, take the default
4193 if (gGlobals
.MakefileName
[0] == 0) {
4194 strcpy (gGlobals
.MakefileName
, MAKEFILE_OUT_NAME
);
4197 // Get the current working directory and use it for the build directory.
4198 // Only do this if they have not defined it on the command line. Do the
4199 // same for the bin dir, output dir, and library directory.
4201 Cptr
= GetSymbolValue (BUILD_DIR
);
4203 Cptr
= _getcwd (NULL
, 0);
4205 AddSymbol (BUILD_DIR
, Cptr
, SYM_OVERWRITE
| SYM_GLOBAL
| SYM_FILEPATH
);
4217 /*****************************************************************************
4218 ******************************************************************************/
4228 if (Syms
->Name
!= NULL
) {
4232 if (Syms
->Value
!= NULL
) {
4244 /*****************************************************************************
4245 ******************************************************************************/
4256 len
= strlen (FileName
);
4258 return FILETYPE_UNKNOWN
;
4262 Cptr
= FileName
+ len
- 1;
4263 while ((*Cptr
!= '.') && (Cptr
>= FileName
)) {
4270 for (i
= 0; mFileTypes
[i
].Extension
!= NULL
; i
++) {
4271 len
= strlen (mFileTypes
[i
].Extension
);
4272 if (_strnicmp (mFileTypes
[i
].Extension
, Cptr
, len
) == 0) {
4273 if ((*(Cptr
+ len
) == 0) || isspace (*(Cptr
+ len
))) {
4274 return mFileTypes
[i
].FileType
;
4280 return FILETYPE_UNKNOWN
;
4283 // Determine if a given file is a standard include file. If we don't know,
4284 // then assume it's not.
4296 len
= strlen (FileName
);
4301 Cptr
= FileName
+ len
- 1;
4302 while ((*Cptr
!= '.') && (Cptr
>= FileName
)) {
4308 // Now go through the list of filename extensions and try to find
4309 // a match for this file extension.
4311 for (i
= 0; mFileTypes
[i
].Extension
!= NULL
; i
++) {
4312 len
= strlen (mFileTypes
[i
].Extension
);
4313 if (_strnicmp (mFileTypes
[i
].Extension
, Cptr
, len
) == 0) {
4315 // Make sure that's all there is to the filename extension.
4317 if ((*(Cptr
+ len
) == 0) || isspace (*(Cptr
+ len
))) {
4318 return mFileTypes
[i
].FileFlags
& FILE_FLAG_INCLUDE
;
4327 /*****************************************************************************
4328 ******************************************************************************/
4331 StripTrailingSpaces (
4336 Cptr
= Str
+ strlen (Str
) - 1;
4337 while (Cptr
> Str
) {
4338 if (isspace (*Cptr
)) {
4347 /*****************************************************************************
4348 ******************************************************************************/
4358 // Don't set it if the user specified it on the command line.
4360 EfiSource
= GetSymbolValue (EFI_SOURCE
);
4361 if ( EfiSource
!= NULL
) {
4362 if (EfiSource
[strlen (EfiSource
) - 1] == '\\') {
4363 EfiSource
[strlen (EfiSource
) - 1] = 0;
4365 return STATUS_SUCCESS
;
4369 // Get the environmental variable setting of EFI_SOURCE.
4371 EfiSource
= getenv (EFI_SOURCE
);
4372 if (EfiSource
!= NULL
) {
4373 if (EfiSource
[strlen (EfiSource
) - 1] == '\\') {
4374 EfiSource
[strlen (EfiSource
) - 1] = 0;
4376 AddSymbol (EFI_SOURCE
, EfiSource
, SYM_GLOBAL
| SYM_FILEPATH
);
4377 return STATUS_SUCCESS
;
4380 Error (NULL
, 0, 0, NULL
, "could not determine EFI_SOURCE");
4381 return STATUS_ERROR
;
4391 INT8 Line
[MAX_LINE_LEN
];
4394 va_start (List
, Fmt
);
4395 vsprintf (Line
, Fmt
, List
);
4396 if (PrintMask
& gGlobals
.Verbose
) {
4397 fprintf (stdout
, "%s\n", Line
);
4410 static const INT8
*Help
[] = {
4411 "Usage: ProcessDsc {options} [Dsc Filename]",
4413 " -d var=value to define symbol 'var' to 'value'",
4414 " -v for verbose mode",
4415 " -g filename to preparse GUID listing file",
4416 " -x filename to create a cross-reference file",
4419 for (i
= 0; Help
[i
] != NULL
; i
++) {
4420 fprintf (stdout
, "%s\n", Help
[i
]);
4426 Routine Description:
4428 Process the [defines] section in the DSC file.
4432 DscFile - pointer to the DSCFile class that contains the relevant info.
4436 0 if not necessarily an absolute path
4442 ProcessDSCDefinesSection (
4446 INT8 Line
[MAX_LINE_LEN
];
4447 INT8 Line2
[MAX_EXP_LINE_LEN
];
4452 // Look for a [defines] section and process it
4454 Sect
= DSCFileFindSection (DscFile
, DEFINES_SECTION_NAME
);
4456 return STATUS_ERROR
;
4459 // Read lines while they're valid
4461 while (DSCFileGetLine (DscFile
, Line
, sizeof (Line
)) != NULL
) {
4463 // Expand symbols on the line
4465 if (ExpandSymbols (Line
, Line2
, sizeof (Line2
), 0)) {
4466 return STATUS_ERROR
;
4471 Cptr
= StripLine (Line2
);
4474 // Make the assignment
4476 AddSymbol (Line2
, NULL
, SYM_OVERWRITE
| SYM_GLOBAL
);
4480 return STATUS_SUCCESS
;
4489 Routine Description:
4491 Determine if a given filename contains the full path information.
4495 FileName - the name of the file, with symbol expanded.
4499 0 if not necessarily an absolute path
4505 // If the first character is a-z, and the second character is a colon, then
4506 // it is an absolute path.
4508 if (isalpha (FileName
[0]) && (FileName
[1] == ':')) {
4520 SMART_FILE
*SmartFile
;
4524 SmartFile
= malloc (sizeof (SMART_FILE
));
4525 if (SmartFile
== NULL
) {
4528 memset (SmartFile
, 0, sizeof (SMART_FILE
));
4530 SmartFile
->FileName
= malloc (strlen (FileName
) + 1);
4531 if (SmartFile
->FileName
== NULL
){
4532 SmartFree (SmartFile
);
4535 strcpy (SmartFile
->FileName
, FileName
);
4537 if ((Fptr
= fopen (FileName
, "r")) != NULL
) {
4538 fseek (Fptr
, 0, SEEK_END
);
4539 FileSize
= ftell (Fptr
);
4540 fseek (Fptr
, 0, SEEK_SET
);
4541 SmartFile
->FileContent
= malloc (FileSize
+ 1);
4542 if (SmartFile
->FileContent
!= NULL
) {
4543 memset (SmartFile
->FileContent
, 0, FileSize
+ 1);
4545 // Usually FileLength < FileSize, because in text mode, carriage return¨Clinefeed
4546 // combinations are translated into single linefeeds on input
4548 SmartFile
->FileLength
= fread (SmartFile
->FileContent
, sizeof(char), FileSize
, Fptr
);
4554 // No previous output file content, re-create the file
4556 if (SmartFile
->FileContent
== NULL
) {
4557 if ((SmartFile
->FilePtr
= fopen (FileName
, "w")) == NULL
) {
4558 SmartFree (SmartFile
);
4568 SMART_FILE
*SmartFile
,
4574 if (SmartFile
->FilePtr
!= NULL
) {
4575 return fprintf (SmartFile
->FilePtr
, "%s", String
);
4577 StrLen
= strlen (String
);
4578 if ((StrLen
> SmartFile
->FileLength
- SmartFile
->FilePosition
) ||
4579 (_strnicmp (&SmartFile
->FileContent
[SmartFile
->FilePosition
], String
, StrLen
) != 0)) {
4581 // file changed, need to re-create.
4583 if ((SmartFile
->FilePtr
= fopen (SmartFile
->FileName
, "w")) == NULL
) {
4584 Error (NULL
, 0, 0, SmartFile
->FileName
, "could not open file for writing when SmartWrite");
4587 SmartFile
->FileContent
[SmartFile
->FilePosition
] = 0;
4588 fprintf (SmartFile
->FilePtr
, "%s%s", SmartFile
->FileContent
, String
);
4592 SmartFile
->FilePosition
+= StrLen
;
4600 SMART_FILE
*SmartFile
4603 if ((SmartFile
->FilePtr
== NULL
) && (SmartFile
->FilePosition
< SmartFile
->FileLength
)) {
4605 // The new file is smaller than before, re-create it.
4607 if ((SmartFile
->FilePtr
= fopen (SmartFile
->FileName
, "w")) == NULL
) {
4608 Error (NULL
, 0, 0, SmartFile
->FileName
, "could not open file for writing when SmartClose");
4610 SmartFile
->FileContent
[SmartFile
->FilePosition
] = 0;
4611 fprintf (SmartFile
->FilePtr
, "%s", SmartFile
->FileContent
);
4615 SmartFree(SmartFile
);
4621 SMART_FILE
*SmartFile
4624 if (SmartFile
== NULL
) {
4628 if (SmartFile
->FileName
!= NULL
) {
4629 free (SmartFile
->FileName
);
4632 if (SmartFile
->FileContent
!= NULL
) {
4633 free (SmartFile
->FileContent
);
4636 if (SmartFile
->FilePtr
!= NULL
) {
4637 fclose (SmartFile
->FilePtr
);
4648 SYMBOL
**SymbolList
,
4654 Routine Description:
4656 Add module name in the global module list.
4657 For the same module names, it is only added once.
4660 SymbolList : add name into this list
4661 ModuleName : point to one module name char string.
4662 InfName : point to this module inf file name with path.
4666 0 : Successfully add input name into the global list.
4667 other value : allocate memory failed.
4671 SYMBOL
*CurrentSymbol
;
4675 // Get the global module list.
4677 CurrentSymbol
= *SymbolList
;
4678 LastSymbol
= *SymbolList
;
4681 // Search whether this module name has been added into the global list.
4683 while (CurrentSymbol
!= NULL
) {
4684 if (_stricmp (CurrentSymbol
->Name
, ModuleName
) == 0) {
4685 if ((CurrentSymbol
->Value
== NULL
) && (InfName
== NULL
)) {
4687 } else if ((CurrentSymbol
->Value
!= NULL
) && (InfName
!= NULL
) && \
4688 (_stricmp (CurrentSymbol
->Value
, InfName
) == 0)) {
4692 LastSymbol
= CurrentSymbol
;
4693 CurrentSymbol
= CurrentSymbol
->Next
;
4697 // Add new module name in list.
4699 if (CurrentSymbol
== NULL
) {
4700 CurrentSymbol
= (SYMBOL
*) malloc (sizeof (SYMBOL
));
4701 if (CurrentSymbol
== NULL
) {
4702 Error (NULL
, 0, 0, NULL
, "failed to allocate memory");
4705 memset ((INT8
*) CurrentSymbol
, 0, sizeof (SYMBOL
));
4707 if (ModuleName
!= NULL
) {
4708 CurrentSymbol
->Name
= (INT8
*) malloc (strlen (ModuleName
) + 1);
4709 strcpy (CurrentSymbol
->Name
, ModuleName
);
4712 if (InfName
!= NULL
) {
4713 CurrentSymbol
->Value
= (INT8
*) malloc (strlen (InfName
) + 1);
4714 strcpy (CurrentSymbol
->Value
, InfName
);
4717 if (LastSymbol
== NULL
) {
4718 *SymbolList
= CurrentSymbol
;
4720 LastSymbol
->Next
= CurrentSymbol
;