home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
REND.LZH
/
READER
/
SCANNER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-23
|
13KB
|
770 lines
/*
トークンの切り出し関数
Copyright T.Kobayashi
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#if defined(X68000) || defined(MSC) || defined(__BORLANDC__)
#include <conio.h>
#endif
#ifdef MSC
#include <search.h>
#endif
#define SCANNER
#include "reader.h"
#include "word.h"
#if defined(DJ) || defined(MSC) || defined(__BORLANDC__)
#define LINEARSEARCH
#endif
#define OLD_FASION 1
#define NOT_NUMBER 11
#define NOT_COLOR 12
#define BAD_MATRIX 13
#define BAD_ARGS 14
#define NAME_TOO_LONG 15
#define NAME_WRONG 16
#define BAD_EXIST 17
#define NOT_FOUND 18
#define UNEXPECTED_EOF 21
#define FILE_NOT_OPEN 22
#define GET_ESC 23
#define ESC 0x1B
static char *words[] = {
"amb",
"atr",
"att",
"back",
"blu",
"bumpmap",
"cmp",
"col",
"colormap",
"cst",
"deg",
"depth",
"dif",
"dst",
"env",
"eye",
"fram",
"frm",
"glad",
"hsv",
"image",
"len",
"light",
"map",
"mapsize",
"mapview",
"mapwind",
"mat",
"mod",
"mov",
"msk",
"non",
"obj",
"opt",
"pal",
"parts",
"plt",
"pnt",
"point",
"poly",
"prim",
"private",
"pxn",
"pxs",
"red",
"ref",
"rfr",
"rgb",
"rln",
"rotx",
"roty",
"rotz",
"scal",
"scr",
"shade",
"spc",
"spot",
"star",
"stop",
"suf",
"target",
"tra",
"trp",
"uvpoly",
"uvshade",
"vec"
};
int FileLine ; /* 行番号 */
/*char FileName[MAXWORD] ;*/
char FileName[F_NAME_LEN] ; /* ファイルネーム */
char nextword[F_NAME_LEN] ; /* 次のワード */
int wordid ; /* 予約語のid */
int errcount ; /* エラーの数 */
int errlevel ; /* エラーレベル
0 : Nomal
1 - 9 : Warning
10 - 19 : Error
20 - 29 : Fatal
*/
int warninglevel = 1 ; /* 警告レベル */
int end_of_file ; /* エンドオブファイル */
#ifdef WINDOWS
FILE *errfp = NULL; /* エラー出力ファイル */
#else
FILE *errfp = stdout ; /* エラー出力ファイル */
#endif
Float minscale = 1e-10 ; /* 最小の正数 */
/* By Taka2 */
void (*interrupt)(void); /* 割り込みルーチン */
/* By Taka2 */
void (*errorexec)(int) = exit ; /* エラー処理ルーチン */
int virtualmode ; /* 仮想記憶モード */
#if 0
#ifndef DJ
#ifdef GCC
register int virtualmode asm( "d7" ); /* 仮想記憶モード */
#else
int virtualmode ; /* 仮想記憶モード */
#endif
#else
int virtualmode ; /* 仮想記憶モード */
#endif
#endif
static FILE *fp ;
static int open1 ; /* ( ) の検出 */
static int comment( void );
static int isword( int );
#ifndef LINEARSEARCH
static int comp( char**, char** );
#endif
static Float frgb( Float , Float , Float );
static void hsvtorgb( Float[ 3 ] , Float[ 3 ] );
static int isname( char* );
static void error( int, char* );
#ifndef BUFFERING
#define scangetc(fp) getc(fp)
#define scanungetc(c,fp) ungetc(c,fp)
#else
#define SCANBUFFERSIZE 16384
static char scanbuffer[SCANBUFFERSIZE+1], *scanpointer;
static int scancounter, scanendflag;
static inline int scangetc(fp)
FILE *fp;
{
if (scancounter == 0) {
if (scanendflag) {
return EOF;
}
scanpointer = scanbuffer+1;
scancounter = fread(scanpointer, 1, SCANBUFFERSIZE, fp);
if (scancounter != SCANBUFFERSIZE) {
scanendflag = TRUE;
}
}
if (*scanpointer == 0x1a) {
return EOF;
}
scancounter--;
return *scanpointer++;
}
static inline void scanungetc(ch, fp)
int ch;
FILE *fp;
{
scancounter++;
*--scanpointer = ch;
}
#endif
#undef isspace
static inline int isspace(int c)
{
return 0 <= c && c <= 32;
}
/*
ファイルのオープン
戻り値 1:正常
0:エラー
*/
int fileopen( name )
char *name ;
{
fp = fopen( name, "rb" );
FileLine = 1 ;
strcpy( FileName, name );
if ( fp == NULL )
{
error( FILE_NOT_OPEN, name );
strcpy( FileName, "" );
return( 0 ) ;
}
end_of_file = 0 ;
errlevel = 0 ;
errcount = 0 ;
#ifdef BUFFERING
scancounter = 0;
scanendflag = FALSE;
#endif
get() ;
return( 1 );
}
void fileclose()
{
fclose( fp );
strcpy( FileName, "" );
}
/* コメントの削除 */
static int comment()
{
int ch ;
ch = scangetc( fp );
do {
while ( isspace( ch ) )
{
if ( ch == '\n' )
FileLine++;
ch = scangetc( fp );
}
if ( ch == '/' ) {
ch = scangetc( fp );
if ( ch != '*' )
{
scanungetc( ch, fp );
return( '/' );
}
for(;;)
{
do {
ch = scangetc( fp );
if ( ch == '\n' )
FileLine++;
if ( ch == EOF )
error( UNEXPECTED_EOF, "" );
} while ( ch != '*' );
if ( (ch = scangetc( fp )) == '/' )
{
ch = scangetc( fp );
break;
}
else
scanungetc( ch, fp );
}
}
} while ( isspace( ch ) );
return( ch );
}
static int isword( c )
int c ;
{
return( isalnum( c ) || c == '_' || c == '.' || c == '+' || c == '-' || c == '\\' || c == ':');
}
#ifdef LINEARSEARCH
char **linearsearch(char *key, char **words, int count)
{
for (;count > 0;--count, words++) {
if (*key == **words) {
if (strcmp(key, *words) == 0) {
return words;
}
}
}
return NULL;
}
#endif
/* トークンの切り出し */
void get()
{
int ch, count, i, n ;
char *p, *str, **wp ;
#ifndef WINDOWS
if ( interrupt != NULL )
(*interrupt)();
#endif
if ( end_of_file )
{
error( UNEXPECTED_EOF, "" );
return ;
}
ch = comment();
if ( ch == EOF )
{
end_of_file = 1 ;
return ;
}
count = 0 ;
if ( isword( ch ) )
{
while ( ch != EOF && isword( ch ) && count < MAXWORD-1 )
{
nextword[count] = (char)ch;
count ++;
ch = scangetc( fp );
}
}
nextword[count] = '\0';
if ( strcmp( nextword, "" ) == 0 )
{
nextword[0] = (char )ch ;
nextword[1] = '\0' ;
}
else
scanungetc( ch, fp );
/* かっこのチェック */
str = "(){}" ;
p = strchr( str, nextword[0] ) ;
if ( p != NULL )
{
wordid = 200 + (int)(p - str) ;
return ;
}
/* 数字のチェック */
n = strlen( nextword );
for( i = 0 ; i < n ; ++i )
{
p = strchr( "0123456789.-+Ee", nextword[i] );
if ( p == NULL )
break ;
}
if ( i == n )
{
wordid = WORD_NUM ;
return ;
}
/* 予約語のチェック */
p = nextword ;
#ifdef LINEARSEARCH
wp = linearsearch(p, words, WORDS);
#else
wp = (char**)bsearch( (char*)&p, (char*)words, WORDS, sizeof(char*), (int (*)(void*,void*))comp);
#endif
if ( wp == NULL )
wordid = WORD_NAME ;
else
wordid = (int)(wp - words) ;
return ;
}
#ifndef LINEARSEARCH
/* 比較関数 */
static int comp( a1, a2 )
char **a1, **a2 ;
{
return( strcmp( *a1, *a2 ) );
}
#endif
/* 数字の読み込み */
int getint()
{
int n ;
if ( wordid != WORD_NUM )
{
error( NOT_NUMBER, "" );
get() ;
return( 0 );
}
n = atoi( nextword );
get() ;
return( n );
}
/* 数字の読み込み */
Float getFloat()
{
Float w ;
if ( wordid != WORD_NUM )
{
error( NOT_NUMBER, "" );
get() ;
return( 0.0 );
}
w = atof( nextword );
get() ;
return( w );
}
/* カラーの読み込み */
int getcolor( col )
Color col ;
{
Vector v, v2 ;
switch( wordid )
{
case WORD_RGB :
isopen1() ;
getvector( v );
vtoc( col, v );
isclose1() ;
return( TRUE );
case WORD_HSV :
isopen1() ;
getvector( v );
hsvtorgb( v2, v );
vtoc( col, v2 );
isclose1() ;
return( TRUE );
case WORD_NUM :
v[0] = v[1] = v[2] = atof( nextword );
vtoc( col, v );
get() ;
return( FALSE );
default :
error( NOT_COLOR, "" );
}
return FALSE;
}
static Float frgb( Float h , Float m1 , Float m2 )
{
if( h < 0.0 )
h = h + 1.0 ;
if( h > 1.0 )
h = h - 1.0 ;
if( h < 1.0 / 6.0 )
return m1 + ( m2 - m1 ) * h * 6.0 ;
if( ( h >= 1.0 / 6.0 ) && ( h < 1.0 / 2.0 ) )
return m2 ;
if( ( h >= 1.0 / 2.0 ) && ( h < 2.0 / 3.0 ) )
return m1 + ( m2 - m1 ) * ( 2.0 / 3.0 - h ) * 6.0 ;
if( ( h >= 2.0 / 3.0 ) && ( h <= 1.0 ) )
return m1 ;
return 0.0;
}
static void hsvtorgb( rgb, hsv )
Float hsv[ 3 ] , rgb[ 3 ] ;
{
Float m1 , m2 ;
if( hsv[ 2 ] <= 0.5 )
m2 = hsv[ 2 ] * ( 1 + hsv[ 1 ] ) ;
else
m2 = hsv[ 2 ] + hsv[ 1 ] - hsv[ 2 ] * hsv[ 1 ] ;
m1 = 2 * hsv[ 2 ] - m2 ;
if( hsv[ 1 ] == 0.0 )
{
rgb[ 0 ] = hsv[ 2 ] ;
rgb[ 1 ] = hsv[ 2 ] ;
rgb[ 2 ] = hsv[ 2 ] ;
}
else
{
rgb[ 0 ] = frgb( hsv[ 0 ] + 1.0 / 3.0 , m1 , m2 ) ;
rgb[ 1 ] = frgb( hsv[ 0 ] , m1 , m2 ) ;
rgb[ 2 ] = frgb( hsv[ 0 ] - 1.0 / 3.0 , m1 , m2 ) ;
}
}
/* ベクトルの読み込み */
void getvector( v )
Vector v ;
{
v[0] = getFloat() ;
v[1] = getFloat() ;
v[2] = getFloat() ;
}
/* 名前の読み込み */
void getname( name )
char *name ;
{
if ( strlen( nextword ) > MAXWORD - 1 )
error( NAME_TOO_LONG, nextword );
else if ( ! isname( nextword ) )
error( NAME_WRONG, nextword );
else
strcpy( name, nextword );
get() ;
if ( wordid == WORD_OPEN1 )
{
error( BAD_ARGS, "" );
skip( ")" );
}
}
/* ファイル名の読み込み */
void getfilename( name )
char *name ;
{
if ( strlen( nextword ) > F_NAME_LEN - 1 )
error( NAME_TOO_LONG, nextword );
else
strcpy( name, nextword );
get() ;
if ( wordid == WORD_OPEN1 )
{
error( BAD_ARGS, "" );
skip( ")" );
}
}
void skip( name )
char *name ;
{
do
{
get() ;
}
while( strcmp( nextword, name ) != 0 ) ;
get() ;
}
/* 移動指定の読み込み */
void getmat( m )
Matrix m ;
{
int i, j ;
Vector xv, zv, v ;
Matrix mm ;
m_unit( m );
switch( wordid )
{
case WORD_MOV :
isopen1() ;
getvector( v );
m_mov( m, v );
break ;
case WORD_ROTX :
isopen1() ;
m_rot( m, 0, getFloat() );
break ;
case WORD_ROTY :
isopen1() ;
m_rot( m, 1, getFloat() );
break ;
case WORD_ROTZ :
isopen1() ;
m_rot( m, 2, getFloat() );
break ;
case WORD_SCAL :
isopen1() ;
getvector( v );
m_scal( m, v );
break ;
case WORD_VEC :
isopen1() ;
getvector( xv ) ;
getvector( zv ) ;
m_vec( m, xv, zv );
break ;
case WORD_MAT :
isopen1() ;
for( i = 0 ; i < 4 ; ++i )
for( j = 0 ; j < 4 ; ++j )
m[i][j] = getFloat() ;
break ;
default :
error( BAD_EXIST, nextword );
get() ;
return ;
}
if ( m_inv( mm, m ) == 0 ) /* 逆行列ができない。 */
error( BAD_MATRIX, "" );
isclose1() ;
}
/* "(" の検出 */
void isopen1()
{
get() ;
if ( wordid == WORD_OPEN1 )
{
get() ;
open1 = 1 ;
}
else
{
error( OLD_FASION, "( がない。" );
open1 = 0 ;
}
}
/* ")"の検出 */
void isclose1()
{
if ( open1 )
{
if ( wordid != WORD_CLOSE1 )
error( NOT_FOUND, ")" );
else
get() ;
}
}
static int isname( name )
char *name ;
{
if ( ! ( isalpha( *name ) || *name == '_' ) )
return( 0 ) ;
while( *(++name) != '\0' )
if ( ! ( isalnum( *name ) || *name == '_' || *name == '.' ) )
return( 0 );
return( 1 );
}
static void error( n, str )
int n ;
char *str ;
{
char *msg ;
int level ;
switch( n )
{
case OLD_FASION :
msg = "警告:古い規格の書式です。:%s" ;
level = 1 ;
break ;
case NOT_NUMBER :
msg = "数字が必要です。" ;
level = 10 ;
break ;
case NOT_COLOR :
msg = "色情報がおかしい。" ;
level = 10 ;
break ;
case BAD_MATRIX :
msg = "座標変換指定がおかしい。" ;
level = 10 ;
break ;
case BAD_ARGS :
msg = "引数の処理はできません。" ;
level = 10 ;
break ;
case NAME_TOO_LONG :
msg = "名前(%s)が長すぎます。(31文字まで)" ;
level = 10 ;
break ;
case NAME_WRONG :
msg = "名前(%s)がおかしい" ;
level = 10 ;
break ;
case BAD_EXIST :
msg = " %s が存在します。" ;
level = 10 ;
break ;
case NOT_FOUND :
msg = " %s がありません。" ;
level = 10 ;
break ;
case UNEXPECTED_EOF :
msg = "エンドオブファイルになりました。" ;
level = 20 ;
break ;
case FILE_NOT_OPEN :
msg = "ファイル %s がオープンできません。" ;
level = 20 ;
break ;
case GET_ESC :
msg = " ESC キーが押されました。" ;
level = 20 ;
break ;
default :
msg = "エラーコードの誤り。( scanner.c )" ;
level = 20 ;
break ;
} ;
errormessage( level, msg, str );
}
void errormessage( level, msg, str )
int level ;
char *msg, *str ;
{
if (errfp == NULL) errfp = stdout;
if ( errlevel < level )
errlevel = level ;
if ( level >= warninglevel )
{
fprintf( errfp, "%-15s%3d : ", FileName, FileLine );
fprintf( errfp, msg, str );
fprintf( errfp, "\n" );
}
if ( level >= 10 )
++ errcount ;
#ifdef MESSAGE
if (level >= 20) {
extern int printwarning(const char *format, ...);
char fmt[256];
strcpy(fmt, "%-15s%3d : ");
strcat(fmt, msg);
printwarning( fmt, FileName, FileLine, str);
}
#endif
if ( errcount >= 100 )
{
#ifdef MESSAGE
extern int printwarning(const char *format, ...);
printwarning( "エラーの数が100を越えました。中止します。");
#endif
fprintf( errfp,
"エラーの数が100を越えました。中止します。\n" );
level = 20 ;
}
if ( level >= 20 ) {
(*errorexec)( level );
}
}