]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/MakeDeps.c
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / MakeDeps / MakeDeps.c
CommitLineData
3eb9473e 1/*++\r
2\r
3e99020d 3Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
4b1e1121 4This program and the accompanying materials \r
3eb9473e 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 MakeDeps.c \r
15\r
16Abstract:\r
17\r
18 Recursively scan source files to find include files and emit them to \r
19 create dependency lists.\r
20\r
21--*/\r
22\r
23#include <stdio.h>\r
24#include <string.h>\r
25#include <stdlib.h>\r
26#include <ctype.h>\r
27\r
28#include "Tiano.h"\r
29#include "EfiUtilityMsgs.h"\r
30\r
31//\r
32// Structure to maintain a linked list of strings\r
33//\r
34typedef struct _STRING_LIST {\r
35 struct _STRING_LIST *Next;\r
36 char *Str;\r
37} STRING_LIST;\r
38\r
39#define UTILITY_NAME "MakeDeps"\r
3e99020d 40#define UTILITY_VERSION "v1.0"\r
3eb9473e 41\r
42#define MAX_LINE_LEN 2048\r
43#define MAX_PATH 2048\r
44#define START_NEST_DEPTH 1\r
45#define MAX_NEST_DEPTH 1000 // just in case we get in an endless loop.\r
46//\r
47// Define the relative paths used by the special #include macros\r
48//\r
49#define PROTOCOL_DIR_PATH "Protocol\\"\r
50#define GUID_DIR_PATH "Guid\\"\r
51#define ARCH_PROTOCOL_DIR_PATH "ArchProtocol\\"\r
52#define PPI_PROTOCOL_DIR_PATH "Ppi\\"\r
53\r
54//\r
55// Use this structure to keep track of all the special #include forms\r
56//\r
57typedef struct {\r
58 INT8 *IncludeMacroName;\r
59 INT8 *PathName;\r
60} INCLUDE_MACRO_CONVERSION;\r
61\r
62//\r
63// This data is used to convert #include macros like:\r
64// #include EFI_PROTOCOL_DEFINITION(xxx)\r
65// into\r
66// #include Protocol/xxx/xxx.h\r
67//\r
68static const INCLUDE_MACRO_CONVERSION mMacroConversion[] = {\r
69 "EFI_PROTOCOL_DEFINITION",\r
70 PROTOCOL_DIR_PATH,\r
71 "EFI_GUID_DEFINITION",\r
72 GUID_DIR_PATH,\r
73 "EFI_ARCH_PROTOCOL_DEFINITION",\r
74 ARCH_PROTOCOL_DIR_PATH,\r
75 "EFI_PROTOCOL_PRODUCER",\r
76 PROTOCOL_DIR_PATH,\r
77 "EFI_PROTOCOL_CONSUMER",\r
78 PROTOCOL_DIR_PATH,\r
79 "EFI_PROTOCOL_DEPENDENCY",\r
80 PROTOCOL_DIR_PATH,\r
81 "EFI_ARCH_PROTOCOL_PRODUCER",\r
82 ARCH_PROTOCOL_DIR_PATH,\r
83 "EFI_ARCH_PROTOCOL_CONSUMER",\r
84 ARCH_PROTOCOL_DIR_PATH,\r
85 "EFI_ARCH_PROTOCOL_DEPENDENCY",\r
86 ARCH_PROTOCOL_DIR_PATH,\r
87 "EFI_PPI_DEFINITION",\r
88 PPI_PROTOCOL_DIR_PATH,\r
89 "EFI_PPI_PRODUCER",\r
90 PPI_PROTOCOL_DIR_PATH,\r
91 "EFI_PPI_CONSUMER",\r
92 PPI_PROTOCOL_DIR_PATH,\r
93 "EFI_PPI_DEPENDENCY",\r
94 PPI_PROTOCOL_DIR_PATH,\r
95 NULL,\r
96 NULL\r
97};\r
98\r
99typedef struct _SYMBOL {\r
100 struct _SYMBOL *Next;\r
101 INT8 *Name;\r
102 INT8 *Value;\r
103} SYMBOL;\r
104\r
95d675b5 105typedef enum {\r
106 SearchCurrentDir,\r
107 SearchIncludePaths,\r
108 SearchAllPaths,\r
109} FILE_SEARCH_TYPE;\r
110\r
3eb9473e 111//\r
112// Here's all our globals. We need a linked list of include paths, a linked\r
113// list of source files, a linked list of subdirectories (appended to each\r
114// include path when searching), and flags to keep track of command-line options.\r
115//\r
116static struct {\r
117 STRING_LIST *IncludePaths; // all include paths to search\r
95d675b5 118 STRING_LIST *ParentPaths; // all parent paths to search\r
3eb9473e 119 STRING_LIST *SourceFiles; // all source files to parse\r
120 STRING_LIST *SubDirs; // appended to each include path when searching\r
121 SYMBOL *SymbolTable; // for replacement strings\r
122 FILE *OutFptr; // output dependencies to this file\r
123 BOOLEAN Verbose; // for more detailed output\r
124 BOOLEAN IgnoreNotFound; // no warnings if files not found\r
125 BOOLEAN QuietMode; // -q - don't print missing file warnings\r
126 BOOLEAN NoSystem; // don't process #include <system> files\r
127 BOOLEAN NeverFail; // always return success\r
128 BOOLEAN NoDupes; // to not list duplicate dependency files (for timing purposes)\r
129 BOOLEAN UseSumDeps; // use summary dependency files if found\r
130 BOOLEAN IsAsm; // The SourceFiles are assembler files\r
95d675b5 131 BOOLEAN IsCl; // The SourceFiles are the output of cl with /showIncludes\r
3eb9473e 132 INT8 TargetFileName[MAX_PATH]; // target object filename\r
133 INT8 SumDepsPath[MAX_PATH]; // path to summary files\r
95d675b5 134 INT8 TmpFileName[MAX_PATH]; // temp file name for output file\r
3eb9473e 135 INT8 *OutFileName; // -o option\r
136} mGlobals;\r
137\r
138static\r
139STATUS\r
140ProcessFile (\r
95d675b5 141 INT8 *TargetFileName,\r
142 INT8 *FileName,\r
143 UINT32 NestDepth,\r
144 STRING_LIST *ProcessedFiles,\r
145 FILE_SEARCH_TYPE FileSearchType\r
146 );\r
147\r
148static\r
149STATUS\r
150ProcessClOutput (\r
3eb9473e 151 INT8 *TargetFileName,\r
152 INT8 *FileName,\r
3eb9473e 153 STRING_LIST *ProcessedFiles\r
154 );\r
155\r
156static\r
157FILE *\r
158FindFile (\r
95d675b5 159 INT8 *FileName,\r
160 UINT32 FileNameLen,\r
161 FILE_SEARCH_TYPE FileSearchType\r
3eb9473e 162 );\r
163\r
164static\r
165void\r
166PrintDependency (\r
167 INT8 *Target,\r
168 INT8 *DependentFile\r
169 );\r
170\r
171static\r
172void\r
173ReplaceSymbols (\r
174 INT8 *Str,\r
175 UINT32 StrSize\r
176 );\r
177\r
178static\r
179STATUS\r
180ProcessArgs (\r
181 int Argc,\r
182 char *Argv[]\r
183 );\r
184\r
185static\r
186void\r
187Usage (\r
188 VOID\r
189 );\r
190\r
191static\r
192void\r
193FreeLists (\r
194 VOID\r
195 );\r
196\r
197int\r
198main (\r
199 int Argc,\r
200 char *Argv[]\r
201 )\r
202/*++\r
203\r
204Routine Description:\r
205\r
206 Call the routine to parse the command-line options, then process each file\r
207 to build dependencies.\r
208 \r
209Arguments:\r
210\r
211 Argc - Standard C main() argc.\r
212 Argv - Standard C main() argv.\r
213\r
214Returns:\r
215\r
216 0 if successful\r
217 nonzero otherwise\r
218 \r
219--*/\r
220{\r
221 STRING_LIST *File;\r
222 STRING_LIST ProcessedFiles;\r
223 STRING_LIST *TempList;\r
224 STATUS Status;\r
225 INT8 *Cptr;\r
226 INT8 TargetFileName[MAX_PATH];\r
227\r
228 SetUtilityName (UTILITY_NAME);\r
229 //\r
230 // Process the command-line arguments\r
231 //\r
232 Status = ProcessArgs (Argc, Argv);\r
233 if (Status != STATUS_SUCCESS) {\r
234 return STATUS_ERROR;\r
235 }\r
236 //\r
237 // Go through the list of source files and process each.\r
238 //\r
239 memset (&ProcessedFiles, 0, sizeof (STRING_LIST));\r
240 File = mGlobals.SourceFiles;\r
241 while (File != NULL) {\r
242 //\r
243 // Clear out our list of processed files\r
244 //\r
245 TempList = ProcessedFiles.Next;\r
246 while (ProcessedFiles.Next != NULL) {\r
247 TempList = ProcessedFiles.Next->Next;\r
248 free (ProcessedFiles.Next->Str);\r
249 free (ProcessedFiles.Next);\r
250 ProcessedFiles.Next = TempList;\r
251 }\r
252 //\r
253 // Replace filename extension with ".obj" if they did not\r
254 // specifically specify the target file\r
255 //\r
256 if (mGlobals.TargetFileName[0] == 0) {\r
257 strcpy (TargetFileName, File->Str);\r
258 //\r
259 // Find the .extension\r
260 //\r
261 for (Cptr = TargetFileName + strlen (TargetFileName) - 1;\r
262 (*Cptr != '\\') && (Cptr > TargetFileName) && (*Cptr != '.');\r
263 Cptr--\r
264 )\r
265 ;\r
266 if (Cptr == TargetFileName) {\r
267 Error (NULL, 0, 0, File->Str, "could not locate extension in filename");\r
268 goto Finish;\r
269 }\r
270 //\r
271 // Tack on the ".obj"\r
272 //\r
273 strcpy (Cptr, ".obj");\r
274 } else {\r
275 //\r
276 // Copy the target filename they specified\r
277 //\r
278 strcpy (TargetFileName, mGlobals.TargetFileName);\r
279 }\r
280\r
95d675b5 281 if (mGlobals.IsCl) {\r
282 Status = ProcessClOutput (TargetFileName, File->Str, &ProcessedFiles);\r
283 } else {\r
284 Status = ProcessFile (TargetFileName, File->Str, START_NEST_DEPTH, \r
285 &ProcessedFiles, SearchCurrentDir);\r
286 }\r
3eb9473e 287 if (Status != STATUS_SUCCESS) {\r
288 goto Finish;\r
289 }\r
290\r
291 File = File->Next;\r
292 }\r
293\r
294Finish:\r
295 //\r
296 // Free up memory\r
297 //\r
298 FreeLists ();\r
299 //\r
300 // Free up our processed files list\r
301 //\r
302 TempList = ProcessedFiles.Next;\r
303 while (ProcessedFiles.Next != NULL) {\r
304 TempList = ProcessedFiles.Next->Next;\r
305 free (ProcessedFiles.Next->Str);\r
306 free (ProcessedFiles.Next);\r
307 ProcessedFiles.Next = TempList;\r
308 }\r
309 //\r
95d675b5 310 // Close our temp output file\r
3eb9473e 311 //\r
312 if ((mGlobals.OutFptr != stdout) && (mGlobals.OutFptr != NULL)) {\r
313 fclose (mGlobals.OutFptr);\r
314 }\r
315\r
316 if (mGlobals.NeverFail) {\r
317 return STATUS_SUCCESS;\r
318 }\r
95d675b5 319\r
320 if (mGlobals.OutFileName != NULL) {\r
321 if (GetUtilityStatus () == STATUS_ERROR) {\r
322 //\r
323 // If any errors, then delete our temp output\r
324 // Also try to delete target file to improve the incremental build\r
325 // \r
326 remove (mGlobals.TmpFileName);\r
327 remove (TargetFileName);\r
328 } else {\r
329 //\r
330 // Otherwise, rename temp file to output file\r
331 //\r
332 remove (mGlobals.OutFileName);\r
333 rename (mGlobals.TmpFileName, mGlobals.OutFileName);\r
334 }\r
3eb9473e 335 }\r
336\r
337 return GetUtilityStatus ();\r
338}\r
339\r
340static\r
341STATUS\r
342ProcessFile (\r
95d675b5 343 INT8 *TargetFileName,\r
344 INT8 *FileName,\r
345 UINT32 NestDepth,\r
346 STRING_LIST *ProcessedFiles,\r
347 FILE_SEARCH_TYPE FileSearchType\r
3eb9473e 348 )\r
349/*++\r
350\r
351Routine Description:\r
352\r
353 Given a source file name, open the file and parse all #include lines.\r
354 \r
355Arguments:\r
356\r
357 TargetFileName - name of the usually .obj target\r
358 FileName - name of the file to process\r
359 NestDepth - how deep we're nested in includes\r
360 ProcessedFiles - list of processed files.\r
95d675b5 361 FileSearchType - search type for FileName\r
3eb9473e 362\r
363Returns:\r
364\r
365 standard status.\r
366 \r
367--*/\r
368{\r
369 FILE *Fptr;\r
370 INT8 Line[MAX_LINE_LEN];\r
371 INT8 *Cptr;\r
372 INT8 *EndPtr;\r
373 INT8 *SaveCptr;\r
374 INT8 EndChar;\r
375 INT8 FileNameCopy[MAX_PATH];\r
376 INT8 MacroIncludeFileName[MAX_LINE_LEN];\r
377 INT8 SumDepsFile[MAX_PATH];\r
378 STATUS Status;\r
379 UINT32 Index;\r
380 UINT32 LineNum;\r
381 STRING_LIST *ListPtr;\r
95d675b5 382 STRING_LIST ParentPath;\r
3eb9473e 383\r
384 Status = STATUS_SUCCESS;\r
385 Fptr = NULL;\r
386 //\r
387 // Print the file being processed. Indent so you can tell the include nesting\r
388 // depth.\r
389 //\r
390 if (mGlobals.Verbose) {\r
391 fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', FileName);\r
392 }\r
393 //\r
394 // If we're using summary dependency files, and a matching .dep file is\r
395 // found for this file, then just emit the summary dependency file as\r
396 // a dependency and return.\r
397 //\r
398 if (mGlobals.UseSumDeps) {\r
399 strcpy (SumDepsFile, mGlobals.SumDepsPath);\r
400 strcat (SumDepsFile, FileName);\r
401 for (Cptr = SumDepsFile + strlen (SumDepsFile) - 1;\r
402 (*Cptr != '\\') && (Cptr > SumDepsFile) && (*Cptr != '.');\r
403 Cptr--\r
404 )\r
405 ;\r
406 if (*Cptr == '.') {\r
407 strcpy (Cptr, ".dep");\r
408 } else {\r
409 strcat (SumDepsFile, ".dep");\r
410 }\r
411 //\r
412 // See if the summary dep file exists. Could use _stat() function, but\r
413 // it's less portable.\r
414 //\r
415 if ((Fptr = fopen (SumDepsFile, "r")) != NULL) {\r
416 PrintDependency (TargetFileName, SumDepsFile);\r
417 fclose (Fptr);\r
418 return STATUS_SUCCESS;\r
419 }\r
420 }\r
3eb9473e 421\r
422 //\r
423 // Make sure we didn't exceed our maximum nesting depth\r
424 //\r
425 if (NestDepth > MAX_NEST_DEPTH) {\r
426 Error (NULL, 0, 0, FileName, "max nesting depth exceeded on file");\r
427 goto Finish;\r
428 }\r
429 //\r
430 // Make a local copy of the filename. Then we can manipulate it\r
431 // if we have to.\r
432 //\r
433 strcpy (FileNameCopy, FileName);\r
95d675b5 434 \r
435 if (FileSearchType == SearchCurrentDir) {\r
436 //\r
437 // Try to open the source file locally\r
438 //\r
439 if ((Fptr = fopen (FileNameCopy, "r")) == NULL) {\r
440 Error (NULL, 0, 0, FileNameCopy, "could not open source file");\r
441 return STATUS_ERROR;\r
442 }\r
443 } else {\r
3eb9473e 444 //\r
445 // Try to find it among the paths.\r
446 //\r
95d675b5 447 Fptr = FindFile (FileNameCopy, sizeof (FileNameCopy), FileSearchType);\r
3eb9473e 448 if (Fptr == NULL) {\r
449 //\r
450 // If this is not the top-level file, and the command-line argument\r
451 // said to ignore missing files, then return ok\r
452 //\r
453 if (NestDepth != START_NEST_DEPTH) {\r
454 if (mGlobals.IgnoreNotFound) {\r
455 if (!mGlobals.QuietMode) {\r
456 DebugMsg (NULL, 0, 0, FileNameCopy, "could not find file");\r
457 }\r
458\r
459 return STATUS_SUCCESS;\r
460 } else {\r
461 Error (NULL, 0, 0, FileNameCopy, "could not find file");\r
462 return STATUS_ERROR;\r
463 }\r
464 } else {\r
465 //\r
466 // Top-level (first) file. Emit an error.\r
467 //\r
468 Error (NULL, 0, 0, FileNameCopy, "could not find file");\r
469 return STATUS_ERROR;\r
470 }\r
471 }\r
472 }\r
95d675b5 473\r
474 //\r
475 // If we're not doing duplicates, and we've already seen this filename,\r
476 // then return\r
477 //\r
478 if (mGlobals.NoDupes) {\r
479 for (ListPtr = ProcessedFiles->Next; ListPtr != NULL; ListPtr = ListPtr->Next) {\r
480 if (_stricmp (FileNameCopy, ListPtr->Str) == 0) {\r
481 break;\r
482 }\r
483 }\r
484 //\r
485 // If we found a match, we're done. If we didn't, create a new element\r
486 // and add it to the list.\r
487 //\r
488 if (ListPtr != NULL) {\r
489 //\r
490 // Print a message if verbose mode\r
491 //\r
492 if (mGlobals.Verbose) {\r
493 DebugMsg (NULL, 0, 0, FileNameCopy, "duplicate include -- not processed again");\r
494 }\r
495 fclose (Fptr);\r
496 return STATUS_SUCCESS;\r
497 }\r
498\r
499 ListPtr = malloc (sizeof (STRING_LIST));\r
500 ListPtr->Str = malloc (strlen (FileNameCopy) + 1);\r
501 strcpy (ListPtr->Str, FileNameCopy);\r
502 ListPtr->Next = ProcessedFiles->Next;\r
503 ProcessedFiles->Next = ListPtr;\r
504 }\r
505 \r
3eb9473e 506 //\r
507 // Print the dependency, with string substitution\r
508 //\r
509 PrintDependency (TargetFileName, FileNameCopy);\r
95d675b5 510 \r
511 //\r
512 // Get the file path and push to ParentPaths\r
513 //\r
514 Cptr = FileNameCopy + strlen (FileNameCopy) - 1;\r
515 for (; (Cptr > FileNameCopy) && (*Cptr != '\\') && (*Cptr != '/'); Cptr--);\r
516 if ((*Cptr == '\\') || (*Cptr == '/')) {\r
517 *(Cptr + 1) = 0;\r
518 } else {\r
519 strcpy (FileNameCopy, ".\\");\r
520 }\r
521 ParentPath.Next = mGlobals.ParentPaths;\r
522 ParentPath.Str = FileNameCopy;\r
523 mGlobals.ParentPaths = &ParentPath;\r
524 \r
3eb9473e 525 //\r
526 // Now read in lines and find all #include lines. Allow them to indent, and\r
527 // to put spaces between the # and include.\r
528 //\r
529 LineNum = 0;\r
530 while ((fgets (Line, sizeof (Line), Fptr) != NULL) && (Status == STATUS_SUCCESS)) {\r
531 LineNum++;\r
532 Cptr = Line;\r
533 //\r
534 // Skip preceeding spaces on the line\r
535 //\r
536 while (*Cptr && (isspace (*Cptr))) {\r
537 Cptr++;\r
538 }\r
539 //\r
540 // Check for # character, there is no # for asm\r
541 //\r
542 if ((*Cptr == '#') || (mGlobals.IsAsm)) {\r
543 if (*Cptr == '#') {\r
544 Cptr++;\r
545 }\r
546 \r
547 //\r
548 // Check for "include", case insensitive for asm\r
549 //\r
550 while (*Cptr && (isspace (*Cptr))) {\r
551 Cptr++;\r
552 }\r
553 if (((!mGlobals.IsAsm) && (strncmp (Cptr, "include", 7) == 0)) || \r
554 (mGlobals.IsAsm && (_strnicmp (Cptr, "include", 7) == 0))) {\r
555 //\r
556 // Skip over "include" and move on to filename as "file" or <file> or file for asm\r
557 //\r
558 Cptr += 7;\r
559 while (*Cptr && (isspace (*Cptr))) {\r
560 Cptr++;\r
561 }\r
562\r
563 if (*Cptr == '<') {\r
564 EndChar = '>';\r
565 } else if (*Cptr == '"') {\r
566 EndChar = '"';\r
567 } else if (mGlobals.IsAsm) {\r
568 //\r
569 // Handle include file for asm\r
570 // Set EndChar to null so we fall through on processing below.\r
571 //\r
572 EndChar = 0;\r
573 \r
574 //\r
575 // Look for the end of include file name\r
576 //\r
577 EndPtr = Cptr;\r
578 while (*EndPtr && (!isspace (*EndPtr))) {\r
579 EndPtr++;\r
580 }\r
581 \r
582 //\r
583 // Null terminate the filename and try to process it.\r
584 //\r
585 *EndPtr = 0;\r
95d675b5 586 Status = ProcessFile (TargetFileName, Cptr, NestDepth + 1, \r
587 ProcessedFiles, SearchAllPaths);\r
3eb9473e 588 } else {\r
589 //\r
590 // Handle special #include MACRO_NAME(file)\r
591 // Set EndChar to null so we fall through on processing below.\r
592 //\r
593 EndChar = 0;\r
594 //\r
595 // Look for all the special include macros and convert accordingly.\r
596 //\r
597 for (Index = 0; mMacroConversion[Index].IncludeMacroName != NULL; Index++) {\r
598 //\r
599 // Save the start of the string in case some macros are substrings\r
600 // of others.\r
601 //\r
602 SaveCptr = Cptr;\r
603 if (strncmp (\r
604 Cptr,\r
605 mMacroConversion[Index].IncludeMacroName,\r
606 strlen (mMacroConversion[Index].IncludeMacroName)\r
607 ) == 0) {\r
608 //\r
609 // Skip over the macro name\r
610 //\r
611 Cptr += strlen (mMacroConversion[Index].IncludeMacroName);\r
612 //\r
613 // Skip over open parenthesis, blank spaces, then find closing\r
614 // parenthesis or blank space\r
615 //\r
616 while (*Cptr && (isspace (*Cptr))) {\r
617 Cptr++;\r
618 }\r
619\r
620 if (*Cptr == '(') {\r
621 Cptr++;\r
622 while (*Cptr && (isspace (*Cptr))) {\r
623 Cptr++;\r
624 }\r
625\r
626 EndPtr = Cptr;\r
627 while (*EndPtr && !isspace (*EndPtr) && (*EndPtr != ')')) {\r
628 EndPtr++;\r
629 }\r
630\r
631 *EndPtr = 0;\r
632 //\r
633 // Create the path\r
634 //\r
635 strcpy (MacroIncludeFileName, mMacroConversion[Index].PathName);\r
636 strcat (MacroIncludeFileName, Cptr);\r
637 strcat (MacroIncludeFileName, "\\");\r
638 strcat (MacroIncludeFileName, Cptr);\r
639 strcat (MacroIncludeFileName, ".h");\r
640 //\r
641 // Process immediately, then break out of the outside FOR loop.\r
642 //\r
95d675b5 643 Status = ProcessFile (TargetFileName, MacroIncludeFileName, NestDepth + 1, \r
644 ProcessedFiles, SearchAllPaths);\r
3eb9473e 645 break;\r
646 }\r
647 }\r
648 //\r
649 // Restore the start\r
650 //\r
651 Cptr = SaveCptr;\r
652 }\r
653 //\r
654 // Don't recognize the include line? Ignore it. We assume that the\r
655 // file compiles anyway.\r
656 //\r
657 if (mMacroConversion[Index].IncludeMacroName == NULL) {\r
658 //\r
659 // Warning (FileNameCopy, LineNum, 0, "could not parse line", NULL);\r
660 // Status = STATUS_WARNING;\r
661 //\r
662 }\r
663 }\r
664 //\r
665 // Process "normal" includes. If the endchar is 0, then the\r
666 // file has already been processed. Otherwise look for the\r
667 // endchar > or ", and process the include file.\r
668 //\r
669 if (EndChar != 0) {\r
670 Cptr++;\r
671 EndPtr = Cptr;\r
672 while (*EndPtr && (*EndPtr != EndChar)) {\r
673 EndPtr++;\r
674 }\r
675\r
676 if (*EndPtr == EndChar) {\r
677 //\r
678 // If we're processing it, do it\r
679 //\r
95d675b5 680 if (EndChar != '>') {\r
3eb9473e 681 //\r
682 // Null terminate the filename and try to process it.\r
683 //\r
684 *EndPtr = 0;\r
95d675b5 685 Status = ProcessFile (TargetFileName, Cptr, NestDepth + 1, \r
686 ProcessedFiles, SearchAllPaths);\r
687 } else if (!mGlobals.NoSystem) {\r
688 //\r
689 // Null terminate the filename and try to process it.\r
690 //\r
691 *EndPtr = 0;\r
692 Status = ProcessFile (TargetFileName, Cptr, NestDepth + 1, \r
693 ProcessedFiles, SearchIncludePaths);\r
3eb9473e 694 }\r
695 } else {\r
696 Warning (FileNameCopy, LineNum, 0, "malformed include", "missing closing %c", EndChar);\r
697 Status = STATUS_WARNING;\r
698 goto Finish;\r
699 }\r
700 }\r
701 }\r
702 }\r
703 }\r
95d675b5 704 //\r
705 // Pop the file path from ParentPaths\r
706 //\r
707 mGlobals.ParentPaths = ParentPath.Next; \r
3eb9473e 708\r
709Finish:\r
710 //\r
711 // Close open files and return status\r
712 //\r
713 if (Fptr != NULL) {\r
714 fclose (Fptr);\r
715 }\r
716\r
717 return Status;\r
718}\r
719\r
95d675b5 720static\r
721STATUS\r
722ProcessClOutput (\r
723 INT8 *TargetFileName,\r
724 INT8 *FileName,\r
725 STRING_LIST *ProcessedFiles\r
726 )\r
727/*++\r
728\r
729Routine Description:\r
730\r
731 Given a source file name, open the file and parse all "Note: including file: xxx.h" lines.\r
732 \r
733Arguments:\r
734\r
735 TargetFileName - name of the usually .obj target\r
736 FileName - name of the file to process\r
737 ProcessedFiles - list of processed files.\r
738\r
739Returns:\r
740\r
741 standard status.\r
742 \r
743--*/\r
744{\r
745 FILE *Fptr;\r
746 INT8 Line[MAX_LINE_LEN];\r
747 INT8 IncludeFileName[MAX_LINE_LEN];\r
748 STRING_LIST *ListPtr;\r
749 BOOLEAN ClError;\r
750 INT32 Ret;\r
751 INT8 Char;\r
752\r
753 if ((Fptr = fopen (FileName, "r")) == NULL) {\r
754 Error (NULL, 0, 0, FileName, "could not open file for reading");\r
755 return STATUS_ERROR;\r
756 }\r
757 if (fgets (Line, sizeof (Line), Fptr) != NULL) {\r
758 //\r
759 // First line is the source file name, print it\r
760 //\r
761 printf ("%s", Line);\r
762 } else {\r
763 //\r
764 // No output from cl\r
765 //\r
766 fclose (Fptr);\r
767 Error (NULL, 0, 0, NULL, "incorrect cl tool path may be used ");\r
768 return STATUS_ERROR;\r
769 }\r
770 \r
771 ClError = FALSE;\r
772 while (fgets (Line, sizeof (Line), Fptr) != NULL) {\r
773 Ret = sscanf (Line, "Note: including file: %s %c", IncludeFileName, &Char);\r
774 if (Ret == 2) {\r
775 //\r
776 // There is space in include file name. It's VS header file. Ignore it.\r
777 //\r
778 continue;\r
779 } else if ( Ret != 1) {\r
780 //\r
781 // Cl error info, print it\r
782 // the tool will return error code to stop the nmake\r
783 //\r
784 ClError = TRUE;\r
785 printf ("%s", Line);\r
786 continue;\r
787 }\r
788 \r
789 //\r
790 // If we're not doing duplicates, and we've already seen this filename,\r
791 // then continue\r
792 //\r
793 if (mGlobals.NoDupes) {\r
794 for (ListPtr = ProcessedFiles->Next; ListPtr != NULL; ListPtr = ListPtr->Next) {\r
795 if (_stricmp (IncludeFileName, ListPtr->Str) == 0) {\r
796 break;\r
797 }\r
798 }\r
799 //\r
800 // If we found a match, we're done. If we didn't, create a new element\r
801 // and add it to the list.\r
802 //\r
803 if (ListPtr != NULL) {\r
804 //\r
805 // Print a message if verbose mode\r
806 //\r
807 if (mGlobals.Verbose) {\r
808 DebugMsg (NULL, 0, 0, IncludeFileName, "duplicate include -- not processed again");\r
809 }\r
810 \r
811 continue;\r
812 }\r
813 \r
814 ListPtr = malloc (sizeof (STRING_LIST));\r
815 ListPtr->Str = malloc (strlen (IncludeFileName) + 1);\r
816 strcpy (ListPtr->Str, IncludeFileName);\r
817 ListPtr->Next = ProcessedFiles->Next;\r
818 ProcessedFiles->Next = ListPtr;\r
819 }\r
820 \r
821 PrintDependency (TargetFileName, IncludeFileName);\r
822 }\r
823 \r
824 fclose (Fptr);\r
825 \r
826 if (ClError) {\r
827 Error (NULL, 0, 0, NULL, "cl error");\r
828 return STATUS_ERROR;\r
829 } else {\r
830 return STATUS_SUCCESS;\r
831 }\r
832}\r
833\r
3eb9473e 834static\r
835void\r
836PrintDependency (\r
837 INT8 *TargetFileName,\r
838 INT8 *DependentFile\r
839 )\r
840/*++\r
841\r
842Routine Description:\r
843\r
844 Given a target (.obj) file name, and a dependent file name, do any string\r
845 substitutions (per the command line options) on the file names, then\r
846 print the dependency line of form:\r
847 \r
848 TargetFileName : DependentFile\r
849 \r
850Arguments:\r
851\r
852 TargetFileName - build target file name\r
853 DependentFile - file on which TargetFileName depends\r
854\r
855Returns:\r
856\r
857 None\r
858 \r
859--*/\r
860{\r
861 INT8 Str[MAX_PATH];\r
862\r
863 //\r
864 // Go through the symbols and do replacements\r
865 //\r
866 strcpy (Str, TargetFileName);\r
867 ReplaceSymbols (Str, sizeof (Str));\r
868 fprintf (mGlobals.OutFptr, "%s : ", Str);\r
869 strcpy (Str, DependentFile);\r
870 ReplaceSymbols (Str, sizeof (Str));\r
871 fprintf (mGlobals.OutFptr, "%s\n", Str);\r
872 //\r
873 // Add pseudo target to avoid incremental build failure when the file is deleted\r
874 //\r
875 fprintf (mGlobals.OutFptr, "%s : \n", Str);\r
876}\r
877\r
878static\r
879void\r
880ReplaceSymbols (\r
881 INT8 *Str,\r
882 UINT32 StrSize\r
883 )\r
884{\r
885 SYMBOL *Sym;\r
886 INT8 StrCopy[MAX_LINE_LEN];\r
887 INT8 *From;\r
888 INT8 *To;\r
889 BOOLEAN Replaced;\r
890\r
891 //\r
892 // Go through the entire string to look for replacement strings at\r
893 // every position.\r
894 //\r
895 From = Str;\r
896 To = StrCopy;\r
897 while (*From) {\r
898 //\r
899 // Copy the character\r
900 //\r
901 *To = *From;\r
902 Replaced = FALSE;\r
903 //\r
904 // Go through each symbol and try to find a string substitution\r
905 //\r
906 Sym = mGlobals.SymbolTable;\r
907 while (Sym != NULL) {\r
908 if (_strnicmp (From, Sym->Value, strlen (Sym->Value)) == 0) {\r
909 //\r
910 // Replace the string, then advance the pointers past the\r
911 // replaced strings\r
912 //\r
913 strcpy (To, Sym->Name);\r
914 To += strlen (Sym->Name);\r
915 From += strlen (Sym->Value);\r
916 Replaced = TRUE;\r
917 //\r
918 // Break from the while()\r
919 //\r
920 break;\r
921 } else {\r
922 Sym = Sym->Next;\r
923 }\r
924 }\r
925\r
926 if (!Replaced) {\r
927 From++;\r
928 To++;\r
929 }\r
930 }\r
931 //\r
932 // Null terminate, and return it\r
933 //\r
934 *To = 0;\r
935 if (strlen (StrCopy) < StrSize) {\r
936 strcpy (Str, StrCopy);\r
937 }\r
938}\r
939//\r
940// Given a filename, try to find it along the include paths.\r
941//\r
942static\r
943FILE *\r
944FindFile (\r
95d675b5 945 INT8 *FileName,\r
946 UINT32 FileNameLen,\r
947 FILE_SEARCH_TYPE FileSearchType\r
3eb9473e 948 )\r
949{\r
950 FILE *Fptr;\r
951 STRING_LIST *List;\r
952 STRING_LIST *SubDir;\r
953 INT8 FullFileName[MAX_PATH * 2];\r
954\r
955 //\r
956 // Traverse the list of paths and try to find the file\r
957 //\r
95d675b5 958 if (FileSearchType == SearchAllPaths) {\r
959 List = mGlobals.ParentPaths;\r
960 while (List != NULL) {\r
961 //\r
962 // Put the path and filename together\r
963 //\r
964 if (strlen (List->Str) + strlen (FileName) + 1 > sizeof (FullFileName)) {\r
965 Error (\r
966 __FILE__,\r
967 __LINE__,\r
968 0,\r
969 "application error",\r
970 "cannot concatenate '%s' + '%s'",\r
971 List->Str,\r
972 FileName\r
973 );\r
974 return NULL;\r
975 }\r
976 //\r
977 // Append the filename to this include path and try to open the file.\r
978 //\r
979 strcpy (FullFileName, List->Str);\r
980 strcat (FullFileName, FileName);\r
981 if ((Fptr = fopen (FullFileName, "r")) != NULL) {\r
982 //\r
983 // Return the file name\r
984 //\r
985 if (FileNameLen <= strlen (FullFileName)) {\r
986 Error (__FILE__, __LINE__, 0, "application error", "internal path name of insufficient length");\r
987 //\r
988 // fprintf (stdout, "File length > %d: %s\n", FileNameLen, FullFileName);\r
989 //\r
990 return NULL;\r
991 }\r
992 \r
993 strcpy (FileName, FullFileName);\r
994 return Fptr;\r
995 }\r
996 \r
997 List = List->Next;\r
998 } \r
999 }\r
1000 \r
3eb9473e 1001 List = mGlobals.IncludePaths;\r
1002 while (List != NULL) {\r
1003 //\r
1004 // Put the path and filename together\r
1005 //\r
1006 if (strlen (List->Str) + strlen (FileName) + 1 > sizeof (FullFileName)) {\r
1007 Error (\r
1008 __FILE__,\r
1009 __LINE__,\r
1010 0,\r
1011 "application error",\r
1012 "cannot concatenate '%s' + '%s'",\r
1013 List->Str,\r
1014 FileName\r
1015 );\r
1016 return NULL;\r
1017 }\r
1018 //\r
1019 // Append the filename to this include path and try to open the file.\r
1020 //\r
1021 strcpy (FullFileName, List->Str);\r
1022 strcat (FullFileName, FileName);\r
1023 if ((Fptr = fopen (FullFileName, "r")) != NULL) {\r
1024 //\r
1025 // Return the file name\r
1026 //\r
1027 if (FileNameLen <= strlen (FullFileName)) {\r
1028 Error (__FILE__, __LINE__, 0, "application error", "internal path name of insufficient length");\r
1029 //\r
1030 // fprintf (stdout, "File length > %d: %s\n", FileNameLen, FullFileName);\r
1031 //\r
1032 return NULL;\r
1033 }\r
1034\r
1035 strcpy (FileName, FullFileName);\r
1036 return Fptr;\r
1037 }\r
1038 //\r
1039 // Didn't find it there. Now try this directory with every subdirectory\r
1040 // the user specified on the command line\r
1041 //\r
1042 for (SubDir = mGlobals.SubDirs; SubDir != NULL; SubDir = SubDir->Next) {\r
1043 strcpy (FullFileName, List->Str);\r
1044 strcat (FullFileName, SubDir->Str);\r
1045 strcat (FullFileName, FileName);\r
1046 if ((Fptr = fopen (FullFileName, "r")) != NULL) {\r
1047 //\r
1048 // Return the file name\r
1049 //\r
1050 if (FileNameLen <= strlen (FullFileName)) {\r
1051 Error (__FILE__, __LINE__, 0, "application error", "internal path name of insufficient length");\r
1052 return NULL;\r
1053 }\r
1054\r
1055 strcpy (FileName, FullFileName);\r
1056 return Fptr;\r
1057 }\r
1058 }\r
1059\r
1060 List = List->Next;\r
1061 }\r
1062 //\r
1063 // Not found\r
1064 //\r
1065 return NULL;\r
1066}\r
1067//\r
1068// Process the command-line arguments\r
1069//\r
1070static\r
1071STATUS\r
1072ProcessArgs (\r
1073 int Argc,\r
1074 char *Argv[]\r
1075 )\r
1076{\r
1077 STRING_LIST *NewList;\r
1078 STRING_LIST *LastIncludePath;\r
1079 STRING_LIST *LastSourceFile;\r
1080 SYMBOL *Symbol;\r
95d675b5 1081\r
3eb9473e 1082 //\r
1083 // Clear our globals\r
1084 //\r
1085 memset ((char *) &mGlobals, 0, sizeof (mGlobals));\r
1086 mGlobals.NoDupes = TRUE;\r
1087 //\r
1088 // Skip program name\r
1089 //\r
1090 Argc--;\r
1091 Argv++;\r
1092 //\r
1093 // Initialize locals\r
1094 //\r
1095 LastIncludePath = NULL;\r
1096 LastSourceFile = NULL;\r
1097 //\r
1098 // Process until no more args\r
1099 //\r
1100 while (Argc) {\r
1101 //\r
1102 // -i path add include search path\r
1103 //\r
1104 if (_stricmp (Argv[0], "-i") == 0) {\r
1105 //\r
1106 // check for one more arg\r
1107 //\r
1108 if (Argc > 1) {\r
1109 //\r
1110 // Allocate memory for a new list element, fill it in, and\r
1111 // add it to our list of include paths. Always make sure it\r
1112 // has a "\" on the end of it.\r
1113 //\r
1114 NewList = malloc (sizeof (STRING_LIST));\r
1115 if (NewList == NULL) {\r
1116 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
1117 return STATUS_ERROR;\r
1118 }\r
1119\r
1120 NewList->Next = NULL;\r
1121 NewList->Str = malloc (strlen (Argv[1]) + 2);\r
1122 if (NewList->Str == NULL) {\r
1123 free (NewList);\r
1124 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
1125 return STATUS_ERROR;\r
1126 }\r
1127\r
1128 strcpy (NewList->Str, Argv[1]);\r
1129 if (NewList->Str[strlen (NewList->Str) - 1] != '\\') {\r
1130 strcat (NewList->Str, "\\");\r
1131 }\r
1132 //\r
1133 // Add it to the end of the our list of include paths\r
1134 //\r
1135 if (mGlobals.IncludePaths == NULL) {\r
1136 mGlobals.IncludePaths = NewList;\r
1137 } else {\r
1138 LastIncludePath->Next = NewList;\r
1139 }\r
1140\r
1141 LastIncludePath = NewList;\r
1142 //\r
1143 // fprintf (stdout, "Added path: %s\n", NewList->Str);\r
1144 //\r
1145 } else {\r
1146 Error (NULL, 0, 0, Argv[0], "option requires an include path");\r
1147 Usage ();\r
1148 return STATUS_ERROR;\r
1149 }\r
1150\r
1151 Argc--;\r
1152 Argv++;\r
1153 } else if (_stricmp (Argv[0], "-f") == 0) {\r
1154 //\r
1155 // Check for one more arg\r
1156 //\r
1157 if (Argc > 1) {\r
1158 //\r
1159 // Allocate memory for a new list element, fill it in, and\r
1160 // add it to our list of source files.\r
1161 //\r
1162 NewList = malloc (sizeof (STRING_LIST));\r
1163 if (NewList == NULL) {\r
1164 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
1165 return STATUS_ERROR;\r
1166 }\r
1167\r
1168 NewList->Next = NULL;\r
1169 //\r
1170 // Allocate space to replace ".c" with ".obj", plus null termination\r
1171 //\r
1172 NewList->Str = malloc (strlen (Argv[1]) + 5);\r
1173 if (NewList->Str == NULL) {\r
1174 free (NewList);\r
1175 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
1176 return STATUS_ERROR;\r
1177 }\r
1178\r
1179 strcpy (NewList->Str, Argv[1]);\r
1180 if (mGlobals.SourceFiles == NULL) {\r
1181 mGlobals.SourceFiles = NewList;\r
1182 } else {\r
1183 LastSourceFile->Next = NewList;\r
1184 }\r
1185\r
1186 LastSourceFile = NewList;\r
1187 } else {\r
1188 Error (NULL, 0, 0, Argv[0], "option requires a file name");\r
1189 Usage ();\r
1190 return STATUS_ERROR;\r
1191 }\r
3eb9473e 1192\r
3eb9473e 1193 Argc--;\r
1194 Argv++;\r
1195 } else if (_stricmp (Argv[0], "-s") == 0) {\r
1196 //\r
1197 // -s subdir add subdirectory subdir to list of subdirecties to scan.\r
1198 // Check for one more arg first.\r
1199 //\r
1200 if (Argc > 1) {\r
1201 //\r
1202 // Allocate memory for a new list element, fill it in, and\r
1203 // add it to our list of subdirectory include paths. Always\r
1204 // make sure it has a "\" on the end of it.\r
1205 //\r
1206 NewList = malloc (sizeof (STRING_LIST));\r
1207 if (NewList == NULL) {\r
1208 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
1209 return STATUS_ERROR;\r
1210 }\r
1211\r
1212 NewList->Str = malloc (strlen (Argv[1]) + 2);\r
1213 if (NewList->Str == NULL) {\r
1214 free (NewList);\r
1215 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
1216 return STATUS_ERROR;\r
1217 }\r
1218\r
1219 strcpy (NewList->Str, Argv[1]);\r
1220 if (NewList->Str[strlen (NewList->Str) - 1] != '\\') {\r
1221 strcat (NewList->Str, "\\");\r
1222 }\r
1223\r
1224 NewList->Next = mGlobals.SubDirs;\r
1225 mGlobals.SubDirs = NewList;\r
1226 } else {\r
1227 Error (NULL, 0, 0, Argv[0], "option requires a subdirectory name");\r
1228 Usage ();\r
1229 return STATUS_ERROR;\r
1230 }\r
1231\r
1232 Argc--;\r
1233 Argv++;\r
1234 } else if (_stricmp (Argv[0], "-sub") == 0) {\r
1235 //\r
1236 // -sub symname symvalue to do string substitution in the output\r
1237 //\r
1238 if (Argc > 2) {\r
1239 //\r
1240 // Allocate memory for the symbol object\r
1241 //\r
1242 Symbol = malloc (sizeof (SYMBOL));\r
1243 if (Symbol == NULL) {\r
1244 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
1245 return STATUS_ERROR;\r
1246 }\r
1247 //\r
1248 // Allocate memory for the symbol name and value, then save copies\r
1249 //\r
1250 Symbol->Name = malloc (strlen (Argv[1]) + 1);\r
1251 if (Symbol->Name == NULL) {\r
1252 free (Symbol);\r
1253 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
1254 return STATUS_ERROR;\r
1255 }\r
1256\r
1257 strcpy (Symbol->Name, Argv[1]);\r
1258 Symbol->Value = malloc (strlen (Argv[2]) + 1);\r
1259 if (Symbol->Value == NULL) {\r
1260 free (Symbol->Name);\r
1261 free (Symbol);\r
1262 Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
1263 return STATUS_ERROR;\r
1264 }\r
1265\r
1266 strcpy (Symbol->Value, Argv[2]);\r
1267 //\r
1268 // Add it to the list\r
1269 //\r
1270 Symbol->Next = mGlobals.SymbolTable;\r
1271 mGlobals.SymbolTable = Symbol;\r
1272 } else {\r
1273 Error (NULL, 0, 0, Argv[0], "option requires a symbol name and value");\r
1274 Usage ();\r
1275 return STATUS_ERROR;\r
1276 }\r
1277 //\r
1278 // Skip over args\r
1279 //\r
1280 Argc -= 2;\r
1281 Argv += 2;\r
1282 } else if (_stricmp (Argv[0], "-nosystem") == 0) {\r
1283 mGlobals.NoSystem = TRUE;\r
1284 } else if (_stricmp (Argv[0], "-nodupes") == 0) {\r
1285 mGlobals.NoDupes = TRUE;\r
1286 } else if (_stricmp (Argv[0], "-nodups") == 0) {\r
1287 mGlobals.NoDupes = TRUE;\r
1288 } else if (_stricmp (Argv[0], "-target") == 0) {\r
1289 //\r
1290 // -target TargetFileName - Target object file (only one allowed right\r
1291 // now) is TargetFileName rather than SourceFile.obj\r
1292 //\r
1293 if (Argc > 1) {\r
1294 strcpy (mGlobals.TargetFileName, Argv[1]);\r
1295 } else {\r
1296 Error (NULL, 0, 0, Argv[0], "option requires a target file name");\r
1297 Usage ();\r
1298 return STATUS_ERROR;\r
1299 }\r
1300\r
1301 Argc--;\r
1302 Argv++;\r
1303 } else if (_stricmp (Argv[0], "-usesumdeps") == 0) {\r
1304 //\r
1305 // -usesumdeps Path - if we find an included file xxx.h, and file\r
1306 // Path/xxx.dep exists, list Path/xxx.dep as a dependency rather than\r
1307 // xxx.h and don't parse xxx.h. This allows you to create a dependency\r
1308 // file for a commonly included file, and have its dependency file updated\r
1309 // only if its included files are updated. Then anyone else including this\r
1310 // common include file can simply have a dependency on that file's .dep file\r
1311 // rather than on all the files included by it. Confusing enough?\r
1312 //\r
1313 mGlobals.UseSumDeps = 1;\r
1314 if (Argc > 1) {\r
1315 strcpy (mGlobals.SumDepsPath, Argv[1]);\r
1316 //\r
1317 // Add slash on end if not there\r
1318 //\r
1319 if (mGlobals.SumDepsPath[strlen (mGlobals.SumDepsPath) - 1] != '\\') {\r
1320 strcat (mGlobals.SumDepsPath, "\\");\r
1321 }\r
1322 } else {\r
1323 Error (NULL, 0, 0, Argv[0], "option requires path to summary dependency files");\r
1324 Usage ();\r
1325 return STATUS_ERROR;\r
1326 }\r
1327\r
1328 Argc--;\r
1329 Argv++;\r
1330\r
1331 } else if (_stricmp (Argv[0], "-o") == 0) {\r
1332 //\r
1333 // -o OutputFileName - specify an output filename for dependency list\r
1334 // check for one more arg\r
1335 //\r
1336 if (Argc > 1) {\r
95d675b5 1337 mGlobals.OutFileName = Argv[1];\r
1338 //\r
1339 // Use temp file for output\r
1340 // This can avoid overwriting previous existed dep file when error \r
1341 // ocurred in this tool\r
3eb9473e 1342 //\r
95d675b5 1343 sprintf (mGlobals.TmpFileName, "%s2", mGlobals.OutFileName);\r
3eb9473e 1344 //\r
95d675b5 1345 // Try to open the temp file\r
1346 //\r
1347 if ((mGlobals.OutFptr = fopen (mGlobals.TmpFileName, "w")) == NULL) {\r
1348 Error (NULL, 0, 0, mGlobals.TmpFileName, "could not open file for writing");\r
3eb9473e 1349 return STATUS_ERROR;\r
1350 }\r
3eb9473e 1351 } else {\r
1352 Error (NULL, 0, 0, Argv[0], "option requires output file name");\r
1353 Usage ();\r
1354 return STATUS_ERROR;\r
1355 }\r
1356\r
1357 Argc--;\r
1358 Argv++;\r
1359 } else if (_stricmp (Argv[0], "-v") == 0) {\r
1360 mGlobals.Verbose = TRUE;\r
1361 } else if (_stricmp (Argv[0], "-neverfail") == 0) {\r
1362 mGlobals.NeverFail = TRUE;\r
1363 } else if (_stricmp (Argv[0], "-q") == 0) {\r
1364 mGlobals.QuietMode = TRUE;\r
1365 } else if (_stricmp (Argv[0], "-ignorenotfound") == 0) {\r
1366 mGlobals.IgnoreNotFound = TRUE;\r
1367 } else if (_stricmp (Argv[0], "-asm") == 0) {\r
95d675b5 1368 if (mGlobals.IsCl) {\r
1369 Error (NULL, 0, 0, Argv[0], "option conflict with -cl");\r
1370 return STATUS_ERROR;\r
1371 } \r
3eb9473e 1372 mGlobals.IsAsm = TRUE;\r
95d675b5 1373 } else if (_stricmp (Argv[0], "-cl") == 0) {\r
1374 if (mGlobals.IsAsm) {\r
1375 Error (NULL, 0, 0, Argv[0], "option conflict with -asm");\r
1376 return STATUS_ERROR;\r
1377 }\r
1378 mGlobals.IsCl = TRUE; \r
3eb9473e 1379 } else if ((_stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {\r
1380 Usage ();\r
1381 return STATUS_ERROR;\r
1382 } else {\r
1383 Error (NULL, 0, 0, Argv[0], "unrecognized option");\r
1384 Usage ();\r
1385 return STATUS_ERROR;\r
1386 }\r
1387\r
1388 Argc--;\r
1389 Argv++;\r
1390 }\r
1391 //\r
1392 // Had to specify at least one source file\r
1393 //\r
1394 if (mGlobals.SourceFiles == NULL) {\r
1395 Error (NULL, 0, 0, "must specify one source file name", NULL);\r
1396 Usage ();\r
1397 return STATUS_ERROR;\r
1398 }\r
1399 //\r
1400 // Assume output to stdout if not specified\r
1401 //\r
1402 if (mGlobals.OutFptr == NULL) {\r
1403 mGlobals.OutFptr = stdout;\r
1404 }\r
1405\r
1406 return STATUS_SUCCESS;\r
1407}\r
1408//\r
1409// Free the global string lists we allocated memory for\r
1410//\r
1411static\r
1412void\r
1413FreeLists (\r
1414 VOID\r
1415 )\r
1416{\r
1417 STRING_LIST *Temp;\r
1418 SYMBOL *NextSym;\r
1419\r
1420 //\r
1421 // printf ("Free lists.....");\r
1422 //\r
1423 // Traverse the include paths, freeing each\r
1424 // printf ("freeing include paths\n");\r
1425 //\r
1426 while (mGlobals.IncludePaths != NULL) {\r
1427 Temp = mGlobals.IncludePaths->Next;\r
1428 //\r
1429 // printf ("Freeing include path string '%s' at 0x%X\n",\r
1430 // mGlobals.IncludePaths->Str, (int)(mGlobals.IncludePaths->Str));\r
1431 //\r
1432 free (mGlobals.IncludePaths->Str);\r
1433 //\r
1434 // printf ("Freeing include path object at 0x%X\n", (int)(mGlobals.IncludePaths));\r
1435 //\r
1436 free (mGlobals.IncludePaths);\r
1437 mGlobals.IncludePaths = Temp;\r
1438 }\r
1439 //\r
1440 // Traverse the source files, freeing each\r
1441 //\r
1442 while (mGlobals.SourceFiles != NULL) {\r
1443 Temp = mGlobals.SourceFiles->Next;\r
1444 free (mGlobals.SourceFiles->Str);\r
1445 free (mGlobals.SourceFiles);\r
1446 mGlobals.SourceFiles = Temp;\r
1447 }\r
1448 //\r
1449 // Traverse the subdirectory list, freeing each\r
1450 //\r
1451 while (mGlobals.SubDirs != NULL) {\r
1452 Temp = mGlobals.SubDirs->Next;\r
1453 free (mGlobals.SubDirs->Str);\r
1454 free (mGlobals.SubDirs);\r
1455 mGlobals.SubDirs = Temp;\r
1456 }\r
1457 //\r
1458 // Free the symbol table\r
1459 //\r
1460 while (mGlobals.SymbolTable != NULL) {\r
1461 NextSym = mGlobals.SymbolTable->Next;\r
1462 free (mGlobals.SymbolTable->Name);\r
1463 free (mGlobals.SymbolTable->Value);\r
1464 mGlobals.SymbolTable = NextSym;\r
1465 }\r
1466 //\r
1467 // printf ("done\n");\r
1468 //\r
1469}\r
1470\r
1471static\r
1472void\r
1473Usage (\r
1474 VOID\r
1475 )\r
1476/*++\r
1477\r
1478Routine Description:\r
1479\r
1480 Print usage information for this utility.\r
1481 \r
1482Arguments:\r
1483\r
1484 None.\r
1485\r
1486Returns:\r
1487\r
1488 Nothing.\r
1489 \r
1490--*/\r
1491{\r
3e99020d
LG
1492 int Index;\r
1493 const char *Str[] = {\r
1494 UTILITY_NAME" "UTILITY_VERSION" - Intel Make Dependencies Utility",\r
1495 " Copyright (C), 2004 - 2008 Intel Corporation",\r
1496 \r
1497#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )\r
1498 " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,\r
1499#endif\r
1500 "",\r
1501 "Usage:",\r
1502 " "UTILITY_NAME" [OPTION]...",\r
1503 "Options:",\r
1504 " -h or -? for this help information",\r
1505 " -f SourceFile add SourceFile to list of files to scan",\r
1506 " -i IncludePath add IncludePath to list of search paths",\r
1507 " -o OutputFile write output dependencies to OutputFile",\r
1508 " -s SubDir for each IncludePath, also search IncludePath\\SubDir",\r
1509 " -v for verbose output",\r
1510 " -ignorenotfound don't warn for files not found",\r
1511 " -target Target for single SourceFile, target is Target, not SourceFile.obj",\r
1512 " -q quiet mode to not report files not found if ignored",\r
1513 " -sub sym str replace all occurrances of 'str' with 'sym' in the output",\r
1514 " -nosystem not process system <include> files",\r
1515 " -neverfail always return a success return code",\r
3eb9473e 1516 //\r
3e99020d 1517 // " -nodupes keep track of include files, don't rescan duplicates",\r
3eb9473e 1518 //\r
3e99020d
LG
1519 " -usesumdeps path use summary dependency files in 'path' directory.",\r
1520 " -asm The SourceFiles are assembler files",\r
1521 " -cl The SourceFiles are the output of cl with /showIncludes",\r
3eb9473e 1522 NULL\r
1523 };\r
1524 for (Index = 0; Str[Index] != NULL; Index++) {\r
1525 fprintf (stdout, "%s\n", Str[Index]);\r
1526 }\r
1527}\r