fmtscan.c

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

C
764
字号
/****************************************************************************
*
*                            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!
*
****************************************************************************/


//
// FmtScan -- Format statement scanning routines for compile and run time
//

#include "ftnstd.h"
#include "format.h"
#include "fmterr.h"
#include "fmtdef.h"
#include "fmtdat.h"

#include <ctype.h>

extern  void            FEmCode(int);
extern  void            R_FError(int);
extern  void            R_FExtension(int);
extern  void            FEmChar(char PGM *);
extern  void            FEmByte(int);
extern  void            FEmNum(int);

typedef struct f_procs {
    byte        code;
    void        (*routine)(void);
} f_procs;


void    R_FDoSpec( void ) {
//===================

// Process a complete format specification.

    FSkipSpaces();
    if( *Fmt_charptr != '(' ) {
        R_FError( PC_NO_OPENPAREN );
    } else {
        R_FSpec();
    }
    if( Fmt_paren_level != 0 ) {
        R_FError( PC_UNMATCH_PAREN );
    }
}


static  bool    R_FRecEos( void ) {
//===========================

// Attempt to recognize the end of a format string.

    FSkipSpaces();
    return( Fmt_charptr >= Fmt_end );
}


static  bool    R_FR_Char( char test_char ) {
//===========================================

// Formatted I/O character recognition.
// This routine returns TRUE if the specified character is found
// Note that the format character is in lower case when the
// comparison is performed.

    if( R_FRecEos() ) return( FALSE );
    if( tolower( *Fmt_charptr ) != test_char ) return( FALSE );
    ++Fmt_charptr;
    FSkipSpaces();
    return( TRUE );
}


static  void    R_FSpec( void ) {
//=========================

// Process a format specification.

    Fmt_delimited = YES_DELIM;
    for(;;) {
        if( R_FRecEos() ) return;
        if( R_FR_Char( ')' ) ) break;
        GetRepSpec();
        FCode();
        if( Fmt_paren_level <= 0 ) return;
    }
    --Fmt_paren_level;
    Fmt_delimited = NO_DELIM;
    FEmCode( RP_FORMAT );
}


static  int     R_FRPConst( void ) {
//============================

// Get a required positive constant in a format string.

    int result;

    result = R_FConst();
    if( result <= 0 ) {
        R_FError( FM_CONST );
    }
    return( result );
}


static  int     R_FConst( void ) {
//==========================

// Scan a non-negative constant in a format string.
//     - blanks are ignored
//     - returns -1 if no constant was found

    char        PGM *start_char;
    int         result;
    char        cur_char;

    FSkipSpaces();
    result = 0;
    start_char = Fmt_charptr;
    for(;;) {
        if( R_FRecEos() ) break;
        cur_char = *Fmt_charptr;
        if( isdigit( cur_char ) == 0 ) break;
        result *= 10;
        if( result >= 0 ) {
            result += ( cur_char - '0' );
            if( result >= 0 ) {
                ++Fmt_charptr;
                FSkipSpaces();
            } else {
                R_FError( FM_CONST );
            }
        } else {
            R_FError( FM_CONST );
        }
    }
    if( Fmt_charptr == start_char ) {
        result = -1;
    }
    return( result );
}


static  bool    R_FReqChar( char test_string, int err_code ) {
//============================================================

// Formatted I/O token scanner.
// This routine generates an error condition if the specified character
// is not found.

    if( R_FR_Char( test_string ) ) return( TRUE );
    R_FError( err_code );
    return( FALSE );
}


static  void    FSkipSpaces( void ) {
//=============================

// Skip spaces between format codes.

    for(;;) {
        if( Fmt_charptr >= Fmt_end ) break;
        if( *Fmt_charptr != ' ' ) break;
        ++Fmt_charptr;
    }
}


static  void    GetRepSpec( void ) {
//============================

// Get a possible repeat specification.

    bool        minus;

    if( ( *Fmt_charptr != '-' ) && ( *Fmt_charptr != '+' ) ) {
        Fmt_rep_spec = R_FConst();
        if( ( tolower( *Fmt_charptr ) == 'p' ) && ( Fmt_rep_spec == -1 ) ) {
            R_FError( FM_CONST );
        }
    } else {
        minus = *Fmt_charptr == '-';
        ++Fmt_charptr;
        Fmt_rep_spec = R_FConst();
        FSkipSpaces();
        if( tolower( *Fmt_charptr ) == 'p' ) {
            if( Fmt_rep_spec <= 0 ) {
                R_FError( FM_CONST );
            } else if( minus ) {
                Fmt_rep_spec = -Fmt_rep_spec;
            }
        } else {
            // set the repeat specifier so that an error will be detected
            // by a subsequent routine
            Fmt_rep_spec = 0;
        }
    }
}


