VirtualBox

source: kBuild/trunk/src/kDepIDB/kDepIDB.c@ 398

Last change on this file since 398 was 398, checked in by bird, 19 years ago

Bugfixing.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.7 KB
Line 
1/* $Id: kDepIDB.c 398 2006-01-13 04:00:35Z bird $ */
2/** @file
3 *
4 * kDepIDB - Extract dependency information from a MS Visual C++ .idb file.
5 *
6 * Copyright (c) 2006 knut st. osmundsen <[email protected]>
7 *
8 *
9 * This file is part of kBuild.
10 *
11 * kBuild is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kBuild is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <errno.h>
35#include <ctype.h>
36#ifndef __WIN32__
37# include <stdint.h>
38#else
39 typedef unsigned char uint8_t;
40 typedef unsigned short uint16_t;
41 typedef unsigned int uint32_t;
42#endif
43#include "kDep.h"
44
45#define OFFSETOF(type, member) ( (int)(void *)&( ((type *)(void *)0)->member) )
46
47/*#define DEBUG*/
48#ifdef DEBUG
49#define dprintf(a) printf a
50#define dump(pb, cb, offBase) hexdump(pb,cb,offBase)
51#else
52#define dprintf(a) do {} while (0)
53#define dump(pb, cb, offBase) do {} while (0)
54#endif
55
56
57/*******************************************************************************
58* Global Variables *
59*******************************************************************************/
60/** the executable name. */
61static const char *argv0 = "";
62
63#ifdef DEBUG
64/**
65 * Performs a hexdump.
66 */
67static void hexdump(const uint8_t *pb, size_t cb, size_t offBase)
68{
69 static const char szHex[16] = "0123456789abcdef";
70
71 const unsigned cchWidth = 16;
72 size_t off = 0;
73 while (off < cb)
74 {
75 unsigned i;
76 printf("%s%0*x %04x:", off ? "\n" : "", sizeof(pb) * 2, offBase + off, off);
77 for (i = 0; i < cchWidth && off + i < cb ; i++)
78 printf(off + i < cb ? !(i & 7) && i ? "-%02x" : " %02x" : " ", pb[i]);
79
80 while (i++ < cchWidth)
81 printf(" ");
82 printf(" ");
83
84 for (i = 0; i < cchWidth && off + i < cb; i++)
85 {
86 const uint8_t u8 = pb[i];
87 printf("%c", u8 < 127 && u8 >= 32 ? u8 : '.', 1);
88 }
89 off += cchWidth;
90 pb += cchWidth;
91 }
92 printf("\n");
93}
94#endif
95
96/**
97 * Scans a stream (chunk of data really) for dependencies.
98 *
99 * @returns 0 on success.
100 * @returns !0 on failure.
101 * @param pbStream The stream bits.
102 * @param cbStream The size of the stream.
103 * @param pszPrefix The dependency prefix.
104 * @param cchPrefix The size of the prefix.
105 */
106static int ScanStream(uint8_t *pbStream, size_t cbStream, const char *pszPrefix, size_t cchPrefix)
107{
108 const uint8_t *pbCur = pbStream;
109 size_t cbLeft = cbStream;
110 register char chFirst = *pszPrefix;
111 while (cbLeft > cchPrefix + 2)
112 {
113 if ( *pbCur != chFirst
114 || memcmp(pbCur, pszPrefix, cchPrefix))
115 {
116 pbCur++;
117 cbLeft--;
118 }
119 else
120 {
121 size_t cchDep;
122 pbCur += cchPrefix;
123 cchDep = strlen(pbCur);
124 depAdd(pbCur, cchDep);
125 dprintf(("%05x: '%s'\n", pbCur - pbStream, pbCur));
126
127 pbCur += cchDep;
128 cbLeft -= cchDep + cchPrefix;
129 }
130 }
131
132 return 0;
133}
134
135
136
137/**
138 * Reads the file specified by the pInput file stream into memory.
139 * The size of the file is returned in *pcbFile if specified.
140 * The returned pointer should be freed by free().
141 */
142void *ReadFileIntoMemory(FILE *pInput, size_t *pcbFile)
143{
144 void *pvFile;
145 long cbFile;
146 int rc = 0;
147
148 /*
149 * Figure out file size.
150 */
151 if ( fseek(pInput, 0, SEEK_END) < 0
152 || (cbFile = ftell(pInput)) < 0
153 || fseek(pInput, 0, SEEK_SET))
154 {
155 fprintf(stderr, "%s: error: Failed to determin file size.\n", argv0);
156 return NULL;
157 }
158 if (pcbFile)
159 *pcbFile = cbFile;
160
161 /*
162 * Allocate memory and read the file.
163 */
164 pvFile = malloc(cbFile + 1);
165 if (pvFile)
166 {
167 if (fread(pvFile, cbFile, 1, pInput))
168 {
169 ((uint8_t *)pvFile)[cbFile] = '\0';
170 return pvFile;
171 }
172 fprintf(stderr, "%s: error: Failed to read %ld bytes.\n", argv0, cbFile);
173 free(pvFile);
174 }
175 else
176 fprintf(stderr, "%s: error: Failed to allocate %ld bytes (file mapping).\n", argv0, cbFile);
177 return NULL;
178}
179
180
181
182///////////////////////////////////////////////////////////////////////////////
183//
184//
185// P D B 7 . 0
186//
187//
188///////////////////////////////////////////////////////////////////////////////
189
190/** A PDB 7.0 Page number. */
191typedef uint32_t PDB70PAGE;
192/** Pointer to a PDB 7.0 Page number. */
193typedef PDB70PAGE *PPDB70PAGE;
194
195/**
196 * A PDB 7.0 stream.
197 */
198typedef struct PDB70STREAM
199{
200 /** The size of the stream. */
201 uint32_t cbStream;
202} PDB70STREAM, *PPDB70STREAM;
203
204
205/** The PDB 7.00 signature. */
206#define PDB_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\x1A" "DS\0\0"
207/**
208 * The PDB 7.0 header.
209 */
210typedef struct PDB70HDR
211{
212 /** The signature string. */
213 uint8_t szSignature[sizeof(PDB_SIGNATURE_700)];
214 /** The page size. */
215 uint32_t cbPage;
216 /** The start page. */
217 PDB70PAGE iStartPage;
218 /** The number of pages in the file. */
219 PDB70PAGE cPages;
220 /** The root stream directory. */
221 uint32_t cbRoot;
222 /** Unknown function, always 0. */
223 uint32_t u32Reserved;
224 /** The page index of the root page table. */
225 PDB70PAGE iRootPages;
226} PDB70HDR, *PPDB70HDR;
227
228/**
229 * The PDB 7.0 root directory.
230 */
231typedef struct PDB70ROOT
232{
233 /** The number of streams */
234 uint32_t cStreams;
235 /** Array of streams. */
236 PDB70STREAM aStreams[1];
237 /* uint32_t aiPages[] */
238} PDB70ROOT, *PPDB70ROOT;
239
240
241
242static int Pdb70ValidateHeader(PPDB70HDR pHdr, size_t cbFile)
243{
244 if (pHdr->cbPage * pHdr->cPages != cbFile)
245 {
246 fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", argv0);
247 return 1;
248 }
249 if (pHdr->iStartPage >= pHdr->cPages && pHdr->iStartPage <= 0)
250 {
251 fprintf(stderr, "%s: error: Bad PDB 2.0 header - iStartPage=%u cPages=%u.\n", argv0,
252 pHdr->iStartPage, pHdr->cPages);
253 return 1;
254 }
255 if (pHdr->iRootPages >= pHdr->cPages && pHdr->iRootPages <= 0)
256 {
257 fprintf(stderr, "%s: error: Bad PDB 2.0 header - iRootPages=%u cPage=%u.\n", argv0,
258 pHdr->iStartPage, pHdr->cPages);
259 return 1;
260 }
261 return 0;
262}
263
264static size_t Pdb70Align(PPDB70HDR pHdr, size_t cb)
265{
266 if (cb == ~(uint32_t)0 || !cb)
267 return 0;
268 return ((cb + pHdr->cbPage - 1) / pHdr->cbPage) * pHdr->cbPage;
269}
270
271static size_t Pdb70Pages(PPDB70HDR pHdr, size_t cb)
272{
273 if (cb == ~(uint32_t)0 || !cb)
274 return 0;
275 return (cb + pHdr->cbPage - 1) / pHdr->cbPage;
276}
277
278static void *Pdb70AllocAndRead(PPDB70HDR pHdr, size_t cb, PPDB70PAGE paiPageMap)
279{
280 const size_t cbPage = pHdr->cbPage;
281 size_t cPages = Pdb70Pages(pHdr, cb);
282 uint8_t *pbBuf = malloc(cPages * cbPage + 1);
283 if (pbBuf)
284 {
285 size_t iPage = 0;
286 while (iPage < cPages)
287 {
288 size_t off = paiPageMap[iPage];
289 if (off < pHdr->cPages)
290 {
291 off *= cbPage;
292 memcpy(pbBuf + iPage * cbPage, (uint8_t *)pHdr + off, cbPage);
293 dump(pbBuf + iPage * cbPage, cbPage, off);
294 }
295 else
296 {
297 fprintf(stderr, "%s: warning: Invalid page index %u (max %u)!\n", argv0,
298 (unsigned)off, pHdr->cPages);
299 memset(pbBuf + iPage * cbPage, 0, cbPage);
300 }
301
302 iPage++;
303 }
304 pbBuf[cPages * cbPage] = '\0';
305 }
306 else
307 fprintf(stderr, "%s: error: failed to allocate %u bytes\n", argv0, cPages * cbPage + 1);
308 return pbBuf;
309}
310
311static PPDB70ROOT Pdb70AllocAndReadRoot(PPDB70HDR pHdr)
312{
313 /*
314 * The tricky bit here is to find the right length.
315 * (Todo: Check if we can just use the stream size..)
316 */
317 PPDB70PAGE piPageMap = (uint32_t *)((uint8_t *)pHdr + pHdr->iRootPages * pHdr->cbPage);
318 PPDB70ROOT pRoot = Pdb70AllocAndRead(pHdr, pHdr->cbRoot, piPageMap);
319 if (pRoot)
320 {
321 /* This stuff is probably unnecessary: */
322 /* size = stream header + array of stream. */
323 size_t cb = OFFSETOF(PDB70ROOT, aStreams[pRoot->cStreams]);
324 free(pRoot);
325 pRoot = Pdb70AllocAndRead(pHdr, cb, piPageMap);
326 if (pRoot)
327 {
328 /* size += page tables. */
329 unsigned iStream = pRoot->cStreams;
330 while (iStream-- > 0)
331 if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
332 cb += Pdb70Pages(pHdr, pRoot->aStreams[iStream].cbStream) * sizeof(PDB70PAGE);
333 free(pRoot);
334 pRoot = Pdb70AllocAndRead(pHdr, cb, piPageMap);
335 if (pRoot)
336 {
337 /* validate? */
338 return pRoot;
339 }
340 }
341 }
342 return NULL;
343}
344
345static void *Pdb70AllocAndReadStream(PPDB70HDR pHdr, PPDB70ROOT pRoot, unsigned iStream, size_t *pcbStream)
346{
347 size_t cbStream = pRoot->aStreams[iStream].cbStream;
348 PPDB70PAGE paiPageMap;
349 if ( iStream >= pRoot->cStreams
350 || cbStream == ~(uint32_t)0)
351 {
352 fprintf(stderr, "%s: error: Invalid stream %d\n", iStream);
353 return NULL;
354 }
355
356 paiPageMap = (PPDB70PAGE)&pRoot->aStreams[pRoot->cStreams];
357 while (iStream-- > 0)
358 if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
359 paiPageMap += Pdb70Pages(pHdr, pRoot->aStreams[iStream].cbStream);
360
361 if (pcbStream)
362 *pcbStream = cbStream;
363 return Pdb70AllocAndRead(pHdr, cbStream, paiPageMap);
364}
365
366static int Pdb70Process(uint8_t *pbFile, size_t cbFile)
367{
368 PPDB70HDR pHdr = (PPDB70HDR)pbFile;
369 PPDB70ROOT pRoot;
370 unsigned iStream;
371 int rc = 0;
372 dprintf(("pdb70\n"));
373
374 /*
375 * Validate the header and read the root stream.
376 */
377 if (Pdb70ValidateHeader(pHdr, cbFile))
378 return 1;
379 pRoot = Pdb70AllocAndReadRoot(pHdr);
380 if (!pRoot)
381 return 1;
382
383 /*
384 * Iterate the streams in the root and scan their content for
385 * dependencies.
386 */
387 rc = 0;
388 for (iStream = 0; iStream < pRoot->cStreams && !rc; iStream++)
389 {
390 const size_t cbStream = Pdb70Align(pHdr, pRoot->aStreams[iStream].cbStream);
391 uint8_t *pbStream;
392 if ( pRoot->aStreams[iStream].cbStream == ~(uint32_t)0
393 || !pRoot->aStreams[iStream].cbStream)
394 continue;
395 dprintf(("Stream #%d: %#x bytes (%#x aligned)\n", iStream, pRoot->aStreams[iStream].cbStream, cbStream));
396 pbStream = (uint8_t *)Pdb70AllocAndReadStream(pHdr, pRoot, iStream, NULL);
397 if (pbStream)
398 {
399 rc = ScanStream(pbStream, cbStream, "/mr/inversedeps/", sizeof("/mr/inversedeps/") - 1);
400 free(pbStream);
401 }
402 else
403 rc = 1;
404 }
405
406 free(pRoot);
407 return rc;
408}
409
410
411
412///////////////////////////////////////////////////////////////////////////////
413//
414//
415// P D B 2 . 0
416//
417//
418///////////////////////////////////////////////////////////////////////////////
419
420
421/** A PDB 2.0 Page number. */
422typedef uint16_t PDB20PAGE;
423/** Pointer to a PDB 2.0 Page number. */
424typedef PDB20PAGE *PPDB20PAGE;
425
426/**
427 * A PDB 2.0 stream.
428 */
429typedef struct PDB20STREAM
430{
431 /** The size of the stream. */
432 uint32_t cbStream;
433 /** Some unknown value. */
434 uint32_t u32Unknown;
435} PDB20STREAM, *PPDB20STREAM;
436
437/** The PDB 2.00 signature. */
438#define PDB_SIGNATURE_200 "Microsoft C/C++ program database 2.00\r\n\x1A" "JG\0"
439/**
440 * The PDB 2.0 header.
441 */
442typedef struct PDB20HDR
443{
444 /** The signature string. */
445 uint8_t szSignature[sizeof(PDB_SIGNATURE_200)];
446 /** The page size. */
447 uint32_t cbPage;
448 /** The start page - whatever that is... */
449 PDB20PAGE iStartPage;
450 /** The number of pages in the file. */
451 PDB20PAGE cPages;
452 /** The root stream directory. */
453 PDB20STREAM RootStream;
454 /** The root page table. */
455 PDB20PAGE aiRootPageMap[1];
456} PDB20HDR, *PPDB20HDR;
457
458/**
459 * The PDB 2.0 root directory.
460 */
461typedef struct PDB20ROOT
462{
463 /** The number of streams */
464 uint16_t cStreams;
465 /** Reserved or high part of cStreams. */
466 uint16_t u16Reserved;
467 /** Array of streams. */
468 PDB20STREAM aStreams[1];
469} PDB20ROOT, *PPDB20ROOT;
470
471
472static int Pdb20ValidateHeader(PPDB20HDR pHdr, size_t cbFile)
473{
474 if (pHdr->cbPage * pHdr->cPages != cbFile)
475 {
476 fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", argv0);
477 return 1;
478 }
479 if (pHdr->iStartPage >= pHdr->cPages && pHdr->iStartPage <= 0)
480 {
481 fprintf(stderr, "%s: error: Bad PDB 2.0 header - cbPage * cPages != cbFile.\n", argv0);
482 return 1;
483 }
484 return 0;
485}
486
487static size_t Pdb20Pages(PPDB20HDR pHdr, size_t cb)
488{
489 if (cb == ~(uint32_t)0 || !cb)
490 return 0;
491 return (cb + pHdr->cbPage - 1) / pHdr->cbPage;
492}
493
494static void *Pdb20AllocAndRead(PPDB20HDR pHdr, size_t cb, PPDB20PAGE paiPageMap)
495{
496 size_t cPages = Pdb20Pages(pHdr, cb);
497 uint8_t *pbBuf = malloc(cPages * pHdr->cbPage + 1);
498 if (pbBuf)
499 {
500 size_t iPage = 0;
501 while (iPage < cPages)
502 {
503 size_t off = paiPageMap[iPage];
504 off *= pHdr->cbPage;
505 memcpy(pbBuf + iPage * pHdr->cbPage, (uint8_t *)pHdr + off, pHdr->cbPage);
506 iPage++;
507 }
508 pbBuf[cPages * pHdr->cbPage] = '\0';
509 }
510 else
511 fprintf(stderr, "%s: error: failed to allocate %d bytes\n", argv0, cPages * pHdr->cbPage + 1);
512 return pbBuf;
513}
514
515static PPDB20ROOT Pdb20AllocAndReadRoot(PPDB20HDR pHdr)
516{
517 /*
518 * The tricky bit here is to find the right length.
519 * (Todo: Check if we can just use the stream size..)
520 */
521 PPDB20ROOT pRoot = Pdb20AllocAndRead(pHdr, sizeof(*pRoot), &pHdr->aiRootPageMap[0]);
522 if (pRoot)
523 {
524 /* size = stream header + array of stream. */
525 size_t cb = OFFSETOF(PDB20ROOT, aStreams[pRoot->cStreams]);
526 free(pRoot);
527 pRoot = Pdb20AllocAndRead(pHdr, cb, &pHdr->aiRootPageMap[0]);
528 if (pRoot)
529 {
530 /* size += page tables. */
531 unsigned iStream = pRoot->cStreams;
532 while (iStream-- > 0)
533 if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
534 cb += Pdb20Pages(pHdr, pRoot->aStreams[iStream].cbStream) * sizeof(PDB20PAGE);
535 free(pRoot);
536 pRoot = Pdb20AllocAndRead(pHdr, cb, &pHdr->aiRootPageMap[0]);
537 if (pRoot)
538 {
539 /* validate? */
540 return pRoot;
541 }
542 }
543 }
544 return NULL;
545
546}
547
548static void *Pdb20AllocAndReadStream(PPDB20HDR pHdr, PPDB20ROOT pRoot, unsigned iStream, size_t *pcbStream)
549{
550 size_t cbStream = pRoot->aStreams[iStream].cbStream;
551 PPDB20PAGE paiPageMap;
552 if ( iStream >= pRoot->cStreams
553 || cbStream == ~(uint32_t)0)
554 {
555 fprintf(stderr, "%s: error: Invalid stream %d\n", iStream);
556 return NULL;
557 }
558
559 paiPageMap = (PPDB20PAGE)&pRoot->aStreams[pRoot->cStreams];
560 while (iStream-- > 0)
561 if (pRoot->aStreams[iStream].cbStream != ~(uint32_t)0)
562 paiPageMap += Pdb20Pages(pHdr, pRoot->aStreams[iStream].cbStream);
563
564 if (pcbStream)
565 *pcbStream = cbStream;
566 return Pdb20AllocAndRead(pHdr, cbStream, paiPageMap);
567}
568
569static int Pdb20Process(uint8_t *pbFile, size_t cbFile)
570{
571 PPDB20HDR pHdr = (PPDB20HDR)pbFile;
572 PPDB20ROOT pRoot;
573 unsigned iStream;
574 int rc = 0;
575
576 /*
577 * Validate the header and read the root stream.
578 */
579 if (Pdb20ValidateHeader(pHdr, cbFile))
580 return 1;
581 pRoot = Pdb20AllocAndReadRoot(pHdr);
582 if (!pRoot)
583 return 1;
584
585 /*
586 * Iterate the streams in the root and scan their content for
587 * dependencies.
588 */
589 rc = 0;
590 for (iStream = 0; iStream < pRoot->cStreams && !rc; iStream++)
591 {
592 uint8_t *pbStream;
593 if (pRoot->aStreams[iStream].cbStream == ~(uint32_t)0)
594 continue;
595 pbStream = (uint8_t *)Pdb20AllocAndReadStream(pHdr, pRoot, iStream, NULL);
596 if (pbStream)
597 {
598 rc = ScanStream(pbStream, pRoot->aStreams[iStream].cbStream, "/ipm/header/", sizeof("/ipm/header/") - 1);
599 free(pbStream);
600 }
601 else
602 rc = 1;
603 }
604
605 free(pRoot);
606 return rc;
607}
608
609
610/**
611 * Make an attempt at parsing a Visual C++ IDB file.
612 */
613static int ProcessIDB(FILE *pInput)
614{
615 long cbFile;
616 char *pbFile;
617 char *pbHdr = PDB_SIGNATURE_200;
618 int rc = 0;
619
620 /*
621 * Read the file into memory.
622 */
623 pbFile = (char *)ReadFileIntoMemory(pInput, &cbFile);
624 if (!pbFile)
625 return 1;
626
627 /*
628 * Figure out which parser to use.
629 */
630 if (!memcmp(pbFile, PDB_SIGNATURE_700, sizeof(PDB_SIGNATURE_700)))
631 rc = Pdb70Process(pbFile, cbFile);
632 else if (!memcmp(pbFile, PDB_SIGNATURE_200, sizeof(PDB_SIGNATURE_200)))
633 rc = Pdb20Process(pbFile, cbFile);
634 else
635 {
636 fprintf(stderr, "%s: error: Doesn't recognize the header of the Visual C++ IDB file.\n", argv0);
637 rc = 1;
638 }
639
640 free(pbFile);
641 return rc;
642}
643
644
645static void usage(const char *argv0)
646{
647 printf("syntax: %s -o <output> -t <target> [-f] [-s] <vc idb-file>\n", argv0);
648}
649
650
651int main(int argc, char *argv[])
652{
653 int i;
654
655 /* Arguments. */
656 FILE *pOutput = NULL;
657 const char *pszOutput = NULL;
658 FILE *pInput = NULL;
659 const char *pszTarget = NULL;
660 int fStubs = 0;
661 int fFixCase = 0;
662 /* Argument parsing. */
663 int fInput = 0; /* set when we've found input argument. */
664
665 argv0 = argv[0];
666
667 /*
668 * Parse arguments.
669 */
670 if (argc <= 1)
671 {
672 usage(argv[0]);
673 return 1;
674 }
675 for (i = 1; i < argc; i++)
676 {
677 if (argv[i][0] == '-')
678 {
679 switch (argv[i][1])
680 {
681 /*
682 * Output file.
683 */
684 case 'o':
685 {
686 pszOutput = &argv[i][2];
687 if (pOutput)
688 {
689 fprintf(stderr, "%s: syntax error: only one output file!\n", argv[0]);
690 return 1;
691 }
692 if (!*pszOutput)
693 {
694 if (++i >= argc)
695 {
696 fprintf(stderr, "%s: syntax error: The '-o' argument is missing the filename.\n", argv[0]);
697 return 1;
698 }
699 pszOutput = argv[i];
700 }
701 if (pszOutput[0] == '-' && !pszOutput[1])
702 pOutput = stdout;
703 else
704 pOutput = fopen(pszOutput, "w");
705 if (!pOutput)
706 {
707 fprintf(stderr, "%s: error: Failed to create output file '%s'.\n", argv[0], pszOutput);
708 return 1;
709 }
710 break;
711 }
712
713 /*
714 * Target name.
715 */
716 case 't':
717 {
718 if (pszTarget)
719 {
720 fprintf(stderr, "%s: syntax error: only one target!\n", argv[0]);
721 return 1;
722 }
723 pszTarget = &argv[i][2];
724 if (!*pszTarget)
725 {
726 if (++i >= argc)
727 {
728 fprintf(stderr, "%s: syntax error: The '-t' argument is missing the target name.\n", argv[0]);
729 return 1;
730 }
731 pszTarget = argv[i];
732 }
733 break;
734 }
735
736 /*
737 * Fix case.
738 */
739 case 'f':
740 {
741 fFixCase = 1;
742 break;
743 }
744
745 /*
746 * Generate stubs.
747 */
748 case 's':
749 {
750 fStubs = 1;
751 break;
752 }
753
754 /*
755 * Invalid argument.
756 */
757 default:
758 fprintf(stderr, "%s: syntax error: Invalid argument '%s'.\n", argv[0], argv[i]);
759 usage(argv[0]);
760 return 1;
761 }
762 }
763 else
764 {
765 pInput = fopen(argv[i], "rb");
766 if (!pInput)
767 {
768 fprintf(stderr, "%s: error: Failed to open input file '%s'.\n", argv[0], argv[i]);
769 return 1;
770 }
771 fInput = 1;
772 }
773
774 /*
775 * End of the line?
776 */
777 if (fInput)
778 {
779 if (++i < argc)
780 {
781 fprintf(stderr, "%s: syntax error: No arguments shall follow the input spec.\n", argv[0]);
782 return 1;
783 }
784 break;
785 }
786 }
787
788 /*
789 * Got all we require?
790 */
791 if (!pInput)
792 {
793 fprintf(stderr, "%s: syntax error: No input!\n", argv[0]);
794 return 1;
795 }
796 if (!pOutput)
797 {
798 fprintf(stderr, "%s: syntax error: No output!\n", argv[0]);
799 return 1;
800 }
801 if (!pszTarget)
802 {
803 fprintf(stderr, "%s: syntax error: No target!\n", argv[0]);
804 return 1;
805 }
806
807 /*
808 * Do the parsing.
809 */
810 i = ProcessIDB(pInput);
811
812 /*
813 * Write the dependecy file.
814 */
815 if (!i)
816 {
817 depOptimize(fFixCase);
818 fprintf(pOutput, "%s:", pszTarget);
819 depPrint(pOutput);
820 if (fStubs)
821 depPrintStubs(pOutput);
822 }
823
824 /*
825 * Close the output, delete output on failure.
826 */
827 if (!i && ferror(pOutput))
828 {
829 i = 1;
830 fprintf(stderr, "%s: error: Error writing to '%s'.\n", argv[0], pszOutput);
831 }
832 fclose(pOutput);
833 if (i)
834 {
835 if (unlink(pszOutput))
836 fprintf(stderr, "%s: warning: failed to remove output file '%s' on failure.\n", argv[0], pszOutput);
837 }
838
839 return i;
840}
841
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette