source: trunk/third/firefox/config/makedep.cpp @ 21695

Revision 21695, 26.6 KB checked in by rbasch, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21694, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Netscape Public License
6 * Version 1.1 (the "License"); you may not use this file except in
7 * compliance with the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/NPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 *
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the NPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the NPL, the GPL or the LGPL.
36 *
37 * ***** END LICENSE BLOCK ***** */
38
39// Dependency building hack
40//
41
42#include <stdio.h>
43#include <stdlib.h>
44#include <sys/stat.h>
45#include <ctype.h>
46#include <afxcoll.h>
47#include <afxtempl.h>
48
49int mainReturn = 0;
50BOOL b16 = FALSE;
51BOOL bSimple = FALSE;
52
53//      freopen won't work on stdout in win16
54FILE *pAltFile = stdout;
55
56CStringArray includeDirectories;
57
58// turn a file, relative path or other into an absolute path
59// This function copied from MFC 1.52
60BOOL PASCAL _AfxFullPath(LPSTR lpszPathOut, LPCSTR lpszFileIn)
61        // lpszPathOut = buffer of _MAX_PATH
62        // lpszFileIn = file, relative path or absolute path
63        // (both in ANSI character set)
64{
65        OFSTRUCT of;
66        if (OpenFile(lpszFileIn, &of, OF_PARSE) != HFILE_ERROR)
67        {
68                // of.szPathName is in the OEM character set
69                OemToAnsi(of.szPathName, lpszPathOut);
70                AnsiUpper(lpszPathOut); // paths in upper case just to be sure
71                return TRUE;
72        }
73        else
74        {
75                TRACE1("Warning: could not parse the path %Fs\n", lpszFileIn);
76                lstrcpy(lpszPathOut, lpszFileIn);  // take it literally
77                AnsiUpper(lpszPathOut); // paths in upper case just to be sure
78                return FALSE;
79        }
80}
81
82void AddIncludeDirectory( char *pString ){
83    CString s = pString;
84        int len = s.GetLength();
85    if(len > 0 && s[len - 1] != '\\' ){
86        s += "\\";
87    }
88    includeDirectories.Add(s);
89}
90
91BOOL FileExists( const char *pString ){
92    struct _stat buf;
93    int result;
94
95    result = _stat( pString, &buf );
96    return (result == 0);
97}
98
99void FixPathName(CString& str) {
100        str.MakeUpper();                // all upper case
101
102        // now switch all forward slashes to back slashes
103        int index;
104        while ((index = str.Find('/')) != -1) {
105                str.SetAt(index, '\\');
106        }
107}
108
109void FATName(CString& csLONGName)
110{
111    //  Only relevant for 16 bits.
112    if(b16) {
113        //  Convert filename to FAT (8.3) equivalent.
114        char aBuffer[2048];
115
116        if(GetShortPathName(csLONGName, aBuffer, 2048)) {
117            csLONGName = aBuffer;
118        }
119    }
120}
121
122
123class CFileRecord {
124public:
125    CString m_shortName;
126    CString m_pathName;
127    CPtrArray m_includes;  // pointers to CFileRecords in fileMap
128    BOOL m_bVisited;
129    BOOL m_bSystem;
130    BOOL m_bSource;
131    static CMapStringToPtr fileMap;      // contains all allocated CFileRecords
132    static CStringArray orderedFileNames;
133    static CMapStringToPtr includeMap;   // pointer to CFileRecords in fileMap
134    static CMapStringToPtr noDependMap;
135
136    CFileRecord( const char *shortName, const char* pFullName, BOOL bSystem, BOOL bSource):
137                m_shortName( shortName ),
138                m_pathName(),
139                m_includes(),
140                m_bVisited(FALSE),
141                m_bSource( bSource ),
142                m_bSystem(bSystem){
143
144                m_pathName = pFullName;
145                FixPathName(m_pathName);                                // all upper case for consistency
146                ASSERT(FindFileRecord(m_pathName) == NULL);     // make sure it's not already in the map
147        fileMap[m_pathName] = this;                     // add this to the filemap, using the appropriate name as the key
148                if (bSource) {
149                        orderedFileNames.Add(m_pathName);       // remember the order we saw source files in
150                }
151    }
152
153    //
154    // open the file and grab all the includes.
155    //
156    void ProcessFile(){
157        FILE *f;
158                CString fullName;
159        BOOL bSystem;
160                DWORD lineCntr = 0;
161                char *a = new char[2048];
162        memset(a, 0, 2048);
163                char srcPath[_MAX_PATH];
164
165                // construct the full path
166                if (!_AfxFullPath(srcPath, m_pathName)) {
167                        strcpy(srcPath, m_pathName);
168                }
169
170                // strip off the source filename to end up with just the path
171                LPSTR pTemp = strrchr(srcPath, '\\');
172                if (pTemp) {
173                        *(pTemp + 1) = 0;
174                }
175
176        f = fopen(m_pathName, "r");
177        if(f != NULL && f != (FILE *)-1)  {
178                        setvbuf(f, NULL, _IOFBF, 32768);                // use a large file buffer
179            while(fgets(a, 2047, f)) {
180                                // if the string "//{{NO_DEPENDENCIES}}" is at the start of one of the
181                                // first 10 lines of a file, don't build dependencies on it or any
182                                // of the files it includes
183                                if (lineCntr < 10) {
184                                        static char* pDependStr = "//{{NO_DEPENDENCIES}}";
185                                        if (strncmp(a, pDependStr, strlen(pDependStr)) == 0) {
186                                                noDependMap[m_pathName] = 0;    // add it to the noDependMap
187                                                break;                                                  // no need for further processing of this file
188                                        }
189                                }
190                                ++lineCntr;
191                                // have to handle a variety of legal syntaxes that we find in our source files:
192                                //    #include
193                                // #   include
194                // #include
195                                // if the first non-whitespace char is a '#', consider this line
196                                pTemp = a;
197                                pTemp += strspn(pTemp, " \t");                  // skip whitespace
198                                if (*pTemp == '#') {
199                                        ++pTemp;                                                        // skip the '#'
200                                        pTemp += strspn(pTemp, " \t");          // skip more whitespace
201                                        if( !strncmp(pTemp, "include", 7) ){
202                                                pTemp += 7;                                             // skip the "include"
203                                                pTemp += strspn(pTemp, " \t");  // skip more whitespace
204                                                bSystem = (*pTemp == '<');              // mark if it's a system include or not
205                        // forget system files -- we just have to search all the paths
206                        // every time and never find them! This change alone speeds a full
207                        // depend run on my system from 5 minutes to 3:15
208                                                // if (bSystem || (*pTemp == '"')) {
209                        if (*pTemp == '"') {
210                                                        LPSTR pStart = pTemp + 1;       // mark the start of the string
211                                                        pTemp = pStart + strcspn(pStart, ">\" ");       // find the end of the string
212                                                        *pTemp = 0;                                     // terminate the string
213
214                                                        // construct the full pathname from the path part of the
215                                                        // source file and the name listed here
216                                                        fullName = srcPath;
217                                                        fullName += pStart;
218                                                        CFileRecord *pAddMe = AddFile( pStart, fullName, bSystem );
219                                                        if (pAddMe) {
220                                                                m_includes.Add(pAddMe);
221                                                        }
222                                                }
223                                        }
224                                }
225            }
226            fclose(f);
227        }
228        delete [] a;
229    }
230
231    void PrintIncludes(){
232        int i = 0;
233        while( i < m_includes.GetSize() ){
234            CFileRecord *pRec = (CFileRecord*) m_includes[i];
235
236            //  Don't write out files that don't exist or are not in the namespace
237            //      of the programs using it (netscape_AppletMozillaContext.h doesn't
238            //      mix well with 16 bits).
239                        // Also don't write out files that are in the noDependMap
240                        void*   lookupJunk;
241            if( !pRec->m_bVisited && pRec->m_pathName.GetLength() != 0 && !noDependMap.Lookup(pRec->m_pathName, lookupJunk)) {
242
243                                // not supposed to have a file in the list that doesn't exist
244                                ASSERT(FileExists(pRec->m_pathName));
245
246                CString csOutput;
247                csOutput = pRec->m_pathName;
248                FATName(csOutput);
249
250                                fprintf(pAltFile, "\\\n    %s ", (const char *) csOutput );
251
252                                // mark this one as done so we don't do it more than once
253                pRec->m_bVisited = TRUE;
254
255                pRec->PrintIncludes();
256            }
257            i++;
258        }
259    }
260
261    void PrintDepend(){
262        CFileRecord *pRec;
263        BOOL bFound;
264        POSITION next;
265        CString name;
266
267                // clear all the m_bVisisted flags so we can use it to keep track
268                // of whether we've already output this file as a dependency
269        next = fileMap.GetStartPosition();
270        while( next ){
271            fileMap.GetNextAssoc( next, name, *(void**)&pRec );
272            pRec->m_bVisited = FALSE;
273        }
274
275        char fname[_MAX_FNAME];
276
277                if (pRec->m_pathName.GetLength() != 0) {
278            if( bSimple ){
279                        fprintf(pAltFile, "\n\n\n%s:\t", m_pathName );
280            }
281            else {
282                CString csOutput;
283                csOutput = m_pathName;
284                FATName(csOutput);
285
286                        _splitpath( csOutput, NULL, NULL, fname, NULL );
287
288                        fprintf(pAltFile, "\n\n\n$(OUTDIR)\\%s.obj: %s ", fname, (const char*) csOutput );
289            }
290                m_bVisited = TRUE;              // mark it as done so we won't do it again
291                PrintIncludes();
292                }
293    }
294
295
296    static CString NormalizeFileName( const char* pName ){
297        return CString(pName);
298    }
299
300    static CFileRecord* FindFileRecord( const char *pName ){
301                CFileRecord* pRec = NULL;
302                CString name(pName);
303                FixPathName(name);
304                fileMap.Lookup(name, (void*&)pRec);
305                return(pRec);
306    }
307public:
308    static CFileRecord* AddFile( const char* pShortName, const char* pFullName, BOOL bSystem = FALSE,
309                BOOL bSource = FALSE ){
310
311                char fullName[_MAX_PATH];
312                BOOL bFound = FALSE;
313                CString foundName;
314                CString fixedShortName;
315        CString s;
316
317        // normalize the name
318        fixedShortName = pShortName;
319        FixPathName(fixedShortName);
320        pShortName = fixedShortName;
321
322        // if it is source, we might be getting an obj file.  If we do,
323        //  convert it to a c or c++ file.
324        if( bSource && (strcmp(GetExt(pShortName),".obj") == 0) ){
325            char path_buffer[_MAX_PATH];
326            char fname[_MAX_FNAME] = "";
327            CString s;
328
329            _splitpath( pShortName, NULL, NULL, fname, NULL );
330            if( FileExists( s = CString(fname) + ".cpp") ){
331                pShortName = s;
332                pFullName = s;
333            }
334            else if( FileExists( s = CString(fname) + ".c" ) ){
335                pShortName = s;
336                pFullName = s;
337            }
338            else {
339                return 0;
340            }
341        }
342
343                // if pFullName was not constructed, construct it here based on the current directory
344                if (!pFullName) {
345                        _AfxFullPath(fullName, pShortName);
346                        pFullName = fullName;
347                }
348               
349                // first check to see if we already have this exact file
350                CFileRecord *pRec = FindFileRecord(pFullName);
351
352        // if not found and not a source file check the header list --
353        // all files we've found in include directories are in the includeMap.
354        // we can save gobs of time by getting it from there
355        if (!pRec && !bSource)
356            includeMap.Lookup(fixedShortName, (void*&)pRec);
357
358        if (!pRec) {
359            // not in one of our lists, start scrounging on disk
360
361            // check the fullname first
362            if (FileExists(pFullName)) {
363                foundName = pFullName;
364                bFound = TRUE;
365            }
366            else {
367                // if still not found, search the include paths
368                int i = 0;
369                while( i < includeDirectories.GetSize() ){
370                    if( FileExists( includeDirectories[i] + pShortName ) ){
371                        foundName = includeDirectories[i] + pShortName;
372                        bFound = TRUE;
373                        break;
374                    }
375                    i++;
376                }
377            }
378        }
379        else {
380            // we found it
381            bFound = TRUE;
382        }
383
384                // source files are not allowed to be missing
385                if (bSource && !pRec && !bFound) {
386                        fprintf(stderr, "Source file: %s doesn't exist\n", pFullName);
387                        mainReturn = -1;                // exit with an error, don't write out the results
388                }
389
390#ifdef _DEBUG
391                if (!pRec && !bFound && !bSystem) {
392                        fprintf(stderr, "Header not found: %s (%s)\n", pShortName, pFullName);
393                }
394#endif
395
396                // if none of the above logic found it already in the list,
397        // must be a new file, add it to the list
398        if (bFound && (pRec == NULL)) {
399            pRec = new CFileRecord( pShortName, foundName, bSystem, bSource);
400
401                        // if this one isn't a source file add it to the includeMap
402                        // for performance reasons (so we can find it there next time rather
403                        // than having to search the file system again)
404                        if (!bSource) {
405                                includeMap[pShortName] = pRec;
406                        }
407        }
408        return pRec;
409    }
410
411
412    static void PrintDependancies(){
413        CFileRecord *pRec;
414        BOOL bFound;
415        POSITION next;
416        CString name;
417
418                // use orderedFileNames to preserve order
419                for (int pos = 0; pos < orderedFileNames.GetSize(); pos++) {
420                        pRec = FindFileRecord(orderedFileNames[pos]);
421            if(pRec && pRec->m_bSource ){
422                pRec->PrintDepend();
423                        }
424                }
425    }
426
427
428    void PrintDepend2(){
429        CFileRecord *pRec;
430        int i;
431
432        if( m_includes.GetSize() != 0 ){
433                        fprintf(pAltFile, "\n\n\n%s: \\\n",m_pathName );
434            i = 0;
435            while( i < m_includes.GetSize() ){
436                pRec = (CFileRecord*) m_includes[i];
437                        fprintf(pAltFile, "\t\t\t%s\t\\\n",pRec->m_pathName );
438                i++;
439            }
440        }
441    }
442
443    static void PrintDependancies2(){
444        CFileRecord *pRec;
445        BOOL bFound;
446        POSITION next;
447        CString name;
448
449        next = fileMap.GetStartPosition();
450        while( next ){
451            fileMap.GetNextAssoc( next, name, *(void**)&pRec );
452            pRec->PrintDepend2();
453        }
454    }
455
456
457    static void PrintTargets(const char *pMacroName, const char *pDelimiter){
458        CFileRecord *pRec;
459        BOOL bFound;
460        POSITION next;
461        CString name;
462
463        BOOL bNeedDelimiter = FALSE;
464                fprintf(pAltFile, "%s = ", pMacroName);       
465
466                // use orderedFileNames to preserve target order
467                for (int pos = 0; pos < orderedFileNames.GetSize(); pos++) {
468                        pRec = FindFileRecord(orderedFileNames[pos]);
469                        ASSERT(pRec);
470
471            if( pRec && pRec->m_bSource && pRec->m_pathName.GetLength() != 0){
472                char fname[_MAX_FNAME];
473
474                CString csOutput;
475                csOutput = pRec->m_pathName;
476                FATName(csOutput);
477
478                _splitpath( csOutput, NULL, NULL, fname, NULL );
479
480                if(bNeedDelimiter)  {
481                    fprintf(pAltFile, "%s\n", pDelimiter);
482                    bNeedDelimiter = FALSE;
483                }
484
485                                fprintf(pAltFile, "     $(OUTDIR)\\%s.obj   ", fname );
486                bNeedDelimiter = TRUE;
487            }
488        }
489                fprintf(pAltFile, "\n\n\n");       
490    }
491
492    static CString DirDefine( const char *pPath ){
493        char path_buffer[_MAX_PATH];
494        char dir[_MAX_DIR] = "";
495        char dir2[_MAX_DIR] = "";
496        char fname[_MAX_FNAME] = "";
497        char ext[_MAX_EXT] = "";
498        CString s;
499
500        _splitpath( pPath, 0, dir, 0, ext );
501
502        BOOL bDone = FALSE;
503
504        while( dir && !bDone){
505            // remove the trailing slash
506            dir[ strlen(dir)-1] = 0;
507            _splitpath( dir, 0, dir2, fname, 0 );
508            if( strcmp( fname, "SRC" ) == 0 ){
509                strcpy( dir, dir2 );
510            }
511            else {
512                bDone = TRUE;
513            }
514        }
515        s = CString(fname) + "_" + (ext+1);
516        return s;
517    }
518
519
520    static void PrintSources(){
521        int i;
522        CString dirName, newDirName;
523
524        for( i=0; i< orderedFileNames.GetSize(); i++ ){
525            newDirName= DirDefine( orderedFileNames[i] );
526            if( newDirName != dirName ){
527                fprintf( pAltFile, "\n\n\nFILES_%s= $(FILES_%s) \\",
528                        (const char*)newDirName, (const char*)newDirName );
529                dirName = newDirName;
530            }
531            fprintf( pAltFile, "\n\t%s^", (const char*)orderedFileNames[i] );
532        }
533    }
534
535    static CString SourceDirName( const char *pPath, BOOL bFileName){
536        char path_buffer[_MAX_PATH];
537        char drive[_MAX_DRIVE] = "";
538        char dir[_MAX_DIR] = "";
539        char fname[_MAX_FNAME] = "";
540        char ext[_MAX_EXT] = "";
541        CString s;
542
543        _splitpath( pPath, drive, dir, fname, ext );
544
545        s = CString(drive) + dir;
546        if( bFileName ){
547            s += CString("FNAME") + ext;
548        }
549        else {
550            // remove the trailing slash
551            s = s.Left( s.GetLength() - 1 );
552        }
553        return s;
554    }
555
556
557    static CString GetExt( const char *pPath){
558        char ext[_MAX_EXT] = "";
559
560        _splitpath( pPath, 0,0,0, ext );
561
562        CString s = CString(ext);
563        s.MakeLower();
564        return s;
565    }
566
567    static void PrintBuildRules(){
568        int i;
569        CString dirName;
570       
571        CMapStringToPtr dirList;
572
573        for( i=0; i< orderedFileNames.GetSize(); i++ ){
574            dirList[ SourceDirName(orderedFileNames[i], TRUE) ]= 0;
575        }
576
577        POSITION next;
578        CString name;
579        void *pVal;
580
581        next = dirList.GetStartPosition();
582        while( next ){
583            dirList.GetNextAssoc( next, name, pVal);
584            CString dirDefine = DirDefine( name );
585            CString ext = GetExt( name );
586            name = SourceDirName( name, FALSE );
587            CString response = dirDefine.Left(8);
588
589            fprintf( pAltFile,
590                "\n\n\n{%s}%s{$(OUTDIR)}.obj:\n"
591                "\t@rem <<$(OUTDIR)\\%s.cl\n"
592                "\t$(CFILEFLAGS)\n"
593                "\t$(CFLAGS_%s)\n"
594                "<<KEEP\n"
595                "\t$(CPP) @$(OUTDIR)\\%s.cl %%s\n",
596                (const char*)name,
597                (const char*)ext,
598                (const char*)response,
599                (const char*)dirDefine,
600                (const char*)response
601            );
602
603            fprintf( pAltFile,
604                "\n\n\nBATCH_%s:\n"
605                "\t@rem <<$(OUTDIR)\\%s.cl\n"
606                "\t$(CFILEFLAGS)\n"
607                "\t$(CFLAGS_%s)\n"
608                "\t$(FILES_%s)\n"
609                "<<KEEP\n"
610                "\t$(TIMESTART)\n"
611                "\t$(CPP) @$(OUTDIR)\\%s.cl\n"
612                "\t$(TIMESTOP)\n",
613                (const char*)dirDefine,
614                (const char*)response,
615                (const char*)dirDefine,
616                (const char*)dirDefine,
617                (const char*)response
618            );
619        }
620
621        //
622        // Loop through one more time and build the final batch build
623        //  rule
624        //
625        fprintf( pAltFile,
626            "\n\n\nBATCH_BUILD_OBJECTS:\t\t\\\n");
627
628        next = dirList.GetStartPosition();
629        while( next ){
630            dirList.GetNextAssoc( next, name, pVal);
631            CString dirDefine = DirDefine( name );
632
633            fprintf( pAltFile,
634                "\tBATCH_%s\t\t\\\n", dirDefine );
635        }
636
637        fprintf( pAltFile,
638            "\n\n");
639    }
640       
641
642    static void ProcessFiles(){
643        CFileRecord *pRec;
644        BOOL bFound;
645        POSITION next;
646        CString name;
647
648                // search all the files for headers, adding each one to the list when found
649                // rather than do it recursively, it simple marks each one it's done
650                // and starts over, stopping only when all are marked as done
651
652        next = fileMap.GetStartPosition();
653        while( next ){
654            fileMap.GetNextAssoc( next, name, *(void**)&pRec );
655            if( pRec->m_bVisited == FALSE && pRec->m_bSystem == FALSE ){
656                                // mark this file as already done so we don't read it again
657                                // to find its headers
658                pRec->m_bVisited = TRUE;
659                pRec->ProcessFile();
660                // Start searching from the beginning again
661                                // because ProcessFile may have added new files
662                                // and changed the GetNextAssoc order
663                next = fileMap.GetStartPosition();       
664
665            }
666        }
667    }
668
669
670};
671
672CMapStringToPtr CFileRecord::fileMap;           // contains all allocated CFileRecords
673CStringArray CFileRecord::orderedFileNames;
674CMapStringToPtr CFileRecord::includeMap;        // pointers to CFileRecords in fileMap
675CMapStringToPtr CFileRecord::noDependMap;       // no data, just an index
676
677int main( int argc, char** argv ){
678    int i = 1;
679    char *pStr;
680    static int iRecursion = 0;  //      Track levels of recursion.
681        static CString outputFileName;
682   
683    //  Entering.
684    iRecursion++;
685
686    while( i < argc ){
687        if( argv[i][0] == '-' || argv[i][0] == '/' ){
688            switch( argv[i][1] ){
689
690            case 'i':
691            case 'I':
692                if( argv[i][2] != 0 ){
693                    pStr = &(argv[i][2]);
694                }
695                else {
696                    i++;
697                    pStr = argv[i];
698                }
699                if( pStr == 0 || *pStr == '-' || *pStr == '/' ){
700                    goto usage;
701                }
702                else {
703                    AddIncludeDirectory( pStr );
704                }
705                break;
706
707            case 'f':
708            case 'F':
709                if( argv[i][2] != 0 ){
710                    pStr = &(argv[i][2]);
711                }
712                else {
713                    i++;
714                    pStr = argv[i];
715                }
716                if( pStr == 0 || *pStr == '-' || *pStr == '/'){
717                    goto usage;
718                }
719                else {
720                    CStdioFile f;
721                    CString s;
722                    if( f.Open( pStr, CFile::modeRead ) ){
723                        while(f.ReadString(s)){
724                            s.TrimLeft();
725                            s.TrimRight();
726                            if( s.GetLength() ){
727                                CFileRecord::AddFile( s, NULL, FALSE, TRUE );
728                            }
729                        }
730                        f.Close();
731                    }
732                    else {
733                        fprintf(stderr,"makedep: file not found: %s", pStr );
734                        exit(-1);
735                    }
736                }
737                break;
738
739            case 'o':
740            case 'O':
741                if( argv[i][2] != 0 ){
742                    pStr = &(argv[i][2]);
743                }
744                else {
745                    i++;
746                    pStr = argv[i];
747                }
748                if( pStr == 0 || *pStr == '-' || *pStr == '/'){
749                    goto usage;
750                }
751                else {
752                    CStdioFile f;
753                    CString s;
754                                        outputFileName = pStr;
755                                        if(!(pAltFile = fopen(pStr, "w+")))     {
756                        fprintf(stderr, "makedep: file not found: %s", pStr );
757                        exit(-1);
758                    }
759                }
760                break;
761
762            case '1':
763                if( argv[i][2] == '6')  {
764                    b16 = TRUE;
765                }
766                break;
767
768            case 's':
769            case 'S':
770                bSimple = TRUE;
771                break;
772
773
774
775            case 'h':
776            case 'H':
777            case '?':
778            usage:
779                fprintf(stderr, "usage: makedep -I <dirname> -F <filelist> <filename>\n"
780                       "  -I <dirname>    Directory name, can be repeated\n"
781                       "  -F <filelist>   List of files to scan, one per line\n"
782                       "  -O <outputFile> File to write output, default stdout\n");
783                exit(-1);
784            }
785        }
786        else if( argv[i][0] == '@' ){
787                //      file contains our commands.
788                CStdioFile f;
789            CString s;
790            int iNewArgc = 0;
791            char **apNewArgv = new char*[5000];
792                        memset(apNewArgv, 0, sizeof(apNewArgv));
793
794                        //      First one is always the name of the exe.
795                        apNewArgv[0] = argv[0];
796                        iNewArgc++;
797
798                        const char *pTraverse;
799                        const char *pBeginArg;
800                if( f.Open( &argv[i][1], CFile::modeRead ) ){
801                while( iNewArgc < 5000 && f.ReadString(s) )     {
802                                        //      Scan the string for args, and do the right thing.
803                                        pTraverse = (const char *)s;
804                                        while(iNewArgc < 5000 && *pTraverse)    {
805                                                if(isspace(*pTraverse)) {
806                                                                pTraverse++;
807                                                                continue;
808                                                }
809
810                                                //      Extract to next space.
811                                                pBeginArg = pTraverse;
812                                                do      {
813                                                        pTraverse++;
814                                                }
815                                                while(*pTraverse && !isspace(*pTraverse));
816                                                apNewArgv[iNewArgc] = new char[pTraverse - pBeginArg + 1];
817                                                memset(apNewArgv[iNewArgc], 0, pTraverse - pBeginArg + 1);
818                                                strncpy(apNewArgv[iNewArgc], pBeginArg, pTraverse - pBeginArg);
819                                                iNewArgc++;
820                                        }
821                    }
822                f.Close();
823                }
824               
825                //      Recurse if needed.
826                if(iNewArgc > 1)        {
827                        main(iNewArgc, apNewArgv);
828                }
829               
830                //      Free off the argvs (but not the very first one which we didn't allocate).
831                while(iNewArgc > 1)     {
832                        iNewArgc--;
833                        delete [] apNewArgv[iNewArgc];
834                }
835                delete [] apNewArgv;
836        }
837        else {
838            CFileRecord::AddFile( argv[i], NULL, FALSE, TRUE );
839        }
840        i++;
841    }
842   
843    //  Only of the very bottom level of recursion do we do this.
844    if(iRecursion == 1) {
845
846                // only write the results out if no errors encountered
847                if (mainReturn == 0) {
848                        CFileRecord::ProcessFiles();
849            if( !bSimple ){
850                        CFileRecord::PrintTargets("OBJ_FILES", "\\");
851                if(b16) {
852                            CFileRecord::PrintTargets("LINK_OBJS", "+\\");
853                }
854                else    {
855                            CFileRecord::PrintTargets("LINK_OBJS", "^");
856                }
857                CFileRecord::PrintSources();
858                CFileRecord::PrintBuildRules();
859            }
860                CFileRecord::PrintDependancies();
861                }
862           
863                if(pAltFile != stdout)  {
864                        fclose(pAltFile);
865                        if (mainReturn != 0) {
866                                remove(outputFileName); // kill output file if returning an error
867                        }
868                }
869        }
870        iRecursion--;
871
872    if (iRecursion == 0 )
873    {
874        // last time through -- clean up allocated CFileRecords!
875        CFileRecord *pFRec;
876        CString     name;
877        POSITION    next;
878
879        next = CFileRecord::fileMap.GetStartPosition();
880        while( next ){
881            CFileRecord::fileMap.GetNextAssoc( next, name, *(void**)&pFRec );
882            delete pFRec;
883        }
884    }
885
886    return mainReturn;
887}
Note: See TracBrowser for help on using the repository browser.