blob: 9162ad647c414d04c40a6bf026ea30dc973c7158 [file] [log] [blame]
The Android Open Source Projectc24a8e62009-03-03 19:28:42 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <string.h>
19#include <stdio.h>
20#undef NDEBUG
21#include <assert.h>
22#include "ast.h"
23#include "execute.h"
24
25typedef struct {
26 int c;
27 const char **v;
28} StringList;
29
30static int execBooleanValue(ExecContext *ctx,
31 const AmBooleanValue *booleanValue, bool *result);
32static int execStringValue(ExecContext *ctx, const AmStringValue *stringValue,
33 const char **result);
34
35static int
36execBooleanExpression(ExecContext *ctx,
37 const AmBooleanExpression *booleanExpression, bool *result)
38{
39 int ret;
40 bool arg1, arg2;
41 bool unary;
42
43 assert(ctx != NULL);
44 assert(booleanExpression != NULL);
45 assert(result != NULL);
46 if (ctx == NULL || booleanExpression == NULL || result == NULL) {
47 return -__LINE__;
48 }
49
50 if (booleanExpression->op == AM_BOP_NOT) {
51 unary = true;
52 } else {
53 unary = false;
54 }
55
56 ret = execBooleanValue(ctx, booleanExpression->arg1, &arg1);
57 if (ret != 0) return ret;
58
59 if (!unary) {
60 ret = execBooleanValue(ctx, booleanExpression->arg2, &arg2);
61 if (ret != 0) return ret;
62 } else {
63 arg2 = false;
64 }
65
66 switch (booleanExpression->op) {
67 case AM_BOP_NOT:
68 *result = !arg1;
69 break;
70 case AM_BOP_EQ:
71 *result = (arg1 == arg2);
72 break;
73 case AM_BOP_NE:
74 *result = (arg1 != arg2);
75 break;
76 case AM_BOP_AND:
77 *result = (arg1 && arg2);
78 break;
79 case AM_BOP_OR:
80 *result = (arg1 || arg2);
81 break;
82 default:
83 return -__LINE__;
84 }
85
86 return 0;
87}
88
89static int
90execFunctionArguments(ExecContext *ctx,
91 const AmFunctionArguments *functionArguments, StringList *result)
92{
93 int ret;
94
95 assert(ctx != NULL);
96 assert(functionArguments != NULL);
97 assert(result != NULL);
98 if (ctx == NULL || functionArguments == NULL || result == NULL) {
99 return -__LINE__;
100 }
101
102 result->c = functionArguments->argc;
103 result->v = (const char **)malloc(result->c * sizeof(const char *));
104 if (result->v == NULL) {
105 result->c = 0;
106 return -__LINE__;
107 }
108
109 int i;
110 for (i = 0; i < functionArguments->argc; i++) {
111 ret = execStringValue(ctx, &functionArguments->argv[i], &result->v[i]);
112 if (ret != 0) {
113 result->c = 0;
114 free(result->v);
115 //TODO: free the individual args, if we're responsible for them.
116 result->v = NULL;
117 return ret;
118 }
119 }
120
121 return 0;
122}
123
124static int
125execFunctionCall(ExecContext *ctx, const AmFunctionCall *functionCall,
126 const char **result)
127{
128 int ret;
129
130 assert(ctx != NULL);
131 assert(functionCall != NULL);
132 assert(result != NULL);
133 if (ctx == NULL || functionCall == NULL || result == NULL) {
134 return -__LINE__;
135 }
136
137 StringList args;
138 ret = execFunctionArguments(ctx, functionCall->args, &args);
139 if (ret != 0) {
140 return ret;
141 }
142
143 ret = callFunction(functionCall->fn, args.c, args.v, (char **)result, NULL);
144 if (ret != 0) {
145 return ret;
146 }
147
148 //TODO: clean up args
149
150 return 0;
151}
152
153static int
154execStringValue(ExecContext *ctx, const AmStringValue *stringValue,
155 const char **result)
156{
157 int ret;
158
159 assert(ctx != NULL);
160 assert(stringValue != NULL);
161 assert(result != NULL);
162 if (ctx == NULL || stringValue == NULL || result == NULL) {
163 return -__LINE__;
164 }
165
166 switch (stringValue->type) {
167 case AM_SVAL_LITERAL:
168 *result = strdup(stringValue->u.literal);
169 break;
170 case AM_SVAL_FUNCTION:
171 ret = execFunctionCall(ctx, stringValue->u.function, result);
172 if (ret != 0) {
173 return ret;
174 }
175 break;
176 default:
177 return -__LINE__;
178 }
179
180 return 0;
181}
182
183static int
184execStringComparisonExpression(ExecContext *ctx,
185 const AmStringComparisonExpression *stringComparisonExpression,
186 bool *result)
187{
188 int ret;
189
190 assert(ctx != NULL);
191 assert(stringComparisonExpression != NULL);
192 assert(result != NULL);
193 if (ctx == NULL || stringComparisonExpression == NULL || result == NULL) {
194 return -__LINE__;
195 }
196
197 const char *arg1, *arg2;
198 ret = execStringValue(ctx, stringComparisonExpression->arg1, &arg1);
199 if (ret != 0) {
200 return ret;
201 }
202 ret = execStringValue(ctx, stringComparisonExpression->arg2, &arg2);
203 if (ret != 0) {
204 return ret;
205 }
206
207 int cmp = strcmp(arg1, arg2);
208
209 switch (stringComparisonExpression->op) {
210 case AM_SOP_LT:
211 *result = (cmp < 0);
212 break;
213 case AM_SOP_LE:
214 *result = (cmp <= 0);
215 break;
216 case AM_SOP_GT:
217 *result = (cmp > 0);
218 break;
219 case AM_SOP_GE:
220 *result = (cmp >= 0);
221 break;
222 case AM_SOP_EQ:
223 *result = (cmp == 0);
224 break;
225 case AM_SOP_NE:
226 *result = (cmp != 0);
227 break;
228 default:
229 return -__LINE__;
230 break;
231 }
232
233 return 0;
234}
235
236static int
237execBooleanValue(ExecContext *ctx, const AmBooleanValue *booleanValue,
238 bool *result)
239{
240 int ret;
241
242 assert(ctx != NULL);
243 assert(booleanValue != NULL);
244 assert(result != NULL);
245 if (ctx == NULL || booleanValue == NULL || result == NULL) {
246 return -__LINE__;
247 }
248
249 switch (booleanValue->type) {
250 case AM_BVAL_EXPRESSION:
251 ret = execBooleanExpression(ctx, &booleanValue->u.expression, result);
252 break;
253 case AM_BVAL_STRING_COMPARISON:
254 ret = execStringComparisonExpression(ctx,
255 &booleanValue->u.stringComparison, result);
256 break;
257 default:
258 ret = -__LINE__;
259 break;
260 }
261
262 return ret;
263}
264
265static int
266execCommand(ExecContext *ctx, const AmCommand *command)
267{
268 int ret;
269
270 assert(ctx != NULL);
271 assert(command != NULL);
272 if (ctx == NULL || command == NULL) {
273 return -__LINE__;
274 }
275
276 CommandArgumentType argType;
277 argType = getCommandArgumentType(command->cmd);
278 switch (argType) {
279 case CMD_ARGS_BOOLEAN:
280 {
281 bool bVal;
282 ret = execBooleanValue(ctx, command->args->u.b, &bVal);
283 if (ret == 0) {
284 ret = callBooleanCommand(command->cmd, bVal);
285 }
286 }
287 break;
288 case CMD_ARGS_WORDS:
289 {
290 AmWordList *words = command->args->u.w;
291 ret = callCommand(command->cmd, words->argc, words->argv);
292 }
293 break;
294 default:
295 ret = -__LINE__;
296 break;
297 }
298
299 return ret;
300}
301
302int
303execCommandList(ExecContext *ctx, const AmCommandList *commandList)
304{
305 int i;
306 for (i = 0; i < commandList->commandCount; i++) {
307 int ret = execCommand(ctx, commandList->commands[i]);
308 if (ret != 0) {
309 int line = commandList->commands[i]->line;
310 return line > 0 ? line : ret;
311 }
312 }
313
314 return 0;
315}