wrdencod.c

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

C
1,273
字号
{
    char code1[10];             // - byte[1] of code
    char code2[10];             // - byte[2] of code (optional)
    int retn;                   // - return value

    GUESS :: NO_ERRS
        retn = write_c_delim();
        QUITIF( retn != 0 );
        space_put_out += 1;
        stxcpy( code1 , code & 0x3f );
        IF( code & LARGE_BIT )
            space_put_out += 1;
            stxcpy( code2 , code >> 8 );
            retn = write_c_strs_eol( "ENC_BIT | "
                                   , "LARGE_BIT | "
                                   , code1
                                   , ", "
                                   , code2
                                   , NULL );
        ELSE
            retn = write_c_strs_eol( "ENC_BIT | "
                                   , code1
                                   , NULL );
        ENDIF
    ENDGUESS
    return( retn );
}


static int print_encod_text()   // PRINT ENCODED TEXT
{
    int retn;                   // - return value

    GUESS :: NO_ERRS
        retn = beg_part( "MSG_SCOPE unsigned char MSG_MEM encoded_text[] =" );
        QUITIF( retn != 0 ) :: NO_ERRS;
        retn = _ring_walk_int( (void ***)RingWords, print_text_encod, 0 );
        QUITIF( retn != 0 ) :: NO_ERRS;
        retn = _ring_walk_int( (void ***)RingPhrases, print_phrase_encod, 0 );
        QUITIF( retn != 0 ) :: NO_ERRS;
        retn = _ring_walk_int( (void **)RingMessages, &print_sentence, 0 );
        QUITIF( retn != 0 ) :: NO_ERRS;
        retn = end_part();
    ENDGUESS
    return( retn );
}


static int print_word_count()   // PRINT WORD COUNT
{
    int retn;                   // - return value
    char encwrds[10];           // - string of number of encoded words

    GUESS :: NO_ERRS
        utoa( enc_words , encwrds , 10 );
        retn = write_c_strs_eol
                        ( "MSG_SCOPE unsigned short MSG_MEM word_count = "
                        , encwrds
                        , ";"
                        , NULL );
        QUITIF( retn != 0 );
        retn = write_c_eol();
    ENDGUESS
    return( retn );
}


static int print_offset()       // PRINT OFFSET OF WORD, PHRASE, OR MESSAGE
{
    int retn;                   // - return value
    char len[10];               // - length in text form

    GUESS :: NO_ERRS
        space_put_out += 2;
        utoa( lenwords , len , 10 );
        retn = write_c_delim();
        QUITIF( retn != 0 );
        retn = write_c_line( len );
    ENDGUESS
    return( retn );
}


static int prt_msg_offset(      // PRINT OFFSET OF A MESSAGE
    MESSAGE *msg )              // - the message
{
    int retn;                   // - return value
    WORD *word;                 // - current word/phrase
    WORD **wordp;               // - points in vector of words
    unsigned count;             // - counts words

    GUESS :: NO_ERRS
        retn = print_offset();
        QUITIF( retn != 0 );
        FOR( wordp = msg->words, count = msg->codes
           ; count > 0
           ; --count )
            word = *wordp++;
            IF( word->code & ENC_BIT )
                IF( word->code & LARGE_BIT )
                    ++ lenwords;
                ENDIF
            ELSE
                lenwords += strlen( word->text );
            ENDIF
            ++ lenwords;
        ENDFOR
        ++ lenwords;
    ENDGUESS
    return( retn );
}


static int prt_enc_word_offset( // PRINT OFFSET OF ENCODED WORD
    WORD *curr )                // - current record
{
    int retn;                   // - return value

    IF( curr->code & ENC_BIT )
        retn = print_offset();
        lenwords += strlen( curr->text ) + 1;
    ELSE
        retn = 0;
    ENDIF
    return( retn );
}


static int print_text_table()   // PRINT TEXT TABLE IN FILE
{
    int retn;                   // - return value

    GUESS :: NO_ERRS
        retn = beg_part( "MSG_SCOPE unsigned short MSG_MEM text_table[] = " );
        QUITIF( retn != 0 );
        lenwords = 0;
        retn = _ring_walk_int( (void **)RingWords , prt_enc_word_offset, 0 );
        QUITIF( retn != 0 );
        retn = _ring_walk_int( (void **)RingPhrases , prt_msg_offset, 0 );
        QUITIF( retn != 0 );
        retn = _ring_walk_int( (void **)RingMessages , prt_msg_offset, 0 );
        QUITIF( retn != 0 );
        retn = end_part();
    ENDGUESS
    return( retn );
}


