src/commands.cc

changeset 75
bf8c57437231
child 79
2425fa6a4f21
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 <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include "main.h"
35 #include "scriptreader.h"
36 #include "str.h"
37 #include "commands.h"
38 #include "lexer.h"
39
40 static list<command_info*> g_commands;
41
42 // ============================================================================
43 // Reads command definitions from commands.def and stores them to memory.
44 void init_commands ()
45 {
46 lexer lx;
47 lx.process_file ("commands.def");
48
49 while (lx.get_next())
50 {
51 command_info* comm = new command_info;
52
53 // Number
54 lx.must_be (tk_number);
55 comm->number = lx.get_token()->text.to_long();
56
57 lx.must_get_next (tk_colon);
58
59 // Name
60 lx.must_get_next (tk_symbol);
61 comm->name = lx.get_token()->text;
62
63 if (IsKeyword (comm->name))
64 error ("command name `%1` conflicts with keyword", comm->name);
65
66 lx.must_get_next (tk_colon);
67
68 // Return value
69 lx.must_get_any_of ({tk_int, tk_void, tk_bool, tk_str});
70 comm->returnvalue = GetTypeByName (lx.get_token()->text); // TODO
71 assert (comm->returnvalue != -1);
72
73 lx.must_get_next (tk_colon);
74
75 // Num args
76 lx.must_get_next (tk_number);
77 comm->numargs = lx.get_token()->text.to_long();
78
79 lx.must_get_next (tk_colon);
80
81 // Max args
82 lx.must_get_next (tk_number);
83 comm->maxargs = lx.get_token()->text.to_long();
84
85 // Argument types
86 int curarg = 0;
87
88 while (curarg < comm->maxargs)
89 {
90 command_argument arg;
91 lx.must_get_next (tk_colon);
92 lx.must_get_any_of ({tk_int, tk_bool, tk_str});
93 type_e type = GetTypeByName (lx.get_token()->text);
94 assert (type != -1 && type != TYPE_VOID);
95 arg.type = type;
96
97 lx.must_get_next (tk_paren_start);
98 lx.must_get_next (tk_symbol);
99 arg.name = lx.get_token()->text;
100
101 // If this is an optional parameter, we need the default value.
102 if (curarg >= comm->numargs)
103 {
104 lx.must_get_next (tk_assign);
105
106 switch (type)
107 {
108 case TYPE_INT:
109 case TYPE_BOOL:
110 lx.must_get_next (tk_number);
111 break;
112
113 case TYPE_STRING:
114 lx.must_get_next (tk_string);
115 break;
116
117 case TYPE_UNKNOWN:
118 case TYPE_VOID:
119 break;
120 }
121
122 arg.defvalue = lx.get_token()->text.to_long();
123 }
124
125 lx.must_get_next (tk_paren_end);
126 comm->args << arg;
127 curarg++;
128 }
129
130 g_commands << comm;
131 }
132
133 if (g_commands.is_empty())
134 error ("no commands defined!\n");
135
136 print ("%1 command definitions read.\n", g_commands.size());
137 }
138
139 // ============================================================================
140 // Finds a command by name
141 command_info* find_command_by_name (string fname)
142 {
143 for (command_info* comm : g_commands)
144 {
145 if (fname.to_uppercase() == comm->name.to_uppercase())
146 return comm;
147 }
148
149 return null;
150 }
151
152 // ============================================================================
153 // Returns the prototype of the command
154 string get_command_signature (command_info* comm)
155 {
156 string text;
157 text += GetTypeName (comm->returnvalue);
158 text += ' ';
159 text += comm->name;
160 text += '(';
161
162 bool hasoptionals = false;
163
164 for (int i = 0; i < comm->maxargs; i++)
165 {
166 if (i == comm->numargs)
167 {
168 hasoptionals = true;
169 text += '[';
170 }
171
172 if (i)
173 text += ", ";
174
175 text += GetTypeName (comm->args[i].type);
176 text += ' ';
177 text += comm->args[i].name;
178
179 if (i >= comm->numargs)
180 {
181 text += '=';
182
183 bool is_string = comm->args[i].type == TYPE_STRING;
184
185 if (is_string)
186 text += '"';
187
188 text += string::from_number (comm->args[i].defvalue);
189
190 if (is_string)
191 text += '"';
192 }
193 }
194
195 if (hasoptionals)
196 text += ']';
197
198 text += ')';
199 return text;
200 }
201
202 const list<command_info*> get_commands()
203 {
204 return g_commands;
205 }

mercurial