Logo Search packages:      
Sourcecode: xulrunner-1.9 version File versions

makedep.cpp

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is mozilla.org code.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

// Dependency building hack
//

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <ctype.h>
#include <afxcoll.h>
#include <afxtempl.h>

int mainReturn = 0;
BOOL b16 = FALSE;
BOOL bSimple = FALSE;

//    freopen won't work on stdout in win16
FILE *pAltFile = stdout;

CStringArray includeDirectories;

// turn a file, relative path or other into an absolute path
// This function copied from MFC 1.52
BOOL PASCAL _AfxFullPath(LPSTR lpszPathOut, LPCSTR lpszFileIn)
        // lpszPathOut = buffer of _MAX_PATH
        // lpszFileIn = file, relative path or absolute path
        // (both in ANSI character set)
{
        OFSTRUCT of;
        if (OpenFile(lpszFileIn, &of, OF_PARSE) != HFILE_ERROR)
        {
                // of.szPathName is in the OEM character set
                OemToAnsi(of.szPathName, lpszPathOut);
                AnsiUpper(lpszPathOut); // paths in upper case just to be sure
                return TRUE;
        }
        else
        {
                TRACE1("Warning: could not parse the path %Fs\n", lpszFileIn);
                lstrcpy(lpszPathOut, lpszFileIn);  // take it literally
                AnsiUpper(lpszPathOut); // paths in upper case just to be sure
                return FALSE;
        }
}

void AddIncludeDirectory( char *pString ){
    CString s = pString;
      int len = s.GetLength();
    if(len > 0 && s[len - 1] != '\\' ){
        s += "\\";
    }
    includeDirectories.Add(s);
}

BOOL FileExists( const char *pString ){
    struct _stat buf;
    int result;

    result = _stat( pString, &buf );
    return (result == 0);
}

void FixPathName(CString& str) {
      str.MakeUpper();        // all upper case

      // now switch all forward slashes to back slashes
      int index;
      while ((index = str.Find('/')) != -1) {
            str.SetAt(index, '\\');
      }
}

void FATName(CString& csLONGName)
{
    //  Only relevant for 16 bits.
    if(b16) {
        //  Convert filename to FAT (8.3) equivalent.
        char aBuffer[2048];

        if(GetShortPathName(csLONGName, aBuffer, 2048)) {
            csLONGName = aBuffer;
        }
    }
}


class CFileRecord {
public:
    CString m_shortName;
    CString m_pathName;
    CPtrArray m_includes;  // pointers to CFileRecords in fileMap
    BOOL m_bVisited;
    BOOL m_bSystem;
    BOOL m_bSource;
    static CMapStringToPtr fileMap;      // contains all allocated CFileRecords
    static CStringArray orderedFileNames;
    static CMapStringToPtr includeMap;   // pointer to CFileRecords in fileMap
    static CMapStringToPtr noDependMap;

    CFileRecord( const char *shortName, const char* pFullName, BOOL bSystem, BOOL bSource):
                m_shortName( shortName ),
                m_pathName(),
                m_includes(),
                m_bVisited(FALSE),
                m_bSource( bSource ),
                m_bSystem(bSystem){

            m_pathName = pFullName;
            FixPathName(m_pathName);                        // all upper case for consistency
            ASSERT(FindFileRecord(m_pathName) == NULL);     // make sure it's not already in the map
        fileMap[m_pathName] = this;             // add this to the filemap, using the appropriate name as the key
            if (bSource) {
                  orderedFileNames.Add(m_pathName);   // remember the order we saw source files in
            }
    }

