commands.cxx

changeset 10
2c0f76090372
parent 8
c8bfa7e6ae1b
child 11
f08abacb46c9
equal deleted inserted replaced
9:d279af9afd6d 10:2c0f76090372
39 */ 39 */
40 40
41 #define __COMMANDS_CXX__ 41 #define __COMMANDS_CXX__
42 #include <stdlib.h> 42 #include <stdlib.h>
43 #include <stdio.h> 43 #include <stdio.h>
44 #include <string.h>
44 #include "common.h" 45 #include "common.h"
45 #include "scriptreader.h" 46 #include "scriptreader.h"
46 #include "str.h" 47 #include "str.h"
47 #include "commands.h" 48 #include "commands.h"
48 49
49 CommandDef* g_CommDef; 50 CommandDef* g_CommDef;
50 51
51 void ReadCommands () { 52 void ReadCommands () {
52 ScriptReader* r = new ScriptReader ((char*)"commands.def"); 53 ScriptReader* r = new ScriptReader ((char*)"commands.def");
54 r->extdelimeters = true;
53 g_CommDef = NULL; 55 g_CommDef = NULL;
54 CommandDef* curdef = g_CommDef; 56 CommandDef* curdef = g_CommDef;
55 unsigned int numCommDefs = 0; 57 unsigned int numCommDefs = 0;
56 58
57 while (r->Next()) { 59 while (r->PeekNext().compare ("") != 0) {
58 CommandDef* comm = new CommandDef; 60 CommandDef* comm = new CommandDef;
61 comm->next = NULL;
59 62
60 // Any more than 4 is a warning, any less is an error. 63 // Number
61 unsigned int c = r->token.count (const_cast<char*> (":")); 64 r->MustNumber ();
62 if (c < 4) 65 comm->number = r->token;
63 r->ParserError ("not enough parameters: got %d, expected 4", c);
64 66
65 int n = 0; 67 r->MustNext (":");
66 str t = ""; 68
67 for (unsigned int u = 0; u < r->token.len(); u++) { 69 // Name
68 // If we're at the last character of the string, we need 70 r->MustNext ();
69 // to both add the character to t and check it. Thus, 71 comm->name = r->token;
70 // we do the addition, exceptionally, here. 72
71 if (u == r->token.len() - 1 && r->token[u] != ':') 73 r->MustNext (":");
72 t += r->token[u]; 74
75 // Return value
76 r->MustNext ();
77 comm->returnvalue = GetReturnTypeByString (r->token);
78 if (comm->returnvalue == -1)
79 r->ParserError ("bad return value type `%s`", r->token.chars());
80
81 r->MustNext (":");
82
83 // Num args
84 r->MustNumber ();
85 comm->numargs = r->token;
86
87 r->MustNext (":");
88
89 // Max args
90 r->MustNumber ();
91 comm->maxargs = r->token;
92
93 if (comm->maxargs > MAX_MAXARGS)
94 r->ParserError ("maxargs (%d) greater than %d!", comm->maxargs, MAX_MAXARGS);
95
96 // Argument types
97 int curarg = 0;
98 while (curarg < comm->maxargs) {
99 r->MustNext (":");
100 r->MustNext ();
73 101
74 if (r->token[u] == ':' || u == r->token.len() - 1) { 102 int type = GetReturnTypeByString (r->token);
75 int i = atoi (t.chars()); 103 if (type == -1)
76 switch (n) { 104 r->ParserError ("bad argument %d type `%s`", curarg, r->token.chars());
77 case 0: 105 if (type == RETURNVAL_VOID)
78 // Number 106 r->ParserError ("void is not a valid argument type!");
79 comm->number = i; 107 comm->argtypes[curarg] = type;
80 break; 108
81 case 1: 109 r->MustNext ("(");
82 // Name 110 r->MustNext ();
83 comm->name = t; 111
84 break; 112 // - 1 because of terminating null character
85 case 2: 113 if (r->token.len() > MAX_ARGNAMELEN - 1)
86 // Return value 114 r->ParserWarning ("argument name is too long (%d, max is %d)",
87 t.tolower(); 115 r->token.len(), MAX_ARGNAMELEN-1);
88 if (!t.compare ("int")) 116
89 comm->returnvalue = RETURNVAL_INT; 117 strncpy (comm->argnames[curarg], r->token.chars(), MAX_ARGNAMELEN);
90 else if (!t.compare ("str")) 118 comm->argnames[curarg][MAX_ARGNAMELEN-1] = 0;
91 comm->returnvalue = RETURNVAL_STRING; 119
92 else if (!t.compare ("void")) 120 // If this is an optional parameter, we need the default value.
93 comm->returnvalue = RETURNVAL_VOID; 121 if (curarg >= comm->numargs) {
94 else if (!t.compare ("bool")) 122 r->MustNext ("=");
95 comm->returnvalue = RETURNVAL_BOOLEAN; 123 switch (type) {
96 else 124 case RETURNVAL_INT: r->MustNumber(); break;
97 r->ParserError ("bad return value type `%s`", t.chars()); 125 case RETURNVAL_STRING: r->token = r->MustGetString(); break;
98 break; 126 case RETURNVAL_BOOLEAN: r->MustBool(); break;
99 case 3:
100 // Num args
101 comm->numargs = i;
102 break;
103 case 4:
104 // Max args
105 comm->maxargs = i;
106 break;
107 default:
108 r->ParserWarning ("too many parameters");
109 break;
110 } 127 }
111 128
112 n++; 129 comm->defvals[curarg] = r->token;
113 t = "";
114 } else {
115 t += r->token[u];
116 } 130 }
131
132 r->MustNext (")");
133 curarg++;
117 } 134 }
118
119 comm->next = NULL;
120 135
121 if (!g_CommDef) 136 if (!g_CommDef)
122 g_CommDef = comm; 137 g_CommDef = comm;
123 138
124 if (!curdef) { 139 if (!curdef) {
140 155
141 delete r; 156 delete r;
142 printf ("%d command definitions read.\n", numCommDefs); 157 printf ("%d command definitions read.\n", numCommDefs);
143 } 158 }
144 159
160 // urgh long name
161 int GetReturnTypeByString (str t) {
162 // "float" is for now just int.
163 // TODO: find out how BotScript floats work
164 // (are they real floats or fixed? how are they
165 // stored?) and add proper floating point support.
166 // NOTE: Also, shouldn't use RETURNVAL for data types..
167 t.tolower();
168 return !t.compare ("int") ? RETURNVAL_INT :
169 !t.compare ("float") ? RETURNVAL_INT :
170 !t.compare ("str") ? RETURNVAL_STRING :
171 !t.compare ("void") ? RETURNVAL_VOID :
172 !t.compare ("bool") ? RETURNVAL_BOOLEAN : -1;
173 }
174
175 // Inverse operation
176 str GetReturnTypeName (int r) {
177 switch (r) {
178 case RETURNVAL_INT: return "int"; break;
179 case RETURNVAL_STRING: return "str"; break;
180 case RETURNVAL_VOID: return "void"; break;
181 case RETURNVAL_BOOLEAN: return "bool"; break;
182 }
183
184 return "";
185 }
186
145 CommandDef* GetCommandByName (str a) { 187 CommandDef* GetCommandByName (str a) {
146 a.tolower (); 188 a.tolower ();
147 CommandDef* c; 189 CommandDef* c;
148 ITERATE_COMMANDS (c) { 190 ITERATE_COMMANDS (c) {
149 str b = c->name; 191 str b = c->name;

mercurial