wrdencod.c

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

C
1,273
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


// MSGENCOD -- encode messages to be generated by GML program
//
// 91/05/24 -- J.W.Welch        -- defined
// 91/05/29 -- E.Sutherland     -- start on project
// 91/06/28 -- E.Sutherland     -- complete with encoding/decoding words
// 91/07/05 -- A.F.Scian        -- removed use of flt-pt in statistics
//                               - cleaned up output of stats
// 91/07/09 -- E.Sutherland     -- added non-overlapping phrase encoding
// 91/10/03 -- J.W.Welch        -- cleaned up, use ENCODIO.C
// 92/03/03 -- J.W.Welch        -- output maximum for message size
// 93/03/05 -- J.W.Welch        -- extend for level vector
// 93/03/30 -- A.F.Scian        -- used unsigned long for byte counts
// 93/11/23 -- A.F.Scian        -- accept 2 digit warning levels
// 95/01/18 -- J.W.Welch        -- emit '\'' instead of '''

#include <stdio.h>
#include <process.h>
#include <direct.h>
#include <ctype.h>
#define process_text not_used
#include "msgencod.h"
#undef  process_text
#include "watlibio.h"

#define ENC_BIT   0x80
#define LARGE_BIT 0x40

typedef struct word WORD;
typedef struct message MESSAGE;

typedef enum                    // TYPES OF MESSAGES
{   MSG_TYPE_ERROR              // - error
,   MSG_TYPE_WARNING            // - warning
,   MSG_TYPE_INFO               // - informational
,   MSG_TYPE_ANSI               // - warning when extensions, error otherwise
,   MSG_TYPE_ANSIERR            // - ignored when extensions, error otherwise
,   MSG_TYPE_ANSIWARN           // - ignored when extensions, warn otherwise
,   MSG_TYPE_ANSICOMP           // - error, can be changed to warning when extensions
,   MSG_TYPE_EXTWARN            // - warn when extensions, ignored otherwise
} MSG_TYPE;


struct word                     // WORD ENTRY
{   WORD *next;                 // - next in ring
    unsigned short code;        // - encoding byte
    unsigned short count;       // - occurence count
    char text[1];               // - text for word
};

struct message                  // MESSAGE/PHRASE ENTRY
{   MESSAGE *next;              // - next in ring
    unsigned short number;      // - message number within group
    unsigned short count;       // - occurence count
    unsigned short codes;       // - number of words/phrases
    unsigned char level;        // - error/warning level
    MSG_TYPE type;              // - type of message
    WORD *words[1];             // - vector of WORD pointers
};

static WORD *RingWords;         // - Ring of Words
static WORD *RingGroups;        // - Ring of Groups
static MESSAGE *RingMessages;   // - Ring of Messages
static MESSAGE *RingPhrases;    // - Ring of Phrases
static unsigned long enc_words; // - number of words encoded
static unsigned long enc_phrases;//- number of phrases encoded
static unsigned msg_size;       // - maximum message size
static unsigned long lenwords;  // - cum. string length
static unsigned long numwords;  // - number of words in group
static char delim[3] = "  ";    // - delimiter for output
static unsigned long space_read_in;// - size of input file
static unsigned long space_put_out;// - size of output file

                                // IO FILES
static char *source;            // - source file
static char *messages;          // - C output file
static char *codes;             // - header output file
static char *levels;            // - levels output file
static FILE_DEFN *filepres;     // - source file, when opened

typedef enum
{   REC_GRP                     // - :MSGGRP token
,   REC_SYM                     // - :MSGSYM token
,   REC_TXT                     // - :MSGTXT token
,   REC_MOD                     // - modifiers
,   REC_EOF                     // - end of file
,   MAX_REC                     // - maximum record
,   REC_NONE                    // - no record read in
} REC_TYPE;                     // TYPE OF RECORD

typedef enum
{   START_LINE                  // - beginning of program
,   FOUND_EOF                   // - found EOF
,   GROUP_LINE                  // - :MSGGRP found
,   SYM_GROUP                   // - :MSGSYM within a group
,   TEXT_GROUP                  // - :MSGTXT within a group
,   SYM_NO_GRP                  // - :MSGSYM first in file
,   TEXT_NO_GRP                 // - :MSGTXT without a group
,   MOD_GROUP                   // - modifier within group
,   MOD_NO_GRP                  // - modifier without group
,   MAX_STATE                   // - highest legal state possible
,   PRE_EOF                     // - premature end-of-dile
,   GRP_NOT_FRST                // - Group not first file
,   MISPL_TXT                   // - misplaced text token
,   MISPL_SYM                   // - misplaced symbol token
,   MISPL_MOD                   // - misplaced modifier
,   DUP_MOD                     // - more than one modifier
}STATE;                         // STATE OF LOGIC

