main.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 647 行 · 第 1/2 页

C
647
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  wmake input analysis
*
****************************************************************************/


#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#if defined(__OS2__) || defined(__DOS__)
   #include <stdio.h>
#endif
#ifdef __WATCOMC__
    #include <process.h>
#endif

#include "massert.h"
#include "mtypes.h"
#include "mtarget.h"
#include "msysdep.h"
#include "macros.h"
#include "make.h"
#include "mcache.h"
#include "mmemory.h"
#include "mexec.h"
#include "mmisc.h"
#include "mparse.h"
#include "mrcmsg.h"
#include "msg.h"
#include "msuffix.h"
#include "mupdate.h"
#include "mvecstr.h"
#include "mautodep.h"


STATIC TLIST    *mustTargs;         /* targets we must update           */
STATIC TLIST    *firstTargFound;    /* first targets we ever found      */
STATIC NODE     *filesToDo;         /* pointers into argv to -f files   */

#ifdef __WATCOMC__
#pragma on (check_stack);
#endif
STATIC void doBuiltIns( const char *makeopts )
/*********************************************
 * perform the builtin commands
 */
{
    TLIST   *list;
    char    buf[2048];
    char    *cpy;

    if( !Glob.overide ) {
        DoingBuiltIn = TRUE;
        FmtStr( buf, "%F", BuiltIns );
        cpy = MallocSafe( 2048 + strlen( makeopts ) );
        FmtStr( cpy, buf, makeopts );
        InsString( cpy, FALSE );
        list = Parse();
        FreeTList( list );
        strcpy(cpy, "MAKE=" );
        if( _cmdname( cpy + sizeof "MAKE=" - 1 ) == NULL ) {
            strcat( cpy, "wmake" );
        }
        InsString( cpy, FALSE );
        list = Parse();
        FreeTList( list );
        if( Glob.microsoft | Glob.unix ) {
            // suffixes must be parsed before builtins
            const char  *suffices = MSSuffixList;
            const char  *builtins = MSBuiltIn;

            FmtStr( cpy, "%%MAKEFLAGS=$(%%MAKEFLAGS) %F", makeopts );
            InsString( cpy, FALSE );
            list = Parse();
            FreeTList( list );
            if( Glob.posix ) {
                suffices = POSIXSuffixList;
                builtins = POSIXBuiltIn;
            } else if( Glob.unix ) {
                suffices = UNIXSuffixList;
                builtins = UNIXBuiltIn;
            }
            FmtStr( cpy, "%F", suffices );
            InsString( cpy, FALSE );
            list = Parse();
            FreeTList( list );
            FmtStr( buf, "%F", builtins );
        } else {
            FmtStr( buf, "%F", SuffixList );
        }
        FmtStr( cpy, buf, makeopts );
        InsString( cpy, FALSE );
        list = Parse();
        FreeTList( list );
        FreeSafe( cpy );
        DoingBuiltIn = FALSE;
    }
}
#ifdef __WATCOMC__
#pragma off(check_stack);
#endif

static void setFirstTarget( TLIST *potential_first )
/**************************************************/
{
    if( firstTargFound != NULL || potential_first == NULL ) {
        if( potential_first ) {
            FreeTList( potential_first );
        }
        return;
    }
    /*  Note all first targets must not have attribute explicit */
    firstTargFound = potential_first;
}

void Header( void )
/*****************/
{
    if( Glob.noheader ) {
        return;
    }
    if( !Glob.headerout ) {
        Glob.headerout = TRUE;  /* so we don't print more than once */
        PrtMsg( INF | BANNER );
    }
}


STATIC void handleMacroDefn( const char *buf )
/*********************************************
 * Can't use Parse() at this point because we need readonly macros, so we
 * simply use LexToken().
 * This statement is not true for microsoft option.  In microsoft, all the
 * macros even the one on the command line can be overwritten
 */
{
    char        *p;
    char        *q;

    assert( buf != NULL );

    q = StrDupSafe( buf );    /* we need our own copy */

    p = strpbrk( q, "#=" );
    assert( p != NULL );
    *p = '=';                   /* lex doesn't recognize '#' */

    InsString( q, FALSE );     /* put arg into stream */
    while( LexToken( LEX_PARSER ) != STRM_END ) {
        /* NOP - eat all the characters */
    }

    if( Glob.microsoft ) {
        /* Insert twice because in nmake declaring a macro in the command line */
        /* is equivalent to declaring one as is and one that is all upper case */
        /* Approximately so. we cater for foo meaning FOO but not FoO W.Briscoe 20031114 */
        /* This is no problem! In make, foo=bar only sets foo and FOO W.Briscoe 20041014 */
        while( --p >= q ) {
            *p = toupper( *p );
        }

        InsString( q, FALSE );     /* put arg into stream */
        while( LexToken( LEX_PARSER ) != STRM_END ) {
            /* NOP - eat the characters. Needs own eater. W.Briscoe 20041014 */
        }
    }
    FreeSafe( q );
}


