cmdutils.c

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

C
1,253
字号
    bool        isdig;
    bool        isvalid;
    char        ch;
    int         size;
    unsigned    value;

    size = 0;
    value = 0;
    for(;;) {
        ch = tolower( *str );
        isdig = isdigit( ch );
        if( radix == 8 ) {
            isvalid = isdig && !(ch == '8' && ch == '9');
        } else {
            isvalid = isxdigit( ch );
        }
        if( !isvalid ) break;
        value *= radix;
        if( isdig ) {
            value += ch - '0';
        } else {
            value += ch - 'a' + 10;
        }
        size++;
        str++;
    }
    *Token.next = value;
    return( size );
}

static void MapEscapeChar( void )
/*******************************/
/* turn the current character located at Token.next into a possibly unprintable
 * character using C escape codes */
{
    char *      str;
    int         shift;

    shift = 2;
    str = Token.next + 1;
    switch( *str ) {
    case 'a':
        *Token.next = '\a';
        break;
    case 'b':
        *Token.next = '\b';
        break;
    case 'f':
        *Token.next = '\f';
        break;
    case 'n':
        *Token.next = '\n';
        break;
    case 'r':
        *Token.next = '\r';
        break;
    case 't':
        *Token.next = '\t';
        break;
    case 'v':
        *Token.next = '\v';
        break;
    case 'x':
        shift += ParseNumber( ++str, 16 );
        break;
    case '0': case '1': case '2': case '3': case '4': case'5': case '6':
    case '7': case '8': case '9':
        shift += ParseNumber( str, 8 ) - 1;
        break;
    default:
        *Token.next = *str;
        break;
    }
    str = Token.next + shift;
    memmove( Token.next + 1, str, strlen( str ) + 1 );
}

static int MapDoubleByteChar( char c )
/************************************/
/* if the double byte character support is on, check if the current character
 * is a double byte character skip it */
{
    switch( CmdFlags & CF_LANGUAGE_MASK ) {
    case CF_LANGUAGE_JAPANESE:
        if( (c >= 0x81 && c <= 0x9F) || (c >= 0xE0 && c <=0xFC) ) {
            Token.next++;
            return 1;
        }
        break;
    case CF_LANGUAGE_CHINESE:
        if( c > 0xFC ) break;
    case CF_LANGUAGE_KOREAN:            // note the fall through
        if( c > 0xFD ) break;
        if( c < 0x81 ) break;
        Token.next++;
        return 1;
    }
    return 0;
}

static bool MakeToken( tokcontrol ctrl, sep_type separator )
/**********************************************************/
{
    bool    quit;
    char    hmm;
    int     len;
    bool    forcematch;
    bool    hitmatch;
    bool    keepspecial;

    Token.this = Token.next;
    len = 0;
    quit = FALSE;
    forcematch = (separator == SEP_QUOTE) || (separator == SEP_PAREN)
                 || (separator == SEP_PERCENT);
    keepspecial = (separator == SEP_SPACE) || (separator == SEP_DOT_EXT);
    if( separator == SEP_DOT_EXT ) {    /* KLUDGE! we want to allow a zero*/
        len--;                  /* length token for parsing wlib files, so */
        Token.next--;           /* artificially back up one here. */
    }
    if( *Token.next == '\\' && separator == SEP_QUOTE
                         && !(ctrl & TOK_IS_FILENAME) ) {
        MapEscapeChar();        /* get escape chars starting in 1st pos. */
    }
    hmm = *Token.next;
    len += MapDoubleByteChar( hmm );
    hitmatch = FALSE;
    for(;;) {
        len++;
        hmm = *++Token.next;
        switch( hmm ) {
        case '\'':
            if( separator == SEP_QUOTE ) {
                ++Token.next;      // don't include end quote in next token.
                hitmatch = TRUE;
                quit = TRUE;
            }
            break;
        case ')':
            if( separator == SEP_PAREN ) {
                ++Token.next;    // don't include end paren in next token.
                hitmatch = TRUE;
                quit = TRUE;
            }
            break;
        case '%':
            if( separator == SEP_PERCENT ) {
                ++Token.next;    // don't include end percent in next token.
                hitmatch = TRUE;
                quit = TRUE;
            }
            break;
        case '.':
            if( !(ctrl & TOK_INCLUDE_DOT) && !forcematch ) {
                quit = TRUE;
            }
            break;
        case '{':
        case '}':
        case '(':
        case ',':
        case '=':
        case '#':
        case '@':
            if( keepspecial ) {
                break;
            }                   // NOTE the potential fall through
        case '\t':
        case ' ':
            if( !forcematch ) {
                quit = TRUE;
            }
            break;
        case '\\':
            if( separator == SEP_QUOTE && !(ctrl & TOK_IS_FILENAME) ) {
                MapEscapeChar();
            }
            break;
        case '\0':
        case '\r':
        case '\n':
        case CTRLZ:
            quit = TRUE;
            break;
        default:
            len += MapDoubleByteChar( hmm );
        }
        if( quit ) {
            break;
        }
    }
    Token.len = len;
    if( forcematch && !hitmatch ) {
        return( FALSE );     // end quote/paren not found before token end.
    }
    return( TRUE );
}