static char state_table[MAX_STATE][MAX_REC] =
//  GROUP      SYMBOL     TEXT        MODIFIER   EOF
{ GROUP_LINE  ,SYM_NO_GRP,MISPL_TXT  ,MISPL_MOD ,PRE_EOF   // START_LINE
, FOUND_EOF   ,FOUND_EOF ,FOUND_EOF  ,FOUND_EOF ,FOUND_EOF // FOUND_EOF
, GROUP_LINE  ,SYM_GROUP ,MISPL_TXT  ,MISPL_MOD ,PRE_EOF   // GROUP_LINE
, MISPL_SYM   ,MISPL_SYM ,TEXT_GROUP ,MISPL_MOD ,PRE_EOF   // SYM_GROUP
, GROUP_LINE  ,SYM_GROUP ,MISPL_TXT  ,MOD_GROUP ,FOUND_EOF // TEXT_GROUP
, GRP_NOT_FRST,MISPL_SYM ,TEXT_NO_GRP,MISPL_MOD ,PRE_EOF   // SYM_NO_GRP
, GRP_NOT_FRST,SYM_NO_GRP,MISPL_TXT  ,MOD_NO_GRP,FOUND_EOF // TEXT_NO_GRP
, GROUP_LINE  ,SYM_GROUP ,MISPL_TXT  ,DUP_MOD   ,FOUND_EOF // MOD_GROUP
, GRP_NOT_FRST,SYM_NO_GRP,MISPL_TXT  ,DUP_MOD   ,FOUND_EOF // MOD_NO_GRP
};


static void scan_name(          // SCAN NAME FROM TEXT LINE
    const char **scanner,       // - line scanner
    const char **word,          // - word on line
    unsigned *length )          // - length of name
{
    const char *cptr;           // - line pointer
    const char *name;           // - name on line

    cptr = scan_over_white_space( *scanner );
    name = cptr;
    cptr = scan_over_black_space( cptr );
    *length = cptr - name;
    *word = name;
    *scanner = cptr;
}


static int write_c_delim()      // WRITE DELIMITER ( '{' OR ',' ) TO C FILE
{
    int retn;                   // - return

    retn = write_c_str( delim );
    delim[0] = ',';
    return( retn );
}


static void substitute_phrases( // SUBSTITUTE PHRASES IN A SENTENCE
    WORD **sentence,            // - sentence
    unsigned *count )           // - addr( # phrases )
{
    unsigned words_left;        // - # words left to scan
    unsigned words_sent;        // - # words in sentence
    unsigned phrase_size;       // - size of current phrase
    MESSAGE *phrase;            // - current phrase
    WORD **word;                // - addr( word in phrase )
    WORD **sent;                // - scan position in "sentence"

    IF( RingPhrases != NULL )
        words_sent = *count;
        LOOP :: SUB_LOOP
            sent = sentence;
            GUESS :: NO_SUBST
                FOR( words_left = words_sent
                   ; words_left > 0
                   ; --words_left, ++sent )
                    phrase = RingPhrases;
                    LOOP
                        phrase = phrase->next;
                        phrase_size = phrase->codes;
                        QUITIF( ( phrase_size <= words_left )
                              &&( 0 ==
                                 memcmp( sent
                                       , phrase->words
                                       , sizeof( WORD * ) * phrase_size ) )
                          ) :: NO_SUBST
                    UNTIL( phrase == RingPhrases );
                ENDFOR
                QUIT :: SUB_LOOP
            ADMIT :: DO_SUBST
                words_left -= phrase_size - 1;
                words_sent -= phrase_size - 1;
                memcpy( sent + 1
                      , sent + phrase_size
                      , sizeof( WORD * ) * ( words_left - 1 ) );
                *sent = (WORD *)phrase;
                FOR( word = phrase->words
                   ; phrase_size > 0
                   ; -- phrase_size, ++ word )
                    -- (*word)->count;
                ENDFOR
                ++ phrase->count;
            ENDGUESS
        ENDLOOP
        *count = words_sent;
    ENDIF
}


static int alloc_ring(          // ALLOCATE RING SPACE
    void **hdr ,                // - ring header
    size_t size ,               // - size to be allocated
    void **element )            // - element allocated
{
    int retn;                   // - return value

    *element = (void *)_ring_alloc( (void ***)hdr, size );
    IF( *element == NULL )
        retn = msgerr( "Out Of Memory" );
    ELSE
        retn = 0;
    ENDIF
    return( retn );
}