    // 
    // open the file and grab all the includes.
    //
    void ProcessFile(){
        FILE *f;
            CString fullName;
        BOOL bSystem;
            DWORD lineCntr = 0;
            char *a = new char[2048];
        memset(a, 0, 2048);
            char srcPath[_MAX_PATH];

            // construct the full path
            if (!_AfxFullPath(srcPath, m_pathName)) {
                  strcpy(srcPath, m_pathName);
            }

            // strip off the source filename to end up with just the path
            LPSTR pTemp = strrchr(srcPath, '\\');
            if (pTemp) {
                  *(pTemp + 1) = 0;
            }

        f = fopen(m_pathName, "r");
        if(f != NULL && f != (FILE *)-1)  {
                  setvbuf(f, NULL, _IOFBF, 32768);          // use a large file buffer
            while(fgets(a, 2047, f)) {
                        // if the string "//{{NO_DEPENDENCIES}}" is at the start of one of the 
                        // first 10 lines of a file, don't build dependencies on it or any
                        // of the files it includes
                        if (lineCntr < 10) {
                              static char* pDependStr = "//{{NO_DEPENDENCIES}}";
                              if (strncmp(a, pDependStr, strlen(pDependStr)) == 0) {
                                    noDependMap[m_pathName] = 0;  // add it to the noDependMap
                                    break;                                          // no need for further processing of this file
                              }
                        }
                        ++lineCntr;
                        // have to handle a variety of legal syntaxes that we find in our source files:
                        //    #include
                        // #   include
                // #include
                        // if the first non-whitespace char is a '#', consider this line
                        pTemp = a;
                        pTemp += strspn(pTemp, " \t");                  // skip whitespace
                        if (*pTemp == '#') {
                              ++pTemp;                                        // skip the '#'
                              pTemp += strspn(pTemp, " \t");            // skip more whitespace
                              if( !strncmp(pTemp, "include", 7) ){
                                    pTemp += 7;                               // skip the "include"
                                    pTemp += strspn(pTemp, " \t");      // skip more whitespace
                                    bSystem = (*pTemp == '<');          // mark if it's a system include or not
                        // forget system files -- we just have to search all the paths
                        // every time and never find them! This change alone speeds a full
                        // depend run on my system from 5 minutes to 3:15
                                    // if (bSystem || (*pTemp == '"')) {
                        if (*pTemp == '"') {
                                          LPSTR pStart = pTemp + 1;     // mark the start of the string
                                          pTemp = pStart + strcspn(pStart, ">\" "); // find the end of the string
                                          *pTemp = 0;                         // terminate the string

                                          // construct the full pathname from the path part of the 
                                          // source file and the name listed here
                                          fullName = srcPath;
                                          fullName += pStart;
                                          CFileRecord *pAddMe = AddFile( pStart, fullName, bSystem );
                                          if (pAddMe) {
                                                m_includes.Add(pAddMe);
                                          }
                                    }
                              }
                        }
            }
            fclose(f);
        }
        delete [] a;
    }

    void PrintIncludes(){
        int i = 0;
        while( i < m_includes.GetSize() ){
            CFileRecord *pRec = (CFileRecord*) m_includes[i];

            //  Don't write out files that don't exist or are not in the namespace
            //      of the programs using it (netscape_AppletMozillaContext.h doesn't
            //      mix well with 16 bits).
                  // Also don't write out files that are in the noDependMap
                  void* lookupJunk;
            if( !pRec->m_bVisited && pRec->m_pathName.GetLength() != 0 && !noDependMap.Lookup(pRec->m_pathName, lookupJunk)) {

                        // not supposed to have a file in the list that doesn't exist
                        ASSERT(FileExists(pRec->m_pathName));

                CString csOutput;
                csOutput = pRec->m_pathName;
                FATName(csOutput);

                        fprintf(pAltFile, "\\\n    %s ", (const char *) csOutput );

                        // mark this one as done so we don't do it more than once
                pRec->m_bVisited = TRUE;

                pRec->PrintIncludes();
            }
            i++;
        }
    }

    void PrintDepend(){
        CFileRecord *pRec;
        BOOL bFound;
        POSITION next;
        CString name;

            // clear all the m_bVisisted flags so we can use it to keep track
            // of whether we've already output this file as a dependency
        next = fileMap.GetStartPosition();
        while( next ){
            fileMap.GetNextAssoc( next, name, *(void**)&pRec );
            pRec->m_bVisited = FALSE;
        }

        char fname[_MAX_FNAME];

            if (pRec->m_pathName.GetLength() != 0) {
            if( bSimple ){
                  fprintf(pAltFile, "\n\n\n%s:\t", m_pathName );
            }
            else {
                CString csOutput;
                csOutput = m_pathName;
                FATName(csOutput);

                  _splitpath( csOutput, NULL, NULL, fname, NULL );

                  fprintf(pAltFile, "\n\n\n$(OUTDIR)\\%s.obj: %s ", fname, (const char*) csOutput );
            }
              m_bVisited = TRUE;          // mark it as done so we won't do it again
              PrintIncludes();
            }
    }


