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 + -
显示快捷键?