00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "q_shared.hpp"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 static const char *punctuation[] = {
00036 "+=", "-=", "*=", "/=", "&=", "|=", "++", "--",
00037 "&&", "||", "<=", ">=", "==", "!=",
00038 NULL
00039 };
00040
00041 typedef struct {
00042 char token[MAX_TOKEN_CHARS];
00043 int lines;
00044 qboolean ungetToken;
00045 char parseFile[MAX_QPATH];
00046 } parseInfo_t;
00047
00048 #define MAX_PARSE_INFO 16
00049 static parseInfo_t parseInfo[MAX_PARSE_INFO];
00050 static int parseInfoNum;
00051 static parseInfo_t *pi = &parseInfo[0];
00052
00053
00054
00055
00056
00057
00058 void Com_BeginParseSession( const char *filename ) {
00059 if ( parseInfoNum == MAX_PARSE_INFO - 1 ) {
00060 Com_Error( ERR_FATAL, "Com_BeginParseSession: session overflow" );
00061 }
00062 parseInfoNum++;
00063 pi = &parseInfo[parseInfoNum];
00064
00065 pi->lines = 1;
00066 Q_strncpyz( pi->parseFile, filename, sizeof( pi->parseFile ) );
00067 }
00068
00069
00070
00071
00072
00073
00074 void Com_EndParseSession( void ) {
00075 if ( parseInfoNum == 0 ) {
00076 Com_Error( ERR_FATAL, "Com_EndParseSession: session underflow" );
00077 }
00078 parseInfoNum--;
00079 pi = &parseInfo[parseInfoNum];
00080 }
00081
00082
00083
00084
00085
00086
00087 int Com_GetCurrentParseLine( void ) {
00088 return pi->lines;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098 void Com_ScriptError( const char *msg, ... ) {
00099 va_list argptr;
00100 char string[32000];
00101
00102 va_start( argptr, msg );
00103 vsprintf( string, msg,argptr );
00104 va_end( argptr );
00105
00106 Com_Error( ERR_DROP, "File %s, line %i: %s", pi->parseFile, pi->lines, string );
00107 }
00108
00109 void Com_ScriptWarning( const char *msg, ... ) {
00110 va_list argptr;
00111 char string[32000];
00112
00113 va_start( argptr, msg );
00114 vsprintf( string, msg,argptr );
00115 va_end( argptr );
00116
00117 Com_Printf( "File %s, line %i: %s", pi->parseFile, pi->lines, string );
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 void Com_UngetToken( void ) {
00130 if ( pi->ungetToken ) {
00131 Com_ScriptError( "UngetToken called twice" );
00132 }
00133 pi->ungetToken = qtrue;
00134 }
00135
00136
00137 static const char *SkipWhitespace( const char (*data), qboolean *hasNewLines ) {
00138 int c;
00139
00140 while( (c = *data) <= ' ') {
00141 if( !c ) {
00142 return NULL;
00143 }
00144 if( c == '\n' ) {
00145 pi->lines++;
00146 *hasNewLines = qtrue;
00147 }
00148 data++;
00149 }
00150
00151 return data;
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 static char *Com_ParseExt( const char *(*data_p), qboolean allowLineBreaks ) {
00168 int c = 0, len;
00169 qboolean hasNewLines = qfalse;
00170 const char *data;
00171 const char **punc;
00172
00173 if ( !data_p ) {
00174 Com_Error( ERR_FATAL, "Com_ParseExt: NULL data_p" );
00175 }
00176
00177 data = *data_p;
00178 len = 0;
00179 pi->token[0] = 0;
00180
00181
00182 if ( !data ) {
00183 *data_p = NULL;
00184 return pi->token;
00185 }
00186
00187
00188 while ( 1 ) {
00189
00190 data = SkipWhitespace( data, &hasNewLines );
00191 if ( !data ) {
00192 *data_p = NULL;
00193 return pi->token;
00194 }
00195 if ( hasNewLines && !allowLineBreaks ) {
00196 *data_p = data;
00197 return pi->token;
00198 }
00199
00200 c = *data;
00201
00202
00203 if ( c == '/' && data[1] == '/' ) {
00204 while (*data && *data != '\n') {
00205 data++;
00206 }
00207 continue;
00208 }
00209
00210
00211 if ( c=='/' && data[1] == '*' ) {
00212 while ( *data && ( *data != '*' || data[1] != '/' ) ) {
00213 if( *data == '\n' ) {
00214 pi->lines++;
00215 }
00216 data++;
00217 }
00218 if ( *data ) {
00219 data += 2;
00220 }
00221 continue;
00222 }
00223
00224
00225 break;
00226 }
00227
00228
00229 if ( c == '\"' ) {
00230 data++;
00231 while( 1 ) {
00232 c = *data++;
00233 if ( ( c=='\\' ) && ( *data == '\"' ) ) {
00234
00235 data++;
00236 } else if ( c=='\"' || !c ) {
00237 pi->token[len] = 0;
00238 *data_p = ( char * ) data;
00239 return pi->token;
00240 } else if( *data == '\n' ) {
00241 pi->lines++;
00242 }
00243 if ( len < MAX_TOKEN_CHARS - 1 ) {
00244 pi->token[len] = c;
00245 len++;
00246 }
00247 }
00248 }
00249
00250
00251
00252 if ( ( c >= '0' && c <= '9' ) || ( c == '-' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) ||
00253 ( c == '.' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) ) {
00254 do {
00255
00256 if (len < MAX_TOKEN_CHARS - 1) {
00257 pi->token[len] = c;
00258 len++;
00259 }
00260 data++;
00261
00262 c = *data;
00263 } while ( ( c >= '0' && c <= '9' ) || c == '.' );
00264
00265
00266 if ( c == 'e' || c == 'E' ) {
00267 if (len < MAX_TOKEN_CHARS - 1) {
00268 pi->token[len] = c;
00269 len++;
00270 }
00271 data++;
00272 c = *data;
00273
00274 if ( c == '-' || c == '+' ) {
00275 if (len < MAX_TOKEN_CHARS - 1) {
00276 pi->token[len] = c;
00277 len++;
00278 }
00279 data++;
00280 c = *data;
00281 }
00282
00283 do {
00284 if (len < MAX_TOKEN_CHARS - 1) {
00285 pi->token[len] = c;
00286 len++;
00287 }
00288 data++;
00289
00290 c = *data;
00291 } while ( c >= '0' && c <= '9' );
00292 }
00293
00294 if (len == MAX_TOKEN_CHARS) {
00295 len = 0;
00296 }
00297 pi->token[len] = 0;
00298
00299 *data_p = ( char * ) data;
00300 return pi->token;
00301 }
00302
00303
00304
00305
00306 if ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' || c == '/' || c == '\\' ) {
00307 do {
00308 if (len < MAX_TOKEN_CHARS - 1) {
00309 pi->token[len] = c;
00310 len++;
00311 }
00312 data++;
00313
00314 c = *data;
00315 } while ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_'
00316 || ( c >= '0' && c <= '9' ) || c == '/' || c == '\\' || c == ':' || c == '.' );
00317
00318 if (len == MAX_TOKEN_CHARS) {
00319 len = 0;
00320 }
00321 pi->token[len] = 0;
00322
00323 *data_p = ( char * ) data;
00324 return pi->token;
00325 }
00326
00327
00328 for ( punc = punctuation ; *punc ; punc++ ) {
00329 int l;
00330 int j;
00331
00332 l = strlen( *punc );
00333 for ( j = 0 ; j < l ; j++ ) {
00334 if ( data[j] != (*punc)[j] ) {
00335 break;
00336 }
00337 }
00338 if ( j == l ) {
00339
00340 memcpy( pi->token, *punc, l );
00341 pi->token[l] = 0;
00342 data += l;
00343 *data_p = (char *)data;
00344 return pi->token;
00345 }
00346 }
00347
00348
00349 pi->token[0] = *data;
00350 pi->token[1] = 0;
00351 data++;
00352 *data_p = (char *)data;
00353
00354 return pi->token;
00355 }
00356
00357
00358
00359
00360
00361
00362 const char *Com_Parse( const char *(*data_p) ) {
00363 if ( pi->ungetToken ) {
00364 pi->ungetToken = qfalse;
00365 return pi->token;
00366 }
00367 return Com_ParseExt( data_p, qtrue );
00368 }
00369
00370
00371
00372
00373
00374
00375 const char *Com_ParseOnLine( const char *(*data_p) ) {
00376 if ( pi->ungetToken ) {
00377 pi->ungetToken = qfalse;
00378 return pi->token;
00379 }
00380 return Com_ParseExt( data_p, qfalse );
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390 void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning ) {
00391 const char *token;
00392
00393 token = Com_Parse( buf_p );
00394 if ( strcmp( token, match ) ) {
00395 if (warning) {
00396 Com_ScriptWarning( "MatchToken: %s != %s", token, match );
00397 } else {
00398 Com_ScriptError( "MatchToken: %s != %s", token, match );
00399 }
00400 }
00401 }
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 void Com_SkipBracedSection( const char *(*program) ) {
00414 const char *token;
00415 int depth;
00416
00417 depth = 0;
00418 do {
00419 token = Com_Parse( program );
00420 if( token[1] == 0 ) {
00421 if( token[0] == '{' ) {
00422 depth++;
00423 }
00424 else if( token[0] == '}' ) {
00425 depth--;
00426 }
00427 }
00428 } while( depth && *program );
00429 }
00430
00431
00432
00433
00434
00435
00436 void Com_SkipRestOfLine ( const char *(*data) ) {
00437 const char *p;
00438 int c;
00439
00440 p = *data;
00441 while ( (c = *p++) != 0 ) {
00442 if ( c == '\n' ) {
00443 pi->lines++;
00444 break;
00445 }
00446 }
00447
00448 *data = p;
00449 }
00450
00451
00452
00453
00454
00455
00456 const char *Com_ParseRestOfLine( const char *(*data_p) ) {
00457 static char line[MAX_TOKEN_CHARS];
00458 const char *token;
00459
00460 line[0] = 0;
00461 while( 1 ) {
00462 token = Com_ParseOnLine( data_p );
00463 if ( !token[0] ) {
00464 break;
00465 }
00466 if ( line[0] ) {
00467 Q_strcat( line, sizeof(line), " " );
00468 }
00469 Q_strcat( line, sizeof(line), token );
00470 }
00471
00472 return line;
00473 }
00474
00475
00476 float Com_ParseFloat( const char *(*buf_p) ) {
00477 const char *token;
00478
00479 token = Com_Parse( buf_p );
00480 if ( !token[0] ) {
00481 return 0;
00482 }
00483 return atof( token );
00484 }
00485
00486 int Com_ParseInt( const char *(*buf_p) ) {
00487 const char *token;
00488
00489 token = Com_Parse( buf_p );
00490 if ( !token[0] ) {
00491 return 0;
00492 }
00493 return atoi( token );
00494 }
00495
00496
00497
00498 void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m ) {
00499 const char *token;
00500 int i;
00501
00502 Com_MatchToken( buf_p, "(" );
00503
00504 for (i = 0 ; i < x ; i++) {
00505 token = Com_Parse(buf_p);
00506 m[i] = atof(token);
00507 }
00508
00509 Com_MatchToken( buf_p, ")" );
00510 }
00511
00512 void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m ) {
00513 int i;
00514
00515 Com_MatchToken( buf_p, "(" );
00516
00517 for (i = 0 ; i < y ; i++) {
00518 Com_Parse1DMatrix (buf_p, x, m + i * x);
00519 }
00520
00521 Com_MatchToken( buf_p, ")" );
00522 }
00523
00524 void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m ) {
00525 int i;
00526
00527 Com_MatchToken( buf_p, "(" );
00528
00529 for (i = 0 ; i < z ; i++) {
00530 Com_Parse2DMatrix (buf_p, y, x, m + i * x*y);
00531 }
00532
00533 Com_MatchToken( buf_p, ")" );
00534 }
00535