    static CString NormalizeFileName( const char* pName ){
        return CString(pName);
    }

    static CFileRecord* FindFileRecord( const char *pName ){
            CFileRecord* pRec = NULL;
            CString name(pName);
            FixPathName(name);
            fileMap.Lookup(name, (void*&)pRec);
            return(pRec);
    }
public:
    static CFileRecord* AddFile( const char* pShortName, const char* pFullName, BOOL bSystem = FALSE, 
                BOOL bSource = FALSE ){

            char fullName[_MAX_PATH];
            BOOL bFound = FALSE;
            CString foundName;
            CString fixedShortName;
        CString s;

        // normalize the name
        fixedShortName = pShortName;
        FixPathName(fixedShortName);
        pShortName = fixedShortName;

        // if it is source, we might be getting an obj file.  If we do,
        //  convert it to a c or c++ file.
        if( bSource && (strcmp(GetExt(pShortName),".obj") == 0) ){
            char path_buffer[_MAX_PATH];
            char fname[_MAX_FNAME] = "";
            CString s;

            _splitpath( pShortName, NULL, NULL, fname, NULL );
            if( FileExists( s = CString(fname) + ".cpp") ){
                pShortName = s;
                pFullName = s;
            }
            else if( FileExists( s = CString(fname) + ".c" ) ){
                pShortName = s;
                pFullName = s;
            }
            else {
                return 0;
            }
        }

            // if pFullName was not constructed, construct it here based on the current directory
            if (!pFullName) {
                  _AfxFullPath(fullName, pShortName);
                  pFullName = fullName;
            }
            
            // first check to see if we already have this exact file
            CFileRecord *pRec = FindFileRecord(pFullName);

        // if not found and not a source file check the header list --
        // all files we've found in include directories are in the includeMap.
        // we can save gobs of time by getting it from there
        if (!pRec && !bSource)
            includeMap.Lookup(fixedShortName, (void*&)pRec);

        if (!pRec) {
            // not in one of our lists, start scrounging on disk

            // check the fullname first
            if (FileExists(pFullName)) {
                foundName = pFullName;
                bFound = TRUE;
            }
            else {
                // if still not found, search the include paths
                int i = 0;
                while( i < includeDirectories.GetSize() ){
                    if( FileExists( includeDirectories[i] + pShortName ) ){
                        foundName = includeDirectories[i] + pShortName;
                        bFound = TRUE;
                        break;
                    }
                    i++;
                }
            }
        }
        else {
            // we found it
            bFound = TRUE;
        }

            // source files are not allowed to be missing
            if (bSource && !pRec && !bFound) {
                  fprintf(stderr, "Source file: %s doesn't exist\n", pFullName);
                  mainReturn = -1;        // exit with an error, don't write out the results
            }

#ifdef _DEBUG
            if (!pRec && !bFound && !bSystem) {
                  fprintf(stderr, "Header not found: %s (%s)\n", pShortName, pFullName);
            }
#endif

            // if none of the above logic found it already in the list, 
        // must be a new file, add it to the list
        if (bFound && (pRec == NULL)) {
            pRec = new CFileRecord( pShortName, foundName, bSystem, bSource);

                  // if this one isn't a source file add it to the includeMap
                  // for performance reasons (so we can find it there next time rather
                  // than having to search the file system again)
                  if (!bSource) {
                        includeMap[pShortName] = pRec;
                  }
        }
        return pRec;
    }


    static void PrintDependancies(){
        CFileRecord *pRec;
        BOOL bFound;
        POSITION next;
        CString name;

            // use orderedFileNames to preserve order
            for (int pos = 0; pos < orderedFileNames.GetSize(); pos++) {
                  pRec = FindFileRecord(orderedFileNames[pos]);
            if(pRec && pRec->m_bSource ){
                pRec->PrintDepend();
                  }
            }
    }


    void PrintDepend2(){
        CFileRecord *pRec;
        int i;

        if( m_includes.GetSize() != 0 ){
                  fprintf(pAltFile, "\n\n\n%s: \\\n",m_pathName );
            i = 0;
            while( i < m_includes.GetSize() ){
                pRec = (CFileRecord*) m_includes[i];
                  fprintf(pAltFile, "\t\t\t%s\t\\\n",pRec->m_pathName );
                i++;
            }
        }
    }

