Lexer.cpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition 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 BFG Edition 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), TAG_IDLIB_LEXER);
  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), TAG_IDLIB_LEXER);
  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() {
  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::SkipWhiteSpace
  324. Reads spaces, tabs, C-like comments etc. When a newline character is found, the scripts line
  325. counter is increased. Returns false if there is no token left to be read.
  326. ========================
  327. */
  328. bool idLexer::SkipWhiteSpace( bool currentLine ) {
  329. while( 1 ) {
  330. assert( script_p <= end_p );
  331. if ( script_p == end_p ) {
  332. return false;
  333. }
  334. // skip white space
  335. while( *script_p <= ' ' ) {
  336. if ( script_p == end_p ) {
  337. return false;
  338. }
  339. if ( !*script_p ) {
  340. return false;
  341. }
  342. if ( *script_p == '\n' ) {
  343. line++;
  344. if ( currentLine ) {
  345. script_p++;
  346. return true;
  347. }
  348. }
  349. script_p++;
  350. }
  351. // skip comments
  352. if ( *script_p == '/' ) {
  353. // comments //
  354. if ( *(script_p+1) == '/' ) {
  355. script_p++;
  356. do {
  357. script_p++;
  358. if ( !*script_p ) {
  359. return false;
  360. }
  361. }
  362. while( *script_p != '\n' );
  363. line++;
  364. script_p++;
  365. if ( currentLine ) {
  366. return true;
  367. }
  368. if ( !*script_p ) {
  369. return false;
  370. }
  371. continue;
  372. }
  373. // comments /* */
  374. else if ( *(script_p+1) == '*' ) {
  375. script_p++;
  376. while( 1 ) {
  377. script_p++;
  378. if ( !*script_p ) {
  379. return false;
  380. }
  381. if ( *script_p == '\n' ) {
  382. line++;
  383. }
  384. else if ( *script_p == '/' ) {
  385. if ( *(script_p-1) == '*' ) {
  386. break;
  387. }
  388. if ( *(script_p+1) == '*' ) {
  389. Warning( "nested comment" );
  390. }
  391. }
  392. }
  393. script_p++;
  394. if ( !*script_p ) {
  395. return false;
  396. }
  397. continue;
  398. }
  399. }
  400. break;
  401. }
  402. return true;
  403. }
  404. /*
  405. ================
  406. idLexer::ReadEscapeCharacter
  407. ================
  408. */
  409. int idLexer::ReadEscapeCharacter( char *ch ) {
  410. int c, val, i;
  411. // step over the leading '\\'
  412. idLexer::script_p++;
  413. // determine the escape character
  414. switch(*idLexer::script_p) {
  415. case '\\': c = '\\'; break;
  416. case 'n': c = '\n'; break;
  417. case 'r': c = '\r'; break;
  418. case 't': c = '\t'; break;
  419. case 'v': c = '\v'; break;
  420. case 'b': c = '\b'; break;
  421. case 'f': c = '\f'; break;
  422. case 'a': c = '\a'; break;
  423. case '\'': c = '\''; break;
  424. case '\"': c = '\"'; break;
  425. case '\?': c = '\?'; break;
  426. case 'x':
  427. {
  428. idLexer::script_p++;
  429. for (i = 0, val = 0; ; i++, idLexer::script_p++) {
  430. c = *idLexer::script_p;
  431. if (c >= '0' && c <= '9')
  432. c = c - '0';
  433. else if (c >= 'A' && c <= 'Z')
  434. c = c - 'A' + 10;
  435. else if (c >= 'a' && c <= 'z')
  436. c = c - 'a' + 10;
  437. else
  438. break;
  439. val = (val << 4) + c;
  440. }
  441. idLexer::script_p--;
  442. if (val > 0xFF) {
  443. idLexer::Warning( "too large value in escape character" );
  444. val = 0xFF;
  445. }
  446. c = val;
  447. break;
  448. }
  449. default: //NOTE: decimal ASCII code, NOT octal
  450. {
  451. if (*idLexer::script_p < '0' || *idLexer::script_p > '9') {
  452. idLexer::Error("unknown escape char");
  453. }
  454. for (i = 0, val = 0; ; i++, idLexer::script_p++) {
  455. c = *idLexer::script_p;
  456. if (c >= '0' && c <= '9')
  457. c = c - '0';
  458. else
  459. break;
  460. val = val * 10 + c;
  461. }
  462. idLexer::script_p--;
  463. if (val > 0xFF) {
  464. idLexer::Warning( "too large value in escape character" );
  465. val = 0xFF;
  466. }
  467. c = val;
  468. break;
  469. }
  470. }
  471. // step over the escape character or the last digit of the number
  472. idLexer::script_p++;
  473. // store the escape character
  474. *ch = c;
  475. // succesfully read escape character
  476. return 1;
  477. }
  478. /*
  479. ================
  480. idLexer::ReadString
  481. Escape characters are interpretted.
  482. Reads two strings with only a white space between them as one string.
  483. ================
  484. */
  485. int idLexer::ReadString( idToken *token, int quote ) {
  486. int tmpline;
  487. const char *tmpscript_p;
  488. char ch;
  489. if ( quote == '\"' ) {
  490. token->type = TT_STRING;
  491. } else {
  492. token->type = TT_LITERAL;
  493. }
  494. // leading quote
  495. idLexer::script_p++;
  496. while(1) {
  497. // if there is an escape character and escape characters are allowed
  498. if (*idLexer::script_p == '\\' && !(idLexer::flags & LEXFL_NOSTRINGESCAPECHARS)) {
  499. if ( !idLexer::ReadEscapeCharacter( &ch ) ) {
  500. return 0;
  501. }
  502. token->AppendDirty( ch );
  503. }
  504. // if a trailing quote
  505. else if (*idLexer::script_p == quote) {
  506. // step over the quote
  507. idLexer::script_p++;
  508. // if consecutive strings should not be concatenated
  509. if ( (idLexer::flags & LEXFL_NOSTRINGCONCAT) &&
  510. (!(idLexer::flags & LEXFL_ALLOWBACKSLASHSTRINGCONCAT) || (quote != '\"')) ) {
  511. break;
  512. }
  513. tmpscript_p = idLexer::script_p;
  514. tmpline = idLexer::line;
  515. // read white space between possible two consecutive strings
  516. if ( !idLexer::ReadWhiteSpace() ) {
  517. idLexer::script_p = tmpscript_p;
  518. idLexer::line = tmpline;
  519. break;
  520. }
  521. if ( idLexer::flags & LEXFL_NOSTRINGCONCAT ) {
  522. if ( *idLexer::script_p != '\\' ) {
  523. idLexer::script_p = tmpscript_p;
  524. idLexer::line = tmpline;
  525. break;
  526. }
  527. // step over the '\\'
  528. idLexer::script_p++;
  529. if ( !idLexer::ReadWhiteSpace() || ( *idLexer::script_p != quote ) ) {
  530. idLexer::Error( "expecting string after '\' terminated line" );
  531. return 0;
  532. }
  533. }
  534. // if there's no leading qoute
  535. if ( *idLexer::script_p != quote ) {
  536. idLexer::script_p = tmpscript_p;
  537. idLexer::line = tmpline;
  538. break;
  539. }
  540. // step over the new leading quote
  541. idLexer::script_p++;
  542. }
  543. else {
  544. if (*idLexer::script_p == '\0') {
  545. idLexer::Error( "missing trailing quote" );
  546. return 0;
  547. }
  548. if (*idLexer::script_p == '\n') {
  549. idLexer::Error( "newline inside string" );
  550. return 0;
  551. }
  552. token->AppendDirty( *idLexer::script_p++ );
  553. }
  554. }
  555. token->data[token->len] = '\0';
  556. if ( token->type == TT_LITERAL ) {
  557. if ( !(idLexer::flags & LEXFL_ALLOWMULTICHARLITERALS) ) {
  558. if ( token->Length() != 1 ) {
  559. idLexer::Warning( "literal is not one character long" );
  560. }
  561. }
  562. token->subtype = (*token)[0];
  563. }
  564. else {
  565. // the sub type is the length of the string
  566. token->subtype = token->Length();
  567. }
  568. return 1;
  569. }
  570. /*
  571. ================
  572. idLexer::ReadName
  573. ================
  574. */
  575. int idLexer::ReadName( idToken *token ) {
  576. char c;
  577. token->type = TT_NAME;
  578. do {
  579. token->AppendDirty( *idLexer::script_p++ );
  580. c = *idLexer::script_p;
  581. } while ((c >= 'a' && c <= 'z') ||
  582. (c >= 'A' && c <= 'Z') ||
  583. (c >= '0' && c <= '9') ||
  584. c == '_' ||
  585. // if treating all tokens as strings, don't parse '-' as a seperate token
  586. ((idLexer::flags & LEXFL_ONLYSTRINGS) && (c == '-')) ||
  587. // if special path name characters are allowed
  588. ((idLexer::flags & LEXFL_ALLOWPATHNAMES) && (c == '/' || c == '\\' || c == ':' || c == '.')) );
  589. token->data[token->len] = '\0';
  590. //the sub type is the length of the name
  591. token->subtype = token->Length();
  592. return 1;
  593. }
  594. /*
  595. ================
  596. idLexer::CheckString
  597. ================
  598. */
  599. ID_INLINE int idLexer::CheckString( const char *str ) const {
  600. int i;
  601. for ( i = 0; str[i]; i++ ) {
  602. if ( idLexer::script_p[i] != str[i] ) {
  603. return false;
  604. }
  605. }
  606. return true;
  607. }
  608. /*
  609. ================
  610. idLexer::ReadNumber
  611. ================
  612. */
  613. int idLexer::ReadNumber( idToken *token ) {
  614. int i;
  615. int dot;
  616. char c, c2;
  617. token->type = TT_NUMBER;
  618. token->subtype = 0;
  619. token->intvalue = 0;
  620. token->floatvalue = 0;
  621. c = *idLexer::script_p;
  622. c2 = *(idLexer::script_p + 1);
  623. if ( c == '0' && c2 != '.' ) {
  624. // check for a hexadecimal number
  625. if ( c2 == 'x' || c2 == 'X' ) {
  626. token->AppendDirty( *idLexer::script_p++ );
  627. token->AppendDirty( *idLexer::script_p++ );
  628. c = *idLexer::script_p;
  629. while((c >= '0' && c <= '9') ||
  630. (c >= 'a' && c <= 'f') ||
  631. (c >= 'A' && c <= 'F')) {
  632. token->AppendDirty( c );
  633. c = *(++idLexer::script_p);
  634. }
  635. token->subtype = TT_HEX | TT_INTEGER;
  636. }
  637. // check for a binary number
  638. else if ( c2 == 'b' || c2 == 'B' ) {
  639. token->AppendDirty( *idLexer::script_p++ );
  640. token->AppendDirty( *idLexer::script_p++ );
  641. c = *idLexer::script_p;
  642. while( c == '0' || c == '1' ) {
  643. token->AppendDirty( c );
  644. c = *(++idLexer::script_p);
  645. }
  646. token->subtype = TT_BINARY | TT_INTEGER;
  647. }
  648. // its an octal number
  649. else {
  650. token->AppendDirty( *idLexer::script_p++ );
  651. c = *idLexer::script_p;
  652. while( c >= '0' && c <= '7' ) {
  653. token->AppendDirty( c );
  654. c = *(++idLexer::script_p);
  655. }
  656. token->subtype = TT_OCTAL | TT_INTEGER;
  657. }
  658. }
  659. else {
  660. // decimal integer or floating point number or ip address
  661. dot = 0;
  662. while( 1 ) {
  663. if ( c >= '0' && c <= '9' ) {
  664. }
  665. else if ( c == '.' ) {
  666. dot++;
  667. }
  668. else {
  669. break;
  670. }
  671. token->AppendDirty( c );
  672. c = *(++idLexer::script_p);
  673. }
  674. if( c == 'e' && dot == 0) {
  675. //We have scientific notation without a decimal point
  676. dot++;
  677. }
  678. // if a floating point number
  679. if ( dot == 1 ) {
  680. token->subtype = TT_DECIMAL | TT_FLOAT;
  681. // check for floating point exponent
  682. if ( c == 'e' ) {
  683. //Append the e so that GetFloatValue code works
  684. token->AppendDirty( c );
  685. c = *(++idLexer::script_p);
  686. if ( c == '-' ) {
  687. token->AppendDirty( c );
  688. c = *(++idLexer::script_p);
  689. }
  690. else if ( c == '+' ) {
  691. token->AppendDirty( c );
  692. c = *(++idLexer::script_p);
  693. }
  694. while( c >= '0' && c <= '9' ) {
  695. token->AppendDirty( c );
  696. c = *(++idLexer::script_p);
  697. }
  698. }
  699. // check for floating point exception infinite 1.#INF or indefinite 1.#IND or NaN
  700. else if ( c == '#' ) {
  701. c2 = 4;
  702. if ( CheckString( "INF" ) ) {
  703. token->subtype |= TT_INFINITE;
  704. }
  705. else if ( CheckString( "IND" ) ) {
  706. token->subtype |= TT_INDEFINITE;
  707. }
  708. else if ( CheckString( "NAN" ) ) {
  709. token->subtype |= TT_NAN;
  710. }
  711. else if ( CheckString( "QNAN" ) ) {
  712. token->subtype |= TT_NAN;
  713. c2++;
  714. }
  715. else if ( CheckString( "SNAN" ) ) {
  716. token->subtype |= TT_NAN;
  717. c2++;
  718. }
  719. for ( i = 0; i < c2; i++ ) {
  720. token->AppendDirty( c );
  721. c = *(++idLexer::script_p);
  722. }
  723. while( c >= '0' && c <= '9' ) {
  724. token->AppendDirty( c );
  725. c = *(++idLexer::script_p);
  726. }
  727. if ( !(idLexer::flags & LEXFL_ALLOWFLOATEXCEPTIONS) ) {
  728. token->AppendDirty( 0 ); // zero terminate for c_str
  729. idLexer::Error( "parsed %s", token->c_str() );
  730. }
  731. }
  732. }
  733. else if ( dot > 1 ) {
  734. if ( !( idLexer::flags & LEXFL_ALLOWIPADDRESSES ) ) {
  735. idLexer::Error( "more than one dot in number" );
  736. return 0;
  737. }
  738. if ( dot != 3 ) {
  739. idLexer::Error( "ip address should have three dots" );
  740. return 0;
  741. }
  742. token->subtype = TT_IPADDRESS;
  743. }
  744. else {
  745. token->subtype = TT_DECIMAL | TT_INTEGER;
  746. }
  747. }
  748. if ( token->subtype & TT_FLOAT ) {
  749. if ( c > ' ' ) {
  750. // single-precision: float
  751. if ( c == 'f' || c == 'F' ) {
  752. token->subtype |= TT_SINGLE_PRECISION;
  753. idLexer::script_p++;
  754. }
  755. // extended-precision: long double
  756. else if ( c == 'l' || c == 'L' ) {
  757. token->subtype |= TT_EXTENDED_PRECISION;
  758. idLexer::script_p++;
  759. }
  760. // default is double-precision: double
  761. else {
  762. token->subtype |= TT_DOUBLE_PRECISION;
  763. }
  764. }
  765. else {
  766. token->subtype |= TT_DOUBLE_PRECISION;
  767. }
  768. }
  769. else if ( token->subtype & TT_INTEGER ) {
  770. if ( c > ' ' ) {
  771. // default: signed long
  772. for ( i = 0; i < 2; i++ ) {
  773. // long integer
  774. if ( c == 'l' || c == 'L' ) {
  775. token->subtype |= TT_LONG;
  776. }
  777. // unsigned integer
  778. else if ( c == 'u' || c == 'U' ) {
  779. token->subtype |= TT_UNSIGNED;
  780. }
  781. else {
  782. break;
  783. }
  784. c = *(++idLexer::script_p);
  785. }
  786. }
  787. }
  788. else if ( token->subtype & TT_IPADDRESS ) {
  789. if ( c == ':' ) {
  790. token->AppendDirty( c );
  791. c = *(++idLexer::script_p);
  792. while( c >= '0' && c <= '9' ) {
  793. token->AppendDirty( c );
  794. c = *(++idLexer::script_p);
  795. }
  796. token->subtype |= TT_IPPORT;
  797. }
  798. }
  799. token->data[token->len] = '\0';
  800. return 1;
  801. }
  802. /*
  803. ================
  804. idLexer::ReadPunctuation
  805. ================
  806. */
  807. int idLexer::ReadPunctuation( idToken *token ) {
  808. int l, n, i;
  809. char *p;
  810. const punctuation_t *punc;
  811. #ifdef PUNCTABLE
  812. for (n = idLexer::punctuationtable[(unsigned int)*(idLexer::script_p)]; n >= 0; n = idLexer::nextpunctuation[n])
  813. {
  814. punc = &(idLexer::punctuations[n]);
  815. #else
  816. int i;
  817. for (i = 0; idLexer::punctuations[i].p; i++) {
  818. punc = &idLexer::punctuations[i];
  819. #endif
  820. p = punc->p;
  821. // check for this punctuation in the script
  822. for ( l = 0; p[l] && idLexer::script_p[l]; l++ ) {
  823. if ( idLexer::script_p[l] != p[l] ) {
  824. break;
  825. }
  826. }
  827. if ( !p[l] ) {
  828. //
  829. token->EnsureAlloced( l+1, false );
  830. for ( i = 0; i <= l; i++ ) {
  831. token->data[i] = p[i];
  832. }
  833. token->len = l;
  834. //
  835. idLexer::script_p += l;
  836. token->type = TT_PUNCTUATION;
  837. // sub type is the punctuation id
  838. token->subtype = punc->n;
  839. return 1;
  840. }
  841. }
  842. return 0;
  843. }
  844. /*
  845. ================
  846. idLexer::ReadToken
  847. ================
  848. */
  849. int idLexer::ReadToken( idToken *token ) {
  850. int c;
  851. if ( !loaded ) {
  852. idLib::common->Error( "idLexer::ReadToken: no file loaded" );
  853. return 0;
  854. }
  855. if ( script_p == NULL ) {
  856. return 0;
  857. }
  858. // if there is a token available (from unreadToken)
  859. if ( tokenavailable ) {
  860. tokenavailable = 0;
  861. *token = idLexer::token;
  862. return 1;
  863. }
  864. // save script pointer
  865. lastScript_p = script_p;
  866. // save line counter
  867. lastline = line;
  868. // clear the token stuff
  869. token->data[0] = '\0';
  870. token->len = 0;
  871. // start of the white space
  872. whiteSpaceStart_p = script_p;
  873. token->whiteSpaceStart_p = script_p;
  874. // read white space before token
  875. if ( !ReadWhiteSpace() ) {
  876. return 0;
  877. }
  878. // end of the white space
  879. idLexer::whiteSpaceEnd_p = script_p;
  880. token->whiteSpaceEnd_p = script_p;
  881. // line the token is on
  882. token->line = line;
  883. // number of lines crossed before token
  884. token->linesCrossed = line - lastline;
  885. // clear token flags
  886. token->flags = 0;
  887. c = *idLexer::script_p;
  888. // if we're keeping everything as whitespace deliminated strings
  889. if ( idLexer::flags & LEXFL_ONLYSTRINGS ) {
  890. // if there is a leading quote
  891. if ( c == '\"' || c == '\'' ) {
  892. if (!idLexer::ReadString( token, c )) {
  893. return 0;
  894. }
  895. } else if ( !idLexer::ReadName( token ) ) {
  896. return 0;
  897. }
  898. }
  899. // if there is a number
  900. else if ( (c >= '0' && c <= '9') ||
  901. (c == '.' && (*(idLexer::script_p + 1) >= '0' && *(idLexer::script_p + 1) <= '9')) ) {
  902. if ( !idLexer::ReadNumber( token ) ) {
  903. return 0;
  904. }
  905. // if names are allowed to start with a number
  906. if ( idLexer::flags & LEXFL_ALLOWNUMBERNAMES ) {
  907. c = *idLexer::script_p;
  908. if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' ) {
  909. if ( !idLexer::ReadName( token ) ) {
  910. return 0;
  911. }
  912. }
  913. }
  914. }
  915. // if there is a leading quote
  916. else if ( c == '\"' || c == '\'' ) {
  917. if (!idLexer::ReadString( token, c )) {
  918. return 0;
  919. }
  920. }
  921. // if there is a name
  922. else if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' ) {
  923. if ( !idLexer::ReadName( token ) ) {
  924. return 0;
  925. }
  926. }
  927. // names may also start with a slash when pathnames are allowed
  928. else if ( ( idLexer::flags & LEXFL_ALLOWPATHNAMES ) && ( (c == '/' || c == '\\') || c == '.' ) ) {
  929. if ( !idLexer::ReadName( token ) ) {
  930. return 0;
  931. }
  932. }
  933. // check for punctuations
  934. else if ( !idLexer::ReadPunctuation( token ) ) {
  935. idLexer::Error( "unknown punctuation %c", c );
  936. return 0;
  937. }
  938. // succesfully read a token
  939. return 1;
  940. }
  941. /*
  942. ================
  943. idLexer::ExpectTokenString
  944. ================
  945. */
  946. int idLexer::ExpectTokenString( const char *string ) {
  947. idToken token;
  948. if (!idLexer::ReadToken( &token )) {
  949. idLexer::Error( "couldn't find expected '%s'", string );
  950. return 0;
  951. }
  952. if ( token != string ) {
  953. idLexer::Error( "expected '%s' but found '%s'", string, token.c_str() );
  954. return 0;
  955. }
  956. return 1;
  957. }
  958. /*
  959. ================
  960. idLexer::ExpectTokenType
  961. ================
  962. */
  963. int idLexer::ExpectTokenType( int type, int subtype, idToken *token ) {
  964. idStr str;
  965. if ( !idLexer::ReadToken( token ) ) {
  966. idLexer::Error( "couldn't read expected token" );
  967. return 0;
  968. }
  969. if ( token->type != type ) {
  970. switch( type ) {
  971. case TT_STRING: str = "string"; break;
  972. case TT_LITERAL: str = "literal"; break;
  973. case TT_NUMBER: str = "number"; break;
  974. case TT_NAME: str = "name"; break;
  975. case TT_PUNCTUATION: str = "punctuation"; break;
  976. default: str = "unknown type"; break;
  977. }
  978. idLexer::Error( "expected a %s but found '%s'", str.c_str(), token->c_str() );
  979. return 0;
  980. }
  981. if ( token->type == TT_NUMBER ) {
  982. if ( (token->subtype & subtype) != subtype ) {
  983. str.Clear();
  984. if ( subtype & TT_DECIMAL ) str = "decimal ";
  985. if ( subtype & TT_HEX ) str = "hex ";
  986. if ( subtype & TT_OCTAL ) str = "octal ";
  987. if ( subtype & TT_BINARY ) str = "binary ";
  988. if ( subtype & TT_UNSIGNED ) str += "unsigned ";
  989. if ( subtype & TT_LONG ) str += "long ";
  990. if ( subtype & TT_FLOAT ) str += "float ";
  991. if ( subtype & TT_INTEGER ) str += "integer ";
  992. str.StripTrailing( ' ' );
  993. idLexer::Error( "expected %s but found '%s'", str.c_str(), token->c_str() );
  994. return 0;
  995. }
  996. }
  997. else if ( token->type == TT_PUNCTUATION ) {
  998. if ( subtype < 0 ) {
  999. idLexer::Error( "BUG: wrong punctuation subtype" );
  1000. return 0;
  1001. }
  1002. if ( token->subtype != subtype ) {
  1003. idLexer::Error( "expected '%s' but found '%s'", GetPunctuationFromId( subtype ), token->c_str() );
  1004. return 0;
  1005. }
  1006. }
  1007. return 1;
  1008. }
  1009. /*
  1010. ================
  1011. idLexer::ExpectAnyToken
  1012. ================
  1013. */
  1014. int idLexer::ExpectAnyToken( idToken *token ) {
  1015. if (!idLexer::ReadToken( token )) {
  1016. idLexer::Error( "couldn't read expected token" );
  1017. return 0;
  1018. }
  1019. else {
  1020. return 1;
  1021. }
  1022. }
  1023. /*
  1024. ================
  1025. idLexer::CheckTokenString
  1026. ================
  1027. */
  1028. int idLexer::CheckTokenString( const char *string ) {
  1029. idToken tok;
  1030. if ( !ReadToken( &tok ) ) {
  1031. return 0;
  1032. }
  1033. // if the given string is available
  1034. if ( tok == string ) {
  1035. return 1;
  1036. }
  1037. // unread token
  1038. script_p = lastScript_p;
  1039. line = lastline;
  1040. return 0;
  1041. }
  1042. /*
  1043. ================
  1044. idLexer::CheckTokenType
  1045. ================
  1046. */
  1047. int idLexer::CheckTokenType( int type, int subtype, idToken *token ) {
  1048. idToken tok;
  1049. if ( !ReadToken( &tok ) ) {
  1050. return 0;
  1051. }
  1052. // if the type matches
  1053. if (tok.type == type && (tok.subtype & subtype) == subtype) {
  1054. *token = tok;
  1055. return 1;
  1056. }
  1057. // unread token
  1058. script_p = lastScript_p;
  1059. line = lastline;
  1060. return 0;
  1061. }
  1062. /*
  1063. ================
  1064. idLexer::PeekTokenString
  1065. ================
  1066. */
  1067. int idLexer::PeekTokenString( const char *string ) {
  1068. idToken tok;
  1069. if ( !ReadToken( &tok ) ) {
  1070. return 0;
  1071. }
  1072. // unread token
  1073. script_p = lastScript_p;
  1074. line = lastline;
  1075. // if the given string is available
  1076. if ( tok == string ) {
  1077. return 1;
  1078. }
  1079. return 0;
  1080. }
  1081. /*
  1082. ================
  1083. idLexer::PeekTokenType
  1084. ================
  1085. */
  1086. int idLexer::PeekTokenType( int type, int subtype, idToken *token ) {
  1087. idToken tok;
  1088. if ( !ReadToken( &tok ) ) {
  1089. return 0;
  1090. }
  1091. // unread token
  1092. script_p = lastScript_p;
  1093. line = lastline;
  1094. // if the type matches
  1095. if ( tok.type == type && ( tok.subtype & subtype ) == subtype ) {
  1096. *token = tok;
  1097. return 1;
  1098. }
  1099. return 0;
  1100. }
  1101. /*
  1102. ================
  1103. idLexer::SkipUntilString
  1104. ================
  1105. */
  1106. int idLexer::SkipUntilString( const char *string ) {
  1107. idToken token;
  1108. while(idLexer::ReadToken( &token )) {
  1109. if ( token == string ) {
  1110. return 1;
  1111. }
  1112. }
  1113. return 0;
  1114. }
  1115. /*
  1116. ================
  1117. idLexer::SkipRestOfLine
  1118. ================
  1119. */
  1120. int idLexer::SkipRestOfLine() {
  1121. idToken token;
  1122. while(idLexer::ReadToken( &token )) {
  1123. if ( token.linesCrossed ) {
  1124. idLexer::script_p = lastScript_p;
  1125. idLexer::line = lastline;
  1126. return 1;
  1127. }
  1128. }
  1129. return 0;
  1130. }
  1131. /*
  1132. =================
  1133. idLexer::SkipBracedSection
  1134. Skips until a matching close brace is found.
  1135. Internal brace depths are properly skipped.
  1136. =================
  1137. */
  1138. int idLexer::SkipBracedSection( bool parseFirstBrace ) {
  1139. idToken token;
  1140. int depth;
  1141. depth = parseFirstBrace ? 0 : 1;
  1142. do {
  1143. if ( !ReadToken( &token ) ) {
  1144. return false;
  1145. }
  1146. if ( token.type == TT_PUNCTUATION ) {
  1147. if ( token == "{" ) {
  1148. depth++;
  1149. } else if ( token == "}" ) {
  1150. depth--;
  1151. }
  1152. }
  1153. } while( depth );
  1154. return true;
  1155. }
  1156. /*
  1157. ================
  1158. idLexer::UnreadToken
  1159. ================
  1160. */
  1161. void idLexer::UnreadToken( const idToken *token ) {
  1162. if ( idLexer::tokenavailable ) {
  1163. idLib::common->FatalError( "idLexer::unreadToken, unread token twice\n" );
  1164. }
  1165. idLexer::token = *token;
  1166. idLexer::tokenavailable = 1;
  1167. }
  1168. /*
  1169. ================
  1170. idLexer::ReadTokenOnLine
  1171. ================
  1172. */
  1173. int idLexer::ReadTokenOnLine( idToken *token ) {
  1174. idToken tok;
  1175. if (!idLexer::ReadToken( &tok )) {
  1176. idLexer::script_p = lastScript_p;
  1177. idLexer::line = lastline;
  1178. return false;
  1179. }
  1180. // if no lines were crossed before this token
  1181. if ( !tok.linesCrossed ) {
  1182. *token = tok;
  1183. return true;
  1184. }
  1185. // restore our position
  1186. idLexer::script_p = lastScript_p;
  1187. idLexer::line = lastline;
  1188. token->Clear();
  1189. return false;
  1190. }
  1191. /*
  1192. ================
  1193. idLexer::ReadRestOfLine
  1194. ================
  1195. */
  1196. const char* idLexer::ReadRestOfLine(idStr& out) {
  1197. while(1) {
  1198. if(*idLexer::script_p == '\n') {
  1199. idLexer::line++;
  1200. break;
  1201. }
  1202. if(!*idLexer::script_p) {
  1203. break;
  1204. }
  1205. if(*idLexer::script_p <= ' ') {
  1206. out += " ";
  1207. } else {
  1208. out += *idLexer::script_p;
  1209. }
  1210. idLexer::script_p++;
  1211. }
  1212. out.Strip(' ');
  1213. return out.c_str();
  1214. }
  1215. /*
  1216. ================
  1217. idLexer::ParseInt
  1218. ================
  1219. */
  1220. int idLexer::ParseInt() {
  1221. idToken token;
  1222. if ( !idLexer::ReadToken( &token ) ) {
  1223. idLexer::Error( "couldn't read expected integer" );
  1224. return 0;
  1225. }
  1226. if ( token.type == TT_PUNCTUATION && token == "-" ) {
  1227. idLexer::ExpectTokenType( TT_NUMBER, TT_INTEGER, &token );
  1228. return -((signed int) token.GetIntValue());
  1229. }
  1230. else if ( token.type != TT_NUMBER || token.subtype == TT_FLOAT ) {
  1231. idLexer::Error( "expected integer value, found '%s'", token.c_str() );
  1232. }
  1233. return token.GetIntValue();
  1234. }
  1235. /*
  1236. ================
  1237. idLexer::ParseBool
  1238. ================
  1239. */
  1240. bool idLexer::ParseBool() {
  1241. idToken token;
  1242. if ( !idLexer::ExpectTokenType( TT_NUMBER, 0, &token ) ) {
  1243. idLexer::Error( "couldn't read expected boolean" );
  1244. return false;
  1245. }
  1246. return ( token.GetIntValue() != 0 );
  1247. }
  1248. /*
  1249. ================
  1250. idLexer::ParseFloat
  1251. ================
  1252. */
  1253. float idLexer::ParseFloat( bool *errorFlag ) {
  1254. idToken token;
  1255. if ( errorFlag ) {
  1256. *errorFlag = false;
  1257. }
  1258. if ( !idLexer::ReadToken( &token ) ) {
  1259. if ( errorFlag ) {
  1260. idLexer::Warning( "couldn't read expected floating point number" );
  1261. *errorFlag = true;
  1262. } else {
  1263. idLexer::Error( "couldn't read expected floating point number" );
  1264. }
  1265. return 0;
  1266. }
  1267. if ( token.type == TT_PUNCTUATION && token == "-" ) {
  1268. idLexer::ExpectTokenType( TT_NUMBER, 0, &token );
  1269. return -token.GetFloatValue();
  1270. }
  1271. else if ( token.type != TT_NUMBER ) {
  1272. if ( errorFlag ) {
  1273. idLexer::Warning( "expected float value, found '%s'", token.c_str() );
  1274. *errorFlag = true;
  1275. } else {
  1276. idLexer::Error( "expected float value, found '%s'", token.c_str() );
  1277. }
  1278. }
  1279. return token.GetFloatValue();
  1280. }
  1281. /*
  1282. ================
  1283. idLexer::Parse1DMatrix
  1284. ================
  1285. */
  1286. int idLexer::Parse1DMatrix( int x, float *m ) {
  1287. int i;
  1288. if ( !idLexer::ExpectTokenString( "(" ) ) {
  1289. return false;
  1290. }
  1291. for ( i = 0; i < x; i++ ) {
  1292. m[i] = idLexer::ParseFloat();
  1293. }
  1294. if ( !idLexer::ExpectTokenString( ")" ) ) {
  1295. return false;
  1296. }
  1297. return true;
  1298. }
  1299. /*
  1300. ================
  1301. idLexer::Parse2DMatrix
  1302. ================
  1303. */
  1304. int idLexer::Parse2DMatrix( int y, int x, float *m ) {
  1305. int i;
  1306. if ( !idLexer::ExpectTokenString( "(" ) ) {
  1307. return false;
  1308. }
  1309. for ( i = 0; i < y; i++ ) {
  1310. if ( !idLexer::Parse1DMatrix( x, m + i * x ) ) {
  1311. return false;
  1312. }
  1313. }
  1314. if ( !idLexer::ExpectTokenString( ")" ) ) {
  1315. return false;
  1316. }
  1317. return true;
  1318. }
  1319. /*
  1320. ================
  1321. idLexer::Parse3DMatrix
  1322. ================
  1323. */
  1324. int idLexer::Parse3DMatrix( int z, int y, int x, float *m ) {
  1325. int i;
  1326. if ( !idLexer::ExpectTokenString( "(" ) ) {
  1327. return false;
  1328. }
  1329. for ( i = 0 ; i < z; i++ ) {
  1330. if ( !idLexer::Parse2DMatrix( y, x, m + i * x*y ) ) {
  1331. return false;
  1332. }
  1333. }
  1334. if ( !idLexer::ExpectTokenString( ")" ) ) {
  1335. return false;
  1336. }
  1337. return true;
  1338. }
  1339. /*
  1340. =================
  1341. idParser::ParseBracedSection
  1342. The next token should be an open brace.
  1343. Parses until a matching close brace is found.
  1344. Maintains exact characters between braces.
  1345. FIXME: this should use ReadToken and replace the token white space with correct indents and newlines
  1346. =================
  1347. */
  1348. const char *idLexer::ParseBracedSectionExact( idStr &out, int tabs ) {
  1349. int depth;
  1350. bool doTabs;
  1351. bool skipWhite;
  1352. out.Empty();
  1353. if ( !idLexer::ExpectTokenString( "{" ) ) {
  1354. return out.c_str( );
  1355. }
  1356. out = "{";
  1357. depth = 1;
  1358. skipWhite = false;
  1359. doTabs = tabs >= 0;
  1360. while( depth && *idLexer::script_p ) {
  1361. char c = *(idLexer::script_p++);
  1362. switch ( c ) {
  1363. case '\t':
  1364. case ' ': {
  1365. if ( skipWhite ) {
  1366. continue;
  1367. }
  1368. break;
  1369. }
  1370. case '\n': {
  1371. if ( doTabs ) {
  1372. skipWhite = true;
  1373. out += c;
  1374. continue;
  1375. }
  1376. break;
  1377. }
  1378. case '{': {
  1379. depth++;
  1380. tabs++;
  1381. break;
  1382. }
  1383. case '}': {
  1384. depth--;
  1385. tabs--;
  1386. break;
  1387. }
  1388. }
  1389. if ( skipWhite ) {
  1390. int i = tabs;
  1391. if ( c == '{' ) {
  1392. i--;
  1393. }
  1394. skipWhite = false;
  1395. for ( ; i > 0; i-- ) {
  1396. out += '\t';
  1397. }
  1398. }
  1399. out += c;
  1400. }
  1401. return out.c_str();
  1402. }
  1403. /*
  1404. =================
  1405. idLexer::ParseBracedSection
  1406. The next token should be an open brace.
  1407. Parses until a matching close brace is found.
  1408. Internal brace depths are properly skipped.
  1409. =================
  1410. */
  1411. const char *idLexer::ParseBracedSection( idStr &out ) {
  1412. idToken token;
  1413. int i, depth;
  1414. out.Empty();
  1415. if ( !idLexer::ExpectTokenString( "{" ) ) {
  1416. return out.c_str();
  1417. }
  1418. out = "{";
  1419. depth = 1;
  1420. do {
  1421. if ( !idLexer::ReadToken( &token ) ) {
  1422. Error( "missing closing brace" );
  1423. return out.c_str();
  1424. }
  1425. // if the token is on a new line
  1426. for ( i = 0; i < token.linesCrossed; i++ ) {
  1427. out += "\r\n";
  1428. }
  1429. if ( token.type == TT_PUNCTUATION ) {
  1430. if ( token[0] == '{' ) {
  1431. depth++;
  1432. }
  1433. else if ( token[0] == '}' ) {
  1434. depth--;
  1435. }
  1436. }
  1437. if ( token.type == TT_STRING ) {
  1438. out += "\"" + token + "\"";
  1439. }
  1440. else {
  1441. out += token;
  1442. }
  1443. out += " ";
  1444. } while( depth );
  1445. return out.c_str();
  1446. }
  1447. /*
  1448. =================
  1449. idLexer::ParseRestOfLine
  1450. parse the rest of the line
  1451. =================
  1452. */
  1453. const char *idLexer::ParseRestOfLine( idStr &out ) {
  1454. idToken token;
  1455. out.Empty();
  1456. while(idLexer::ReadToken( &token )) {
  1457. if ( token.linesCrossed ) {
  1458. idLexer::script_p = lastScript_p;
  1459. idLexer::line = lastline;
  1460. break;
  1461. }
  1462. if ( out.Length() ) {
  1463. out += " ";
  1464. }
  1465. out += token;
  1466. }
  1467. return out.c_str();
  1468. }
  1469. /*
  1470. ========================
  1471. idLexer::ParseCompleteLine
  1472. Returns a string up to the \n, but doesn't eat any whitespace at the beginning of the next line.
  1473. ========================
  1474. */
  1475. const char *idLexer::ParseCompleteLine( idStr &out ) {
  1476. idToken token;
  1477. const char *start;
  1478. start = script_p;
  1479. while ( 1 ) {
  1480. // end of buffer
  1481. if ( *script_p == 0 ) {
  1482. break;
  1483. }
  1484. if ( *script_p == '\n' ) {
  1485. line++;
  1486. script_p++;
  1487. break;
  1488. }
  1489. script_p++;
  1490. }
  1491. out.Empty();
  1492. out.Append( start, script_p - start );
  1493. return out.c_str();
  1494. }
  1495. /*
  1496. ================
  1497. idLexer::GetLastWhiteSpace
  1498. ================
  1499. */
  1500. int idLexer::GetLastWhiteSpace( idStr &whiteSpace ) const {
  1501. whiteSpace.Clear();
  1502. for ( const char *p = whiteSpaceStart_p; p < whiteSpaceEnd_p; p++ ) {
  1503. whiteSpace.Append( *p );
  1504. }
  1505. return whiteSpace.Length();
  1506. }
  1507. /*
  1508. ================
  1509. idLexer::GetLastWhiteSpaceStart
  1510. ================
  1511. */
  1512. int idLexer::GetLastWhiteSpaceStart() const {
  1513. return whiteSpaceStart_p - buffer;
  1514. }
  1515. /*
  1516. ================
  1517. idLexer::GetLastWhiteSpaceEnd
  1518. ================
  1519. */
  1520. int idLexer::GetLastWhiteSpaceEnd() const {
  1521. return whiteSpaceEnd_p - buffer;
  1522. }
  1523. /*
  1524. ================
  1525. idLexer::Reset
  1526. ================
  1527. */
  1528. void idLexer::Reset() {
  1529. // pointer in script buffer
  1530. idLexer::script_p = idLexer::buffer;
  1531. // pointer in script buffer before reading token
  1532. idLexer::lastScript_p = idLexer::buffer;
  1533. // begin of white space
  1534. idLexer::whiteSpaceStart_p = NULL;
  1535. // end of white space
  1536. idLexer::whiteSpaceEnd_p = NULL;
  1537. // set if there's a token available in idLexer::token
  1538. idLexer::tokenavailable = 0;
  1539. idLexer::line = 1;
  1540. idLexer::lastline = 1;
  1541. // clear the saved token
  1542. idLexer::token = "";
  1543. }
  1544. /*
  1545. ================
  1546. idLexer::EndOfFile
  1547. ================
  1548. */
  1549. bool idLexer::EndOfFile() {
  1550. return idLexer::script_p >= idLexer::end_p;
  1551. }
  1552. /*
  1553. ================
  1554. idLexer::NumLinesCrossed
  1555. ================
  1556. */
  1557. int idLexer::NumLinesCrossed() {
  1558. return idLexer::line - idLexer::lastline;
  1559. }
  1560. /*
  1561. ================
  1562. idLexer::LoadFile
  1563. ================
  1564. */
  1565. int idLexer::LoadFile( const char *filename, bool OSPath ) {
  1566. idFile *fp;
  1567. idStr pathname;
  1568. int length;
  1569. char *buf;
  1570. if ( idLexer::loaded ) {
  1571. idLib::common->Error("idLexer::LoadFile: another script already loaded");
  1572. return false;
  1573. }
  1574. if ( !OSPath && ( baseFolder[0] != '\0' ) ) {
  1575. pathname = va( "%s/%s", baseFolder, filename );
  1576. } else {
  1577. pathname = filename;
  1578. }
  1579. if ( OSPath ) {
  1580. fp = idLib::fileSystem->OpenExplicitFileRead( pathname );
  1581. } else {
  1582. fp = idLib::fileSystem->OpenFileRead( pathname );
  1583. }
  1584. if ( !fp ) {
  1585. return false;
  1586. }
  1587. length = fp->Length();
  1588. buf = (char *) Mem_Alloc( length + 1, TAG_IDLIB_LEXER );
  1589. buf[length] = '\0';
  1590. fp->Read( buf, length );
  1591. idLexer::fileTime = fp->Timestamp();
  1592. idLexer::filename = fp->GetFullPath();
  1593. idLib::fileSystem->CloseFile( fp );
  1594. idLexer::buffer = buf;
  1595. idLexer::length = length;
  1596. // pointer in script buffer
  1597. idLexer::script_p = idLexer::buffer;
  1598. // pointer in script buffer before reading token
  1599. idLexer::lastScript_p = idLexer::buffer;
  1600. // pointer to end of script buffer
  1601. idLexer::end_p = &(idLexer::buffer[length]);
  1602. idLexer::tokenavailable = 0;
  1603. idLexer::line = 1;
  1604. idLexer::lastline = 1;
  1605. idLexer::allocated = true;
  1606. idLexer::loaded = true;
  1607. return true;
  1608. }
  1609. /*
  1610. ================
  1611. idLexer::LoadMemory
  1612. ================
  1613. */
  1614. int idLexer::LoadMemory( const char *ptr, int length, const char *name, int startLine ) {
  1615. if ( idLexer::loaded ) {
  1616. idLib::common->Error("idLexer::LoadMemory: another script already loaded");
  1617. return false;
  1618. }
  1619. idLexer::filename = name;
  1620. idLexer::buffer = ptr;
  1621. idLexer::fileTime = 0;
  1622. idLexer::length = length;
  1623. // pointer in script buffer
  1624. idLexer::script_p = idLexer::buffer;
  1625. // pointer in script buffer before reading token
  1626. idLexer::lastScript_p = idLexer::buffer;
  1627. // pointer to end of script buffer
  1628. idLexer::end_p = &(idLexer::buffer[length]);
  1629. idLexer::tokenavailable = 0;
  1630. idLexer::line = startLine;
  1631. idLexer::lastline = startLine;
  1632. idLexer::allocated = false;
  1633. idLexer::loaded = true;
  1634. return true;
  1635. }
  1636. /*
  1637. ================
  1638. idLexer::FreeSource
  1639. ================
  1640. */
  1641. void idLexer::FreeSource() {
  1642. #ifdef PUNCTABLE
  1643. if ( idLexer::punctuationtable && idLexer::punctuationtable != default_punctuationtable ) {
  1644. Mem_Free( (void *) idLexer::punctuationtable );
  1645. idLexer::punctuationtable = NULL;
  1646. }
  1647. if ( idLexer::nextpunctuation && idLexer::nextpunctuation != default_nextpunctuation ) {
  1648. Mem_Free( (void *) idLexer::nextpunctuation );
  1649. idLexer::nextpunctuation = NULL;
  1650. }
  1651. #endif //PUNCTABLE
  1652. if ( idLexer::allocated ) {
  1653. Mem_Free( (void *) idLexer::buffer );
  1654. idLexer::buffer = NULL;
  1655. idLexer::allocated = false;
  1656. }
  1657. idLexer::tokenavailable = 0;
  1658. idLexer::token = "";
  1659. idLexer::loaded = false;
  1660. }
  1661. /*
  1662. ================
  1663. idLexer::idLexer
  1664. ================
  1665. */
  1666. idLexer::idLexer() {
  1667. idLexer::loaded = false;
  1668. idLexer::filename = "";
  1669. idLexer::flags = 0;
  1670. idLexer::SetPunctuations( NULL );
  1671. idLexer::allocated = false;
  1672. idLexer::fileTime = 0;
  1673. idLexer::length = 0;
  1674. idLexer::line = 0;
  1675. idLexer::lastline = 0;
  1676. idLexer::tokenavailable = 0;
  1677. idLexer::token = "";
  1678. idLexer::next = NULL;
  1679. idLexer::hadError = false;
  1680. }
  1681. /*
  1682. ================
  1683. idLexer::idLexer
  1684. ================
  1685. */
  1686. idLexer::idLexer( int flags ) {
  1687. idLexer::loaded = false;
  1688. idLexer::filename = "";
  1689. idLexer::flags = flags;
  1690. idLexer::SetPunctuations( NULL );
  1691. idLexer::allocated = false;
  1692. idLexer::fileTime = 0;
  1693. idLexer::length = 0;
  1694. idLexer::line = 0;
  1695. idLexer::lastline = 0;
  1696. idLexer::tokenavailable = 0;
  1697. idLexer::token = "";
  1698. idLexer::next = NULL;
  1699. idLexer::hadError = false;
  1700. }
  1701. /*
  1702. ================
  1703. idLexer::idLexer
  1704. ================
  1705. */
  1706. idLexer::idLexer( const char *filename, int flags, bool OSPath ) {
  1707. idLexer::loaded = false;
  1708. idLexer::flags = flags;
  1709. idLexer::SetPunctuations( NULL );
  1710. idLexer::allocated = false;
  1711. idLexer::token = "";
  1712. idLexer::next = NULL;
  1713. idLexer::hadError = false;
  1714. idLexer::LoadFile( filename, OSPath );
  1715. }
  1716. /*
  1717. ================
  1718. idLexer::idLexer
  1719. ================
  1720. */
  1721. idLexer::idLexer( const char *ptr, int length, const char *name, int flags ) {
  1722. idLexer::loaded = false;
  1723. idLexer::flags = flags;
  1724. idLexer::SetPunctuations( NULL );
  1725. idLexer::allocated = false;
  1726. idLexer::token = "";
  1727. idLexer::next = NULL;
  1728. idLexer::hadError = false;
  1729. idLexer::LoadMemory( ptr, length, name );
  1730. }
  1731. /*
  1732. ================
  1733. idLexer::~idLexer
  1734. ================
  1735. */
  1736. idLexer::~idLexer() {
  1737. idLexer::FreeSource();
  1738. }
  1739. /*
  1740. ================
  1741. idLexer::SetBaseFolder
  1742. ================
  1743. */
  1744. void idLexer::SetBaseFolder( const char *path ) {
  1745. idStr::Copynz( baseFolder, path, sizeof( baseFolder ) );
  1746. }
  1747. /*
  1748. ================
  1749. idLexer::HadError
  1750. ================
  1751. */
  1752. bool idLexer::HadError() const {
  1753. return hadError;
  1754. }