home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
POLYEDIT.LZH
/
READER
/
RSCANNER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-12
|
13KB
|
737 lines
/*
トークンの切り出し関数
Copyright T.Kobayashi
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <sys/stat.h>
#include "assert.h"
#define SCANNER
#include "lib.h"
#include "_reader.h"
#include "word.h"
#include "inlib.h"
#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 NO_MEMORY 24
#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 nextword[MAXWORD] ; /* 次のワード */
int wordid ; /* 予約語のid */
int end_of_file ; /* エンドオブファイル */
double minscale = 1e-10 ; /* 最小の正数 */
void (*interrupt)(void) = NULL ; /* 割り込みルーチン */
int lasterror; /* 発生エラーレベル */
/*static int NextChar ; /* 次の一文字 */
static FILE *fp = NULL ; /* ファイルハンドル */
static char *FileBuf; /* 読み込みバッファ */
static char *FilePtr, *FileLast;
static int GetChar( void );
static void UnGetChar( int );
static int comment( void );
static int isword( int );
static int comp( const char**, const char** );
static double frgb( double , double , double );
static void hsvtorgb( double[3] );
static int isname( char* );
static void error( int, const char* );
#define static
/*
ファイルのオープン
戻り値 1:正常
0:エラー
*/
int fileopen( name )
const char *name ;
{
struct stat sbuf ;
int size;
if ( fp != NULL )
fclose( fp );
fp = fopen( name, "r" );
if ( fp == NULL )
{
error( FILE_NOT_OPEN, name );
return FALSE ;
}
stat( name, &sbuf );
if ((FileBuf = malloc( sbuf.st_size + 1 )) == NULL) {
error( NO_MEMORY, "形状読み込み" );
return FALSE;
}
size = fread( FileBuf, 1, sbuf.st_size, fp );
if ( size > sbuf.st_size )
{
error( NO_MEMORY, "形状読み込み" );
return FALSE;
}
FilePtr = FileBuf;
FileLast = FileBuf + size;
FileBuf[size] = FileBuf[size-1];
FileLine = 1 ;
/* NextChar = 0 ;*/
strcpy( FileName, name );
end_of_file = 0 ;
get();
return TRUE ;
}
void fileclose()
{
strcpy( FileName, "" );
if ( fp != NULL )
fclose( fp );
fp = NULL ;
if (FileBuf != NULL)
free(FileBuf);
FileBuf = NULL;
}
#ifndef __GNUC__
#define inline
#endif
/* 1文字入力 */
static inline int GetChar()
{
int c ;
#if 0
if ( NextChar == 0 )
c = fgetc( fp );
else
{
c = NextChar ;
NextChar = 0 ;
}
#else
if ( FilePtr == FileLast )
return EOF ;
c = *FilePtr++ ;
/*
if ( c == '\n' )
FileLine ++ ;
*/
#endif
return c ;
}
#if 0
static inline void UnGetChar( c )
int c ;
{
#if 0
assert( NextChar == 0 );
NextChar = c ;
#else
*--FilePtr = c;
#endif
}
#else
#define UnGetChar(c) (FilePtr--)
#endif
/* コメントの削除 */
static int comment()
{
int ch ;
ch = GetChar();
do {
while ( isspace( ch ) )
{
if ( ch == '\n' )
FileLine++;
ch = GetChar();
}
if ( ch == '/' ) {
ch = GetChar();
if ( ch != '*' )
{
UnGetChar( ch );
return( '/' );
}
for(;;)
{
do {
ch = GetChar();
if ( ch == '\n' )
FileLine++;
if ( ch == EOF )
error( UNEXPECTED_EOF, "" );
} while ( ch != '*' );
if ( (ch = GetChar() ) == '/' )
{
ch = GetChar();
break;
}
else
UnGetChar( ch );
}
}
} while ( isspace( ch ) );
return( ch );
}
static inline int isword( c )
int c ;
{
return( isalnum( c ) || c == '_' || c == '.' || c == '+' || c == '-' );
}
/* トークンの切り出し */
void get()
{
int ch, count, i, n ;
char *p, *str, **wp ;
#if 0
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 ;
n = TRUE;
while ( ch != EOF && isword( ch ) && count < MAXWORD-1 )
{
nextword[count] = (char)ch;
if ((isalpha(ch) && ch != 'E' && ch != 'e') || ch == '_') {
n = FALSE;
}
count ++;
ch = GetChar();
}
nextword[count] = '\0';
if ( count == 0 )
{
count = 1;
nextword[0] = (char )ch ;
nextword[1] = '\0' ;
if (nextword[0] == '(') {wordid = 200; return; }
if (nextword[0] == ')') {wordid = 201; return; }
if (nextword[0] == '{') {wordid = 202; return; }
if (nextword[0] == '}') {wordid = 203; return; }
}
else
UnGetChar( ch );
/* かっこのチェック */
#if 0
str = "(){}" ;
p = strchr( str, nextword[0] ) ;
if ( p != NULL )
{
wordid = 200 + p - str ;
return ;
}
#endif
/* 数字のチェック */
#if 0
#if 0
n = strlen( nextword );
#else
n = count;
#endif
for( i = 0 ; i < n ; ++i )
{
#if 0
p = strchr( "0123456789.-+Ee", nextword[i] );
if ( p == NULL )
break ;
#else
if ((nextword[i] < '0' || '9' < nextword[i])
&& nextword[i] != '.' && nextword[i] != '-' && nextword[i] != '+'
&& nextword[i] != 'E' && nextword[i] != 'e') {
break;
}
#endif
}
if ( i == n )
{
wordid = WORD_NUM ;
return ;
}
#else
if (n != FALSE) {
wordid = WORD_NUM ;
return ;
}
#endif
/* 予約語のチェック */
p = nextword ;
wp = (char**)bsearch( (char*)&p, (char*)words, WORDS, sizeof(char*),
(int(*)( const void*, const void *))comp );
if ( wp == NULL )
wordid = WORD_NAME ;
else
wordid = wp - words ;
return ;
}
/* 比較関数 */
static int comp( a1, a2 )
const char **a1, **a2 ;
{
return( strcmp( *a1, *a2 ) );
}
/* 数字の読み込み */
int getint()
{
int n ;
if ( wordid != WORD_NUM )
{
error( NOT_NUMBER, "" );
get() ;
return( 0 );
}
n = atoi( nextword );
get() ;
return( n );
}
/* 数字の読み込み */
double getdouble()
{
double w ;
if ( wordid != WORD_NUM )
{
error( NOT_NUMBER, "" );
get() ;
return( 0.0 );
}
w = atof( nextword );
get() ;
return( w );
}
/* 数字の読み込み */
float getfloat()
{
float w ;
if ( wordid != WORD_NUM )
{
error( NOT_NUMBER, "" );
get() ;
return( 0.0 );
}
w = (float)atof( nextword );
get() ;
return( w );
}
/* 色の読み込み */
int getcolor( col )
Color *col ;
{
int ret ;
double rgb[3] ;
switch( wordid )
{
case WORD_RGB :
case WORD_HSV :
isopen1() ;
rgb[0] = getdouble();
rgb[1] = getdouble();
rgb[2] = getdouble();
if ( wordid == WORD_HSV )
hsvtorgb( rgb );
isclose1() ;
ret = TRUE ;
break ;
case WORD_NUM :
rgb[0] = rgb[1] = rgb[2] = atof( nextword );
get() ;
ret = TRUE;
break ;
default :
error( NOT_COLOR, "" );
return FALSE ;
}
col->r = (int)( rgb[0] * (double)(1<<COLOR_SHIFT) );
col->g = (int)( rgb[1] * (double)(1<<COLOR_SHIFT) );
col->b = (int)( rgb[2] * (double)(1<<COLOR_SHIFT) );
return ret ;
}
static double frgb( h , m1 , m2 )
double h , m1 , 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 ;
else if ( h < 1.0 / 2.0 )
return m2 ;
else if ( h < 2.0 / 3.0 )
return m1 + ( m2 - m1 ) * ( 2.0 / 3.0 - h ) * 6.0 ;
else if ( h <= 1.0 )
return m1 ;
else
return m1 ;
}
static void hsvtorgb( hsv )
double hsv[3] ;
{
double m1 , m2, h ;
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 ;
h = hsv[ 0 ] ;
if( hsv[ 1 ] == 0.0 )
{
hsv[ 0 ] = hsv[ 2 ] ;
hsv[ 1 ] = hsv[ 2 ] ;
hsv[ 2 ] = hsv[ 2 ] ;
}
else
{
hsv[ 0 ] = frgb( h + 1.0 / 3.0 , m1 , m2 ) ;
hsv[ 1 ] = frgb( h, m1 , m2 ) ;
hsv[ 2 ] = frgb( h - 1.0 / 3.0 , m1 , m2 ) ;
}
}
/* 名前の読み込み */
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 skip( name )
char *name ;
{
do
{
get() ;
if (lasterror) return;
}
while( strcmp( nextword, name ) != 0 ) ;
get() ;
}
/* 移動指定の読み込み */
void getmat( m )
Matrix m ;
{
int i, j, id ;
double x, y, z ;
Matrix mm ;
id = wordid ;
isopen1() ;
switch( id )
{
case WORD_MOV :
x = getdouble();
y = getdouble();
z = getdouble();
MatMove( m, x, y, z );
break ;
case WORD_ROTX :
MatRot( m, RotX, getdouble() );
break ;
case WORD_ROTY :
MatRot( m, RotY, getdouble() );
break ;
case WORD_ROTZ :
MatRot( m, RotZ, getdouble() );
break ;
case WORD_SCAL :
x = getdouble();
y = getdouble();
z = getdouble();
MatScale( m, x, y, z );
break ;
case WORD_MAT :
for( i = 0 ; i < 4 ; ++i )
{
for( j = 0 ; j < 3 ; ++j )
mm[i][j] = getdouble() ;
getdouble() ;
}
MatMult( m, mm, m );
break ;
default :
error( BAD_EXIST, nextword );
get() ;
return ;
}
MatCopy( mm, m );
if ( MatInv( mm ) == 0 ) /* 逆行列ができない。 */
error( BAD_MATRIX, "" );
isclose1() ;
}
/* "(" の検出 */
void isopen1()
{
get() ;
if ( wordid == WORD_OPEN1 )
get() ;
else
error( NOT_FOUND, "(" );
}
/* ")"の検出 */
void isclose1()
{
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 ;
const char *str ;
{
char *msg ;
int level ;
switch( n )
{
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 ;
case NO_MEMORY :
msg = "メモリが足りません。";
level = 20;
break;
default :
msg = "エラーコードの誤り。( scanner.c )" ;
level = 20 ;
break ;
} ;
errormessage( level, msg, str );
}
void errormessage( level, msg, str )
int level ;
const char *msg, *str ;
{
char fmt[256], buf[256] ;
#if 1
sprintf( fmt, "%s%3d : %s next token=%s", FileName, FileLine, msg, nextword );
sprintf( buf, fmt, str );
#endif
#if 0
if ( level < 10 )
MessageWarning( buf );
else
MessageError( buf );
#else
MessageWarning( buf );
#endif
lasterror = level;
}
int ReaderError(void)
{
return lasterror >= 10;
}