msgbuild.cpp

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

CPP
497
字号
/****************************************************************************
*
*                            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!
*
****************************************************************************/


// MSGBUILD.CPP -- version(2) message compression
//
// 95/01/30 -- J.W.Welch        -- defined

#include <ctype.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>

#include "BuildMsg.h"
#include "Exc.h"
#include "FileCtl.h"
#include "Msg.h"
#include "Ring.h"
#include "Utility.h"
#include "Word.h"


// STATIC STORAGE

static FileCtlInput  gml;       // input file
static FileCtlOutput codes;     // codes file
static FileCtlOutput msgs;      // encoded messages
static FileCtlOutput levels;    // levels file
static unsigned line_ctr;       // line counter
static EncStats stats;          // statistics


static char const * const help_text[] = // - help text
{   "Usage: msgencod source message codes levels" ,
    "" ,
    "Example: msgencod ftnmsgs ftnerrs ftnhead levels" ,
    "" ,
    "The program takes the \"source\" (in GML format) and produces a" ,
    "\"message.c\" file, a \"codes.h\" file, and a \"levels.h\" file." ,
    "" ,
    "The \"message.c\" file contains all the messages (encoded).",
    "The \"codes.h\" file contains tags for the messages." ,
    "The \"levels.h\" file contains message levels for the messages." ,
    NULL
};


static void display_help()      // DISPLAY HELP TEXT
{
    for( char const * const *text = help_text
       ; *text != NULL
       ; ++ text ) {
        puts( *text );
    }
}


static char const* scanOverWS   // SCAN OVER WHITE SPACE
    ( char const *scan )
{
    for( ; isspace( *scan ); ++ scan );
    return scan;
}


static char const* scanOverBS   // SCAN OVER BLACK SPACE
    ( char const *scan )
{
    for( ; *scan != '\0' && ! isspace( *scan ); ++ scan );
    return scan;
}

enum ProcState                  // ProcState: processing state
{   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
,   FOUND_PHR                   // - :MSGPHR
,   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
};

static ProcState stateTable[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
, FOUND_PHR   ,FOUND_PHR ,FOUND_PHR  ,FOUND_PHR ,FOUND_PHR // FOUND_PHR
};

struct _KwGml
{   char const *kw;
    RecType rec_type;
    MsgType msg_type;
    unsigned char kw_size;
    unsigned :0;
};

#define kw( text, rec, msg ) { text, rec, msg, sizeof( text ) - 1 }

static _KwGml const kwTable[] = // table of keywords
{   kw( "MSGSYM"    , REC_SYM, MSG_TYPE_ERROR )
,   kw( "MSGTXT"    , REC_TXT, MSG_TYPE_ERROR )
,   kw( "WARNING"   , REC_MOD, MSG_TYPE_WARNING )
,   kw( "ANSICOMP"  , REC_MOD, MSG_TYPE_ANSICOMP )
,   kw( "ANSIERR"   , REC_MOD, MSG_TYPE_ANSIERR )
,   kw( "ANSIWARN"  , REC_MOD, MSG_TYPE_ANSIWARN )
,   kw( "ANSI"      , REC_MOD, MSG_TYPE_ANSI )
,   kw( "EXTWARN"   , REC_MOD, MSG_TYPE_EXTWARN )
,   kw( "INFO"      , REC_MOD, MSG_TYPE_INFO )
,   kw( "MSGGRP"    , REC_GRP, MSG_TYPE_ERROR )
,   kw( "MSGPHR"    , REC_PHR, MSG_TYPE_ERROR )
,   kw( 0           , REC_NONE,MSG_TYPE_ERROR )
};

#undef kw


static void scanError           // THROW SCANNING ERROR
    ( char const *msg )         // - message
{
    char buffer[16];
    utoa( line_ctr, buffer, 10 );
    throw Exc( "SCAN", msg, "on line", buffer, NULL );
}


static void checkEOL            // CHECK FOR END-OF-LINE
    ( char const *text )        // - scanner
{
    text = scanOverWS( text );
    if( '\0' != *text ) {
        scanError( "extra stuff on line" );
    }
}


static byte scanWords           // SCAN WORDS ON A LINE
    ( char const *text          // - scanner
    , Word** words )            // - words vector
{
    byte word_count;            // - # words
    char const * word_beg;      // - start of word
    unsigned message_size;      // - size of message

    message_size = 0;
    for( word_count = 0; ; ++word_count ) {
        text = scanOverWS( text );
        if( '\0' == *text ) break;
        word_beg = text;
        text = scanOverBS( text );
        unsigned size = text - word_beg;
        message_size += 1 + size;
        words[ word_count ] = Word::newWord( word_beg, size );
    }
    if( message_size > stats.max_message ) {
        stats.max_message = message_size;
    }
    stats.space_read_in += message_size;
    return word_count;
}


static byte scanLevel           // SCAN MESSAGE LEVEL
    ( char const *text )        // - scanner
{
    byte retn;                  // - scanned level

    text = scanOverWS( text );
    if( *text == '\0' ) {
        scanError( "missing level" );
    }
    if( ! isdigit( *text ) ) {
        scanError( "invalid level" );
    }
    retn = (byte)( *text - '0' );
    ++text;
    if( *text != '\0' ) {
        if( ! isdigit( *text ) ) {
            scanError( "invalid level" );
        }
        retn = (byte)( retn * 10 + *text - '0' );
        ++ text;
    }
    checkEOL( text );
    return retn;
}


static void processText         // PROCESS :MSGTXT
    ( char const *text          // - scanner
    , unsigned short sym_num )  // - symbol number
{
    Word* words[50];            // - words in message
    byte word_count;            // - # words

    word_count = scanWords( text, words );
    new Msg( sym_num, word_count, words );
}


static void processSymbol       // PROCESS :MSGSYM
    ( char const *text          // - scanner
    , unsigned short grp_num    // - group number
    , unsigned short sym_num )  // - symbol number

⌨️ 快捷键说明

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