Lexer.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "precompiled.h"
  21. #pragma hdrstop
  22. #define PUNCTABLE
  23. //longer punctuations first
  24. punctuation_t default_punctuations[] = {
  25. //binary operators
  26. {">>=",P_RSHIFT_ASSIGN},
  27. {"<<=",P_LSHIFT_ASSIGN},
  28. //
  29. {"...",P_PARMS},
  30. //define merge operator
  31. {"##",P_PRECOMPMERGE}, // pre-compiler
  32. //logic operators
  33. {"&&",P_LOGIC_AND}, // pre-compiler
  34. {"||",P_LOGIC_OR}, // pre-compiler
  35. {">=",P_LOGIC_GEQ}, // pre-compiler
  36. {"<=",P_LOGIC_LEQ}, // pre-compiler
  37. {"==",P_LOGIC_EQ}, // pre-compiler
  38. {"!=",P_LOGIC_UNEQ}, // pre-compiler
  39. //arithmatic operators
  40. {"*=",P_MUL_ASSIGN},
  41. {"/=",P_DIV_ASSIGN},
  42. {"%=",P_MOD_ASSIGN},
  43. {"+=",P_ADD_ASSIGN},
  44. {"-=",P_SUB_ASSIGN},
  45. {"++",P_INC},
  46. {"--",P_DEC},
  47. //binary operators
  48. {"&=",P_BIN_AND_ASSIGN},
  49. {"|=",P_BIN_OR_ASSIGN},
  50. {"^=",P_BIN_XOR_ASSIGN},
  51. {">>",P_RSHIFT}, // pre-compiler
  52. {"<<",P_LSHIFT}, // pre-compiler
  53. //reference operators
  54. {"->",P_POINTERREF},
  55. //C++
  56. {"::",P_CPP1},
  57. {".*",P_CPP2},
  58. //arithmatic operators
  59. {"*",P_MUL}, // pre-compiler
  60. {"/",P_DIV}, // pre-compiler
  61. {"%",P_MOD}, // pre-compiler
  62. {"+",P_ADD}, // pre-compiler
  63. {"-",P_SUB}, // pre-compiler
  64. {"=",P_ASSIGN},
  65. //binary operators
  66. {"&",P_BIN_AND}, // pre-compiler
  67. {"|",P_BIN_OR}, // pre-compiler
  68. {"^",P_BIN_XOR}, // pre-compiler
  69. {"~",P_BIN_NOT}, // pre-compiler
  70. //logic operators
  71. {"!",P_LOGIC_NOT}, // pre-compiler
  72. {">",P_LOGIC_GREATER}, // pre-compiler
  73. {"<",P_LOGIC_LESS}, // pre-compiler
  74. //reference operator
  75. {".",P_REF},
  76. //seperators
  77. {",",P_COMMA}, // pre-compiler
  78. {";",P_SEMICOLON},
  79. //label indication
  80. {":",P_COLON}, // pre-compiler
  81. //if statement
  82. {"?",P_QUESTIONMARK}, // pre-compiler
  83. //embracements
  84. {"(",P_PARENTHESESOPEN}, // pre-compiler
  85. {")",P_PARENTHESESCLOSE}, // pre-compiler
  86. {"{",P_BRACEOPEN}, // pre-compiler
  87. {"}",P_BRACECLOSE}, // pre-compiler
  88. {"[",P_SQBRACKETOPEN},
  89. {"]",P_SQBRACKETCLOSE},
  90. //
  91. {"\\",P_BACKSLASH},
  92. //precompiler operator
  93. {"#",P_PRECOMP}, // pre-compiler
  94. {"$",P_DOLLAR},
  95. {NULL, 0}
  96. };
  97. int default_punctuationtable[256];
  98. int default_nextpunctuation[sizeof(default_punctuations) / sizeof(punctuation_t)];
  99. int default_setup;
  100. char idLexer::baseFolder[ 256 ];
  101. /*
  102. ================
  103. idLexer::CreatePunctuationTable
  104. ================
  105. */
  106. void idLexer::CreatePunctuationTable( const punctuation_t *punctuations ) {
  107. int i, n, lastp;
  108. const punctuation_t *p, *newp;
  109. //get memory for the table
  110. if ( punctuations == default_punctuations ) {
  111. idLexer::punctuationtable = default_punctuationtable;
  112. idLexer::nextpunctuation = default_nextpunctuation;
  113. if ( default_setup ) {
  114. return;
  115. }
  116. default_setup = true;
  117. i = sizeof(default_punctuations) / sizeof(punctuation_t);
  118. }
  119. else {
  120. if ( !idLexer::punctuationtable || idLexer::punctuationtable == default_punctuationtable ) {
  121. idLexer::punctuationtable = (int *) Mem_Alloc(256 * sizeof(int));
  122. }
  123. if ( idLexer::nextpunctuation && idLexer::nextpunctuation != default_nextpunctuation ) {
  124. Mem_Free( idLexer::nextpunctuation );
  125. }
  126. for (i = 0; punctuations[i].p; i++) {
  127. }
  128. idLexer::nextpunctuation = (int *) Mem_Alloc(i * sizeof(int));
  129. }
  130. memset(idLexer::punctuationtable, 0xFF, 256 * sizeof(int));
  131. memset(idLexer::nextpunctuation, 0xFF, i * sizeof(int));
  132. //add the punctuations in the list to the punctuation table
  133. for (i = 0; punctuations[i].p; i++) {
  134. newp = &punctuations[i];
  135. lastp = -1;
  136. //sort the punctuations in this table entry on length (longer punctuations first)
  137. for (n = idLexer::punctuationtable[(unsigned int) newp->p[0]]; n >= 0; n = idLexer::nextpunctuation[n] ) {
  138. p = &punctuations[n];
  139. if (strlen(p->p) < strlen(newp->p)) {
  140. idLexer::nextpunctuation[i] = n;
  141. if (lastp >= 0) {
  142. idLexer::nextpunctuation[lastp] = i;
  143. }
  144. else {
  145. idLexer::punctuationtable[(unsigned int) newp->p[0]] = i;
  146. }
  147. break;
  148. }
  149. lastp = n;
  150. }
  151. if (n < 0) {
  152. idLexer::nextpunctuation[i] = -1;
  153. if (lastp >= 0) {
  154. idLexer::nextpunctuation[lastp] = i;
  155. }
  156. else {
  157. idLexer::punctuationtable[(unsigned int) newp->p[0]] = i;
  158. }
  159. }
  160. }
  161. }
  162. /*
  163. ================
  164. idLexer::GetPunctuationFromId
  165. ================
  166. */
  167. const char *idLexer::GetPunctuationFromId( int id ) {
  168. int i;
  169. for (i = 0; idLexer::punctuations[i].p; i++) {
  170. if ( idLexer::punctuations[i].n == id ) {
  171. return idLexer::punctuations[i].p;
  172. }
  173. }
  174. return "unkown punctuation";
  175. }
  176. /*
  177. ================
  178. idLexer::GetPunctuationId
  179. ================
  180. */
  181. int idLexer::GetPunctuationId( const char *p ) {
  182. int i;
  183. for (i = 0; idLexer::punctuations[i].p; i++) {
  184. if ( !strcmp(idLexer::punctuations[i].p, p) ) {
  185. return idLexer::punctuations[i].n;
  186. }
  187. }
  188. return 0;
  189. }
  190. /*
  191. ================
  192. idLexer::Error
  193. ================
  194. */
  195. void idLexer::Error( const char *str, ... ) {
  196. char text[MAX_STRING_CHARS];
  197. va_list ap;
  198. hadError = true;
  199. if ( idLexer::flags & LEXFL_NOERRORS ) {
  200. return;
  201. }
  202. va_start(ap, str);
  203. vsprintf(text, str, ap);
  204. va_end(ap);
  205. if ( idLexer::flags & LEXFL_NOFATALERRORS ) {
  206. idLib::common->Warning( "file %s, line %d: %s", idLexer::filename.c_str(), idLexer::line, text );
  207. } else {
  208. idLib::common->Error( "file %s, line %d: %s", idLexer::filename.c_str(), idLexer::line, text );
  209. }
  210. }
  211. /*
  212. ================
  213. idLexer::Warning
  214. ================
  215. */
  216. void idLexer::Warning( const char *str, ... ) {
  217. char text[MAX_STRING_CHARS];
  218. va_list ap;
  219. if ( idLexer::flags & LEXFL_NOWARNINGS ) {
  220. return;
  221. }
  222. va_start( ap, str );
  223. vsprintf( text, str, ap );
  224. va_end( ap );
  225. idLib::common->Warning( "file %s, line %d: %s", idLexer::filename.c_str(), idLexer::line, text );
  226. }
  227. /*
  228. ================
  229. idLexer::SetPunctuations
  230. ================
  231. */
  232. void idLexer::SetPunctuations( const punctuation_t *p ) {
  233. #ifdef PUNCTABLE
  234. if (p) {
  235. idLexer::CreatePunctuationTable( p );
  236. }
  237. else {
  238. idLexer::CreatePunctuationTable( default_punctuations );
  239. }
  240. #endif //PUNCTABLE
  241. if (p) {
  242. idLexer::punctuations = p;
  243. }
  244. else {
  245. idLexer::punctuations = default_punctuations;
  246. }
  247. }
  248. /*
  249. ================
  250. idLexer::ReadWhiteSpace
  251. Reads spaces, tabs, C-like comments etc.
  252. When a newline character is found the scripts line counter is increased.
  253. ================
  254. */
  255. int idLexer::ReadWhiteSpace( void ) {
  256. while(1) {
  257. // skip white space
  258. while(*idLexer::script_p <= ' ') {
  259. if (!*idLexer::script_p) {
  260. return 0;
  261. }
  262. if (*idLexer::script_p == '\n') {
  263. idLexer::line++;
  264. }
  265. idLexer::script_p++;
  266. }
  267. // skip comments
  268. if (*idLexer::script_p == '/') {
  269. // comments //
  270. if (*(idLexer::script_p+1) == '/') {
  271. idLexer::script_p++;
  272. do {
  273. idLexer::script_p++;
  274. if ( !*idLexer::script_p ) {
  275. return 0;
  276. }
  277. }
  278. while( *idLexer::script_p != '\n' );
  279. idLexer::line++;
  280. idLexer::script_p++;
  281. if ( !*idLexer::script_p ) {
  282. return 0;
  283. }
  284. continue;
  285. }
  286. // comments /* */
  287. else if (*(idLexer::script_p+1) == '*') {
  288. idLexer::script_p++;
  289. while( 1 ) {
  290. idLexer::script_p++;
  291. if ( !*idLexer::script_p ) {
  292. return 0;
  293. }
  294. if ( *idLexer::script_p == '\n' ) {
  295. idLexer::line++;
  296. }
  297. else if ( *idLexer::script_p == '/' ) {
  298. if ( *(idLexer::script_p-1) == '*' ) {
  299. break;
  300. }
  301. if ( *(idLexer::script_p+1) == '*' ) {
  302. idLexer::Warning( "nested comment" );
  303. }
  304. }
  305. }
  306. idLexer::script_p++;
  307. if ( !*idLexer::script_p ) {
  308. return 0;
  309. }
  310. idLexer::script_p++;
  311. if ( !*idLexer::script_p ) {
  312. return 0;
  313. }
  314. continue;
  315. }
  316. }
  317. break;
  318. }
  319. return 1;
  320. }
  321. /*
  322. ================
  323. idLexer::ReadEscapeCharacter
  324. ================
  325. */
  326. int idLexer::ReadEscapeCharacter( char *ch ) {
  327. int c, val, i;
  328. // step over the leading '\\'
  329. idLexer::script_p++;
  330. // determine the escape character
  331. switch(*idLexer::script_p) {
  332. case '\\': c = '\\'; break;
  333. case 'n': c = '\n'; break;
  334. case 'r': c = '\r'; break;
  335. case 't': c = '\t'; break;
  336. case 'v': c = '\v'; break;
  337. case 'b': c = '\b'; break;
  338. case 'f': c = '\f'; break;
  339. case 'a': c = '\a'; break;
  340. case '\'': c = '\''; break;
  341. case '\"': c = '\"'; break;
  342. case '\?': c = '\?'; break;
  343. case 'x':
  344. {
  345. idLexer::script_p++;
  346. for (i = 0, val = 0; ; i++, idLexer::script_p++) {
  347. c = *idLexer::script_p;
  348. if (c >= '0' && c <= '9')
  349. c = c - '0';
  350. else if (c >= 'A' && c <= 'Z')
  351. c = c - 'A' + 10;
  352. else if (c >= 'a' && c <= 'z')
  353. c = c - 'a' + 10;
  354. else
  355. break;
  356. val = (val << 4) + c;
  357. }
  358. idLexer::script_p--;
  359. if (val > 0xFF) {
  360. idLexer::Warning( "too large value in escape character" );
  361. val = 0xFF;
  362. }
  363. c = val;
  364. break;
  365. }
  366. default: //NOTE: decimal ASCII code, NOT octal
  367. {
  368. if (*idLexer::script_p < '0' || *idLexer::script_p > '9') {
  369. idLexer::Error("unknown escape char");
  370. }
  371. for (i = 0, val = 0; ; i++, idLexer::script_p++) {
  372. c = *idLexer::script_p;
  373. if (c >= '0' && c <= '9')
  374. c = c - '0';
  375. else
  376. break;
  377. val = val * 10 + c;
  378. }
  379. idLexer::script_p--;
  380. if (val > 0xFF) {
  381. idLexer::Warning( "too large value in escape character" );
  382. val = 0xFF;
  383. }
  384. c = val;
  385. break;
  386. }
  387. }
  388. // step over the escape character or the last digit of the number
  389. idLexer::script_p++;
  390. // store the escape character
  391. *ch = c;
  392. // succesfully read escape character
  393. return 1;
  394. }
  395. /*
  396. ================
  397. idLexer::ReadString
  398. Escape characters are interpretted.
  399. Reads two strings with only a white space between them as one string.
  400. ================
  401. */
  402. int idLexer::ReadString( idToken *token, int quote ) {
  403. int tmpline;
  404. const char *tmpscript_p;
  405. char ch;
  406. if ( quote == '\"' ) {
  407. token->type = TT_STRING;
  408. } else {
  409. token->type = TT_LITERAL;
  410. }
  411. // leading quote
  412. idLexer::script_p++;
  413. while(1) {
  414. // if there is an escape character and escape characters are allowed
  415. if (*idLexer::script_p == '\\' && !(idLexer::flags & LEXFL_NOSTRINGESCAPECHARS)) {
  416. if ( !idLexer::ReadEscapeCharacter( &ch ) ) {
  417. return 0;
  418. }
  419. token->AppendDirty( ch );
  420. }
  421. // if a trailing quote
  422. else if (*idLexer::script_p == quote) {
  423. // step over the quote
  424. idLexer::script_p++;
  425. // if consecutive strings should not be concatenated
  426. if ( (idLexer::flags & LEXFL_NOSTRINGCONCAT) &&
  427. (!(idLexer::flags & LEXFL_ALLOWBACKSLASHSTRINGCONCAT) || (quote != '\"')) ) {
  428. break;
  429. }
  430. tmpscript_p = idLexer::script_p;
  431. tmpline = idLexer::line;
  432. // read white space between possible two consecutive strings
  433. if ( !idLexer::ReadWhiteSpace() ) {
  434. idLexer::script_p = tmpscript_p;
  435. idLexer::line = tmpline;
  436. break;
  437. }
  438. if ( idLexer::flags & LEXFL_NOSTRINGCONCAT ) {
  439. if ( *idLexer::script_p != '\\' ) {
  440. idLexer::script_p = tmpscript_p;
  441. idLexer::line = tmpline;
  442. break;
  443. }
  444. // step over the '\\'
  445. idLexer::script_p++;
  446. if ( !idLexer::ReadWhiteSpace() || ( *idLexer::script_p != quote ) ) {
  447. idLexer::Error( "expecting string after '\' terminated line" );
  448. return 0;
  449. }
  450. }
  451. // if there's no leading qoute
  452. if ( *idLexer::script_p != quote ) {
  453. idLexer::script_p = tmpscript_p;
  454. idLexer::line = tmpline;
  455. break;
  456. }
  457. // step over the new leading quote
  458. idLexer::script_p++;
  459. }
  460. else {
  461. if (*idLexer::script_p == '\0') {
  462. idLexer::Error( "missing trailing quote" );
  463. return 0;
  464. }
  465. if (*idLexer::script_p == '\n') {
  466. idLexer::Error( "newline inside string" );
  467. return 0;
  468. }
  469. token->AppendDirty( *idLexer::script_p++ );
  470. }
  471. }
  472. token->data[token->len] = '\0';
  473. if ( token->type == TT_LITERAL ) {
  474. if ( !(idLexer::flags & LEXFL_ALLOWMULTICHARLITERALS) ) {
  475. if ( token->Length() != 1 ) {
  476. idLexer::Warning( "literal is not one character long" );
  477. }
  478. }
  479. token->subtype = (*token)[0];
  480. }
  481. else {
  482. // the sub type is the length of the string
  483. token->subtype = token->Length();
  484. }
  485. return 1;
  486. }
  487. /*
  488. ================
  489. idLexer::ReadName
  490. ================
  491. */
  492. int idLexer::ReadName( idToken *token ) {
  493. char c;
  494. token->type = TT_NAME;
  495. do {
  496. token->AppendDirty( *idLexer::script_p++ );
  497. c = *idLexer::script_p;
  498. } while ((c >= 'a' && c <= 'z') ||
  499. (c >= 'A' && c <= 'Z') ||
  500. (c >= '0' && c <= '9') ||
  501. c == '_' ||
  502. // if treating all tokens as strings, don't parse '-' as a seperate token
  503. ((idLexer::flags & LEXFL_ONLYSTRINGS) && (c == '-')) ||
  504. // if special path name characters are allowed
  505. ((idLexer::flags & LEXFL_ALLOWPATHNAMES) && (c == '/' || c == '\\' || c == ':' || c == '.')) );
  506. token->data[token->len] = '\0';
  507. //the sub type is the length of the name
  508. token->subtype = token->Length();
  509. return 1;
  510. }
  511. /*
  512. ================
  513. idLexer::CheckString
  514. ================
  515. */
  516. ID_INLINE int idLexer::CheckString( const char *str ) const {
  517. int i;
  518. for ( i = 0; str[i]; i++ ) {
  519. if ( idLexer::script_p[i] != str[i] ) {
  520. return false;
  521. }
  522. }
  523. return true;
  524. }
  525. /*
  526. ================
  527. idLexer::ReadNumber
  528. ================
  529. */
  530. int idLexer::ReadNumber( idToken *token ) {
  531. int i;
  532. int dot;
  533. char c, c2;
  534. token->type = TT_NUMBER;
  535. token->subtype = 0;
  536. token->intvalue = 0;
  537. token->floatvalue = 0;
  538. c = *idLexer::script_p;
  539. c2 = *(idLexer::script_p + 1);
  540. if ( c == '0' && c2 != '.' ) {
  541. // check for a hexadecimal number
  542. if ( c2 == 'x' || c2 == 'X' ) {
  543. token->AppendDirty( *idLexer::script_p++ );
  544. token->AppendDirty( *idLexer::script_p++ );
  545. c = *idLexer::script_p;
  546. while((c >= '0' && c <= '9') ||
  547. (c >= 'a' && c <= 'f') ||
  548. (c >= 'A' && c <= 'F')) {
  549. token->AppendDirty( c );
  550. c = *(++idLexer::script_p);
  551. }
  552. token->subtype = TT_HEX | TT_INTEGER;
  553. }
  554. // check for a binary number
  555. else if ( c2 == 'b' || c2 == 'B' ) {
  556. token->AppendDirty( *idLexer::script_p++ );
  557. token->AppendDirty( *idLexer::script_p++ );
  558. c = *idLexer::script_p;
  559. while( c == '0' || c == '1' ) {
  560. token->AppendDirty( c );
  561. c = *(++idLexer::script_p);
  562. }
  563. token->subtype = TT_BINARY | TT_INTEGER;
  564. }
  565. // its an octal number
  566. else {
  567. token->AppendDirty( *idLexer::script_p++ );
  568. c = *idLexer::script_p;
  569. while( c >= '0' && c <= '7' ) {
  570. token->AppendDirty( c );
  571. c = *(++idLexer::script_p);
  572. }
  573. token->subtype = TT_OCTAL | TT_INTEGER;
  574. }
  575. }
  576. else {
  577. // decimal integer or floating point number or ip address
  578. dot = 0;
  579. while( 1 ) {
  580. if ( c >= '0' && c <= '9' ) {
  581. }
  582. else if ( c == '.' ) {
  583. dot++;
  584. }
  585. else {
  586. break;
  587. }
  588. token->AppendDirty( c );
  589. c = *(++idLexer::script_p);
  590. }
  591. if( c == 'e' && dot == 0) {
  592. //We have scientific notation without a decimal point
  593. dot++;
  594. }
  595. // if a floating point number
  596. if ( dot == 1 ) {
  597. token->subtype = TT_DECIMAL | TT_FLOAT;
  598. // check for floating point exponent
  599. if ( c == 'e' ) {
  600. //Append the e so that GetFloatValue code works
  601. token->AppendDirty( c );
  602. c = *(++idLexer::script_p);
  603. if ( c == '-' ) {
  604. token->AppendDirty( c );
  605. c = *(++idLexer::script_p);
  606. }
  607. else if ( c == '+' ) {
  608. token->AppendDirty( c );
  609. c = *(++idLexer::script_p);
  610. }
  611. while( c >= '0' && c <= '9' ) {
  612. token->AppendDirty( c );
  613. c = *(++idLexer::script_p);
  614. }
  615. }
  616. // check for floating point exception infinite 1.#INF or indefinite 1.#IND or NaN
  617. else if ( c == '#' ) {
  618. c2 = 4;
  619. if ( CheckString( "INF" ) ) {
  620. token->subtype |= TT_INFINITE;
  621. }
  622. else if ( CheckString( "IND" ) ) {
  623. token->subtype |= TT_INDEFINITE;
  624. }
  625. else if ( CheckString( "NAN" ) ) {
  626. token->subtype |= TT_NAN;
  627. }
  628. else if ( CheckString( "QNAN" ) ) {
  629. token->subtype |= TT_NAN;
  630. c2++;
  631. }
  632. else if ( CheckString( "SNAN" ) ) {
  633. token->subtype |= TT_NAN;
  634. c2++;
  635. }
  636. for ( i = 0; i < c2; i++ ) {
  637. token->AppendDirty( c );
  638. c = *(++idLexer::script_p);
  639. }
  640. while( c >= '0' && c <= '9' ) {
  641. token->AppendDirty( c );
  642. c = *(++idLexer::script_p);
  643. }
  644. if ( !(idLexer::flags & LEXFL_ALLOWFLOATEXCEPTIONS) ) {
  645. token->AppendDirty( 0 ); // zero terminate for c_str
  646. idLexer::Error( "parsed %s", token->c_str() );
  647. }
  648. }
  649. }
  650. else if ( dot > 1 ) {
  651. if ( !( idLexer::flags & LEXFL_ALLOWIPADDRESSES ) ) {
  652. idLexer::Error( "more than one dot in number" );
  653. return 0;
  654. }
  655. if ( dot != 3 ) {
  656. idLexer::Error( "ip address should have three dots" );
  657. return 0;
  658. }
  659. token->subtype = TT_IPADDRESS;
  660. }
  661. else {
  662. token->subtype = TT_DECIMAL | TT_INTEGER;
  663. }
  664. }
  665. if ( token->subtype & TT_FLOAT ) {
  666. if ( c > ' ' ) {
  667. // single-precision: float
  668. if ( c == 'f' || c == 'F' ) {
  669. token->subtype |= TT_SINGLE_PRECISION;
  670. idLexer::script_p++;
  671. }
  672. // extended-precision: long double
  673. else if ( c == 'l' || c == 'L' ) {
  674. token->subtype |= TT_EXTENDED_PRECISION;
  675. idLexer::script_p++;
  676. }
  677. // default is double-precision: double
  678. else {
  679. token->subtype |= TT_DOUBLE_PRECISION;
  680. }
  681. }
  682. else {
  683. token->subtype |= TT_DOUBLE_PRECISION;
  684. }
  685. }
  686. else if ( token->subtype & TT_INTEGER ) {
  687. if ( c > ' ' ) {
  688. // default: signed long
  689. for ( i = 0; i < 2; i++ ) {
  690. // long integer
  691. if ( c == 'l' || c == 'L' ) {
  692. token->subtype |= TT_LONG;
  693. }
  694. // unsigned integer
  695. else if ( c == 'u' || c == 'U' ) {
  696. token->subtype |= TT_UNSIGNED;
  697. }
  698. else {
  699. break;
  700. }
  701. c = *(++idLexer::script_p);
  702. }
  703. }
  704. }
  705. else if ( token->subtype & TT_IPADDRESS ) {
  706. if ( c == ':' ) {
  707. token->AppendDirty( c );
  708. c = *(++idLexer::script_p);
  709. while( c >= '0' && c <= '9' ) {
  710. token->AppendDirty( c );
  711. c = *(++idLexer::script_p);
  712. }
  713. token->subtype |= TT_IPPORT;
  714. }
  715. }
  716. token->data[token->len] = '\0';
  717. return 1;
  718. }
  719. /*
  720. ================
  721. idLexer::ReadPunctuation
  722. ================
  723. */
  724. int idLexer::ReadPunctuation( idToken *token ) {
  725. int l, n, i;
  726. char *p;
  727. const punctuation_t *punc;
  728. #ifdef PUNCTABLE
  729. for (n = idLexer::punctuationtable[(unsigned int)*(idLexer::script_p)]; n >= 0; n = idLexer::nextpunctuation[n])
  730. {
  731. punc = &(idLexer::punctuations[n]);
  732. #else
  733. int i;
  734. for (i = 0; idLexer::punctuations[i].p; i++) {
  735. punc = &idLexer::punctuations[i];
  736. #endif
  737. p = punc->p;
  738. // check for this punctuation in the script
  739. for ( l = 0; p[l] && idLexer::script_p[l]; l++ ) {
  740. if ( idLexer::script_p[l] != p[l] ) {
  741. break;
  742. }
  743. }
  744. if ( !p[l] ) {
  745. //
  746. token->EnsureAlloced( l+1, false );
  747. for ( i = 0; i <= l; i++ ) {
  748. token->data[i] = p[i];
  749. }
  750. token->len = l;
  751. //
  752. idLexer::script_p += l;
  753. token->type = TT_PUNCTUATION;
  754. // sub type is the punctuation id
  755. token->subtype = punc->n;
  756. return 1;
  757. }
  758. }
  759. return 0;
  760. }
  761. /*
  762. ================
  763. idLexer::ReadToken
  764. ================
  765. */
  766. int idLexer::ReadToken( idToken *token ) {
  767. int c;
  768. if ( !loaded ) {
  769. idLib::common->Error( "idLexer::ReadToken: no file loaded" );
  770. return 0;
  771. }
  772. // if there is a token available (from unreadToken)
  773. if ( tokenavailable ) {
  774. tokenavailable = 0;
  775. *token = idLexer::token;
  776. return 1;
  777. }
  778. // save script pointer
  779. lastScript_p = script_p;
  780. // save line counter
  781. lastline = line;
  782. // clear the token stuff
  783. token->data[0] = '\0';
  784. token->len = 0;
  785. // start of the white space
  786. whiteSpaceStart_p = script_p;
  787. token->whiteSpaceStart_p = script_p;
  788. // read white space before token
  789. if ( !ReadWhiteSpace() ) {
  790. return 0;
  791. }
  792. // end of the white space
  793. idLexer::whiteSpaceEnd_p = script_p;
  794. token->whiteSpaceEnd_p = script_p;
  795. // line the token is on
  796. token->line = line;
  797. // number of lines crossed before token
  798. token->linesCrossed = line - lastline;
  799. // clear token flags
  800. token->flags = 0;
  801. c = *idLexer::script_p;
  802. // if we're keeping everything as whitespace deliminated strings
  803. if ( idLexer::flags & LEXFL_ONLYSTRINGS ) {
  804. // if there is a leading quote
  805. if ( c == '\"' || c == '\'' ) {
  806. if (!idLexer::ReadString( token, c )) {
  807. return 0;
  808. }
  809. } else if ( !idLexer::ReadName( token ) ) {
  810. return 0;
  811. }
  812. }
  813. // if there is a number
  814. else if ( (c >= '0' && c <= '9') ||
  815. (c == '.' && (*(idLexer::script_p + 1) >= '0' && *(idLexer::script_p + 1) <= '9')) ) {
  816. if ( !idLexer::ReadNumber( token ) ) {
  817. return 0;
  818. }
  819. // if names are allowed to start with a number
  820. if ( idLexer::flags & LEXFL_ALLOWNUMBERNAMES ) {
  821. c = *idLexer::script_p;
  822. if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' ) {
  823. if ( !idLexer::ReadName( token ) ) {
  824. return 0;
  825. }
  826. }
  827. }
  828. }
  829. // if there is a leading quote
  830. else if ( c == '\"' || c == '\'' ) {
  831. if (!idLexer::ReadString( token, c )) {
  832. return 0;
  833. }
  834. }
  835. // if there is a name
  836. else if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' ) {
  837. if ( !idLexer::ReadName( token ) ) {
  838. return 0;
  839. }
  840. }
  841. // names may also start with a slash when pathnames are allowed
  842. else if ( ( idLexer::flags & LEXFL_ALLOWPATHNAMES ) && ( (c == '/' || c == '\\') || c == '.' ) ) {
  843. if ( !idLexer::ReadName( token ) ) {
  844. return 0;
  845. }
  846. }
  847. // check for punctuations
  848. else if ( !idLexer::ReadPunctuation( token ) ) {
  849. idLexer::Error( "unknown punctuation %c", c );
  850. return 0;
  851. }
  852. // succesfully read a token
  853. return 1;
  854. }
  855. /*
  856. ================
  857. idLexer::ExpectTokenString
  858. ================
  859. */
  860. int idLexer::ExpectTokenString( const char *string ) {
  861. idToken token;
  862. if (!idLexer::ReadToken( &token )) {
  863. idLexer::Error( "couldn't find expected '%s'", string );
  864. return 0;
  865. }
  866. if ( token != string ) {
  867. idLexer::Error( "expected '%s' but found '%s'", string, token.c_str() );
  868. return 0;
  869. }
  870. return 1;
  871. }
  872. /*
  873. ================
  874. idLexer::ExpectTokenType
  875. ================
  876. */
  877. int idLexer::ExpectTokenType( int type, int subtype, idToken *token ) {
  878. idStr str;
  879. if ( !idLexer::ReadToken( token ) ) {
  880. idLexer::Error( "couldn't read expected token" );
  881. return 0;
  882. }
  883. if ( token->type != type ) {
  884. switch( type ) {
  885. case TT_STRING: str = "string"; break;
  886. case TT_LITERAL: str = "literal"; break;
  887. case TT_NUMBER: str = "number"; break;
  888. case TT_NAME: str = "name"; break;
  889. case TT_PUNCTUATION: str = "punctuation"; break;
  890. default: str = "unknown type"; break;
  891. }
  892. idLexer::Error( "expected a %s but found '%s'", str.c_str(), token->c_str() );
  893. return 0;
  894. }
  895. if ( token->type == TT_NUMBER ) {
  896. if ( (token->subtype & subtype) != subtype ) {
  897. str.Clear();
  898. if ( subtype & TT_DECIMAL ) str = "decimal ";
  899. if ( subtype & TT_HEX ) str = "hex ";
  900. if ( subtype & TT_OCTAL ) str = "octal ";
  901. if ( subtype & TT_BINARY ) str = "binary ";
  902. if ( subtype & TT_UNSIGNED ) str += "unsigned ";
  903. if ( subtype & TT_LONG ) str += "long ";
  904. if ( subtype & TT_FLOAT ) str += "float ";
  905. if ( subtype & TT_INTEGER ) str += "integer ";
  906. str.StripTrailing( ' ' );
  907. idLexer::Error( "expected %s but found '%s'", str.c_str(), token->c_str() );
  908. return 0;
  909. }
  910. }
  911. else if ( token->type == TT_PUNCTUATION ) {
  912. if ( subtype < 0 ) {
  913. idLexer::Error( "BUG: wrong punctuation subtype" );
  914. return 0;
  915. }
  916. if ( token->subtype != subtype ) {
  917. idLexer::Error( "expected '%s' but found '%s'", GetPunctuationFromId( subtype ), token->c_str() );
  918. return 0;
  919. }
  920. }
  921. return 1;
  922. }
  923. /*
  924. ================
  925. idLexer::ExpectAnyToken
  926. ================
  927. */
  928. int idLexer::ExpectAnyToken( idToken *token ) {
  929. if (!idLexer::ReadToken( token )) {
  930. idLexer::Error( "couldn't read expected token" );
  931. return 0;
  932. }
  933. else {
  934. return 1;
  935. }
  936. }
  937. /*
  938. ================
  939. idLexer::CheckTokenString
  940. ================
  941. */
  942. int idLexer::CheckTokenString( const char *string ) {
  943. idToken tok;
  944. if ( !ReadToken( &tok ) ) {
  945. return 0;
  946. }
  947. // if the given string is available
  948. if ( tok == string ) {
  949. return 1;
  950. }
  951. // unread token
  952. script_p = lastScript_p;
  953. line = lastline;
  954. return 0;
  955. }
  956. /*
  957. ================
  958. idLexer::CheckTokenType
  959. ================
  960. */
  961. int idLexer::CheckTokenType( int type, int subtype, idToken *token ) {
  962. idToken tok;
  963. if ( !ReadToken( &tok ) ) {
  964. return 0;
  965. }
  966. // if the type matches
  967. if (tok.type == type && (tok.subtype & subtype) == subtype) {
  968. *token = tok;
  969. return 1;
  970. }
  971. // unread token
  972. script_p = lastScript_p;
  973. line = lastline;
  974. return 0;
  975. }
  976. /*
  977. ================
  978. idLexer::PeekTokenString
  979. ================
  980. */
  981. int idLexer::PeekTokenString( const char *string ) {
  982. idToken tok;
  983. if ( !ReadToken( &tok ) ) {
  984. return 0;
  985. }
  986. // unread token
  987. script_p = lastScript_p;
  988. line = lastline;
  989. // if the given string is available
  990. if ( tok == string ) {
  991. return 1;
  992. }
  993. return 0;
  994. }
  995. /*
  996. ================
  997. idLexer::PeekTokenType
  998. ================
  999. */
  1000. int idLexer::PeekTokenType( int type, int subtype, idToken *token ) {
  1001. idToken tok;
  1002. if ( !ReadToken( &tok ) ) {
  1003. return 0;
  1004. }
  1005. // unread token
  1006. script_p = lastScript_p;
  1007. line = lastline;
  1008. // if the type matches
  1009. if ( tok.type == type && ( tok.subtype & subtype ) == subtype ) {
  1010. *token = tok;
  1011. return 1;
  1012. }
  1013. return 0;
  1014. }
  1015. /*
  1016. ================
  1017. idLexer::SkipUntilString
  1018. ================
  1019. */
  1020. int idLexer::SkipUntilString( const char *string ) {
  1021. idToken token;
  1022. while(idLexer::ReadToken( &token )) {
  1023. if ( token == string ) {
  1024. return 1;
  1025. }
  1026. }
  1027. return 0;
  1028. }
  1029. /*
  1030. ================
  1031. idLexer::SkipRestOfLine
  1032. ================
  1033. */
  1034. int idLexer::SkipRestOfLine( void ) {
  1035. idToken token;
  1036. while(idLexer::ReadToken( &token )) {
  1037. if ( token.linesCrossed ) {
  1038. idLexer::script_p = lastScript_p;
  1039. idLexer::line = lastline;
  1040. return 1;
  1041. }
  1042. }
  1043. return 0;
  1044. }
  1045. /*
  1046. =================
  1047. idLexer::SkipBracedSection
  1048. Skips until a matching close brace is found.
  1049. Internal brace depths are properly skipped.
  1050. =================
  1051. */
  1052. int idLexer::SkipBracedSection( bool parseFirstBrace ) {
  1053. idToken token;
  1054. int depth;
  1055. depth = parseFirstBrace ? 0 : 1;
  1056. do {
  1057. if ( !ReadToken( &token ) ) {
  1058. return false;
  1059. }
  1060. if ( token.type == TT_PUNCTUATION ) {
  1061. if ( token == "{" ) {
  1062. depth++;
  1063. } else if ( token == "}" ) {
  1064. depth--;
  1065. }
  1066. }
  1067. } while( depth );
  1068. return true;
  1069. }
  1070. /*
  1071. ================
  1072. idLexer::UnreadToken
  1073. ================
  1074. */
  1075. void idLexer::UnreadToken( const idToken *token ) {
  1076. if ( idLexer::tokenavailable ) {
  1077. idLib::common->FatalError( "idLexer::unreadToken, unread token twice\n" );
  1078. }
  1079. idLexer::token = *token;
  1080. idLexer::tokenavailable = 1;
  1081. }
  1082. /*
  1083. ================
  1084. idLexer::ReadTokenOnLine
  1085. ================
  1086. */
  1087. int idLexer::ReadTokenOnLine( idToken *token ) {
  1088. idToken tok;
  1089. if (!idLexer::ReadToken( &tok )) {
  1090. idLexer::script_p = lastScript_p;
  1091. idLexer::line = lastline;
  1092. return false;
  1093. }
  1094. // if no lines were crossed before this token
  1095. if ( !tok.linesCrossed ) {
  1096. *token = tok;
  1097. return true;
  1098. }
  1099. // restore our position
  1100. idLexer::script_p = lastScript_p;
  1101. idLexer::line = lastline;
  1102. token->Clear();
  1103. return false;
  1104. }
  1105. /*
  1106. ================
  1107. idLexer::ReadRestOfLine
  1108. ================
  1109. */
  1110. const char* idLexer::ReadRestOfLine(idStr& out) {
  1111. while(1) {
  1112. if(*idLexer::script_p == '\n') {
  1113. idLexer::line++;
  1114. break;
  1115. }
  1116. if(!*idLexer::script_p) {
  1117. break;
  1118. }
  1119. if(*idLexer::script_p <= ' ') {
  1120. out += " ";
  1121. } else {
  1122. out += *idLexer::script_p;
  1123. }
  1124. idLexer::script_p++;
  1125. }
  1126. out.Strip(' ');
  1127. return out.c_str();
  1128. }
  1129. /*
  1130. ================
  1131. idLexer::ParseInt
  1132. ================
  1133. */
  1134. int idLexer::ParseInt( void ) {
  1135. idToken token;
  1136. if ( !idLexer::ReadToken( &token ) ) {
  1137. idLexer::Error( "couldn't read expected integer" );
  1138. return 0;
  1139. }
  1140. if ( token.type == TT_PUNCTUATION && token == "-" ) {
  1141. idLexer::ExpectTokenType( TT_NUMBER, TT_INTEGER, &token );
  1142. return -((signed int) token.GetIntValue());
  1143. }
  1144. else if ( token.type != TT_NUMBER || token.subtype == TT_FLOAT ) {
  1145. idLexer::Error( "expected integer value, found '%s'", token.c_str() );
  1146. }
  1147. return token.GetIntValue();
  1148. }
  1149. /*
  1150. ================
  1151. idLexer::ParseBool
  1152. ================
  1153. */
  1154. bool idLexer::ParseBool( void ) {
  1155. idToken token;
  1156. if ( !idLexer::ExpectTokenType( TT_NUMBER, 0, &token ) ) {
  1157. idLexer::Error( "couldn't read expected boolean" );
  1158. return false;
  1159. }
  1160. return ( token.GetIntValue() != 0 );
  1161. }
  1162. /*
  1163. ================
  1164. idLexer::ParseFloat
  1165. ================
  1166. */
  1167. float idLexer::ParseFloat( bool *errorFlag ) {
  1168. idToken token;
  1169. if ( errorFlag ) {
  1170. *errorFlag = false;
  1171. }
  1172. if ( !idLexer::ReadToken( &token ) ) {
  1173. if ( errorFlag ) {
  1174. idLexer::Warning( "couldn't read expected floating point number" );
  1175. *errorFlag = true;
  1176. } else {
  1177. idLexer::Error( "couldn't read expected floating point number" );
  1178. }
  1179. return 0;
  1180. }
  1181. if ( token.type == TT_PUNCTUATION && token == "-" ) {
  1182. idLexer::ExpectTokenType( TT_NUMBER, 0, &token );
  1183. return -token.GetFloatValue();
  1184. }
  1185. else if ( token.type != TT_NUMBER ) {
  1186. if ( errorFlag ) {
  1187. idLexer::Warning( "expected float value, found '%s'", token.c_str() );
  1188. *errorFlag = true;
  1189. } else {
  1190. idLexer::Error( "expected float value, found '%s'", token.c_str() );
  1191. }
  1192. }
  1193. return token.GetFloatValue();
  1194. }
  1195. /*
  1196. ================
  1197. idLexer::Parse1DMatrix
  1198. ================
  1199. */
  1200. int idLexer::Parse1DMatrix( int x, float *m ) {
  1201. int i;
  1202. if ( !idLexer::ExpectTokenString( "(" ) ) {
  1203. return false;
  1204. }
  1205. for ( i = 0; i < x; i++ ) {
  1206. m[i] = idLexer::ParseFloat();
  1207. }
  1208. if ( !idLexer::ExpectTokenString( ")" ) ) {
  1209. return false;
  1210. }
  1211. return true;
  1212. }
  1213. /*
  1214. ================
  1215. idLexer::Parse2DMatrix
  1216. ================
  1217. */
  1218. int idLexer::Parse2DMatrix( int y, int x, float *m ) {
  1219. int i;
  1220. if ( !idLexer::ExpectTokenString( "(" ) ) {
  1221. return false;
  1222. }
  1223. for ( i = 0; i < y; i++ ) {
  1224. if ( !idLexer::Parse1DMatrix( x, m + i * x ) ) {
  1225. return false;
  1226. }
  1227. }
  1228. if ( !idLexer::ExpectTokenString( ")" ) ) {
  1229. return false;
  1230. }
  1231. return true;
  1232. }
  1233. /*
  1234. ================
  1235. idLexer::Parse3DMatrix
  1236. ================
  1237. */
  1238. int idLexer::Parse3DMatrix( int z, int y, int x, float *m ) {
  1239. int i;
  1240. if ( !idLexer::ExpectTokenString( "(" ) ) {
  1241. return false;
  1242. }
  1243. for ( i = 0 ; i < z; i++ ) {
  1244. if ( !idLexer::Parse2DMatrix( y, x, m + i * x*y ) ) {
  1245. return false;
  1246. }
  1247. }
  1248. if ( !idLexer::ExpectTokenString( ")" ) ) {
  1249. return false;
  1250. }
  1251. return true;
  1252. }
  1253. /*
  1254. =================
  1255. idParser::ParseBracedSection
  1256. The next token should be an open brace.
  1257. Parses until a matching close brace is found.
  1258. Maintains exact characters between braces.
  1259. FIXME: this should use ReadToken and replace the token white space with correct indents and newlines
  1260. =================
  1261. */
  1262. const char *idLexer::ParseBracedSectionExact( idStr &out, int tabs ) {
  1263. int depth;
  1264. bool doTabs;
  1265. bool skipWhite;
  1266. out.Empty();
  1267. if ( !idLexer::ExpectTokenString( "{" ) ) {
  1268. return out.c_str( );
  1269. }
  1270. out = "{";
  1271. depth = 1;
  1272. skipWhite = false;
  1273. doTabs = tabs >= 0;
  1274. while( depth && *idLexer::script_p ) {
  1275. char c = *(idLexer::script_p++);
  1276. switch ( c ) {
  1277. case '\t':
  1278. case ' ': {
  1279. if ( skipWhite ) {
  1280. continue;
  1281. }
  1282. break;
  1283. }
  1284. case '\n': {
  1285. if ( doTabs ) {
  1286. skipWhite = true;
  1287. out += c;
  1288. continue;
  1289. }
  1290. break;
  1291. }
  1292. case '{': {
  1293. depth++;
  1294. tabs++;
  1295. break;
  1296. }
  1297. case '}': {
  1298. depth--;
  1299. tabs--;
  1300. break;
  1301. }
  1302. }
  1303. if ( skipWhite ) {
  1304. int i = tabs;
  1305. if ( c == '{' ) {
  1306. i--;
  1307. }
  1308. skipWhite = false;
  1309. for ( ; i > 0; i-- ) {
  1310. out += '\t';
  1311. }
  1312. }
  1313. out += c;
  1314. }
  1315. return out.c_str();
  1316. }
  1317. /*
  1318. =================
  1319. idLexer::ParseBracedSection
  1320. The next token should be an open brace.
  1321. Parses until a matching close brace is found.
  1322. Internal brace depths are properly skipped.
  1323. =================
  1324. */
  1325. const char *idLexer::ParseBracedSection( idStr &out ) {
  1326. idToken token;
  1327. int i, depth;
  1328. out.Empty();
  1329. if ( !idLexer::ExpectTokenString( "{" ) ) {
  1330. return out.c_str();
  1331. }
  1332. out = "{";
  1333. depth = 1;
  1334. do {
  1335. if ( !idLexer::ReadToken( &token ) ) {
  1336. Error( "missing closing brace" );
  1337. return out.c_str();
  1338. }
  1339. // if the token is on a new line
  1340. for ( i = 0; i < token.linesCrossed; i++ ) {
  1341. out += "\r\n";
  1342. }
  1343. if ( token.type == TT_PUNCTUATION ) {
  1344. if ( token[0] == '{' ) {
  1345. depth++;
  1346. }
  1347. else if ( token[0] == '}' ) {
  1348. depth--;
  1349. }
  1350. }
  1351. if ( token.type == TT_STRING ) {
  1352. out += "\"" + token + "\"";
  1353. }
  1354. else {
  1355. out += token;
  1356. }
  1357. out += " ";
  1358. } while( depth );
  1359. return out.c_str();
  1360. }
  1361. /*
  1362. =================
  1363. idLexer::ParseRestOfLine
  1364. parse the rest of the line
  1365. =================
  1366. */
  1367. const char *idLexer::ParseRestOfLine( idStr &out ) {
  1368. idToken token;
  1369. out.Empty();
  1370. while(idLexer::ReadToken( &token )) {
  1371. if ( token.linesCrossed ) {
  1372. idLexer::script_p = lastScript_p;
  1373. idLexer::line = lastline;
  1374. break;
  1375. }
  1376. if ( out.Length() ) {
  1377. out += " ";
  1378. }
  1379. out += token;
  1380. }
  1381. return out.c_str();
  1382. }
  1383. /*
  1384. ================
  1385. idLexer::GetLastWhiteSpace
  1386. ================
  1387. */
  1388. int idLexer::GetLastWhiteSpace( idStr &whiteSpace ) const {
  1389. whiteSpace.Clear();
  1390. for ( const char *p = whiteSpaceStart_p; p < whiteSpaceEnd_p; p++ ) {
  1391. whiteSpace.Append( *p );
  1392. }
  1393. return whiteSpace.Length();
  1394. }
  1395. /*
  1396. ================
  1397. idLexer::GetLastWhiteSpaceStart
  1398. ================
  1399. */
  1400. int idLexer::GetLastWhiteSpaceStart( void ) const {
  1401. return whiteSpaceStart_p - buffer;
  1402. }
  1403. /*
  1404. ================
  1405. idLexer::GetLastWhiteSpaceEnd
  1406. ================
  1407. */
  1408. int idLexer::GetLastWhiteSpaceEnd( void ) const {
  1409. return whiteSpaceEnd_p - buffer;
  1410. }
  1411. /*
  1412. ================
  1413. idLexer::Reset
  1414. ================
  1415. */
  1416. void idLexer::Reset( void ) {
  1417. // pointer in script buffer
  1418. idLexer::script_p = idLexer::buffer;
  1419. // pointer in script buffer before reading token
  1420. idLexer::lastScript_p = idLexer::buffer;
  1421. // begin of white space
  1422. idLexer::whiteSpaceStart_p = NULL;
  1423. // end of white space
  1424. idLexer::whiteSpaceEnd_p = NULL;
  1425. // set if there's a token available in idLexer::token
  1426. idLexer::tokenavailable = 0;
  1427. idLexer::line = 1;
  1428. idLexer::lastline = 1;
  1429. // clear the saved token
  1430. idLexer::token = "";
  1431. }
  1432. /*
  1433. ================
  1434. idLexer::EndOfFile
  1435. ================
  1436. */
  1437. int idLexer::EndOfFile( void ) {
  1438. return idLexer::script_p >= idLexer::end_p;
  1439. }
  1440. /*
  1441. ================
  1442. idLexer::NumLinesCrossed
  1443. ================
  1444. */
  1445. int idLexer::NumLinesCrossed( void ) {
  1446. return idLexer::line - idLexer::lastline;
  1447. }
  1448. /*
  1449. ================
  1450. idLexer::LoadFile
  1451. ================
  1452. */
  1453. int idLexer::LoadFile( const char *filename, bool OSPath ) {
  1454. idFile *fp;
  1455. idStr pathname;
  1456. int length;
  1457. char *buf;
  1458. if ( idLexer::loaded ) {
  1459. idLib::common->Error("idLexer::LoadFile: another script already loaded");
  1460. return false;
  1461. }
  1462. if ( !OSPath && ( baseFolder[0] != '\0' ) ) {
  1463. pathname = va( "%s/%s", baseFolder, filename );
  1464. } else {
  1465. pathname = filename;
  1466. }
  1467. if ( OSPath ) {
  1468. fp = idLib::fileSystem->OpenExplicitFileRead( pathname );
  1469. } else {
  1470. fp = idLib::fileSystem->OpenFileRead( pathname );
  1471. }
  1472. if ( !fp ) {
  1473. return false;
  1474. }
  1475. length = fp->Length();
  1476. buf = (char *) Mem_Alloc( length + 1 );
  1477. buf[length] = '\0';
  1478. fp->Read( buf, length );
  1479. idLexer::fileTime = fp->Timestamp();
  1480. idLexer::filename = fp->GetFullPath();
  1481. idLib::fileSystem->CloseFile( fp );
  1482. idLexer::buffer = buf;
  1483. idLexer::length = length;
  1484. // pointer in script buffer
  1485. idLexer::script_p = idLexer::buffer;
  1486. // pointer in script buffer before reading token
  1487. idLexer::lastScript_p = idLexer::buffer;
  1488. // pointer to end of script buffer
  1489. idLexer::end_p = &(idLexer::buffer[length]);
  1490. idLexer::tokenavailable = 0;
  1491. idLexer::line = 1;
  1492. idLexer::lastline = 1;
  1493. idLexer::allocated = true;
  1494. idLexer::loaded = true;
  1495. return true;
  1496. }
  1497. /*
  1498. ================
  1499. idLexer::LoadMemory
  1500. ================
  1501. */
  1502. int idLexer::LoadMemory( const char *ptr, int length, const char *name, int startLine ) {
  1503. if ( idLexer::loaded ) {
  1504. idLib::common->Error("idLexer::LoadMemory: another script already loaded");
  1505. return false;
  1506. }
  1507. idLexer::filename = name;
  1508. idLexer::buffer = ptr;
  1509. idLexer::fileTime = 0;
  1510. idLexer::length = length;
  1511. // pointer in script buffer
  1512. idLexer::script_p = idLexer::buffer;
  1513. // pointer in script buffer before reading token
  1514. idLexer::lastScript_p = idLexer::buffer;
  1515. // pointer to end of script buffer
  1516. idLexer::end_p = &(idLexer::buffer[length]);
  1517. idLexer::tokenavailable = 0;
  1518. idLexer::line = startLine;
  1519. idLexer::lastline = startLine;
  1520. idLexer::allocated = false;
  1521. idLexer::loaded = true;
  1522. return true;
  1523. }
  1524. /*
  1525. ================
  1526. idLexer::FreeSource
  1527. ================
  1528. */
  1529. void idLexer::FreeSource( void ) {
  1530. #ifdef PUNCTABLE
  1531. if ( idLexer::punctuationtable && idLexer::punctuationtable != default_punctuationtable ) {
  1532. Mem_Free( (void *) idLexer::punctuationtable );
  1533. idLexer::punctuationtable = NULL;
  1534. }
  1535. if ( idLexer::nextpunctuation && idLexer::nextpunctuation != default_nextpunctuation ) {
  1536. Mem_Free( (void *) idLexer::nextpunctuation );
  1537. idLexer::nextpunctuation = NULL;
  1538. }
  1539. #endif //PUNCTABLE
  1540. if ( idLexer::allocated ) {
  1541. Mem_Free( (void *) idLexer::buffer );
  1542. idLexer::buffer = NULL;
  1543. idLexer::allocated = false;
  1544. }
  1545. idLexer::tokenavailable = 0;
  1546. idLexer::token = "";
  1547. idLexer::loaded = false;
  1548. }
  1549. /*
  1550. ================
  1551. idLexer::idLexer
  1552. ================
  1553. */
  1554. idLexer::idLexer( void ) {
  1555. idLexer::loaded = false;
  1556. idLexer::filename = "";
  1557. idLexer::flags = 0;
  1558. idLexer::SetPunctuations( NULL );
  1559. idLexer::allocated = false;
  1560. idLexer::fileTime = 0;
  1561. idLexer::length = 0;
  1562. idLexer::line = 0;
  1563. idLexer::lastline = 0;
  1564. idLexer::tokenavailable = 0;
  1565. idLexer::token = "";
  1566. idLexer::next = NULL;
  1567. idLexer::hadError = false;
  1568. }
  1569. /*
  1570. ================
  1571. idLexer::idLexer
  1572. ================
  1573. */
  1574. idLexer::idLexer( int flags ) {
  1575. idLexer::loaded = false;
  1576. idLexer::filename = "";
  1577. idLexer::flags = flags;
  1578. idLexer::SetPunctuations( NULL );
  1579. idLexer::allocated = false;
  1580. idLexer::fileTime = 0;
  1581. idLexer::length = 0;
  1582. idLexer::line = 0;
  1583. idLexer::lastline = 0;
  1584. idLexer::tokenavailable = 0;
  1585. idLexer::token = "";
  1586. idLexer::next = NULL;
  1587. idLexer::hadError = false;
  1588. }
  1589. /*
  1590. ================
  1591. idLexer::idLexer
  1592. ================
  1593. */
  1594. idLexer::idLexer( const char *filename, int flags, bool OSPath ) {
  1595. idLexer::loaded = false;
  1596. idLexer::flags = flags;
  1597. idLexer::SetPunctuations( NULL );
  1598. idLexer::allocated = false;
  1599. idLexer::token = "";
  1600. idLexer::next = NULL;
  1601. idLexer::hadError = false;
  1602. idLexer::LoadFile( filename, OSPath );
  1603. }
  1604. /*
  1605. ================
  1606. idLexer::idLexer
  1607. ================
  1608. */
  1609. idLexer::idLexer( const char *ptr, int length, const char *name, int flags ) {
  1610. idLexer::loaded = false;
  1611. idLexer::flags = flags;
  1612. idLexer::SetPunctuations( NULL );
  1613. idLexer::allocated = false;
  1614. idLexer::token = "";
  1615. idLexer::next = NULL;
  1616. idLexer::hadError = false;
  1617. idLexer::LoadMemory( ptr, length, name );
  1618. }
  1619. /*
  1620. ================
  1621. idLexer::~idLexer
  1622. ================
  1623. */
  1624. idLexer::~idLexer( void ) {
  1625. idLexer::FreeSource();
  1626. }
  1627. /*
  1628. ================
  1629. idLexer::SetBaseFolder
  1630. ================
  1631. */
  1632. void idLexer::SetBaseFolder( const char *path ) {
  1633. idStr::Copynz( baseFolder, path, sizeof( baseFolder ) );
  1634. }
  1635. /*
  1636. ================
  1637. idLexer::HadError
  1638. ================
  1639. */
  1640. bool idLexer::HadError( void ) const {
  1641. return hadError;
  1642. }