src/main.cxx

changeset 75
bf8c57437231
parent 74
007fbadfa7f9
child 76
c8058716070a
equal deleted inserted replaced
74:007fbadfa7f9 75:bf8c57437231
1 /*
2 Copyright (c) 2013-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 "containers.h"
39 #include "data_buffer.h"
40 #include "bots.h"
41 #include "object_writer.h"
42 #include "parser.h"
43
44 // List of keywords
45 const string_list g_Keywords =
46 {
47 "bool",
48 "break",
49 "case",
50 "continue",
51 "const",
52 "default",
53 "do",
54 "else",
55 "event",
56 "for",
57 "goto",
58 "if",
59 "int",
60 "mainloop",
61 "onenter",
62 "onexit",
63 "state",
64 "switch",
65 "str"
66 "void",
67 "while",
68
69 // These ones aren't implemented yet but I plan to do so, thus they are
70 // reserved. Also serves as a to-do list of sorts for me. >:F
71 "enum", // Would enum actually be useful? I think so.
72 "func", // Would function support need external support from zandronum?
73 "return",
74 };
75
76 // databuffer global variable
77 int g_NextMark = 0;
78
79 int main (int argc, char** argv)
80 {
81 // Intepret command-line parameters:
82 // -l: list commands
83 // I guess there should be a better way to do this.
84 if (argc == 2 && !strcmp (argv[1], "-l"))
85 {
86 ReadCommands();
87 printf ("Begin list of commands:\n");
88 printf ("------------------------------------------------------\n");
89
90 CommandDef* comm;
91 ITERATE_COMMANDS (comm)
92 print ("%1\n", GetCommandPrototype (comm));
93
94 printf ("------------------------------------------------------\n");
95 printf ("End of command list\n");
96 exit (0);
97 }
98
99 // Print header
100 string header;
101 string headerline;
102 header = format ("%1 version %2.%3", APPNAME, VERSION_MAJOR, VERSION_MINOR);
103
104 for (int i = 0; i < (header.len() / 2) - 1; ++i)
105 headerline += "-=";
106
107 headerline += '-';
108 print ("%1\n%2\n", header, headerline);
109
110 if (argc < 2)
111 {
112 fprintf (stderr, "usage: %s <infile> [outfile] # compiles botscript\n", argv[0]);
113 fprintf (stderr, " %s -l # lists commands\n", argv[0]);
114 exit (1);
115 }
116
117 string outfile;
118
119 if (argc < 3)
120 outfile = ObjectFileName (argv[1]);
121 else
122 outfile = argv[2];
123
124 // If we'd end up writing into an existing file,
125 // ask the user if we want to overwrite it
126 if (fexists (outfile))
127 {
128 // Additional warning if the paths are the same
129 string warning;
130 #ifdef FILE_CASEINSENSITIVE
131
132 if (+outfile == +string (argv[1]))
133 #else
134 if (outfile == argv[1])
135 #endif
136 {
137 warning = "\nWARNING: Output file is the same as the input file. ";
138 warning += "Answering yes here will destroy the source!\n";
139 warning += "Continue nevertheless?";
140 }
141
142 printf ("output file `%s` already exists! overwrite?%s (y/n) ", outfile.chars(), warning.chars());
143
144 char ans;
145 fgets (&ans, 1, stdin);
146
147 if (ans != 'y')
148 {
149 printf ("abort\n");
150 exit (1);
151 }
152 }
153
154 // Read definitions
155 printf ("Reading definitions...\n");
156 ReadEvents();
157 ReadCommands();
158
159 // Prepare reader and writer
160 botscript_parser* r = new botscript_parser;
161 object_writer* w = new object_writer;
162
163 // We're set, begin parsing :)
164 printf ("Parsing script...\n");
165 r->parse_botscript (argv[1], w);
166 printf ("Script parsed successfully.\n");
167
168 // Parse done, print statistics and write to file
169 int globalcount = g_GlobalVariables.size();
170 int stringcount = num_strings_in_table();
171 int NumMarks = w->MainBuffer->count_marks();
172 int NumRefs = w->MainBuffer->count_references();
173 print ("%1 / %2 strings written\n", stringcount, MAX_LIST_STRINGS);
174 print ("%1 / %2 global variables\n", globalcount, MAX_SCRIPT_VARIABLES);
175 print ("%1 / %2 bytecode marks\n", NumMarks, MAX_MARKS); // TODO: nuke
176 print ("%1 / %2 bytecode references\n", NumRefs, MAX_MARKS); // TODO: nuke
177 print ("%1 / %2 events\n", g_NumEvents, MAX_NUM_EVENTS);
178 print ("%1 state%s1\n", g_NumStates);
179
180 w->write_to_file (outfile);
181
182 // Clear out the junk
183 delete r;
184 delete w;
185
186 // Done!
187 exit (0);
188 }
189
190 // ============================================================================
191 // Utility functions
192
193 // ============================================================================
194 // Does the given file exist?
195 bool fexists (string path)
196 {
197 if (FILE* test = fopen (path, "r"))
198 {
199 fclose (test);
200 return true;
201 }
202
203 return false;
204 }
205
206 // ============================================================================
207 // Generic error
208 void error (const char* text, ...)
209 {
210 va_list va;
211 va_start (va, text);
212 fprintf (stderr, "error: ");
213 vfprintf (stderr, text, va);
214 va_end (va);
215 exit (1);
216 }
217
218 // ============================================================================
219 // Mutates given filename to an object filename
220 string ObjectFileName (string s)
221 {
222 // Locate the extension and chop it out
223 int extdot = s.last (".");
224
225 if (extdot >= s.len() - 4)
226 s -= (s.len() - extdot);
227
228 s += ".o";
229 return s;
230 }
231
232 // ============================================================================
233 // Is the given argument a reserved keyword?
234 bool IsKeyword (string s)
235 {
236 for (int u = 0; u < NumKeywords(); u++)
237 if (s.to_uppercase() == g_Keywords[u].to_uppercase())
238 return true;
239
240 return false;
241 }
242
243 int NumKeywords()
244 {
245 return sizeof (g_Keywords) / sizeof (const char*);
246 }
247
248 // ============================================================================
249 type_e GetTypeByName (string t)
250 {
251 t = t.to_lowercase();
252 return (t == "int") ? TYPE_INT :
253 (t == "str") ? TYPE_STRING :
254 (t == "void") ? TYPE_VOID :
255 (t == "bool") ? TYPE_BOOL :
256 TYPE_UNKNOWN;
257 }
258
259
260 // ============================================================================
261 // Inverse operation - type name by value
262 string GetTypeName (type_e type)
263 {
264 switch (type)
265 {
266 case TYPE_INT: return "int"; break;
267
268 case TYPE_STRING: return "str"; break;
269
270 case TYPE_VOID: return "void"; break;
271
272 case TYPE_BOOL: return "bool"; break;
273
274 case TYPE_UNKNOWN: return "???"; break;
275 }
276
277 return "";
278 }

mercurial