cmdline.c

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

C
859
字号

    char        buffer[ _MAX_PATH2 ];
    char        *drive;
    char        *dir;
    char        *fname;
    char        *ext;
    char        path[ _MAX_PATH ];
    int         fh;

    _splitpath2( file_name, buffer, &drive, &dir, &fname, &ext );
    _makepath( path, drive, dir, fname, ( ext[0] == 0 ) ? WMP_EXTENSION : ext );
    fh = open( path, O_RDONLY | O_TEXT );
    if( fh == -1 ) {
        Fatal( MSG_UNABLE_TO_OPEN_FILE, path );
    }
    return( fh );
}

STATIC char *readIncludeFile( int fh ) {

#define READ_SIZE   512
    size_t  file_len;
    size_t  len_read;
    char    buf[ READ_SIZE + 1 ];   /* extra byte for a sentinal */
    char    *file;
    char    *fptr;
    size_t  i;

/**/myassert( fh != -1 );
/*
    We will count the non-space characters in the file.  White space will be
    collapsed into a single space (or two spaces if it crosses a READ_SIZE
    byte boundary) to save memory.

    Be careful!  The two loops which read the file must behave identically!
    Otherwise the second loop which writes to memory might overwrite the
    buffer allocation.
*/
    file_len = 0;
/**/myassert( !isspace( 0 ) );  /* will be using 0 as a sentinal */
    for(;;) {
        len_read = read( fh, buf, READ_SIZE );
        if( len_read == 0 ) break;
        buf[ len_read ] = 0; /* a sentinal so we can speed this up a bit */
        i = 0;
        do {
            ++file_len;
            if( file_len == 0 ) {
                close( fh );
                Fatal( MSG_INCLUDE_TOO_LARGE );
            }
            if( isspace( buf[ i ] ) ) {
                do {
                    ++i;
                } while( isspace( buf[ i ] ) ); /* use sentinal to stop */
            } else {
                ++i;
            }
        } while( i < len_read );
    }
    if( file_len > 0 ) {
        /* now read the file into an array of the appropriate size */
        if( lseek( fh, (long)0, SEEK_SET ) == -1 ) {
            Fatal( MSG_DISK_ERROR, "lseek" );
        }
        file = MemAlloc( file_len + 1 );
        fptr = file;
        for(;;) {
            len_read = read( fh, buf, READ_SIZE );
            if( len_read == 0 ) break;
            buf[ len_read ] = 0;        /* set sentinal */
            i = 0;
            do {
                *fptr++ = buf[ i ];
                if( isspace( buf[ i ] ) ) {
                    do {
                        ++i;
                    } while( isspace( buf[ i ] ) ); /* use sentinal */
                } else {
                    ++i;
                }
            } while( i < len_read );
        }
        *fptr = 0;
    } else {
        file = NULL;
    }
    close( fh );
    return( file );
#undef READ_SIZE
}

FORWARD STATIC void parseString( const char *str );

STATIC const char *doInclude( const char *str ) {

    int     fh;
    char    *file;
    char    *file_name;
    const char *env_var;

/**/myassert( str != NULL );
    if( isBreakChar( *str ) ) unrecognized( '@' );
    file_name = getFile( &str );
    env_var = getenv( file_name );
    if( env_var != NULL ) {
        MemFree( file_name );
        parseString( env_var );
    } else {
        /* both these functions use a lot of stack, so we separate them */
        fh = openIncludeFile( file_name );
        MemFree( file_name );
        file = readIncludeFile( fh );
        if( file != NULL ) {
            parseString( file );
            MemFree( file );
        }
    }
    return( str );
}
#pragma off( check_stack );

STATIC void parseString( const char *str ) {

/**/myassert( str != NULL );
    for(;;) {
        while( isspace( *str ) ) ++str;
        switch( *str ) {
        case 0:
            return;
        case SWCHAR:
        case '-':
            str += 2;
            switch( str[-1] ) {
            case 'o':   str = doOutput( str );      break;
            case 'd':   str = doDebug( str );       break;
            case 'p':   str = doParse( str );       break;
            case 'f':   str = doFile( str );        break;
            case 'q':   /* FALL THROUGH */
#if 0
            case 'l':
#endif
            case 'b':   str = doToggle( str );      break;
            default:    usage();
            }
            if( !isBreakChar( *str ) ) usage();
            break;
        case INCCHAR:
            str = doInclude( str + 1 );
            break;
        case CMTCHAR:
            str = doComment( str + 1 );
            break;
        default:
            str = addFile( str );
            break;
        }
    }

}

