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
00038
00039
00040
00041 #ifdef SCREWUP
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <limits.h>
00045 #include <string.h>
00046 #include <stdarg.h>
00047 #include <time.h>
00048 #include "l_memory.h"
00049 #include "l_script.h"
00050 #include "l_precomp.h"
00051
00052 typedef enum {qfalse, qtrue} qboolean;
00053 #endif //SCREWUP
00054
00055 #ifdef BOTLIB
00056 #include "../game/q_shared.h"
00057 #include "../game/botlib.h"
00058 #include "be_interface.h"
00059 #include "l_memory.h"
00060 #include "l_script.h"
00061 #include "l_precomp.h"
00062 #include "l_log.h"
00063 #endif //BOTLIB
00064
00065 #ifdef MEQCC
00066 #include "qcc.h"
00067 #include "time.h"
00068 #include "math.h"
00069 #include "l_memory.h"
00070 #include "l_script.h"
00071 #include "l_precomp.h"
00072 #include "l_log.h"
00073
00074 #define qtrue true
00075 #define qfalse false
00076 #endif //MEQCC
00077
00078 #ifdef BSPC
00079
00080 #include "../bspc/qbsp.h"
00081 #include "../bspc/l_log.h"
00082 #include "../bspc/l_mem.h"
00083 #include "l_precomp.h"
00084
00085 #define qtrue true
00086 #define qfalse false
00087 #define Q_stricmp stricmp
00088
00089 #endif //BSPC
00090
00091 #if defined(QUAKE) && !defined(BSPC)
00092 #include "l_utils.h"
00093 #endif //QUAKE
00094
00095
00096
00097 #define MAX_DEFINEPARMS 128
00098
00099 #define DEFINEHASHING 1
00100
00101
00102 typedef struct directive_s
00103 {
00104 char *name;
00105 int (*func)(source_t *source);
00106 } directive_t;
00107
00108 #define DEFINEHASHSIZE 1024
00109
00110 #define TOKEN_HEAP_SIZE 4096
00111
00112 int numtokens;
00113
00114
00115
00116
00117
00118
00119
00120 define_t *globaldefines;
00121
00122
00123
00124
00125
00126
00127
00128 void QDECL SourceError(source_t *source, char *str, ...)
00129 {
00130 char text[1024];
00131 va_list ap;
00132
00133 va_start(ap, str);
00134 vsprintf(text, str, ap);
00135 va_end(ap);
00136 #ifdef BOTLIB
00137 botimport.Print(PRT_ERROR, "file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
00138 #endif //BOTLIB
00139 #ifdef MEQCC
00140 printf("error: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
00141 #endif //MEQCC
00142 #ifdef BSPC
00143 Log_Print("error: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
00144 #endif //BSPC
00145 }
00146
00147
00148
00149
00150
00151
00152 void QDECL SourceWarning(source_t *source, char *str, ...)
00153 {
00154 char text[1024];
00155 va_list ap;
00156
00157 va_start(ap, str);
00158 vsprintf(text, str, ap);
00159 va_end(ap);
00160 #ifdef BOTLIB
00161 botimport.Print(PRT_WARNING, "file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
00162 #endif //BOTLIB
00163 #ifdef MEQCC
00164 printf("warning: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
00165 #endif //MEQCC
00166 #ifdef BSPC
00167 Log_Print("warning: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
00168 #endif //BSPC
00169 }
00170
00171
00172
00173
00174
00175
00176 void PC_PushIndent(source_t *source, int type, int skip)
00177 {
00178 indent_t *indent;
00179
00180 indent = (indent_t *) GetMemory(sizeof(indent_t));
00181 indent->type = type;
00182 indent->script = source->scriptstack;
00183 indent->skip = (skip != 0);
00184 source->skip += indent->skip;
00185 indent->next = source->indentstack;
00186 source->indentstack = indent;
00187 }
00188
00189
00190
00191
00192
00193
00194 void PC_PopIndent(source_t *source, int *type, int *skip)
00195 {
00196 indent_t *indent;
00197
00198 *type = 0;
00199 *skip = 0;
00200
00201 indent = source->indentstack;
00202 if (!indent) return;
00203
00204
00205 if (source->indentstack->script != source->scriptstack) return;
00206
00207 *type = indent->type;
00208 *skip = indent->skip;
00209 source->indentstack = source->indentstack->next;
00210 source->skip -= indent->skip;
00211 FreeMemory(indent);
00212 }
00213
00214
00215
00216
00217
00218
00219 void PC_PushScript(source_t *source, script_t *script)
00220 {
00221 script_t *s;
00222
00223 for (s = source->scriptstack; s; s = s->next)
00224 {
00225 if (!Q_stricmp(s->filename, script->filename))
00226 {
00227 SourceError(source, "%s recursively included", script->filename);
00228 return;
00229 }
00230 }
00231
00232 script->next = source->scriptstack;
00233 source->scriptstack = script;
00234 }
00235
00236
00237
00238
00239
00240
00241 void PC_InitTokenHeap(void)
00242 {
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 }
00256
00257
00258
00259
00260
00261
00262 token_t *PC_CopyToken(token_t *token)
00263 {
00264 token_t *t;
00265
00266
00267 t = (token_t *) GetMemory(sizeof(token_t));
00268
00269 if (!t)
00270 {
00271 #ifdef BSPC
00272 Error("out of token space\n");
00273 #else
00274 Com_Error(ERR_FATAL, "out of token space\n");
00275 #endif
00276 return NULL;
00277 }
00278
00279 Com_Memcpy(t, token, sizeof(token_t));
00280 t->next = NULL;
00281 numtokens++;
00282 return t;
00283 }
00284
00285
00286
00287
00288
00289
00290 void PC_FreeToken(token_t *token)
00291 {
00292
00293 FreeMemory(token);
00294
00295
00296 numtokens--;
00297 }
00298
00299
00300
00301
00302
00303
00304 int PC_ReadSourceToken(source_t *source, token_t *token)
00305 {
00306 token_t *t;
00307 script_t *script;
00308 int type, skip;
00309
00310
00311 while(!source->tokens)
00312 {
00313
00314 if (PS_ReadToken(source->scriptstack, token)) return qtrue;
00315
00316 if (EndOfScript(source->scriptstack))
00317 {
00318
00319 while(source->indentstack &&
00320 source->indentstack->script == source->scriptstack)
00321 {
00322 SourceWarning(source, "missing #endif");
00323 PC_PopIndent(source, &type, &skip);
00324 }
00325 }
00326
00327 if (!source->scriptstack->next) return qfalse;
00328
00329 script = source->scriptstack;
00330 source->scriptstack = source->scriptstack->next;
00331 FreeScript(script);
00332 }
00333
00334 Com_Memcpy(token, source->tokens, sizeof(token_t));
00335
00336 t = source->tokens;
00337 source->tokens = source->tokens->next;
00338 PC_FreeToken(t);
00339 return qtrue;
00340 }
00341
00342
00343
00344
00345
00346
00347 int PC_UnreadSourceToken(source_t *source, token_t *token)
00348 {
00349 token_t *t;
00350
00351 t = PC_CopyToken(token);
00352 t->next = source->tokens;
00353 source->tokens = t;
00354 return qtrue;
00355 }
00356
00357
00358
00359
00360
00361
00362 int PC_ReadDefineParms(source_t *source, define_t *define, token_t **parms, int maxparms)
00363 {
00364 token_t token, *t, *last;
00365 int i, done, lastcomma, numparms, indent;
00366
00367 if (!PC_ReadSourceToken(source, &token))
00368 {
00369 SourceError(source, "define %s missing parms", define->name);
00370 return qfalse;
00371 }
00372
00373 if (define->numparms > maxparms)
00374 {
00375 SourceError(source, "define with more than %d parameters", maxparms);
00376 return qfalse;
00377 }
00378
00379 for (i = 0; i < define->numparms; i++) parms[i] = NULL;
00380
00381 if (strcmp(token.string, "("))
00382 {
00383 PC_UnreadSourceToken(source, &token);
00384 SourceError(source, "define %s missing parms", define->name);
00385 return qfalse;
00386 }
00387
00388 for (done = 0, numparms = 0, indent = 0; !done;)
00389 {
00390 if (numparms >= maxparms)
00391 {
00392 SourceError(source, "define %s with too many parms", define->name);
00393 return qfalse;
00394 }
00395 if (numparms >= define->numparms)
00396 {
00397 SourceWarning(source, "define %s has too many parms", define->name);
00398 return qfalse;
00399 }
00400 parms[numparms] = NULL;
00401 lastcomma = 1;
00402 last = NULL;
00403 while(!done)
00404 {
00405
00406 if (!PC_ReadSourceToken(source, &token))
00407 {
00408 SourceError(source, "define %s incomplete", define->name);
00409 return qfalse;
00410 }
00411
00412 if (!strcmp(token.string, ","))
00413 {
00414 if (indent <= 0)
00415 {
00416 if (lastcomma) SourceWarning(source, "too many comma's");
00417 lastcomma = 1;
00418 break;
00419 }
00420 }
00421 lastcomma = 0;
00422
00423 if (!strcmp(token.string, "("))
00424 {
00425 indent++;
00426 continue;
00427 }
00428 else if (!strcmp(token.string, ")"))
00429 {
00430 if (--indent <= 0)
00431 {
00432 if (!parms[define->numparms-1])
00433 {
00434 SourceWarning(source, "too few define parms");
00435 }
00436 done = 1;
00437 break;
00438 }
00439 }
00440
00441 if (numparms < define->numparms)
00442 {
00443
00444 t = PC_CopyToken(&token);
00445 t->next = NULL;
00446 if (last) last->next = t;
00447 else parms[numparms] = t;
00448 last = t;
00449 }
00450 }
00451 numparms++;
00452 }
00453 return qtrue;
00454 }
00455
00456
00457
00458
00459
00460
00461 int PC_StringizeTokens(token_t *tokens, token_t *token)
00462 {
00463 token_t *t;
00464
00465 token->type = TT_STRING;
00466 token->whitespace_p = NULL;
00467 token->endwhitespace_p = NULL;
00468 token->string[0] = '\0';
00469 strcat(token->string, "\"");
00470 for (t = tokens; t; t = t->next)
00471 {
00472 strncat(token->string, t->string, MAX_TOKEN - strlen(token->string));
00473 }
00474 strncat(token->string, "\"", MAX_TOKEN - strlen(token->string));
00475 return qtrue;
00476 }
00477
00478
00479
00480
00481
00482
00483 int PC_MergeTokens(token_t *t1, token_t *t2)
00484 {
00485
00486 if (t1->type == TT_NAME && (t2->type == TT_NAME || t2->type == TT_NUMBER))
00487 {
00488 strcat(t1->string, t2->string);
00489 return qtrue;
00490 }
00491
00492 if (t1->type == TT_STRING && t2->type == TT_STRING)
00493 {
00494
00495 t1->string[strlen(t1->string)-1] = '\0';
00496
00497 strcat(t1->string, &t2->string[1]);
00498 return qtrue;
00499 }
00500
00501 return qfalse;
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 #if DEFINEHASHING
00521
00522
00523
00524
00525
00526
00527 void PC_PrintDefineHashTable(define_t **definehash)
00528 {
00529 int i;
00530 define_t *d;
00531
00532 for (i = 0; i < DEFINEHASHSIZE; i++)
00533 {
00534 Log_Write("%4d:", i);
00535 for (d = definehash[i]; d; d = d->hashnext)
00536 {
00537 Log_Write(" %s", d->name);
00538 }
00539 Log_Write("\n");
00540 }
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550 int PC_NameHash(char *name)
00551 {
00552 int register hash, i;
00553
00554 hash = 0;
00555 for (i = 0; name[i] != '\0'; i++)
00556 {
00557 hash += name[i] * (119 + i);
00558
00559
00560 }
00561 hash = (hash ^ (hash >> 10) ^ (hash >> 20)) & (DEFINEHASHSIZE-1);
00562 return hash;
00563 }
00564
00565
00566
00567
00568
00569
00570 void PC_AddDefineToHash(define_t *define, define_t **definehash)
00571 {
00572 int hash;
00573
00574 hash = PC_NameHash(define->name);
00575 define->hashnext = definehash[hash];
00576 definehash[hash] = define;
00577 }
00578
00579
00580
00581
00582
00583
00584 define_t *PC_FindHashedDefine(define_t **definehash, char *name)
00585 {
00586 define_t *d;
00587 int hash;
00588
00589 hash = PC_NameHash(name);
00590 for (d = definehash[hash]; d; d = d->hashnext)
00591 {
00592 if (!strcmp(d->name, name)) return d;
00593 }
00594 return NULL;
00595 }
00596 #endif //DEFINEHASHING
00597
00598
00599
00600
00601
00602
00603 define_t *PC_FindDefine(define_t *defines, char *name)
00604 {
00605 define_t *d;
00606
00607 for (d = defines; d; d = d->next)
00608 {
00609 if (!strcmp(d->name, name)) return d;
00610 }
00611 return NULL;
00612 }
00613
00614
00615
00616
00617
00618
00619
00620 int PC_FindDefineParm(define_t *define, char *name)
00621 {
00622 token_t *p;
00623 int i;
00624
00625 i = 0;
00626 for (p = define->parms; p; p = p->next)
00627 {
00628 if (!strcmp(p->string, name)) return i;
00629 i++;
00630 }
00631 return -1;
00632 }
00633
00634
00635
00636
00637
00638
00639 void PC_FreeDefine(define_t *define)
00640 {
00641 token_t *t, *next;
00642
00643
00644 for (t = define->parms; t; t = next)
00645 {
00646 next = t->next;
00647 PC_FreeToken(t);
00648 }
00649
00650 for (t = define->tokens; t; t = next)
00651 {
00652 next = t->next;
00653 PC_FreeToken(t);
00654 }
00655
00656 FreeMemory(define);
00657 }
00658
00659
00660
00661
00662
00663
00664 void PC_AddBuiltinDefines(source_t *source)
00665 {
00666 int i;
00667 define_t *define;
00668 struct builtin
00669 {
00670 char *string;
00671 int builtin;
00672 } builtin[] = {
00673 { "__LINE__", BUILTIN_LINE },
00674 { "__FILE__", BUILTIN_FILE },
00675 { "__DATE__", BUILTIN_DATE },
00676 { "__TIME__", BUILTIN_TIME },
00677
00678 { NULL, 0 }
00679 };
00680
00681 for (i = 0; builtin[i].string; i++)
00682 {
00683 define = (define_t *) GetMemory(sizeof(define_t) + strlen(builtin[i].string) + 1);
00684 Com_Memset(define, 0, sizeof(define_t));
00685 define->name = (char *) define + sizeof(define_t);
00686 strcpy(define->name, builtin[i].string);
00687 define->flags |= DEFINE_FIXED;
00688 define->builtin = builtin[i].builtin;
00689
00690 #if DEFINEHASHING
00691 PC_AddDefineToHash(define, source->definehash);
00692 #else
00693 define->next = source->defines;
00694 source->defines = define;
00695 #endif //DEFINEHASHING
00696 }
00697 }
00698
00699
00700
00701
00702
00703
00704 int PC_ExpandBuiltinDefine(source_t *source, token_t *deftoken, define_t *define,
00705 token_t **firsttoken, token_t **lasttoken)
00706 {
00707 token_t *token;
00708 unsigned long t;
00709 char *curtime;
00710
00711 token = PC_CopyToken(deftoken);
00712 switch(define->builtin)
00713 {
00714 case BUILTIN_LINE:
00715 {
00716 sprintf(token->string, "%d", deftoken->line);
00717 #ifdef NUMBERVALUE
00718 token->intvalue = deftoken->line;
00719 token->floatvalue = deftoken->line;
00720 #endif //NUMBERVALUE
00721 token->type = TT_NUMBER;
00722 token->subtype = TT_DECIMAL | TT_INTEGER;
00723 *firsttoken = token;
00724 *lasttoken = token;
00725 break;
00726 }
00727 case BUILTIN_FILE:
00728 {
00729 strcpy(token->string, source->scriptstack->filename);
00730 token->type = TT_NAME;
00731 token->subtype = strlen(token->string);
00732 *firsttoken = token;
00733 *lasttoken = token;
00734 break;
00735 }
00736 case BUILTIN_DATE:
00737 {
00738 t = time(NULL);
00739 curtime = ctime(&t);
00740 strcpy(token->string, "\"");
00741 strncat(token->string, curtime+4, 7);
00742 strncat(token->string+7, curtime+20, 4);
00743 strcat(token->string, "\"");
00744 free(curtime);
00745 token->type = TT_NAME;
00746 token->subtype = strlen(token->string);
00747 *firsttoken = token;
00748 *lasttoken = token;
00749 break;
00750 }
00751 case BUILTIN_TIME:
00752 {
00753 t = time(NULL);
00754 curtime = ctime(&t);
00755 strcpy(token->string, "\"");
00756 strncat(token->string, curtime+11, 8);
00757 strcat(token->string, "\"");
00758 free(curtime);
00759 token->type = TT_NAME;
00760 token->subtype = strlen(token->string);
00761 *firsttoken = token;
00762 *lasttoken = token;
00763 break;
00764 }
00765 case BUILTIN_STDC:
00766 default:
00767 {
00768 *firsttoken = NULL;
00769 *lasttoken = NULL;
00770 break;
00771 }
00772 }
00773 return qtrue;
00774 }
00775
00776
00777
00778
00779
00780
00781 int PC_ExpandDefine(source_t *source, token_t *deftoken, define_t *define,
00782 token_t **firsttoken, token_t **lasttoken)
00783 {
00784 token_t *parms[MAX_DEFINEPARMS], *dt, *pt, *t;
00785 token_t *t1, *t2, *first, *last, *nextpt, token;
00786 int parmnum, i;
00787
00788
00789 if (define->builtin)
00790 {
00791 return PC_ExpandBuiltinDefine(source, deftoken, define, firsttoken, lasttoken);
00792 }
00793
00794 if (define->numparms)
00795 {
00796 if (!PC_ReadDefineParms(source, define, parms, MAX_DEFINEPARMS)) return qfalse;
00797 #ifdef DEBUG_EVAL
00798 for (i = 0; i < define->numparms; i++)
00799 {
00800 Log_Write("define parms %d:", i);
00801 for (pt = parms[i]; pt; pt = pt->next)
00802 {
00803 Log_Write("%s", pt->string);
00804 }
00805 }
00806 #endif //DEBUG_EVAL
00807 }
00808
00809 first = NULL;
00810 last = NULL;
00811
00812 for (dt = define->tokens; dt; dt = dt->next)
00813 {
00814 parmnum = -1;
00815
00816 if (dt->type == TT_NAME)
00817 {
00818 parmnum = PC_FindDefineParm(define, dt->string);
00819 }
00820
00821 if (parmnum >= 0)
00822 {
00823 for (pt = parms[parmnum]; pt; pt = pt->next)
00824 {
00825 t = PC_CopyToken(pt);
00826
00827 t->next = NULL;
00828 if (last) last->next = t;
00829 else first = t;
00830 last = t;
00831 }
00832 }
00833 else
00834 {
00835
00836 if (dt->string[0] == '#' && dt->string[1] == '\0')
00837 {
00838
00839 if (dt->next) parmnum = PC_FindDefineParm(define, dt->next->string);
00840 else parmnum = -1;
00841
00842 if (parmnum >= 0)
00843 {
00844
00845 dt = dt->next;
00846
00847 if (!PC_StringizeTokens(parms[parmnum], &token))
00848 {
00849 SourceError(source, "can't stringize tokens");
00850 return qfalse;
00851 }
00852 t = PC_CopyToken(&token);
00853 }
00854 else
00855 {
00856 SourceWarning(source, "stringizing operator without define parameter");
00857 continue;
00858 }
00859 }
00860 else
00861 {
00862 t = PC_CopyToken(dt);
00863 }
00864
00865 t->next = NULL;
00866 if (last) last->next = t;
00867 else first = t;
00868 last = t;
00869 }
00870 }
00871
00872 for (t = first; t; )
00873 {
00874 if (t->next)
00875 {
00876
00877 if (t->next->string[0] == '#' && t->next->string[1] == '#')
00878 {
00879 t1 = t;
00880 t2 = t->next->next;
00881 if (t2)
00882 {
00883 if (!PC_MergeTokens(t1, t2))
00884 {
00885 SourceError(source, "can't merge %s with %s", t1->string, t2->string);
00886 return qfalse;
00887 }
00888 PC_FreeToken(t1->next);
00889 t1->next = t2->next;
00890 if (t2 == last) last = t1;
00891 PC_FreeToken(t2);
00892 continue;
00893 }
00894 }
00895 }
00896 t = t->next;
00897 }
00898
00899 *firsttoken = first;
00900 *lasttoken = last;
00901
00902 for (i = 0; i < define->numparms; i++)
00903 {
00904 for (pt = parms[i]; pt; pt = nextpt)
00905 {
00906 nextpt = pt->next;
00907 PC_FreeToken(pt);
00908 }
00909 }
00910
00911 return qtrue;
00912 }
00913
00914
00915
00916
00917
00918
00919 int PC_ExpandDefineIntoSource(source_t *source, token_t *deftoken, define_t *define)
00920 {
00921 token_t *firsttoken, *lasttoken;
00922
00923 if (!PC_ExpandDefine(source, deftoken, define, &firsttoken, &lasttoken)) return qfalse;
00924
00925 if (firsttoken && lasttoken)
00926 {
00927 lasttoken->next = source->tokens;
00928 source->tokens = firsttoken;
00929 return qtrue;
00930 }
00931 return qfalse;
00932 }
00933
00934
00935
00936
00937
00938
00939 void PC_ConvertPath(char *path)
00940 {
00941 char *ptr;
00942
00943
00944 for (ptr = path; *ptr;)
00945 {
00946 if ((*ptr == '\\' || *ptr == '/') &&
00947 (*(ptr+1) == '\\' || *(ptr+1) == '/'))
00948 {
00949 strcpy(ptr, ptr+1);
00950 }
00951 else
00952 {
00953 ptr++;
00954 }
00955 }
00956
00957 for (ptr = path; *ptr;)
00958 {
00959 if (*ptr == '/' || *ptr == '\\') *ptr = PATHSEPERATOR_CHAR;
00960 ptr++;
00961 }
00962 }
00963
00964
00965
00966
00967
00968
00969 int PC_Directive_include(source_t *source)
00970 {
00971 script_t *script;
00972 token_t token;
00973 char path[MAX_PATH];
00974 #ifdef QUAKE
00975 foundfile_t file;
00976 #endif //QUAKE
00977
00978 if (source->skip > 0) return qtrue;
00979
00980 if (!PC_ReadSourceToken(source, &token))
00981 {
00982 SourceError(source, "#include without file name");
00983 return qfalse;
00984 }
00985 if (token.linescrossed > 0)
00986 {
00987 SourceError(source, "#include without file name");
00988 return qfalse;
00989 }
00990 if (token.type == TT_STRING)
00991 {
00992 StripDoubleQuotes(token.string);
00993 PC_ConvertPath(token.string);
00994 script = LoadScriptFile(token.string);
00995 if (!script)
00996 {
00997 strcpy(path, source->includepath);
00998 strcat(path, token.string);
00999 script = LoadScriptFile(path);
01000 }
01001 }
01002 else if (token.type == TT_PUNCTUATION && *token.string == '<')
01003 {
01004 strcpy(path, source->includepath);
01005 while(PC_ReadSourceToken(source, &token))
01006 {
01007 if (token.linescrossed > 0)
01008 {
01009 PC_UnreadSourceToken(source, &token);
01010 break;
01011 }
01012 if (token.type == TT_PUNCTUATION && *token.string == '>') break;
01013 strncat(path, token.string, MAX_PATH);
01014 }
01015 if (*token.string != '>')
01016 {
01017 SourceWarning(source, "#include missing trailing >");
01018 }
01019 if (!strlen(path))
01020 {
01021 SourceError(source, "#include without file name between < >");
01022 return qfalse;
01023 }
01024 PC_ConvertPath(path);
01025 script = LoadScriptFile(path);
01026 }
01027 else
01028 {
01029 SourceError(source, "#include without file name");
01030 return qfalse;
01031 }
01032 #ifdef QUAKE
01033 if (!script)
01034 {
01035 Com_Memset(&file, 0, sizeof(foundfile_t));
01036 script = LoadScriptFile(path);
01037 if (script) strncpy(script->filename, path, MAX_PATH);
01038 }
01039 #endif //QUAKE
01040 if (!script)
01041 {
01042 #ifdef SCREWUP
01043 SourceWarning(source, "file %s not found", path);
01044 return qtrue;
01045 #else
01046 SourceError(source, "file %s not found", path);
01047 return qfalse;
01048 #endif //SCREWUP
01049 }
01050 PC_PushScript(source, script);
01051 return qtrue;
01052 }
01053
01054
01055
01056
01057
01058
01059
01060
01061 int PC_ReadLine(source_t *source, token_t *token)
01062 {
01063 int crossline;
01064
01065 crossline = 0;
01066 do
01067 {
01068 if (!PC_ReadSourceToken(source, token)) return qfalse;
01069
01070 if (token->linescrossed > crossline)
01071 {
01072 PC_UnreadSourceToken(source, token);
01073 return qfalse;
01074 }
01075 crossline = 1;
01076 } while(!strcmp(token->string, "\\"));
01077 return qtrue;
01078 }
01079
01080
01081
01082
01083
01084
01085 int PC_WhiteSpaceBeforeToken(token_t *token)
01086 {
01087 return token->endwhitespace_p - token->whitespace_p > 0;
01088 }
01089
01090
01091
01092
01093
01094
01095 void PC_ClearTokenWhiteSpace(token_t *token)
01096 {
01097 token->whitespace_p = NULL;
01098 token->endwhitespace_p = NULL;
01099 token->linescrossed = 0;
01100 }
01101
01102
01103
01104
01105
01106
01107 int PC_Directive_undef(source_t *source)
01108 {
01109 token_t token;
01110 define_t *define, *lastdefine;
01111 int hash;
01112
01113 if (source->skip > 0) return qtrue;
01114
01115 if (!PC_ReadLine(source, &token))
01116 {
01117 SourceError(source, "undef without name");
01118 return qfalse;
01119 }
01120 if (token.type != TT_NAME)
01121 {
01122 PC_UnreadSourceToken(source, &token);
01123 SourceError(source, "expected name, found %s", token.string);
01124 return qfalse;
01125 }
01126 #if DEFINEHASHING
01127
01128 hash = PC_NameHash(token.string);
01129 for (lastdefine = NULL, define = source->definehash[hash]; define; define = define->hashnext)
01130 {
01131 if (!strcmp(define->name, token.string))
01132 {
01133 if (define->flags & DEFINE_FIXED)
01134 {
01135 SourceWarning(source, "can't undef %s", token.string);
01136 }
01137 else
01138 {
01139 if (lastdefine) lastdefine->hashnext = define->hashnext;
01140 else source->definehash[hash] = define->hashnext;
01141 PC_FreeDefine(define);
01142 }
01143 break;
01144 }
01145 lastdefine = define;
01146 }
01147 #else //DEFINEHASHING
01148 for (lastdefine = NULL, define = source->defines; define; define = define->next)
01149 {
01150 if (!strcmp(define->name, token.string))
01151 {
01152 if (define->flags & DEFINE_FIXED)
01153 {
01154 SourceWarning(source, "can't undef %s", token.string);
01155 }
01156 else
01157 {
01158 if (lastdefine) lastdefine->next = define->next;
01159 else source->defines = define->next;
01160 PC_FreeDefine(define);
01161 }
01162 break;
01163 }
01164 lastdefine = define;
01165 }
01166 #endif //DEFINEHASHING
01167 return qtrue;
01168 }
01169
01170
01171
01172
01173
01174
01175 int PC_Directive_define(source_t *source)
01176 {
01177 token_t token, *t, *last;
01178 define_t *define;
01179
01180 if (source->skip > 0) return qtrue;
01181
01182 if (!PC_ReadLine(source, &token))
01183 {
01184 SourceError(source, "#define without name");
01185 return qfalse;
01186 }
01187 if (token.type != TT_NAME)
01188 {
01189 PC_UnreadSourceToken(source, &token);
01190 SourceError(source, "expected name after #define, found %s", token.string);
01191 return qfalse;
01192 }
01193
01194 #if DEFINEHASHING
01195 define = PC_FindHashedDefine(source->definehash, token.string);
01196 #else
01197 define = PC_FindDefine(source->defines, token.string);
01198 #endif //DEFINEHASHING
01199 if (define)
01200 {
01201 if (define->flags & DEFINE_FIXED)
01202 {
01203 SourceError(source, "can't redefine %s", token.string);
01204 return qfalse;
01205 }
01206 SourceWarning(source, "redefinition of %s", token.string);
01207
01208 PC_UnreadSourceToken(source, &token);
01209 if (!PC_Directive_undef(source)) return qfalse;
01210
01211 #if DEFINEHASHING
01212 define = PC_FindHashedDefine(source->definehash, token.string);
01213 #else
01214 define = PC_FindDefine(source->defines, token.string);
01215 #endif //DEFINEHASHING
01216 }
01217
01218 define = (define_t *) GetMemory(sizeof(define_t) + strlen(token.string) + 1);
01219 Com_Memset(define, 0, sizeof(define_t));
01220 define->name = (char *) define + sizeof(define_t);
01221 strcpy(define->name, token.string);
01222
01223 #if DEFINEHASHING
01224 PC_AddDefineToHash(define, source->definehash);
01225 #else //DEFINEHASHING
01226 define->next = source->defines;
01227 source->defines = define;
01228 #endif //DEFINEHASHING
01229
01230 if (!PC_ReadLine(source, &token)) return qtrue;
01231
01232 if (!PC_WhiteSpaceBeforeToken(&token) && !strcmp(token.string,