l_script.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. /*****************************************************************************
  19. * name: l_script.c
  20. *
  21. * desc: lexicographical parser
  22. *
  23. * $Archive: /MissionPack/code/botlib/l_script.c $
  24. *
  25. *****************************************************************************/
  26. //#define SCREWUP
  27. //#define BOTLIB
  28. //#define MEQCC
  29. //#define BSPC
  30. #ifdef SCREWUP
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <limits.h>
  34. #include <string.h>
  35. #include <stdarg.h>
  36. #include "l_memory.h"
  37. #include "l_script.h"
  38. typedef enum {qfalse, qtrue} qboolean;
  39. #endif //SCREWUP
  40. #ifdef BOTLIB
  41. //include files for usage in the bot library
  42. #include "../game/q_shared.h"
  43. #include "../game/botlib.h"
  44. #include "be_interface.h"
  45. #include "l_script.h"
  46. #include "l_memory.h"
  47. #include "l_log.h"
  48. #include "l_libvar.h"
  49. #endif //BOTLIB
  50. #ifdef MEQCC
  51. //include files for usage in MrElusive's QuakeC Compiler
  52. #include "qcc.h"
  53. #include "l_script.h"
  54. #include "l_memory.h"
  55. #include "l_log.h"
  56. #define qtrue true
  57. #define qfalse false
  58. #endif //MEQCC
  59. #ifdef BSPC
  60. //include files for usage in the BSP Converter
  61. #include "../bspc/qbsp.h"
  62. #include "../bspc/l_log.h"
  63. #include "../bspc/l_mem.h"
  64. #define qtrue true
  65. #define qfalse false
  66. #endif //BSPC
  67. #define PUNCTABLE
  68. //longer punctuations first
  69. punctuation_t default_punctuations[] =
  70. {
  71. //binary operators
  72. {">>=",P_RSHIFT_ASSIGN, NULL},
  73. {"<<=",P_LSHIFT_ASSIGN, NULL},
  74. //
  75. {"...",P_PARMS, NULL},
  76. //define merge operator
  77. {"##",P_PRECOMPMERGE, NULL},
  78. //logic operators
  79. {"&&",P_LOGIC_AND, NULL},
  80. {"||",P_LOGIC_OR, NULL},
  81. {">=",P_LOGIC_GEQ, NULL},
  82. {"<=",P_LOGIC_LEQ, NULL},
  83. {"==",P_LOGIC_EQ, NULL},
  84. {"!=",P_LOGIC_UNEQ, NULL},
  85. //arithmatic operators
  86. {"*=",P_MUL_ASSIGN, NULL},
  87. {"/=",P_DIV_ASSIGN, NULL},
  88. {"%=",P_MOD_ASSIGN, NULL},
  89. {"+=",P_ADD_ASSIGN, NULL},
  90. {"-=",P_SUB_ASSIGN, NULL},
  91. {"++",P_INC, NULL},
  92. {"--",P_DEC, NULL},
  93. //binary operators
  94. {"&=",P_BIN_AND_ASSIGN, NULL},
  95. {"|=",P_BIN_OR_ASSIGN, NULL},
  96. {"^=",P_BIN_XOR_ASSIGN, NULL},
  97. {">>",P_RSHIFT, NULL},
  98. {"<<",P_LSHIFT, NULL},
  99. //reference operators
  100. {"->",P_POINTERREF, NULL},
  101. //C++
  102. {"::",P_CPP1, NULL},
  103. {".*",P_CPP2, NULL},
  104. //arithmatic operators
  105. {"*",P_MUL, NULL},
  106. {"/",P_DIV, NULL},
  107. {"%",P_MOD, NULL},
  108. {"+",P_ADD, NULL},
  109. {"-",P_SUB, NULL},
  110. {"=",P_ASSIGN, NULL},
  111. //binary operators
  112. {"&",P_BIN_AND, NULL},
  113. {"|",P_BIN_OR, NULL},
  114. {"^",P_BIN_XOR, NULL},
  115. {"~",P_BIN_NOT, NULL},
  116. //logic operators
  117. {"!",P_LOGIC_NOT, NULL},
  118. {">",P_LOGIC_GREATER, NULL},
  119. {"<",P_LOGIC_LESS, NULL},
  120. //reference operator
  121. {".",P_REF, NULL},
  122. //seperators
  123. {",",P_COMMA, NULL},
  124. {";",P_SEMICOLON, NULL},
  125. //label indication
  126. {":",P_COLON, NULL},
  127. //if statement
  128. {"?",P_QUESTIONMARK, NULL},
  129. //embracements
  130. {"(",P_PARENTHESESOPEN, NULL},
  131. {")",P_PARENTHESESCLOSE, NULL},
  132. {"{",P_BRACEOPEN, NULL},
  133. {"}",P_BRACECLOSE, NULL},
  134. {"[",P_SQBRACKETOPEN, NULL},
  135. {"]",P_SQBRACKETCLOSE, NULL},
  136. //
  137. {"\\",P_BACKSLASH, NULL},
  138. //precompiler operator
  139. {"#",P_PRECOMP, NULL},
  140. #ifdef DOLLAR
  141. {"$",P_DOLLAR, NULL},
  142. #endif //DOLLAR
  143. {NULL, 0}
  144. };
  145. #ifdef BSPC
  146. char basefolder[MAX_PATH];
  147. #else
  148. char basefolder[MAX_QPATH];
  149. #endif
  150. //===========================================================================
  151. //
  152. // Parameter: -
  153. // Returns: -
  154. // Changes Globals: -
  155. //===========================================================================
  156. void PS_CreatePunctuationTable(script_t *script, punctuation_t *punctuations)
  157. {
  158. int i;
  159. punctuation_t *p, *lastp, *newp;
  160. //get memory for the table
  161. if (!script->punctuationtable) script->punctuationtable = (punctuation_t **)
  162. GetMemory(256 * sizeof(punctuation_t *));
  163. Com_Memset(script->punctuationtable, 0, 256 * sizeof(punctuation_t *));
  164. //add the punctuations in the list to the punctuation table
  165. for (i = 0; punctuations[i].p; i++)
  166. {
  167. newp = &punctuations[i];
  168. lastp = NULL;
  169. //sort the punctuations in this table entry on length (longer punctuations first)
  170. for (p = script->punctuationtable[(unsigned int) newp->p[0]]; p; p = p->next)
  171. {
  172. if (strlen(p->p) < strlen(newp->p))
  173. {
  174. newp->next = p;
  175. if (lastp) lastp->next = newp;
  176. else script->punctuationtable[(unsigned int) newp->p[0]] = newp;
  177. break;
  178. } //end if
  179. lastp = p;
  180. } //end for
  181. if (!p)
  182. {
  183. newp->next = NULL;
  184. if (lastp) lastp->next = newp;
  185. else script->punctuationtable[(unsigned int) newp->p[0]] = newp;
  186. } //end if
  187. } //end for
  188. } //end of the function PS_CreatePunctuationTable
  189. //===========================================================================
  190. //
  191. // Parameter: -
  192. // Returns: -
  193. // Changes Globals: -
  194. //===========================================================================
  195. char *PunctuationFromNum(script_t *script, int num)
  196. {
  197. int i;
  198. for (i = 0; script->punctuations[i].p; i++)
  199. {
  200. if (script->punctuations[i].n == num) return script->punctuations[i].p;
  201. } //end for
  202. return "unkown punctuation";
  203. } //end of the function PunctuationFromNum
  204. //===========================================================================
  205. //
  206. // Parameter: -
  207. // Returns: -
  208. // Changes Globals: -
  209. //===========================================================================
  210. void QDECL ScriptError(script_t *script, char *str, ...)
  211. {
  212. char text[1024];
  213. va_list ap;
  214. if (script->flags & SCFL_NOERRORS) return;
  215. va_start(ap, str);
  216. vsprintf(text, str, ap);
  217. va_end(ap);
  218. #ifdef BOTLIB
  219. botimport.Print(PRT_ERROR, "file %s, line %d: %s\n", script->filename, script->line, text);
  220. #endif //BOTLIB
  221. #ifdef MEQCC
  222. printf("error: file %s, line %d: %s\n", script->filename, script->line, text);
  223. #endif //MEQCC
  224. #ifdef BSPC
  225. Log_Print("error: file %s, line %d: %s\n", script->filename, script->line, text);
  226. #endif //BSPC
  227. } //end of the function ScriptError
  228. //===========================================================================
  229. //
  230. // Parameter: -
  231. // Returns: -
  232. // Changes Globals: -
  233. //===========================================================================
  234. void QDECL ScriptWarning(script_t *script, char *str, ...)
  235. {
  236. char text[1024];
  237. va_list ap;
  238. if (script->flags & SCFL_NOWARNINGS) return;
  239. va_start(ap, str);
  240. vsprintf(text, str, ap);
  241. va_end(ap);
  242. #ifdef BOTLIB
  243. botimport.Print(PRT_WARNING, "file %s, line %d: %s\n", script->filename, script->line, text);
  244. #endif //BOTLIB
  245. #ifdef MEQCC
  246. printf("warning: file %s, line %d: %s\n", script->filename, script->line, text);
  247. #endif //MEQCC
  248. #ifdef BSPC
  249. Log_Print("warning: file %s, line %d: %s\n", script->filename, script->line, text);
  250. #endif //BSPC
  251. } //end of the function ScriptWarning
  252. //===========================================================================
  253. //
  254. // Parameter: -
  255. // Returns: -
  256. // Changes Globals: -
  257. //===========================================================================
  258. void SetScriptPunctuations(script_t *script, punctuation_t *p)
  259. {
  260. #ifdef PUNCTABLE
  261. if (p) PS_CreatePunctuationTable(script, p);
  262. else PS_CreatePunctuationTable(script, default_punctuations);
  263. #endif //PUNCTABLE
  264. if (p) script->punctuations = p;
  265. else script->punctuations = default_punctuations;
  266. } //end of the function SetScriptPunctuations
  267. //============================================================================
  268. // Reads spaces, tabs, C-like comments etc.
  269. // When a newline character is found the scripts line counter is increased.
  270. //
  271. // Parameter: -
  272. // Returns: -
  273. // Changes Globals: -
  274. //============================================================================
  275. int PS_ReadWhiteSpace(script_t *script)
  276. {
  277. while(1)
  278. {
  279. //skip white space
  280. while(*script->script_p <= ' ')
  281. {
  282. if (!*script->script_p) return 0;
  283. if (*script->script_p == '\n') script->line++;
  284. script->script_p++;
  285. } //end while
  286. //skip comments
  287. if (*script->script_p == '/')
  288. {
  289. //comments //
  290. if (*(script->script_p+1) == '/')
  291. {
  292. script->script_p++;
  293. do
  294. {
  295. script->script_p++;
  296. if (!*script->script_p) return 0;
  297. } //end do
  298. while(*script->script_p != '\n');
  299. script->line++;
  300. script->script_p++;
  301. if (!*script->script_p) return 0;
  302. continue;
  303. } //end if
  304. //comments /* */
  305. else if (*(script->script_p+1) == '*')
  306. {
  307. script->script_p++;
  308. do
  309. {
  310. script->script_p++;
  311. if (!*script->script_p) return 0;
  312. if (*script->script_p == '\n') script->line++;
  313. } //end do
  314. while(!(*script->script_p == '*' && *(script->script_p+1) == '/'));
  315. script->script_p++;
  316. if (!*script->script_p) return 0;
  317. script->script_p++;
  318. if (!*script->script_p) return 0;
  319. continue;
  320. } //end if
  321. } //end if
  322. break;
  323. } //end while
  324. return 1;
  325. } //end of the function PS_ReadWhiteSpace
  326. //============================================================================
  327. // Reads an escape character.
  328. //
  329. // Parameter: script : script to read from
  330. // ch : place to store the read escape character
  331. // Returns: -
  332. // Changes Globals: -
  333. //============================================================================
  334. int PS_ReadEscapeCharacter(script_t *script, char *ch)
  335. {
  336. int c, val, i;
  337. //step over the leading '\\'
  338. script->script_p++;
  339. //determine the escape character
  340. switch(*script->script_p)
  341. {
  342. case '\\': c = '\\'; break;
  343. case 'n': c = '\n'; break;
  344. case 'r': c = '\r'; break;
  345. case 't': c = '\t'; break;
  346. case 'v': c = '\v'; break;
  347. case 'b': c = '\b'; break;
  348. case 'f': c = '\f'; break;
  349. case 'a': c = '\a'; break;
  350. case '\'': c = '\''; break;
  351. case '\"': c = '\"'; break;
  352. case '\?': c = '\?'; break;
  353. case 'x':
  354. {
  355. script->script_p++;
  356. for (i = 0, val = 0; ; i++, script->script_p++)
  357. {
  358. c = *script->script_p;
  359. if (c >= '0' && c <= '9') c = c - '0';
  360. else if (c >= 'A' && c <= 'Z') c = c - 'A' + 10;
  361. else if (c >= 'a' && c <= 'z') c = c - 'a' + 10;
  362. else break;
  363. val = (val << 4) + c;
  364. } //end for
  365. script->script_p--;
  366. if (val > 0xFF)
  367. {
  368. ScriptWarning(script, "too large value in escape character");
  369. val = 0xFF;
  370. } //end if
  371. c = val;
  372. break;
  373. } //end case
  374. default: //NOTE: decimal ASCII code, NOT octal
  375. {
  376. if (*script->script_p < '0' || *script->script_p > '9') ScriptError(script, "unknown escape char");
  377. for (i = 0, val = 0; ; i++, script->script_p++)
  378. {
  379. c = *script->script_p;
  380. if (c >= '0' && c <= '9') c = c - '0';
  381. else break;
  382. val = val * 10 + c;
  383. } //end for
  384. script->script_p--;
  385. if (val > 0xFF)
  386. {
  387. ScriptWarning(script, "too large value in escape character");
  388. val = 0xFF;
  389. } //end if
  390. c = val;
  391. break;
  392. } //end default
  393. } //end switch
  394. //step over the escape character or the last digit of the number
  395. script->script_p++;
  396. //store the escape character
  397. *ch = c;
  398. //succesfully read escape character
  399. return 1;
  400. } //end of the function PS_ReadEscapeCharacter
  401. //============================================================================
  402. // Reads C-like string. Escape characters are interpretted.
  403. // Quotes are included with the string.
  404. // Reads two strings with a white space between them as one string.
  405. //
  406. // Parameter: script : script to read from
  407. // token : buffer to store the string
  408. // Returns: qtrue when a string was read succesfully
  409. // Changes Globals: -
  410. //============================================================================
  411. int PS_ReadString(script_t *script, token_t *token, int quote)
  412. {
  413. int len, tmpline;
  414. char *tmpscript_p;
  415. if (quote == '\"') token->type = TT_STRING;
  416. else token->type = TT_LITERAL;
  417. len = 0;
  418. //leading quote
  419. token->string[len++] = *script->script_p++;
  420. //
  421. while(1)
  422. {
  423. //minus 2 because trailing double quote and zero have to be appended
  424. if (len >= MAX_TOKEN - 2)
  425. {
  426. ScriptError(script, "string longer than MAX_TOKEN = %d", MAX_TOKEN);
  427. return 0;
  428. } //end if
  429. //if there is an escape character and
  430. //if escape characters inside a string are allowed
  431. if (*script->script_p == '\\' && !(script->flags & SCFL_NOSTRINGESCAPECHARS))
  432. {
  433. if (!PS_ReadEscapeCharacter(script, &token->string[len]))
  434. {
  435. token->string[len] = 0;
  436. return 0;
  437. } //end if
  438. len++;
  439. } //end if
  440. //if a trailing quote
  441. else if (*script->script_p == quote)
  442. {
  443. //step over the double quote
  444. script->script_p++;
  445. //if white spaces in a string are not allowed
  446. if (script->flags & SCFL_NOSTRINGWHITESPACES) break;
  447. //
  448. tmpscript_p = script->script_p;
  449. tmpline = script->line;
  450. //read unusefull stuff between possible two following strings
  451. if (!PS_ReadWhiteSpace(script))
  452. {
  453. script->script_p = tmpscript_p;
  454. script->line = tmpline;
  455. break;
  456. } //end if
  457. //if there's no leading double qoute
  458. if (*script->script_p != quote)
  459. {
  460. script->script_p = tmpscript_p;
  461. script->line = tmpline;
  462. break;
  463. } //end if
  464. //step over the new leading double quote
  465. script->script_p++;
  466. } //end if
  467. else
  468. {
  469. if (*script->script_p == '\0')
  470. {
  471. token->string[len] = 0;
  472. ScriptError(script, "missing trailing quote");
  473. return 0;
  474. } //end if
  475. if (*script->script_p == '\n')
  476. {
  477. token->string[len] = 0;
  478. ScriptError(script, "newline inside string %s", token->string);
  479. return 0;
  480. } //end if
  481. token->string[len++] = *script->script_p++;
  482. } //end else
  483. } //end while
  484. //trailing quote
  485. token->string[len++] = quote;
  486. //end string with a zero
  487. token->string[len] = '\0';
  488. //the sub type is the length of the string
  489. token->subtype = len;
  490. return 1;
  491. } //end of the function PS_ReadString
  492. //============================================================================
  493. //
  494. // Parameter: -
  495. // Returns: -
  496. // Changes Globals: -
  497. //============================================================================
  498. int PS_ReadName(script_t *script, token_t *token)
  499. {
  500. int len = 0;
  501. char c;
  502. token->type = TT_NAME;
  503. do
  504. {
  505. token->string[len++] = *script->script_p++;
  506. if (len >= MAX_TOKEN)
  507. {
  508. ScriptError(script, "name longer than MAX_TOKEN = %d", MAX_TOKEN);
  509. return 0;
  510. } //end if
  511. c = *script->script_p;
  512. } while ((c >= 'a' && c <= 'z') ||
  513. (c >= 'A' && c <= 'Z') ||
  514. (c >= '0' && c <= '9') ||
  515. c == '_');
  516. token->string[len] = '\0';
  517. //the sub type is the length of the name
  518. token->subtype = len;
  519. return 1;
  520. } //end of the function PS_ReadName
  521. //============================================================================
  522. //
  523. // Parameter: -
  524. // Returns: -
  525. // Changes Globals: -
  526. //============================================================================
  527. void NumberValue(char *string, int subtype, unsigned long int *intvalue,
  528. long double *floatvalue)
  529. {
  530. unsigned long int dotfound = 0;
  531. *intvalue = 0;
  532. *floatvalue = 0;
  533. //floating point number
  534. if (subtype & TT_FLOAT)
  535. {
  536. while(*string)
  537. {
  538. if (*string == '.')
  539. {
  540. if (dotfound) return;
  541. dotfound = 10;
  542. string++;
  543. } //end if
  544. if (dotfound)
  545. {
  546. *floatvalue = *floatvalue + (long double) (*string - '0') /
  547. (long double) dotfound;
  548. dotfound *= 10;
  549. } //end if
  550. else
  551. {
  552. *floatvalue = *floatvalue * 10.0 + (long double) (*string - '0');
  553. } //end else
  554. string++;
  555. } //end while
  556. *intvalue = (unsigned long) *floatvalue;
  557. } //end if
  558. else if (subtype & TT_DECIMAL)
  559. {
  560. while(*string) *intvalue = *intvalue * 10 + (*string++ - '0');
  561. *floatvalue = *intvalue;
  562. } //end else if
  563. else if (subtype & TT_HEX)
  564. {
  565. //step over the leading 0x or 0X
  566. string += 2;
  567. while(*string)
  568. {
  569. *intvalue <<= 4;
  570. if (*string >= 'a' && *string <= 'f') *intvalue += *string - 'a' + 10;
  571. else if (*string >= 'A' && *string <= 'F') *intvalue += *string - 'A' + 10;
  572. else *intvalue += *string - '0';
  573. string++;
  574. } //end while
  575. *floatvalue = *intvalue;
  576. } //end else if
  577. else if (subtype & TT_OCTAL)
  578. {
  579. //step over the first zero
  580. string += 1;
  581. while(*string) *intvalue = (*intvalue << 3) + (*string++ - '0');
  582. *floatvalue = *intvalue;
  583. } //end else if
  584. else if (subtype & TT_BINARY)
  585. {
  586. //step over the leading 0b or 0B
  587. string += 2;
  588. while(*string) *intvalue = (*intvalue << 1) + (*string++ - '0');
  589. *floatvalue = *intvalue;
  590. } //end else if
  591. } //end of the function NumberValue
  592. //============================================================================
  593. //
  594. // Parameter: -
  595. // Returns: -
  596. // Changes Globals: -
  597. //============================================================================
  598. int PS_ReadNumber(script_t *script, token_t *token)
  599. {
  600. int len = 0, i;
  601. int octal, dot;
  602. char c;
  603. // unsigned long int intvalue = 0;
  604. // long double floatvalue = 0;
  605. token->type = TT_NUMBER;
  606. //check for a hexadecimal number
  607. if (*script->script_p == '0' &&
  608. (*(script->script_p + 1) == 'x' ||
  609. *(script->script_p + 1) == 'X'))
  610. {
  611. token->string[len++] = *script->script_p++;
  612. token->string[len++] = *script->script_p++;
  613. c = *script->script_p;
  614. //hexadecimal
  615. while((c >= '0' && c <= '9') ||
  616. (c >= 'a' && c <= 'f') ||
  617. (c >= 'A' && c <= 'A'))
  618. {
  619. token->string[len++] = *script->script_p++;
  620. if (len >= MAX_TOKEN)
  621. {
  622. ScriptError(script, "hexadecimal number longer than MAX_TOKEN = %d", MAX_TOKEN);
  623. return 0;
  624. } //end if
  625. c = *script->script_p;
  626. } //end while
  627. token->subtype |= TT_HEX;
  628. } //end if
  629. #ifdef BINARYNUMBERS
  630. //check for a binary number
  631. else if (*script->script_p == '0' &&
  632. (*(script->script_p + 1) == 'b' ||
  633. *(script->script_p + 1) == 'B'))
  634. {
  635. token->string[len++] = *script->script_p++;
  636. token->string[len++] = *script->script_p++;
  637. c = *script->script_p;
  638. //binary
  639. while(c == '0' || c == '1')
  640. {
  641. token->string[len++] = *script->script_p++;
  642. if (len >= MAX_TOKEN)
  643. {
  644. ScriptError(script, "binary number longer than MAX_TOKEN = %d", MAX_TOKEN);
  645. return 0;
  646. } //end if
  647. c = *script->script_p;
  648. } //end while
  649. token->subtype |= TT_BINARY;
  650. } //end if
  651. #endif //BINARYNUMBERS
  652. else //decimal or octal integer or floating point number
  653. {
  654. octal = qfalse;
  655. dot = qfalse;
  656. if (*script->script_p == '0') octal = qtrue;
  657. while(1)
  658. {
  659. c = *script->script_p;
  660. if (c == '.') dot = qtrue;
  661. else if (c == '8' || c == '9') octal = qfalse;
  662. else if (c < '0' || c > '9') break;
  663. token->string[len++] = *script->script_p++;
  664. if (len >= MAX_TOKEN - 1)
  665. {
  666. ScriptError(script, "number longer than MAX_TOKEN = %d", MAX_TOKEN);
  667. return 0;
  668. } //end if
  669. } //end while
  670. if (octal) token->subtype |= TT_OCTAL;
  671. else token->subtype |= TT_DECIMAL;
  672. if (dot) token->subtype |= TT_FLOAT;
  673. } //end else
  674. for (i = 0; i < 2; i++)
  675. {
  676. c = *script->script_p;
  677. //check for a LONG number
  678. if ( (c == 'l' || c == 'L') // bk001204 - brackets
  679. && !(token->subtype & TT_LONG))
  680. {
  681. script->script_p++;
  682. token->subtype |= TT_LONG;
  683. } //end if
  684. //check for an UNSIGNED number
  685. else if ( (c == 'u' || c == 'U') // bk001204 - brackets
  686. && !(token->subtype & (TT_UNSIGNED | TT_FLOAT)))
  687. {
  688. script->script_p++;
  689. token->subtype |= TT_UNSIGNED;
  690. } //end if
  691. } //end for
  692. token->string[len] = '\0';
  693. #ifdef NUMBERVALUE
  694. NumberValue(token->string, token->subtype, &token->intvalue, &token->floatvalue);
  695. #endif //NUMBERVALUE
  696. if (!(token->subtype & TT_FLOAT)) token->subtype |= TT_INTEGER;
  697. return 1;
  698. } //end of the function PS_ReadNumber
  699. //============================================================================
  700. //
  701. // Parameter: -
  702. // Returns: -
  703. // Changes Globals: -
  704. //============================================================================
  705. int PS_ReadLiteral(script_t *script, token_t *token)
  706. {
  707. token->type = TT_LITERAL;
  708. //first quote
  709. token->string[0] = *script->script_p++;
  710. //check for end of file
  711. if (!*script->script_p)
  712. {
  713. ScriptError(script, "end of file before trailing \'");
  714. return 0;
  715. } //end if
  716. //if it is an escape character
  717. if (*script->script_p == '\\')
  718. {
  719. if (!PS_ReadEscapeCharacter(script, &token->string[1])) return 0;
  720. } //end if
  721. else
  722. {
  723. token->string[1] = *script->script_p++;
  724. } //end else
  725. //check for trailing quote
  726. if (*script->script_p != '\'')
  727. {
  728. ScriptWarning(script, "too many characters in literal, ignored");
  729. while(*script->script_p &&
  730. *script->script_p != '\'' &&
  731. *script->script_p != '\n')
  732. {
  733. script->script_p++;
  734. } //end while
  735. if (*script->script_p == '\'') script->script_p++;
  736. } //end if
  737. //store the trailing quote
  738. token->string[2] = *script->script_p++;
  739. //store trailing zero to end the string
  740. token->string[3] = '\0';
  741. //the sub type is the integer literal value
  742. token->subtype = token->string[1];
  743. //
  744. return 1;
  745. } //end of the function PS_ReadLiteral
  746. //============================================================================
  747. //
  748. // Parameter: -
  749. // Returns: -
  750. // Changes Globals: -
  751. //============================================================================
  752. int PS_ReadPunctuation(script_t *script, token_t *token)
  753. {
  754. int len;
  755. char *p;
  756. punctuation_t *punc;
  757. #ifdef PUNCTABLE
  758. for (punc = script->punctuationtable[(unsigned int)*script->script_p]; punc; punc = punc->next)
  759. {
  760. #else
  761. int i;
  762. for (i = 0; script->punctuations[i].p; i++)
  763. {
  764. punc = &script->punctuations[i];
  765. #endif //PUNCTABLE
  766. p = punc->p;
  767. len = strlen(p);
  768. //if the script contains at least as much characters as the punctuation
  769. if (script->script_p + len <= script->end_p)
  770. {
  771. //if the script contains the punctuation
  772. if (!strncmp(script->script_p, p, len))
  773. {
  774. strncpy(token->string, p, MAX_TOKEN);
  775. script->script_p += len;
  776. token->type = TT_PUNCTUATION;
  777. //sub type is the number of the punctuation
  778. token->subtype = punc->n;
  779. return 1;
  780. } //end if
  781. } //end if
  782. } //end for
  783. return 0;
  784. } //end of the function PS_ReadPunctuation
  785. //============================================================================
  786. //
  787. // Parameter: -
  788. // Returns: -
  789. // Changes Globals: -
  790. //============================================================================
  791. int PS_ReadPrimitive(script_t *script, token_t *token)
  792. {
  793. int len;
  794. len = 0;
  795. while(*script->script_p > ' ' && *script->script_p != ';')
  796. {
  797. if (len >= MAX_TOKEN)
  798. {
  799. ScriptError(script, "primitive token longer than MAX_TOKEN = %d", MAX_TOKEN);
  800. return 0;
  801. } //end if
  802. token->string[len++] = *script->script_p++;
  803. } //end while
  804. token->string[len] = 0;
  805. //copy the token into the script structure
  806. Com_Memcpy(&script->token, token, sizeof(token_t));
  807. //primitive reading successfull
  808. return 1;
  809. } //end of the function PS_ReadPrimitive
  810. //============================================================================
  811. //
  812. // Parameter: -
  813. // Returns: -
  814. // Changes Globals: -
  815. //============================================================================
  816. int PS_ReadToken(script_t *script, token_t *token)
  817. {
  818. //if there is a token available (from UnreadToken)
  819. if (script->tokenavailable)
  820. {
  821. script->tokenavailable = 0;
  822. Com_Memcpy(token, &script->token, sizeof(token_t));
  823. return 1;
  824. } //end if
  825. //save script pointer
  826. script->lastscript_p = script->script_p;
  827. //save line counter
  828. script->lastline = script->line;
  829. //clear the token stuff
  830. Com_Memset(token, 0, sizeof(token_t));
  831. //start of the white space
  832. script->whitespace_p = script->script_p;
  833. token->whitespace_p = script->script_p;
  834. //read unusefull stuff
  835. if (!PS_ReadWhiteSpace(script)) return 0;
  836. //end of the white space
  837. script->endwhitespace_p = script->script_p;
  838. token->endwhitespace_p = script->script_p;
  839. //line the token is on
  840. token->line = script->line;
  841. //number of lines crossed before token
  842. token->linescrossed = script->line - script->lastline;
  843. //if there is a leading double quote
  844. if (*script->script_p == '\"')
  845. {
  846. if (!PS_ReadString(script, token, '\"')) return 0;
  847. } //end if
  848. //if an literal
  849. else if (*script->script_p == '\'')
  850. {
  851. //if (!PS_ReadLiteral(script, token)) return 0;
  852. if (!PS_ReadString(script, token, '\'')) return 0;
  853. } //end if
  854. //if there is a number
  855. else if ((*script->script_p >= '0' && *script->script_p <= '9') ||
  856. (*script->script_p == '.' &&
  857. (*(script->script_p + 1) >= '0' && *(script->script_p + 1) <= '9')))
  858. {
  859. if (!PS_ReadNumber(script, token)) return 0;
  860. } //end if
  861. //if this is a primitive script
  862. else if (script->flags & SCFL_PRIMITIVE)
  863. {
  864. return PS_ReadPrimitive(script, token);
  865. } //end else if
  866. //if there is a name
  867. else if ((*script->script_p >= 'a' && *script->script_p <= 'z') ||
  868. (*script->script_p >= 'A' && *script->script_p <= 'Z') ||
  869. *script->script_p == '_')
  870. {
  871. if (!PS_ReadName(script, token)) return 0;
  872. } //end if
  873. //check for punctuations
  874. else if (!PS_ReadPunctuation(script, token))
  875. {
  876. ScriptError(script, "can't read token");
  877. return 0;
  878. } //end if
  879. //copy the token into the script structure
  880. Com_Memcpy(&script->token, token, sizeof(token_t));
  881. //succesfully read a token
  882. return 1;
  883. } //end of the function PS_ReadToken
  884. //============================================================================
  885. //
  886. // Parameter: -
  887. // Returns: -
  888. // Changes Globals: -
  889. //============================================================================
  890. int PS_ExpectTokenString(script_t *script, char *string)
  891. {
  892. token_t token;
  893. if (!PS_ReadToken(script, &token))
  894. {
  895. ScriptError(script, "couldn't find expected %s", string);
  896. return 0;
  897. } //end if
  898. if (strcmp(token.string, string))
  899. {
  900. ScriptError(script, "expected %s, found %s", string, token.string);
  901. return 0;
  902. } //end if
  903. return 1;
  904. } //end of the function PS_ExpectToken
  905. //============================================================================
  906. //
  907. // Parameter: -
  908. // Returns: -
  909. // Changes Globals: -
  910. //============================================================================
  911. int PS_ExpectTokenType(script_t *script, int type, int subtype, token_t *token)
  912. {
  913. char str[MAX_TOKEN];
  914. if (!PS_ReadToken(script, token))
  915. {
  916. ScriptError(script, "couldn't read expected token");
  917. return 0;
  918. } //end if
  919. if (token->type != type)
  920. {
  921. if (type == TT_STRING) strcpy(str, "string");
  922. if (type == TT_LITERAL) strcpy(str, "literal");
  923. if (type == TT_NUMBER) strcpy(str, "number");
  924. if (type == TT_NAME) strcpy(str, "name");
  925. if (type == TT_PUNCTUATION) strcpy(str, "punctuation");
  926. ScriptError(script, "expected a %s, found %s", str, token->string);
  927. return 0;
  928. } //end if
  929. if (token->type == TT_NUMBER)
  930. {
  931. if ((token->subtype & subtype) != subtype)
  932. {
  933. if (subtype & TT_DECIMAL) strcpy(str, "decimal");
  934. if (subtype & TT_HEX) strcpy(str, "hex");
  935. if (subtype & TT_OCTAL) strcpy(str, "octal");
  936. if (subtype & TT_BINARY) strcpy(str, "binary");
  937. if (subtype & TT_LONG) strcat(str, " long");
  938. if (subtype & TT_UNSIGNED) strcat(str, " unsigned");
  939. if (subtype & TT_FLOAT) strcat(str, " float");
  940. if (subtype & TT_INTEGER) strcat(str, " integer");
  941. ScriptError(script, "expected %s, found %s", str, token->string);
  942. return 0;
  943. } //end if
  944. } //end if
  945. else if (token->type == TT_PUNCTUATION)
  946. {
  947. if (subtype < 0)
  948. {
  949. ScriptError(script, "BUG: wrong punctuation subtype");
  950. return 0;
  951. } //end if
  952. if (token->subtype != subtype)
  953. {
  954. ScriptError(script, "expected %s, found %s",
  955. script->punctuations[subtype], token->string);
  956. return 0;
  957. } //end if
  958. } //end else if
  959. return 1;
  960. } //end of the function PS_ExpectTokenType
  961. //============================================================================
  962. //
  963. // Parameter: -
  964. // Returns: -
  965. // Changes Globals: -
  966. //============================================================================
  967. int PS_ExpectAnyToken(script_t *script, token_t *token)
  968. {
  969. if (!PS_ReadToken(script, token))
  970. {
  971. ScriptError(script, "couldn't read expected token");
  972. return 0;
  973. } //end if
  974. else
  975. {
  976. return 1;
  977. } //end else
  978. } //end of the function PS_ExpectAnyToken
  979. //============================================================================
  980. //
  981. // Parameter: -
  982. // Returns: -
  983. // Changes Globals: -
  984. //============================================================================
  985. int PS_CheckTokenString(script_t *script, char *string)
  986. {
  987. token_t tok;
  988. if (!PS_ReadToken(script, &tok)) return 0;
  989. //if the token is available
  990. if (!strcmp(tok.string, string)) return 1;
  991. //token not available
  992. script->script_p = script->lastscript_p;
  993. return 0;
  994. } //end of the function PS_CheckTokenString
  995. //============================================================================
  996. //
  997. // Parameter: -
  998. // Returns: -
  999. // Changes Globals: -
  1000. //============================================================================
  1001. int PS_CheckTokenType(script_t *script, int type, int subtype, token_t *token)
  1002. {
  1003. token_t tok;
  1004. if (!PS_ReadToken(script, &tok)) return 0;
  1005. //if the type matches
  1006. if (tok.type == type &&
  1007. (tok.subtype & subtype) == subtype)
  1008. {
  1009. Com_Memcpy(token, &tok, sizeof(token_t));
  1010. return 1;
  1011. } //end if
  1012. //token is not available
  1013. script->script_p = script->lastscript_p;
  1014. return 0;
  1015. } //end of the function PS_CheckTokenType
  1016. //============================================================================
  1017. //
  1018. // Parameter: -
  1019. // Returns: -
  1020. // Changes Globals: -
  1021. //============================================================================
  1022. int PS_SkipUntilString(script_t *script, char *string)
  1023. {
  1024. token_t token;
  1025. while(PS_ReadToken(script, &token))
  1026. {
  1027. if (!strcmp(token.string, string)) return 1;
  1028. } //end while
  1029. return 0;
  1030. } //end of the function PS_SkipUntilString
  1031. //============================================================================
  1032. //
  1033. // Parameter: -
  1034. // Returns: -
  1035. // Changes Globals: -
  1036. //============================================================================
  1037. void PS_UnreadLastToken(script_t *script)
  1038. {
  1039. script->tokenavailable = 1;
  1040. } //end of the function UnreadLastToken
  1041. //============================================================================
  1042. //
  1043. // Parameter: -
  1044. // Returns: -
  1045. // Changes Globals: -
  1046. //============================================================================
  1047. void PS_UnreadToken(script_t *script, token_t *token)
  1048. {
  1049. Com_Memcpy(&script->token, token, sizeof(token_t));
  1050. script->tokenavailable = 1;
  1051. } //end of the function UnreadToken
  1052. //============================================================================
  1053. // returns the next character of the read white space, returns NULL if none
  1054. //
  1055. // Parameter: -
  1056. // Returns: -
  1057. // Changes Globals: -
  1058. //============================================================================
  1059. char PS_NextWhiteSpaceChar(script_t *script)
  1060. {
  1061. if (script->whitespace_p != script->endwhitespace_p)
  1062. {
  1063. return *script->whitespace_p++;
  1064. } //end if
  1065. else
  1066. {
  1067. return 0;
  1068. } //end else
  1069. } //end of the function PS_NextWhiteSpaceChar
  1070. //============================================================================
  1071. //
  1072. // Parameter: -
  1073. // Returns: -
  1074. // Changes Globals: -
  1075. //============================================================================
  1076. void StripDoubleQuotes(char *string)
  1077. {
  1078. if (*string == '\"')
  1079. {
  1080. strcpy(string, string+1);
  1081. } //end if
  1082. if (string[strlen(string)-1] == '\"')
  1083. {
  1084. string[strlen(string)-1] = '\0';
  1085. } //end if
  1086. } //end of the function StripDoubleQuotes
  1087. //============================================================================
  1088. //
  1089. // Parameter: -
  1090. // Returns: -
  1091. // Changes Globals: -
  1092. //============================================================================
  1093. void StripSingleQuotes(char *string)
  1094. {
  1095. if (*string == '\'')
  1096. {
  1097. strcpy(string, string+1);
  1098. } //end if
  1099. if (string[strlen(string)-1] == '\'')
  1100. {
  1101. string[strlen(string)-1] = '\0';
  1102. } //end if
  1103. } //end of the function StripSingleQuotes
  1104. //============================================================================
  1105. //
  1106. // Parameter: -
  1107. // Returns: -
  1108. // Changes Globals: -
  1109. //============================================================================
  1110. long double ReadSignedFloat(script_t *script)
  1111. {
  1112. token_t token;
  1113. long double sign = 1;
  1114. PS_ExpectAnyToken(script, &token);
  1115. if (!strcmp(token.string, "-"))
  1116. {
  1117. sign = -1;
  1118. PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
  1119. } //end if
  1120. else if (token.type != TT_NUMBER)
  1121. {
  1122. ScriptError(script, "expected float value, found %s\n", token.string);
  1123. } //end else if
  1124. return sign * token.floatvalue;
  1125. } //end of the function ReadSignedFloat
  1126. //============================================================================
  1127. //
  1128. // Parameter: -
  1129. // Returns: -
  1130. // Changes Globals: -
  1131. //============================================================================
  1132. signed long int ReadSignedInt(script_t *script)
  1133. {
  1134. token_t token;
  1135. signed long int sign = 1;
  1136. PS_ExpectAnyToken(script, &token);
  1137. if (!strcmp(token.string, "-"))
  1138. {
  1139. sign = -1;
  1140. PS_ExpectTokenType(script, TT_NUMBER, TT_INTEGER, &token);
  1141. } //end if
  1142. else if (token.type != TT_NUMBER || token.subtype == TT_FLOAT)
  1143. {
  1144. ScriptError(script, "expected integer value, found %s\n", token.string);
  1145. } //end else if
  1146. return sign * token.intvalue;
  1147. } //end of the function ReadSignedInt
  1148. //============================================================================
  1149. //
  1150. // Parameter: -
  1151. // Returns: -
  1152. // Changes Globals: -
  1153. //============================================================================
  1154. void SetScriptFlags(script_t *script, int flags)
  1155. {
  1156. script->flags = flags;
  1157. } //end of the function SetScriptFlags
  1158. //============================================================================
  1159. //
  1160. // Parameter: -
  1161. // Returns: -
  1162. // Changes Globals: -
  1163. //============================================================================
  1164. int GetScriptFlags(script_t *script)
  1165. {
  1166. return script->flags;
  1167. } //end of the function GetScriptFlags
  1168. //============================================================================
  1169. //
  1170. // Parameter: -
  1171. // Returns: -
  1172. // Changes Globals: -
  1173. //============================================================================
  1174. void ResetScript(script_t *script)
  1175. {
  1176. //pointer in script buffer
  1177. script->script_p = script->buffer;
  1178. //pointer in script buffer before reading token
  1179. script->lastscript_p = script->buffer;
  1180. //begin of white space
  1181. script->whitespace_p = NULL;
  1182. //end of white space
  1183. script->endwhitespace_p = NULL;
  1184. //set if there's a token available in script->token
  1185. script->tokenavailable = 0;
  1186. //
  1187. script->line = 1;
  1188. script->lastline = 1;
  1189. //clear the saved token
  1190. Com_Memset(&script->token, 0, sizeof(token_t));
  1191. } //end of the function ResetScript
  1192. //============================================================================
  1193. // returns true if at the end of the script
  1194. //
  1195. // Parameter: -
  1196. // Returns: -
  1197. // Changes Globals: -
  1198. //============================================================================
  1199. int EndOfScript(script_t *script)
  1200. {
  1201. return script->script_p >= script->end_p;
  1202. } //end of the function EndOfScript
  1203. //============================================================================
  1204. //
  1205. // Parameter: -
  1206. // Returns: -
  1207. // Changes Globals: -
  1208. //============================================================================
  1209. int NumLinesCrossed(script_t *script)
  1210. {
  1211. return script->line - script->lastline;
  1212. } //end of the function NumLinesCrossed
  1213. //============================================================================
  1214. //
  1215. // Parameter: -
  1216. // Returns: -
  1217. // Changes Globals: -
  1218. //============================================================================
  1219. int ScriptSkipTo(script_t *script, char *value)
  1220. {
  1221. int len;
  1222. char firstchar;
  1223. firstchar = *value;
  1224. len = strlen(value);
  1225. do
  1226. {
  1227. if (!PS_ReadWhiteSpace(script)) return 0;
  1228. if (*script->script_p == firstchar)
  1229. {
  1230. if (!strncmp(script->script_p, value, len))
  1231. {
  1232. return 1;
  1233. } //end if
  1234. } //end if
  1235. script->script_p++;
  1236. } while(1);
  1237. } //end of the function ScriptSkipTo
  1238. #ifndef BOTLIB
  1239. //============================================================================
  1240. //
  1241. // Parameter: -
  1242. // Returns: -
  1243. // Changes Globals: -
  1244. //============================================================================
  1245. int FileLength(FILE *fp)
  1246. {
  1247. int pos;
  1248. int end;
  1249. pos = ftell(fp);
  1250. fseek(fp, 0, SEEK_END);
  1251. end = ftell(fp);
  1252. fseek(fp, pos, SEEK_SET);
  1253. return end;
  1254. } //end of the function FileLength
  1255. #endif
  1256. //============================================================================
  1257. //
  1258. // Parameter: -
  1259. // Returns: -
  1260. // Changes Globals: -
  1261. //============================================================================
  1262. script_t *LoadScriptFile(const char *filename)
  1263. {
  1264. #ifdef BOTLIB
  1265. fileHandle_t fp;
  1266. char pathname[MAX_QPATH];
  1267. #else
  1268. FILE *fp;
  1269. #endif
  1270. int length;
  1271. void *buffer;
  1272. script_t *script;
  1273. #ifdef BOTLIB
  1274. if (strlen(basefolder))
  1275. Com_sprintf(pathname, sizeof(pathname), "%s/%s", basefolder, filename);
  1276. else
  1277. Com_sprintf(pathname, sizeof(pathname), "%s", filename);
  1278. length = botimport.FS_FOpenFile( pathname, &fp, FS_READ );
  1279. if (!fp) return NULL;
  1280. #else
  1281. fp = fopen(filename, "rb");
  1282. if (!fp) return NULL;
  1283. length = FileLength(fp);
  1284. #endif
  1285. buffer = GetClearedMemory(sizeof(script_t) + length + 1);
  1286. script = (script_t *) buffer;
  1287. Com_Memset(script, 0, sizeof(script_t));
  1288. strcpy(script->filename, filename);
  1289. script->buffer = (char *) buffer + sizeof(script_t);
  1290. script->buffer[length] = 0;
  1291. script->length = length;
  1292. //pointer in script buffer
  1293. script->script_p = script->buffer;
  1294. //pointer in script buffer before reading token
  1295. script->lastscript_p = script->buffer;
  1296. //pointer to end of script buffer
  1297. script->end_p = &script->buffer[length];
  1298. //set if there's a token available in script->token
  1299. script->tokenavailable = 0;
  1300. //
  1301. script->line = 1;
  1302. script->lastline = 1;
  1303. //
  1304. SetScriptPunctuations(script, NULL);
  1305. //
  1306. #ifdef BOTLIB
  1307. botimport.FS_Read(script->buffer, length, fp);
  1308. botimport.FS_FCloseFile(fp);
  1309. #else
  1310. if (fread(script->buffer, length, 1, fp) != 1)
  1311. {
  1312. FreeMemory(buffer);
  1313. script = NULL;
  1314. } //end if
  1315. fclose(fp);
  1316. #endif
  1317. //
  1318. script->length = COM_Compress(script->buffer);
  1319. return script;
  1320. } //end of the function LoadScriptFile
  1321. //============================================================================
  1322. //
  1323. // Parameter: -
  1324. // Returns: -
  1325. // Changes Globals: -
  1326. //============================================================================
  1327. script_t *LoadScriptMemory(char *ptr, int length, char *name)
  1328. {
  1329. void *buffer;
  1330. script_t *script;
  1331. buffer = GetClearedMemory(sizeof(script_t) + length + 1);
  1332. script = (script_t *) buffer;
  1333. Com_Memset(script, 0, sizeof(script_t));
  1334. strcpy(script->filename, name);
  1335. script->buffer = (char *) buffer + sizeof(script_t);
  1336. script->buffer[length] = 0;
  1337. script->length = length;
  1338. //pointer in script buffer
  1339. script->script_p = script->buffer;
  1340. //pointer in script buffer before reading token
  1341. script->lastscript_p = script->buffer;
  1342. //pointer to end of script buffer
  1343. script->end_p = &script->buffer[length];
  1344. //set if there's a token available in script->token
  1345. script->tokenavailable = 0;
  1346. //
  1347. script->line = 1;
  1348. script->lastline = 1;
  1349. //
  1350. SetScriptPunctuations(script, NULL);
  1351. //
  1352. Com_Memcpy(script->buffer, ptr, length);
  1353. //
  1354. return script;
  1355. } //end of the function LoadScriptMemory
  1356. //============================================================================
  1357. //
  1358. // Parameter: -
  1359. // Returns: -
  1360. // Changes Globals: -
  1361. //============================================================================
  1362. void FreeScript(script_t *script)
  1363. {
  1364. #ifdef PUNCTABLE
  1365. if (script->punctuationtable) FreeMemory(script->punctuationtable);
  1366. #endif //PUNCTABLE
  1367. FreeMemory(script);
  1368. } //end of the function FreeScript
  1369. //============================================================================
  1370. //
  1371. // Parameter: -
  1372. // Returns: -
  1373. // Changes Globals: -
  1374. //============================================================================
  1375. void PS_SetBaseFolder(char *path)
  1376. {
  1377. #ifdef BSPC
  1378. sprintf(basefolder, path);
  1379. #else
  1380. Com_sprintf(basefolder, sizeof(basefolder), path);
  1381. #endif
  1382. } //end of the function PS_SetBaseFolder