extern char *FileName( char *buff, int len, byte etype, bool force )
/******************************************************************/
{
    char *  namptr;
    char *  namstart;
    char *  ptr;
    int     cnt;
    int     namelen;

    namptr = buff + len;
    cnt = 0;
    while( cnt != len ) {
        cnt++;
        --namptr;
        if( IS_PATH_SEP( *namptr ) ) break;
    }
    if( IS_PATH_SEP( *namptr ) ) {
        namptr++;
    }
    namstart = namptr;
    cnt = len - ( (int) namptr - (int) buff );
    if( cnt == 0 ) {
        ptr = alloca( len + 1 );
        memcpy( ptr, buff, len );
        ptr[len] = '\0';
        LnkMsg( LOC+LINE+FTL+MSG_INV_FILENAME, "s", ptr );
    }
    namelen = cnt;
    namptr = buff + len - 1;
    while( --cnt != 0 && *namptr != '.' ) {
        namptr--;
    }
    if( force || *namptr != '.' ) {
        if( force && etype == E_MAP ) {         // op map goes in current dir.
            buff = namstart;
            len = namelen;
        }
        if( cnt != 0 ) {
            len = namptr - buff;
        }
        _ChkAlloc( ptr, len + strlen( DefExt[ etype ] ) + 1 );
        memcpy( ptr, buff, len );
        strcpy( ptr + len, DefExt[ etype ] );
    } else {
        _ChkAlloc( ptr, len + 1 );
        memcpy( ptr, buff, len );
        ptr[ len ] = '\0';
    }
    return( ptr );
}

extern void RestoreCmdLine( void )
/********************************/
// Restore a saved command line.
{
    cmdfilelist *   temp;

    if( CmdFile->prev == NULL ) {     /* can't free last file */
        Token.where = ENDOFCMD;
        return;
    }
    switch( Token.how ) {
    case SYSTEM:
        break;
    default:
        _LnkFree( Token.buff );
        if( CmdFile->file > STDIN_HANDLE ) {
            QClose( CmdFile->file, CmdFile->name );
        }
        break;
    }
    if( CmdFile->symprefix)
        _LnkFree( CmdFile->symprefix );
    CmdFile->symprefix = NULL;
    _LnkFree( CmdFile->name );
    temp = CmdFile->prev;
    temp->next = CmdFile->next;
    if( temp->next != NULL ) {
        temp->next->prev = temp;
    }
    _LnkFree( CmdFile );
    CmdFile = temp;
    memcpy( &Token, &CmdFile->token, sizeof( tok ) ); // restore old state.
}

extern bool IsSystemBlock()
/*************************/
// Are we in a system block?
{
    cmdfilelist *   temp;

    if( Token.how == SYSTEM ) return( TRUE );

    for( temp = CmdFile; temp != NULL; temp = temp->prev ) {
        if( temp->token.how == SYSTEM ) return( TRUE );
    }
    return( FALSE );
}