cmdline_t *CmdLineParse( void ) {
/*****************************/

    const char  *env_var;
    char        *cmd_line;
    size_t      cmd_len;
    act_grp_t   *cur;
    act_grp_t   *next;

    tempFileNum = 0;
    env_var = getenv( ENVVAR );
    if( env_var != NULL ) {
        parseString( env_var );
    }
    cmd_line = MemAlloc( 10240 );   /* FIXME - arbitrarily large constant! */
    getcmd( cmd_line );
    cmd_len = strlen( cmd_line );
    if( cmd_len > 0 ) {
        cmd_line = MemRealloc( cmd_line, cmd_len + 1 );
        parseString( cmd_line );
    }
    MemFree( cmd_line );

    /* reverse the stack of actions */
    cmdLine.action = NULL;  /* no actions by default */
    cur = curAct;
    while( cur != NULL ) {
        next = cur->next;
        if( cur->num_files == 0 ) { /* trim out the needless actions */
            MemFree( cur );
        } else {
            cur->next = cmdLine.action; /* stack it up */
            cmdLine.action = cur;
        }
        cur = next;
    }
    if( cmdLine.action == NULL ) {
        usage();
    }
    cmdLine.quiet = cmdLine.action->quiet;
    header();
    return( &cmdLine );
}

void ActionInit( cmdline_t *cmd ) {
/*******************************/
    act_grp_t   *cur;
    int         os2_specific;

/**/myassert( cmd != NULL && cmd->action != NULL );
    cur = cmd->action;
    cmdLine.quiet = cmdLine.action->quiet;
    os2_specific = 0;
    switch( cur->omf_generator ) {
    case OGEN_NULL:
        cmd->need_output = 0;
        break;
    case OGEN_MICROSOFT_OS2:
        os2_specific = 1;
        /* fall through */
    case OGEN_MICROSOFT:
        GenMSOmfInit();
        cmd->need_output = 1;
        break;
    case OGEN_PHARLAP:
        GenPharInit();
        cmd->need_output = 1;
        break;
    default:
/**/    never_reach();
    }
    switch( cur->dbg_generator ) {
    case DGEN_NULL:
        break;
    case DGEN_TXT:
        Can2TxtInit();
        break;
    case DGEN_MICROSOFT:
        Can2MsInit( 0, os2_specific );
        break;
    case DGEN_METAWARE:
        Can2MsInit( 1, os2_specific );
        break;
    case DGEN_TURBO:
        Can2TDInit();
        break;
    default:
/**/    never_reach();
    }
    if( cur->deflib ) {
        DefLibInit();
    }
    switch( cur->dbg_parser ) {
    case PARSE_NULL:                            break;
    case PARSE_WATCOM:      Wat2CanInit( 0 );   break;
    case PARSE_WATCOM_70:   Wat2CanInit( 1 );   break;
    default:
/**/    never_reach();
    }
}

void ActionFini( cmdline_t *cmd ) {
/*******************************/

    act_grp_t   *cur;
    act_grp_t   *next;
    size_t      file_num;
    size_t      num_files;

/**/myassert( cmd != NULL && cmd->action != NULL );
    cur = cmd->action;
    switch( cur->dbg_parser ) {
    case PARSE_NULL:                            break;
    case PARSE_WATCOM:      Wat2CanFini();      break;
    case PARSE_WATCOM_70:   Wat2CanFini();      break;
    default:
/**/    never_reach();
    }
    if( cur->deflib ) {
        DefLibFini();
    }
    switch( cur->dbg_generator ) {
    case DGEN_NULL:                             break;
    case DGEN_TXT:          Can2TxtFini();      break;
    case DGEN_MICROSOFT:    Can2MsFini();       break;
    case DGEN_METAWARE:     Can2MsFini();       break;
    case DGEN_TURBO:        Can2TDFini();       break;
    default:
/**/    never_reach();
    }
    switch( cur->omf_generator ) {
    case OGEN_NULL:                             break;
    case OGEN_MICROSOFT_OS2:GenMSOmfFini();     break;
    case OGEN_MICROSOFT:    GenMSOmfFini();     break;
    case OGEN_PHARLAP:      GenPharFini();      break;
    default:
/**/    never_reach();
    }
    if( cur->output != NULL ) {
        MemFree( cur->output );
    }
    num_files = cur->num_files;
    for( file_num = 0; file_num < num_files; ++file_num ) {
        MemFree( cur->files[ file_num ] );
    }
    next = cur->next;
    MemFree( cur );
    cmd->action = next;
}