    static void PrintDependancies2(){
        CFileRecord *pRec;
        BOOL bFound;
        POSITION next;
        CString name;

        next = fileMap.GetStartPosition();
        while( next ){
            fileMap.GetNextAssoc( next, name, *(void**)&pRec );
            pRec->PrintDepend2();
        }
    }


    static void PrintTargets(const char *pMacroName, const char *pDelimiter){
        CFileRecord *pRec;
        BOOL bFound;
        POSITION next;
        CString name;

        BOOL bNeedDelimiter = FALSE;
            fprintf(pAltFile, "%s = ", pMacroName);        

            // use orderedFileNames to preserve target order
            for (int pos = 0; pos < orderedFileNames.GetSize(); pos++) {
                  pRec = FindFileRecord(orderedFileNames[pos]);
                  ASSERT(pRec);

            if( pRec && pRec->m_bSource && pRec->m_pathName.GetLength() != 0){
                char fname[_MAX_FNAME];

                CString csOutput;
                csOutput = pRec->m_pathName;
                FATName(csOutput);

                _splitpath( csOutput, NULL, NULL, fname, NULL );

                if(bNeedDelimiter)  {
                    fprintf(pAltFile, "%s\n", pDelimiter);
                    bNeedDelimiter = FALSE;
                }

                        fprintf(pAltFile, "     $(OUTDIR)\\%s.obj   ", fname );
                bNeedDelimiter = TRUE;
            }
        }
            fprintf(pAltFile, "\n\n\n");        
    }

    static CString DirDefine( const char *pPath ){
        char path_buffer[_MAX_PATH];
        char dir[_MAX_DIR] = "";
        char dir2[_MAX_DIR] = "";
        char fname[_MAX_FNAME] = "";
        char ext[_MAX_EXT] = "";
        CString s;

        _splitpath( pPath, 0, dir, 0, ext );

        BOOL bDone = FALSE;

        while( dir && !bDone){
            // remove the trailing slash
            dir[ strlen(dir)-1] = 0;
            _splitpath( dir, 0, dir2, fname, 0 );
            if( strcmp( fname, "SRC" ) == 0 ){
                strcpy( dir, dir2 );
            }
            else {
                bDone = TRUE;
            }
        }
        s = CString(fname) + "_" + (ext+1);
        return s;
    }


    static void PrintSources(){
        int i;
        CString dirName, newDirName;

        for( i=0; i< orderedFileNames.GetSize(); i++ ){
            newDirName= DirDefine( orderedFileNames[i] );
            if( newDirName != dirName ){
                fprintf( pAltFile, "\n\n\nFILES_%s= $(FILES_%s) \\", 
                        (const char*)newDirName, (const char*)newDirName );
                dirName = newDirName;
            }
            fprintf( pAltFile, "\n\t%s^", (const char*)orderedFileNames[i] );
        }
    }

    static CString SourceDirName( const char *pPath, BOOL bFileName){
        char path_buffer[_MAX_PATH];
        char drive[_MAX_DRIVE] = "";
        char dir[_MAX_DIR] = "";
        char fname[_MAX_FNAME] = "";
        char ext[_MAX_EXT] = "";
        CString s;

        _splitpath( pPath, drive, dir, fname, ext );

        s = CString(drive) + dir;
        if( bFileName ){
            s += CString("FNAME") + ext;
        }
        else {
            // remove the trailing slash
            s = s.Left( s.GetLength() - 1 );
        }
        return s;
    }


    static CString GetExt( const char *pPath){
        char ext[_MAX_EXT] = "";

        _splitpath( pPath, 0,0,0, ext );

        CString s = CString(ext);
        s.MakeLower();
        return s;
    }

