Sync EDKII BaseTools to BaseTools project r1903.
[efi/edk2/.git] / edk2 / BaseTools / Source / C / VfrCompile / VfrCompiler.cpp
1 /** @file\r
2   \r
3   VfrCompiler main class and main function.\r
4 \r
5 Copyright (c) 2004 - 2010, Intel Corporation                                                         \r
6 All rights reserved. This program and the accompanying materials                          \r
7 are licensed and made available under the terms and conditions of the BSD License         \r
8 which accompanies this distribution.  The full text of the license may be found at        \r
9 http://opensource.org/licenses/bsd-license.php                                            \r
10                                                                                           \r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
13 \r
14 **/\r
15 \r
16 #include "stdio.h"\r
17 #include "stdlib.h"\r
18 #include "string.h"\r
19 #include "VfrCompiler.h"\r
20 #include "CommonLib.h"\r
21 #include "EfiUtilityMsgs.h"\r
22 \r
23 PACKAGE_DATA  gCBuffer;\r
24 PACKAGE_DATA  gRBuffer;\r
25 \r
26 VOID \r
27 CVfrCompiler::DebugError (\r
28   IN CHAR8         *FileName,\r
29   IN UINT32        LineNumber,\r
30   IN UINT32        MessageCode,\r
31   IN CONST CHAR8   *Text,\r
32   IN CONST CHAR8   *MsgFmt,\r
33   ...\r
34   ) \r
35 {\r
36   va_list List;\r
37   va_start (List, MsgFmt);\r
38   PrintMessage ((CHAR8 *) "ERROR", FileName, LineNumber, MessageCode, (CHAR8 *) Text, (CHAR8 *) MsgFmt, List);\r
39   va_end (List);\r
40 }\r
41 \r
42 VOID\r
43 CVfrCompiler::SET_RUN_STATUS (\r
44   IN COMPILER_RUN_STATUS Status\r
45   )\r
46 {\r
47   mRunStatus = Status;\r
48 }\r
49 \r
50 BOOLEAN\r
51 CVfrCompiler::IS_RUN_STATUS (\r
52   IN COMPILER_RUN_STATUS Status\r
53   )\r
54 {\r
55   return mRunStatus == Status;\r
56 }\r
57 \r
58 VOID\r
59 CVfrCompiler::OptionInitialization (\r
60   IN INT32      Argc, \r
61   IN CHAR8      **Argv\r
62   )\r
63 {\r
64   INT32         Index;\r
65   \r
66   SetUtilityName ((CHAR8*) PROGRAM_NAME);\r
67 \r
68   mOptions.VfrFileName[0]                = '\0';\r
69   mOptions.RecordListFile[0]             = '\0';\r
70   mOptions.CreateRecordListFile          = FALSE;\r
71   mOptions.CreateIfrPkgFile              = FALSE;\r
72   mOptions.PkgOutputFileName[0]          = '\0';\r
73   mOptions.COutputFileName[0]            = '\0';\r
74   mOptions.OutputDirectory[0]            = '\0';\r
75   mOptions.PreprocessorOutputFileName[0] = '\0';\r
76   mOptions.VfrBaseFileName[0]            = '\0';\r
77   mOptions.IncludePaths                  = NULL;\r
78   mOptions.SkipCPreprocessor             = TRUE;\r
79   mOptions.CPreprocessorOptions          = NULL;\r
80   mOptions.CompatibleMode                = FALSE;\r
81   \r
82   if (Argc == 1) {\r
83     Usage ();\r
84     SET_RUN_STATUS (STATUS_DEAD);\r
85     return;\r
86   }\r
87 \r
88   for (Index = 1; (Index < Argc) && (Argv[Index][0] == '-'); Index++) {\r
89     if ((stricmp(Argv[Index], "-h") == 0) || (stricmp(Argv[Index], "--help") == 0)) {\r
90       Usage ();\r
91       SET_RUN_STATUS (STATUS_DEAD);\r
92       return;\r
93     } else if (stricmp(Argv[Index], "-l") == 0) {\r
94       mOptions.CreateRecordListFile = TRUE;\r
95       gCIfrRecordInfoDB.TurnOn ();\r
96     } else if (stricmp(Argv[Index], "-i") == 0) {\r
97       Index++;\r
98       if ((Index >= Argc) || (Argv[Index][0] == '-')) {\r
99         DebugError (NULL, 0, 1001, "Missing option", "-i missing path argument"); \r
100         goto Fail;\r
101       }\r
102 \r
103       AppendIncludePath(Argv[Index]);\r
104     } else if (stricmp(Argv[Index], "-o") == 0 || stricmp(Argv[Index], "--output-directory") == 0 || stricmp(Argv[Index], "-od") == 0) {\r
105       Index++;\r
106       if ((Index >= Argc) || (Argv[Index][0] == '-')) {\r
107         DebugError (NULL, 0, 1001, "Missing option", "-o missing output directory name");\r
108         goto Fail;\r
109       }\r
110       strcpy (mOptions.OutputDirectory, Argv[Index]);\r
111       \r
112       CHAR8 lastChar = mOptions.OutputDirectory[strlen(mOptions.OutputDirectory) - 1];\r
113       if ((lastChar != '/') && (lastChar != '\\')) {\r
114         if (strchr(mOptions.OutputDirectory, '/') != NULL) {\r
115           strcat (mOptions.OutputDirectory, "/");\r
116         } else {\r
117           strcat (mOptions.OutputDirectory, "\\");\r
118         }\r
119       }\r
120       DebugMsg (NULL, 0, 9, (CHAR8 *) "Output Directory", mOptions.OutputDirectory);\r
121     } else if (stricmp(Argv[Index], "-b") == 0 || stricmp(Argv[Index], "--create-ifr-package") == 0 || stricmp(Argv[Index], "-ibin") == 0) {\r
122       mOptions.CreateIfrPkgFile = TRUE;\r
123     } else if (stricmp(Argv[Index], "-n") == 0 || stricmp(Argv[Index], "--no-pre-processing") == 0 || stricmp(Argv[Index], "-nopp") == 0) {\r
124       mOptions.SkipCPreprocessor = TRUE;\r
125     } else if (stricmp(Argv[Index], "-f") == 0 || stricmp(Argv[Index], "--pre-processing-flag") == 0 || stricmp(Argv[Index], "-ppflag") == 0) {\r
126       Index++;\r
127       if ((Index >= Argc) || (Argv[Index][0] == '-')) {\r
128         DebugError (NULL, 0, 1001, "Missing option", "-od - missing C-preprocessor argument");\r
129         goto Fail;\r
130       }\r
131 \r
132       AppendCPreprocessorOptions (Argv[Index]);\r
133     } else if (stricmp(Argv[Index], "-c") == 0 || stricmp(Argv[Index], "--compatible-framework") == 0) {\r
134       mOptions.CompatibleMode = TRUE;\r
135     } else {\r
136       DebugError (NULL, 0, 1000, "Unknown option", "unrecognized option %s", Argv[Index]);\r
137       goto Fail;\r
138     }\r
139   }\r
140 \r
141   if (Index != Argc - 1) {\r
142     DebugError (NULL, 0, 1001, "Missing option", "VFR file name is not specified.");\r
143     goto Fail;\r
144   } else {\r
145     strcpy (mOptions.VfrFileName, Argv[Index]);\r
146   }\r
147 \r
148   if (SetBaseFileName() != 0) {\r
149     goto Fail;\r
150   }\r
151   if (SetPkgOutputFileName () != 0) {\r
152     goto Fail;\r
153   }\r
154   if (SetCOutputFileName() != 0) {\r
155     goto Fail;\r
156   }\r
157   if (SetPreprocessorOutputFileName () != 0) {\r
158     goto Fail;\r
159   }\r
160   if (SetRecordListFileName () != 0) {\r
161     goto Fail;\r
162   }\r
163   return;\r
164 \r
165 Fail:\r
166   SET_RUN_STATUS (STATUS_DEAD);\r
167 \r
168   mOptions.VfrFileName[0]                = '\0';\r
169   mOptions.RecordListFile[0]             = '\0';\r
170   mOptions.CreateRecordListFile          = FALSE;\r
171   mOptions.CreateIfrPkgFile              = FALSE;\r
172   mOptions.PkgOutputFileName[0]          = '\0';\r
173   mOptions.COutputFileName[0]            = '\0';\r
174   mOptions.OutputDirectory[0]            = '\0';\r
175   mOptions.PreprocessorOutputFileName[0] = '\0';\r
176   mOptions.VfrBaseFileName[0]            = '\0';\r
177   if (mOptions.IncludePaths != NULL) {\r
178     delete mOptions.IncludePaths;\r
179     mOptions.IncludePaths                = NULL;\r
180   } \r
181   if (mOptions.CPreprocessorOptions != NULL) {\r
182     delete mOptions.CPreprocessorOptions;\r
183     mOptions.CPreprocessorOptions        = NULL;\r
184   }\r
185 }\r
186 \r
187 VOID\r
188 CVfrCompiler::AppendIncludePath (\r
189   IN CHAR8      *PathStr\r
190   )\r
191 {\r
192   UINT32  Len           = 0;\r
193   CHAR8   *IncludePaths = NULL;\r
194 \r
195   Len = strlen (" -I ") + strlen (PathStr) + 1;\r
196   if (mOptions.IncludePaths != NULL) {\r
197     Len += strlen (mOptions.IncludePaths);\r
198   }\r
199   IncludePaths = new CHAR8[Len];\r
200   if (IncludePaths == NULL) {\r
201     DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);\r
202     return;\r
203   }\r
204   IncludePaths[0] = '\0';\r
205   if (mOptions.IncludePaths != NULL) {\r
206     strcat (IncludePaths, mOptions.IncludePaths);\r
207   }\r
208   strcat (IncludePaths, " -I ");\r
209   strcat (IncludePaths, PathStr);\r
210   if (mOptions.IncludePaths != NULL) {\r
211     delete mOptions.IncludePaths;\r
212   }\r
213   mOptions.IncludePaths = IncludePaths;\r
214 }\r
215 \r
216 VOID\r
217 CVfrCompiler::AppendCPreprocessorOptions (\r
218   IN CHAR8      *Options\r
219   )\r
220 {\r
221   UINT32  Len           = 0;\r
222   CHAR8   *Opt          = NULL;\r
223 \r
224   Len = strlen (Options) + strlen (" ") + 1;\r
225   if (mOptions.CPreprocessorOptions != NULL) {\r
226     Len += strlen (mOptions.CPreprocessorOptions);\r
227   }\r
228   Opt = new CHAR8[Len];\r
229   if (Opt == NULL) {\r
230     DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);\r
231     return;\r
232   }\r
233   Opt[0] = 0;\r
234   if (mOptions.CPreprocessorOptions != NULL) {\r
235     strcat (Opt, mOptions.CPreprocessorOptions);\r
236   }\r
237   strcat (Opt, " ");\r
238   strcat (Opt, Options);\r
239   if (mOptions.CPreprocessorOptions != NULL) {\r
240     delete mOptions.CPreprocessorOptions;\r
241   }\r
242   mOptions.CPreprocessorOptions = Opt;\r
243 }\r
244 \r
245 INT8\r
246 CVfrCompiler::SetBaseFileName (\r
247   VOID\r
248   )\r
249 {\r
250   CHAR8         *pFileName, *pPath, *pExt;\r
251 \r
252   if (mOptions.VfrFileName[0] == '\0') {\r
253     return -1;\r
254   }\r
255 \r
256   pFileName = mOptions.VfrFileName;\r
257   while (\r
258     ((pPath = strchr (pFileName, '\\')) != NULL) ||\r
259     ((pPath = strchr (pFileName, '/')) != NULL)\r
260     )\r
261   {\r
262     pFileName = pPath + 1;\r
263   }\r
264 \r
265   if (pFileName == NULL) {\r
266     return -1;\r
267   }\r
268 \r
269   if ((pExt = strchr (pFileName, '.')) == NULL) {\r
270     return -1;\r
271   }\r
272 \r
273   strncpy (mOptions.VfrBaseFileName, pFileName, pExt - pFileName);\r
274   mOptions.VfrBaseFileName[pExt - pFileName] = '\0';\r
275 \r
276   return 0;\r
277 }\r
278 \r
279 INT8\r
280 CVfrCompiler::SetPkgOutputFileName (\r
281   VOID\r
282   )\r
283 {\r
284   if (mOptions.VfrBaseFileName[0] == '\0') {\r
285     return -1;\r
286   }\r
287 \r
288   strcpy (mOptions.PkgOutputFileName, mOptions.OutputDirectory);\r
289   strcat (mOptions.PkgOutputFileName, mOptions.VfrBaseFileName);\r
290   strcat (mOptions.PkgOutputFileName, VFR_PACKAGE_FILENAME_EXTENSION);\r
291 \r
292   return 0;\r
293 }\r
294 \r
295 INT8\r
296 CVfrCompiler::SetCOutputFileName (\r
297   VOID\r
298   )\r
299 {\r
300   if (mOptions.VfrBaseFileName[0] == '\0') {\r
301     return -1;\r
302   }\r
303 \r
304   strcpy (mOptions.COutputFileName, mOptions.OutputDirectory);\r
305   strcat (mOptions.COutputFileName, mOptions.VfrBaseFileName);\r
306   strcat (mOptions.COutputFileName, ".c");\r
307 \r
308   return 0;\r
309 }\r
310 \r
311 INT8\r
312 CVfrCompiler::SetPreprocessorOutputFileName (\r
313   VOID\r
314   )\r
315 {\r
316   if (mOptions.VfrBaseFileName[0] == '\0') {\r
317     return -1;\r
318   }\r
319 \r
320   strcpy (mOptions.PreprocessorOutputFileName, mOptions.OutputDirectory);\r
321   strcat (mOptions.PreprocessorOutputFileName, mOptions.VfrBaseFileName);\r
322   strcat (mOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION);\r
323 \r
324   return 0;\r
325 }\r
326 \r
327 INT8\r
328 CVfrCompiler::SetRecordListFileName (\r
329   VOID\r
330   )\r
331 {\r
332   if (mOptions.VfrBaseFileName[0] == '\0') {\r
333     return -1;\r
334   }\r
335 \r
336   strcpy (mOptions.RecordListFile, mOptions.OutputDirectory);\r
337   strcat (mOptions.RecordListFile, mOptions.VfrBaseFileName);\r
338   strcat (mOptions.RecordListFile, VFR_RECORDLIST_FILENAME_EXTENSION);\r
339 \r
340   return 0;\r
341 }\r
342 \r
343 CVfrCompiler::CVfrCompiler (\r
344   IN INT32      Argc, \r
345   IN CHAR8      **Argv\r
346   )\r
347 {\r
348   mPreProcessCmd = (CHAR8 *) PREPROCESSOR_COMMAND;\r
349   mPreProcessOpt = (CHAR8 *) PREPROCESSOR_OPTIONS;\r
350 \r
351   OptionInitialization(Argc, Argv);\r
352 \r
353   if ((IS_RUN_STATUS(STATUS_FAILED)) || (IS_RUN_STATUS(STATUS_DEAD))) {\r
354     return;\r
355   }\r
356 \r
357   SET_RUN_STATUS(STATUS_INITIALIZED);\r
358 }\r
359 \r
360 CVfrCompiler::~CVfrCompiler (\r
361   VOID\r
362   )\r
363 {\r
364   if (mOptions.IncludePaths != NULL) {\r
365     delete mOptions.IncludePaths;\r
366     mOptions.IncludePaths = NULL;\r
367   }\r
368 \r
369   if (mOptions.CPreprocessorOptions != NULL) {\r
370     delete mOptions.CPreprocessorOptions;\r
371     mOptions.CPreprocessorOptions = NULL;\r
372   }\r
373 \r
374   SET_RUN_STATUS(STATUS_DEAD);\r
375 }\r
376 \r
377 VOID \r
378 CVfrCompiler::Usage (\r
379   VOID\r
380   )\r
381 {\r
382   UINT32 Index;\r
383   CONST  CHAR8 *Help[] = {\r
384     " ", \r
385     "VfrCompile version " VFR_COMPILER_VERSION VFR_COMPILER_UPDATE_TIME,\r
386     "Copyright (c) 2004-2010 Intel Corporation. All rights reserved.",\r
387     " ",\r
388     "Usage: VfrCompile [options] VfrFile",\r
389     " ",\r
390     "Options:",\r
391     "  -h, --help     prints this help",\r
392     "  -l             create an output IFR listing file",\r
393     "  -o DIR, --output-directory DIR",\r
394     "                 deposit all output files to directory OutputDir",\r
395     "                 default is current directory",\r
396     "  -b, --create-ifr-package",\r
397     "                 create an IFR HII pack file",\r
398     "  -n, --no-pre-processing",\r
399     "                 do not preprocessing input file",\r
400     "  -c, --compatible-framework",\r
401     "                 compatible framework vfr file",\r
402     NULL\r
403     };\r
404   for (Index = 0; Help[Index] != NULL; Index++) {\r
405     fprintf (stdout, "%s\n", Help[Index]);\r
406   }\r
407 }\r
408 \r
409 VOID\r
410 CVfrCompiler::PreProcess (\r
411   VOID\r
412   )\r
413 {\r
414   FILE    *pVfrFile      = NULL;\r
415   UINT32  CmdLen         = 0;\r
416   CHAR8   *PreProcessCmd = NULL;\r
417 \r
418   if (!IS_RUN_STATUS(STATUS_INITIALIZED)) {\r
419     goto Fail;\r
420   }\r
421 \r
422   if (mOptions.SkipCPreprocessor == TRUE) {\r
423     goto Out;\r
424   }\r
425 \r
426   if ((pVfrFile = fopen (mOptions.VfrFileName, "r")) == NULL) {\r
427     DebugError (NULL, 0, 0001, "Error opening the input VFR file", mOptions.VfrFileName);\r
428     goto Fail;\r
429   }\r
430   fclose (pVfrFile);\r
431 \r
432   CmdLen = strlen (mPreProcessCmd) + strlen (mPreProcessOpt) + \r
433                strlen (mOptions.VfrFileName) + strlen (mOptions.PreprocessorOutputFileName);\r
434   if (mOptions.CPreprocessorOptions != NULL) {\r
435     CmdLen += strlen (mOptions.CPreprocessorOptions);\r
436   }\r
437   if (mOptions.IncludePaths != NULL) {\r
438     CmdLen += strlen (mOptions.IncludePaths);\r
439   }\r
440 \r
441   PreProcessCmd = new CHAR8[CmdLen + 10];\r
442   if (PreProcessCmd == NULL) {\r
443     DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL);\r
444     goto Fail;\r
445   }\r
446   strcpy (PreProcessCmd, mPreProcessCmd), strcat (PreProcessCmd, " ");\r
447   strcat (PreProcessCmd, mPreProcessOpt), strcat (PreProcessCmd, " ");\r
448   if (mOptions.IncludePaths != NULL) {\r
449     strcat (PreProcessCmd, mOptions.IncludePaths), strcat (PreProcessCmd, " ");\r
450   }\r
451   if (mOptions.CPreprocessorOptions != NULL) {\r
452     strcat (PreProcessCmd, mOptions.CPreprocessorOptions), strcat (PreProcessCmd, " ");\r
453   }\r
454   strcat (PreProcessCmd, mOptions.VfrFileName), strcat (PreProcessCmd, " > ");\r
455   strcat (PreProcessCmd, mOptions.PreprocessorOutputFileName);\r
456 \r
457   if (system (PreProcessCmd) != 0) {\r
458     DebugError (NULL, 0, 0003, "Error parsing file", "failed to spawn C preprocessor on VFR file %s\n", PreProcessCmd);\r
459     goto Fail;\r
460   }\r
461 \r
462   delete PreProcessCmd;\r
463 \r
464 Out:\r
465   SET_RUN_STATUS (STATUS_PREPROCESSED);\r
466   return;\r
467 \r
468 Fail:\r
469   if (!IS_RUN_STATUS(STATUS_DEAD)) {\r
470     SET_RUN_STATUS (STATUS_FAILED);\r
471   }\r
472   delete PreProcessCmd;\r
473 }\r
474 \r
475 extern UINT8 VfrParserStart (IN FILE *, IN BOOLEAN);\r
476 \r
477 VOID\r
478 CVfrCompiler::Compile (\r
479   VOID\r
480   )\r
481 {\r
482   FILE  *pInFile    = NULL;\r
483   CHAR8 *InFileName = NULL;\r
484 \r
485   if (!IS_RUN_STATUS(STATUS_PREPROCESSED)) {\r
486     goto Fail;\r
487   }\r
488 \r
489   InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;\r
490 \r
491   gCVfrErrorHandle.SetInputFile (InFileName);\r
492 \r
493   if ((pInFile = fopen (InFileName, "r")) == NULL) {\r
494     DebugError (NULL, 0, 0001, "Error opening the input file", InFileName);\r
495     goto Fail;\r
496   }\r
497 \r
498   if (VfrParserStart (pInFile, mOptions.CompatibleMode) != 0) {\r
499     goto Fail;\r
500   }\r
501 \r
502   fclose (pInFile);\r
503 \r
504   if (gCFormPkg.HavePendingUnassigned () == TRUE) {\r
505     gCFormPkg.PendingAssignPrintAll ();\r
506     goto Fail;\r
507   }\r
508 \r
509   SET_RUN_STATUS (STATUS_COMPILEED);\r
510   return;\r
511 \r
512 Fail:\r
513   if (!IS_RUN_STATUS(STATUS_DEAD)) {\r
514     DebugError (NULL, 0, 0003, "Error parsing", "compile error in file %s", InFileName);\r
515     SET_RUN_STATUS (STATUS_FAILED);\r
516   }\r
517   if (pInFile != NULL) {\r
518     fclose (pInFile);\r
519   }\r
520 }\r
521 \r
522 VOID\r
523 CVfrCompiler::AdjustBin (\r
524   VOID\r
525   )\r
526 {\r
527   EFI_VFR_RETURN_CODE Status;\r
528   //\r
529   // Check Binary Code consistent between Form and IfrRecord\r
530   //\r
531 \r
532   //\r
533   // Get Package Data and IfrRecord Data\r
534   //\r
535   gCFormPkg.BuildPkg (gCBuffer);\r
536   gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer); \r
537 \r
538   //\r
539   // Compare Form and Record data\r
540   //\r
541   if (gCBuffer.Buffer != NULL && gRBuffer.Buffer != NULL) {\r
542     UINT32 Index;\r
543     if (gCBuffer.Size != gRBuffer.Size) {\r
544       DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s. FormBinary Size 0x%X is not same to RecordBuffer Size 0x%X", mOptions.VfrFileName, gCBuffer.Size, gRBuffer.Size);\r
545     }\r
546     for (Index = 0; Index < gCBuffer.Size; Index ++) {\r
547       if (gCBuffer.Buffer[Index] != gRBuffer.Buffer[Index]) {\r
548         break;\r
549       }\r
550     }\r
551     if (Index != gCBuffer.Size) {\r
552       DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s. the 0x%X byte is different between Form and Record", mOptions.VfrFileName, Index);\r
553     }\r
554     DebugMsg (NULL, 0, 9, (CHAR8 *) "IFR Buffer", (CHAR8 *) "Form Buffer same to Record Buffer and Size is 0x%X", Index);\r
555   } else if (gCBuffer.Buffer == NULL && gRBuffer.Buffer == NULL) {\r
556     //ok\r
557   } else {\r
558     DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s.Buffer not allocated.", mOptions.VfrFileName);\r
559   }\r
560 \r
561   //\r
562   // For UEFI mode, not do OpCode Adjust\r
563   //\r
564   if (mOptions.CompatibleMode) {\r
565     //\r
566     // Adjust Opcode to be compatible with framework vfr\r
567     //\r
568     Status = gCIfrRecordInfoDB.IfrRecordAdjust ();\r
569     if (Status != VFR_RETURN_SUCCESS) {\r
570       //\r
571       // Record List Adjust Failed\r
572       //\r
573       SET_RUN_STATUS (STATUS_FAILED);\r
574       return;\r
575     }\r
576     //\r
577     // Re get the IfrRecord Buffer.\r
578     //\r
579     gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer); \r
580   }\r
581 \r
582   return;\r
583 }\r
584 \r
585 VOID\r
586 CVfrCompiler::GenBinary (\r
587   VOID\r
588   )\r
589 {\r
590   FILE                    *pFile = NULL;\r
591 \r
592   if (!IS_RUN_STATUS(STATUS_COMPILEED)) {\r
593     goto Fail;\r
594   }\r
595 \r
596   if (mOptions.CreateIfrPkgFile == TRUE) {\r
597     if ((pFile = fopen (mOptions.PkgOutputFileName, "wb")) == NULL) {\r
598       DebugError (NULL, 0, 0001, "Error opening file", mOptions.PkgOutputFileName);\r
599       goto Fail;\r
600     }\r
601     if (gCFormPkg.BuildPkg (pFile, &gRBuffer) != VFR_RETURN_SUCCESS) {\r
602       fclose (pFile);\r
603       goto Fail;\r
604     }\r
605     fclose (pFile);\r
606   }\r
607 \r
608   SET_RUN_STATUS (STATUS_GENBINARY);\r
609 \r
610   return;\r
611 \r
612 Fail:\r
613   if (!IS_RUN_STATUS(STATUS_DEAD)) {\r
614     SET_RUN_STATUS (STATUS_FAILED);\r
615   }\r
616 }\r
617 \r
618 static const char *gSourceFileHeader[] = {\r
619   "//",\r
620   "//  DO NOT EDIT -- auto-generated file",\r
621   "//",\r
622   "//  This file is generated by the vfrcompiler utility",\r
623   "//",\r
624   NULL\r
625 };\r
626 \r
627 VOID\r
628 CVfrCompiler::GenCFile (\r
629   VOID\r
630   )\r
631 {\r
632   FILE                    *pFile;\r
633   UINT32                  Index;\r
634 \r
635   if (!IS_RUN_STATUS(STATUS_GENBINARY)) {\r
636     goto Fail;\r
637   }\r
638   \r
639   if (!mOptions.CreateIfrPkgFile || mOptions.CompatibleMode) {\r
640     if ((pFile = fopen (mOptions.COutputFileName, "w")) == NULL) {\r
641       DebugError (NULL, 0, 0001, "Error opening output C file", mOptions.COutputFileName);\r
642       goto Fail;\r
643     }\r
644 \r
645     for (Index = 0; gSourceFileHeader[Index] != NULL; Index++) {\r
646       fprintf (pFile, "%s\n", gSourceFileHeader[Index]);\r
647     }\r
648 \r
649     if (mOptions.CompatibleMode) { \r
650       gCVfrBufferConfig.OutputCFile (pFile, mOptions.VfrBaseFileName);\r
651     }\r
652 \r
653     if (gCFormPkg.GenCFile (mOptions.VfrBaseFileName, pFile, &gRBuffer) != VFR_RETURN_SUCCESS) {\r
654       fclose (pFile);\r
655       goto Fail;\r
656     }\r
657     fclose (pFile);\r
658   }\r
659 \r
660   SET_RUN_STATUS (STATUS_FINISHED);\r
661   return;\r
662 \r
663 Fail:\r
664   if (!IS_RUN_STATUS(STATUS_DEAD)) {\r
665     SET_RUN_STATUS (STATUS_FAILED);\r
666   }\r
667 }\r
668 \r
669 VOID\r
670 CVfrCompiler::GenRecordListFile (\r
671   VOID\r
672   )\r
673 {\r
674   CHAR8  *InFileName = NULL;\r
675   FILE   *pInFile    = NULL;\r
676   FILE   *pOutFile   = NULL;\r
677   CHAR8  LineBuf[MAX_VFR_LINE_LEN];\r
678   UINT32 LineNo;\r
679 \r
680   InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;\r
681 \r
682   if (mOptions.CreateRecordListFile == TRUE) {\r
683     if ((InFileName[0] == '\0') || (mOptions.RecordListFile[0] == '\0')) {\r
684       return;\r
685     }\r
686 \r
687     if ((pInFile = fopen (InFileName, "r")) == NULL) {\r
688       DebugError (NULL, 0, 0001, "Error opening the input VFR preprocessor output file", InFileName);\r
689       return;\r
690     }\r
691 \r
692     if ((pOutFile = fopen (mOptions.RecordListFile, "w")) == NULL) {\r
693       DebugError (NULL, 0, 0001, "Error opening the record list file", mOptions.RecordListFile);\r
694       goto Err1;\r
695     }\r
696 \r
697     fprintf (pOutFile, "//\n//  VFR compiler version " VFR_COMPILER_VERSION "\n//\n");\r
698     LineNo = 0;\r
699     while (!feof (pInFile)) {\r
700       if (fgets (LineBuf, MAX_VFR_LINE_LEN, pInFile) != NULL) {\r
701         fprintf (pOutFile, "%s", LineBuf);\r
702         LineNo++;\r
703         gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, LineNo);\r
704       }\r
705     }\r
706     \r
707     fprintf (pOutFile, "\n//\n// All Opcode Record List \n//\n");\r
708     gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, 0);\r
709     gCVfrVarDataTypeDB.Dump(pOutFile);\r
710 \r
711     fclose (pOutFile);\r
712     fclose (pInFile);\r
713   }\r
714 \r
715   return;\r
716 \r
717 Err1:\r
718   fclose (pInFile);\r
719 }\r
720 \r
721 int\r
722 main (\r
723   IN int             Argc, \r
724   IN char            **Argv\r
725   )\r
726 {\r
727   COMPILER_RUN_STATUS  Status;\r
728   CVfrCompiler         Compiler(Argc, Argv);\r
729   \r
730   Compiler.PreProcess();\r
731   Compiler.Compile();\r
732   Compiler.AdjustBin();\r
733   Compiler.GenBinary();\r
734   Compiler.GenCFile();\r
735   Compiler.GenRecordListFile ();\r
736 \r
737   Status = Compiler.RunStatus ();\r
738   if ((Status == STATUS_DEAD) || (Status == STATUS_FAILED)) {\r
739     return 2;\r
740   }\r
741 \r
742   if (gCBuffer.Buffer != NULL) {\r
743     delete gCBuffer.Buffer;\r
744   }\r
745   \r
746   if (gRBuffer.Buffer != NULL) {\r
747     delete gRBuffer.Buffer;\r
748   }\r
749 \r
750   return GetUtilityStatus ();\r
751 }\r
752 \r
753 \r