commands.cxx

changeset 71
11f23fabf8a6
parent 70
fc257920ac00
child 72
03e4d9db3fd9
equal deleted inserted replaced
70:fc257920ac00 71:11f23fabf8a6
1 /*
2 * botc source code
3 * Copyright (C) 2012 Santeri `Dusk` Piippo
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3. Neither the name of the developer nor the names of its contributors may
15 * be used to endorse or promote products derived from this software without
16 * specific prior written permission.
17 * 4. Redistributions in any form must be accompanied by information on how to
18 * obtain complete source code for the software and any accompanying
19 * software that uses the software. The source code must either be included
20 * in the distribution or be available for no more than the cost of
21 * distribution plus a nominal fee, and must be freely redistributable
22 * under reasonable conditions. For an executable file, complete source
23 * code means the source code for all modules it contains. It does not
24 * include source code for modules or files that typically accompany the
25 * major components of the operating system on which the executable file
26 * runs.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
32 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #define __COMMANDS_CXX__
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include "common.h"
46 #include "scriptreader.h"
47 #include "str.h"
48 #include "commands.h"
49
50 // ============================================================================
51 // Reads command definitions from commands.def and stores them to memory.
52 void ReadCommands () {
53 ScriptReader* r = new ScriptReader ("commands.def");
54 g_CommDef = NULL;
55 CommandDef* curdef = g_CommDef;
56 unsigned int numCommDefs = 0;
57
58 while (r->PeekNext().len()) {
59 CommandDef* comm = new CommandDef;
60 comm->next = NULL;
61
62 // Number
63 r->MustNumber ();
64 comm->number = r->token;
65
66 r->MustNext (":");
67
68 // Name
69 r->MustNext ();
70 comm->name = r->token;
71 if (IsKeyword (comm->name))
72 r->ParserError ("command name `%s` conflicts with keyword", comm->name.chars());
73
74 r->MustNext (":");
75
76 // Return value
77 r->MustNext ();
78 comm->returnvalue = GetTypeByName (r->token);
79 if (comm->returnvalue == -1)
80 r->ParserError ("bad return value type `%s` for command %s", r->token.chars(), comm->name.chars());
81
82 r->MustNext (":");
83
84 // Num args
85 r->MustNumber ();
86 comm->numargs = r->token;
87
88 r->MustNext (":");
89
90 // Max args
91 r->MustNumber ();
92 comm->maxargs = r->token;
93
94 if (comm->maxargs > MAX_MAXARGS)
95 r->ParserError ("maxargs (%d) greater than %d!", comm->maxargs, MAX_MAXARGS);
96
97 // Argument types
98 int curarg = 0;
99 while (curarg < comm->maxargs) {
100 r->MustNext (":");
101 r->MustNext ();
102
103 type_e type = GetTypeByName (r->token);
104 if (type == -1)
105 r->ParserError ("bad argument %d type `%s`", curarg, r->token.chars());
106 if (type == TYPE_VOID)
107 r->ParserError ("void is not a valid argument type!");
108 comm->argtypes[curarg] = type;
109
110 r->MustNext ("(");
111 r->MustNext ();
112
113 // - 1 because of terminating null character
114 if (r->token.len() > MAX_ARGNAMELEN - 1)
115 r->ParserWarning ("argument name is too long (%d, max is %d)",
116 r->token.len(), MAX_ARGNAMELEN - 1);
117
118 strncpy (comm->argnames[curarg], r->token.chars(), MAX_ARGNAMELEN);
119 comm->argnames[curarg][MAX_ARGNAMELEN-1] = 0;
120
121 // If this is an optional parameter, we need the default value.
122 if (curarg >= comm->numargs) {
123 r->MustNext ("=");
124 switch (type) {
125 case TYPE_INT:
126 case TYPE_BOOL:
127 r->MustNumber();
128 break;
129 case TYPE_STRING:
130 r->MustString();
131 break;
132 case TYPE_UNKNOWN:
133 case TYPE_VOID:
134 break;
135 }
136
137 comm->defvals[curarg] = r->token;
138 }
139
140 r->MustNext (")");
141 curarg++;
142 }
143
144 if (!g_CommDef)
145 g_CommDef = comm;
146
147 if (!curdef) {
148 curdef = comm;
149 } else {
150 curdef->next = comm;
151 curdef = comm;
152 }
153 numCommDefs++;
154 }
155
156 if (!numCommDefs)
157 r->ParserError ("no commands defined!\n");
158
159 r->CloseFile ();
160 delete r;
161 printf ("%d command definitions read.\n", numCommDefs);
162 }
163
164 // ============================================================================
165 // Finds a command by name
166 CommandDef* FindCommand (str fname) {
167 CommandDef* comm;
168 ITERATE_COMMANDS (comm) {
169 if (!fname.icompare (comm->name))
170 return comm;
171 }
172
173 return NULL;
174 }
175
176 // ============================================================================
177 // Returns the prototype of the command
178 str GetCommandPrototype (CommandDef* comm) {
179 str text;
180 text += GetTypeName (comm->returnvalue);
181 text += ' ';
182 text += comm->name;
183 text += '(';
184
185 bool hasOptionalArguments = false;
186 for (int i = 0; i < comm->maxargs; i++) {
187 if (i == comm->numargs) {
188 hasOptionalArguments = true;
189 text += '[';
190 }
191
192 if (i)
193 text += ", ";
194
195 text += GetTypeName (comm->argtypes[i]);
196 text += ' ';
197 text += comm->argnames[i];
198
199 if (i >= comm->numargs) {
200 text += '=';
201
202 bool isString = comm->argtypes[i] == TYPE_STRING;
203 if (isString) text += '"';
204
205 char defvalstring[8];
206 sprintf (defvalstring, "%d", comm->defvals[i]);
207 text += defvalstring;
208
209 if (isString) text += '"';
210 }
211 }
212
213 if (hasOptionalArguments)
214 text += ']';
215 text += ')';
216 return text;
217 }

mercurial