    static void PrintBuildRules(){
        int i;
        CString dirName;
        
        CMapStringToPtr dirList;

        for( i=0; i< orderedFileNames.GetSize(); i++ ){
            dirList[ SourceDirName(orderedFileNames[i], TRUE) ]= 0;
        }

        POSITION next;
        CString name;
        void *pVal;

        next = dirList.GetStartPosition();
        while( next ){
            dirList.GetNextAssoc( next, name, pVal);
            CString dirDefine = DirDefine( name );
            CString ext = GetExt( name );
            name = SourceDirName( name, FALSE );
            CString response = dirDefine.Left(8);

            fprintf( pAltFile, 
                "\n\n\n{%s}%s{$(OUTDIR)}.obj:\n"
                "\t@rem <<$(OUTDIR)\\%s.cl\n"
                "\t$(CFILEFLAGS)\n"
                "\t$(CFLAGS_%s)\n"
                "<<KEEP\n"
                "\t$(CPP) @$(OUTDIR)\\%s.cl %%s\n",
                (const char*)name,
                (const char*)ext,
                (const char*)response,
                (const char*)dirDefine,
                (const char*)response
            );

            fprintf( pAltFile, 
                "\n\n\nBATCH_%s:\n"
                "\t@rem <<$(OUTDIR)\\%s.cl\n"
                "\t$(CFILEFLAGS)\n"
                "\t$(CFLAGS_%s)\n"
                "\t$(FILES_%s)\n"
                "<<KEEP\n"
                "\t$(TIMESTART)\n"
                "\t$(CPP) @$(OUTDIR)\\%s.cl\n"
                "\t$(TIMESTOP)\n",
                (const char*)dirDefine,
                (const char*)response,
                (const char*)dirDefine,
                (const char*)dirDefine,
                (const char*)response
            );
        }

        //
        // Loop through one more time and build the final batch build
        //  rule
        //
        fprintf( pAltFile, 
            "\n\n\nBATCH_BUILD_OBJECTS:\t\t\\\n");

        next = dirList.GetStartPosition();
        while( next ){
            dirList.GetNextAssoc( next, name, pVal);
            CString dirDefine = DirDefine( name );

            fprintf( pAltFile, 
                "\tBATCH_%s\t\t\\\n", dirDefine );
        }

        fprintf( pAltFile, 
            "\n\n");
    }
        

    static void ProcessFiles(){
        CFileRecord *pRec;
        BOOL bFound;
        POSITION next;
        CString name;

            // search all the files for headers, adding each one to the list when found
            // rather than do it recursively, it simple marks each one it's done
            // and starts over, stopping only when all are marked as done

        next = fileMap.GetStartPosition();
        while( next ){
            fileMap.GetNextAssoc( next, name, *(void**)&pRec );
            if( pRec->m_bVisited == FALSE && pRec->m_bSystem == FALSE ){
                        // mark this file as already done so we don't read it again
                        // to find its headers
                pRec->m_bVisited = TRUE;
                pRec->ProcessFile();
                // Start searching from the beginning again
                        // because ProcessFile may have added new files 
                        // and changed the GetNextAssoc order
                next = fileMap.GetStartPosition();       

            }
        }
    }


};

CMapStringToPtr CFileRecord::fileMap;           // contains all allocated CFileRecords
CStringArray CFileRecord::orderedFileNames;
CMapStringToPtr CFileRecord::includeMap;        // pointers to CFileRecords in fileMap
CMapStringToPtr CFileRecord::noDependMap;       // no data, just an index

