src/main.cc

changeset 75
bf8c57437231
child 77
ad17801b1a36
equal deleted inserted replaced
74:007fbadfa7f9 75:bf8c57437231
1 /*
2 Copyright (c) 2012-2014, Santeri Piippo
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 * Neither the name of the <organization> nor the
16 names of its contributors may be used to endorse or promote products
17 derived from this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "main.h"
32 #include "scriptreader.h"
33 #include "object_writer.h"
34 #include "events.h"
35 #include "commands.h"
36 #include "stringtable.h"
37 #include "variables.h"
38 #include "data_buffer.h"
39 #include "object_writer.h"
40 #include "parser.h"
41 #include "lexer.h"
42
43 // List of keywords
44 const string_list g_Keywords =
45 {
46 "bool",
47 "break",
48 "case",
49 "continue",
50 "const",
51 "default",
52 "do",
53 "else",
54 "event",
55 "for",
56 "goto",
57 "if",
58 "int",
59 "mainloop",
60 "onenter",
61 "onexit",
62 "state",
63 "switch",
64 "str"
65 "void",
66 "while",
67
68 // These ones aren't implemented yet but I plan to do so, thus they are
69 // reserved. Also serves as a to-do list of sorts for me. >:F
70 "enum", // Would enum actually be useful? I think so.
71 "func", // Would function support need external support from zandronum?
72 "return",
73 };
74
75 // databuffer global variable
76 int g_NextMark = 0;
77
78 int main (int argc, char** argv)
79 {
80 try
81 {
82 // Intepret command-line parameters:
83 // -l: list commands
84 // I guess there should be a better way to do this.
85 if (argc == 2 && !strcmp (argv[1], "-l"))
86 {
87 command_info* comm;
88 init_commands();
89 printf ("Begin list of commands:\n");
90 printf ("------------------------------------------------------\n");
91
92 for (command_info* comm : get_commands())
93 print ("%1\n", get_command_signature (comm));
94
95 printf ("------------------------------------------------------\n");
96 printf ("End of command list\n");
97 exit (0);
98 }
99
100 // Print header
101 string header;
102 string headerline;
103 header = format ("%1 version %2.%3", APPNAME, VERSION_MAJOR, VERSION_MINOR);
104
105 for (int i = 0; i < (header.len() / 2) - 1; ++i)
106 headerline += "-=";
107
108 headerline += '-';
109 print ("%1\n%2\n", header, headerline);
110
111 if (argc < 2)
112 {
113 fprintf (stderr, "usage: %s <infile> [outfile] # compiles botscript\n", argv[0]);
114 fprintf (stderr, " %s -l # lists commands\n", argv[0]);
115 exit (1);
116 }
117
118 string outfile;
119
120 if (argc < 3)
121 outfile = ObjectFileName (argv[1]);
122 else
123 outfile = argv[2];
124
125 // If we'd end up writing into an existing file,
126 // ask the user if we want to overwrite it
127 if (fexists (outfile))
128 {
129 // Additional warning if the paths are the same
130 string warning;
131 #ifdef FILE_CASEINSENSITIVE
132
133 if (+outfile == +string (argv[1]))
134 #else
135 if (outfile == argv[1])
136 #endif
137 {
138 warning = "\nWARNING: Output file is the same as the input file. ";
139 warning += "Answering yes here will destroy the source!\n";
140 warning += "Continue nevertheless?";
141 }
142
143 printf ("output file `%s` already exists! overwrite?%s (y/n) ", outfile.chars(), warning.chars());
144
145 char ans;
146 fgets (&ans, 1, stdin);
147
148 if (ans != 'y')
149 {
150 printf ("abort\n");
151 exit (1);
152 }
153 }
154
155 // Read definitions
156 printf ("Reading definitions...\n");
157 init_events();
158 init_commands();
159
160 // Prepare reader and writer
161 botscript_parser* r = new botscript_parser;
162 object_writer* w = new object_writer;
163
164 // We're set, begin parsing :)
165 printf ("Parsing script...\n");
166 r->parse_botscript (argv[1], w);
167 printf ("Script parsed successfully.\n");
168
169 // Parse done, print statistics and write to file
170 int globalcount = g_GlobalVariables.size();
171 int stringcount = num_strings_in_table();
172 int NumMarks = w->MainBuffer->count_marks();
173 int NumRefs = w->MainBuffer->count_references();
174 print ("%1 / %2 strings written\n", stringcount, g_max_stringlist_size);
175 print ("%1 / %2 global variables\n", globalcount, g_max_global_vars);
176 print ("%1 / %2 bytecode marks\n", NumMarks, MAX_MARKS); // TODO: nuke
177 print ("%1 / %2 bytecode references\n", NumRefs, MAX_MARKS); // TODO: nuke
178 print ("%1 / %2 events\n", g_NumEvents, g_max_events);
179 print ("%1 state%s1\n", g_NumStates);
180
181 w->write_to_file (outfile);
182
183 // Clear out the junk
184 delete r;
185 delete w;
186
187 // Done!
188 exit (0);
189 }
190 catch (script_error& e)
191 {
192 lexer* lx = lexer::get_main_lexer();
193 string fileinfo;
194
195 if (lx != null && lx->has_valid_token())
196 {
197 lexer::token* tk = lx->get_token();
198 fileinfo = format ("%1:%2:%3: ", tk->file, tk->line, tk->column);
199 }
200
201 fprint (stderr, "%1error: %2\n", fileinfo, e.what());
202 }
203 }
204
205 // ============================================================================
206 // Utility functions
207
208 // ============================================================================
209 // Does the given file exist?
210 bool fexists (string path)
211 {
212 if (FILE* test = fopen (path, "r"))
213 {
214 fclose (test);
215 return true;
216 }
217
218 return false;
219 }
220
221 // ============================================================================
222 // Mutates given filename to an object filename
223 string ObjectFileName (string s)
224 {
225 // Locate the extension and chop it out
226 int extdot = s.last (".");
227
228 if (extdot >= s.len() - 4)
229 s -= (s.len() - extdot);
230
231 s += ".o";
232 return s;
233 }
234
235 // ============================================================================
236 // Is the given argument a reserved keyword?
237 bool IsKeyword (string s)
238 {
239 for (int u = 0; u < NumKeywords(); u++)
240 if (s.to_uppercase() == g_Keywords[u].to_uppercase())
241 return true;
242
243 return false;
244 }
245
246 int NumKeywords()
247 {
248 return sizeof (g_Keywords) / sizeof (const char*);
249 }
250
251 // ============================================================================
252 type_e GetTypeByName (string t)
253 {
254 t = t.to_lowercase();
255 return (t == "int") ? TYPE_INT :
256 (t == "str") ? TYPE_STRING :
257 (t == "void") ? TYPE_VOID :
258 (t == "bool") ? TYPE_BOOL :
259 TYPE_UNKNOWN;
260 }
261
262
263 // ============================================================================
264 // Inverse operation - type name by value
265 string GetTypeName (type_e type)
266 {
267 switch (type)
268 {
269 case TYPE_INT: return "int"; break;
270
271 case TYPE_STRING: return "str"; break;
272
273 case TYPE_VOID: return "void"; break;
274
275 case TYPE_BOOL: return "bool"; break;
276
277 case TYPE_UNKNOWN: return "???"; break;
278 }
279
280 return "";
281 }

mercurial