extern void BurnUtils( void )
/***************************/
// Burn data structures used in command utils.
{
    void *      temp;

    if( CmdFile->next != NULL ) {
        LnkMsg( LOC+LINE+ERR+MSG_NO_INPUT_LEFT, NULL );
    }
    while( CmdFile != NULL ) {
        if( CmdFile->file > STDIN_HANDLE ) {
            QClose( CmdFile->file, CmdFile->name );
        }
        if( CmdFile->symprefix)
            _LnkFree( CmdFile->symprefix );
        CmdFile->symprefix = NULL;
        _LnkFree( CmdFile->name );
        switch( CmdFile->token.how ) {
        case ENVIRONMENT:
        case SYSTEM:
            break;
        default:
            _LnkFree( CmdFile->token.buff );
            break;
        }
        temp = CmdFile;
        CmdFile = CmdFile->prev;
        _LnkFree( temp );
    }
    Token.how = BUFFERED;       // so error message stuff reports right name
}

extern outfilelist * NewOutFile( char * filename )
/************************************************/
{
    outfilelist *   fnode;

    fnode = OutFiles;
    while( fnode != NULL ) {
        if( FNAMECMPSTR( filename, fnode->fname ) == 0 ) {
            _LnkFree( filename );       // don't need this now.
            return( fnode );
        }
        fnode = fnode->next;
    }
// file name not already in list, so add a list entry.
    _ChkAlloc( fnode, sizeof( outfilelist ) );
    InitBuffFile( fnode, filename, TRUE );
    fnode->next = OutFiles;
    OutFiles = fnode;
    return( fnode );
}

int stricmp_wrapper( const void *s1, const void *s2 )
{
    return stricmp( s1, s2 );
}

extern section * NewSection( void )
/*********************************/
{
    section             *sect;

    OvlNum++;
    _ChkAlloc( sect, sizeof( section ) );
    sect->next_sect = NULL;
    sect->classlist = NULL;
    sect->orderlist = NULL;
    sect->areas = NULL;
    sect->files = NULL;
    sect->modFilesHashed = CreateHTable( 256, StringiHashFunc, stricmp_wrapper,
                                        ChkLAlloc, LFree );
    sect->mods = NULL;
    sect->reloclist = NULL;
    sect->sect_addr.off = 0;
    sect->sect_addr.seg = UNDEFINED;
    sect->ovl_num = 0;
    sect->parent = NULL;
    sect->relocs = 0;
    sect->size = 0;
    sect->outfile = NULL;
    sect->u.dist_mods = NULL;
    sect->dbg_info = NULL;
    return( sect );
}

extern char * GetFileName( char **membname, bool setname )
/********************************************************/
{
    char *  ptr;
    int     namelen;
    char *  objname;
    char *  fullmemb;
    int     memblen;

    namelen = Token.len;
    objname = alloca( namelen );
    memcpy( objname, Token.this, namelen );
    if( GetToken( SEP_PAREN, TOK_INCLUDE_DOT ) ) {   // got LIBNAME(LIB_MEMBER)
        fullmemb = alloca( Token.len + 1 );
        memcpy( fullmemb, Token.this, Token.len );
        fullmemb[Token.len] = '\0';
        fullmemb = RemovePath( fullmemb, &memblen );
        _ChkAlloc( *membname, memblen + 1 );
        memcpy( *membname, fullmemb, memblen );
        (*membname)[memblen] = '\0';
        ptr = FileName( objname, namelen, E_LIBRARY, FALSE );
    } else {
        *membname = NULL;
        if( setname && Name == NULL ) {
            _ChkAlloc( Name, namelen + 1 );
            memcpy( Name, objname, namelen );
            Name[ namelen ] = '\0';
        }
        ptr = FileName( objname, namelen, E_OBJECT, FALSE );
    }
    return( ptr );
}

⌨️ 快捷键说明

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