int main( int argc, char** argv ){
    int i = 1;
    char *pStr;
    static int iRecursion = 0;      //    Track levels of recursion.
      static CString outputFileName;
    
    //      Entering.
    iRecursion++;

    while( i < argc ){
        if( argv[i][0] == '-' || argv[i][0] == '/' ){
            switch( argv[i][1] ){

            case 'i':
            case 'I':
                if( argv[i][2] != 0 ){
                    pStr = &(argv[i][2]);
                }
                else {
                    i++;
                    pStr = argv[i];
                }
                if( pStr == 0 || *pStr == '-' || *pStr == '/' ){
                    goto usage;
                }
                else {
                    AddIncludeDirectory( pStr );
                }
                break;

            case 'f':
            case 'F':
                if( argv[i][2] != 0 ){
                    pStr = &(argv[i][2]);
                }
                else {
                    i++;
                    pStr = argv[i];
                }
                if( pStr == 0 || *pStr == '-' || *pStr == '/'){
                    goto usage;
                }
                else {
                    CStdioFile f;
                    CString s;
                    if( f.Open( pStr, CFile::modeRead ) ){
                        while(f.ReadString(s)){
                            s.TrimLeft();
                            s.TrimRight();
                            if( s.GetLength() ){
                                CFileRecord::AddFile( s, NULL, FALSE, TRUE );
                            }
                        } 
                        f.Close();
                    }
                    else {
                        fprintf(stderr,"makedep: file not found: %s", pStr );
                        exit(-1);
                    }
                }
                break;

            case 'o':
            case 'O':
                if( argv[i][2] != 0 ){
                    pStr = &(argv[i][2]);
                }
                else {
                    i++;
                    pStr = argv[i];
                }
                if( pStr == 0 || *pStr == '-' || *pStr == '/'){
                    goto usage;
                }
                else {
                    CStdioFile f;
                    CString s;
                              outputFileName = pStr;
                              if(!(pAltFile = fopen(pStr, "w+"))) {
                        fprintf(stderr, "makedep: file not found: %s", pStr );
                        exit(-1);
                    }
                }
                break;

            case '1':
                if( argv[i][2] == '6')  {
                    b16 = TRUE;
                }
                break;

            case 's':
            case 'S':
                bSimple = TRUE;
                break;



            case 'h':
            case 'H':
            case '?':
            usage:
                fprintf(stderr, "usage: makedep -I <dirname> -F <filelist> <filename>\n"
                       "  -I <dirname>    Directory name, can be repeated\n"
                       "  -F <filelist>   List of files to scan, one per line\n"
                       "  -O <outputFile> File to write output, default stdout\n");
                exit(-1);
            }
        }
        else if( argv[i][0] == '@' ){
            //    file contains our commands.
              CStdioFile f;
          CString s;
          int iNewArgc = 0;
          char **apNewArgv = new char*[5000];
                  memset(apNewArgv, 0, sizeof(apNewArgv));

                  //    First one is always the name of the exe.
                  apNewArgv[0] = argv[0];
                  iNewArgc++;

                  const char *pTraverse;
                  const char *pBeginArg;
              if( f.Open( &argv[i][1], CFile::modeRead ) ){
              while( iNewArgc < 5000 && f.ReadString(s) )   {
                              //    Scan the string for args, and do the right thing.
                              pTraverse = (const char *)s;
                              while(iNewArgc < 5000 && *pTraverse)      {
                                    if(isspace(*pTraverse)) {
                                                pTraverse++;
                                                continue;
                                    }

                                    //    Extract to next space.
                                    pBeginArg = pTraverse;
                                    do    {
                                          pTraverse++;
                                    }
                                    while(*pTraverse && !isspace(*pTraverse));
                                    apNewArgv[iNewArgc] = new char[pTraverse - pBeginArg + 1];
                                    memset(apNewArgv[iNewArgc], 0, pTraverse - pBeginArg + 1);
                                    strncpy(apNewArgv[iNewArgc], pBeginArg, pTraverse - pBeginArg);
                                    iNewArgc++;
                              }
                  } 
              f.Close();
            }
            
            //    Recurse if needed.
            if(iNewArgc > 1)  {
                  main(iNewArgc, apNewArgv);
            }
            
            //    Free off the argvs (but not the very first one which we didn't allocate).
            while(iNewArgc > 1)     {
                  iNewArgc--;
                  delete [] apNewArgv[iNewArgc];
            }
            delete [] apNewArgv;
        }
        else {
            CFileRecord::AddFile( argv[i], NULL, FALSE, TRUE );
        }
        i++;
    }
    
    //      Only of the very bottom level of recursion do we do this.
    if(iRecursion == 1) {

            // only write the results out if no errors encountered
            if (mainReturn == 0) {
                  CFileRecord::ProcessFiles();
            if( !bSimple ){
                  CFileRecord::PrintTargets("OBJ_FILES", "\\");
                if(b16) {
                      CFileRecord::PrintTargets("LINK_OBJS", "+\\");
                }
                else    {
                      CFileRecord::PrintTargets("LINK_OBJS", "^");
                }
                CFileRecord::PrintSources();
                CFileRecord::PrintBuildRules();
            }
            CFileRecord::PrintDependancies();
            }
          
            if(pAltFile != stdout)  {
                  fclose(pAltFile);
                  if (mainReturn != 0) {
                        remove(outputFileName); // kill output file if returning an error
                  }
            }
      }
      iRecursion--;

    if (iRecursion == 0 )
    {
        // last time through -- clean up allocated CFileRecords!
        CFileRecord *pFRec;
        CString     name;
        POSITION    next;

        next = CFileRecord::fileMap.GetStartPosition();
        while( next ){
            CFileRecord::fileMap.GetNextAssoc( next, name, *(void**)&pFRec );
            delete pFRec;
        }
    }

    return mainReturn;
}

Generated by  Doxygen 1.6.0   Back to index