static int print_group_num(     // PRINT GROUP NUMBER
    MESSAGE *curr )             // - current message
{
    int retn;                   // - return value
    char putwrds[5];            // - string of numwords;

    GUESS :: NO_ERRS
        retn = 0;
        QUITIF( curr->number != 0 )
        utoa( numwords , putwrds , 10 );
        retn = write_c_delim();
        QUITIF( retn != 0 ) :: NO_ERRS
        retn = write_c_line( putwrds );
    ENDGUESS
    ++numwords;
    return( retn );
}


static int print_group_table(   // PRINT GROUP_TABLE
    int index)                  // - group indexer
{
    int retn;                   // - return value

    GUESS :: NO_ERRS
        retn = beg_part( "MSG_SCOPE unsigned short MSG_MEM group_table[]= " );
        QUITIF( retn != 0 );
        numwords = index;
        retn = _ring_walk_int( (void **)RingMessages , print_group_num, 0 );
        QUITIF( retn != 0 );
        retn = end_part();
    ENDGUESS
    return( retn );
}


static void encode_phrases()    // ENCODE PHRASES
{
    unsigned number;            // - phrase number
    MESSAGE *phrase;            // - current phrase

    phrase = RingPhrases;
    IF( phrase != NULL )
        number = enc_words;
        LOOP
            phrase = phrase->next;
            phrase->number = ( number & 0x3f )
                           | ( ( number & 0xffc0 ) << 2 )
                           | ENC_BIT;
            IF( number++ >= 64 )
                phrase->number |= LARGE_BIT;
            ENDIF
        UNTIL( phrase == RingPhrases );
    ENDIF
}


static void encode_dec(         // DECIDE ENCODE
    WORD *curr )                // - current record
{
    IF( ( enc_words < 64 )
      &&( ( ( curr->count - 1 )*( strlen( curr->text ) ) ) > 3 ) )
        curr->code = enc_words + ENC_BIT;
        ++enc_words;
    ELSEIF ( ( enc_words >= 64 )&&
     ( ( ( curr->count - 1 )*( strlen( curr->text ) - 1 ) ) > 4 ) )
        curr->code = ( enc_words & 0x3f ) + ( (enc_words & 0x3fc0 ) << 2 ) +
                       ENC_BIT  + LARGE_BIT;
        ++enc_words;
    ENDIF
}


static void encode_words()      // ENCODE WORDS
{
    enc_words = 0;
    _ring_walk( (void **)RingWords , encode_dec );
}


static int compare_word_counts( // COMPARE WORDS, USING COUNTS, FOR SORT
    WORD *op1,                  // - word(1) (current)
    WORD *op2 )                 // - word(2) (being inserted)
{
    return( op2->count - op1->count );
}


static void sort_words()        // SORT WORDS
{
    _ring_sort( (void ***)&RingWords, &compare_word_counts );
}


static int compare_phr_counts(  // COMPARE WORDS, USING COUNTS, FOR SORT
    MESSAGE *op1,               // - phrase(1) (current)
    MESSAGE *op2 )              // - phrase(2) (being inserted)
{
    return( op2->count - op1->count );
}


static void sort_phrases()      // SORT WORDS
{
    _ring_sort( (void ***)&RingPhrases, &compare_phr_counts );
}


static int write_define(        // WRITE DEFINE STATEMENTS
    int (*writer)               // - writer
        ( const char * ) )      // - - string
{
    unsigned fmt_size;
    int retn;                   // - return
    char msg[80];               // - message buffer

    GUESS :: NO_ERRS
        retn = (*writer)( "#define ENC_BIT 0x80" );
        QUITIF( retn != 0 );
        retn = (*writer)( "#define LARGE_BIT 0x40" );
        QUITIF( retn != 0 );
        // messages involve an extra ' ' at the end
        // so we'll add 16 and round up to mos 16 to be absolutely safe
        fmt_size = ( ( msg_size + 16 ) + 0x0f ) & ~ 0x0f;
        stucpy( stpcpy( msg, "#define MAX_MSG " ), fmt_size );
        retn = (*writer)( msg );
        QUITIF( retn != 0 );
        retn = (*writer)( "" );
        QUITIF( retn != 0 );
    ENDGUESS
    return( retn );
}


