00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifdef SCREWUP
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <limits.h>
00041 #include <string.h>
00042 #include <stdarg.h>
00043 #include "l_memory.h"
00044 #include "l_script.h"
00045
00046 typedef enum {qfalse, qtrue} qboolean;
00047
00048 #endif //SCREWUP
00049
00050 #ifdef BOTLIB
00051
00052 #include "../game/q_shared.h"
00053 #include "../game/botlib.h"
00054 #include "be_interface.h"
00055 #include "l_script.h"
00056 #include "l_memory.h"
00057 #include "l_log.h"
00058 #include "l_libvar.h"
00059 #endif //BOTLIB
00060
00061 #ifdef MEQCC
00062
00063 #include "qcc.h"
00064 #include "l_script.h"
00065 #include "l_memory.h"
00066 #include "l_log.h"
00067
00068 #define qtrue true
00069 #define qfalse false
00070 #endif //MEQCC
00071
00072 #ifdef BSPC
00073
00074 #include "../bspc/qbsp.h"
00075 #include "../bspc/l_log.h"
00076 #include "../bspc/l_mem.h"
00077
00078 #define qtrue true
00079 #define qfalse false
00080 #endif //BSPC
00081
00082
00083 #define PUNCTABLE
00084
00085
00086 punctuation_t default_punctuations[] =
00087 {
00088
00089 {">>=",P_RSHIFT_ASSIGN, NULL},
00090 {"<<=",P_LSHIFT_ASSIGN, NULL},
00091
00092 {"...",P_PARMS, NULL},
00093
00094 {"##",P_PRECOMPMERGE, NULL},
00095
00096 {"&&",P_LOGIC_AND, NULL},
00097 {"||",P_LOGIC_OR, NULL},
00098 {">=",P_LOGIC_GEQ, NULL},
00099 {"<=",P_LOGIC_LEQ, NULL},
00100 {"==",P_LOGIC_EQ, NULL},
00101 {"!=",P_LOGIC_UNEQ, NULL},
00102
00103 {"*=",P_MUL_ASSIGN, NULL},
00104 {"/=",P_DIV_ASSIGN, NULL},
00105 {"%=",P_MOD_ASSIGN, NULL},
00106 {"+=",P_ADD_ASSIGN, NULL},
00107 {"-=",P_SUB_ASSIGN, NULL},
00108 {"++",P_INC, NULL},
00109 {"--",P_DEC, NULL},
00110
00111 {"&=",P_BIN_AND_ASSIGN, NULL},
00112 {"|=",P_BIN_OR_ASSIGN, NULL},
00113 {"^=",P_BIN_XOR_ASSIGN, NULL},
00114 {">>",P_RSHIFT, NULL},
00115 {"<<",P_LSHIFT, NULL},
00116
00117 {"->",P_POINTERREF, NULL},
00118
00119 {"::",P_CPP1, NULL},
00120 {".*",P_CPP2, NULL},
00121
00122 {"*",P_MUL, NULL},
00123 {"/",P_DIV, NULL},
00124 {"%",P_MOD, NULL},
00125 {"+",P_ADD, NULL},
00126 {"-",P_SUB, NULL},
00127 {"=",P_ASSIGN, NULL},
00128
00129 {"&",P_BIN_AND, NULL},
00130 {"|",P_BIN_OR, NULL},
00131 {"^",P_BIN_XOR, NULL},
00132 {"~",P_BIN_NOT, NULL},
00133
00134 {"!",P_LOGIC_NOT, NULL},
00135 {">",P_LOGIC_GREATER, NULL},
00136 {"<",P_LOGIC_LESS, NULL},
00137
00138 {".",P_REF, NULL},
00139
00140 {",",P_COMMA, NULL},
00141 {";",P_SEMICOLON, NULL},
00142
00143 {":",P_COLON, NULL},
00144
00145 {"?",P_QUESTIONMARK, NULL},
00146
00147 {"(",P_PARENTHESESOPEN, NULL},
00148 {")",P_PARENTHESESCLOSE, NULL},
00149 {"{",P_BRACEOPEN, NULL},
00150 {"}",P_BRACECLOSE, NULL},
00151 {"[",P_SQBRACKETOPEN, NULL},
00152 {"]",P_SQBRACKETCLOSE, NULL},
00153
00154 {"\\",P_BACKSLASH, NULL},
00155
00156 {"#",P_PRECOMP, NULL},
00157 #ifdef DOLLAR
00158 {"$",P_DOLLAR, NULL},
00159 #endif //DOLLAR
00160 {NULL, 0}
00161 };
00162
00163 #ifdef BSPC
00164 char basefolder[MAX_PATH];
00165 #else
00166 char basefolder[MAX_QPATH];
00167 #endif
00168
00169
00170
00171
00172
00173
00174
00175 void PS_CreatePunctuationTable(script_t *script, punctuation_t *punctuations)
00176 {
00177 int i;
00178 punctuation_t *p, *lastp, *newp;
00179
00180
00181 if (!script->punctuationtable) script->punctuationtable = (punctuation_t **)
00182 GetMemory(256 * sizeof(punctuation_t *));
00183 Com_Memset(script->punctuationtable, 0, 256 * sizeof(punctuation_t *));
00184
00185 for (i = 0; punctuations[i].p; i++)
00186 {
00187 newp = &punctuations[i];
00188 lastp = NULL;
00189
00190 for (p = script->punctuationtable[(unsigned int) newp->p[0]]; p; p = p->next)
00191 {
00192 if (strlen(p->p) < strlen(newp->p))
00193 {
00194 newp->next = p;
00195 if (lastp) lastp->next = newp;
00196 else script->punctuationtable[(unsigned int) newp->p[0]] = newp;
00197 break;
00198 }
00199 lastp = p;
00200 }
00201 if (!p)
00202 {
00203 newp->next = NULL;
00204 if (lastp) lastp->next = newp;
00205 else script->punctuationtable[(unsigned int) newp->p[0]] = newp;
00206 }
00207 }
00208 }
00209
00210
00211
00212
00213
00214
00215 char *PunctuationFromNum(script_t *script, int num)
00216 {
00217 int i;
00218
00219 for (i = 0; script->punctuations[i].p; i++)
00220 {
00221 if (script->punctuations[i].n == num) return script->punctuations[i].p;
00222 }
00223 return "unkown punctuation";
00224 }
00225
00226
00227
00228
00229
00230
00231 void QDECL ScriptError(script_t *script, char *str, ...)
00232 {
00233 char text[1024];
00234 va_list ap;
00235
00236 if (script->flags & SCFL_NOERRORS) return;
00237
00238 va_start(ap, str);
00239 vsprintf(text, str, ap);
00240 va_end(ap);
00241 #ifdef BOTLIB
00242 botimport.Print(PRT_ERROR, "file %s, line %d: %s\n", script->filename, script->line, text);
00243 #endif //BOTLIB
00244 #ifdef MEQCC
00245 printf("error: file %s, line %d: %s\n", script->filename, script->line, text);
00246 #endif //MEQCC
00247 #ifdef BSPC
00248 Log_Print("error: file %s, line %d: %s\n", script->filename, script->line, text);
00249 #endif //BSPC
00250 }
00251
00252
00253
00254
00255
00256
00257 void QDECL ScriptWarning(script_t *script, char *str, ...)
00258 {
00259 char text[1024];
00260 va_list ap;
00261
00262 if (script->flags & SCFL_NOWARNINGS) return;
00263
00264 va_start(ap, str);
00265 vsprintf(text, str, ap);
00266 va_end(ap);
00267 #ifdef BOTLIB
00268 botimport.Print(PRT_WARNING, "file %s, line %d: %s\n", script->filename, script->line, text);
00269 #endif //BOTLIB
00270 #ifdef MEQCC
00271 printf("warning: file %s, line %d: %s\n", script->filename, script->line, text);
00272 #endif //MEQCC
00273 #ifdef BSPC
00274 Log_Print("warning: file %s, line %d: %s\n", script->filename, script->line, text);
00275 #endif //BSPC
00276 }
00277
00278
00279
00280
00281
00282
00283 void SetScriptPunctuations(script_t *script, punctuation_t *p)
00284 {
00285 #ifdef PUNCTABLE
00286 if (p) PS_CreatePunctuationTable(script, p);
00287 else PS_CreatePunctuationTable(script, default_punctuations);
00288 #endif //PUNCTABLE
00289 if (p) script->punctuations = p;
00290 else script->punctuations = default_punctuations;
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300 int PS_ReadWhiteSpace(script_t *script)
00301 {
00302 while(1)
00303 {
00304
00305 while(*script->script_p <= ' ')
00306 {
00307 if (!*script->script_p) return 0;
00308 if (*script->script_p == '\n') script->line++;
00309 script->script_p++;
00310 }
00311
00312 if (*script->script_p == '/')
00313 {
00314
00315 if (*(script->script_p+1) == '/')
00316 {
00317 script->script_p++;
00318 do
00319 {
00320 script->script_p++;
00321 if (!*script->script_p) return 0;
00322 }
00323 while(*script->script_p != '\n');
00324 script->line++;
00325 script->script_p++;
00326 if (!*script->script_p) return 0;
00327 continue;
00328 }
00329
00330 else if (*(script->script_p+1) == '*')
00331 {
00332 script->script_p++;
00333 do
00334 {
00335 script->script_p++;
00336 if (!*script->script_p) return 0;
00337 if (*script->script_p == '\n') script->line++;
00338 }
00339 while(!(*script->script_p == '*' && *(script->script_p+1) == '/'));
00340 script->script_p++;
00341 if (!*script->script_p) return 0;
00342 script->script_p++;
00343 if (!*script->script_p) return 0;
00344 continue;
00345 }
00346 }
00347 break;
00348 }
00349 return 1;
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359 int PS_ReadEscapeCharacter(script_t *script, char *ch)
00360 {
00361 int c, val, i;
00362
00363
00364 script->script_p++;
00365
00366 switch(*script->script_p)
00367 {
00368 case '\\': c = '\\'; break;
00369 case 'n': c = '\n'; break;
00370 case 'r': c = '\r'; break;
00371 case 't': c = '\t'; break;
00372 case 'v': c = '\v'; break;
00373 case 'b': c = '\b'; break;
00374 case 'f': c = '\f'; break;
00375 case 'a': c = '\a'; break;
00376 case '\'': c = '\''; break;
00377 case '\"': c = '\"'; break;
00378 case '\?': c = '\?'; break;
00379 case 'x':
00380 {
00381 script->script_p++;
00382 for (i = 0, val = 0; ; i++, script->script_p++)
00383 {
00384 c = *script->script_p;
00385 if (c >= '0' && c <= '9') c = c - '0';
00386 else if (c >= 'A' && c <= 'Z') c = c - 'A' + 10;
00387 else if (c >= 'a' && c <= 'z') c = c - 'a' + 10;
00388 else break;
00389 val = (val << 4) + c;
00390 }
00391 script->script_p--;
00392 if (val > 0xFF)
00393 {
00394 ScriptWarning(script, "too large value in escape character");
00395 val = 0xFF;
00396 }
00397 c = val;
00398 break;
00399 }
00400 default:
00401 {
00402 if (*script->script_p < '0' || *script->script_p > '9') ScriptError(script, "unknown escape char");
00403 for (i = 0, val = 0; ; i++, script->script_p++)
00404 {
00405 c = *script->script_p;
00406 if (c >= '0' && c <= '9') c = c - '0';
00407 else break;
00408 val = val * 10 + c;
00409 }
00410 script->script_p--;
00411 if (val > 0xFF)
00412 {
00413 ScriptWarning(script, "too large value in escape character");
00414 val = 0xFF;
00415 }
00416 c = val;
00417 break;
00418 }
00419 }
00420
00421 script->script_p++;
00422
00423 *ch = c;
00424
00425 return 1;
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 int PS_ReadString(script_t *script, token_t *token, int quote)
00438 {
00439 int len, tmpline;
00440 char *tmpscript_p;
00441
00442 if (quote == '\"') token->type = TT_STRING;
00443 else token->type = TT_LITERAL;
00444
00445 len = 0;
00446
00447 token->string[len++] = *script->script_p++;
00448
00449 while(1)
00450 {
00451
00452 if (len >= MAX_TOKEN - 2)
00453 {
00454 ScriptError(script, "string longer than MAX_TOKEN = %d", MAX_TOKEN);
00455 return 0;
00456 }
00457
00458
00459 if (*script->script_p == '\\' && !(script->flags & SCFL_NOSTRINGESCAPECHARS))
00460 {
00461 if (!PS_ReadEscapeCharacter(script, &token->string[len]))
00462 {
00463 token->string[len] = 0;
00464 return 0;
00465 }
00466 len++;
00467 }
00468
00469 else if (*script->script_p == quote)
00470 {
00471
00472 script->script_p++;
00473
00474 if (script->flags & SCFL_NOSTRINGWHITESPACES) break;
00475
00476 tmpscript_p = script->script_p;
00477 tmpline = script->line;
00478
00479 if (!PS_ReadWhiteSpace(script))
00480 {
00481 script->script_p = tmpscript_p;
00482 script->line = tmpline;
00483 break;
00484 }
00485
00486 if (*script->script_p != quote)
00487 {
00488 script->script_p = tmpscript_p;
00489 script->line = tmpline;
00490 break;
00491 }
00492
00493 script->script_p++;
00494 }
00495 else
00496 {
00497 if (*script->script_p == '\0')
00498 {
00499 token->string[len] = 0;
00500 ScriptError(script, "missing trailing quote");
00501 return 0;
00502 }
00503 if (*script->script_p == '\n')
00504 {
00505 token->string[len] = 0;
00506 ScriptError(script, "newline inside string %s", token->string);
00507 return 0;
00508 }
00509 token->string[len++] = *script->script_p++;
00510 }
00511 }
00512
00513 token->string[len++] = quote;
00514
00515 token->string[len] = '\0';
00516
00517 token->subtype = len;
00518 return 1;
00519 }
00520
00521
00522
00523
00524
00525
00526 int PS_ReadName(script_t *script, token_t *token)
00527 {
00528 int len = 0;
00529 char c;
00530
00531 token->type = TT_NAME;
00532 do
00533 {
00534 token->string[len++] = *script->script_p++;
00535 if (len >= MAX_TOKEN)
00536 {
00537 ScriptError(script, "name longer than MAX_TOKEN = %d", MAX_TOKEN);
00538 return 0;
00539 }
00540 c = *script->script_p;
00541 } while ((c >= 'a' && c <= 'z') ||
00542 (c >= 'A' && c <= 'Z') ||
00543 (c >= '0' && c <= '9') ||
00544 c == '_');
00545 token->string[len] = '\0';
00546
00547 token->subtype = len;
00548 return 1;
00549 }
00550
00551
00552
00553
00554
00555
00556 void NumberValue(char *string, int subtype, unsigned long int *intvalue,
00557 long double *floatvalue)
00558 {
00559 unsigned long int dotfound = 0;
00560
00561 *intvalue = 0;
00562 *floatvalue = 0;
00563
00564 if (subtype & TT_FLOAT)
00565 {
00566 while(*string)
00567 {
00568 if (*string == '.')
00569 {
00570 if (dotfound) return;
00571 dotfound = 10;
00572 string++;
00573 }
00574 if (dotfound)
00575 {
00576 *floatvalue = *floatvalue + (long double) (*string - '0') /
00577 (long double) dotfound;
00578 dotfound *= 10;
00579 }
00580 else
00581 {
00582 *floatvalue = *floatvalue * 10.0 + (long double) (*string - '0');
00583 }
00584 string++;
00585 }
00586 *intvalue = (unsigned long) *floatvalue;
00587 }
00588 else if (subtype & TT_DECIMAL)
00589 {
00590 while(*string) *intvalue = *intvalue * 10 + (*string++ - '0');
00591 *floatvalue = *intvalue;
00592 }
00593 else if (subtype & TT_HEX)
00594 {
00595
00596 string += 2;
00597 while(*string)
00598 {
00599 *intvalue <<= 4;
00600 if (*string >= 'a' && *string <= 'f') *intvalue += *string - 'a' + 10;
00601 else if (*string >= 'A' && *string <= 'F') *intvalue += *string - 'A' + 10;
00602 else *intvalue += *string - '0';
00603 string++;
00604 }
00605 *floatvalue = *intvalue;
00606 }
00607 else if (subtype & TT_OCTAL)
00608 {
00609
00610 string += 1;
00611 while(*string) *intvalue = (*intvalue << 3) + (*string++ - '0');
00612 *floatvalue = *intvalue;
00613 }
00614 else if (subtype & TT_BINARY)
00615 {
00616
00617 string += 2;
00618 while(*string) *intvalue = (*intvalue << 1) + (*string++ - '0');
00619 *floatvalue = *intvalue;
00620 }
00621 }
00622
00623
00624
00625
00626
00627
00628 int PS_ReadNumber(script_t *script, token_t *token)
00629 {
00630 int len = 0, i;
00631 int octal, dot;
00632 char c;
00633
00634
00635
00636 token->type = TT_NUMBER;
00637
00638 if (*script->script_p == '0' &&
00639 (*(script->script_p + 1) == 'x' ||
00640 *(script->script_p + 1) == 'X'))
00641 {
00642 token->string[len++] = *script->script_p++;
00643 token->string[len++] = *script->script_p++;
00644 c = *script->script_p;
00645
00646 while((c >= '0' && c <= '9') ||
00647 (c >= 'a' && c <= 'f') ||
00648 (c >= 'A' && c <= 'A'))
00649 {
00650 token->string[len++] = *script->script_p++;
00651 if (len >= MAX_TOKEN)
00652 {
00653 ScriptError(script, "hexadecimal number longer than MAX_TOKEN = %d", MAX_TOKEN);
00654 return 0;
00655 }
00656 c = *script->script_p;
00657 }
00658 token->subtype |= TT_HEX;
00659 }
00660 #ifdef BINARYNUMBERS
00661
00662 else if (*script->script_p == '0' &&
00663 (*(script->script_p + 1) == 'b' ||
00664 *(script->script_p + 1) == 'B'))
00665 {
00666 token->string[len++] = *script->script_p++;
00667 token->string[len++] = *script->script_p++;
00668 c = *script->script_p;
00669
00670 while(c == '0' || c == '1')
00671 {
00672 token->string[len++] = *script->script_p++;
00673 if (len >= MAX_TOKEN)
00674 {
00675 ScriptError(script, "binary number longer than MAX_TOKEN = %d", MAX_TOKEN);
00676 return 0;
00677 }
00678 c = *script->script_p;
00679 }
00680 token->subtype |= TT_BINARY;
00681 }
00682 #endif //BINARYNUMBERS
00683 else
00684 {
00685 octal = qfalse;
00686 dot = qfalse;
00687 if (*script->script_p == '0') octal = qtrue;
00688 while(1)
00689 {
00690 c = *script->script_p;
00691 if (c == '.') dot = qtrue;
00692 else if (c == '8' || c == '9') octal = qfalse;
00693 else if (c < '0' || c > '9') break;
00694 token->string[len++] = *script->script_p++;
00695 if (len >= MAX_TOKEN - 1)
00696 {
00697 ScriptError(script, "number longer than MAX_TOKEN = %d", MAX_TOKEN);
00698 return 0;
00699 }
00700 }
00701 if (octal) token->subtype |= TT_OCTAL;
00702 else token->subtype |= TT_DECIMAL;
00703 if (dot) token->subtype |= TT_FLOAT;
00704 }
00705 for (i = 0; i < 2; i++)
00706 {
00707 c = *script->script_p;
00708
00709 if ( (c == 'l' || c == 'L')
00710 && !(token->subtype & TT_LONG))
00711 {
00712 script->script_p++;
00713 token->subtype |= TT_LONG;
00714 }
00715
00716 else if ( (c == 'u' || c == 'U')
00717 && !(token->subtype & (TT_UNSIGNED | TT_FLOAT)))
00718 {
00719 script->script_p++;
00720 token->subtype |= TT_UNSIGNED;
00721 }
00722 }
00723 token->string[len] = '\0';
00724 #ifdef NUMBERVALUE
00725 NumberValue(token->string, token->subtype, &token->intvalue, &token->floatvalue);
00726 #endif //NUMBERVALUE
00727 if (!(token->subtype & TT_FLOAT)) token->subtype |= TT_INTEGER;
00728 return 1;
00729 }
00730
00731
00732
00733
00734
00735
00736 int PS_ReadLiteral(script_t *script, token_t *token)
00737 {
00738 token->type = TT_LITERAL;
00739
00740 token->string[0] = *script->script_p++;
00741
00742 if (!*script->script_p)
00743 {
00744 ScriptError(script, "end of file before trailing \'");
00745 return 0;
00746 }
00747
00748 if (*script->script_p == '\\')
00749 {
00750 if (!PS_ReadEscapeCharacter(script, &token->string[1])) return 0;
00751 }
00752 else
00753 {
00754 token->string[1] = *script->script_p++;
00755 }
00756
00757 if (*script->script_p != '\'')
00758 {
00759 ScriptWarning(script, "too many characters in literal, ignored");
00760 while(*script->script_p &&
00761 *script->script_p != '\'' &&
00762 *script->script_p != '\n')
00763 {
00764 script->script_p++;
00765 }
00766 if (*script->script_p == '\'') script->script_p++;
00767 }
00768
00769 token->string[2] = *script->script_p++;
00770
00771 token->string[3] = '\0';
00772
00773 token->subtype = token->string[1];
00774
00775 return 1;
00776 }
00777
00778
00779
00780
00781
00782
00783 int PS_ReadPunctuation(script_t *script, token_t *token)
00784 {
00785 int len;
00786 char *p;
00787 punctuation_t *punc;
00788
00789 #ifdef PUNCTABLE
00790 for (punc = script->punctuationtable[(unsigned int)*script->script_p]; punc; punc = punc->next)
00791 {
00792 #else
00793 int i;
00794
00795 for (i = 0; script->punctuations[i].p; i++)
00796 {
00797 punc = &script->punctuations[i];
00798 #endif //PUNCTABLE
00799 p = punc->p;
00800 len = strlen(p);
00801
00802 if (script->script_p + len <= script->end_p)
00803 {
00804
00805 if (!strncmp(script->script_p, p, len))
00806 {
00807 strncpy(token->string, p, MAX_TOKEN);
00808 script->script_p += len;
00809 token->type = TT_PUNCTUATION;
00810
00811 token->subtype = punc->n;
00812 return 1;
00813 }
00814 }
00815 }
00816 return 0;
00817 }
00818
00819
00820
00821
00822
00823
00824 int PS_ReadPrimitive(script_t *script, token_t *token)
00825 {
00826 int len;
00827
00828 len = 0;
00829 while(*script->script_p > ' ' && *script->script_p != ';')
00830 {
00831 if (len >= MAX_TOKEN)
00832 {
00833 ScriptError(script, "primitive token longer than MAX_TOKEN = %d", MAX_TOKEN);
00834 return 0;
00835 }
00836 token->string[len++] = *script->script_p++;
00837 }
00838 token->string[len] = 0;
00839
00840 Com_Memcpy(&script->token, token, sizeof(token_t));
00841
00842 return 1;
00843 }
00844
00845
00846
00847
00848
00849
00850 int PS_ReadToken(script_t *script, token_t *token)
00851 {
00852
00853 if (script->tokenavailable)
00854 {
00855 script->tokenavailable = 0;
00856 Com_Memcpy(token, &script->token, sizeof(token_t));
00857 return 1;
00858 }
00859
00860 script->lastscript_p = script->script_p;
00861
00862 script->lastline = script->line;
00863
00864 Com_Memset(token, 0, sizeof(token_t));
00865
00866 script->whitespace_p = script->script_p;
00867 token->whitespace_p = script->script_p;
00868
00869 if (!PS_ReadWhiteSpace(script)) return 0;
00870
00871 script->endwhitespace_p = script->script_p;
00872 token->endwhitespace_p = script->script_p;
00873
00874 token->line = script->line;
00875
00876 token->linescrossed = script->line - script->lastline;
00877
00878 if (*script->script_p == '\"')
00879 {
00880 if (!PS_ReadString(script, token, '\"')) return 0;
00881 }
00882
00883 else if (*script->script_p == '\'')
00884 {
00885
00886 if (!PS_ReadString(script, token, '\'')) return 0;
00887 }
00888
00889 else if ((*script->script_p >= '0' && *script->script_p <= '9') ||
00890 (*script->script_p == '.' &&
00891 (*(script->script_p + 1) >= '0' && *(script->script_p + 1) <= '9')))
00892 {
00893 if (!PS_ReadNumber(script, token)) return 0;
00894 }
00895
00896 else if (script->flags & SCFL_PRIMITIVE)
00897 {
00898 return PS_ReadPrimitive(script, token);
00899 }
00900
00901 else if ((*script->script_p >= 'a' && *script->script_p <= 'z') ||
00902 (*script->script_p >= 'A' && *script->script_p <= 'Z') ||
00903 *script->script_p == '_')
00904 {
00905 if (!PS_ReadName(script, token)) return 0;
00906 }
00907
00908 else if (!PS_ReadPunctuation(script, token))
00909 {
00910 ScriptError(script, "can't read token");
00911 return 0;
00912 }
00913
00914 Com_Memcpy(&script->token, token, sizeof(token_t));
00915
00916 return 1;
00917 }
00918
00919
00920
00921
00922
00923
00924 int PS_ExpectTokenString(script_t *script, char *string)
00925 {
00926 token_t token;
00927
00928 if (!PS_ReadToken(script, &token))
00929 {
00930 ScriptError(script, "couldn't find expected %s", string);
00931 return 0;
00932 }
00933
00934 if (strcmp(token.string, string))
00935 {
00936 ScriptError(script, "expected %s, found %s", string, token.string);
00937 return 0;
00938 }
00939 return 1;
00940 }
00941
00942
00943
00944
00945
00946
00947 int PS_ExpectTokenType(script_t *script, int type, int subtype, token_t *token)
00948 {
00949 char str[MAX_TOKEN];
00950
00951 if (!PS_ReadToken(script, token))
00952 {
00953 ScriptError(script, "couldn't read expected token");
00954 return 0;
00955 }
00956
00957 if (token->type != type)
00958 {
00959 if (type == TT_STRING) strcpy(str, "string");
00960 if (type == TT_LITERAL) strcpy(str, "literal");
00961 if (type == TT_NUMBER) strcpy(str, "number");
00962 if (type == TT_NAME) strcpy(str, "name");
00963 if (type == TT_PUNCTUATION) strcpy(str, "punctuation");
00964 ScriptError(script, "expected a %s, found %s", str, token->string);
00965 return 0;
00966 }
00967 if (token->type == TT_NUMBER)
00968 {
00969 if ((token->subtype & subtype) != subtype)
00970 {
00971 if (subtype & TT_DECIMAL) strcpy(str, "decimal");
00972 if (subtype & TT_HEX) strcpy(str, "hex");
00973 if (subtype & TT_OCTAL) strcpy(str, "octal");
00974 if (subtype & TT_BINARY) strcpy(str, "binary");
00975 if (subtype & TT_LONG) strcat(str, " long");
00976 if (subtype & TT_UNSIGNED) strcat(str, " unsigned");
00977 if (subtype & TT_FLOAT) strcat(str, " float");
00978 if (subtype & TT_INTEGER) strcat(str, " integer");
00979 ScriptError(script, "expected %s, found %s", str, token->string);
00980 return 0;
00981 }
00982 }
00983 else if (token->type == TT_PUNCTUATION)
00984 {
00985 if (subtype < 0)
00986 {
00987 ScriptError(script, "BUG: wrong punctuation subtype");
00988 return 0;
00989 }
00990 if (token->subtype != subtype)
00991 {
00992 ScriptError(script, "expected %s, found %s",
00993 script->punctuations[subtype], token->string);
00994 return 0;
00995 }
00996 }
00997 return 1;
00998 }
00999
01000
01001
01002
01003
01004
01005 int PS_ExpectAnyToken(script_t *script, token_t *token)
01006 {
01007 if (!PS_ReadToken(script, token))
01008 {
01009 ScriptError(script, "couldn't read expected token");
01010 return 0;
01011 }
01012 else
01013 {
01014 return 1;
01015 }
01016 }
01017
01018
01019
01020
01021
01022
01023 int PS_CheckTokenString(script_t *script, char *string)
01024 {
01025 token_t tok;
01026
01027 if (!PS_ReadToken(script, &tok)) return 0;
01028
01029 if (!strcmp(tok.string, string)) return 1;
01030
01031 script->script_p = script->lastscript_p;
01032 return 0;
01033 }
01034
01035
01036
01037
01038
01039
01040 int PS_CheckTokenType(script_t *script, int type, int subtype, token_t *token)
01041 {
01042 token_t tok;
01043
01044 if (!PS_ReadToken(script, &tok)) return 0;
01045
01046 if (tok.type == type &&
01047 (tok.subtype & subtype) == subtype)
01048 {
01049 Com_Memcpy(token, &tok, sizeof(token_t));
01050 return 1;
01051 }
01052
01053 script->script_p = script->lastscript_p;
01054 return 0;
01055 }
01056
01057
01058
01059
01060
01061
01062 int PS_SkipUntilString(script_t *script, char *string)
01063 {
01064 token_t token;
01065
01066 while(PS_ReadToken(script, &token))
01067 {
01068 if (!strcmp(token.string, string)) return 1;
01069 }
01070 return 0;
01071 }
01072
01073
01074
01075
01076
01077
01078 void PS_UnreadLastToken(script_t *script)
01079 {
01080 script->tokenavailable = 1;
01081 }
01082
01083
01084
01085
01086
01087
01088 void PS_UnreadToken(script_t *script, token_t *token)
01089 {
01090 Com_Memcpy(&script->token, token, sizeof(token_t));
01091 script->tokenavailable = 1;
01092 }
01093
01094
01095
01096
01097
01098
01099
01100 char PS_NextWhiteSpaceChar(script_t *script)
01101 {
01102 if (script->whitespace_p != script->endwhitespace_p)
01103 {
01104 return *script->whitespace_p++;
01105 }
01106 else
01107 {
01108 return 0;
01109 }
01110 }
01111
01112
01113
01114
01115
01116
01117 void StripDoubleQuotes(char *string)
01118 {
01119 if (*string == '\"')
01120 {
01121 strcpy(string, string+1);
01122 }
01123 if (string[strlen(string)-1] == '\"')
01124 {
01125 string[strlen(string)-1] = '\0';
01126 }
01127 }
01128
01129
01130
01131
01132
01133
01134 void StripSingleQuotes(char *string)
01135 {
01136 if (*string == '\'')
01137 {
01138 strcpy(string, string+1);
01139 }
01140 if (string[strlen(string)-1] == '\'')
01141 {
01142 string[strlen(string)-1] = '\0';
01143 }
01144 }
01145
01146
01147
01148
01149
01150
01151 long double ReadSignedFloat(script_t *script)
01152 {
01153 token_t token;
01154 long double sign = 1;
01155
01156 PS_ExpectAnyToken(script, &token);
01157 if (!strcmp(token.string, "-"))
01158 {
01159 sign