void ActionInfile( cmdline_t *cmd, char *buf, uint file_num ) {
/***********************************************************/

    char        buffer[ _MAX_PATH2 ];
    char        *drive;
    char        *dir;
    char        *fname;
    char        *ext;

/**/myassert( cmd != NULL );
/**/myassert( cmd->action != NULL );
/**/myassert( file_num < cmd->action->num_files );
    _splitpath2( cmd->action->files[ file_num ], buffer,
        &drive, &dir, &fname, &ext );
    _makepath( buf, drive, dir, fname, ( ext[0]==0 ) ? OBJ_EXTENSION : ext );
}

void ActionOutfile( cmdline_t *cmd, char *buf, uint file_num ) {
/************************************************************/

    char        sp_buf[ _MAX_PATH2 ];
    char        *drive;
    char        *dir;
    char        fname[ _MAX_FNAME ];
    const char *output;

/**/myassert( cmd != NULL );
/**/myassert( cmd->need_output );
/**/myassert( cmd->action != NULL );
/**/myassert( file_num < cmd->action->num_files );
    output = cmd->action->output;
    _splitpath2( ( output == NULL || output[0] == 0 ) ?
                cmd->action->files[ file_num ] : output,
                sp_buf, &drive, &dir, NULL, NULL );
    fname[0] = '_';
    fname[1] = 'W';
    for(;;) {
        StrDec( &fname[2], tempFileNum++ );
        _makepath( buf, drive, dir, fname, "TMP" );
        if( access( buf, 0 ) == -1 ) {
            break;
        }
    }
}

/*
    FIXME: this is an ugly function!
*/
void ActionRename( cmdline_t *cmd, const char *in, const char *out,
    uint file_num, int make_lib, size_t page_size ) {
/***************************************************/
    char        sp_buf[ _MAX_PATH2 ];
    char        sp_buf2[ _MAX_PATH2 ];
    char        *drive;
    char        *dir;
    char        *fname;
    char        *ext;
    char        buf[ _MAX_PATH ];
    const char  *output;
    act_grp_t   *cur;
    int         rc;

/**/myassert( cmd != NULL );
/**/myassert( cmd->need_output );
/**/myassert( cmd->action != NULL );
/**/myassert( file_num < cmd->action->num_files );
    cur = cmd->action;
    output = cur->output;
    if( output == NULL || output[0] == 0 ) {
        /* get the drive and directory of input file */
        _splitpath2( in, sp_buf, &drive, &dir, NULL, NULL );
        fname = "";
        ext = "";
    } else {
        /* split up the output spec */
        _splitpath2( output, sp_buf, &drive, &dir, &fname, &ext );
    }
    /* If the output spec was like '/o=.mbj' or '/o=f:\tmp\.mbj' then
       we have to use the filename and/or the extension from the input. */
    _splitpath2( cur->files[ file_num ], sp_buf2, NULL, NULL,
        ( fname[0] == 0 ) ? &fname : NULL,      /* get filename from input */
        ( ext[0] == 0 ) ? &ext : NULL );        /* get extension from input */
    if( ext[0] == 0 ) {                 /* use default extension if necessary */
        ext = OBJ_EXTENSION;
    }
    _makepath( buf, drive, dir, fname, ext );
    if( make_lib ) {
        if( cur->batch ) {
            PrtFmt( "wlib %s /b/n/p=%u +%s\n", buf, page_size, out );
            PrtFmt( "del %s\n", out );
        } else {
            char pbuf[ sizeof( size_t ) * 3 ];
            StrDec( pbuf, page_size );
#ifdef M_I86
            _fheapshrink();
#endif
            _nheapshrink();
            rc = spawnlp(P_WAIT,"wlib","wlib",buf,"/b/n/p=",pbuf,"+",out,NULL);
            if( rc < 0 ) {
                Fatal( MSG_DISK_ERROR, "spawnlp( , \"wlib\", ... )" );
            } else if( rc > 0 ) {
                Fatal( MSG_WLIB_ERROR );
            }
            if( unlink( out ) != 0 ) {
                Fatal( MSG_DISK_ERROR, "unlink" );
            }
        }
    } else if( cur->batch ) {
        PrtFmt( "if exist %s del %s\n", buf, buf );
        PrtFmt( "rename %s %s\n", out, buf );
    } else {
        unlink( buf );          /* delete any file of this name */
        if( rename( out, buf ) != 0 ) {
            Fatal( MSG_DISK_ERROR, "rename" );
        }
    }
}

⌨️ 快捷键说明

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