static int create_output()      // CREATE OUTPUT
{
    int retn;                   // - return value

    GUESS :: NO_OPEN
        retn = open_c_file( messages );
        QUITIF( retn == 0 );
    ADMIT :: ENCODE_TEXT
        sort_words();
        encode_words();
        sort_phrases();
        encode_phrases();
        write_define( &write_c_line );
        retn = print_group_table( enc_words + enc_phrases );
        QUITIF( retn != 0 );
        retn = print_text_table();
        QUITIF( retn != 0 );
        retn = print_word_count( );
        QUITIF( retn != 0 );
        retn = print_encod_text();
        QUITIF( retn != 0 );
        IF( RingGroups != NULL )
            retn = print_group_prefix();
            QUITIF( retn != 0 );
        ENDIF
        retn = close_c_file();
    ENDGUESS
    return( retn );
}


static void create_level(       // CREATE A LEVEL ENTRY
    MESSAGE *msg )              // - current entry
{
    char buffer[16];            // - record buffer

    buffer[0] = delim[0];
    delim[0] = ',';
    stucpy( buffer+1, ( msg->type << 4 ) + msg->level );
    write_h_line( buffer );
}


static int create_levels()      // CREATE LEVELS FILE
{
    int retn;                   // - return value

    GUESS :: NO_OPEN
        retn = open_h_file( levels );
        QUITIF( retn == 0 );
    ADMIT :: LEVELS
        write_h_line( "typedef enum" );
        write_h_line( "{   MSG_TYPE_ERROR" );
        write_h_line( ",   MSG_TYPE_WARNING" );
        write_h_line( ",   MSG_TYPE_INFO" );
        write_h_line( ",   MSG_TYPE_ANSI" );
        write_h_line( ",   MSG_TYPE_ANSIERR" );
        write_h_line( ",   MSG_TYPE_ANSIWARN" );
        write_h_line( ",   MSG_TYPE_ANSICOMP" );
        write_h_line( ",   MSG_TYPE_EXTWARN" );
        write_h_line( "} MSG_TYPE;" );
        write_h_line( " " );
        write_h_line( "static unsigned char msg_level[] =" );
        delim[0] = '{';
        _ring_walk( (void**)RingMessages, &create_level );
        write_h_line( "};" );
        retn = close_h_file();
    ENDGUESS
    return retn;
}


static int process_group(       // GRP OPTION FOUND
    const char *scanner )       // - line scanner
{
    int retn;                   // - return value
    char *name;                 // - group name
    unsigned length;            // - length of given word
    WORD *new;                  // - new group name

    GUESS :: NO_GROUP
        scanner = scan_over_black_space( scanner );
        scan_name( &scanner , &name , &length );
        QUITIF( length > 0 ) :: NO_GROUP;
        retn = msgerr( "No group name present" );
    ADMIT :: NO_ERRS
        retn = alloc_ring( &RingGroups , sizeof( struct word ) + length ,
                                                    &new );
        QUITIF( retn != 0 ) :: NO_ERRS;
        stvcpy( new->text , name , length );
    ENDGUESS
    return( retn );
}


static int alloc_message(       // ALLOCATE A MESSAGE ENTRY (OR PHRASE)
    void **ring,                // - ring
    WORD **words,               // - words vector
    unsigned count,             // - number of words
    unsigned number )           // - message number
{
    int retn;                   // - return code
    MESSAGE *msg;               // - new message

    GUESS :: NO_ERRS
        substitute_phrases( words, &count );
        retn = alloc_ring( ring, sizeof( struct message ) +
                 (count - 1 )*( sizeof( WORD * ) ) , &msg );
        QUITIF( retn != 0 );
        memcpy( msg->words, words, count * sizeof( WORD * ) );
        msg->codes = count;
        msg->count = 0;
        msg->number = number;
        msg->type = MSG_TYPE_ERROR;
        msg->level = 0;
    ENDGUESS
    return( retn );
}


static int scan_level(          // SCAN LEVEL
    const char *cptr,           // - line scanner
    unsigned *level )           // - level scanned
{
    int retn;                   // - return code

    GUESS :: NO_LEVEL
        cptr = scan_over_white_space( cptr );
        if( *cptr == '.' ) {
            cptr = scan_over_white_space( cptr + 1 );
        }
        QUITIF( *cptr != '\0' );
        retn = msgerr( "No warning level" );
    ADMIT :: BAD_LEVEL
        QUITIF( isdigit( *cptr ) );
        retn = msgerr( "Invalid warning level" );
    ADMIT :: MORE_JUNK
        *level = *cptr - '0';
        ++cptr;
        if( *cptr != '\0' && isdigit( *cptr ) ) {
            *level *= 10;
            *level += *cptr - '0';
            ++cptr;

⌨️ 快捷键说明

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