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