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