src/commands.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 <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
39 CommandDef* g_CommDef;
40
41 // ============================================================================
42 // Reads command definitions from commands.def and stores them to memory.
43 void ReadCommands () {
44 ScriptReader* r = new ScriptReader ("commands.def");
45 g_CommDef = null;
46 CommandDef* curdef = g_CommDef;
47 int numCommDefs = 0;
48
49 while (r->PeekNext().len()) {
50 CommandDef* comm = new CommandDef;
51 comm->next = null;
52
53 // Number
54 r->MustNumber ();
55 comm->number = r->token.to_long();
56
57 r->MustNext (":");
58
59 // Name
60 r->MustNext ();
61 comm->name = r->token;
62 if (IsKeyword (comm->name))
63 r->ParserError ("command name `%s` conflicts with keyword", comm->name.chars());
64
65 r->MustNext (":");
66
67 // Return value
68 r->MustNext ();
69 comm->returnvalue = GetTypeByName (r->token);
70 if (comm->returnvalue == -1)
71 r->ParserError ("bad return value type `%s` for command %s", r->token.chars(), comm->name.chars());
72
73 r->MustNext (":");
74
75 // Num args
76 r->MustNumber ();
77 comm->numargs = r->token.to_long();
78
79 r->MustNext (":");
80
81 // Max args
82 r->MustNumber ();
83 comm->maxargs = r->token.to_long();
84
85 if (comm->maxargs > MAX_MAXARGS)
86 r->ParserError ("maxargs (%d) greater than %d!", comm->maxargs, MAX_MAXARGS);
87
88 // Argument types
89 int curarg = 0;
90 while (curarg < comm->maxargs) {
91 r->MustNext (":");
92 r->MustNext ();
93
94 type_e type = GetTypeByName (r->token);
95 if (type == -1)
96 r->ParserError ("bad argument %d type `%s`", curarg, r->token.chars());
97 if (type == TYPE_VOID)
98 r->ParserError ("void is not a valid argument type!");
99 comm->argtypes[curarg] = type;
100
101 r->MustNext ("(");
102 r->MustNext ();
103
104 // - 1 because of terminating null character
105 if (r->token.len() > MAX_ARGNAMELEN - 1)
106 r->ParserWarning ("argument name is too long (%d, max is %d)",
107 r->token.len(), MAX_ARGNAMELEN - 1);
108
109 strncpy (comm->argnames[curarg], r->token.chars(), MAX_ARGNAMELEN);
110 comm->argnames[curarg][MAX_ARGNAMELEN-1] = 0;
111
112 // If this is an optional parameter, we need the default value.
113 if (curarg >= comm->numargs) {
114 r->MustNext ("=");
115 switch (type) {
116 case TYPE_INT:
117 case TYPE_BOOL:
118 r->MustNumber();
119 break;
120 case TYPE_STRING:
121 r->MustString();
122 break;
123 case TYPE_UNKNOWN:
124 case TYPE_VOID:
125 break;
126 }
127
128 comm->defvals[curarg] = r->token.to_long();
129 }
130
131 r->MustNext (")");
132 curarg++;
133 }
134
135 if (!g_CommDef)
136 g_CommDef = comm;
137
138 if (!curdef) {
139 curdef = comm;
140 } else {
141 curdef->next = comm;
142 curdef = comm;
143 }
144 numCommDefs++;
145 }
146
147 if (!numCommDefs)
148 r->ParserError ("no commands defined!\n");
149
150 r->CloseFile ();
151 delete r;
152 printf ("%d command definitions read.\n", numCommDefs);
153 }
154
155 // ============================================================================
156 // Finds a command by name
157 CommandDef* FindCommand (string fname) {
158 CommandDef* comm;
159 ITERATE_COMMANDS (comm) {
160 if (fname.to_uppercase() == comm->name.to_uppercase())
161 return comm;
162 }
163
164 return null;
165 }
166
167 // ============================================================================
168 // Returns the prototype of the command
169 string GetCommandPrototype (CommandDef* comm) {
170 string text;
171 text += GetTypeName (comm->returnvalue);
172 text += ' ';
173 text += comm->name;
174 text += '(';
175
176 bool hasOptionalArguments = false;
177 for (int i = 0; i < comm->maxargs; i++) {
178 if (i == comm->numargs) {
179 hasOptionalArguments = true;
180 text += '[';
181 }
182
183 if (i)
184 text += ", ";
185
186 text += GetTypeName (comm->argtypes[i]);
187 text += ' ';
188 text += comm->argnames[i];
189
190 if (i >= comm->numargs) {
191 text += '=';
192
193 bool isString = comm->argtypes[i] == TYPE_STRING;
194 if (isString) text += '"';
195
196 char defvalstring[8];
197 sprintf (defvalstring, "%d", comm->defvals[i]);
198 text += defvalstring;
199
200 if (isString) text += '"';
201 }
202 }
203
204 if (hasOptionalArguments)
205 text += ']';
206 text += ')';
207 return text;
208 }

mercurial