]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c
1) Sync EdkCompatibilityPkg with EDK 1.04. The changes includes:
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / ProcessDsc / ProcessDsc.c
Content-type: text/html ]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c


500 - Internal Server Error

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