1 #include <stdio.h> |
|
2 #include <stdlib.h> |
|
3 #include "main.h" |
|
4 #include "str.h" |
|
5 #include "scriptreader.h" |
|
6 |
|
7 /* Since the preprocessor is *called* from ReadChar and I don't want |
|
8 * to worry about recursive preprocessing, the preprocessor uses its |
|
9 * own bare-bones variant of the function for file reading. |
|
10 */ |
|
11 char ScriptReader::PPReadChar () { |
|
12 char c; |
|
13 if (!fread (&c, sizeof (char), 1, fp[fc])) |
|
14 return 0; |
|
15 curchar[fc]++; |
|
16 return c; |
|
17 } |
|
18 |
|
19 void ScriptReader::PPMustChar (char c) { |
|
20 char d = PPReadChar (); |
|
21 if (c != d) |
|
22 ParserError ("expected `%c`, got `%d`", c, d); |
|
23 } |
|
24 |
|
25 // ============================================================================ |
|
26 // Reads a word until whitespace |
|
27 string ScriptReader::PPReadWord (char &term) { |
|
28 string word; |
|
29 while (1) { |
|
30 char c = PPReadChar(); |
|
31 if (feof (fp[fc]) || (isspace (c) && word.len ())) { |
|
32 term = c; |
|
33 break; |
|
34 } |
|
35 word += c; |
|
36 } |
|
37 return word; |
|
38 } |
|
39 |
|
40 // ============================================================================ |
|
41 // Preprocess any directives found in the script file |
|
42 void ScriptReader::PreprocessDirectives () { |
|
43 size_t spos = ftell (fp[fc]); |
|
44 if (!DoDirectivePreprocessing ()) |
|
45 fseek (fp[fc], spos, SEEK_SET); |
|
46 } |
|
47 |
|
48 /* ============================================================================ |
|
49 * Returns true if the pre-processing was successful, false if not. |
|
50 * If pre-processing was successful, the file pointer remains where |
|
51 * it was, if not, it's pushed back to where it was before preprocessing |
|
52 * took place and is parsed normally. |
|
53 */ |
|
54 bool ScriptReader::DoDirectivePreprocessing () { |
|
55 char trash; |
|
56 // Directives start with a pound sign |
|
57 if (PPReadChar() != '#') |
|
58 return false; |
|
59 |
|
60 // Read characters until next whitespace to |
|
61 // build the name of the directive |
|
62 string directive = PPReadWord (trash); |
|
63 |
|
64 // Now check the directive name against known names |
|
65 if (directive == "include") { |
|
66 // #include-directive |
|
67 char terminator; |
|
68 string file = PPReadWord (terminator); |
|
69 |
|
70 if (!file.len()) |
|
71 ParserError ("expected file name for #include, got nothing instead"); |
|
72 OpenFile (file); |
|
73 return true; |
|
74 } else if (directive == "neurosphere") { |
|
75 // #neurosphere - activates neurosphere compatibility, aka stuff |
|
76 // that is still WIP and what main zandronum does not yet support. |
|
77 // Most end users should never need this. |
|
78 g_Neurosphere = true; |
|
79 return true; |
|
80 } |
|
81 |
|
82 ParserError ("unknown directive `#%s`!", directive.chars()); |
|
83 return false; |
|
84 } |
|