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