~ubuntu-branches/ubuntu/quantal/enigmail/quantal-security

« back to all changes in this revision

Viewing changes to config/makedep.cpp

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2013-09-13 16:02:15 UTC
  • mfrom: (0.12.16)
  • Revision ID: package-import@ubuntu.com-20130913160215-u3g8nmwa0pdwagwc
Tags: 2:1.5.2-0ubuntu0.12.10.1
* New upstream release v1.5.2 for Thunderbird 24

* Build enigmail using a stripped down Thunderbird 17 build system, as it's
  now quite difficult to build the way we were doing previously, with the
  latest Firefox build system
* Add debian/patches/no_libxpcom.patch - Don't link against libxpcom, as it
  doesn't exist anymore (but exists in the build system)
* Add debian/patches/use_sdk.patch - Use the SDK version of xpt.py and
  friends
* Drop debian/patches/ipc-pipe_rename.diff (not needed anymore)
* Drop debian/patches/makefile_depth.diff (not needed anymore)

Show diffs side-by-side

added added

removed removed

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