STATIC void handleTarg( const char *buf )
/***************************************/
{
    assert( buf != NULL );

    /* if it is not a valid target name, Update() won't be able to make it */
    WildTList( &mustTargs, buf, FALSE, TRUE );
}


STATIC void checkCtrl( const char *p )
/************************************/
{
    // p != NULL is checked by caller
    while( *p ) {          // scan for control characters
        if( !isprint( *p ) ) {
            PrtMsg( FTL | CTRL_CHAR_IN_CMD, *p );
        }
        ++p;
    }
}


STATIC char *procFlags( char const * const *argv, const char **log_name )
/************************************************************************
 * process the flags, macro=defn, and targets from the command line
 * writes targets to mustTargs, files to fileToDo, and defines macros
 * it is important to have the ms switch first to have correct functionality
 * of some features in microsoft compatability
 */
{
    char        select = '\0';  /* - or swchar (*argv)[0]       */
    char        option = '\0';  /* the option (*argv)[1]        */
    const char  *p;             /* working pointer to *argv     */
    NODE        *new;           /* for adding a new file        */
    int         options[256 + 1] = { 0 };

    if( (p = argv[1]) != NULL ) {
        if( strcmp( p, "?" ) == 0
        || ((p[0] == '-' || p[0] == Glob.swchar) && strcmp( p + 1, "?" ) == 0) ) {
            Usage();
        }
    }

    Glob.macreadonly = TRUE;

    while( *++argv != NULL ) {
        checkCtrl( p = *argv );
        select = p[0], option = (char) tolower( p[1] );
        if( select == '-' || select == Glob.swchar ) {
            if( option != NULLCHAR && p[2] == NULLCHAR ) {
                switch( option ) {
                case '?':   Usage();                break;
                case 'a':   Glob.all       = TRUE;  break;
                case 'b':   Glob.block     = TRUE;  break;
                case 'c':   Glob.nocheck   = TRUE;  break;
                case 'd':   Glob.debug     = TRUE;  break;
                case 'e':   Glob.erase     = TRUE;  break;
                case 'h':   Glob.noheader  = TRUE;  break;
                case 'i':   Glob.ignore    = TRUE;  break;
                case 'j':   Glob.rcs_make  = TRUE;  break;
                case 'k':   Glob.cont      = TRUE;  break;
                case 'm':   Glob.nomakeinit= TRUE;  break;
                case 'n':   Glob.noexec    = TRUE;  break;
                case 'o':   Glob.optimize  = TRUE;  break;
                case 'p':   Glob.print     = TRUE;  break;
                case 'q':   Glob.query     = TRUE;  break;
                case 'r':   Glob.overide   = TRUE;  break;
                case 's':   Glob.silent    = TRUE;  break;
                case 't':   Glob.touch     = TRUE;  break;
                case 'u':   Glob.unix      = TRUE;  break;
                case 'v':   Glob.verbose   = TRUE;  break;
                case 'w':   Glob.auto_depends = TRUE;break;
#ifdef CACHE_STATS
                case 'x':   Glob.cachestat = TRUE;  break;
#endif
                case 'y':   Glob.show_offenders = TRUE; break;
                case 'z':   Glob.hold      = TRUE;  break;
                    /* these options require a filename */
                case 'f':
                case 'l':
                    if( ( p = *++argv ) == NULL ) {
                        PrtMsg( ERR | INVALID_FILE_OPTION, select, option );
                        Usage();
                    }
                    checkCtrl( p );
                    if( option == 'f' ) {
                        if( (p[0] == '-') && (p[1] == NULLCHAR) ) {
                            // stdin
                        } else if( (p[0] == '-') || (p[0] == Glob.swchar) ) {
                            PrtMsg( ERR | INVALID_FILE_OPTION, select, option );
                            Usage();
                        }
                        new = MallocSafe( sizeof( *new ) );
                        new->name = (char *)p;
                        new->next = filesToDo;
                        filesToDo = new;
                    } else
                        *log_name = p;
                    break;
                default:
                    PrtMsg( ERR | INVALID_OPTION, select, option );
                    Usage();
                    break;
                }
                options[(option | 0x20) + 1] = TRUE;
                continue;
            }
            if( p[3] == NULLCHAR ) {
                if( option == 'm'  && tolower( p[2] ) == 's' ) {
                    Glob.microsoft = TRUE;
                    Glob.nocheck   = TRUE;
                    options[(option | 0x20) + 1] = TRUE;
                    continue;
                }
                if( option == 's'  && tolower( p[2] ) == 'n' ) {
                    Glob.silentno  = TRUE;
                    options[(option | 0x20) + 1] = TRUE;
                    continue;
                }
                if( option == 'u'  && tolower( p[2] ) == 'x' ) {
                    Glob.unix       = TRUE;
                    Glob.posix      = TRUE;
                    Glob.nomakeinit = TRUE;
                    Glob.nocheck    = TRUE;
                    options[(option | 0x20) + 1] = TRUE;
                    continue;
                }
            }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?