src/scriptreader.cxx

changeset 72
03e4d9db3fd9
parent 71
11f23fabf8a6
child 73
1ee9b312dc18
equal deleted inserted replaced
71:11f23fabf8a6 72:03e4d9db3fd9
1 /* 1 #include "main.h"
2 * botc source code
3 * Copyright (C) 2012 Santeri `Dusk` Piippo
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3. Neither the name of the developer nor the names of its contributors may
15 * be used to endorse or promote products derived from this software without
16 * specific prior written permission.
17 * 4. Redistributions in any form must be accompanied by information on how to
18 * obtain complete source code for the software and any accompanying
19 * software that uses the software. The source code must either be included
20 * in the distribution or be available for no more than the cost of
21 * distribution plus a nominal fee, and must be freely redistributable
22 * under reasonable conditions. For an executable file, complete source
23 * code means the source code for all modules it contains. It does not
24 * include source code for modules or files that typically accompany the
25 * major components of the operating system on which the executable file
26 * runs.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
32 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include "string.h"
44 #include "str.h"
45 #include "common.h"
46 #include "scriptreader.h" 2 #include "scriptreader.h"
47 3
48 #define STORE_POSITION \ 4 #define STORE_POSITION \
49 bool _atnewline = atnewline; \ 5 bool stored_atnewline = atnewline; \
50 unsigned int _curline = curline[fc]; \ 6 unsigned int stored_curline = curline[fc]; \
51 unsigned int _curchar = curchar[fc]; 7 unsigned int stored_curchar = curchar[fc];
52 8
53 #define RESTORE_POSITION \ 9 #define RESTORE_POSITION \
54 atnewline = _atnewline; \ 10 atnewline = stored_atnewline; \
55 curline[fc] = _curline; \ 11 curline[fc] = stored_curline; \
56 curchar[fc] = _curchar; 12 curchar[fc] = stored_curchar;
57 13
58 // ============================================================================ 14 // ============================================================================
59 ScriptReader::ScriptReader (str path) { 15 ScriptReader::ScriptReader (string path) {
60 token = ""; 16 token = "";
61 prevtoken = ""; 17 prevtoken = "";
62 prevpos = 0; 18 prevpos = 0;
63 fc = -1; 19 fc = -1;
64 20
65 for (unsigned int u = 0; u < MAX_FILESTACK; u++) 21 for (unsigned int u = 0; u < MAX_FILESTACK; u++)
66 fp[u] = NULL; 22 fp[u] = null;
67 23
68 OpenFile (path); 24 OpenFile (path);
69 commentmode = 0; 25 commentmode = 0;
70 } 26 }
71 27
85 } 41 }
86 } 42 }
87 43
88 // ============================================================================ 44 // ============================================================================
89 // Opens a file and pushes its pointer to stack 45 // Opens a file and pushes its pointer to stack
90 void ScriptReader::OpenFile (str path) { 46 void ScriptReader::OpenFile (string path) {
91 if (fc+1 >= MAX_FILESTACK) 47 if (fc+1 >= MAX_FILESTACK)
92 ParserError ("supposed to open file `%s` but file stack is full! do you have recursive `#include` directives?", 48 ParserError ("supposed to open file `%s` but file stack is full! do you have recursive `#include` directives?",
93 path.chars()); 49 path.chars());
94 50
95 // Save the position first. 51 // Save the position first.
121 77
122 if (!fp[u]) 78 if (!fp[u])
123 return; 79 return;
124 80
125 fclose (fp[u]); 81 fclose (fp[u]);
126 fp[u] = NULL; 82 fp[u] = null;
127 fc--; 83 fc--;
128 84
129 if (fc != -1) 85 if (fc != -1)
130 fseek (fp[fc], savedpos[fc], SEEK_SET); 86 fseek (fp[fc], savedpos[fc], SEEK_SET);
131 } 87 }
184 140
185 // ============================================================================ 141 // ============================================================================
186 // Read a token from the file buffer. Returns true if token was found, false if not. 142 // Read a token from the file buffer. Returns true if token was found, false if not.
187 bool ScriptReader::Next (bool peek) { 143 bool ScriptReader::Next (bool peek) {
188 prevpos = ftell (fp[fc]); 144 prevpos = ftell (fp[fc]);
189 str tmp = ""; 145 string tmp = "";
190 146
191 while (1) { 147 while (1) {
192 // Check end-of-file 148 // Check end-of-file
193 if (feof (fp[fc])) { 149 if (feof (fp[fc])) {
194 // If we're just peeking, we shouldn't 150 // If we're just peeking, we shouldn't
249 else 205 else
250 tmp += c; 206 tmp += c;
251 break; 207 break;
252 } 208 }
253 209
254 if (IsCharWhitespace (c)) { 210 if (isspace (c)) {
255 // Don't break if we haven't gathered anything yet. 211 // Don't break if we haven't gathered anything yet.
256 if (tmp.len()) 212 if (tmp.len())
257 break; 213 break;
258 } else { 214 } else {
259 tmp += c; 215 tmp += c;
273 return true; 229 return true;
274 } 230 }
275 231
276 // ============================================================================ 232 // ============================================================================
277 // Returns the next token without advancing the cursor. 233 // Returns the next token without advancing the cursor.
278 str ScriptReader::PeekNext (int offset) { 234 string ScriptReader::PeekNext (int offset) {
279 // Store current information 235 // Store current information
280 str storedtoken = token; 236 string storedtoken = token;
281 int cpos = ftell (fp[fc]); 237 int cpos = ftell (fp[fc]);
282 STORE_POSITION 238 STORE_POSITION
283 239
284 // Advance on the token. 240 // Advance on the token.
285 while (offset >= 0) { 241 while (offset >= 0) {
286 if (!Next (true)) 242 if (!Next (true))
287 return ""; 243 return "";
288 offset--; 244 offset--;
289 } 245 }
290 246
291 str tmp = token; 247 string tmp = token;
292 248
293 // Restore position 249 // Restore position
294 fseek (fp[fc], cpos, SEEK_SET); 250 fseek (fp[fc], cpos, SEEK_SET);
295 pos[fc]--; 251 pos[fc]--;
296 token = storedtoken; 252 token = storedtoken;
335 ParserError ("expected `%s`, got `%s` instead", c, token.chars()); 291 ParserError ("expected `%s`, got `%s` instead", c, token.chars());
336 } 292 }
337 293
338 // ============================================================================ 294 // ============================================================================
339 void ScriptReader::ParserError (const char* message, ...) { 295 void ScriptReader::ParserError (const char* message, ...) {
340 PERFORM_FORMAT (message, outmessage); 296 char buf[512];
341 ParserMessage ("\nError: ", outmessage); 297 va_list va;
298 va_start (va, message);
299 sprintf (buf, message, va);
300 va_end (va);
301 ParserMessage ("\nError: ", buf);
342 exit (1); 302 exit (1);
343 } 303 }
344 304
345 // ============================================================================ 305 // ============================================================================
346 void ScriptReader::ParserWarning (const char* message, ...) { 306 void ScriptReader::ParserWarning (const char* message, ...) {
347 PERFORM_FORMAT (message, outmessage); 307 char buf[512];
348 ParserMessage ("Warning: ", outmessage); 308 va_list va;
349 } 309 va_start (va, message);
350 310 sprintf (buf, message, va);
351 // ============================================================================ 311 va_end (va);
352 void ScriptReader::ParserMessage (const char* header, char* message) { 312 ParserMessage ("Warning: ", buf);
313 }
314
315 // ============================================================================
316 void ScriptReader::ParserMessage (const char* header, string message) {
353 if (fc >= 0 && fc < MAX_FILESTACK) 317 if (fc >= 0 && fc < MAX_FILESTACK)
354 fprintf (stderr, "%s%s:%u:%u: %s\n", 318 fprintf (stderr, "%s%s:%u:%u: %s\n",
355 header, filepath[fc], curline[fc], curchar[fc], message); 319 header, filepath[fc].c_str(), curline[fc], curchar[fc], message.c_str());
356 else 320 else
357 fprintf (stderr, "%s%s\n", header, message); 321 fprintf (stderr, "%s%s\n", header, message.c_str());
358 } 322 }
359 323
360 // ============================================================================ 324 // ============================================================================
361 // if gotquote == 1, the current token already holds the quotation mark. 325 // if gotquote == 1, the current token already holds the quotation mark.
362 void ScriptReader::MustString (bool gotquote) { 326 void ScriptReader::MustString (bool gotquote) {
363 if (gotquote) 327 if (gotquote)
364 MustThis ("\""); 328 MustThis ("\"");
365 else 329 else
366 MustNext ("\""); 330 MustNext ("\"");
367 331
368 str string; 332 string string;
369 // Keep reading characters until we find a terminating quote. 333 // Keep reading characters until we find a terminating quote.
370 while (1) { 334 while (1) {
371 // can't end here! 335 // can't end here!
372 if (feof (fp[fc])) 336 if (feof (fp[fc]))
373 ParserError ("unterminated string"); 337 ParserError ("unterminated string");
385 // ============================================================================ 349 // ============================================================================
386 void ScriptReader::MustNumber (bool fromthis) { 350 void ScriptReader::MustNumber (bool fromthis) {
387 if (!fromthis) 351 if (!fromthis)
388 MustNext (); 352 MustNext ();
389 353
390 str num = token; 354 string num = token;
391 if (num == "-") { 355 if (num == "-") {
392 MustNext (); 356 MustNext ();
393 num += token; 357 num += token;
394 } 358 }
395 359
396 // "true" and "false" are valid numbers 360 // "true" and "false" are valid numbers
397 if (!token.icompare ("true")) 361 if (-token == "true")
398 token = "1"; 362 token = "1";
399 else if (!token.icompare ("false")) 363 else if (-token == "false")
400 token = "0"; 364 token = "0";
401 else { 365 else {
402 if (!token.isnumber()) 366 bool ok;
403 ParserError ("expected a number, got `%s`", num.chars()); 367 int num = token.to_long (&ok);
404 368
405 str check; 369 if (!ok)
406 check.appendformat ("%d", atoi (num)); 370 ParserError ("expected a number, got `%s`", token.chars());
407 if (token != check) 371
408 ParserWarning ("integer too large: %s -> %s", num.chars(), check.chars());
409
410 token = num; 372 token = num;
411 } 373 }
412 } 374 }

mercurial