Standardized the command line options.
[people/mcb30/basetools.git] / Source / C / VfrCompile / VfrCompiler.cpp
1 #include "stdio.h"\r
2 #include "string.h"\r
3 #include "process.h"\r
4 #include "VfrCompiler.h"\r
5 \r
6 \r
7 VOID\r
8 CVfrCompiler::SET_RUN_STATUS (\r
9   IN COMPILER_RUN_STATUS Status\r
10   )\r
11 {\r
12   mRunStatus = Status;\r
13 }\r
14 \r
15 BOOLEAN\r
16 CVfrCompiler::IS_RUN_STATUS (\r
17   IN COMPILER_RUN_STATUS Status\r
18   )\r
19 {\r
20   return mRunStatus == Status;\r
21 }\r
22 \r
23 VOID\r
24 CVfrCompiler::OptionInitialization (\r
25   IN INT32      Argc, \r
26   IN INT8       **Argv\r
27   )\r
28 {\r
29   INT32         Index;\r
30 \r
31   mOptions.VfrFileName[0]                = '\0';\r
32   mOptions.RecordListFile[0]             = '\0';\r
33   mOptions.CreateRecordListFile          = FALSE;\r
34   mOptions.CreateIfrPkgFile              = FALSE;\r
35   mOptions.PkgOutputFileName[0]          = '\0';\r
36   mOptions.COutputFileName[0]            = '\0';\r
37   mOptions.OutputDirectory[0]            = '\0';\r
38   mOptions.PreprocessorOutputFileName[0] = '\0';\r
39   mOptions.VfrBaseFileName[0]            = '\0';\r
40   mOptions.IncludePaths                  = NULL;\r
41   mOptions.SkipCPreprocessor             = FALSE;\r
42   mOptions.CPreprocessorOptions          = NULL;\r
43 \r
44   for (Index = 1; (Index < Argc) && (Argv[Index][0] == '-'); Index++) {\r
45     if ((_stricmp(Argv[Index], "-h") == 0) || (_stricmp(Argv[Index], "--help") == 0)) {\r
46       Usage ();\r
47       SET_RUN_STATUS (STATUS_DEAD);\r
48       return;\r
49     } else if (_stricmp(Argv[Index], "-l") == 0) {\r
50       mOptions.CreateRecordListFile = TRUE;\r
51       gCIfrRecordInfoDB.TurnOn ();\r
52     } else if (_stricmp(Argv[Index], "-i") == 0) {\r
53       Index++;\r
54       if ((Index >= Argc) || (Argv[Index][0] == '-')) {\r
55         printf ("%s -i - missing path argument\n", PROGRAM_NAME);\r
56         goto Fail;\r
57       }\r
58 \r
59       AppendIncludePath(Argv[Index]);\r
60     } else if (_stricmp(Argv[Index], "-o") == 0 || _stricmp(Argv[Index], "--output-directory") == 0) {\r
61       Index++;\r
62       if ((Index >= Argc) || (Argv[Index][0] == '-')) {\r
63         printf ("%s -od - missing output directory name\n", PROGRAM_NAME);\r
64         goto Fail;\r
65       }\r
66       strcpy (mOptions.OutputDirectory, Argv[Index]);\r
67       strcat (mOptions.OutputDirectory, "\\");\r
68     } else if (_stricmp(Argv[Index], "-b") == 0 || _stricmp(Argv[Index], "--create-ifr-package") == 0) {\r
69       mOptions.CreateIfrPkgFile = TRUE;\r
70     } else if (_stricmp(Argv[Index], "--no-strings") == 0) {\r
71     } else if (_stricmp(Argv[Index], "-n") == 0 || _stricmp(Argv[Index], "--no-preprocessing") == 0) {\r
72       mOptions.SkipCPreprocessor = TRUE;\r
73     } else if (_stricmp(Argv[Index], "-f") == 0 || _stricmp(Argv[Index], "--preprocessing-flag") == 0) {\r
74       Index++;\r
75       if ((Index >= Argc) || (Argv[Index][0] == '-')) {\r
76         printf ("%s -od - missing C-preprocessor argument\n", PROGRAM_NAME);\r
77         goto Fail;\r
78       }\r
79 \r
80       AppendCPreprocessorOptions (Argv[Index]);\r
81     } else {\r
82       printf ("%s unrecognized option %s\n", PROGRAM_NAME, Argv[Index]);\r
83       Usage ();\r
84       goto Fail;\r
85     }\r
86   }\r
87 \r
88   if (Index != Argc - 1) {\r
89     printf ("%s must specify VFR file name", PROGRAM_NAME);\r
90     Usage ();\r
91     goto Fail;\r
92   } else {\r
93     strcpy (mOptions.VfrFileName, Argv[Index]);\r
94   }\r
95 \r
96   if (SetBaseFileName() != 0) {\r
97     goto Fail;\r
98   }\r
99   if (SetPkgOutputFileName () != 0) {\r
100     goto Fail;\r
101   }\r
102   if (SetCOutputFileName() != 0) {\r
103     goto Fail;\r
104   }\r
105   if (SetPreprocessorOutputFileName () != 0) {\r
106     goto Fail;\r
107   }\r
108   if (SetRecordListFileName () != 0) {\r
109     goto Fail;\r
110   }\r
111   return;\r
112 \r
113 Fail:\r
114   SET_RUN_STATUS (STATUS_FAILED);\r
115 \r
116   mOptions.VfrFileName[0]                = '\0';\r
117   mOptions.RecordListFile[0]             = '\0';\r
118   mOptions.CreateRecordListFile          = FALSE;\r
119   mOptions.CreateIfrPkgFile              = FALSE;\r
120   mOptions.PkgOutputFileName[0]          = '\0';\r
121   mOptions.COutputFileName[0]            = '\0';\r
122   mOptions.OutputDirectory[0]            = '\0';\r
123   mOptions.PreprocessorOutputFileName[0] = '\0';\r
124   mOptions.VfrBaseFileName[0]            = '\0';\r
125   if (mOptions.IncludePaths != NULL) {\r
126     delete mOptions.IncludePaths;\r
127     mOptions.IncludePaths                = NULL;\r
128   } \r
129   if (mOptions.CPreprocessorOptions != NULL) {\r
130     delete mOptions.CPreprocessorOptions;\r
131     mOptions.CPreprocessorOptions        = NULL;\r
132   }\r
133 }\r
134 \r
135 VOID\r
136 CVfrCompiler::AppendIncludePath (\r
137   IN INT8       *PathStr\r
138   )\r
139 {\r
140   UINT32  Len           = 0;\r
141   INT8    *IncludePaths = NULL;\r
142 \r
143   Len = strlen (" -I ") + strlen (PathStr) + 1;\r
144   if (mOptions.IncludePaths != NULL) {\r
145     Len += strlen (mOptions.IncludePaths);\r
146   }\r
147   IncludePaths = new INT8[Len];\r
148   if (IncludePaths == NULL) {\r
149     printf ("%s memory allocation failure\n", PROGRAM_NAME);\r
150     return;\r
151   }\r
152   IncludePaths[0] = '\0';\r
153   if (mOptions.IncludePaths != NULL) {\r
154     strcat (IncludePaths, mOptions.IncludePaths);\r
155   }\r
156   strcat (IncludePaths, " -I ");\r
157   strcat (IncludePaths, PathStr);\r
158   if (mOptions.IncludePaths != NULL) {\r
159     delete mOptions.IncludePaths;\r
160   }\r
161   mOptions.IncludePaths = IncludePaths;\r
162 }\r
163 \r
164 VOID\r
165 CVfrCompiler::AppendCPreprocessorOptions (\r
166   IN INT8       *Options\r
167   )\r
168 {\r
169   UINT32  Len           = 0;\r
170   INT8    *Opt          = NULL;\r
171 \r
172   Len = strlen (Options) + strlen (" ") + 1;\r
173   if (mOptions.CPreprocessorOptions != NULL) {\r
174     Len += strlen (mOptions.CPreprocessorOptions);\r
175   }\r
176   Opt = new INT8[Len];\r
177   if (Opt == NULL) {\r
178     printf ("%s memory allocation failure\n", PROGRAM_NAME);\r
179     return;\r
180   }\r
181   Opt[0] = 0;\r
182   if (mOptions.CPreprocessorOptions != NULL) {\r
183     strcat (Opt, mOptions.CPreprocessorOptions);\r
184   }\r
185   strcat (Opt, " ");\r
186   strcat (Opt, Options);\r
187   if (mOptions.CPreprocessorOptions != NULL) {\r
188     delete mOptions.CPreprocessorOptions;\r
189   }\r
190   mOptions.CPreprocessorOptions = Opt;\r
191 }\r
192 \r
193 INT8\r
194 CVfrCompiler::SetBaseFileName (\r
195   VOID\r
196   )\r
197 {\r
198   INT8          *pFileName, *pPath, *pExt;\r
199 \r
200   if (mOptions.VfrFileName[0] == '\0') {\r
201     return -1;\r
202   }\r
203 \r
204   pFileName = mOptions.VfrFileName;\r
205   while ((pPath = strchr (pFileName, '\\')) != NULL) {\r
206     pFileName = pPath + 1;\r
207   }\r
208 \r
209   if (pFileName == NULL) {\r
210     return -1;\r
211   }\r
212 \r
213   if ((pExt = strchr (pFileName, '.')) == NULL) {\r
214     return -1;\r
215   }\r
216 \r
217   strncpy (mOptions.VfrBaseFileName, pFileName, pExt - pFileName);\r
218   mOptions.VfrBaseFileName[pExt - pFileName] = '\0';\r
219 \r
220   return 0;\r
221 }\r
222 \r
223 INT8\r
224 CVfrCompiler::SetPkgOutputFileName (\r
225   VOID\r
226   )\r
227 {\r
228   if (mOptions.VfrBaseFileName[0] == '\0') {\r
229     return -1;\r
230   }\r
231 \r
232   strcpy (mOptions.PkgOutputFileName, mOptions.OutputDirectory);\r
233   strcat (mOptions.PkgOutputFileName, mOptions.VfrBaseFileName);\r
234   strcat (mOptions.PkgOutputFileName, VFR_PACKAGE_FILENAME_EXTENSION);\r
235 \r
236   return 0;\r
237 }\r
238 \r
239 INT8\r
240 CVfrCompiler::SetCOutputFileName (\r
241   VOID\r
242   )\r
243 {\r
244   if (mOptions.VfrBaseFileName[0] == '\0') {\r
245     return -1;\r
246   }\r
247 \r
248   strcpy (mOptions.COutputFileName, mOptions.OutputDirectory);\r
249   strcat (mOptions.COutputFileName, mOptions.VfrBaseFileName);\r
250   strcat (mOptions.COutputFileName, ".c");\r
251 \r
252   return 0;\r
253 }\r
254 \r
255 INT8\r
256 CVfrCompiler::SetPreprocessorOutputFileName (\r
257   VOID\r
258   )\r
259 {\r
260   if (mOptions.VfrBaseFileName[0] == '\0') {\r
261     return -1;\r
262   }\r
263 \r
264   strcpy (mOptions.PreprocessorOutputFileName, mOptions.OutputDirectory);\r
265   strcat (mOptions.PreprocessorOutputFileName, mOptions.VfrBaseFileName);\r
266   strcat (mOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION);\r
267 \r
268   return 0;\r
269 }\r
270 \r
271 INT8\r
272 CVfrCompiler::SetRecordListFileName (\r
273   VOID\r
274   )\r
275 {\r
276   if (mOptions.VfrBaseFileName[0] == '\0') {\r
277     return -1;\r
278   }\r
279 \r
280   strcpy (mOptions.RecordListFile, mOptions.OutputDirectory);\r
281   strcat (mOptions.RecordListFile, mOptions.VfrBaseFileName);\r
282   strcat (mOptions.RecordListFile, VFR_RECORDLIST_FILENAME_EXTENSION);\r
283 \r
284   return 0;\r
285 }\r
286 \r
287 CVfrCompiler::CVfrCompiler (\r
288   IN INT32      Argc, \r
289   IN INT8       **Argv\r
290   )\r
291 {\r
292   mPreProcessCmd = PREPROCESSOR_COMMAND;\r
293   mPreProcessOpt = PREPROCESSOR_OPTIONS;\r
294 \r
295   OptionInitialization(Argc, Argv);\r
296 \r
297   if ((IS_RUN_STATUS(STATUS_FAILED)) || (IS_RUN_STATUS(STATUS_DEAD))) {\r
298     return;\r
299   }\r
300 \r
301   SET_RUN_STATUS(STATUS_INITIALIZED);\r
302 }\r
303 \r
304 CVfrCompiler::~CVfrCompiler (\r
305   VOID\r
306   )\r
307 {\r
308   if (mOptions.IncludePaths != NULL) {\r
309     delete mOptions.IncludePaths;\r
310     mOptions.IncludePaths = NULL;\r
311   }\r
312 \r
313   if (mOptions.CPreprocessorOptions != NULL) {\r
314     delete mOptions.CPreprocessorOptions;\r
315     mOptions.CPreprocessorOptions = NULL;\r
316   }\r
317 \r
318   SET_RUN_STATUS(STATUS_DEAD);\r
319 }\r
320 \r
321 VOID \r
322 CVfrCompiler::Usage (\r
323   VOID\r
324   )\r
325 {\r
326   UINT32 Index;\r
327   CONST  INT8 *Help[] = {\r
328     " ", \r
329     "VfrCompile version " VFR_COMPILER_VERSION,\r
330     " ",\r
331     "Usage: VfrCompile [options] VfrFile",\r
332     " ",\r
333     "Options:",\r
334     "  -h, --help     prints this help",\r
335     "  -l             create an output IFR listing file",\r
336     "  -i IncPath     add IncPath to the search path for VFR included files",\r
337     "  -o DIR, --output-directory DIR",\r
338     "                 deposit all output files to directory OutputDir (default=cwd)",\r
339     "  -b, --create-ifr-package",\r
340     "                 create an IFR HII pack file",\r
341     "  -n, --no-pre-processing",\r
342     "                 do not preprocessing input file",\r
343     "  -f, --pre-processing-flag",\r
344     "                 Preprocessing flags",\r
345     " ",\r
346     NULL\r
347     };\r
348   for (Index = 0; Help[Index] != NULL; Index++) {\r
349     fprintf (stdout, "%s\n", Help[Index]);\r
350   }\r
351 }\r
352 \r
353 VOID\r
354 CVfrCompiler::PreProcess (\r
355   VOID\r
356   )\r
357 {\r
358   FILE    *pVfrFile      = NULL;\r
359   UINT32  CmdLen         = 0;\r
360   INT8    *PreProcessCmd = NULL;\r
361 \r
362   if (!IS_RUN_STATUS(STATUS_INITIALIZED)) {\r
363     goto Fail;\r
364   }\r
365 \r
366   if (mOptions.SkipCPreprocessor == TRUE) {\r
367     goto Out;\r
368   }\r
369 \r
370   if ((pVfrFile = fopen (mOptions.VfrFileName, "r")) == NULL) {\r
371     printf ("%s could not open input VFR file - %s\n", PROGRAM_NAME, mOptions.VfrFileName);\r
372     goto Fail;\r
373   }\r
374   fclose (pVfrFile);\r
375 \r
376   CmdLen = strlen (mPreProcessCmd) + strlen (mPreProcessOpt) + \r
377                strlen (mOptions.VfrFileName) + strlen (mOptions.PreprocessorOutputFileName);\r
378   if (mOptions.CPreprocessorOptions != NULL) {\r
379     CmdLen += strlen (mOptions.CPreprocessorOptions);\r
380   }\r
381   if (mOptions.IncludePaths != NULL) {\r
382     CmdLen += strlen (mOptions.IncludePaths);\r
383   }\r
384 \r
385   PreProcessCmd = new INT8[CmdLen + 10];\r
386   if (PreProcessCmd == NULL) {\r
387     printf ("%s could not allocate memory\n", PROGRAM_NAME);\r
388     goto Fail;\r
389   }\r
390   strcpy (PreProcessCmd, mPreProcessCmd), strcat (PreProcessCmd, " ");\r
391   strcat (PreProcessCmd, mPreProcessOpt), strcat (PreProcessCmd, " ");\r
392   if (mOptions.IncludePaths != NULL) {\r
393     strcat (PreProcessCmd, mOptions.IncludePaths), strcat (PreProcessCmd, " ");\r
394   }\r
395   if (mOptions.CPreprocessorOptions != NULL) {\r
396     strcat (PreProcessCmd, mOptions.CPreprocessorOptions), strcat (PreProcessCmd, " ");\r
397   }\r
398   strcat (PreProcessCmd, mOptions.VfrFileName), strcat (PreProcessCmd, " > ");\r
399   strcat (PreProcessCmd, mOptions.PreprocessorOutputFileName);\r
400 \r
401   if (system (PreProcessCmd) != 0) {\r
402     printf ("%s failed to spawn C preprocessor on VFR file \n\t - %s\n", PROGRAM_NAME, PreProcessCmd);\r
403     goto Fail;\r
404   }\r
405 \r
406   delete PreProcessCmd;\r
407 \r
408 Out:\r
409   SET_RUN_STATUS (STATUS_PREPROCESSED);\r
410   return;\r
411 \r
412 Fail:\r
413   if (!IS_RUN_STATUS(STATUS_DEAD)) {\r
414     SET_RUN_STATUS (STATUS_FAILED);\r
415   }\r
416   delete PreProcessCmd;\r
417 }\r
418 \r
419 extern UINT8 VfrParserStart (IN FILE *);\r
420 \r
421 VOID\r
422 CVfrCompiler::Compile (\r
423   VOID\r
424   )\r
425 {\r
426   FILE *pInFile    = NULL;\r
427   INT8 *InFileName = NULL;\r
428 \r
429   if (!IS_RUN_STATUS(STATUS_PREPROCESSED)) {\r
430     goto Fail;\r
431   }\r
432 \r
433   InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;\r
434 \r
435   gCVfrErrorHandle.SetInputFile (InFileName);\r
436 \r
437   if ((pInFile = fopen (InFileName, "r")) == NULL) {\r
438     printf ("%s failed to open input file - %s\n", PROGRAM_NAME, InFileName);\r
439     goto Fail;\r
440   }\r
441 \r
442   if (VfrParserStart (pInFile) != 0) {\r
443     goto Fail;\r
444   }\r
445 \r
446   fclose (pInFile);\r
447 \r
448   if (gCFormPkg.HavePendingUnassigned () == TRUE) {\r
449     gCFormPkg.PendingAssignPrintAll ();\r
450     goto Fail;\r
451   }\r
452 \r
453   SET_RUN_STATUS (STATUS_COMPILEED);\r
454   return;\r
455 \r
456 Fail:\r
457   if (!IS_RUN_STATUS(STATUS_DEAD)) {\r
458     printf ("%s compile error!\n", PROGRAM_NAME);\r
459     SET_RUN_STATUS (STATUS_FAILED);\r
460   }\r
461   if (pInFile != NULL) {\r
462     fclose (pInFile);\r
463   }\r
464 }\r
465 \r
466 VOID\r
467 CVfrCompiler::GenBinary (\r
468   VOID\r
469   )\r
470 {\r
471   FILE                    *pFile = NULL;\r
472 \r
473   if (!IS_RUN_STATUS(STATUS_COMPILEED)) {\r
474     goto Fail;\r
475   }\r
476 \r
477   if (mOptions.CreateIfrPkgFile == TRUE) {\r
478     if ((pFile = fopen (mOptions.PkgOutputFileName, "wb")) == NULL) {\r
479       printf ("can not open %s\n", mOptions.PkgOutputFileName);\r
480       goto Fail;\r
481     }\r
482     if (gCFormPkg.BuildPkg (pFile) != VFR_RETURN_SUCCESS) {\r
483       fclose (pFile);\r
484       goto Fail;\r
485     }\r
486     fclose (pFile);\r
487   }\r
488 \r
489   SET_RUN_STATUS (STATUS_GENBINARY);\r
490   return;\r
491 \r
492 Fail:\r
493   if (!IS_RUN_STATUS(STATUS_DEAD)) {\r
494     SET_RUN_STATUS (STATUS_FAILED);\r
495   }\r
496 }\r
497 \r
498 static const char *gSourceFileHeader[] = {\r
499   "//",\r
500   "//  DO NOT EDIT -- auto-generated file",\r
501   "//",\r
502   "//  This file is generated by the vfrcompiler utility",\r
503   "//",\r
504   NULL\r
505 };\r
506 \r
507 VOID\r
508 CVfrCompiler::GenCFile (\r
509   VOID\r
510   )\r
511 {\r
512   FILE                    *pFile;\r
513   UINT32                  Index;\r
514 \r
515   if (!IS_RUN_STATUS(STATUS_GENBINARY)) {\r
516     goto Fail;\r
517   }\r
518 \r
519   if ((pFile = fopen (mOptions.COutputFileName, "w")) == NULL) {\r
520     printf ("failed to open output C file - %s\n", mOptions.COutputFileName);\r
521     goto Fail;\r
522   }\r
523 \r
524   for (Index = 0; gSourceFileHeader[Index] != NULL; Index++) {\r
525     fprintf (pFile, "%s\n", gSourceFileHeader[Index]);\r
526   }\r
527 \r
528   gCVfrBufferConfig.OutputCFile (pFile, mOptions.VfrBaseFileName);\r
529 \r
530   if (gCFormPkg.GenCFile (mOptions.VfrBaseFileName, pFile) != VFR_RETURN_SUCCESS) {\r
531     fclose (pFile);\r
532     goto Fail;\r
533   }\r
534   fclose (pFile);\r
535 \r
536   SET_RUN_STATUS (STATUS_FINISHED);\r
537   return;\r
538 \r
539 Fail:\r
540   if (!IS_RUN_STATUS(STATUS_DEAD)) {\r
541     SET_RUN_STATUS (STATUS_FAILED);\r
542   }\r
543 }\r
544 \r
545 VOID\r
546 CVfrCompiler::GenRecordListFile (\r
547   VOID\r
548   )\r
549 {\r
550   INT8   *InFileName = NULL;\r
551   FILE   *pInFile    = NULL;\r
552   FILE   *pOutFile   = NULL;\r
553   INT8   LineBuf[MAX_LINE_LEN];\r
554   UINT32 LineNo;\r
555 \r
556   InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName;\r
557 \r
558   if (mOptions.CreateRecordListFile == TRUE) {\r
559     if ((InFileName[0] == '\0') || (mOptions.RecordListFile[0] == '\0')) {\r
560       return;\r
561     }\r
562 \r
563     if ((pInFile = fopen (InFileName, "r")) == NULL) {\r
564       printf ("%s failed to open input VFR preprocessor output file - %s\n", PROGRAM_NAME, InFileName);\r
565       return;\r
566     }\r
567 \r
568     if ((pOutFile = fopen (mOptions.RecordListFile, "w")) == NULL) {\r
569       printf ("%s failed to open record list file for writing - %s\n", PROGRAM_NAME, mOptions.RecordListFile);\r
570       goto Err1;\r
571     }\r
572 \r
573     fprintf (pOutFile, "//\n//  VFR compiler version " VFR_COMPILER_VERSION "\n//\n");\r
574     LineNo = 0;\r
575     while (!feof (pInFile)) {\r
576       if (fgets (LineBuf, MAX_LINE_LEN, pInFile) != NULL) {\r
577         fprintf (pOutFile, "%s", LineBuf);\r
578         LineNo++;\r
579         gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, LineNo);\r
580       }\r
581     }\r
582 \r
583     fclose (pOutFile);\r
584     fclose (pInFile);\r
585   }\r
586 \r
587   return;\r
588 \r
589 Err1:\r
590   fclose (pInFile);\r
591 }\r
592 \r
593 INT32\r
594 main (\r
595   IN INT32             Argc, \r
596   IN INT8              **Argv\r
597   )\r
598 {\r
599   COMPILER_RUN_STATUS  Status;\r
600   CVfrCompiler         Compiler(Argc, Argv);\r
601 \r
602   Compiler.PreProcess();\r
603   Compiler.Compile();\r
604   Compiler.GenBinary();\r
605   Compiler.GenCFile();\r
606   Compiler.GenRecordListFile ();\r
607 \r
608   Status = Compiler.RunStatus ();\r
609   if ((Status == STATUS_DEAD) || (Status == STATUS_FAILED)) {\r
610     return 2;\r
611   }\r
612 \r
613   return 0;\r
614 }\r
615 \r