]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c
1) Sync EdkCompatibilityPkg with EDK 1.04. The changes includes:
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / ProcessDsc / ProcessDsc.c
1 /*++
2
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
8
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.
11
12 Module Name:
13
14 ProcessDsc.c
15
16 Abstract:
17
18 Main module for the ProcessDsc utility.
19
20 --*/
21
22 #include <windows.h> // for GetShortPathName()
23 #include <stdio.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <stdarg.h>
27 #include <direct.h> // for _mkdir()
28 #include <errno.h>
29 #include <stdlib.h> // for getenv()
30 #include "DSCFile.h"
31 #include "FWVolume.h"
32 #include "Exceptions.h"
33 #include "Common.h"
34
35 #include "EfiUtilityMsgs.h"
36 #include "TianoBind.h"
37 //
38 // Disable warning for while(1) code
39 //
40 #pragma warning(disable : 4127)
41 //
42 // Disable warning for unreferenced function parameters
43 //
44 #pragma warning(disable : 4100)
45
46 extern int errno;
47
48 #define PROGRAM_NAME "ProcessDsc"
49
50 //
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.
56 //
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"
69 #define FV "FV"
70 #define BASE_NAME "BASE_NAME"
71 #define GUID "GUID"
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
108
109 //
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.
112 //
113 #define IS_NULL_SYMBOL_VALUE(var) ((var != NULL) && (strlen (var) == 0))
114
115 //
116 // Defines for file types
117 //
118 #define FILETYPE_UNKNOWN 0
119 #define FILETYPE_C 1
120 #define FILETYPE_ASM 2
121 #define FILETYPE_S 3
122 #define FILETYPE_VFR 4
123 #define FILETYPE_INC 5
124 #define FILETYPE_H 6
125 #define FILETYPE_I 7
126
127
128 typedef struct {
129 INT8 *Extension; // file extension
130 INT8 *BuiltExtension;
131 INT8 FileFlags;
132 int FileType;
133 } FILETYPE;
134
135 //
136 // Define masks for the FileFlags field
137 //
138 #define FILE_FLAG_INCLUDE 0x01
139 #define FILE_FLAG_SOURCE 0x02
140
141 //
142 // This table describes a from-to list of files. For
143 // example, when a ".c" is built, it results in a ".obj" file.
144 //
145 static const FILETYPE mFileTypes[] = {
146 {
147 ".c",
148 ".obj",
149 FILE_FLAG_SOURCE,
150 FILETYPE_C
151 },
152 {
153 ".asm",
154 ".obj",
155 FILE_FLAG_SOURCE,
156 FILETYPE_ASM
157 },
158 {
159 ".s",
160 ".obj",
161 FILE_FLAG_SOURCE,
162 FILETYPE_S
163 },
164 {
165 ".vfr",
166 ".obj",
167 FILE_FLAG_SOURCE,
168 FILETYPE_VFR
169 }, // actually *.vfr -> *.c -> *.obj
170 {
171 ".h",
172 NULL,
173 FILE_FLAG_INCLUDE,
174 FILETYPE_H
175 },
176 {
177 ".inc",
178 NULL,
179 FILE_FLAG_INCLUDE,
180 FILETYPE_INC
181 },
182 {
183 ".i",
184 NULL,
185 FILE_FLAG_INCLUDE,
186 FILETYPE_I
187 },
188 {
189 NULL,
190 NULL,
191 0,
192 0
193 }
194 };
195
196 //
197 // Structure to split up a file into its different parts.
198 //
199 typedef struct {
200 INT8 Drive[3];
201 INT8 *Path;
202 INT8 *BaseName;
203 INT8 *Extension;
204 int ExtensionCode;
205 } FILE_NAME_PARTS;
206
207 //
208 // Maximum length for any line in any file after symbol expansion
209 //
210 #define MAX_EXP_LINE_LEN (MAX_LINE_LEN * 2)
211
212 //
213 // Linked list to keep track of all symbols
214 //
215 typedef struct _SYMBOL {
216 struct _SYMBOL *Next;
217 int Type; // local or global symbol
218 INT8 *Name;
219 INT8 *Value;
220 } SYMBOL;
221
222 //
223 // Define new SYMBOL list to record all module name used in the platform.dsc file.
224 //
225 SYMBOL *gModuleList = NULL;
226
227 //
228 // This structure is used to save globals
229 //
230 struct {
231 INT8 *DscFilename;
232 SYMBOL *Symbol;
233 INT8 MakefileName[MAX_PATH]; // output makefile name
234 INT8 XRefFileName[MAX_PATH];
235 INT8 GuidDatabaseFileName[MAX_PATH];
236 INT8 ModuleMakefileName[MAX_PATH];
237 FILE *MakefileFptr;
238 FILE *ModuleMakefileFptr;
239 SYMBOL *ModuleList;
240 SYMBOL *OutdirList;
241 UINT32 Verbose;
242 } gGlobals;
243
244 //
245 // This gets dumped to the head of makefile.out
246 //
247 static const INT8 *MakefileHeader[] = {
248 "#/*++",
249 "#",
250 "# DO NOT EDIT",
251 "# File auto-generated by build utility",
252 "#",
253 "# Module Name:",
254 "#",
255 "# makefile",
256 "#",
257 "# Abstract:",
258 "#",
259 "# Auto-generated makefile for building of EFI components/libraries",
260 "#",
261 "#--*/",
262 "",
263 NULL
264 };
265
266 //
267 // Function prototypes
268 //
269 static
270 int
271 ProcessOptions (
272 int Argc,
273 INT8 *Argv[]
274 );
275
276 static
277 void
278 Usage (
279 VOID
280 );
281
282 static
283 INT8 *
284 StripLine (
285 INT8 *Line
286 );
287
288 static
289 STATUS
290 ParseGuidDatabaseFile (
291 INT8 *FileName
292 );
293
294 #define DSC_SECTION_TYPE_COMPONENTS 0
295 #define DSC_SECTION_TYPE_LIBRARIES 1
296 #define DSC_SECTION_TYPE_PLATFORM_LIBRARIES 2
297
298 static
299 int
300 ProcessSectionComponents (
301 DSC_FILE *DscFile,
302 int DscSectionType,
303 int Instance
304 );
305 static
306 int
307 ProcessComponentFile (
308 DSC_FILE *DscFile,
309 INT8 *Line,
310 int DscSectionType,
311 int Instance
312 );
313 static
314 int
315 ProcessIncludeFiles (
316 DSC_FILE *ComponentFile,
317 FILE *MakeFptr
318 );
319 static
320
321 int
322 ProcessIncludeFilesSingle (
323 DSC_FILE *ComponentFile,
324 FILE *MakeFptr,
325 INT8 *SectionName
326 );
327
328 //
329 // Mode flags for processing source files
330 //
331 #define SOURCE_MODE_BUILD_COMMANDS 0x01
332 #define SOURCE_MODE_SOURCE_FILES 0x02
333
334 static
335 int
336 ProcessSourceFiles (
337 DSC_FILE *DSCFile,
338 DSC_FILE *ComponentFile,
339 FILE *MakeFptr,
340 UINT32 Mode
341 );
342
343 static
344 int
345 ProcessSourceFilesSection (
346 DSC_FILE *DSCFile,
347 DSC_FILE *ComponentFile,
348 FILE *MakeFptr,
349 INT8 *SectionName,
350 UINT32 Mode
351 );
352
353 static
354 int
355 ProcessObjects (
356 DSC_FILE *ComponentFile,
357 FILE *MakeFptr
358 );
359
360 static
361 int
362 ProcessObjectsSingle (
363 DSC_FILE *ComponentFile,
364 FILE *MakeFptr,
365 INT8 *SectionName
366 );
367
368 static
369 int
370 ProcessLibs (
371 DSC_FILE *ComponentFile,
372 FILE *MakeFptr
373 );
374
375 static
376 int
377 ProcessLibsSingle (
378 DSC_FILE *ComponentFile,
379 FILE *MakeFptr,
380 INT8 *SectionName
381 );
382
383 static
384 int
385 ProcessIncludesSection (
386 DSC_FILE *ComponentFile,
387 FILE *MakeFptr
388 );
389
390 static
391 int
392 ProcessIncludesSectionSingle (
393 DSC_FILE *ComponentFile,
394 FILE *MakeFptr,
395 INT8 *SectionName
396 );
397
398 static
399 int
400 ProcessINFNMakeSection (
401 DSC_FILE *ComponentFile,
402 FILE *MakeFptr
403 );
404
405 static
406 int
407 ProcessINFDefinesSection (
408 DSC_FILE *ComponentFile
409 );
410
411 static
412 int
413 ProcessINFDefinesSectionSingle (
414 DSC_FILE *ComponentFile,
415 INT8 *SectionName
416 );
417
418 static
419 int
420 ProcessSectionLibraries (
421 DSC_FILE *DscFile,
422 long Offset
423 );
424
425 static
426 int
427 ProcessDSCDefinesSection (
428 DSC_FILE *DscFile
429 );
430
431 static
432 int
433 SetSymbolType (
434 INT8 *SymbolName,
435 INT8 Type
436 );
437
438 static
439 int
440 RemoveLocalSymbols (
441 VOID
442 );
443
444 static
445 int
446 RemoveFileSymbols (
447 VOID
448 );
449
450 static
451 int
452 RemoveSymbol (
453 INT8 *Name,
454 INT8 SymbolType
455 );
456
457 static
458 int
459 SetFileExtension (
460 INT8 *FileName,
461 INT8 *Extension
462 );
463
464 static
465 int
466 GetSourceFileType (
467 INT8 *FileName
468 );
469
470 static
471 int
472 IsIncludeFile (
473 INT8 *FileName
474 );
475
476 static
477 int
478 WriteCompileCommands (
479 DSC_FILE *DscFile,
480 FILE *MakeFptr,
481 INT8 *FileName,
482 INT8 *Processor
483 );
484
485 static
486 int
487 WriteCommonMakefile (
488 DSC_FILE *DscFile,
489 FILE *MakeFptr,
490 INT8 *Processor
491 );
492
493 static
494 int
495 WriteComponentTypeBuildCommands (
496 DSC_FILE *DscFile,
497 FILE *MakeFptr,
498 INT8 *SectionName
499 );
500
501 static
502 void
503 StripTrailingSpaces (
504 INT8 *Str
505 );
506
507 static
508 void
509 FreeFileParts (
510 FILE_NAME_PARTS *FP
511 );
512
513 static
514 FILE_NAME_PARTS *
515 GetFileParts (
516 INT8 *FileName
517 );
518
519 static
520 SYMBOL *
521 FreeSymbols (
522 SYMBOL *Syms
523 );
524
525 static
526 int
527 GetEfiSource (
528 VOID
529 );
530
531 static
532 int
533 CreatePackageFile (
534 DSC_FILE *DSCFile
535 );
536
537 static
538 INT8 *
539 BuiltFileExtension (
540 INT8 *SourceFileName
541 );
542
543 static
544 void
545 SmartFree (
546 SMART_FILE *SmartFile
547 );
548
549 static
550 int
551 AddModuleName (
552 SYMBOL **SymbolList,
553 INT8 *ModuleName,
554 INT8 *InfName
555 );
556
557 static
558 void
559 ReplaceSlash (
560 INT8 *Path
561 );
562
563 /*****************************************************************************/
564 int
565 main (
566 int Argc,
567 INT8 *Argv[]
568 )
569 /*++
570
571 Routine Description:
572
573 Main utility entry point.
574
575 Arguments:
576
577 Argc - Standard app entry point args.
578 Argv - Standard app entry point args.
579
580 Returns:
581
582 0 if successful
583 non-zero otherwise
584
585 --*/
586 {
587 int i;
588 DSC_FILE DSCFile;
589 SECTION *Sect;
590 INT8 Line[MAX_LINE_LEN];
591 INT8 ExpLine[MAX_LINE_LEN];
592 INT8 *EMsg;
593 FILE *FpModule;
594 SYMBOL *TempSymbol;
595
596 SetUtilityName (PROGRAM_NAME);
597
598 InitExceptions ();
599
600 DSCFileInit (&DSCFile);
601 //
602 // Initialize the firmware volume data
603 //
604 CFVConstructor ();
605 //
606 // Exception handling for this block of code.
607 //
608 TryException ();
609 //
610 // Process command-line options.
611 //
612 if (ProcessOptions (Argc, Argv)) {
613 EMsg = CatchException ();
614 if (EMsg != NULL) {
615 fprintf (stderr, "%s\n", EMsg);
616 }
617
618 return STATUS_ERROR;
619 }
620 //
621 // Parse the GUID database file if specified
622 //
623 if (gGlobals.GuidDatabaseFileName[0] != 0) {
624 ParseGuidDatabaseFile (gGlobals.GuidDatabaseFileName);
625 }
626 //
627 // Set the output cross-reference file if applicable
628 //
629 if (gGlobals.XRefFileName[0]) {
630 CFVSetXRefFileName (gGlobals.XRefFileName);
631 }
632
633 //
634 // Now get the EFI_SOURCE directory which we use everywhere.
635 //
636 if (GetEfiSource ()) {
637 return STATUS_ERROR;
638 }
639
640 //
641 // Pre-process the DSC file to get section info.
642 //
643 if (DSCFileSetFile (&DSCFile, gGlobals.DscFilename) != 0) {
644 goto ProcessingError;
645 }
646
647 //
648 // Set output makefile name for single module build
649 //
650 strcpy (gGlobals.ModuleMakefileName, MODULE_MAKEFILE_NAME);
651
652 //
653 // Try to open all final output makefiles
654 //
655 if ((gGlobals.MakefileFptr = fopen (gGlobals.MakefileName, "w")) == NULL) {
656 Error (NULL, 0, 0, gGlobals.MakefileName, "failed to open output makefile for writing");
657 goto ProcessingError;
658 }
659 if ((gGlobals.ModuleMakefileFptr = fopen (gGlobals.ModuleMakefileName, "w")) == NULL) {
660 Error (NULL, 0, 0, gGlobals.ModuleMakefileName, "failed to open output makefile for writing");
661 goto ProcessingError;
662 }
663
664 //
665 // Write the header out to the makefiles
666 //
667 for (i = 0; MakefileHeader[i] != NULL; i++) {
668 fprintf (gGlobals.MakefileFptr, "%s\n", MakefileHeader[i]);
669 fprintf (gGlobals.ModuleMakefileFptr, "%s\n", MakefileHeader[i]);
670 }
671
672 //
673 // Init global potint = NULL
674 //
675 gGlobals.ModuleList = NULL;
676 gGlobals.OutdirList = NULL;
677
678 //
679 // Process the [defines] section in the DSC file to get any defines we need
680 // elsewhere
681 //
682 ProcessDSCDefinesSection (&DSCFile);
683 if (ExceptionThrown ()) {
684 goto ProcessingError;
685 }
686 //
687 // Write out the [makefile.out] section data to the output makefiles
688 //
689 Sect = DSCFileFindSection (&DSCFile, MAKEFILE_OUT_SECTION_NAME);
690 if (Sect != NULL) {
691 while (DSCFileGetLine (&DSCFile, Line, sizeof (Line)) != NULL) {
692 ExpandSymbols (Line, ExpLine, sizeof (ExpLine), 0);
693 //
694 // Write the line to the output makefiles
695 //
696 fprintf (gGlobals.MakefileFptr, ExpLine);
697 fprintf (gGlobals.ModuleMakefileFptr, ExpLine);
698 }
699 }
700
701 //
702 // Add a pseudo target for GLOBAL_LINK_LIB_NAME to avoid single module build
703 // failure when this lib is not used.
704 //
705 fprintf (gGlobals.ModuleMakefileFptr, "%sbuild ::\n\n", GLOBAL_LINK_LIB_NAME);
706
707 fprintf (gGlobals.MakefileFptr, "libraries : \n");
708 //
709 // Process [libraries] section in the DSC file
710 //
711 Sect = DSCFileFindSection (&DSCFile, LIBRARIES_SECTION_NAME);
712 if (Sect != NULL) {
713 ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_LIBRARIES, 0);
714 }
715
716 if (ExceptionThrown ()) {
717 goto ProcessingError;
718 }
719 //
720 // Process [libraries.platform] section in the DSC file
721 //
722 Sect = DSCFileFindSection (&DSCFile, LIBRARIES_PLATFORM_SECTION_NAME);
723 if (Sect != NULL) {
724 ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_PLATFORM_LIBRARIES, 0);
725 }
726
727 fprintf (gGlobals.MakefileFptr, "\n");
728 if (ExceptionThrown ()) {
729 goto ProcessingError;
730 }
731
732 //
733 // Process [components] section in the DSC file
734 //
735 Sect = DSCFileFindSection (&DSCFile, COMPONENTS_SECTION_NAME);
736 if (Sect != NULL) {
737 fprintf (gGlobals.MakefileFptr, "components_0 : \n");
738 ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_COMPONENTS, 0);
739 fprintf (gGlobals.MakefileFptr, "\n");
740 }
741
742 if (ExceptionThrown ()) {
743 goto ProcessingError;
744 }
745 //
746 // Now cycle through all [components.1], [components.2], ....[components.n].
747 // This is necessary to support building of firmware volumes that may contain
748 // other encapsulated firmware volumes (ala capsules).
749 //
750 i = 1;
751 while (1) {
752 RemoveSymbol (FV, SYM_GLOBAL);
753 sprintf (Line, "%s.%d", COMPONENTS_SECTION_NAME, i);
754 Sect = DSCFileFindSection (&DSCFile, Line);
755 if (Sect != NULL) {
756 fprintf (gGlobals.MakefileFptr, "components_%d : \n", i);
757 ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_COMPONENTS, i);
758 fprintf (gGlobals.MakefileFptr, "\n");
759 } else {
760 break;
761 }
762
763 if (ExceptionThrown ()) {
764 goto ProcessingError;
765 }
766
767 i++;
768 }
769
770 ProcessingError:
771 EMsg = CatchException ();
772 if (EMsg != NULL) {
773 fprintf (stderr, "%s\n", EMsg);
774 fprintf (stderr, "Processing aborted\n");
775 }
776
777 TryException ();
778 //
779 // Create the FV files if no fatal errors or errors
780 //
781 if (GetUtilityStatus () < STATUS_ERROR) {
782 CFVWriteInfFiles (&DSCFile, gGlobals.MakefileFptr);
783 }
784
785 //
786 // Write all module name into MODULE_NAME_FILE file.
787 //
788 if ((FpModule = fopen (MODULE_NAME_FILE, "w")) != NULL) {
789 TempSymbol = gGlobals.ModuleList;
790 while (TempSymbol != NULL) {
791 fprintf (FpModule, " %-*s %s \n", MODULE_BASE_NAME_WIDTH, TempSymbol->Name, TempSymbol->Value);
792 TempSymbol = TempSymbol->Next;
793 }
794 fclose (FpModule);
795 FpModule = NULL;
796 }
797
798 //
799 // Close the all the output makefiles
800 //
801 if (gGlobals.MakefileFptr != NULL) {
802 fclose (gGlobals.MakefileFptr);
803 gGlobals.MakefileFptr = NULL;
804 }
805
806 if (gGlobals.ModuleMakefileFptr != NULL) {
807 fclose (gGlobals.ModuleMakefileFptr);
808 gGlobals.ModuleMakefileFptr = NULL;
809 }
810
811 //
812 // Clean up
813 //
814 FreeSymbols (gGlobals.ModuleList);
815 FreeSymbols (gGlobals.OutdirList);
816 FreeSymbols (gGlobals.Symbol);
817 gGlobals.Symbol = NULL;
818 CFVDestructor ();
819 DSCFileDestroy (&DSCFile);
820
821 EMsg = CatchException ();
822 if (EMsg != NULL) {
823 fprintf (stderr, "%s\n", EMsg);
824 fprintf (stderr, "Processing aborted\n");
825 }
826
827 return GetUtilityStatus ();
828 }
829
830 static
831 int
832 ProcessSectionComponents (
833 DSC_FILE *DSCFile,
834 int DscSectionType,
835 int Instance
836 )
837 /*++
838
839 Routine Description:
840
841 Process the [components] or [libraries] section in the description file. We
842 use this function for both since they're very similar. Here we just
843 read each line from the section, and if it's valid, call a function to
844 do the actual processing of the component description file.
845
846 Arguments:
847
848 DSCFile - structure containing section info on the description file
849 DscSectionType - type of description section
850
851 Returns:
852
853 0 if successful
854
855 --*/
856 {
857 INT8 Line[MAX_LINE_LEN];
858 INT8 Line2[MAX_EXP_LINE_LEN];
859 INT8 *Cptr;
860
861 //
862 // Read lines while they're valid
863 //
864 while (DSCFileGetLine (DSCFile, Line, sizeof (Line)) != NULL) {
865 //
866 // Expand symbols on the line
867 //
868 if (ExpandSymbols (Line, Line2, sizeof (Line2), 0)) {
869 return STATUS_ERROR;
870 }
871 //
872 // Strip the line
873 //
874 Cptr = StripLine (Line2);
875 if (*Cptr) {
876 Message (2, "Processing component line: %s", Line2);
877 if (ProcessComponentFile (DSCFile, Line2, DscSectionType, Instance) != 0) {
878 return STATUS_ERROR;
879 }
880 }
881 }
882
883 return 0;
884 }
885
886 static
887 int
888 ProcessComponentFile (
889 DSC_FILE *DSCFile,
890 INT8 *ArgLine,
891 int DscSectionType,
892 int Instance
893 )
894 /*++
895
896 Routine Description:
897
898 Given a line from the [components] or [libraries] section of the description
899 file, process the line to extract the component's INF filename and
900 parameters. Then open the INF file and process it to create a corresponding
901 makefile.
902
903 Arguments:
904
905 DSCFile The project DSC file info structure.
906 Libs Indicates whether we're processing the [components]
907 section or the [libraries] section.
908 ArgLine The actual line from the DSC file. Looks something like
909 one of the following:
910
911 dxe\drivers\vm\vm.dsc PROCESSOR=IA32 DEST_DIR=$(DEST_DIR)\xxx FV=FV1,FV2
912 $(BUILD_DIR).\FvVariable.ffs COMPONENT_TYPE=FILE
913 .\FvVariable.ffs COMPONENT_TYPE=FILE
914 define VAR1=value1 VAR2=value2
915
916 Returns:
917
918 0 if successful
919
920 --*/
921 {
922 FILE *MakeFptr;
923 FILE *TempFptr;
924 INT8 *Cptr;
925 INT8 *name;
926 INT8 *End;
927 INT8 *TempCptr;
928 INT8 FileName[MAX_PATH];
929 INT8 ComponentFilePath[MAX_PATH];
930 INT8 InLine[MAX_LINE_LEN];
931 INT8 Line[MAX_LINE_LEN];
932 INT8 *Processor;
933 INT8 SymType;
934 int Len;
935 int ComponentCreated;
936 int ComponentFilePathAbsolute;
937 int DefineLine;
938 DSC_FILE ComponentFile;
939 INT8 ComponentMakefileName[MAX_PATH];
940 BOOLEAN IsForFv;
941
942 //
943 // Now remove all local symbols
944 //
945 RemoveLocalSymbols ();
946 //
947 // Null out the file pointer in case we take an exception somewhere
948 // and we need to close it only if we opened it.
949 //
950 MakeFptr = NULL;
951 ComponentFilePathAbsolute = 0;
952 ComponentCreated = 0;
953 //
954 // Skip preceeding spaces on the line
955 //
956 while (isspace (*ArgLine) && (*ArgLine)) {
957 ArgLine++;
958 }
959 //
960 // Find the end of the component's filename and truncate the line at that
961 // point. From here on out ArgLine is the name of the component filename.
962 //
963 Cptr = ArgLine;
964 while (!isspace (*Cptr) && *Cptr) {
965 Cptr++;
966 }
967
968 End = Cptr;
969 if (*Cptr) {
970 End++;
971 *Cptr = 0;
972 }
973 //
974 // Exception-handle processing of this component description file
975 //
976 TryException ();
977
978 //
979 // We also allow a component line format for defines of global symbols
980 // instead of a component filename. In this case, the line looks like:
981 // defines x=abc y=yyy. Be nice and accept "define" and "defines" in a
982 // case-insensitive manner. If it's defines, then make the symbols global.
983 //
984 if ((_stricmp (ArgLine, "define") == 0) || (_stricmp (ArgLine, "defines") == 0)) {
985 SymType = SYM_OVERWRITE | SYM_GLOBAL;
986 DefineLine = 1;
987 } else {
988 SymType = SYM_OVERWRITE | SYM_LOCAL;
989 DefineLine = 0;
990 }
991 //
992 // The rest of the component line from the DSC file should be defines
993 //
994 while (*End) {
995 End = StripLine (End);
996 if (*End) {
997 //
998 // If we're processing a "define abc=1 xyz=2" line, then set symbols
999 // as globals per the SymType set above.
1000 //
1001 Len = AddSymbol (End, NULL, SymType);
1002 if (Len > 0) {
1003 End += Len;
1004 } else {
1005 Warning (NULL, 0, 0, ArgLine, "unrecognized option in description file");
1006 break;
1007 }
1008 }
1009 }
1010
1011 //
1012 // If DEBUG_BREAK or EFI_BREAKPOINT is defined, then do a debug breakpoint.
1013 //
1014 if ((GetSymbolValue ("DEBUG_BREAK") != NULL) || (GetSymbolValue ("EFI_BREAKPOINT") != NULL)) {
1015 EFI_BREAKPOINT ();
1016 }
1017
1018 //
1019 // If it's a define line, then we're done
1020 //
1021 if (DefineLine) {
1022 //
1023 // If there is NonFFS_FV, create the FVxxx.inf file
1024 // and include it in makefile.out. Remove the symbol
1025 // in order not to process it again next time
1026 //
1027 Cptr = GetSymbolValue (NONFFS_FV);
1028 if (Cptr != NULL) {
1029 NonFFSFVWriteInfFiles (DSCFile, Cptr);
1030 RemoveSymbol (NONFFS_FV, SYM_GLOBAL);
1031 }
1032
1033 goto ComponentDone;
1034 }
1035
1036 //
1037 // Expand symbols in the component description filename to expand the newly
1038 // added local symbols
1039 //
1040 ExpandSymbols (ArgLine, Line, sizeof (Line), EXPANDMODE_NO_UNDEFS);
1041
1042 //
1043 // If we have "c:\path\filename"
1044 //
1045 ReplaceSlash (Line);
1046 if (IsAbsolutePath (Line)) {
1047 ComponentFilePathAbsolute = 1;
1048 } else if (Line[0] == '.') {
1049 //
1050 // or if the path starts with ".", then it's build-dir relative.
1051 // Prepend $(BUILD_DIR) on the file name
1052 //
1053 sprintf (InLine, "%s\\%s", GetSymbolValue (BUILD_DIR), Line);
1054 strcpy (Line, InLine);
1055 ComponentFilePathAbsolute = 1;
1056 }
1057
1058 //
1059 // Save the path from the component name for later. It may be relative or
1060 // absolute.
1061 //
1062 strcpy (ComponentFilePath, Line);
1063 Cptr = ComponentFilePath + strlen (ComponentFilePath) - 1;
1064 while ((*Cptr != '\\') && (Cptr != ComponentFilePath)) {
1065 Cptr--;
1066 }
1067 //
1068 // Terminate the path.
1069 //
1070 *Cptr = 0;
1071
1072 //
1073 // Typically the given line is a component description filename. However we
1074 // also allow a FV filename (fvvariable.ffs COMPONENT_TYPE=FILE). If the
1075 // component type is "FILE", then add it to the FV list, create a package
1076 // file, and we're done.
1077 //
1078 Cptr = GetSymbolValue (COMPONENT_TYPE);
1079 if ((Cptr != NULL) && (strncmp (
1080 Cptr,
1081 COMPONENT_TYPE_FILE,
1082 strlen (COMPONENT_TYPE_FILE)
1083 ) == 0)) {
1084 if (ComponentFilePathAbsolute) {
1085 strcpy (InLine, Line);
1086 } else {
1087 sprintf (InLine, "%s\\%s", GetSymbolValue (EFI_SOURCE), Line);
1088 }
1089 CFVAddFVFile (
1090 InLine,
1091 Cptr,
1092 GetSymbolValue (FV),
1093 Instance,
1094 NULL,
1095 NULL,
1096 GetSymbolValue (APRIORI),
1097 NULL,
1098 NULL
1099 );
1100 goto ComponentDone;
1101 }
1102
1103 //
1104 // Better have defined processor by this point.
1105 //
1106 Processor = GetSymbolValue (PROCESSOR);
1107 if (Processor == NULL) {
1108 Error (NULL, 0, 0, NULL, "PROCESSOR not defined for component %s", Line);
1109 return STATUS_ERROR;
1110 }
1111
1112 //
1113 // The bin, out, and lib dirs are now = $(BUILD_DIR)/$(PROCESSOR). Set them.
1114 // Don't flag them as file paths (required for short 8.3 filenames) since
1115 // they're defined using the BUILD_DIR macro.
1116 //
1117 sprintf (InLine, "$(BUILD_DIR)\\%s", Processor);
1118 AddSymbol (BIN_DIR, InLine, SYM_LOCAL);
1119 AddSymbol (OUT_DIR, InLine, SYM_LOCAL);
1120 AddSymbol (LIB_DIR, InLine, SYM_LOCAL);
1121 //
1122 // See if it's been destined for an FV. It's possible to not be in an
1123 // FV if they just want to build it.
1124 //
1125 Cptr = GetSymbolValue (FV);
1126 if ((Cptr != NULL) && !IS_NULL_SYMBOL_VALUE (Cptr)) {
1127 IsForFv = TRUE;
1128 } else {
1129 IsForFv = FALSE;
1130 }
1131 //
1132 // As an optimization, if they've defined SKIP_FV_NULL as non-zero, and
1133 // the component is not destined for an FV, then skip it.
1134 // Since libraries are never intended for firmware volumes, we have to
1135 // build all of them.
1136 //
1137 if ((DscSectionType == DSC_SECTION_TYPE_COMPONENTS) && (IsForFv == FALSE)) {
1138 if ((GetSymbolValue (SKIP_FV_NULL) != NULL) && (atoi (GetSymbolValue (SKIP_FV_NULL)) != 0)) {
1139 Message (0, "%s not being built (FV=NULL)", FileName);
1140 goto ComponentDone;
1141 }
1142 }
1143 //
1144 // Prepend EFI_SOURCE to the component description file to get the
1145 // full path. Only do this if the path is not a full path already.
1146 //
1147 if (ComponentFilePathAbsolute == 0) {
1148 name = GetSymbolValue (EFI_SOURCE);
1149 sprintf (FileName, "%s\\%s", name, Line);
1150 } else {
1151 strcpy (FileName, Line);
1152 }
1153 //
1154 // Print a message, depending on verbose level.
1155 //
1156 if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) {
1157 Message (1, "Processing component %s", FileName);
1158 } else {
1159 Message (1, "Processing library %s", FileName);
1160 }
1161 //
1162 // Open the component's description file and get the sections. If we fail
1163 // to open it, see if they defined "OPTIONAL=1, in which case we'll just
1164 // ignore the component.
1165 //
1166 TempFptr = fopen (FileName, "r");
1167 if (TempFptr == NULL) {
1168 //
1169 // Better have defined OPTIONAL
1170 //
1171 if (GetSymbolValue (OPTIONAL_COMPONENT) != NULL) {
1172 if (atoi (GetSymbolValue (OPTIONAL_COMPONENT)) != 0) {
1173 Message (0, "Optional component '%s' not found", FileName);
1174 goto ComponentDone;
1175 }
1176 }
1177
1178 ParserError (0, FileName, "failed to open component file");
1179 return STATUS_ERROR;
1180 } else {
1181 fclose (TempFptr);
1182 }
1183
1184 DSCFileInit (&ComponentFile);
1185 ComponentCreated = 1;
1186 if (DSCFileSetFile (&ComponentFile, FileName)) {
1187 Error (NULL, 0, 0, NULL, "failed to preprocess component file '%s'", FileName);
1188 return STATUS_ERROR;
1189 }
1190 //
1191 // Add a symbol for the INF filename so users can create dependencies
1192 // in makefiles.
1193 //
1194 AddSymbol (INF_FILENAME, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILENAME);
1195 //
1196 // Process the [defines], [defines.$(PROCESSOR)], and [defines.$(PROCESSOR).$(PLATFORM)]
1197 // sections in the INF file
1198 //
1199 ProcessINFDefinesSection (&ComponentFile);
1200 //
1201 // Better have defined FILE_GUID if not a library
1202 //
1203 if ((GetSymbolValue (GUID) == NULL) &&
1204 (GetSymbolValue (FILE_GUID) == NULL) &&
1205 (DscSectionType == DSC_SECTION_TYPE_COMPONENTS)
1206 ) {
1207 Error (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "missing FILE_GUID definition in component file");
1208 DSCFileDestroy (&ComponentFile);
1209 return STATUS_ERROR;
1210 }
1211 //
1212 // Better have defined base name
1213 //
1214 if (GetSymbolValue (BASE_NAME) == NULL) {
1215 Error (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "missing BASE_NAME definition in INF file");
1216 DSCFileDestroy (&ComponentFile);
1217 return STATUS_ERROR;
1218 }
1219 //
1220 // Better have defined COMPONENT_TYPE, since it's used to find named sections.
1221 //
1222 if (GetSymbolValue (COMPONENT_TYPE) == NULL) {
1223 Error (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "missing COMPONENT_TYPE definition in INF file");
1224 DSCFileDestroy (&ComponentFile);
1225 return STATUS_ERROR;
1226 }
1227
1228 //
1229 // Create the source directory path from the component file's path. If the component
1230 // file's path is absolute, we may have problems here. Try to account for it though.
1231 //
1232 if (ComponentFilePathAbsolute == 0) {
1233 sprintf (
1234 FileName,
1235 "%s\\%s",
1236 GetSymbolValue (EFI_SOURCE),
1237 ComponentFilePath
1238 );
1239 } else {
1240 strcpy (FileName, ComponentFilePath);
1241 }
1242 AddSymbol (SOURCE_DIR, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILEPATH);
1243
1244 //
1245 // Create the destination path.
1246 // They may have defined DEST_DIR on the component INF line, so it's already
1247 // been defined, If that's the case, then don't set it to the path of this file.
1248 //
1249 TempCptr = GetSymbolValue (DEST_DIR);
1250 if (TempCptr == NULL) {
1251 if (ComponentFilePathAbsolute == 0) {
1252 //
1253 // The destination path is $(BUILD_DIR)\$(PROCESSOR)\component_path
1254 //
1255 sprintf (
1256 FileName,
1257 "%s\\%s\\%s",
1258 GetSymbolValue (BUILD_DIR),
1259 Processor,
1260 ComponentFilePath
1261 );
1262 } else {
1263 //
1264 // The destination path is $(BUILD_DIR)\$(PROCESSOR)\$(BASE_NAME)
1265 //
1266 sprintf (
1267 FileName,
1268 "%s\\%s\\%s",
1269 GetSymbolValue (BUILD_DIR),
1270 Processor,
1271 GetSymbolValue (BASE_NAME)
1272 );
1273 }
1274 AddSymbol (DEST_DIR, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILEPATH);
1275 } else {
1276 ReplaceSlash (TempCptr);
1277 }
1278
1279 //
1280 // Create the output directory, then open the output component's makefile
1281 // we're going to create. Allow them to override the makefile name.
1282 //
1283 TempCptr = GetSymbolValue (MAKEFILE_NAME);
1284 if (TempCptr != NULL) {
1285 ExpandSymbols (TempCptr, ComponentMakefileName, sizeof (ComponentMakefileName), EXPANDMODE_NO_UNDEFS);
1286 TempCptr = ComponentMakefileName;
1287 } else {
1288 TempCptr = "makefile";
1289 }
1290
1291 sprintf (FileName, "%s\\%s", GetSymbolValue (DEST_DIR), TempCptr);
1292 //
1293 // Save it now with path info
1294 //
1295 AddSymbol (MAKEFILE_NAME, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILENAME);
1296
1297 if (MakeFilePath (FileName)) {
1298 return STATUS_ERROR;
1299 }
1300
1301 if ((MakeFptr = fopen (FileName, "w")) == NULL) {
1302 Error (NULL, 0, 0, FileName, "could not create makefile");
1303 return STATUS_ERROR;
1304 }
1305 //
1306 // At this point we should have all the info we need to create a package
1307 // file if setup to do so. Libraries don't use package files, so
1308 // don't do this for libs.
1309 //
1310 if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) {
1311 CreatePackageFile (DSCFile);
1312 }
1313
1314 //
1315 // Add Module name to the global module list
1316 //
1317 AddModuleName (&gGlobals.ModuleList, GetSymbolValue (BASE_NAME), GetSymbolValue (INF_FILENAME));
1318 //
1319 // Write an nmake line to makefile.out
1320 //
1321 fprintf (gGlobals.MakefileFptr, " @cd %s\n", Processor);
1322 fprintf (gGlobals.MakefileFptr, " $(MAKE) -f %s all\n", FileName);
1323 fprintf (gGlobals.MakefileFptr, " @cd ..\n");
1324
1325 //
1326 // Copy the common makefile section from the description file to
1327 // the component's makefile
1328 //
1329 WriteCommonMakefile (DSCFile, MakeFptr, Processor);
1330 //
1331 // Process the component's [nmake.common] and [nmake.$(PROCESSOR)] sections
1332 //
1333 ProcessINFNMakeSection (&ComponentFile, MakeFptr);
1334 //
1335 // Create the SOURCE_FILES macro that includes the names of all source
1336 // files in this component. This macro can then be used elsewhere to
1337 // process all the files making up the component. Required for scanning
1338 // files for string localization.
1339 //
1340 ProcessSourceFiles (DSCFile, &ComponentFile, MakeFptr, SOURCE_MODE_SOURCE_FILES);
1341 //
1342 // Create the include paths. Process [includes.common] and
1343 // [includes.$(PROCESSOR)] and [includes.$(PROCESSOR).$(PLATFORM)] sections.
1344 //
1345 ProcessIncludesSection (&ComponentFile, MakeFptr);
1346 //
1347 // Process all include source files to create a dependency list that can
1348 // be used in the makefile.
1349 //
1350 ProcessIncludeFiles (&ComponentFile, MakeFptr);
1351 //
1352 // Process the [sources.common], [sources.$(PROCESSOR)], and
1353 // [sources.$(PROCESSOR).$(PLATFORM)] files and emit their build commands
1354 //
1355 ProcessSourceFiles (DSCFile, &ComponentFile, MakeFptr, SOURCE_MODE_BUILD_COMMANDS);
1356 //
1357 // Process sources again to create an OBJECTS macro
1358 //
1359 ProcessObjects (&ComponentFile, MakeFptr);
1360
1361 //
1362 // Add Single Module target : build and clean in top level makefile
1363 //
1364 fprintf (gGlobals.ModuleMakefileFptr, "%sbuild ::", GetSymbolValue (BASE_NAME));
1365 if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) {
1366 fprintf (gGlobals.ModuleMakefileFptr, " %sbuild", GLOBAL_LINK_LIB_NAME);
1367 }
1368
1369 //
1370 // Process all the libraries to define "LIBS = x.lib y.lib..."
1371 // Be generous and append ".lib" if they forgot.
1372 // Make a macro definition: LIBS = $(LIBS) xlib.lib ylib.lib...
1373 // Also add libs dependency for single module build: basenamebuild :: xlibbuild ylibbuild ...
1374 //
1375 ProcessLibs (&ComponentFile, MakeFptr);
1376
1377 fprintf (gGlobals.ModuleMakefileFptr, "\n");
1378
1379 fprintf (gGlobals.ModuleMakefileFptr, " @cd %s\n", Processor);
1380 fprintf (gGlobals.ModuleMakefileFptr, " $(MAKE) -f %s all\n", FileName);
1381 fprintf (gGlobals.ModuleMakefileFptr, " @cd ..\n\n");
1382
1383 fprintf (gGlobals.ModuleMakefileFptr, "%sclean ::\n", GetSymbolValue (BASE_NAME));
1384 fprintf (gGlobals.ModuleMakefileFptr, " $(MAKE) -f %s clean\n\n", FileName);
1385
1386 //
1387 // Emit commands to create the component. These are simply copied from
1388 // the description file to the component's makefile. First look for
1389 // [build.$(PROCESSOR).$(BUILD_TYPE)]. If not found, then look for if
1390 // find a [build.$(PROCESSOR).$(COMPONENT_TYPE)] line.
1391 //
1392 Cptr = GetSymbolValue (BUILD_TYPE);
1393 if (Cptr != NULL) {
1394 sprintf (InLine, "build.%s.%s", Processor, Cptr);
1395 WriteComponentTypeBuildCommands (DSCFile, MakeFptr, InLine);
1396 } else {
1397 sprintf (InLine, "build.%s.%s", Processor, GetSymbolValue (COMPONENT_TYPE));
1398 WriteComponentTypeBuildCommands (DSCFile, MakeFptr, InLine);
1399 }
1400 //
1401 // Add it to the FV if not a library
1402 //
1403 if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) {
1404 //
1405 // Create the FV filename and add it to the FV.
1406 // By this point we know it's in FV.
1407 //
1408 Cptr = GetSymbolValue (FILE_GUID);
1409 if (Cptr == NULL) {
1410 Cptr = GetSymbolValue (GUID);
1411 }
1412
1413 sprintf (InLine, "%s-%s", Cptr, GetSymbolValue (BASE_NAME));
1414 //
1415 // We've deprecated FV_EXT, which should be FFS_EXT, the extension
1416 // of the FFS file generated by GenFFSFile.
1417 //
1418 TempCptr = GetSymbolValue (FFS_EXT);
1419 if (TempCptr == NULL) {
1420 TempCptr = GetSymbolValue ("FV_EXT");
1421 }
1422
1423 CFVAddFVFile (
1424 InLine,
1425 GetSymbolValue (COMPONENT_TYPE),
1426 GetSymbolValue (FV),
1427 Instance,
1428 TempCptr,
1429 Processor,
1430 GetSymbolValue (APRIORI),
1431 GetSymbolValue (BASE_NAME),
1432 Cptr
1433 );
1434 }
1435 //
1436 // Catch any failures and print the name of the component file
1437 // being processed to assist debugging.
1438 //
1439 ComponentDone:
1440
1441 Cptr = CatchException ();
1442 if (Cptr != NULL) {
1443 fprintf (stderr, "%s\n", Cptr);
1444 sprintf (InLine, "Processing of component %s failed", ArgLine);
1445 ThrowException (InLine);
1446 }
1447
1448 if (MakeFptr != NULL) {
1449 fclose (MakeFptr);
1450 }
1451
1452 if (ComponentCreated) {
1453 DSCFileDestroy (&ComponentFile);
1454 }
1455
1456 return STATUS_SUCCESS;
1457 }
1458
1459 static
1460 int
1461 CreatePackageFile (
1462 DSC_FILE *DSCFile
1463 )
1464 {
1465 INT8 *Package;
1466 SECTION *TempSect;
1467 INT8 Str[MAX_LINE_LEN];
1468 INT8 StrExpanded[MAX_LINE_LEN];
1469 SMART_FILE *PkgFptr;
1470 int Status;
1471
1472 PkgFptr = NULL;
1473
1474 //
1475 // First find out if PACKAGE_FILENAME or PACKAGE is defined. PACKAGE_FILENAME
1476 // is used to specify the exact package file to use. PACKAGE is used to
1477 // specify the package section name.
1478 //
1479 Package = GetSymbolValue (PACKAGE_FILENAME);
1480 if (Package != NULL) {
1481 //
1482 // Use existing file. We're done.
1483 //
1484 return STATUS_SUCCESS;
1485 }
1486 //
1487 // See if PACKAGE or PACKAGE_TAG is defined
1488 //
1489 Package = GetSymbolValue (PACKAGE);
1490 if (Package == NULL) {
1491 Package = GetSymbolValue (PACKAGE_TAG);
1492 }
1493
1494 if (Package == NULL) {
1495 //
1496 // Not defined either. Assume they are not using the package functionality
1497 // of this utility. However define the PACKAGE_FILENAME macro to the
1498 // best-guess value.
1499 //
1500 sprintf (
1501 Str,
1502 "%s\\%s.pkg",
1503 GetSymbolValue (SOURCE_DIR),
1504 GetSymbolValue (BASE_NAME)
1505 );
1506
1507 //
1508 // Expand symbols in the package filename
1509 //
1510 ExpandSymbols (Str, StrExpanded, sizeof (StrExpanded), EXPANDMODE_NO_UNDEFS);
1511
1512 AddSymbol (PACKAGE_FILENAME, StrExpanded, SYM_LOCAL | SYM_FILENAME);
1513 return STATUS_SUCCESS;
1514 }
1515 //
1516 // Save the position in the DSC file.
1517 // Find the [package.$(COMPONENT_TYPE).$(PACKAGE)] section in the DSC file
1518 //
1519 Status = STATUS_SUCCESS;
1520 DSCFileSavePosition (DSCFile);
1521 sprintf (Str, "%s.%s.%s", PACKAGE, GetSymbolValue (COMPONENT_TYPE), Package);
1522 TempSect = DSCFileFindSection (DSCFile, Str);
1523 if (TempSect != NULL) {
1524 //
1525 // So far so good. Create the name of the package file, then open it up
1526 // for writing. File name is c:\...\oem\platform\nt32\ia32\...\BaseName.pkg.
1527 //
1528 sprintf (
1529 Str,
1530 "%s\\%s.pkg",
1531 GetSymbolValue (DEST_DIR),
1532 GetSymbolValue (BASE_NAME)
1533 );
1534
1535 //
1536 // Expand symbols in the package filename
1537 //
1538 ExpandSymbols (Str, StrExpanded, sizeof (StrExpanded), EXPANDMODE_NO_UNDEFS);
1539
1540 //
1541 // Try to open the file, then save the file name as the PACKAGE_FILENAME
1542 // symbol for use elsewhere.
1543 //
1544 if ((PkgFptr = SmartOpen (StrExpanded)) == NULL) {
1545 Error (NULL, 0, 0, Str, "could not open package file for writing");
1546 Status = STATUS_ERROR;
1547 goto Finish;
1548 }
1549
1550 AddSymbol (PACKAGE_FILENAME, StrExpanded, SYM_LOCAL | SYM_FILENAME);
1551 //
1552 // Now read lines in from the DSC file and write them back out to the
1553 // package file (with string substitution).
1554 //
1555 while (DSCFileGetLine (DSCFile, Str, sizeof (Str)) != NULL) {
1556 //
1557 // Expand symbols, then write the line out to the package file
1558 //
1559 ExpandSymbols (Str, StrExpanded, sizeof (StrExpanded), EXPANDMODE_RECURSIVE);
1560 SmartWrite (PkgFptr, StrExpanded);
1561 }
1562 } else {
1563 Warning (
1564 NULL,
1565 0,
1566 0,
1567 NULL,
1568 "cannot locate package section [%s] in DSC file for %s",
1569 Str,
1570 GetSymbolValue (INF_FILENAME)
1571 );
1572 Status = STATUS_WARNING;
1573 goto Finish;
1574 }
1575
1576 if (PkgFptr != NULL) {
1577 SmartClose (PkgFptr);
1578 }
1579
1580 Finish:
1581 //
1582 // Restore the position in the DSC file
1583 //
1584 DSCFileRestorePosition (DSCFile);
1585
1586 return STATUS_SUCCESS;
1587 }
1588
1589 static
1590 int
1591 ProcessINFDefinesSection (
1592 DSC_FILE *ComponentFile
1593 )
1594 /*++
1595
1596 Routine Description:
1597
1598 Process the [defines.xxx] sections of the component description file. Process
1599 platform first, then processor. In this way, if a platform wants and override,
1600 that one gets parsed first, and later assignments do not overwrite the value.
1601
1602 Arguments:
1603
1604 ComponentFile - section info on the component file being processed
1605
1606 Returns:
1607
1608
1609 --*/
1610 {
1611 INT8 *Cptr;
1612 INT8 Str[MAX_LINE_LEN];
1613
1614 //
1615 // Find a [defines.$(PROCESSOR).$(PLATFORM)] section and process it
1616 //
1617 Cptr = GetSymbolValue (PLATFORM);
1618 if (Cptr != NULL) {
1619 sprintf (
1620 Str,
1621 "%s.%s.%s",
1622 DEFINES_SECTION_NAME,
1623 GetSymbolValue (PROCESSOR),
1624 Cptr
1625 );
1626 ProcessINFDefinesSectionSingle (ComponentFile, Str);
1627 }
1628 //
1629 // Find a [defines.$(PROCESSOR)] section and process it
1630 //
1631 sprintf (Str, "%s.%s", DEFINES_SECTION_NAME, GetSymbolValue (PROCESSOR));
1632 ProcessINFDefinesSectionSingle (ComponentFile, Str);
1633
1634 //
1635 // Find a [defines] section and process it
1636 //
1637 if (ProcessINFDefinesSectionSingle (ComponentFile, DEFINES_SECTION_NAME) != STATUS_SUCCESS) {
1638 Error (NULL, 0, 0, NULL, "missing [defines] section in component file %s", GetSymbolValue (INF_FILENAME));
1639 return STATUS_ERROR;
1640 }
1641
1642 return STATUS_SUCCESS;
1643 }
1644
1645 static
1646 int
1647 ProcessINFDefinesSectionSingle (
1648 DSC_FILE *ComponentFile,
1649 INT8 *SectionName
1650 )
1651 {
1652 INT8 *Cptr;
1653 INT8 Str[MAX_LINE_LEN];
1654 INT8 ExpandedLine[MAX_LINE_LEN];
1655 SECTION *TempSect;
1656
1657 TempSect = DSCFileFindSection (ComponentFile, SectionName);
1658 if (TempSect != NULL) {
1659 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) {
1660 ExpandSymbols (Str, ExpandedLine, sizeof (ExpandedLine), 0);
1661 Cptr = StripLine (ExpandedLine);
1662 //
1663 // Don't process blank lines.
1664 //
1665 if (*Cptr) {
1666 //
1667 // Add without overwriting macros specified on the component line
1668 // in the description file
1669 //
1670 AddSymbol (Cptr, NULL, SYM_LOCAL);
1671 }
1672 }
1673 } else {
1674 return STATUS_WARNING;
1675 }
1676
1677 return STATUS_SUCCESS;
1678 }
1679
1680 static
1681 int
1682 ProcessINFNMakeSection (
1683 DSC_FILE *ComponentFile,
1684 FILE *MakeFptr
1685 )
1686 /*++
1687
1688 Routine Description:
1689
1690 Process the [nmake.common] and [nmake.$(PROCESSOR)] sections of the component
1691 description file and write and copy them to the component's makefile.
1692
1693 Arguments:
1694
1695 ComponentFile - section info on the component file being processed
1696 MakeFptr - file pointer to the component' makefile we're creating
1697
1698 Returns:
1699
1700 Always STATUS_SUCCESS right now, since the sections are optional.
1701
1702 --*/
1703 {
1704 INT8 *Cptr;
1705 INT8 Str[MAX_LINE_LEN];
1706 INT8 ExpandedLine[MAX_LINE_LEN];
1707 SECTION *TempSect;
1708
1709 //
1710 // Copy the [nmake.common] and [nmake.$(PROCESSOR)] sections from the
1711 // component file directly to the output file.
1712 // The line will be stripped and don't print blank lines
1713 //
1714 sprintf (Str, "%s.%s", NMAKE_SECTION_NAME, COMMON_SECTION_NAME);
1715 TempSect = DSCFileFindSection (ComponentFile, Str);
1716 if (TempSect != NULL) {
1717 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) {
1718 ExpandSymbols (
1719 Str,
1720 ExpandedLine,
1721 sizeof (ExpandedLine),
1722 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR
1723 );
1724 Cptr = StripLine (ExpandedLine);
1725 if (*Cptr) {
1726 fprintf (MakeFptr, "%s\n", Cptr);
1727 }
1728 }
1729
1730 fprintf (MakeFptr, "\n");
1731 } else {
1732 Error (GetSymbolValue (INF_FILENAME), 1, 0, Str, "section not found in component INF file");
1733 }
1734
1735 sprintf (Str, "%s.%s", NMAKE_SECTION_NAME, GetSymbolValue (PROCESSOR));
1736 TempSect = DSCFileFindSection (ComponentFile, Str);
1737 if (TempSect != NULL) {
1738 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) {
1739 ExpandSymbols (
1740 Str,
1741 ExpandedLine,
1742 sizeof (ExpandedLine),
1743 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR
1744 );
1745 Cptr = StripLine (ExpandedLine);
1746 if (*Cptr) {
1747 fprintf (MakeFptr, "%s\n", Cptr);
1748 }
1749 }
1750
1751 fprintf (MakeFptr, "\n");
1752 }
1753 //
1754 // Do the same for [nmake.$(PROCESSOR).$(PLATFORM)]
1755 //
1756 Cptr = GetSymbolValue (PLATFORM);
1757 if (Cptr != NULL) {
1758 sprintf (Str, "%s.%s.%s", NMAKE_SECTION_NAME, GetSymbolValue (PROCESSOR), Cptr);
1759 TempSect = DSCFileFindSection (ComponentFile, Str);
1760 if (TempSect != NULL) {
1761 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) {
1762 ExpandSymbols (
1763 Str,
1764 ExpandedLine,
1765 sizeof (ExpandedLine),
1766 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR
1767 );
1768 Cptr = StripLine (ExpandedLine);
1769 if (*Cptr) {
1770 fprintf (MakeFptr, "%s\n", Cptr);
1771 }
1772 }
1773
1774 fprintf (MakeFptr, "\n");
1775 }
1776 }
1777
1778 return STATUS_SUCCESS;
1779 }
1780
1781 static
1782 int
1783 ProcessIncludesSection (
1784 DSC_FILE *ComponentFile,
1785 FILE *MakeFptr
1786 )
1787 /*++
1788
1789 Routine Description:
1790
1791 Process the [includes.common], [includes.processor], and
1792 [includes.processor.platform] section of the component description file
1793 and write the appropriate macros to the component's makefile.
1794
1795 Process in reverse order to allow overrides on platform basis.
1796
1797 Arguments:
1798
1799 ComponentFile - section info on the component file being processed
1800 MakeFptr - file pointer to the component' makefile we're creating
1801
1802 Returns:
1803
1804 Always STATUS_SUCCESS right now, since the sections are optional.
1805
1806 --*/
1807 {
1808 INT8 *Cptr;
1809 INT8 Str[MAX_LINE_LEN];
1810 INT8 *Processor;
1811 INT8 *OverridePath;
1812
1813 //
1814 // Write a useful comment to the output makefile so the user knows where
1815 // the data came from.
1816 //
1817 fprintf (MakeFptr, "#\n# Tool-generated list of include paths that are created\n");
1818 fprintf (MakeFptr, "# from the list of include paths in the [includes.*] sections\n");
1819 fprintf (MakeFptr, "# of the component INF file.\n#\n");
1820
1821 //
1822 // We use this a lot here, so get the value only once.
1823 //
1824 Processor = GetSymbolValue (PROCESSOR);
1825 //
1826 // If they're using an override source path, then add OverridePath and
1827 // OverridePath\$(PROCESSOR) to the list of include paths.
1828 //
1829 OverridePath = GetSymbolValue (SOURCE_OVERRIDE_PATH);
1830 if (OverridePath != NULL) {
1831 ReplaceSlash (OverridePath);
1832 fprintf (MakeFptr, "INC = $(INC) -I %s\n", OverridePath);
1833 fprintf (MakeFptr, "INC = $(INC) -I %s\\%s \n", OverridePath, Processor);
1834 }
1835 //
1836 // Try for an [includes.$(PROCESSOR).$(PLATFORM)]
1837 //
1838 Cptr = GetSymbolValue (PLATFORM);
1839 if (Cptr != NULL) {
1840 sprintf (Str, "%s.%s.%s", INCLUDE_SECTION_NAME, Processor, Cptr);
1841 ProcessIncludesSectionSingle (ComponentFile, MakeFptr, Str);
1842 }
1843 //
1844 // Now the [includes.$(PROCESSOR)] section
1845 //
1846 sprintf (Str, "%s.%s", INCLUDE_SECTION_NAME, Processor);
1847 ProcessIncludesSectionSingle (ComponentFile, MakeFptr, Str);
1848
1849 //
1850 // Now the [includes.common] section
1851 //
1852 sprintf (Str, "%s.%s", INCLUDE_SECTION_NAME, COMMON_SECTION_NAME);
1853 ProcessIncludesSectionSingle (ComponentFile, MakeFptr, Str);
1854
1855 //
1856 // Done
1857 //
1858 fprintf (MakeFptr, "\n");
1859 return STATUS_SUCCESS;
1860 }
1861 //
1862 // Process one of the [includes.xxx] sections to create a list of all
1863 // the include paths.
1864 //
1865 static
1866 int
1867 ProcessIncludesSectionSingle (
1868 DSC_FILE *ComponentFile,
1869 FILE *MakeFptr,
1870 INT8 *SectionName
1871 )
1872 {
1873 INT8 *Cptr;
1874 SECTION *TempSect;
1875 INT8 Str[MAX_LINE_LEN];
1876 INT8 ExpandedLine[MAX_LINE_LEN];
1877 INT8 *Processor;
1878
1879 TempSect = DSCFileFindSection (ComponentFile, SectionName);
1880 if (TempSect != NULL) {
1881 //
1882 // Add processor subdirectory on every include path
1883 //
1884 Processor = GetSymbolValue (PROCESSOR);
1885 //
1886 // Copy lines directly
1887 //
1888 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) {
1889 ExpandSymbols (Str, ExpandedLine, sizeof (ExpandedLine), 0);
1890 Cptr = StripLine (ExpandedLine);
1891 //
1892 // Don't process blank lines
1893 //
1894 if (*Cptr) {
1895 ReplaceSlash (Cptr);
1896 //
1897 // Strip off trailing slash
1898 //
1899 if (Cptr[strlen (Cptr) - 1] == '\\') {
1900 Cptr[strlen (Cptr) - 1] = 0;
1901 }
1902 //
1903 // Special case of ".". Replace it with source path
1904 // and the rest of the line (for .\$(PROCESSOR))
1905 //
1906 if (*Cptr == '.') {
1907 //
1908 // Handle case of just a "."
1909 //
1910 if (Cptr[1] == 0) {
1911 fprintf (MakeFptr, "INC = $(INC) -I $(SOURCE_DIR)\n");
1912 fprintf (
1913 MakeFptr,
1914 "INC = $(INC) -I $(SOURCE_DIR)\\%s \n",
1915 Processor
1916 );
1917 } else {
1918 //
1919 // Handle case of ".\path\path\path" or "..\path\path\path"
1920 //
1921 fprintf (
1922 MakeFptr,
1923 "INC = $(INC) -I $(SOURCE_DIR)\\%s \n",
1924 Cptr
1925 );
1926 fprintf (
1927 MakeFptr,
1928 "INC = $(INC) -I $(SOURCE_DIR)\\%s\\%s \n",
1929 Cptr,
1930 Processor
1931 );
1932 }
1933 } else if ((Cptr[1] != ':') && isalpha (*Cptr)) {
1934 fprintf (MakeFptr, "INC = $(INC) -I $(EFI_SOURCE)\\%s \n", Cptr);
1935 fprintf (
1936 MakeFptr,
1937 "INC = $(INC) -I $(EFI_SOURCE)\\%s\\%s \n",
1938 Cptr,
1939 Processor
1940 );
1941 } else {
1942 //
1943 // The line is something like: $(EFI_SOURCE)\dxe\include. Add it to
1944 // the existing $(INC) definition. Add user includes before any
1945 // other existing paths.
1946 //
1947 fprintf (MakeFptr, "INC = $(INC) -I %s \n", Cptr);
1948 fprintf (MakeFptr, "INC = $(INC) -I %s\\%s \n", Cptr, Processor);
1949 }
1950 }
1951 }
1952 }
1953
1954 return STATUS_SUCCESS;
1955 }
1956
1957 static
1958 int
1959 ProcessSourceFiles (
1960 DSC_FILE *DSCFile,
1961 DSC_FILE *ComponentFile,
1962 FILE *MakeFptr,
1963 UINT32 Mode
1964 )
1965 /*++
1966
1967 Routine Description:
1968
1969 Process the [sources.common], [sources.$(PROCESSOR)], and
1970 [sources.$(PROCESSOR).$(PLATFORM] sections of the component
1971 description file and write the appropriate build commands out to the
1972 component's makefile. If $(SOURCE_SELECT) is defined, then it overrides
1973 the source selections. We use this functionality for SMM.
1974
1975 Arguments:
1976
1977 ComponentFile - section info on the component file being processed
1978 MakeFptr - file pointer to the component' makefile we're creating
1979 DSCFile - section info on the description file we're processing
1980 Mode - to write build commands, or just create a list
1981 of sources.
1982
1983 Returns:
1984
1985 Always STATUS_SUCCESS right now, since the sections are optional.
1986
1987 --*/
1988 {
1989 INT8 Str[MAX_LINE_LEN];
1990 INT8 *Processor;
1991 INT8 *Platform;
1992 INT8 *SourceSelect;
1993 INT8 *CStart;
1994 INT8 *CEnd;
1995 INT8 CSave;
1996 INT8 *CopySourceSelect;
1997
1998 if (Mode & SOURCE_MODE_SOURCE_FILES) {
1999 //
2000 // Write a useful comment to the output makefile so the user knows where
2001 // the data came from.
2002 //
2003 fprintf (MakeFptr, "#\n# Tool-generated list of source files that are created\n");
2004 fprintf (MakeFptr, "# from the list of source files in the [sources.*] sections\n");
2005 fprintf (MakeFptr, "# of the component INF file.\n#\n");
2006 }
2007
2008 //
2009 // We use this a lot here, so get the value only once.
2010 //
2011 Processor = GetSymbolValue (PROCESSOR);
2012 //
2013 // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll
2014 // select each [sources.xxx] and [sources.yyy] files and process
2015 // them.
2016 //
2017 SourceSelect = GetSymbolValue (SOURCE_SELECT);
2018
2019 if (SourceSelect != NULL) {
2020 //
2021 // Make a copy of the string and break it up (comma-separated) and
2022 // select each [sources.*] file from the INF.
2023 //
2024 CopySourceSelect = (INT8 *) malloc (strlen (SourceSelect) + 1);
2025 if (CopySourceSelect == NULL) {
2026 Error (NULL, 0, 0, NULL, "failed to allocate memory");
2027 return STATUS_ERROR;
2028 }
2029
2030 strcpy (CopySourceSelect, SourceSelect);
2031 CStart = CopySourceSelect;
2032 CEnd = CStart;
2033 while (*CStart) {
2034 CEnd = CStart + 1;
2035 while (*CEnd && *CEnd != ',') {
2036 CEnd++;
2037 }
2038
2039 CSave = *CEnd;
2040 *CEnd = 0;
2041 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, CStart);
2042 ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode);
2043 //
2044 // Restore the terminator and advance
2045 //
2046 *CEnd = CSave;
2047 CStart = CEnd;
2048 if (*CStart) {
2049 CStart++;
2050 }
2051 }
2052
2053 free (CopySourceSelect);
2054
2055 } else {
2056 //
2057 // Process all the [sources.common] source files to make them build
2058 //
2059 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, COMMON_SECTION_NAME);
2060 ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode);
2061 //
2062 // Now process the [sources.$(PROCESSOR)] files.
2063 //
2064 sprintf (Str, "sources.%s", Processor);
2065 ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode);
2066 //
2067 // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files.
2068 //
2069 Platform = GetSymbolValue (PLATFORM);
2070 if (Platform != NULL) {
2071 sprintf (Str, "sources.%s.%s", Processor, Platform);
2072 ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode);
2073 }
2074 }
2075
2076 fprintf (MakeFptr, "\n");
2077 return STATUS_SUCCESS;
2078 }
2079
2080 /*++
2081
2082 Routine Description:
2083 Given a source file line from an INF file, parse it to see if there are
2084 any defines on it. If so, then add them to the symbol table.
2085 Also, terminate the line after the file name.
2086
2087 Arguments:
2088 SourceFileLine - a line from a [sources.?] section of the INF file. Likely
2089 something like:
2090
2091 MySourceFile.c BUILT_NAME=$(BUILD_DIR)\MySourceFile.obj
2092
2093 Returns:
2094 Nothing.
2095
2096 --*/
2097 static
2098 void
2099 AddFileSymbols (
2100 INT8 *SourceFileLine
2101 )
2102 {
2103 int Len;
2104 //
2105 // Skip spaces
2106 //
2107 for (; *SourceFileLine && isspace (*SourceFileLine); SourceFileLine++)
2108 ;
2109 for (; *SourceFileLine && !isspace (*SourceFileLine); SourceFileLine++)
2110 ;
2111 if (*SourceFileLine) {
2112 *SourceFileLine = 0;
2113 SourceFileLine++;
2114 //
2115 // AddSymbol() will parse it for us, and return the length. Keep calling
2116 // it until it reports an error or is done.
2117 //
2118 do {
2119 Len = AddSymbol (SourceFileLine, NULL, SYM_FILE);
2120 SourceFileLine += Len;
2121 } while (Len > 0);
2122 }
2123 }
2124 //
2125 // Process a single section of source files in the component INF file
2126 //
2127 static
2128 int
2129 ProcessSourceFilesSection (
2130 DSC_FILE *DSCFile,
2131 DSC_FILE *ComponentFile,
2132 FILE *MakeFptr,
2133 INT8 *SectionName,
2134 UINT32 Mode
2135 )
2136 {
2137 INT8 *Cptr;
2138 INT8 FileName[MAX_EXP_LINE_LEN];
2139 INT8 FilePath[MAX_PATH];
2140 INT8 TempFileName[MAX_PATH];
2141 SECTION *TempSect;
2142 INT8 Str[MAX_LINE_LEN];
2143 INT8 *Processor;
2144 INT8 *OverridePath;
2145 FILE *FPtr;
2146
2147 TempSect = DSCFileFindSection (ComponentFile, SectionName);
2148 if (TempSect != NULL) {
2149 Processor = GetSymbolValue (PROCESSOR);
2150 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) {
2151 Cptr = StripLine (Str);
2152 //
2153 // Don't process blank lines
2154 //
2155 if (*Cptr) {
2156 //
2157 // Expand symbols in the filename, then parse the line for symbol
2158 // definitions. AddFileSymbols() will null-terminate the line
2159 // after the file name. Save a copy for override purposes, in which
2160 // case we'll need to know the file name and path (in case it's in
2161 // a subdirectory).
2162 //
2163 ExpandSymbols (Cptr, FileName, sizeof (FileName), 0);
2164 AddFileSymbols (FileName);
2165 ReplaceSlash (FileName);
2166 //
2167 // Set the SOURCE_FILE_NAME symbol. What we have now is the name of
2168 // the file, relative to the location of the INF file. So prepend
2169 // $(SOURCE_DIR) to it first.
2170 //
2171 if (IsAbsolutePath (FileName)) {
2172 strcpy (TempFileName, FileName);
2173 } else {
2174 strcpy (TempFileName, "$(SOURCE_DIR)\\");
2175 strcat (TempFileName, FileName);
2176 }
2177 AddSymbol (SOURCE_FILE_NAME, TempFileName, SYM_FILE | SYM_OVERWRITE);
2178 //
2179 // Extract path information from the source file and set internal
2180 // variable SOURCE_RELATIVE_PATH. Only do this if the path
2181 // contains a backslash.
2182 //
2183 strcpy (FilePath, FileName);
2184 for (Cptr = FilePath + strlen (FilePath) - 1; (Cptr > FilePath) && (*Cptr != '\\'); Cptr--)
2185 ;
2186 if (*Cptr == '\\') {
2187 *(Cptr + 1) = 0;
2188 AddSymbol (SOURCE_RELATIVE_PATH, FilePath, SYM_FILE);
2189 }
2190 //
2191 // Define another internal symbol for the name of the file without
2192 // the path and extension.
2193 //
2194 for (Cptr = FileName + strlen (FileName) - 1; (Cptr > FileName) && (*Cptr != '\\'); Cptr--)
2195 ;
2196 if (*Cptr == '\\') {
2197 Cptr++;
2198 }
2199
2200 strcpy (FilePath, Cptr);
2201 //
2202 // We now have a file name with no path information. Before we do anything else,
2203 // see if OVERRIDE_PATH is set, and if so, see if file $(OVERRIDE_PATH)FileName
2204 // exists. If it does, then recursive call this function to use the override file
2205 // instead of the one from the INF file.
2206 //
2207 if (IsAbsolutePath (FileName)) {
2208 OverridePath = NULL;
2209 } else {
2210 OverridePath = GetSymbolValue (SOURCE_OVERRIDE_PATH);
2211 }
2212 if (OverridePath != NULL) {
2213 ReplaceSlash (OverridePath);
2214 //
2215 // See if the file exists. If it does, reset the SOURCE_FILE_NAME symbol.
2216 //
2217 strcpy (TempFileName, OverridePath);
2218 strcat (TempFileName, "\\");
2219 strcat (TempFileName, FileName);
2220 if ((FPtr = fopen (TempFileName, "rb")) != NULL) {
2221 fclose (FPtr);
2222 AddSymbol (SOURCE_FILE_NAME, TempFileName, SYM_FILE | SYM_OVERWRITE);
2223 //
2224 // Print a message. This function is called to create build commands
2225 // for source files, and to create a macro of all source files. Therefore
2226 // do this check so we don't print the override message multiple times.
2227 //
2228 if (Mode & SOURCE_MODE_BUILD_COMMANDS) {
2229 fprintf (stdout, "Override: %s\n", TempFileName);
2230 }
2231 } else {
2232 //
2233 // Set override path to null to use as a flag below
2234 //
2235 OverridePath = NULL;
2236 }
2237 }
2238
2239 //
2240 // Start at the end and work back
2241 //
2242 for (Cptr = FilePath + strlen (FilePath) - 1; (Cptr > FilePath) && (*Cptr != '\\') && (*Cptr != '.'); Cptr--)
2243 ;
2244 if (*Cptr == '.') {
2245 *Cptr = 0;
2246 AddSymbol (SOURCE_FILE_EXTENSION, Cptr + 1, SYM_FILE);
2247 }
2248
2249 AddSymbol (SOURCE_BASE_NAME, FilePath, SYM_FILE);
2250 //
2251 // If we're just creating the SOURCE_FILES macro, then write the
2252 // file name out to the makefile.
2253 //
2254 if (Mode & SOURCE_MODE_SOURCE_FILES) {
2255 //
2256 // If we're processing an override file, then use the file name as-is
2257 //
2258 if (OverridePath != NULL) {
2259 //
2260 // SOURCE_FILES = $(SOURCE_FILES) c:\Path\ThisFile.c
2261 //
2262 fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) %s\n", TempFileName);
2263 } else if (IsAbsolutePath (FileName)) {
2264 //
2265 // For Absolute path, don't print $(SOURCE_FILE) directory.
2266 //
2267 fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) %s\n", FileName);
2268 } else {
2269 //
2270 // SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\ThisFile.c
2271 //
2272 fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\\%s\n", FileName);
2273 }
2274 } else if (Mode & SOURCE_MODE_BUILD_COMMANDS) {
2275 //
2276 // Write the build commands for this file per the build commands
2277 // for this file type as defined in the description file.
2278 // Also create the directory for it in the build path.
2279 //
2280 WriteCompileCommands (DSCFile, MakeFptr, FileName, Processor);
2281 if (!IsAbsolutePath (FileName)) {
2282 sprintf (Str, "%s\\%s", GetSymbolValue (DEST_DIR), FileName);
2283 MakeFilePath (Str);
2284 //
2285 // Get all output directory for build output files.
2286 //
2287 Cptr = FileName + strlen (FileName) - 1;
2288 for (; (Cptr > FileName) && (*Cptr != '\\'); Cptr--);
2289 if (*Cptr == '\\') {
2290 *Cptr = '\0';
2291 AddModuleName (&gGlobals.OutdirList, FileName, NULL);
2292 }
2293 }
2294 }
2295 //
2296 // Remove file-level symbols
2297 //
2298 RemoveFileSymbols ();
2299 }
2300 }
2301 }
2302
2303 return STATUS_SUCCESS;
2304 }
2305 //
2306 // Process the INF [sources.*] sections and emit the OBJECTS = .....
2307 // lines to the component's makefile.
2308 //
2309 static
2310 int
2311 ProcessObjects (
2312 DSC_FILE *ComponentFile,
2313 FILE *MakeFptr
2314 )
2315 {
2316 INT8 Str[MAX_LINE_LEN];
2317 INT8 *Processor;
2318 INT8 *Platform;
2319 INT8 *SourceSelect;
2320 INT8 *CStart;
2321 INT8 *CEnd;
2322 INT8 CSave;
2323 INT8 *CopySourceSelect;
2324 SYMBOL *TempSymbol;
2325
2326 //
2327 // Write a useful comment to the output makefile so the user knows where
2328 // the data came from.
2329 //
2330 fprintf (MakeFptr, "#\n# Tool-generated list of object files that are created\n");
2331 fprintf (MakeFptr, "# from the list of source files in the [sources.*] sections\n");
2332 fprintf (MakeFptr, "# of the component INF file.\n#\n");
2333 //
2334 // We use this a lot here, so get the value only once.
2335 //
2336 Processor = GetSymbolValue (PROCESSOR);
2337 //
2338 // Now define the OBJECTS variable and assign it to be all the object files we're going
2339 // to create. Afterwards create a pseudo-target objects to let the user quickly just compile
2340 // the source files. This means we need to process all the common objects and
2341 // processor-specific objects again.
2342 //
2343 fprintf (MakeFptr, "OBJECTS = $(OBJECTS) ");
2344 //
2345 // See if they defined SOURCE_SELECT=xxx,yyy in which case well
2346 // select each [sources.xxx] and [sources.yyy] files and process
2347 // them.
2348 //
2349 SourceSelect = GetSymbolValue (SOURCE_SELECT);
2350
2351 if (SourceSelect != NULL) {
2352 //
2353 // Make a copy of the string and break it up (comma-separated) and
2354 // select each [sources.*] file from the INF.
2355 //
2356 CopySourceSelect = (INT8 *) malloc (strlen (SourceSelect) + 1);
2357 if (CopySourceSelect == NULL) {
2358 Error (NULL, 0, 0, NULL, "failed to allocate memory");
2359 return STATUS_ERROR;
2360 }
2361
2362 strcpy (CopySourceSelect, SourceSelect);
2363 CStart = CopySourceSelect;
2364 CEnd = CStart;
2365 while (*CStart) {
2366 CEnd = CStart + 1;
2367 while (*CEnd && *CEnd != ',') {
2368 CEnd++;
2369 }
2370
2371 CSave = *CEnd;
2372 *CEnd = 0;
2373 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, CStart);
2374 ProcessObjectsSingle (ComponentFile, MakeFptr, Str);
2375 //
2376 // Restore the terminator and advance
2377 //
2378 *CEnd = CSave;
2379 CStart = CEnd;
2380 if (*CStart) {
2381 CStart++;
2382 }
2383 }
2384
2385 free (CopySourceSelect);
2386
2387 } else {
2388 //
2389 // Now process all the [sources.common] files and emit build commands for them
2390 //
2391 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, COMMON_SECTION_NAME);
2392 if (ProcessObjectsSingle (ComponentFile, MakeFptr, Str) != STATUS_SUCCESS) {
2393 Warning (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "no [%s] section found in component description", Str);
2394 }
2395 //
2396 // Now process any processor-specific source files in [sources.$(PROCESSOR)]
2397 //
2398 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, Processor);
2399 ProcessObjectsSingle (ComponentFile, MakeFptr, Str);
2400
2401 //
2402 // Now process any [sources.$(PROCESSOR).$(PLATFORM)] files
2403 //
2404 Platform = GetSymbolValue (PLATFORM);
2405 if (Platform != NULL) {
2406 sprintf (Str, "sources.%s.%s", Processor, Platform);
2407 ProcessObjectsSingle (ComponentFile, MakeFptr, Str);
2408 }
2409 }
2410
2411 fprintf (MakeFptr, "\n\n");
2412
2413 //
2414 // Write a useful comment to the output makefile so the user knows where
2415 // the data came from.
2416 //
2417 fprintf (MakeFptr, "#\n# Tool-generated list of dest output dirs that are created\n");
2418 fprintf (MakeFptr, "# from the list of source files in the [sources.*] sections\n");
2419 fprintf (MakeFptr, "# of the component INF file.\n#\n");
2420 //
2421 // Create output directory list
2422 // for clean target to delete all build output files.
2423 //
2424 fprintf (MakeFptr, "DEST_OUTPUT_DIRS = $(%s) ", DEST_DIR);
2425
2426 TempSymbol = gGlobals.OutdirList;
2427 while (TempSymbol != NULL) {
2428 fprintf (MakeFptr, "\\\n $(%s)\\%s ",
2429 DEST_DIR, TempSymbol->Name);
2430 TempSymbol = TempSymbol->Next;
2431 }
2432 fprintf (MakeFptr, "\n\n");
2433
2434 //
2435 // clean up for the next module
2436 //
2437 FreeSymbols (gGlobals.OutdirList);
2438 gGlobals.OutdirList = NULL;
2439
2440 return STATUS_SUCCESS;
2441 }
2442
2443 static
2444 INT8 *
2445 BuiltFileExtension (
2446 INT8 *SourceFileName
2447 )
2448 {
2449 int i;
2450 INT8 *Cptr;
2451 //
2452 // Find the dot in the filename extension
2453 //
2454 for (Cptr = SourceFileName + strlen (SourceFileName) - 1;
2455 (Cptr > SourceFileName) && (*Cptr != '\\') && (*Cptr != '.');
2456 Cptr--
2457 ) {
2458 //
2459 // Do nothing
2460 //
2461 }
2462
2463 if (*Cptr != '.') {
2464 return NULL;
2465 }
2466 //
2467 // Look through our list of known file types and return a pointer to
2468 // its built file extension.
2469 //
2470 for (i = 0; mFileTypes[i].Extension != NULL; i++) {
2471 if (_stricmp (Cptr, mFileTypes[i].Extension) == 0) {
2472 return mFileTypes[i].BuiltExtension;
2473 }
2474 }
2475
2476 return NULL;
2477 }
2478
2479 int
2480 ProcessObjectsSingle (
2481 DSC_FILE *ComponentFile,
2482 FILE *MakeFptr,
2483 INT8 *SectionName
2484 )
2485 {
2486 INT8 *Cptr;
2487 INT8 *Cptr2;
2488 INT8 Str[MAX_LINE_LEN];
2489 INT8 FileName[MAX_EXP_LINE_LEN];
2490 SECTION *TempSect;
2491
2492 TempSect = DSCFileFindSection (ComponentFile, SectionName);
2493 if (TempSect != NULL) {
2494 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) {
2495 Cptr = StripLine (Str);
2496 //
2497 // Don't process blank lines
2498 //
2499 if (*Cptr) {
2500 //
2501 // Expand symbols then create the output filename. We'll do a lookup
2502 // on the source file's extension to determine what the extension of
2503 // the built version of the file is. For example, .c -> .obj.
2504 //
2505 if (!IsIncludeFile (Cptr)) {
2506 ExpandSymbols (Cptr, FileName, sizeof (FileName), 0);
2507 ReplaceSlash (FileName);
2508 Cptr2 = BuiltFileExtension (FileName);
2509 if (Cptr2 != NULL) {
2510 SetFileExtension (FileName, Cptr2);
2511 if (!IsAbsolutePath (FileName)) {
2512 fprintf (MakeFptr, "\\\n $(%s)\\%s ", DEST_DIR, FileName);
2513 } else {
2514 fprintf (MakeFptr, "\\\n %s ", FileName);
2515 }
2516 }
2517 }
2518 }
2519 }
2520 } else {
2521 return STATUS_WARNING;
2522 }
2523
2524 return STATUS_SUCCESS;
2525 }
2526 //
2527 // Process all [libraries.*] sections in the component INF file to create a
2528 // macro to the component's output makefile: LIBS = Lib1 Lib2, ...
2529 //
2530 static
2531 int
2532 ProcessLibs (
2533 DSC_FILE *ComponentFile,
2534 FILE *MakeFptr
2535 )
2536 {
2537 INT8 Str[MAX_LINE_LEN];
2538 INT8 *Processor;
2539 INT8 *Platform;
2540
2541 //
2542 // Print a useful comment to the component's makefile so the user knows
2543 // where the data came from.
2544 //
2545 fprintf (MakeFptr, "#\n# Tool-generated list of libraries that are generated\n");
2546 fprintf (MakeFptr, "# from the list of libraries listed in the [libraries.*] sections\n");
2547 fprintf (MakeFptr, "# of the component INF file.\n#\n");
2548
2549 fprintf (MakeFptr, "LIBS = $(LIBS) ");
2550
2551 Processor = GetSymbolValue (PROCESSOR);
2552 //
2553 // Process [libraries.common] files
2554 //
2555 sprintf (Str, "%s.%s", LIBRARIES_SECTION_NAME, COMMON_SECTION_NAME);
2556 ProcessLibsSingle (ComponentFile, MakeFptr, Str);
2557 //
2558 // Process the [libraries.$(PROCESSOR)] libraries to define "LIBS = x.lib y.lib..."
2559 //
2560 sprintf (Str, "%s.%s", LIBRARIES_SECTION_NAME, Processor);
2561 ProcessLibsSingle (ComponentFile, MakeFptr, Str);
2562 //
2563 // Now process any [libraries.$(PROCESSOR).$(PLATFORM)] files
2564 //
2565 Platform = GetSymbolValue (PLATFORM);
2566 if (Platform != NULL) {
2567 sprintf (Str, "%s.%s.%s", LIBRARIES_SECTION_NAME, Processor, Platform);
2568 ProcessLibsSingle (ComponentFile, MakeFptr, Str);
2569 }
2570 //
2571 // Process any [libraries.platform] files
2572 //
2573 ProcessLibsSingle (ComponentFile, MakeFptr, LIBRARIES_PLATFORM_SECTION_NAME);
2574
2575 fprintf (MakeFptr, "\n\n");
2576 return STATUS_SUCCESS;
2577 }
2578
2579 static
2580 int
2581 ProcessLibsSingle (
2582 DSC_FILE *ComponentFile,
2583 FILE *MakeFptr,
2584 INT8 *SectionName
2585 )
2586 {
2587 INT8 *Cptr;
2588 INT8 Str[MAX_LINE_LEN];
2589 INT8 ExpandedLine[MAX_LINE_LEN];
2590 SECTION *TempSect;
2591
2592 TempSect = DSCFileFindSection (ComponentFile, SectionName);
2593 if (TempSect != NULL) {
2594 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) {
2595 ExpandSymbols (Str, ExpandedLine, sizeof (ExpandedLine), 0);
2596 Cptr = StripLine (ExpandedLine);
2597 //
2598 // Don't process blank lines
2599 //
2600 if (*Cptr) {
2601 if (Cptr[strlen (Cptr) - 4] != '.') {
2602 fprintf (MakeFptr, " \\\n $(LIB_DIR)\\%s.lib", Cptr);
2603 //
2604 // Add lib dependency for single module build
2605 //
2606 fprintf (gGlobals.ModuleMakefileFptr, " %sbuild", Cptr);
2607 } else {
2608 fprintf (MakeFptr, " \\\n $(LIB_DIR)\\%s", Cptr);
2609 //
2610 // Add lib dependency for single module build
2611 //
2612 Cptr[strlen (Cptr) - 4] = 0;
2613 fprintf (gGlobals.ModuleMakefileFptr, " %sbuild", Cptr);
2614 }
2615 }
2616 }
2617 }
2618
2619 return STATUS_SUCCESS;
2620 }
2621
2622 static
2623 int
2624 ProcessIncludeFiles (
2625 DSC_FILE *ComponentFile,
2626 FILE *MakeFptr
2627 )
2628 {
2629 INT8 Str[MAX_LINE_LEN];
2630 INT8 *Processor;
2631 INT8 *Platform;
2632 INT8 *SourceSelect;
2633 INT8 *CStart;
2634 INT8 *CEnd;
2635 INT8 CSave;
2636 INT8 *CopySourceSelect;
2637
2638 //
2639 // Print a useful comment to the output makefile so the user knows where
2640 // the info came from
2641 //
2642 //fprintf (MakeFptr, "#\n# Tool-generated include dependencies from any include files in the\n");
2643 //fprintf (MakeFptr, "# [sources.*] sections of the component INF file\n#\n");
2644
2645 Processor = GetSymbolValue (PROCESSOR);
2646
2647 //
2648 // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll
2649 // select each [sources.xxx] and [sources.yyy] files and process
2650 // them.
2651 //
2652 SourceSelect = GetSymbolValue (SOURCE_SELECT);
2653
2654 if (SourceSelect != NULL) {
2655 //
2656 // Make a copy of the string and break it up (comma-separated) and
2657 // select each [sources.*] file from the INF.
2658 //
2659 CopySourceSelect = (INT8 *) malloc (strlen (SourceSelect) + 1);
2660 if (CopySourceSelect == NULL) {
2661 Error (NULL, 0, 0, NULL, "failed to allocate memory");
2662 return STATUS_ERROR;
2663 }
2664
2665 strcpy (CopySourceSelect, SourceSelect);
2666 CStart = CopySourceSelect;
2667 CEnd = CStart;
2668 while (*CStart) {
2669 CEnd = CStart + 1;
2670 while (*CEnd && *CEnd != ',') {
2671 CEnd++;
2672 }
2673
2674 CSave = *CEnd;
2675 *CEnd = 0;
2676 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, CStart);
2677 ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str);
2678 //
2679 // Restore the terminator and advance
2680 //
2681 *CEnd = CSave;
2682 CStart = CEnd;
2683 if (*CStart) {
2684 CStart++;
2685 }
2686 }
2687
2688 free (CopySourceSelect);
2689
2690 } else {
2691 //
2692 // Find all the include files in the [sources.common] sections.
2693 //
2694 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, COMMON_SECTION_NAME);
2695 ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str);
2696 //
2697 // Now process the [sources.$(PROCESSOR)] files.
2698 //
2699 sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, Processor);
2700 ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str);
2701 //
2702 // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files.
2703 //
2704 Platform = GetSymbolValue (PLATFORM);
2705 if (Platform != NULL) {
2706 sprintf (Str, "sources.%s.%s", Processor, Platform);
2707 ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str);
2708 }
2709 }
2710
2711 fprintf (MakeFptr, "\n");
2712 return STATUS_SUCCESS;
2713 }
2714
2715 int
2716 ProcessIncludeFilesSingle (
2717 DSC_FILE *ComponentFile,
2718 FILE *MakeFptr,
2719 INT8 *SectionName
2720 )
2721 {
2722 INT8 *Cptr;
2723 INT8 FileName[MAX_EXP_LINE_LEN];
2724 INT8 TempFileName[MAX_PATH];
2725 SECTION *TempSect;
2726 INT8 Str[MAX_LINE_LEN];
2727 INT8 *OverridePath;
2728 FILE *FPtr;
2729
2730 TempSect = DSCFileFindSection (ComponentFile, SectionName);
2731 if (TempSect != NULL) {
2732 //
2733 // See if the SOURCE_OVERRIDE_PATH has been set. If it has, and
2734 // they have an include file that is overridden, then add the path
2735 // to it to the list of include paths (prepend).
2736 //
2737 OverridePath = GetSymbolValue (SOURCE_OVERRIDE_PATH);
2738 while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) {
2739 Cptr = StripLine (Str);
2740 //
2741 // Don't process blank lines
2742 //
2743 if (*Cptr) {
2744 //
2745 // Expand symbols in the filename, then get its parts
2746 //
2747 ExpandSymbols (Cptr, FileName, sizeof (FileName), 0);
2748 AddFileSymbols (FileName);
2749 ReplaceSlash (FileName);
2750 if (IsIncludeFile (FileName)) {
2751 if ((OverridePath != NULL) && (!IsAbsolutePath (FileName))) {
2752 ReplaceSlash (OverridePath);
2753 strcpy (TempFileName, OverridePath);
2754 strcat (TempFileName, "\\");
2755 strcat (TempFileName, FileName);
2756 if ((FPtr = fopen (TempFileName, "rb")) != NULL) {
2757 fclose (FPtr);
2758 //
2759 // Null-terminate the file name at the last backslash and add that
2760 // to the beginning of the list of include paths.
2761 //
2762 for (Cptr = TempFileName + strlen (TempFileName) - 1;
2763 (Cptr >= TempFileName) && (*Cptr != '\\');
2764 Cptr--
2765 )
2766 ;
2767 if (Cptr >= TempFileName) {
2768 *Cptr = 0;
2769 }
2770
2771 fprintf (MakeFptr, "INC = -I %s $(INC)\n", TempFileName);
2772 }
2773 }
2774 //
2775 // If absolute path already, don't prepend source directory
2776 //
2777 // if (IsAbsolutePath (FileName)) {
2778 // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) %s\n", FileName);
2779 // } else {
2780 // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) $(SOURCE_DIR)\\%s\n", FileName);
2781 // }
2782 }
2783
2784 RemoveFileSymbols ();
2785 }
2786 }
2787 }
2788
2789 return STATUS_SUCCESS;
2790 }
2791
2792 static
2793 void
2794 FreeFileParts (
2795 FILE_NAME_PARTS *FP
2796 )
2797 {
2798 if (FP != NULL) {
2799 if (FP->Path != NULL) {
2800 free (FP->Path);
2801 }
2802
2803 if (FP->BaseName != NULL) {
2804 free (FP->BaseName);
2805 }
2806
2807 if (FP->Extension != NULL) {
2808 free (FP->Extension);
2809 }
2810 }
2811 }
2812
2813 static
2814 FILE_NAME_PARTS *
2815 GetFileParts (
2816 INT8 *FileName
2817 )
2818 {
2819 FILE_NAME_PARTS *FP;
2820 INT8 *Cptr;
2821 INT8 CopyFileName[MAX_PATH];
2822 INT8 *FileNamePtr;
2823
2824 strcpy (CopyFileName, FileName);
2825 FP = (FILE_NAME_PARTS *) malloc (sizeof (FILE_NAME_PARTS));
2826 if (FP == NULL) {
2827 Error (NULL, 0, 0, NULL, "failed to allocate memory");
2828 return NULL;
2829 }
2830
2831 memset ((INT8 *) FP, 0, sizeof (FILE_NAME_PARTS));
2832 //
2833 // Get extension code
2834 //
2835 FP->ExtensionCode = GetSourceFileType (CopyFileName);
2836 //
2837 // Get drive if there
2838 //
2839 FileNamePtr = CopyFileName;
2840 if (FileNamePtr[1] == ':') {
2841 FP->Drive[0] = FileNamePtr[0];
2842 FP->Drive[1] = ':';
2843 FileNamePtr += 2;
2844 }
2845 //
2846 // Start at the end and work back
2847 //
2848 for (Cptr = FileNamePtr + strlen (FileNamePtr) - 1; (Cptr > FileNamePtr) && (*Cptr != '.'); Cptr--)
2849 ;
2850
2851 if (*Cptr == '.') {
2852 //
2853 // Don't copy the dot
2854 //
2855 FP->Extension = (char *) malloc (strlen (Cptr));
2856 strcpy (FP->Extension, Cptr + 1);
2857 *Cptr = 0;
2858 Cptr--;
2859 StripTrailingSpaces (FP->Extension);
2860 } else {
2861 //
2862 // Create empty string for extension
2863 //
2864 FP->Extension = (char *) malloc (1);
2865 FP->Extension[0] = 0;
2866 }
2867 //
2868 // Now back up and get the base name (include the preceding '\')
2869 //
2870 for (; (Cptr > FileNamePtr) && (*Cptr != '\\'); Cptr--)
2871 ;
2872 FP->BaseName = (char *) malloc (strlen (Cptr) + 1);
2873 strcpy (FP->BaseName, Cptr);
2874 *Cptr = 0;
2875 Cptr--;
2876 //
2877 // Rest is path
2878 //
2879 if (Cptr >= FileNamePtr) {
2880 Cptr = FileNamePtr;
2881 FP->Path = (char *) malloc (strlen (Cptr) + 1);
2882 strcpy (FP->Path, Cptr);
2883 } else {
2884 FP->Path = (char *) malloc (1);
2885 FP->Path[0] = 0;
2886 }
2887
2888 return FP;
2889 }
2890
2891 /*****************************************************************************
2892 ******************************************************************************/
2893 static
2894 int
2895 WriteCommonMakefile (
2896 DSC_FILE *DSCFile,
2897 FILE *MakeFptr,
2898 INT8 *Processor
2899 )
2900 {
2901 INT8 InLine[MAX_LINE_LEN];
2902 INT8 OutLine[MAX_EXP_LINE_LEN];
2903 SECTION *Sect;
2904 INT8 *Sym;
2905 int i;
2906 //
2907 // Don't mess up the original file pointer, since we're processing it at a higher
2908 // level.
2909 //
2910 DSCFileSavePosition (DSCFile);
2911 //
2912 // Write the header to the file
2913 //
2914 for (i = 0; MakefileHeader[i] != NULL; i++) {
2915 fprintf (MakeFptr, "%s\n", MakefileHeader[i]);
2916 }
2917
2918 fprintf (MakeFptr, "#\n# Hard-coded defines output by the tool\n#\n");
2919 //
2920 // First write the basics to the component's makefile. These includes
2921 // EFI_SOURCE, BIN_DIR, OUT_DIR, LIB_DIR, SOURCE_DIR, DEST_DIR.
2922 //
2923 Sym = GetSymbolValue (EFI_SOURCE);
2924 fprintf (MakeFptr, "%s = %s\n", EFI_SOURCE, Sym);
2925 Sym = GetSymbolValue (BUILD_DIR);
2926 fprintf (MakeFptr, "%s = %s\n", BUILD_DIR, Sym);
2927 Sym = GetSymbolValue (BIN_DIR);
2928 fprintf (MakeFptr, "%s = %s\n", BIN_DIR, Sym);
2929 Sym = GetSymbolValue (OUT_DIR);
2930 fprintf (MakeFptr, "%s = %s\n", OUT_DIR, Sym);
2931 Sym = GetSymbolValue (LIB_DIR);
2932 fprintf (MakeFptr, "%s = %s\n", LIB_DIR, Sym);
2933 Sym = GetSymbolValue (SOURCE_DIR);
2934 fprintf (MakeFptr, "%s = %s\n", SOURCE_DIR, Sym);
2935 Sym = GetSymbolValue (DEST_DIR);
2936 fprintf (MakeFptr, "%s = %s\n", DEST_DIR, Sym);
2937 fprintf (MakeFptr, "\n");
2938 //
2939 // If there was a [makefile.common] section in the description file,
2940 // copy it (after symbol expansion) to the output file.
2941 //
2942 sprintf (InLine, "%s.%s", MAKEFILE_SECTION_NAME, COMMON_SECTION_NAME);
2943 Sect = DSCFileFindSection (DSCFile, InLine);
2944 if (Sect != NULL) {
2945 //
2946 // fprintf (MakeFptr, "# From the [makefile.common] section of the DSC file\n");
2947 // Read lines, expand, then dump out
2948 //
2949 while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) {
2950 //
2951 // Replace symbols
2952 //
2953 ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE);
2954 fprintf (MakeFptr, OutLine);
2955 }
2956 }
2957 //
2958 // If there was a [makefile.platform] section in the description file,
2959 // copy it (after symbol expansion) to the output file.
2960 //
2961 sprintf (InLine, "%s.%s", MAKEFILE_SECTION_NAME, "Platform");
2962 Sect = DSCFileFindSection (DSCFile, InLine);
2963 if (Sect != NULL) {
2964 //
2965 // Read lines, expand, then dump out
2966 //
2967 while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) {
2968 //
2969 // Replace symbols
2970 //
2971 ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE);
2972 fprintf (MakeFptr, OutLine);
2973 }
2974 }
2975 //
2976 // Do the same for any [makefile.$(PROCESSOR)]
2977 //
2978 sprintf (InLine, "%s.%s", MAKEFILE_SECTION_NAME, Processor);
2979 Sect = DSCFileFindSection (DSCFile, InLine);
2980 if (Sect != NULL) {
2981 //
2982 // Read lines, expand, then dump out
2983 //
2984 while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) {
2985 ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE);
2986 fprintf (MakeFptr, OutLine);
2987 }
2988 }
2989 //
2990 // Same thing for [makefile.$(PROCESSOR).$(PLATFORM)]
2991 //
2992 Sym = GetSymbolValue (PLATFORM);
2993 if (Sym != NULL) {
2994 sprintf (InLine, "%s.%s.%s", MAKEFILE_SECTION_NAME, Processor, Sym);
2995 Sect = DSCFileFindSection (DSCFile, InLine);
2996 if (Sect != NULL) {
2997 //
2998 // Read lines, expand, then dump out
2999 //
3000 while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) {
3001 ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE);
3002 fprintf (MakeFptr, OutLine);
3003 }
3004 }
3005 }
3006
3007 fprintf (MakeFptr, "\n");
3008 DSCFileRestorePosition (DSCFile);
3009 return 0;
3010 }
3011
3012 static
3013 int
3014 WriteComponentTypeBuildCommands (
3015 DSC_FILE *DSCFile,
3016 FILE *MakeFptr,
3017 INT8 *SectionName
3018 )
3019 /*++
3020
3021 Routine Description:
3022
3023 Given a section name such as [build.ia32.library], find the section in
3024 the description file and copy the build commands.
3025
3026 Arguments:
3027
3028 DSCFile - section information on the main description file
3029 MakeFptr - file pointer to the makefile we're writing to
3030 SectionName - name of the section we're to copy out to the makefile.
3031
3032 Returns:
3033
3034 Always successful, since the section may be optional.
3035
3036 --*/
3037 {
3038 SECTION *Sect;
3039 INT8 InLine[MAX_LINE_LEN];
3040 INT8 OutLine[MAX_EXP_LINE_LEN];
3041
3042 //
3043 // Don't mess up the original file pointer, since we're processing it at a higher
3044 // level.
3045 //
3046 DSCFileSavePosition (DSCFile);
3047 Sect = DSCFileFindSection (DSCFile, SectionName);
3048 if (Sect != NULL) {
3049 //
3050 // Read lines, expand, then dump out
3051 //
3052 while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) {
3053 ExpandSymbols (
3054 InLine,
3055 OutLine,
3056 sizeof(OutLine),
3057 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR
3058 );
3059 fprintf (MakeFptr, OutLine);
3060 }
3061 } else {
3062 Warning (
3063 NULL,
3064 0,
3065 0,
3066 GetSymbolValue (INF_FILENAME),
3067 "no [%s] build commands found in DSC file for component",
3068 SectionName
3069 );
3070 }
3071
3072 DSCFileRestorePosition (DSCFile);
3073 return STATUS_SUCCESS;
3074 }
3075
3076 /*****************************************************************************
3077
3078 ******************************************************************************/
3079 static
3080 int
3081 WriteCompileCommands (
3082 DSC_FILE *DscFile,
3083 FILE *MakeFptr,
3084 INT8 *FileName,
3085 INT8 *Processor
3086 )
3087 {
3088 FILE_NAME_PARTS *File;
3089 SECTION *Sect;
3090 INT8 BuildSectionName[40];
3091 INT8 InLine[MAX_LINE_LEN];
3092 INT8 OutLine[MAX_EXP_LINE_LEN];
3093 INT8 *SourceCompileType;
3094 char *CPtr;
3095 char *CPtr2;
3096 //
3097 // Determine the filename, then chop it up into its parts
3098 //
3099 File = GetFileParts (FileName);
3100 if (File != NULL) {
3101 //
3102 // Don't mess up the original file pointer, since we're processing it at a higher
3103 // level.
3104 //
3105 DSCFileSavePosition (DscFile);
3106 //
3107 // Option 1: SOURCE_COMPILE_TYPE=MyCompileSection
3108 // Find a section of that name from which to get the compile
3109 // commands for this source file.
3110 // Look for [compile.$(PROCESSOR).$(SOURCE_COMPILE_TYPE]
3111 // Option 2: COMPILE_SELECT=.c=MyCCompile,.asm=MyAsm
3112 // Find a [compile.$(PROCESSOR).MyCompile] section from which to
3113 // get the compile commands for this source file.
3114 // Look for [compile.$(PROCESSOR).MyCompile]
3115 // Option 3: Look for standard section types to compile the file by extension.
3116 // Look for [compile.$(PROCESSOR).<extension>]
3117 //
3118 Sect = NULL;
3119 //
3120 // Option 1 - use SOURCE_COMPILE_TYPE variable
3121 //
3122 SourceCompileType = GetSymbolValue (SOURCE_COMPILE_TYPE);
3123 if (SourceCompileType != NULL) {
3124 sprintf (BuildSectionName, "compile.%s.%s", Processor, SourceCompileType);
3125 Sect = DSCFileFindSection (DscFile, BuildSectionName);
3126 }
3127 //
3128 // Option 2 - use COMPILE_SELECT variable
3129 //
3130 if (Sect == NULL) {
3131 SourceCompileType = GetSymbolValue (COMPILE_SELECT);
3132 if (SourceCompileType != NULL) {
3133 //
3134 // Parse the variable, which looks like COMPILE_SELECT=.c=MyCCompiler;.asm=MyAsm;
3135 // to find an entry with a matching file name extension. If you find one,
3136 // then use that name to find the section name.
3137 //
3138 CPtr = SourceCompileType;
3139 while (*CPtr && (Sect == NULL)) {
3140 //
3141 // See if we found a match with this source file name extension. File->Extension
3142 // does not include the dot, so skip the dot in the COMPILE_SELECT variable if there
3143 // is one.
3144 //
3145 if (*CPtr == '.') {
3146 CPtr++;
3147 }
3148
3149 if (_strnicmp (CPtr, File->Extension, strlen (File->Extension)) == 0) {
3150 //
3151 // Found a file name extension match -- extract the name from the variable, for
3152 // example "MyCCompiler"
3153 //
3154 while (*CPtr && (*CPtr != '=')) {
3155 CPtr++;
3156 }
3157
3158 if ((*CPtr != '=') || (CPtr[1] == 0)) {
3159 Error (NULL, 0, 0, SourceCompileType, "malformed COMPILE_SELECT variable");
3160 break;
3161 }
3162
3163 CPtr++;
3164 sprintf (BuildSectionName, "compile.%s.", Processor);
3165 for (CPtr2 = BuildSectionName + strlen (BuildSectionName);
3166 *CPtr && (*CPtr != ',') && (*CPtr != ';');
3167 CPtr++
3168 ) {
3169 *CPtr2 = *CPtr;
3170 CPtr2++;
3171 }
3172
3173 *CPtr2 = 0;
3174 Sect = DSCFileFindSection (DscFile, BuildSectionName);
3175 if (Sect == NULL) {
3176 ParserError (
3177 0,
3178 BuildSectionName,
3179 "could not find section in DSC file - selected by COMPILE_SELECT variable"
3180 );
3181 }
3182 }
3183
3184 //
3185 // Skip to next file name extension in the COMPILE_SELECT variable
3186 //
3187 while (*CPtr && (*CPtr != ';') && (*CPtr != ',')) {
3188 CPtr++;
3189 }
3190
3191 if (*CPtr) {
3192 CPtr++;
3193 }
3194 }
3195 }
3196 }
3197 //
3198 // Option 3 - use "Compile.$(PROCESSOR).<Extension>" section
3199 //
3200 if (Sect == NULL) {
3201 sprintf (BuildSectionName, "compile.%s.%s", Processor, File->Extension);
3202 Sect = DSCFileFindSection (DscFile, BuildSectionName);
3203 }
3204 //
3205 // Should have found something by now unless it's an include (.h) file
3206 //
3207 if (Sect != NULL) {
3208 //
3209 // Temporarily add a FILE variable to the global symbol table. Omit the
3210 // extension.
3211 //
3212 sprintf (InLine, "%s%s%s", File->Drive, File->Path, File->BaseName);
3213 AddSymbol ("FILE", InLine, SYM_OVERWRITE | SYM_LOCAL | SYM_FILENAME);
3214 //
3215 // Read lines, expand (except SOURCE_DIR and DEST_DIR), then dump out
3216 //
3217 while (DSCFileGetLine (DscFile, InLine, sizeof (InLine)) != NULL) {
3218 ExpandSymbols (
3219 InLine,
3220 OutLine,
3221 sizeof (OutLine),
3222 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR
3223 );
3224 fprintf (MakeFptr, OutLine);
3225 }
3226 fprintf (MakeFptr, "\n");
3227 } else {
3228 //
3229 // Be nice and ignore include files
3230 //
3231 if (!IsIncludeFile (FileName)) {
3232 Error (
3233 NULL,
3234 0,
3235 0,
3236 NULL,
3237 "no compile commands section [%s] found in DSC file for %s",
3238 BuildSectionName,
3239 FileName
3240 );
3241 }
3242 }
3243
3244 DSCFileRestorePosition (DscFile);
3245 FreeFileParts (File);
3246 }
3247
3248 return STATUS_SUCCESS;
3249 }
3250
3251 /*****************************************************************************
3252 ******************************************************************************/
3253 static
3254 int
3255 SetFileExtension (
3256 INT8 *FileName,
3257 INT8 *Extension
3258 )
3259 {
3260 INT8 *Cptr;
3261
3262 Cptr = FileName + strlen (FileName) - 1;
3263 while ((Cptr > FileName) && (*Cptr != '.')) {
3264 Cptr--;
3265
3266 }
3267 //
3268 // Better be a dot
3269 //
3270 if (*Cptr != '.') {
3271 Message (2, "Missing filename extension: %s", FileName);
3272 return STATUS_WARNING;
3273 }
3274
3275 Cptr++;
3276 if (*Extension == '.') {
3277 Extension++;
3278 }
3279
3280 strcpy (Cptr, Extension);
3281 return STATUS_SUCCESS;
3282 }
3283
3284 /*****************************************************************************
3285 ******************************************************************************/
3286 int
3287 MakeFilePath (
3288 INT8 *FileName
3289 )
3290 {
3291 INT8 *Cptr;
3292 INT8 SavedChar;
3293 INT8 BuildDir[MAX_PATH];
3294 INT8 CopyFileName[MAX_PATH];
3295
3296 //
3297 // Expand symbols in the filename
3298 //
3299 if (ExpandSymbols (FileName, CopyFileName, sizeof (CopyFileName), EXPANDMODE_NO_UNDEFS)) {
3300 Error (NULL, 0, 0, NULL, "undefined symbols in file path: %s", FileName);
3301 return STATUS_ERROR;
3302 }
3303 //
3304 // Copy it back
3305 //
3306 strcpy (FileName, CopyFileName);
3307 //
3308 // To avoid creating $(BUILD_DIR) path, see if this path is the same as
3309 // $(BUILD_DIR), and if it is, see if build dir exists and skip over that
3310 // portion if it does
3311 //
3312 Cptr = GetSymbolValue (BUILD_DIR);
3313 if (Cptr != NULL) {
3314 if (_strnicmp (Cptr, FileName, strlen (Cptr)) == 0) {
3315 //
3316 // BUILD_DIR path. See if it exists
3317 //
3318 strcpy (BuildDir, FileName);
3319 BuildDir[strlen (Cptr)] = 0;
3320 if ((_mkdir (BuildDir) != 0) && (errno != EEXIST)) {
3321 Cptr = FileName;
3322 } else {
3323 //
3324 // Already done. Shortcut. Skip to next path so that we don't create
3325 // the BUILD_DIR as well.
3326 //
3327 Cptr = FileName + strlen (Cptr);
3328 if (*Cptr == '\\') {
3329 Cptr++;
3330 }
3331 }
3332 } else {
3333 //
3334 // Not build dir
3335 //
3336 Cptr = FileName;
3337 }
3338 } else {
3339 Cptr = FileName;
3340 }
3341 //
3342 // Create directories until done. Skip over "c:\" in the path if it exists
3343 //
3344 if (*Cptr && (*(Cptr + 1) == ':') && (*(Cptr + 2) == '\\')) {
3345 Cptr += 3;
3346 }
3347
3348 for (;;) {
3349 for (; *Cptr && (*Cptr != '\\'); Cptr++)
3350 ;
3351 if (*Cptr) {
3352 SavedChar = *Cptr;
3353 *Cptr = 0;
3354 if ((_mkdir (FileName) != 0)) {
3355 //
3356 // Error (NULL, 0, 0, FileName, "failed to create directory");
3357 // return 1;
3358 //
3359 }
3360
3361 *Cptr = SavedChar;
3362 Cptr++;
3363 } else {
3364 break;
3365 }
3366 }
3367
3368 return STATUS_SUCCESS;
3369 }
3370
3371 /*****************************************************************************
3372 ******************************************************************************/
3373 int
3374 ExpandSymbols (
3375 INT8 *SourceLine,
3376 INT8 *DestLine,
3377 int LineLen,
3378 int ExpandMode
3379 )
3380 {
3381 static int NestDepth = 0;
3382 INT8 *FromPtr;
3383 INT8 *ToPtr;
3384 INT8 *SaveStart;
3385 INT8 *Cptr;
3386 INT8 *value;
3387 int Expanded;
3388 int ExpandedCount;
3389 INT8 *LocalDestLine;
3390 STATUS Status;
3391 int LocalLineLen;
3392
3393 NestDepth++;
3394 Status = STATUS_SUCCESS;
3395 LocalDestLine = (INT8 *) malloc (LineLen);
3396 if (LocalDestLine == NULL) {
3397 Error (__FILE__, __LINE__, 0, "application error", "memory allocation failed");
3398 NestDepth = 0;
3399 return STATUS_ERROR;
3400 }
3401
3402 FromPtr = SourceLine;
3403 ToPtr = LocalDestLine;
3404 //
3405 // Walk the entire line, replacing $(SYMBOL_NAME).
3406 //
3407 LocalLineLen = LineLen;
3408 ExpandedCount = 0;
3409 while (*FromPtr && (LocalLineLen > 0)) {
3410 if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) {
3411 //
3412 // Save the start in case it's undefined, in which case we copy it as-is.
3413 //
3414 SaveStart = FromPtr;
3415 Expanded = 0;
3416 //
3417 // Symbol expansion time. Find the end (no spaces allowed)
3418 //
3419 FromPtr += 2;
3420 for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++)
3421 ;
3422 if (*Cptr) {
3423 //
3424 // Truncate the string at the closing parenthesis for ease-of-use.
3425 // Then copy the string directly to the destination line in case we don't find
3426 // a definition for it.
3427 //
3428 *Cptr = 0;
3429 strcpy (ToPtr, SaveStart);
3430 if ((_stricmp (SOURCE_DIR, FromPtr) == 0) && (ExpandMode & EXPANDMODE_NO_SOURCEDIR)) {
3431 //
3432 // excluded this expansion
3433 //
3434 } else if ((_stricmp (DEST_DIR, FromPtr) == 0) && (ExpandMode & EXPANDMODE_NO_DESTDIR)) {
3435 //
3436 // excluded this expansion
3437 //
3438 } else if ((value = GetSymbolValue (FromPtr)) != NULL) {
3439 strcpy (ToPtr, value);
3440 LocalLineLen -= strlen (value);
3441 ToPtr += strlen (value);
3442 Expanded = 1;
3443 ExpandedCount++;
3444 } else if (ExpandMode & EXPANDMODE_NO_UNDEFS) {
3445 Error (NULL, 0, 0, "undefined symbol", "$(%s)", FromPtr);
3446 Status = STATUS_ERROR;
3447 goto Done;
3448 }
3449
3450 //
3451 // Restore closing parenthesis, and advance to next character
3452 //
3453 *Cptr = ')';
3454 if (!Expanded) {
3455 FromPtr = SaveStart + 1;
3456 ToPtr++;
3457 } else {
3458 FromPtr = Cptr + 1;
3459 }
3460 } else {
3461 Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on symbol");
3462 strcpy (ToPtr, FromPtr);
3463 Status = STATUS_WARNING;
3464 goto Done;
3465 }
3466 } else {
3467 *ToPtr = *FromPtr;
3468 FromPtr++;
3469 ToPtr++;
3470 LocalLineLen--;
3471 }
3472 }
3473
3474 if (*FromPtr == 0) {
3475 *ToPtr = 0;
3476 }
3477
3478 //
3479 // If we're in recursive mode, and we expanded at least one string successfully,
3480 // then make a recursive call to try again.
3481 //
3482 if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (ExpandMode & EXPANDMODE_RECURSIVE) && (NestDepth < 2)) {
3483 Status = ExpandSymbols (LocalDestLine, DestLine, LineLen, ExpandMode);
3484 free (LocalDestLine);
3485 NestDepth = 0;
3486 return Status;
3487 }
3488
3489 Done:
3490 if (Status != STATUS_ERROR) {
3491 strcpy (DestLine, LocalDestLine);
3492 }
3493
3494 NestDepth = 0;
3495 free (LocalDestLine);
3496 return Status;
3497 }
3498
3499 INT8 *
3500 GetSymbolValue (
3501 INT8 *SymbolName
3502 )
3503 /*++
3504
3505 Routine Description:
3506
3507 Look up a symbol in our symbol table.
3508
3509 Arguments:
3510
3511 SymbolName - The name of symbol.
3512
3513 Returns:
3514
3515 Pointer to the value of the symbol if found
3516 NULL if the symbol is not found
3517
3518 --*/
3519 {
3520 SYMBOL *Symbol;
3521
3522 //
3523 // Scan once for file-level symbols
3524 //
3525 Symbol = gGlobals.Symbol;
3526 while (Symbol) {
3527 if ((_stricmp (SymbolName, Symbol->Name) == 0) && (Symbol->Type & SYM_FILE)) {
3528 return Symbol->Value;
3529 }
3530
3531 Symbol = Symbol->Next;
3532 }
3533 //
3534 // Scan once for local symbols
3535 //
3536 Symbol = gGlobals.Symbol;
3537 while (Symbol) {
3538 if ((_stricmp (SymbolName, Symbol->Name) == 0) && (Symbol->Type & SYM_LOCAL)) {
3539 return Symbol->Value;
3540 }
3541
3542 Symbol = Symbol->Next;
3543 }
3544 //
3545 // No local value found. Scan for globals.
3546 //
3547 Symbol = gGlobals.Symbol;
3548 while (Symbol) {
3549 if ((_stricmp (SymbolName, Symbol->Name) == 0) && (Symbol->Type & SYM_GLOBAL)) {
3550 return Symbol->Value;
3551 }
3552
3553 Symbol = Symbol->Next;
3554 }
3555 //
3556 // For backwards-compatibility, if it's "GUID", return FILE_GUID value
3557 //
3558 if (_stricmp (SymbolName, GUID) == 0) {
3559 return GetSymbolValue (FILE_GUID);
3560 }
3561
3562 return NULL;
3563 }
3564
3565 static
3566 int
3567 RemoveLocalSymbols (
3568 VOID
3569 )
3570 /*++
3571
3572 Routine Description:
3573
3574 Remove all local symbols from the symbol table. Local symbols are those
3575 that are defined typically by the component's INF file.
3576
3577 Arguments:
3578
3579 None.
3580
3581 Returns:
3582
3583 Right now, never fails.
3584
3585 --*/
3586 {
3587 SYMBOL *Sym;
3588 int FoundOne;
3589
3590 do {
3591 FoundOne = 0;
3592 Sym = gGlobals.Symbol;
3593 while (Sym) {
3594 if (Sym->Type & SYM_LOCAL) {
3595 //
3596 // Going to delete it out from under ourselves, so break and restart
3597 //
3598 FoundOne = 1;
3599 RemoveSymbol (Sym->Name, SYM_LOCAL);
3600 break;
3601 }
3602
3603 Sym = Sym->Next;
3604 }
3605 } while (FoundOne);
3606 return STATUS_SUCCESS;
3607 }
3608
3609 static
3610 int
3611 RemoveFileSymbols (
3612 VOID
3613 )
3614 /*++
3615
3616 Routine Description:
3617
3618 Remove all file-level symbols from the symbol table. File-level symbols are
3619 those that are defined on a source file line in an INF file.
3620
3621 Arguments:
3622
3623 None.
3624
3625 Returns:
3626
3627 Right now, never fails.
3628
3629 --*/
3630 {
3631 SYMBOL *Sym;
3632 int FoundOne;
3633
3634 do {
3635 FoundOne = 0;
3636 Sym = gGlobals.Symbol;
3637 while (Sym) {
3638 if (Sym->Type & SYM_FILE) {
3639 //
3640 // Going to delete it out from under ourselves, so break and restart
3641 //
3642 FoundOne = 1;
3643 RemoveSymbol (Sym->Name, SYM_FILE);
3644 break;
3645 }
3646
3647 Sym = Sym->Next;
3648 }
3649 } while (FoundOne);
3650 return STATUS_SUCCESS;
3651 }
3652
3653 static
3654 STATUS
3655 ParseGuidDatabaseFile (
3656 INT8 *FileName
3657 )
3658 /*++
3659
3660 Routine Description:
3661 This function parses a GUID-to-basename text file (perhaps output by
3662 the GuidChk utility) to define additional symbols. The format of the
3663 file should be:
3664
3665 7BB28B99-61BB-11D5-9A5D-0090273FC14D EFI_DEFAULT_BMP_LOGO_GUID gEfiDefaultBmpLogoGuid
3666
3667 This function parses the line and defines global symbol:
3668
3669 EFI_DEFAULT_BMP_LOGO_GUID=7BB28B99-61BB-11D5-9A5D-0090273FC14D
3670
3671 This symbol (rather than the actual GUID) can then be used in INF files to
3672 fix duplicate GUIDs
3673
3674 Arguments:
3675 FileName - the name of the file to parse.
3676
3677 Returns:
3678 STATUS_ERROR - could not open FileName
3679 STATUS_SUCCESS - we opened the file
3680
3681 --*/
3682 {
3683 FILE *Fptr;
3684 INT8 Line[100];
3685 INT8 Guid[100];
3686 INT8 DefineName[80];
3687
3688 Fptr = fopen (FileName, "r");
3689 if (Fptr == NULL) {
3690 Error (NULL, 0, 0, FileName, "failed to open input GUID database input file");
3691 return STATUS_ERROR;
3692 }
3693
3694 while (fgets (Line, sizeof (Line), Fptr) != NULL) {
3695 //
3696 // Get the GUID string, skip the defined name (EFI_XXX_GUID), and get the
3697 // variable name (gWhateverProtocolGuid)
3698 //
3699 if (sscanf (Line, "%s %s %*s", Guid, DefineName) == 2) {
3700 AddSymbol (DefineName, Guid, SYM_GLOBAL);
3701 }
3702 }
3703
3704 fclose (Fptr);
3705 return STATUS_SUCCESS;
3706 }
3707
3708 /*****************************************************************************
3709
3710 Returns:
3711 0 if successful standard add
3712 length of the parsed string if passed in " name = value "
3713 < 0 on error
3714
3715 ******************************************************************************/
3716 int
3717 AddSymbol (
3718 INT8 *Name,
3719 INT8 *Value,
3720 int Mode
3721 )
3722 {
3723 SYMBOL *Symbol;
3724 SYMBOL *NewSymbol;
3725 int Len;
3726 INT8 *Start;
3727 INT8 *Cptr;
3728 INT8 CSave1;
3729 INT8 *SaveCptr1;
3730 INT8 CSave2;
3731 INT8 *SaveCptr2;
3732 INT8 ShortName[MAX_PATH];
3733
3734 Len = 0;
3735 SaveCptr1 = NULL;
3736 CSave1 = 0;
3737 SaveCptr2 = NULL;
3738 CSave2 = 0;
3739
3740 ShortName[0] = 0;
3741 //
3742 // Mode better be local or global symbol
3743 //
3744 if ((Mode & (SYM_LOCAL | SYM_GLOBAL | SYM_FILE)) == 0) {
3745 Error (NULL, 0, 0, "APP ERROR", "adding symbol '%s' that is not local, global, nor file level", Name);
3746 return -1;
3747 }
3748 //
3749 // If value pointer is null, then they passed us a line something like:
3750 // varname = value, or simply var =
3751 //
3752 if (Value == NULL) {
3753 Start = Name;
3754 while (*Name && isspace (*Name)) {
3755 Name++;
3756
3757 }
3758
3759 if (!*Name) {
3760 return -1;
3761 }
3762 //
3763 // Find the end of the name. Either space or a '='.
3764 //
3765 for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++)
3766 ;
3767 if (!*Value) {
3768 return -1;
3769 }
3770 //
3771 // Look for the '='
3772 //
3773 Cptr = Value;
3774 while (*Value && (*Value != '=')) {
3775 Value++;
3776 }
3777
3778 if (!*Value) {
3779 return -1;
3780 }
3781
3782 //
3783 // Now truncate the name
3784 //
3785 CSave1 = *Cptr;
3786 SaveCptr1 = Cptr;
3787 *Cptr = 0;
3788
3789 //
3790 // Skip over the = and then any spaces
3791 //
3792 Value++;
3793 while (*Value && isspace (*Value)) {
3794 Value++;
3795
3796 }
3797 //
3798 // Find end of string, checking for quoted string
3799 //
3800 if (*Value == '\"') {
3801 Value++;
3802 for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++)
3803 ;
3804 } else {
3805 for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++)
3806 ;
3807 }
3808 //
3809 // Null terminate the value string
3810 //
3811 if (*Cptr) {
3812 Len = (int) (Cptr - Start) + 1;
3813 CSave2 = *Cptr;
3814 SaveCptr2 = Cptr;
3815 *Cptr = 0;
3816 } else {
3817 Len = (int) (Cptr - Start);
3818 }
3819 }
3820
3821 //
3822 // If file name or file path, and we're shortening, then print it
3823 //
3824 if ((Mode & (SYM_FILEPATH | SYM_FILENAME)) && (GetSymbolValue (SHORT_NAMES) != NULL)) {
3825 if (GetShortPathName (Value, ShortName, sizeof (ShortName)) > 0) {
3826 //
3827 // fprintf (stdout, "String value '%s' shortened to '%s'\n",
3828 // Value, ShortName);
3829 //
3830 Value = ShortName;
3831 } else {
3832 //
3833 // fprintf (stdout, "WARNING: Failed to get short name for %s\n", Value);
3834 //
3835 }
3836 }
3837 //
3838 // We now have a symbol name and a value. Look for an existing variable of
3839 // the same type (global or local) and overwrite it.
3840 //
3841 Symbol = gGlobals.Symbol;
3842 while (Symbol) {
3843 //
3844 // Check for symbol name match
3845 //
3846 if (_stricmp (Name, Symbol->Name) == 0) {
3847 //
3848 // See if this symbol is of the same type (global or local) as what
3849 // they're requesting
3850 //
3851 if ((Symbol->Type & (SYM_LOCAL | SYM_GLOBAL)) == (Mode & (SYM_LOCAL | SYM_GLOBAL))) {
3852 //
3853 // Did they say we could overwrite it?
3854 //
3855 if (Mode & SYM_OVERWRITE) {
3856 free (Symbol->Value);
3857 Symbol->Value = (INT8 *) malloc (strlen (Value) + 1);
3858 if (Symbol->Value == NULL) {
3859 Error (NULL, 0, 0, NULL, "failed to allocate memory");
3860 return -1;
3861 }
3862
3863 strcpy (Symbol->Value, Value);
3864 //
3865 // If value == "NULL", then make it a 0-length string
3866 //
3867 if (_stricmp (Symbol->Value, "NULL") == 0) {
3868 Symbol->Value[0] = 0;
3869 }
3870
3871 return Len;
3872 } else {
3873 return STATUS_ERROR;
3874 }
3875 }
3876 }
3877
3878 Symbol = Symbol->Next;
3879 }
3880 //
3881 // Does not exist, create a new one
3882 //
3883 NewSymbol = (SYMBOL *) malloc (sizeof (SYMBOL));
3884 if (NewSymbol == NULL) {
3885 Error (NULL, 0, 0, NULL, "failed to allocate memory");
3886 return -1;
3887 }
3888
3889 memset ((INT8 *) NewSymbol, 0, sizeof (SYMBOL));
3890 NewSymbol->Name = (INT8 *) malloc (strlen (Name) + 1);
3891 NewSymbol->Value = (INT8 *) malloc (strlen (Value) + 1);
3892 //
3893 // Simply use the mode bits as the type.
3894 //
3895 NewSymbol->Type = Mode;
3896 if ((NewSymbol->Name == NULL) || (NewSymbol->Value == NULL)) {
3897 Error (NULL, 0, 0, NULL, "failed to allocate memory");
3898 return -1;
3899 }
3900
3901 strcpy (NewSymbol->Name, Name);
3902 strcpy (NewSymbol->Value, Value);
3903 //
3904 // Remove trailing spaces
3905 //
3906 Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1;
3907 while (Cptr > NewSymbol->Value) {
3908 if (isspace (*Cptr)) {
3909 *Cptr = 0;
3910 Cptr--;
3911 } else {
3912 break;
3913 }
3914 }
3915 //
3916 // Add it to the head of the list.
3917 //
3918 NewSymbol->Next = gGlobals.Symbol;
3919 gGlobals.Symbol = NewSymbol;
3920 //
3921 // If value == "NULL", then make it a 0-length string
3922 //
3923 if (_stricmp (NewSymbol->Value, "NULL") == 0) {
3924 NewSymbol->Value[0] = 0;
3925 }
3926 //
3927 // Restore the terminator we inserted if they passed in var=value
3928 //
3929 if (SaveCptr1 != NULL) {
3930 *SaveCptr1 = CSave1;
3931 }
3932 if (SaveCptr2 != NULL) {
3933 *SaveCptr2 = CSave2;
3934 }
3935
3936 return Len;
3937 }
3938
3939 /*****************************************************************************
3940 ******************************************************************************/
3941 static
3942 int
3943 RemoveSymbol (
3944 INT8 *Name,
3945 INT8 SymbolType
3946 )
3947 {
3948 SYMBOL *Symbol;
3949 SYMBOL *PrevSymbol;
3950
3951 PrevSymbol = NULL;
3952 Symbol = gGlobals.Symbol;
3953 while (Symbol) {
3954 if ((_stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) {
3955 if (Symbol->Value) {
3956 free (Symbol->Value);
3957 }
3958
3959 free (Symbol->Name);
3960 if (PrevSymbol) {
3961 PrevSymbol->Next = Symbol->Next;
3962 } else {
3963 gGlobals.Symbol = Symbol->Next;
3964 }
3965
3966 free (Symbol);
3967 return STATUS_SUCCESS;
3968 }
3969
3970 PrevSymbol = Symbol;
3971 Symbol = Symbol->Next;
3972 }
3973
3974 return STATUS_WARNING;
3975 }
3976
3977 #if 0
3978
3979 /*****************************************************************************
3980 ******************************************************************************/
3981 static
3982 void
3983 FreeSections (
3984 SECTION *Sect
3985 )
3986 {
3987 SECTION *Next;
3988
3989 while (Sect != NULL) {
3990 Next = Sect->Next;
3991 if (Sect->Name != NULL) {
3992 delete[] Sect->Name;
3993 }
3994
3995 delete Sect;
3996 Sect = Next;
3997 }
3998 }
3999 #endif
4000
4001 /*****************************************************************************
4002 ******************************************************************************/
4003 static
4004 INT8 *
4005 StripLine (
4006 INT8 *Line
4007 )
4008 {
4009 INT8 *Cptr;
4010 int Len;
4011
4012 Cptr = Line;
4013 //
4014 // Look for '#' comments in first character of line
4015 //
4016 if (*Cptr == '#') {
4017 *Cptr = 0;
4018 return Cptr;
4019 }
4020
4021 while (isspace (*Cptr)) {
4022 Cptr++;
4023 }
4024 //
4025 // Hack off newlines
4026 //
4027 Len = strlen (Cptr);
4028 if ((Len > 0) && (Cptr[Len - 1] == '\n')) {
4029 Cptr[Len - 1] = 0;
4030 }
4031 //
4032 // Hack off trailing spaces
4033 //
4034 StripTrailingSpaces (Cptr);
4035 return Cptr;
4036 }
4037
4038 /*****************************************************************************
4039 FUNCTION: ProcessOptions()
4040
4041 DESCRIPTION: Process the command-line options.
4042 ******************************************************************************/
4043 static
4044 int
4045 ProcessOptions (
4046 int Argc,
4047 INT8 *Argv[]
4048 )
4049 /*++
4050
4051 Routine Description:
4052
4053 Process the command line options to this utility.
4054
4055 Arguments:
4056
4057 Argc - Standard Argc.
4058 Argv[] - Standard Argv.
4059
4060 Returns:
4061
4062 --*/
4063 {
4064 INT8 *Cptr;
4065 int FreeCwd;
4066
4067 //
4068 // Clear out the options
4069 //
4070 memset ((INT8 *) &gGlobals, 0, sizeof (gGlobals));
4071
4072 Argc--;
4073 Argv++;
4074
4075 if (Argc == 0) {
4076 Usage ();
4077 return STATUS_ERROR;
4078 }
4079 //
4080 // Now process the arguments
4081 //
4082 while (Argc > 0) {
4083
4084 if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {
4085 switch (Argv[0][1]) {
4086 //
4087 // -? or -h help option
4088 //
4089 case '?':
4090 case 'h':
4091 case 'H':
4092 Usage ();
4093 return STATUS_ERROR;
4094
4095 //
4096 // /d symbol=name
4097 //
4098 case 'd':
4099 case 'D':
4100 //
4101 // Skip to next arg
4102 //
4103 Argc--;
4104 Argv++;
4105 if (Argc == 0) {
4106 Argv--;
4107 Error (NULL, 0, 0, NULL, "missing symbol definition with %c%c", Argv[0][0], Argv[0][1]);
4108 return STATUS_ERROR;
4109 } else {
4110 if (AddSymbol (Argv[0], NULL, SYM_OVERWRITE | SYM_GLOBAL) <= 0) {
4111 Warning (NULL, 0, 0, Argv[0], "failed to add symbol: %s");
4112 }
4113 }
4114 break;
4115
4116 //
4117 // output makefile name
4118 //
4119 case 'm':
4120 case 'M':
4121 //
4122 // Skip to next arg
4123 //
4124 Argc--;
4125 Argv++;
4126 if (Argc == 0) {
4127 Argv--;
4128 Error (NULL, 0, 0, Argv[0], "missing output makefile name with option");
4129 Usage ();
4130 return STATUS_ERROR;
4131 } else {
4132 strcpy (gGlobals.MakefileName, Argv[0]);
4133 }
4134 break;
4135
4136 //
4137 // Print a cross-reference file containing guid/basename/processor
4138 //
4139 case 'x':
4140 case 'X':
4141 //
4142 // Skip to next arg
4143 //
4144 Argc--;
4145 Argv++;
4146 if (Argc == 0) {
4147 Argv--;
4148 Error (NULL, 0, 0, Argv[0], "missing cross-reference output filename with option");
4149 Usage ();
4150 return STATUS_ERROR;
4151 } else {
4152 strcpy (gGlobals.XRefFileName, Argv[0]);
4153 }
4154 break;
4155
4156 //
4157 // GUID database file to preparse
4158 //
4159 case 'g':
4160 case 'G':
4161 //
4162 // Skip to next arg
4163 //
4164 Argc--;
4165 Argv++;
4166 if (Argc == 0) {
4167 Argv--;
4168 Error (NULL, 0, 0, Argv[0], "missing input GUID database filename with option");
4169 Usage ();
4170 return STATUS_ERROR;
4171 } else {
4172 strcpy (gGlobals.GuidDatabaseFileName, Argv[0]);
4173 }
4174 break;
4175
4176 case 'v':
4177 case 'V':
4178 gGlobals.Verbose = 1;
4179 break;
4180
4181 default:
4182 Error (NULL, 0, 0, Argv[0], "unrecognized option");
4183 return STATUS_ERROR;
4184 }
4185 } else {
4186 break;
4187 }
4188
4189 Argc--;
4190 Argv++;
4191 }
4192 //
4193 // Must be at least one arg left
4194 //
4195 if (Argc > 0) {
4196 gGlobals.DscFilename = Argv[0];
4197 }
4198
4199 if (gGlobals.DscFilename == NULL) {
4200 Error (NULL, 0, 0, NULL, "must specify DSC filename on command line");
4201 return STATUS_ERROR;
4202 }
4203 //
4204 // Make a global symbol for the DSC filename
4205 //
4206 AddSymbol (DSC_FILENAME, gGlobals.DscFilename, SYM_GLOBAL | SYM_FILENAME);
4207 //
4208 // If no output makefile specified, take the default
4209 //
4210 if (gGlobals.MakefileName[0] == 0) {
4211 strcpy (gGlobals.MakefileName, MAKEFILE_OUT_NAME);
4212 }
4213 //
4214 // Get the current working directory and use it for the build directory.
4215 // Only do this if they have not defined it on the command line. Do the
4216 // same for the bin dir, output dir, and library directory.
4217 //
4218 Cptr = GetSymbolValue (BUILD_DIR);
4219 if (Cptr == NULL) {
4220 Cptr = _getcwd (NULL, 0);
4221 FreeCwd = 1;
4222 AddSymbol (BUILD_DIR, Cptr, SYM_OVERWRITE | SYM_GLOBAL | SYM_FILEPATH);
4223 } else {
4224 ReplaceSlash (Cptr);
4225 FreeCwd = 0;
4226 }
4227
4228 if (FreeCwd) {
4229 free (Cptr);
4230 }
4231
4232 return 0;
4233 }
4234
4235 /*****************************************************************************
4236 ******************************************************************************/
4237 static
4238 SYMBOL *
4239 FreeSymbols (
4240 SYMBOL *Syms
4241 )
4242 {
4243 SYMBOL *Next;
4244 while (Syms) {
4245
4246 if (Syms->Name != NULL) {
4247 free (Syms->Name);
4248 }
4249
4250 if (Syms->Value != NULL) {
4251 free (Syms->Value);
4252 }
4253
4254 Next = Syms->Next;
4255 free (Syms);
4256 Syms = Next;
4257 }
4258
4259 return Syms;
4260 }
4261
4262 /*****************************************************************************
4263 ******************************************************************************/
4264 static
4265 int
4266 GetSourceFileType (
4267 INT8 *FileName
4268 )
4269 {
4270 INT8 *Cptr;
4271 int len;
4272 int i;
4273
4274 len = strlen (FileName);
4275 if (len == 0) {
4276 return FILETYPE_UNKNOWN;
4277
4278 }
4279
4280 Cptr = FileName + len - 1;
4281 while ((*Cptr != '.') && (Cptr >= FileName)) {
4282 Cptr--;
4283
4284 }
4285
4286 if (*Cptr == '.') {
4287
4288 for (i = 0; mFileTypes[i].Extension != NULL; i++) {
4289 len = strlen (mFileTypes[i].Extension);
4290 if (_strnicmp (mFileTypes[i].Extension, Cptr, len) == 0) {
4291 if ((*(Cptr + len) == 0) || isspace (*(Cptr + len))) {
4292 return mFileTypes[i].FileType;
4293 }
4294 }
4295 }
4296 }
4297
4298 return FILETYPE_UNKNOWN;
4299 }
4300 //
4301 // Determine if a given file is a standard include file. If we don't know,
4302 // then assume it's not.
4303 //
4304 static
4305 int
4306 IsIncludeFile (
4307 INT8 *FileName
4308 )
4309 {
4310 INT8 *Cptr;
4311 int len;
4312 int i;
4313
4314 len = strlen (FileName);
4315 if (len == 0) {
4316 return 0;
4317 }
4318
4319 Cptr = FileName + len - 1;
4320 while ((*Cptr != '.') && (Cptr >= FileName)) {
4321 Cptr--;
4322 }
4323
4324 if (*Cptr == '.') {
4325 //
4326 // Now go through the list of filename extensions and try to find
4327 // a match for this file extension.
4328 //
4329 for (i = 0; mFileTypes[i].Extension != NULL; i++) {
4330 len = strlen (mFileTypes[i].Extension);
4331 if (_strnicmp (mFileTypes[i].Extension, Cptr, len) == 0) {
4332 //
4333 // Make sure that's all there is to the filename extension.
4334 //
4335 if ((*(Cptr + len) == 0) || isspace (*(Cptr + len))) {
4336 return mFileTypes[i].FileFlags & FILE_FLAG_INCLUDE;
4337 }
4338 }
4339 }
4340 }
4341
4342 return 0;
4343 }
4344
4345 /*****************************************************************************
4346 ******************************************************************************/
4347 static
4348 void
4349 StripTrailingSpaces (
4350 INT8 *Str
4351 )
4352 {
4353 INT8 *Cptr;
4354 Cptr = Str + strlen (Str) - 1;
4355 while (Cptr > Str) {
4356 if (isspace (*Cptr)) {
4357 *Cptr = 0;
4358 Cptr--;
4359 } else {
4360 break;
4361 }
4362 }
4363 }
4364
4365 /*****************************************************************************
4366 ******************************************************************************/
4367 static
4368 int
4369 GetEfiSource (
4370 VOID
4371 )
4372 {
4373 INT8 *EfiSource;
4374
4375 //
4376 // Don't set it if the user specified it on the command line.
4377 //
4378 EfiSource = GetSymbolValue (EFI_SOURCE);
4379 if ( EfiSource != NULL) {
4380 ReplaceSlash (EfiSource);
4381 if (EfiSource[strlen (EfiSource) - 1] == '\\') {
4382 EfiSource[strlen (EfiSource) - 1] = 0;
4383 }
4384 return STATUS_SUCCESS;
4385 }
4386
4387 //
4388 // Get the environmental variable setting of EFI_SOURCE.
4389 //
4390 EfiSource = getenv (EFI_SOURCE);
4391 if (EfiSource != NULL) {
4392 ReplaceSlash (EfiSource);
4393 if (EfiSource[strlen (EfiSource) - 1] == '\\') {
4394 EfiSource[strlen (EfiSource) - 1] = 0;
4395 }
4396 AddSymbol (EFI_SOURCE, EfiSource, SYM_GLOBAL | SYM_FILEPATH);
4397 return STATUS_SUCCESS;
4398 }
4399
4400 Error (NULL, 0, 0, NULL, "could not determine EFI_SOURCE");
4401 return STATUS_ERROR;
4402 }
4403
4404 void
4405 Message (
4406 UINT32 PrintMask,
4407 INT8 *Fmt,
4408 ...
4409 )
4410 {
4411 INT8 Line[MAX_LINE_LEN];
4412 va_list List;
4413
4414 va_start (List, Fmt);
4415 vsprintf (Line, Fmt, List);
4416 if (PrintMask & gGlobals.Verbose) {
4417 fprintf (stdout, "%s\n", Line);
4418 }
4419
4420 va_end (List);
4421 }
4422
4423 static
4424 void
4425 Usage (
4426 VOID
4427 )
4428 {
4429 int i;
4430 static const INT8 *Help[] = {
4431 "Usage: ProcessDsc {options} [Dsc Filename]",
4432 " Options:",
4433 " -d var=value to define symbol 'var' to 'value'",
4434 " -v for verbose mode",
4435 " -g filename to preparse GUID listing file",
4436 " -x filename to create a cross-reference file",
4437 NULL
4438 };
4439 for (i = 0; Help[i] != NULL; i++) {
4440 fprintf (stdout, "%s\n", Help[i]);
4441 }
4442 }
4443
4444 /*++
4445
4446 Routine Description:
4447
4448 Process the [defines] section in the DSC file.
4449
4450 Arguments:
4451
4452 DscFile - pointer to the DSCFile class that contains the relevant info.
4453
4454 Returns:
4455
4456 0 if not necessarily an absolute path
4457 1 otherwise
4458
4459 --*/
4460 static
4461 int
4462 ProcessDSCDefinesSection (
4463 DSC_FILE *DscFile
4464 )
4465 {
4466 INT8 Line[MAX_LINE_LEN];
4467 INT8 Line2[MAX_EXP_LINE_LEN];
4468 INT8 *Cptr;
4469 SECTION *Sect;
4470
4471 //
4472 // Look for a [defines] section and process it
4473 //
4474 Sect = DSCFileFindSection (DscFile, DEFINES_SECTION_NAME);
4475 if (Sect == NULL) {
4476 return STATUS_ERROR;
4477 }
4478 //
4479 // Read lines while they're valid
4480 //
4481 while (DSCFileGetLine (DscFile, Line, sizeof (Line)) != NULL) {
4482 //
4483 // Expand symbols on the line
4484 //
4485 if (ExpandSymbols (Line, Line2, sizeof (Line2), 0)) {
4486 return STATUS_ERROR;
4487 }
4488 //
4489 // Strip the line
4490 //
4491 Cptr = StripLine (Line2);
4492 if (*Cptr) {
4493 //
4494 // Make the assignment
4495 //
4496 AddSymbol (Line2, NULL, SYM_OVERWRITE | SYM_GLOBAL);
4497 }
4498 }
4499
4500 return STATUS_SUCCESS;
4501 }
4502
4503 int
4504 IsAbsolutePath (
4505 char *FileName
4506 )
4507 /*++
4508
4509 Routine Description:
4510
4511 Determine if a given filename contains the full path information.
4512
4513 Arguments:
4514
4515 FileName - the name of the file, with symbol expanded.
4516
4517 Returns:
4518
4519 0 if not necessarily an absolute path
4520 1 otherwise
4521
4522 --*/
4523 {
4524 //
4525 // If the first character is a-z, and the second character is a colon, then
4526 // it is an absolute path.
4527 //
4528 if (isalpha (FileName[0]) && (FileName[1] == ':')) {
4529 return 1;
4530 }
4531
4532 return 0;
4533 }
4534
4535 SMART_FILE *
4536 SmartOpen (
4537 char *FileName
4538 )
4539 {
4540 SMART_FILE *SmartFile;
4541 FILE *Fptr;
4542 int FileSize;
4543
4544 SmartFile = malloc (sizeof (SMART_FILE));
4545 if (SmartFile == NULL) {
4546 return NULL;
4547 }
4548 memset (SmartFile, 0, sizeof (SMART_FILE));
4549
4550 SmartFile->FileName = malloc (strlen (FileName) + 1);
4551 if (SmartFile->FileName == NULL){
4552 SmartFree (SmartFile);
4553 return NULL;
4554 }
4555 strcpy (SmartFile->FileName, FileName);
4556
4557 if ((Fptr = fopen (FileName, "r")) != NULL) {
4558 fseek (Fptr, 0, SEEK_END);
4559 FileSize = ftell (Fptr);
4560 fseek (Fptr, 0, SEEK_SET);
4561 SmartFile->FileContent = malloc (FileSize + 1);
4562 if (SmartFile->FileContent != NULL) {
4563 memset (SmartFile->FileContent, 0, FileSize + 1);
4564 //
4565 // Usually FileLength < FileSize, because in text mode, carriage return¨Clinefeed
4566 // combinations are translated into single linefeeds on input
4567 //
4568 SmartFile->FileLength = fread (SmartFile->FileContent, sizeof(char), FileSize, Fptr);
4569 }
4570 fclose (Fptr);
4571 }
4572
4573 //
4574 // No previous output file content, re-create the file
4575 //
4576 if (SmartFile->FileContent == NULL) {
4577 if ((SmartFile->FilePtr = fopen (FileName, "w")) == NULL) {
4578 SmartFree (SmartFile);
4579 return NULL;
4580 }
4581 }
4582
4583 return SmartFile;
4584 }
4585
4586 int
4587 SmartWrite (
4588 SMART_FILE *SmartFile,
4589 char *String
4590 )
4591 {
4592 int StrLen;
4593
4594 if (SmartFile->FilePtr != NULL) {
4595 return fprintf (SmartFile->FilePtr, "%s", String);
4596 } else {
4597 StrLen = strlen (String);
4598 if ((StrLen > SmartFile->FileLength - SmartFile->FilePosition) ||
4599 (_strnicmp (&SmartFile->FileContent[SmartFile->FilePosition], String, StrLen) != 0)) {
4600 //
4601 // file changed, need to re-create.
4602 //
4603 if ((SmartFile->FilePtr = fopen (SmartFile->FileName, "w")) == NULL) {
4604 Error (NULL, 0, 0, SmartFile->FileName, "could not open file for writing when SmartWrite");
4605 return -1;
4606 } else {
4607 SmartFile->FileContent[SmartFile->FilePosition] = 0;
4608 fprintf (SmartFile->FilePtr, "%s%s", SmartFile->FileContent, String);
4609 return StrLen;
4610 }
4611 } else {
4612 SmartFile->FilePosition += StrLen;
4613 return StrLen;
4614 }
4615 }
4616 }
4617
4618 void
4619 SmartClose (
4620 SMART_FILE *SmartFile
4621 )
4622 {
4623 if ((SmartFile->FilePtr == NULL) && (SmartFile->FilePosition < SmartFile->FileLength)) {
4624 //
4625 // The new file is smaller than before, re-create it.
4626 //
4627 if ((SmartFile->FilePtr = fopen (SmartFile->FileName, "w")) == NULL) {
4628 Error (NULL, 0, 0, SmartFile->FileName, "could not open file for writing when SmartClose");
4629 } else {
4630 SmartFile->FileContent[SmartFile->FilePosition] = 0;
4631 fprintf (SmartFile->FilePtr, "%s", SmartFile->FileContent);
4632 }
4633 }
4634
4635 SmartFree(SmartFile);
4636 }
4637
4638 static
4639 void
4640 SmartFree (
4641 SMART_FILE *SmartFile
4642 )
4643 {
4644 if (SmartFile == NULL) {
4645 return;
4646 }
4647
4648 if (SmartFile->FileName != NULL ) {
4649 free (SmartFile->FileName);
4650 }
4651
4652 if (SmartFile->FileContent != NULL ) {
4653 free (SmartFile->FileContent);
4654 }
4655
4656 if (SmartFile->FilePtr != NULL ) {
4657 fclose (SmartFile->FilePtr);
4658 }
4659
4660 free (SmartFile);
4661
4662 return;
4663 }
4664
4665 static
4666 int
4667 AddModuleName (
4668 SYMBOL **SymbolList,
4669 INT8 *ModuleName,
4670 INT8 *InfName
4671 )
4672 /*++
4673
4674 Routine Description:
4675
4676 Add module name in the global module list.
4677 For the same module names, it is only added once.
4678
4679 Arguments:
4680 SymbolList : add name into this list
4681 ModuleName : point to one module name char string.
4682 InfName : point to this module inf file name with path.
4683
4684 Returns:
4685
4686 0 : Successfully add input name into the global list.
4687 other value : allocate memory failed.
4688
4689 --*/
4690 {
4691 SYMBOL *CurrentSymbol;
4692 SYMBOL *LastSymbol;
4693
4694 //
4695 // Get the global module list.
4696 //
4697 CurrentSymbol = *SymbolList;
4698 LastSymbol = *SymbolList;
4699
4700 //
4701 // Search whether this module name has been added into the global list.
4702 //
4703 while (CurrentSymbol != NULL) {
4704 if (_stricmp (CurrentSymbol->Name, ModuleName) == 0) {
4705 if ((CurrentSymbol->Value == NULL) && (InfName == NULL)) {
4706 break;
4707 } else if ((CurrentSymbol->Value != NULL) && (InfName != NULL) && \
4708 (_stricmp (CurrentSymbol->Value, InfName) == 0)) {
4709 break;
4710 }
4711 }
4712 LastSymbol = CurrentSymbol;
4713 CurrentSymbol = CurrentSymbol->Next;
4714 }
4715
4716 //
4717 // Add new module name in list.
4718 //
4719 if (CurrentSymbol == NULL) {
4720 CurrentSymbol = (SYMBOL *) malloc (sizeof (SYMBOL));
4721 if (CurrentSymbol == NULL) {
4722 Error (NULL, 0, 0, NULL, "failed to allocate memory");
4723 return -1;
4724 }
4725 memset ((INT8 *) CurrentSymbol, 0, sizeof (SYMBOL));
4726
4727 if (ModuleName != NULL) {
4728 CurrentSymbol->Name = (INT8 *) malloc (strlen (ModuleName) + 1);
4729 strcpy (CurrentSymbol->Name, ModuleName);
4730 }
4731
4732 if (InfName != NULL) {
4733 CurrentSymbol->Value = (INT8 *) malloc (strlen (InfName) + 1);
4734 strcpy (CurrentSymbol->Value, InfName);
4735 }
4736
4737 if (LastSymbol == NULL) {
4738 *SymbolList = CurrentSymbol;
4739 } else {
4740 LastSymbol->Next = CurrentSymbol;
4741 }
4742 }
4743
4744 return 0;
4745 }
4746
4747
4748 static
4749 void
4750 ReplaceSlash (
4751 INT8 *Path
4752 )
4753 /*++
4754
4755 Routine Description:
4756
4757 Replace '/' with '\\'
4758
4759 Returns:
4760
4761 --*/
4762 {
4763 while (*Path) {
4764 if (*Path == '/') {
4765 *Path = '\\';
4766 }
4767 Path++;
4768 }
4769 }