static int print_name(          // - SPLIT NAME AND PRINT
    const char *name )          // - name to be parsed
{
    int retn;                   // - return value

    GUESS :: NO_ERRS
        LOOP
            retn = write_c_delim();
            QUITIF( retn != 0 ) :: NO_ERRS
            retn = write_c_chr( '\'' );
            QUITIF( retn != 0 ) :: NO_ERRS
            IF( *name == '\'' )
                retn = write_c_chr( '\\' );
                QUITIF( retn != 0 ) :: NO_ERRS
            ENDIF
            retn = write_c_chr( *name );
            QUITIF( retn != 0 ) :: NO_ERRS
            IF( *name == '\\' )
                retn = write_c_chr( *name );
                QUITIF( retn != 0 ) :: NO_ERRS
            ENDIF
            retn = write_c_chr( '\'' );
            QUITIF( retn != 0 ) :: NO_ERRS
            ++name;
            QUITIF( *name == '\0' );
        ENDLOOP
        retn = write_c_eol();
    ENDGUESS
    return( retn );
}


static int beg_part(            // PUT OUT STARTING PART
    const char *text )          // - text for start
{
    delim[0] = '{';
    return( write_c_line( text ) );
}


static int end_part()           // PUT SPACE BETWEEN PARTS
{
    int retn;                   // - return value

    GUESS :: NO_ERRS
        retn = write_c_line( "};" );
        QUITIF( retn != 0 );
        retn = write_c_eol();
    ENDGUESS
    return( retn );
}


static int print_group_name(    // PRINT NAME
    WORD *curr )                // - current value
{
    return( print_name( curr->text ) );
}


static int print_group_prefix() // PRINT GROUP PREFIXES
{
    int retn;                   // - return value

    GUESS :: NO_ERRS
      retn = beg_part( "MSG_SCOPE unsigned char MSG_MEM group_prefix[] = {" );
      QUITIF( retn != 0 );
      retn = _ring_walk_int( (void **)RingGroups , print_group_name , 0 );
      QUITIF( retn != 0 ) :: NO_ERRS;
      retn = end_part();
    ENDGUESS
    return( retn );
}


static int write_raw(           // write text in unencoded format
    const char *curr )          // - current word
{
    int retn;                   // - return value
    int length;                 // - length of a word
    char len[5];                // - string of length

    GUESS :: NO_ERRS
        length = strlen( curr );
        space_put_out += length + 1;
        utoa( length , len , 10 );
        retn = write_c_delim();
        QUITIF( retn != 0 );
        retn = write_c_str( len );
        QUITIF( retn != 0 );
        retn = print_name( curr );
    ENDGUESS
    return( retn );
}


static int print_msg_word(      // PRINT ENCODING FOR A WORD/PHRASE
    WORD *word )                // - word in sentence
{
    int retn;                   // - return value

    IF( word->code & ENC_BIT )
        retn = write_encode( word->code );
    ELSE
        retn = write_raw( word->text );
    ENDIF
    return( retn );
}


static int print_msg_words(     // PRINT WORDS IN A MESSAGE
    WORD **text,                // - text (words)
    unsigned count,             // - number of words
    unsigned number,            // - number in comment
    const char *comment )       // - comment
{
    int retn;                   // - return value
    char buf[10];

    GUESS :: NO_ERRS
        utoa( number, buf, 10 );
        retn = write_c_strs_eol( "/" "* "
                               , comment
                               , buf
                               , " *" "/"
                               , NULL );
        QUITIF( retn != 0 );
        FOR( ; count > 0; -- count )
            retn = print_msg_word( *text++ );
            QUITIF( retn != 0 ) :: NO_ERRS
        ENDFOR
        retn = write_c_line( ", 0" );
        space_put_out += 1;
    ENDGUESS
    return( retn );
}


static int print_phrase_encod(  // PRINT PHRASE
    MESSAGE *curr )             // - current phrase
{
    return( print_msg_words( curr->words
                           , curr->codes
                           , ( curr->number & 0x3f )
                           + ( ( curr->number & 0xff00 ) >> 2 )
                           , "PHRASE " ) );
}


static int print_sentence(      // PRINT SENTENCE IN A MESSAGE
    MESSAGE *curr )             // - current message
{
    return( print_msg_words( curr->words
                           , curr->codes
                           , curr->number
                           , "MESSAGE " ) );
}


static int print_text_encod(    // PRINT ENCODED TEXT
    WORD *curr )                // - current record
{
    int retn;                   // - return value

    IF( curr->code & ENC_BIT )
        retn = write_raw( curr->text );
    ELSE
        retn = 0;
    ENDIF
    return( retn );
}


static int write_encode(        // WRITE ENCODED PARTS
    unsigned int code )         // - given code

⌨️ 快捷键说明

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