static  bool    FNoRep( void ) {
//========================

// Make sure that no repeat specification was given.
// Return TRUE if no repeat spec was given.

    if( Fmt_rep_spec == -1 ) return( TRUE );
    R_FError( FM_NO_REP );
    return( FALSE );
}


static  void    R_FLiteral( void ) {
//============================

// Process a literal format code.

    int         lit_length;
    char        PGM *cur_char_ptr;

    FChkDelimiter();
    if( FNoRep() ) {
        lit_length = 0;
        cur_char_ptr = ++Fmt_charptr;
        for(;;) {
            if( *Fmt_charptr == '\'' ) {
                ++Fmt_charptr;
                if( *Fmt_charptr != '\'' ) break;
            }
            ++lit_length;
            ++Fmt_charptr;
            if( Fmt_charptr >= Fmt_end ) break;
        }
        if( Fmt_charptr >= Fmt_end ) {
            R_FError( FM_QUOTE );
        }
        if( Fmt_charptr < Fmt_end ) {
            FEmCode( H_FORMAT );
            FEmNum( lit_length );
            for(;;) {
                if( *cur_char_ptr == '\'' ) {
                    ++cur_char_ptr;
                    if( *cur_char_ptr != '\'' ) break;
                }
                FEmChar( cur_char_ptr );
                ++cur_char_ptr;
            }
        }
    }
}


static  void    R_FH( void ) {
//======================

// Process an H format code.
// Note that Fmt_rep_spec represents the desired length of
// the H format code.

    FChkDelimiter();
    if( ( Fmt_rep_spec <= 0 ) || ( Fmt_charptr + Fmt_rep_spec >= Fmt_end ) ) {
        R_FError( FM_WIDTH );
    } else {
        FEmCode( H_FORMAT );
        FEmNum( Fmt_rep_spec );
        for(;;) {
            FEmChar( Fmt_charptr );
            ++Fmt_charptr;
            if( --Fmt_rep_spec == 0 ) break;
        }
    }
}


static  void    R_FComma( void ) {
//==========================

// Process a comma format delimiter/code.

    if( FNoRep() ) {
        if( !R_FRecEos() && ( *Fmt_charptr != ',' ) &&
            ( *Fmt_charptr != ')' ) ) {
            Fmt_delimited = YES_DELIM;
        } else {
            R_FError( FM_DELIM );
        }
    }
}


static  bool    FRep( void ) {
//======================

// Validate and emit the repeat specification.
// Return TRUE if the repeat spec was valid.

    if( Fmt_rep_spec == 0 ) {
        R_FError( FM_INV_REP );
        return( FALSE );
    } else if( Fmt_rep_spec > 1 ) {
        FEmCode( REP_FORMAT );
        FEmNum( Fmt_rep_spec );
    }
    return( TRUE );
}


static  void    R_FSlash( void ) {
//==========================

// Process a slash format delimeter/code.

    if( FNoRep() ) {
        Fmt_delimited = YES_DELIM;
        Fmt_rep_spec = 0;
        for(;;) {
            ++Fmt_rep_spec;
            if( !R_FR_Char( '/' ) ) break;
        }
        FRep();
        FEmCode( SL_FORMAT );
    }
}


static  void    R_FX( void ) {
//======================

// Process an X format code.
// Note that Fmt_rep_spec represents the number of spaces
// that are desired to skipped.

    FChkDelimiter();
    if( Fmt_rep_spec == -1 ) {
        Fmt_rep_spec = 1;
        R_FExtension( FM_ASSUME_CONST );
    } else if( Fmt_rep_spec <= 0 ) {
        R_FError( FM_CONST );
    }
    FEmCode( X_FORMAT );
    FEmNum( Fmt_rep_spec );
}


static  void    R_FI( void ) {
//======================

// Process an I format code.

    int         fmt_width;
    int         fmt_min;

⌨️ 快捷键说明

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