1 /*
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 */
16
17 #include "udm_config.h"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #include <errno.h>
24 #include <math.h>
25
26 #include "udm_common.h"
27 #include "udm_template.h"
28 #include "udm_server.h"
29 #include "udm_env.h"
30 #include "udm_conf.h"
31 #include "udm_db.h"
32 #include "udm_http.h"
33 #include "udm_parsehtml.h"
34 #include "udm_host.h"
35 #include "udm_contentencoding.h"
36 #include "udm_utils.h"
37 #include "udm_vars.h"
38 #include "udm_wild.h"
39 #include "udm_searchtool.h"
40 #include "udm_doc.h"
41 #include "udm_match.h"
42 #include "udm_sgml.h"
43 #include "udm_proto.h"
44 #include "udm_ctype.h"
45 #include "udm_lex.h"
46 #include "udm_prog.h"
47
48
49 /*
50 TODO:
51 - Add C++ keywords
52 - Add size_t
53 - Add sizeof
54 - Refactor cout, make << an operator in ostream.
55 - Change functions _argv() and _argc() to paramenters argv and argc
56 - More efficient data alignment: see UdmValueHandlerAlignedDataSize()
57 - Add a warning: "Suggest parentheses around &&" when mixing || and &&
58 - Restore a warning: see ExpressionHasEffect()
59 - Create function call arguments on stack rather than on heap.
60 - Allow function calls as arguments to other function calls.
61 - maximum execution time
62 - string comparison: if (x < "yyy")
63 - string concatenation with operator+
64
65 TODO-TEMPLATE:
66 - DetectClones: copy from msearch-test/include/search.htm
67 - doccount is 0 if there is only one search word
68 - qcache and "missing" do not work together
69 - mark stopwords (check origin)
70 - don't display suggestions (origin=6) in word statistics
71 - "Strict mode ... too few result" does not get displayed
72 if Strict found 0 results
73 - display query in browser charset, e.g. res.property_html("q") ?
74 - Remove DateFormat, implement strftime() instead
75 - HTML-aware string::left(). See UdmHtmlStrLeft().
76 - ExcerptSize and ExcerptPadding should probably be parameters to
77 property(), or to a new method.
78 */
79
80 #define UDM_CMDNAME(x) {UDM_CSTR_WITH_LEN(x)}
81 #define UDM_CMD1_VOID(name, exec) {UDM_CMDNAME(name), 1, exec}
82 #define UDM_CMD2_VOID(name, exec) {UDM_CMDNAME(name), 2, exec}
83 #define UDM_CMD1_IREG0(name, exec) {UDM_CMDNAME(name), 1, exec}
84
85
86 typedef enum
87 {
88 UDM_ASSIGNMENT_MUL,
89 UDM_ASSIGNMENT_DIV,
90 UDM_ASSIGNMENT_REM,
91 UDM_ASSIGNMENT_ADD,
92 UDM_ASSIGNMENT_SUB,
93 UDM_ASSIGNMENT_AND,
94 UDM_ASSIGNMENT_OR,
95 UDM_ASSIGNMENT_XOR,
96 UDM_ASSIGNMENT_LSHIFT,
97 UDM_ASSIGNMENT_RSHIFT
98 } udm_special_assignment_t;
99
100
101 typedef enum
102 {
103 UDM_UNARY_OPERATOR_PREFIX_INC,
104 UDM_UNARY_OPERATOR_PREFIX_DEC,
105 UDM_UNARY_OPERATOR_POSTFIX_INC,
106 UDM_UNARY_OPERATOR_POSTFIX_DEC
107 } udm_unary_operator_t;
108
109
110 typedef enum
111 {
112 UDM_EXPRESSION_IDENT,
113 UDM_EXPRESSION_CONST,
114 UDM_EXPRESSION_OBJECT, /* The value can be in a temp var */
115 UDM_EXPRESSION_COMPUTED /* The value is in registers */
116 } udm_expression_t;
117
118
119 typedef struct
120 {
121 UDM_PROG_VAR Var;
122 udm_expression_t type;
123 char buf[2];
124 udm_offset_and_length_t textdata_addr;
125 } UDM_PROG_PRIMARY_EXPRESSION;
126
127
128 typedef struct
129 {
130 UDM_PROG_PRIMARY_EXPRESSION args[UDM_PROG_MAXARG];
131 size_t nargs;
132 } UDM_PROG_FUNCTION_CALL_ARGUMENTS;
133
134
135 typedef struct
136 {
137 UDM_PROG_PRIMARY_EXPRESSION primary_expr;
138 UDM_PROG_FUNCTION_CALL_ARGUMENTS arglist;
139 } UDM_PROG_EXPRESSION;
140
141
142 static const UDM_VALUE_HANDLER *
UdmProgVarHandler(const UDM_PROG_VAR * Var)143 UdmProgVarHandler(const UDM_PROG_VAR *Var)
144 {
145 return Var->value.handler;
146 }
147
148
149 static void
UdmProgVarSetHandler(UDM_PROG_VAR * Var,const UDM_VALUE_HANDLER * handler)150 UdmProgVarSetHandler(UDM_PROG_VAR *Var, const UDM_VALUE_HANDLER *handler)
151 {
152 Var->value.handler= handler;
153 }
154
155
156 static const UDM_VALUE_HANDLER *
UdmPrimaryExprHandler(const UDM_PROG_PRIMARY_EXPRESSION * expr)157 UdmPrimaryExprHandler(const UDM_PROG_PRIMARY_EXPRESSION *expr)
158 {
159 return expr->Var.value.handler;
160 }
161
162
163 static const UDM_VALUE_HANDLER *
UdmExprHandler(const UDM_PROG_EXPRESSION * expr)164 UdmExprHandler(const UDM_PROG_EXPRESSION *expr)
165 {
166 return expr->primary_expr.Var.value.handler;
167 }
168
169
170 static void
UdmExprSetHandler(UDM_PROG_EXPRESSION * expr,const UDM_VALUE_HANDLER * handler)171 UdmExprSetHandler(UDM_PROG_EXPRESSION *expr,
172 const UDM_VALUE_HANDLER *handler)
173 {
174 expr->primary_expr.Var.value.handler= handler;
175 }
176
177
178 /************************************************************/
179
180 static udm_bool_t
UdmGenerateOp(UDM_PROG_COMPILER * compiler,udm_tmpl_cmd_t cmd)181 UdmGenerateOp(UDM_PROG_COMPILER *compiler, udm_tmpl_cmd_t cmd)
182 {
183 return UDM_OK == UdmProgAddArg0SimpleOp(compiler->prg, cmd);
184 }
185
186
187 static void
UdmProgItemArgInitFromLiteral(UDM_PROG_ARG * arg,const UDM_CONST_TOKEN * str,const udm_offset_and_length_t * textdata)188 UdmProgItemArgInitFromLiteral(UDM_PROG_ARG *arg,
189 const UDM_CONST_TOKEN *str,
190 const udm_offset_and_length_t *textdata)
191 {
192 arg->textdata_addr= *textdata;
193 }
194
195
196 static void
UdmProgItemArgInitFromLiteralAndHandler(UDM_PROG_ARG * arg,const UDM_PROG_PRIMARY_EXPRESSION * expr)197 UdmProgItemArgInitFromLiteralAndHandler(UDM_PROG_ARG *arg,
198 const UDM_PROG_PRIMARY_EXPRESSION *expr)
199 {
200 arg->handler= UdmPrimaryExprHandler(expr);
201 arg->textdata_addr= expr->textdata_addr;
202 }
203
204
205 static void
UdmProgItemArgInitFromVar(UDM_PROG_ARG * arg,const UDM_PROG_VAR * Var)206 UdmProgItemArgInitFromVar(UDM_PROG_ARG *arg, const UDM_PROG_VAR *Var)
207 {
208 arg->stack_offset= Var->value.stack_offset;
209 arg->handler= Var->value.handler;
210 }
211
212
213 static udm_rc_t
UdmProgAddJmpWithComment(UDM_PROG * prog,udm_tmpl_cmd_t cmdnum,int addr,const char * comment)214 UdmProgAddJmpWithComment(UDM_PROG *prog,
215 udm_tmpl_cmd_t cmdnum,
216 int addr, const char *comment)
217 {
218 UDM_PROG_ITEM i;
219 UdmProgItemInit(&i);
220 i.cmdnum= cmdnum;
221 i.comment= strdup(comment);
222 i.cmdarg.jump= addr;
223 return UdmProgAdd(prog, &i);
224 }
225
226
227 static udm_bool_t
UdmGenerateOpOffset(UDM_PROG_COMPILER * compiler,udm_tmpl_cmd_t cmdnum,size_t offset)228 UdmGenerateOpOffset(UDM_PROG_COMPILER *compiler,
229 udm_tmpl_cmd_t cmdnum,
230 size_t offset)
231 {
232 UDM_PROG_ITEM it;
233 UdmProgItemInit(&it);
234 it.cmdnum= cmdnum;
235 it.cmdarg.offset= offset;
236 return UDM_OK == UdmProgAdd(compiler->prg, &it);
237 }
238
239
240 /*********************************************************************/
241
242 static const UDM_PROG_ITEM *
UdmProgExecutorStateCurrentCmd(const UDM_PROG_EXECUTOR_STATE * p)243 UdmProgExecutorStateCurrentCmd(const UDM_PROG_EXECUTOR_STATE *p)
244 {
245 return p->curr;
246 }
247
248
249 static void *
UdmProgExecutorStateStackAddr0(UDM_PROG_EXECUTOR_STATE * st,const UDM_PROG_ITEM * it)250 UdmProgExecutorStateStackAddr0(UDM_PROG_EXECUTOR_STATE *st,
251 const UDM_PROG_ITEM *it)
252 {
253 return st->stack.Val.str + it->item_args.stack_offset;
254 }
255
256
257 static void
Template_mov_dregn_var0(UDM_PROG_EXECUTOR_STATE * T,size_t dregno)258 Template_mov_dregn_var0(UDM_PROG_EXECUTOR_STATE *T, size_t dregno)
259 {
260 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
261 void *Data= UdmProgExecutorStateStackAddr0(T, it);
262 it->item_args.handler->GetDouble(Data, &T->reg.d[dregno]);
263 }
264
265
266 static void
Template_mov_iregn_var0(UDM_PROG_EXECUTOR_STATE * T,size_t iregno)267 Template_mov_iregn_var0(UDM_PROG_EXECUTOR_STATE *T, size_t iregno)
268 {
269 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
270 void *Data= UdmProgExecutorStateStackAddr0(T, it);
271 it->item_args.handler->GetInt(Data, &T->reg.i[iregno]);
272 }
273
274
275 /* Variable initialization */
276
277 /*TODO34: destructor is never called for declared variables!!! */
278 static void
Template_construct_var(UDM_PROG_EXECUTOR_STATE * T)279 Template_construct_var(UDM_PROG_EXECUTOR_STATE *T)
280 {
281 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
282 const UDM_VALUE_HANDLER *ha= it->item_args.handler;
283 void *Data= UdmProgExecutorStateStackAddr0(T, it);
284 UDM_ASSERT(it->item_args.stack_offset + ha->DataSize() < T->stack.size_alloced);
285 if (UDM_OK != ha->Constructor(Data, NULL, 0))
286 T->fatal_error= UDM_TRUE;
287 }
288
289
290 static void
Template_set_var_from_ireg0(UDM_PROG_EXECUTOR_STATE * T)291 Template_set_var_from_ireg0(UDM_PROG_EXECUTOR_STATE *T)
292 {
293 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
294 void *Data= UdmProgExecutorStateStackAddr0(T, it);
295 const UDM_VALUE_HANDLER *ha= it->item_args.handler;
296 ha->SetInt(Data, T->reg.i[0]);
297 }
298
299
300 static void
Template_set_var_from_dreg0(UDM_PROG_EXECUTOR_STATE * T)301 Template_set_var_from_dreg0(UDM_PROG_EXECUTOR_STATE *T)
302 {
303 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
304 void *Data= UdmProgExecutorStateStackAddr0(T, it);
305 const UDM_VALUE_HANDLER *ha= it->item_args.handler;
306 ha->SetDouble(Data, T->reg.d[0]);
307 }
308
309
310 static void
Template_set_var_from_text0(UDM_PROG_EXECUTOR_STATE * T)311 Template_set_var_from_text0(UDM_PROG_EXECUTOR_STATE *T)
312 {
313 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
314 void *Data= UdmProgExecutorStateStackAddr0(T, it);
315 const UDM_VALUE_HANDLER *ha= it->item_args.handler;
316 ha->SetStrn(Data,
317 T->prog->textdata.Val.str + it->item_args.textdata_addr.offset,
318 it->item_args.textdata_addr.length);
319 }
320
321
322 static void
Template_set_var_from_cs0_z0(UDM_PROG_EXECUTOR_STATE * T)323 Template_set_var_from_cs0_z0(UDM_PROG_EXECUTOR_STATE *T)
324 {
325 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
326 void *Dst= UdmProgExecutorStateStackAddr0(T, it);
327 if (UDM_OK != it->item_args.handler->SetStrn(Dst, T->reg.cs0, T->reg.z0))
328 T->fatal_error= UDM_TRUE;
329 }
330
331
332 static void
Template_get_var_to_cs0_z0(UDM_PROG_EXECUTOR_STATE * T)333 Template_get_var_to_cs0_z0(UDM_PROG_EXECUTOR_STATE *T)
334 {
335 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
336 void *Src= UdmProgExecutorStateStackAddr0(T, it);
337 UDM_CONST_STR str;
338 it->item_args.handler->GetConstStr(Src, &str);
339 T->reg.cs0= str.str;
340 T->reg.z0= str.length;
341 }
342
343
344 static void
Template_get_textdata_to_cs0_z0(UDM_PROG_EXECUTOR_STATE * T)345 Template_get_textdata_to_cs0_z0(UDM_PROG_EXECUTOR_STATE *T)
346 {
347 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
348 T->reg.cs0= T->prog->textdata.Val.str + it->item_args.textdata_addr.offset;
349 T->reg.z0= it->item_args.textdata_addr.length;
350 }
351
352
353 static void
Template_destruct_var(UDM_PROG_EXECUTOR_STATE * T)354 Template_destruct_var(UDM_PROG_EXECUTOR_STATE *T)
355 {
356 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
357 void *Data= UdmProgExecutorStateStackAddr0(T, it);
358 it->item_args.handler->Destructor(Data);
359 }
360
361
362 static void
Template_mov_ireg0_var0(UDM_PROG_EXECUTOR_STATE * T)363 Template_mov_ireg0_var0(UDM_PROG_EXECUTOR_STATE *T)
364 {
365 Template_mov_iregn_var0(T, 0);
366 }
367
368
369 static void
Template_mov_ireg1_var0(UDM_PROG_EXECUTOR_STATE * T)370 Template_mov_ireg1_var0(UDM_PROG_EXECUTOR_STATE *T)
371 {
372 Template_mov_iregn_var0(T, 1);
373 }
374
375
376 static void
Template_mov_dreg0_var0(UDM_PROG_EXECUTOR_STATE * T)377 Template_mov_dreg0_var0(UDM_PROG_EXECUTOR_STATE *T)
378 {
379 Template_mov_dregn_var0(T, 0);
380 }
381
382
383 static void
Template_mov_dreg1_var0(UDM_PROG_EXECUTOR_STATE * T)384 Template_mov_dreg1_var0(UDM_PROG_EXECUTOR_STATE *T)
385 {
386 Template_mov_dregn_var0(T, 1);
387 }
388
389
390 #define UDM_CMDNAME(x) {UDM_CSTR_WITH_LEN(x)}
391
392
393 #define UDM_CMD1_VOID(name, exec) {UDM_CMDNAME(name), 1, exec}
394 #define UDM_CMD2_VOID(name, exec) {UDM_CMDNAME(name), 2, exec}
395 #define UDM_CMD3_VOID(name, exec) {UDM_CMDNAME(name), 3, exec}
396
397 #define UDM_CMD0_IREG0(name, exec) {UDM_CMDNAME(name), 0, exec}
398 #define UDM_CMD0_IREG1(name, exec) {UDM_CMDNAME(name), 0, exec}
399 #define UDM_CMD0_DREG0(name, exec) {UDM_CMDNAME(name), 0, exec}
400 #define UDM_CMD0_DREG1(name, exec) {UDM_CMDNAME(name), 0, exec}
401
402 #define UDM_CMD1_IREG0(name, exec) {UDM_CMDNAME(name), 1, exec}
403 #define UDM_CMD1_IREG1(name, exec) {UDM_CMDNAME(name), 1, exec}
404 #define UDM_CMD1_DREG0(name, exec) {UDM_CMDNAME(name), 1, exec}
405 #define UDM_CMD1_DREG1(name, exec) {UDM_CMDNAME(name), 1, exec}
406
407 #define UDM_CMD2_IREG0(name, exec) {UDM_CMDNAME(name), 2, exec}
408
409
410
411 /* Registers and variables */
412 static UDM_PROG_CMD
413 udm_tmpl_mov_ireg0_var0= UDM_CMD1_IREG0("GetInt i0 v0", Template_mov_ireg0_var0),
414 udm_tmpl_mov_ireg1_var0= UDM_CMD1_IREG1("GetInt i1 v0", Template_mov_ireg1_var0);
415
416 static UDM_PROG_CMD
417 udm_tmpl_mov_dreg0_var0= UDM_CMD1_DREG0("GetDbl d0 v0", Template_mov_dreg0_var0),
418 udm_tmpl_mov_dreg1_var0= UDM_CMD1_DREG0("GetDbl d1 v0", Template_mov_dreg1_var0);
419
420 static UDM_PROG_CMD
421 udm_tmpl_get_var_to_cs0_z0= UDM_CMD1_DREG0("GetStr cs0/z0 v0", Template_get_var_to_cs0_z0);
422
423 static UDM_PROG_CMD
424 udm_tmpl_textdata_to_cs0_z0= UDM_CMD1_DREG0("GetStr cs0/z0 textdata", Template_get_textdata_to_cs0_z0);
425
426 /* Registers and values */
427
428 static UDM_PROG_CMD
429 udm_tmpl_set_var_from_text0= UDM_CMD2_VOID("SetStr v0 text0", Template_set_var_from_text0),
430 udm_tmpl_set_var_from_ireg0= UDM_CMD2_VOID("SetInt v0 i0", Template_set_var_from_ireg0),
431 udm_tmpl_set_var_from_dreg0= UDM_CMD2_VOID("SetDbl v0 d0", Template_set_var_from_dreg0),
432 udm_tmpl_set_var_from_cs0_z0= UDM_CMD2_VOID("SetStr v0 cs0/z0", Template_set_var_from_cs0_z0),
433 udm_tmpl_construct_var= UDM_CMD2_VOID("construct", Template_construct_var),
434 udm_tmpl_destruct_var= UDM_CMD2_VOID("destruct", Template_destruct_var);
435
436 /*********************************************************************/
437
438 static void
Exec_method_make_arg(UDM_PROG_EXECUTOR_STATE * T,size_t argno)439 Exec_method_make_arg(UDM_PROG_EXECUTOR_STATE *T, size_t argno)
440 {
441 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
442 const UDM_VALUE_HANDLER *handler= it->item_args.handler;
443 T->vreg[argno].Data= UdmMalloc(handler->DataSize());
444 handler->Constructor(T->vreg[argno].Data, NULL, 0);
445 handler->SetStrn(T->vreg[argno].Data,
446 T->prog->textdata.Val.str + it->item_args.textdata_addr.offset,
447 it->item_args.textdata_addr.length);
448 }
449
450
451 static void
Exec_method_free_arg(UDM_PROG_EXECUTOR_STATE * T,size_t argno)452 Exec_method_free_arg(UDM_PROG_EXECUTOR_STATE *T, size_t argno)
453 {
454 const UDM_PROG_ITEM *it= UdmProgExecutorStateCurrentCmd(T);
455 const UDM_VALUE_HANDLER *handler= it->item_args.handler;
456 handler->Destructor(T->vreg[argno].Data);
457 UdmFree(T->vreg[argno].Data);
458 T->vreg[argno].Data= NULL;
459 }
460
461 /**** arg0 ***/
462
463 static void
Exec_method_make_arg0(UDM_PROG_EXECUTOR_STATE * T)464 Exec_method_make_arg0(UDM_PROG_EXECUTOR_STATE *T)
465 {
466 Exec_method_make_arg(T, 0);
467 }
468
469 static void
Exec_method_free_arg0(UDM_PROG_EXECUTOR_STATE * T)470 Exec_method_free_arg0(UDM_PROG_EXECUTOR_STATE *T)
471 {
472 Exec_method_free_arg(T, 0);
473 }
474
475
476 static void
Exec_method_clear_arg0(UDM_PROG_EXECUTOR_STATE * T)477 Exec_method_clear_arg0(UDM_PROG_EXECUTOR_STATE *T)
478 {
479 T->vreg[0].Data= NULL;
480 }
481
482
483 /*** arg1 ***/
484
485 static void
Exec_method_make_arg1(UDM_PROG_EXECUTOR_STATE * T)486 Exec_method_make_arg1(UDM_PROG_EXECUTOR_STATE *T)
487 {
488 Exec_method_make_arg(T, 1);
489 }
490
491 static void
Exec_method_free_arg1(UDM_PROG_EXECUTOR_STATE * T)492 Exec_method_free_arg1(UDM_PROG_EXECUTOR_STATE *T)
493 {
494 Exec_method_free_arg(T, 1);
495 }
496
497 static void
Exec_method_clear_arg1(UDM_PROG_EXECUTOR_STATE * T)498 Exec_method_clear_arg1(UDM_PROG_EXECUTOR_STATE *T)
499 {
500 T->vreg[1].Data= NULL;
501 }
502
503
504 /*** arg2 ***/
505
506 static void
Exec_method_make_arg2(UDM_PROG_EXECUTOR_STATE * T)507 Exec_method_make_arg2(UDM_PROG_EXECUTOR_STATE *T)
508 {
509 Exec_method_make_arg(T, 2);
510 }
511
512 static void
Exec_method_free_arg2(UDM_PROG_EXECUTOR_STATE * T)513 Exec_method_free_arg2(UDM_PROG_EXECUTOR_STATE *T)
514 {
515 Exec_method_free_arg(T, 2);
516 }
517
518 static void
Exec_method_clear_arg2(UDM_PROG_EXECUTOR_STATE * T)519 Exec_method_clear_arg2(UDM_PROG_EXECUTOR_STATE *T)
520 {
521 T->vreg[2].Data= NULL;
522 }
523
524 /*** arg3 ***/
525
526 static void
Exec_method_make_arg3(UDM_PROG_EXECUTOR_STATE * T)527 Exec_method_make_arg3(UDM_PROG_EXECUTOR_STATE *T)
528 {
529 Exec_method_make_arg(T, 3);
530 }
531
532 static void
Exec_method_free_arg3(UDM_PROG_EXECUTOR_STATE * T)533 Exec_method_free_arg3(UDM_PROG_EXECUTOR_STATE *T)
534 {
535 Exec_method_free_arg(T, 3);
536 }
537
538 static void
Exec_method_clear_arg3(UDM_PROG_EXECUTOR_STATE * T)539 Exec_method_clear_arg3(UDM_PROG_EXECUTOR_STATE *T)
540 {
541 T->vreg[3].Data= NULL;
542 }
543
544 /*** arg4 ***/
545
546 static void
Exec_method_make_arg4(UDM_PROG_EXECUTOR_STATE * T)547 Exec_method_make_arg4(UDM_PROG_EXECUTOR_STATE *T)
548 {
549 Exec_method_make_arg(T, 4);
550 }
551
552 static void
Exec_method_free_arg4(UDM_PROG_EXECUTOR_STATE * T)553 Exec_method_free_arg4(UDM_PROG_EXECUTOR_STATE *T)
554 {
555 Exec_method_free_arg(T, 4);
556 }
557
558 static void
Exec_method_clear_arg4(UDM_PROG_EXECUTOR_STATE * T)559 Exec_method_clear_arg4(UDM_PROG_EXECUTOR_STATE *T)
560 {
561 T->vreg[4].Data= NULL;
562 }
563
564 /****/
565
566 static UDM_PROG_CMD
567 udm_method_clear_arg0= UDM_CMD1_VOID("mov v0,0", Exec_method_clear_arg0),
568 udm_method_clear_arg1= UDM_CMD1_VOID("mov v1,0", Exec_method_clear_arg1),
569 udm_method_clear_arg2= UDM_CMD1_VOID("mov v2,0", Exec_method_clear_arg2),
570 udm_method_clear_arg3= UDM_CMD1_VOID("mov v3,0", Exec_method_clear_arg3),
571 udm_method_clear_arg4= UDM_CMD1_VOID("mov v4,0", Exec_method_clear_arg4);
572
573
574 static UDM_PROG_CMD
575 udm_method_make_arg0= UDM_CMD1_VOID("MAKE-ARG0", Exec_method_make_arg0),
576 udm_method_free_arg0= UDM_CMD1_VOID("FREE-ARG0", Exec_method_free_arg0);
577
578
579 static UDM_PROG_CMD
580 udm_method_make_arg1= UDM_CMD1_VOID("MAKE-ARG1", Exec_method_make_arg1),
581 udm_method_free_arg1= UDM_CMD1_VOID("FREE-ARG1", Exec_method_free_arg1);
582
583
584 static UDM_PROG_CMD
585 udm_method_make_arg2= UDM_CMD1_VOID("MAKE-ARG2", Exec_method_make_arg2),
586 udm_method_free_arg2= UDM_CMD1_VOID("FREE-ARG2", Exec_method_free_arg2);
587
588
589 static UDM_PROG_CMD
590 udm_method_make_arg3= UDM_CMD1_VOID("MAKE-ARG3", Exec_method_make_arg3),
591 udm_method_free_arg3= UDM_CMD1_VOID("FREE-ARG3", Exec_method_free_arg3);
592
593
594 static UDM_PROG_CMD
595 udm_method_make_arg4= UDM_CMD1_VOID("MAKE-ARG4", Exec_method_make_arg4),
596 udm_method_free_arg4= UDM_CMD1_VOID("FREE-ARG4", Exec_method_free_arg4);
597
598
599 /*********************************************************************/
600
601 static void
Template_cout_ireg0(UDM_PROG_EXECUTOR_STATE * T)602 Template_cout_ireg0(UDM_PROG_EXECUTOR_STATE *T)
603 {
604 fprintf(T->globals.stdout, "%d", T->reg.i[0]);
605 }
606
607
608 static void
Template_cout_ireg0_char(UDM_PROG_EXECUTOR_STATE * T)609 Template_cout_ireg0_char(UDM_PROG_EXECUTOR_STATE *T)
610 {
611 char ch= T->reg.i[0];
612 (void) fwrite(&ch, 1, 1, T->globals.stdout);
613
614 }
615
616
617 static void
Template_cout_dreg0(UDM_PROG_EXECUTOR_STATE * T)618 Template_cout_dreg0(UDM_PROG_EXECUTOR_STATE *T)
619 {
620 fprintf(T->globals.stdout, "%f", T->reg.d[0]);
621 }
622
623
624 static void
Template_cout_cs0_z0(UDM_PROG_EXECUTOR_STATE * T)625 Template_cout_cs0_z0(UDM_PROG_EXECUTOR_STATE *T)
626 {
627 fwrite(T->reg.cs0, T->reg.z0, 1, T->globals.stdout);
628 }
629
630
631 /* New echo functions */
632 static UDM_PROG_CMD
633 udm_tmpl_cout_ireg0= UDM_CMD1_VOID("cout i0", Template_cout_ireg0),
634 udm_tmpl_cout_ireg0_char= UDM_CMD1_VOID("cout i0 (char)", Template_cout_ireg0_char),
635 udm_tmpl_cout_dreg0= UDM_CMD1_VOID("cout d0", Template_cout_dreg0),
636 udm_tmpl_cout_cs0_z0= UDM_CMD1_VOID("cout cs0/z0", Template_cout_cs0_z0);
637
638
639 /*********************************************************************/
640
641
642 static void
UdmPIScanLexToken(UDM_LEX_SCANNER * p,UDM_LEX_TOKEN * a)643 UdmPIScanLexToken(UDM_LEX_SCANNER *p, UDM_LEX_TOKEN *a)
644 {
645 beg:
646 UdmLexScannerSkipSpaces(p);
647 a->token.str= UdmLexScannerCur(p);
648 if (UdmLexScannerEOF(p))
649 {
650 a->type= UDM_LEX_EOF;
651 a->token.end= a->token.str;
652 }
653 else if (!UdmLexScannerScanCComment(p, a))
654 {
655 goto beg;
656 }
657 else if (!UdmLexScannerScanCOperator(p, a))
658 {
659 }
660 else if (!UdmLexScannerScanIdentifier(p, a))
661 {
662 }
663 else if (!UdmLexScannerScanPunctuation(p, a))
664 {
665 }
666 else if (!UdmLexScannerScanEscapedString(p, a))
667 {
668 }
669 else if (!UdmLexScannerScanChar(p, a))
670 {
671 }
672 else if (!UdmLexScannerScanUnsignedNumber(p, a))
673 {
674 }
675 else
676 {
677 a->type= UDM_LEX_UNKNOWN;
678 }
679
680 #if 0
681 fprintf(stderr, "LEX=%s='%.*s'\n",
682 UdmLex2str(a->type), (int) (a->token.end-a->token.str), a->token.str);
683 #endif
684 }
685
686
687 static void
UdmPIParserInit(UDM_PROG_COMPILER * compiler,const char * src,size_t length)688 UdmPIParserInit(UDM_PROG_COMPILER *compiler, const char *src, size_t length)
689 {
690 UdmLexScannerInit(&compiler->scanner, src, length);
691 UdmProgVarListListInit(&compiler->Vars2);
692 compiler->errstr[0]= '\0';
693 compiler->current_loop_continue= 0;
694 }
695
696
697 static void
UdmPIParserFree(UDM_PROG_COMPILER * compiler)698 UdmPIParserFree(UDM_PROG_COMPILER *compiler)
699 {
700 UdmProgVarListListFree(&compiler->Vars2);
701 }
702
703
704 static size_t
UdmProgCompilerLineno(UDM_PROG_COMPILER * compiler)705 UdmProgCompilerLineno(UDM_PROG_COMPILER *compiler)
706 {
707 const char *s;
708 size_t lineno= compiler->lineno;
709 for (s= compiler->start; s < compiler->scanner.token.token.str; s++)
710 {
711 if (*s == '\n')
712 lineno++;
713 }
714 return lineno + 1;
715 }
716
717
718 static size_t
UdmProgCompilerNextVarStackOffset(UDM_PROG_COMPILER * compiler)719 UdmProgCompilerNextVarStackOffset(UDM_PROG_COMPILER *compiler)
720 {
721 UDM_PROG_VARLIST *Vars= &compiler->Vars2.Item[compiler->Vars2.nitems - 1];
722 UDM_ASSERT(compiler->Vars2.nitems);
723 return Vars->next_stack_offset;
724 }
725
726
727 static udm_rc_t
UdmProgCompilerNextVarStackOffsetIncrement(UDM_PROG_COMPILER * compiler,size_t inc)728 UdmProgCompilerNextVarStackOffsetIncrement(UDM_PROG_COMPILER *compiler,
729 size_t inc)
730 {
731 UDM_PROG_VARLIST *Vars= &compiler->Vars2.Item[compiler->Vars2.nitems - 1];
732 Vars->next_stack_offset+= inc;
733 return UDM_OK;
734 }
735
736
737 static udm_bool_t
UdmProgCompilerEnterBlock(UDM_PROG_COMPILER * compiler)738 UdmProgCompilerEnterBlock(UDM_PROG_COMPILER *compiler)
739 {
740 UDM_PROG_VARLIST tmp;
741 UdmProgVarListInit(&tmp);
742 tmp.next_stack_offset= compiler->Vars2.nitems ?
743 UdmProgCompilerNextVarStackOffset(compiler) : 0;
744 if (UDM_OK != UdmProgVarListListAdd(&compiler->Vars2, &tmp))
745 return UDM_FALSE;
746 return UDM_TRUE;
747 }
748
749
750 /**
751 Generate destructors for all variables in the list,
752 in reverse creation order.
753 */
754 static udm_bool_t
UdmProgCompilerGenerateVarListDestructors(UDM_PROG_COMPILER * compiler,UDM_PROG_VARLIST * Vars)755 UdmProgCompilerGenerateVarListDestructors(UDM_PROG_COMPILER *compiler,
756 UDM_PROG_VARLIST *Vars)
757 {
758 size_t i;
759 for (i= 0; i < Vars->nitems; i++)
760 {
761 const UDM_PROG_VAR2 *Var= &Vars->Item[Vars->nitems - i - 1];
762 UDM_PROG_ITEM it;
763 UdmProgItemInit(&it);
764 it.item_args.stack_offset= Var->value.stack_offset;
765 it.item_args.handler= Var->value.handler;
766 it.cmd= &udm_tmpl_destruct_var;
767 if (compiler->generate_debug_info)
768 it.comment= UdmStrdup(Var->name);
769 if (UDM_OK != UdmProgAdd(compiler->prg, &it))
770 return UDM_FALSE;
771 }
772 return UDM_TRUE;
773 }
774
775
776 static udm_bool_t
UdmProgCompilerGenerateVarListListDestructors(UDM_PROG_COMPILER * compiler)777 UdmProgCompilerGenerateVarListListDestructors(UDM_PROG_COMPILER *compiler)
778 {
779 size_t i;
780 /*
781 Generate destructors for all variables on all levels,
782 to avoid memory leaks.
783 */
784 for (i= compiler->Vars2.nitems; i > 0; i--)
785 {
786 UDM_PROG_VARLIST *Vars= &compiler->Vars2.Item[i - 1];
787 if (!UdmProgCompilerGenerateVarListDestructors(compiler, Vars))
788 return UDM_FALSE;
789 }
790 return UDM_TRUE;
791 }
792
793
794 static udm_bool_t
UdmProgCompilerLeaveBlock(UDM_PROG_COMPILER * compiler)795 UdmProgCompilerLeaveBlock(UDM_PROG_COMPILER *compiler)
796 {
797 UDM_PROG_VARLIST *Vars= &compiler->Vars2.Item[compiler->Vars2.nitems - 1];
798 UDM_ASSERT(compiler->Vars2.nitems);
799 if (!UdmProgCompilerGenerateVarListDestructors(compiler, Vars))
800 return UDM_FALSE;
801 UdmProgVarListFree(Vars);
802 compiler->Vars2.nitems--;
803 return UDM_TRUE;
804 }
805
806
807 static udm_bool_t
UdmProgCompilerRedeclarationError(UDM_PROG_COMPILER * compiler,const char * name)808 UdmProgCompilerRedeclarationError(UDM_PROG_COMPILER *compiler,
809 const char *name)
810 {
811 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
812 "%d: ERROR: Redeclaration of '%s'",
813 (int) UdmProgCompilerLineno(compiler), name);
814 return UDM_FALSE;
815 }
816
817
818 typedef struct
819 {
820 udm_unary_operator_t op;
821 UDM_VALUE_HANDLER *ha;
822 } UDM_UNARY_OPERATOR;
823
824
825 static UDM_UNARY_OPERATOR unary_operators[]=
826 {
827 {UDM_UNARY_OPERATOR_PREFIX_INC, &UdmValueHandlerInt},
828 {UDM_UNARY_OPERATOR_PREFIX_DEC, &UdmValueHandlerInt},
829 {UDM_UNARY_OPERATOR_POSTFIX_INC, &UdmValueHandlerInt},
830 {UDM_UNARY_OPERATOR_POSTFIX_DEC, &UdmValueHandlerInt},
831
832 {UDM_UNARY_OPERATOR_PREFIX_INC, &UdmValueHandlerChar},
833 {UDM_UNARY_OPERATOR_PREFIX_DEC, &UdmValueHandlerChar},
834 {UDM_UNARY_OPERATOR_POSTFIX_INC, &UdmValueHandlerChar},
835 {UDM_UNARY_OPERATOR_POSTFIX_DEC, &UdmValueHandlerChar},
836
837 {UDM_UNARY_OPERATOR_PREFIX_INC, &UdmValueHandlerDouble},
838 {UDM_UNARY_OPERATOR_PREFIX_DEC, &UdmValueHandlerDouble},
839 {UDM_UNARY_OPERATOR_POSTFIX_INC, &UdmValueHandlerDouble},
840 {UDM_UNARY_OPERATOR_POSTFIX_DEC, &UdmValueHandlerDouble},
841
842 {UDM_UNARY_OPERATOR_PREFIX_INC, NULL}
843 };
844
845
846 static const UDM_UNARY_OPERATOR *
UdmUnaryOperatorFind(const UDM_UNARY_OPERATOR * ops,udm_unary_operator_t op,const UDM_VALUE_HANDLER * h1)847 UdmUnaryOperatorFind(const UDM_UNARY_OPERATOR *ops,
848 udm_unary_operator_t op,
849 const UDM_VALUE_HANDLER *h1)
850 {
851 for ( ; ops->ha; ops++)
852 {
853 if (ops->ha == h1 && ops->op == op)
854 return ops;
855 }
856 return NULL;
857 }
858
859
860 static const UDM_UNARY_OPERATOR *
UdmUnaryOperatorFindWithError(UDM_PROG_COMPILER * compiler,const UDM_UNARY_OPERATOR * ops,udm_unary_operator_t op,const UDM_VALUE_HANDLER * ha,const char * name)861 UdmUnaryOperatorFindWithError(UDM_PROG_COMPILER *compiler,
862 const UDM_UNARY_OPERATOR *ops,
863 udm_unary_operator_t op,
864 const UDM_VALUE_HANDLER *ha,
865 const char *name)
866 {
867 const UDM_UNARY_OPERATOR *res;
868 if ((res= UdmUnaryOperatorFind(ops, op, ha)))
869 return res;
870 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
871 "%d: no operator '%s' declared for '%s'",
872 (int) UdmProgCompilerLineno(compiler),
873 name, ha->type_name);
874 return NULL;
875 }
876
877
878 typedef struct
879 {
880 const UDM_VALUE_HANDLER *h1;
881 const UDM_VALUE_HANDLER *h2;
882 const UDM_VALUE_HANDLER *res; /* Aggregate type for h1 and h2 */
883 } UDM_DYADIC_OPERATOR;
884
885
886 static UDM_DYADIC_OPERATOR assignment_operators[]=
887 {
888 {&UdmValueHandlerDouble, &UdmValueHandlerDouble, NULL},
889 {&UdmValueHandlerDouble, &UdmValueHandlerInt, NULL},
890 {&UdmValueHandlerDouble, &UdmValueHandlerChar, NULL},
891 {&UdmValueHandlerInt, &UdmValueHandlerDouble, NULL},
892 {&UdmValueHandlerInt, &UdmValueHandlerInt, NULL},
893 {&UdmValueHandlerInt, &UdmValueHandlerChar, NULL},
894 {&UdmValueHandlerChar, &UdmValueHandlerDouble, NULL},
895 {&UdmValueHandlerChar, &UdmValueHandlerInt, NULL},
896 {&UdmValueHandlerChar, &UdmValueHandlerChar, NULL},
897 {&UdmValueHandlerSimple, &UdmValueHandlerSimple, NULL},
898 {&UdmValueHandlerQueryWord, &UdmValueHandlerQueryWord, NULL},
899 {NULL, NULL}
900 };
901
902
903 static const UDM_DYADIC_OPERATOR *
UdmDyadicOperatorFind(UDM_DYADIC_OPERATOR * ops,const UDM_VALUE_HANDLER * h1,const UDM_VALUE_HANDLER * h2)904 UdmDyadicOperatorFind(UDM_DYADIC_OPERATOR *ops,
905 const UDM_VALUE_HANDLER *h1,
906 const UDM_VALUE_HANDLER *h2)
907 {
908 const UDM_DYADIC_OPERATOR *op;
909 for (op= ops; op->h1; op++)
910 {
911 if (op->h1 == h1 && op->h2 == h2)
912 return op;
913 }
914 return NULL;
915 }
916
917
918 static udm_bool_t
UdmCompilerErrorInvalidOperands(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * h1,const UDM_VALUE_HANDLER * h2,const char * name)919 UdmCompilerErrorInvalidOperands(UDM_PROG_COMPILER *compiler,
920 const UDM_VALUE_HANDLER *h1,
921 const UDM_VALUE_HANDLER *h2,
922 const char *name)
923 {
924 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
925 "%d: Invalid operands of types for '%s' and '%s' to operator '%s'",
926 (int) UdmProgCompilerLineno(compiler),
927 h1->type_name, h2->type_name, name);
928 return UDM_FALSE;
929 }
930
931
932 static const UDM_DYADIC_OPERATOR *
UdmDyadicOperatorFindWithError(UDM_PROG_COMPILER * compiler,UDM_DYADIC_OPERATOR * ops,const UDM_VALUE_HANDLER * h1,const UDM_VALUE_HANDLER * h2,const char * name)933 UdmDyadicOperatorFindWithError(UDM_PROG_COMPILER *compiler,
934 UDM_DYADIC_OPERATOR *ops,
935 const UDM_VALUE_HANDLER *h1,
936 const UDM_VALUE_HANDLER *h2,
937 const char *name)
938 {
939 const UDM_DYADIC_OPERATOR *op;
940 if ((op= UdmDyadicOperatorFind(ops, h1, h2)))
941 return op;
942 UdmCompilerErrorInvalidOperands(compiler, h1, h2, name);
943 return NULL;
944 }
945
946
947 static udm_bool_t
UdmProgCompilerError(const UDM_PROG_COMPILER * compiler)948 UdmProgCompilerError(const UDM_PROG_COMPILER *compiler)
949 {
950 return compiler->errstr[0] != '\0';
951 }
952
953
954 static void
UdmProgCompilerScan(UDM_PROG_COMPILER * compiler)955 UdmProgCompilerScan(UDM_PROG_COMPILER *compiler)
956 {
957 UdmPIScanLexToken(&compiler->scanner, &compiler->scanner.token);
958 }
959
960
961 static udm_lex_t
UdmProgCompilerLastTokenType(const UDM_PROG_COMPILER * compiler)962 UdmProgCompilerLastTokenType(const UDM_PROG_COMPILER *compiler)
963 {
964 return compiler->scanner.token.type;
965 }
966
967
968 static udm_bool_t
ParseTerm(UDM_PROG_COMPILER * compiler,udm_lex_t term)969 ParseTerm(UDM_PROG_COMPILER *compiler, udm_lex_t term)
970 {
971 if (UdmProgCompilerError(compiler))
972 return UDM_FALSE;
973 if (UdmProgCompilerLastTokenType(compiler) != term)
974 return UDM_FALSE;
975 UdmProgCompilerScan(compiler);
976 return UDM_TRUE;
977 }
978
979
980 static udm_bool_t
ParseTermOrError(UDM_PROG_COMPILER * compiler,udm_lex_t term)981 ParseTermOrError(UDM_PROG_COMPILER *compiler, udm_lex_t term)
982 {
983 if (UdmProgCompilerError(compiler))
984 return UDM_FALSE;
985 if (UdmProgCompilerLastTokenType(compiler) != term)
986 {
987 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
988 "%d: ERROR: Expected %s got %s",
989 (int) UdmProgCompilerLineno(compiler),
990 UdmLex2str(term),
991 UdmLex2str(UdmProgCompilerLastTokenType(compiler)));
992 return UDM_FALSE;
993 }
994 UdmProgCompilerScan(compiler);
995 return UDM_TRUE;
996 }
997
998
999 static udm_bool_t
UdmProgCompilerErrorMultiCharacter(UDM_PROG_COMPILER * compiler)1000 UdmProgCompilerErrorMultiCharacter(UDM_PROG_COMPILER *compiler)
1001 {
1002 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1003 "%d: error: multi-character character constant",
1004 (int) UdmProgCompilerLineno(compiler));
1005 return UDM_FALSE;
1006 }
1007
1008
1009 static udm_bool_t
UdmProgCompilerGenericError(UDM_PROG_COMPILER * compiler,const char * msg)1010 UdmProgCompilerGenericError(UDM_PROG_COMPILER *compiler, const char *msg)
1011 {
1012 if (!UdmProgCompilerError(compiler))
1013 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1014 "%d: ERROR: %s",
1015 (int) UdmProgCompilerLineno(compiler), msg);
1016 return UDM_FALSE;
1017 }
1018
1019
1020 static udm_bool_t
UdmProgCompilerExpectedRule(UDM_PROG_COMPILER * compiler,const char * expected)1021 UdmProgCompilerExpectedRule(UDM_PROG_COMPILER *compiler, const char *expected)
1022 {
1023 if (!UdmProgCompilerError(compiler))
1024 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1025 "%d: ERROR: Expected %s got %s",
1026 (int) UdmProgCompilerLineno(compiler), expected,
1027 UdmLex2str(UdmProgCompilerLastTokenType(compiler)));
1028 return UDM_FALSE;
1029 }
1030
1031
1032 static udm_bool_t
UdmProgCompilerNotSupported(UDM_PROG_COMPILER * compiler,const char * msg)1033 UdmProgCompilerNotSupported(UDM_PROG_COMPILER *compiler, const char *msg)
1034 {
1035 if (!UdmProgCompilerError(compiler))
1036 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1037 "%d: ERROR: %s is not supported",
1038 (int) UdmProgCompilerLineno(compiler), msg);
1039 return UDM_FALSE;
1040 }
1041
1042
1043 static udm_bool_t
UdmProgCompilerExponentHasNoDigits(UDM_PROG_COMPILER * compiler)1044 UdmProgCompilerExponentHasNoDigits(UDM_PROG_COMPILER *compiler)
1045 {
1046 if (!UdmProgCompilerError(compiler))
1047 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1048 "%d: ERROR: exponent has no digits",
1049 (int) UdmProgCompilerLineno(compiler));
1050 return UDM_FALSE;
1051 }
1052
1053
1054 static udm_bool_t
UdmProgCompilerExponentInvalidSuffix(UDM_PROG_COMPILER * compiler,const UDM_CONST_TOKEN * exponent)1055 UdmProgCompilerExponentInvalidSuffix(UDM_PROG_COMPILER *compiler,
1056 const UDM_CONST_TOKEN *exponent)
1057 {
1058 if (!UdmProgCompilerError(compiler))
1059 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1060 "%d: ERROR: invalid suffix \"%.*s\" on floating exponent",
1061 (int) UdmProgCompilerLineno(compiler),
1062 (int) (exponent->end - exponent->str), exponent->str);
1063 return UDM_FALSE;
1064 }
1065
1066
1067 static udm_bool_t
UdmProgCompilerUnknownIdentifierError(UDM_PROG_COMPILER * compiler,const UDM_CONST_TOKEN * name)1068 UdmProgCompilerUnknownIdentifierError(UDM_PROG_COMPILER *compiler,
1069 const UDM_CONST_TOKEN *name)
1070 {
1071 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1072 "%d: ERROR: Unknown identifier '%.*s'",
1073 (int) UdmProgCompilerLineno(compiler),
1074 (int) (name->end - name->str), name->str);
1075 return UDM_FALSE;
1076 }
1077
1078
1079 static udm_bool_t
UdmProgCompilerBadDataTypeForArg(UDM_PROG_COMPILER * compiler,size_t argno,const UDM_VALUE_HANDLER * expected,const UDM_VALUE_HANDLER * actual)1080 UdmProgCompilerBadDataTypeForArg(UDM_PROG_COMPILER *compiler, size_t argno,
1081 const UDM_VALUE_HANDLER *expected,
1082 const UDM_VALUE_HANDLER *actual)
1083 {
1084 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1085 "%d: ERROR: Bad data type for argument #%d: expected '%s', got '%s'",
1086 (int) UdmProgCompilerLineno(compiler),
1087 (int) argno, expected->type_name, actual->type_name);
1088 return UDM_FALSE;
1089 }
1090
1091
1092 static udm_bool_t
UdmProgCompilerBadDataTypeForOperator2(UDM_PROG_COMPILER * compiler,const char * name,const UDM_VALUE_HANDLER * arg1,const UDM_VALUE_HANDLER * arg2)1093 UdmProgCompilerBadDataTypeForOperator2(UDM_PROG_COMPILER *compiler,
1094 const char *name,
1095 const UDM_VALUE_HANDLER *arg1,
1096 const UDM_VALUE_HANDLER *arg2)
1097 {
1098 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1099 "%d: ERROR: Invalid operands to binary operator '%s' "
1100 "(have '%s' and '%s')",
1101 (int) UdmProgCompilerLineno(compiler),
1102 name, arg1->type_name, arg2->type_name);
1103 return UDM_FALSE;
1104 }
1105
1106
1107 typedef struct
1108 {
1109 UDM_CONST_STR name;
1110 UDM_VALUE_HANDLER *handler;
1111 } UDM_TYPE_SPECIFIER;
1112
1113 #define STD_TYPE_SPECIFIER(x, h) {{UDM_CSTR_WITH_LEN(x)}, h}
1114
1115 static UDM_TYPE_SPECIFIER std_type_specifiers[]=
1116 {
1117 STD_TYPE_SPECIFIER("string", &UdmValueHandlerSimple),
1118 STD_TYPE_SPECIFIER("ENV", &UdmValueHandlerEnv),
1119 STD_TYPE_SPECIFIER("RESULT", &UdmValueHandlerResult),
1120 STD_TYPE_SPECIFIER("DOCUMENT", &UdmValueHandlerDocument),
1121 STD_TYPE_SPECIFIER("QUERYWORD", &UdmValueHandlerQueryWord),
1122 {{0, 0}}
1123 };
1124
1125 /*
1126 <type-specifier> ::= void
1127 | char
1128 | short
1129 | int
1130 | long
1131 | float
1132 | double
1133 | signed
1134 | unsigned
1135 | <struct-or-union-specifier>
1136 | <enum-specifier>
1137 | <typedef-name>
1138 */
1139 static const UDM_VALUE_HANDLER *
FindTypeByName(const UDM_CONST_TOKEN * name)1140 FindTypeByName(const UDM_CONST_TOKEN *name)
1141 {
1142 UDM_TYPE_SPECIFIER *t;
1143 for (t= std_type_specifiers; t->name.str; t++)
1144 {
1145 size_t name_length= name->end - name->str;
1146 if (name_length == t->name.length &&
1147 !memcmp(name->str, t->name.str, name_length))
1148 return t->handler;
1149 }
1150 return NULL;
1151 }
1152
1153
1154 static udm_bool_t
ParseTypeSpecifier(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** ha)1155 ParseTypeSpecifier(UDM_PROG_COMPILER *compiler,
1156 const UDM_VALUE_HANDLER **ha)
1157 {
1158 if (ParseTerm(compiler, UDM_LEX_CHAR))
1159 {
1160 ha[0]= &UdmValueHandlerChar;
1161 return UDM_TRUE;
1162 }
1163 if (ParseTerm(compiler, UDM_LEX_INT))
1164 {
1165 ha[0]= &UdmValueHandlerInt;
1166 return UDM_TRUE;
1167 }
1168 if (ParseTerm(compiler, UDM_LEX_DOUBLE))
1169 {
1170 ha[0]= &UdmValueHandlerDouble;
1171 return UDM_TRUE;
1172 }
1173 if (UdmProgCompilerLastTokenType(compiler) != UDM_LEX_IDENT)
1174 return UDM_FALSE;
1175 if (!(ha[0]= FindTypeByName(&compiler->scanner.token.token)))
1176 return UDM_FALSE;
1177 return ParseTerm(compiler, UDM_LEX_IDENT);
1178 }
1179
1180
1181 /**
1182 This needs to do look-ahead for one more step, to distinguish between:
1183 x= (ident); // a parenthesized expression
1184 x= (type) expression; // a type cast
1185 */
1186 static udm_bool_t
TestParenthesizedTypeSpecifier(UDM_PROG_COMPILER * compiler)1187 TestParenthesizedTypeSpecifier(UDM_PROG_COMPILER *compiler)
1188 {
1189 udm_bool_t rc;
1190 UDM_LEX_SCANNER scanner;
1191 const UDM_VALUE_HANDLER *ha;
1192 if (UdmProgCompilerLastTokenType(compiler) != UDM_LEX_LP)
1193 return UDM_FALSE;
1194 scanner= compiler->scanner;
1195 if (!ParseTerm(compiler, UDM_LEX_LP))
1196 {
1197 UDM_ASSERT(0);
1198 return UDM_FALSE;
1199 }
1200 rc= ParseTypeSpecifier(compiler, &ha) && ParseTerm(compiler, UDM_LEX_RP);
1201 compiler->scanner= scanner; /* Rollback to the initial state */
1202 return rc;
1203 }
1204
1205
1206 /*
1207 <declaration-specifier> ::= <storage-class-specifier>
1208 | <type-specifier>
1209 | <type-qualifier>
1210 */
1211 static udm_bool_t
ParseDeclarationSpecifier(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** ha)1212 ParseDeclarationSpecifier(UDM_PROG_COMPILER *compiler,
1213 const UDM_VALUE_HANDLER **ha)
1214 {
1215 return ParseTypeSpecifier(compiler, ha);
1216 }
1217
1218
1219 static void
UdmDSTRAppendArgTypes(UDM_DSTR * dstr,const UDM_PROG_FUNCTION_CALL_ARGUMENTS * arglist)1220 UdmDSTRAppendArgTypes(UDM_DSTR *dstr,
1221 const UDM_PROG_FUNCTION_CALL_ARGUMENTS *arglist)
1222 {
1223 size_t i;
1224 for (i= 0; i < arglist->nargs; i++)
1225 {
1226 if (i > 0)
1227 UdmDSTRAppend(dstr, ",", 1);
1228 UdmDSTRAppendSTR(dstr, UdmPrimaryExprHandler(&arglist->args[i])->type_name);
1229 }
1230 }
1231
1232
1233 static udm_bool_t
UdmProgCompilerErrorUnknownFunction(UDM_PROG_COMPILER * compiler,const UDM_CONST_TOKEN * name,const UDM_PROG_FUNCTION_CALL_ARGUMENTS * arglist)1234 UdmProgCompilerErrorUnknownFunction(UDM_PROG_COMPILER *compiler,
1235 const UDM_CONST_TOKEN *name,
1236 const UDM_PROG_FUNCTION_CALL_ARGUMENTS *arglist)
1237 {
1238 UDM_DSTR dstr;
1239 UdmDSTRInit(&dstr, 128);
1240 UdmDSTRAppendf(&dstr, "%d: ERROR: unknown function: %.*s(",
1241 (int) UdmProgCompilerLineno(compiler),
1242 (int) UdmConstTokenLength(name), UdmConstTokenStr(name));
1243 UdmDSTRAppendArgTypes(&dstr, arglist);
1244 UdmDSTRAppend(&dstr, ")", 1);
1245 udm_snprintf(compiler->errstr, sizeof(compiler->errstr), "%.*s",
1246 (int) UdmDSTRLength(&dstr), UdmDSTRPtr(&dstr));
1247 UdmDSTRFree(&dstr);
1248 return UDM_FALSE;
1249 }
1250
1251
1252 static udm_bool_t
UdmProgCompilerUnknownMethodError(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * handler,const UDM_CONST_TOKEN * name,const UDM_PROG_FUNCTION_CALL_ARGUMENTS * args)1253 UdmProgCompilerUnknownMethodError(UDM_PROG_COMPILER *compiler,
1254 const UDM_VALUE_HANDLER *handler,
1255 const UDM_CONST_TOKEN *name,
1256 const UDM_PROG_FUNCTION_CALL_ARGUMENTS *args)
1257 {
1258 size_t i;
1259 UDM_DSTR dstr;
1260 UdmDSTRInit(&dstr, 128);
1261 UdmDSTRAppendf(&dstr, "%d: ERROR: %s has no method '%.*s(",
1262 (int) UdmProgCompilerLineno(compiler),
1263 handler->type_name, (int) UdmConstTokenLength(name),
1264 UdmConstTokenStr(name));
1265 for (i= 0; i < args->nargs; i++)
1266 {
1267 UdmDSTRAppendf(&dstr, "%s%s&", i > 0 ? "," : "",
1268 UdmPrimaryExprHandler(&args->args[i])->type_name);
1269 }
1270 UdmDSTRAppend(&dstr, ")'", 2);
1271 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1272 "%.*s", (int) UdmDSTRLength(&dstr), UdmDSTRPtr(&dstr));
1273 UdmDSTRFree(&dstr);
1274 return UDM_FALSE;
1275 }
1276
1277
1278 static udm_bool_t
UdmProgCompilerVoidValueIsNotIgnored(UDM_PROG_COMPILER * compiler)1279 UdmProgCompilerVoidValueIsNotIgnored(UDM_PROG_COMPILER *compiler)
1280 {
1281 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
1282 "%d: ERROR: void value is not ignored as it ought to be",
1283 (int) UdmProgCompilerLineno(compiler));
1284 return UDM_FALSE;
1285 }
1286
1287
1288 static udm_bool_t
UdmProgGenerateVariableItemWithComment(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var,UDM_PROG_ITEM * it)1289 UdmProgGenerateVariableItemWithComment(UDM_PROG_COMPILER *compiler,
1290 const UDM_PROG_VAR *Var,
1291 UDM_PROG_ITEM *it)
1292 {
1293 UdmProgItemArgInitFromVar(&it->item_args, Var);
1294 if (compiler->generate_debug_info)
1295 it->comment= UdmConstTokenStrDup(&Var->name);
1296 return UdmProgAdd(compiler->prg, it) == UDM_OK;
1297 }
1298
1299
1300 static udm_bool_t
UdmGenerateVariableOp(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var,udm_tmpl_cmd_t op)1301 UdmGenerateVariableOp(UDM_PROG_COMPILER *compiler,
1302 const UDM_PROG_VAR *Var,
1303 udm_tmpl_cmd_t op)
1304 {
1305 UDM_PROG_ITEM i;
1306 UdmProgItemInit(&i);
1307 i.cmdnum= op;
1308 return UdmProgGenerateVariableItemWithComment(compiler, Var, &i);
1309 }
1310
1311
1312 static udm_bool_t
UdmGenerateVariableOperation(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var,UDM_PROG_CMD * cmd)1313 UdmGenerateVariableOperation(UDM_PROG_COMPILER *compiler,
1314 const UDM_PROG_VAR *Var,
1315 UDM_PROG_CMD *cmd)
1316 {
1317 UDM_PROG_ITEM i;
1318 UdmProgItemInit(&i);
1319 i.cmd= cmd;
1320 return UdmProgGenerateVariableItemWithComment(compiler, Var, &i);
1321 }
1322
1323
1324 static udm_bool_t
UdmGenerateConstructor(UDM_PROG_COMPILER * c,const UDM_PROG_VAR * Var)1325 UdmGenerateConstructor(UDM_PROG_COMPILER *c, const UDM_PROG_VAR *Var)
1326 {
1327 return UdmGenerateVariableOperation(c, Var, &udm_tmpl_construct_var);
1328 }
1329
1330
1331 static udm_bool_t
UdmGenerateVariableOperationToIReg0(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var)1332 UdmGenerateVariableOperationToIReg0(UDM_PROG_COMPILER *compiler,
1333 const UDM_PROG_VAR *Var)
1334 {
1335 if (UdmProgVarHandler(Var)->datatype == UDM_VALUE_DATA_TYPE_INT)
1336 {
1337 UDM_PROG_ITEM it;
1338 UdmProgItemInit(&it);
1339 it.cmdnum= UDM_PROG_MOV_IREG0_INT_PTR_STACK_OFFSET;
1340 return UdmProgGenerateVariableItemWithComment(compiler, Var, &it);
1341 }
1342 return UdmGenerateVariableOperation(compiler, Var, &udm_tmpl_mov_ireg0_var0);
1343 }
1344
1345
1346 static udm_bool_t
UdmGenerateVariableOperationToDReg0(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var)1347 UdmGenerateVariableOperationToDReg0(UDM_PROG_COMPILER *compiler,
1348 const UDM_PROG_VAR *Var)
1349 {
1350 if (UdmProgVarHandler(Var)->datatype == UDM_VALUE_DATA_TYPE_DOUBLE)
1351 {
1352 UDM_PROG_ITEM it;
1353 UdmProgItemInit(&it);
1354 it.cmdnum= UDM_PROG_MOV_DREG0_DBL_PTR_STACK_OFFSET;
1355 return UdmProgGenerateVariableItemWithComment(compiler, Var, &it);
1356 }
1357 return UdmGenerateVariableOperation(compiler, Var, &udm_tmpl_mov_dreg0_var0);
1358 }
1359
1360
1361 static udm_bool_t
UdmGenerateVariableOperationToIReg1(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var)1362 UdmGenerateVariableOperationToIReg1(UDM_PROG_COMPILER *compiler,
1363 const UDM_PROG_VAR *Var)
1364 {
1365 if (UdmProgVarHandler(Var)->datatype == UDM_VALUE_DATA_TYPE_INT)
1366 {
1367 UDM_PROG_ITEM it;
1368 UdmProgItemInit(&it);
1369 it.cmdnum= UDM_PROG_MOV_IREG1_INT_PTR_STACK_OFFSET;
1370 return UdmProgGenerateVariableItemWithComment(compiler, Var, &it);
1371 }
1372 return UdmGenerateVariableOperation(compiler, Var, &udm_tmpl_mov_ireg1_var0);
1373 }
1374
1375
1376 static udm_bool_t
UdmGenerateVariableOperationToDReg1(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var)1377 UdmGenerateVariableOperationToDReg1(UDM_PROG_COMPILER *compiler,
1378 const UDM_PROG_VAR *Var)
1379 {
1380 if (UdmProgVarHandler(Var)->datatype == UDM_VALUE_DATA_TYPE_DOUBLE)
1381 {
1382 UDM_PROG_ITEM it;
1383 UdmProgItemInit(&it);
1384 it.cmdnum= UDM_PROG_MOV_DREG1_DBL_PTR_STACK_OFFSET;
1385 return UdmProgGenerateVariableItemWithComment(compiler, Var, &it);
1386 }
1387 return UdmGenerateVariableOperation(compiler, Var, &udm_tmpl_mov_dreg1_var0);
1388 }
1389
1390
1391 static udm_bool_t
UdmGenerateBooleanTest(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * handler,udm_bool_t positive)1392 UdmGenerateBooleanTest(UDM_PROG_COMPILER *compiler,
1393 const UDM_VALUE_HANDLER *handler,
1394 udm_bool_t positive)
1395 {
1396 if (!handler)
1397 return UdmProgCompilerVoidValueIsNotIgnored(compiler);
1398 switch (handler->datatype)
1399 {
1400 case UDM_VALUE_DATA_TYPE_CHAR:
1401 case UDM_VALUE_DATA_TYPE_INT:
1402 case UDM_VALUE_DATA_TYPE_DOUBLE:
1403 break;
1404 case UDM_VALUE_DATA_TYPE_STR:
1405 case UDM_VALUE_DATA_TYPE_ENV:
1406 case UDM_VALUE_DATA_TYPE_RESULT:
1407 case UDM_VALUE_DATA_TYPE_DOCUMENT:
1408 case UDM_VALUE_DATA_TYPE_SQLRESULT:
1409 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
1410 return UdmProgCompilerNotSupported(compiler, "boolean test for data type");
1411 }
1412
1413 if (handler == &UdmValueHandlerInt)
1414 {
1415 if (UDM_OK != UdmProgAddArg0SimpleOp(compiler->prg,
1416 UDM_PROG_MOV_IREG1_0))
1417 return UDM_FALSE;
1418 if (UDM_OK != UdmProgAddArg0SimpleOp(compiler->prg,
1419 positive ?
1420 UDM_PROG_CMP_IREG0_IREG1_NE:
1421 UDM_PROG_CMP_IREG0_IREG1_EQ))
1422 return UDM_FALSE;
1423 }
1424 else
1425 {
1426 if (UDM_OK != UdmProgAddArg0SimpleOp(compiler->prg,
1427 UDM_PROG_MOV_DREG1_0))
1428 return UDM_FALSE;
1429 if (UDM_OK != UdmProgAddArg0SimpleOp(compiler->prg,
1430 positive ?
1431 UDM_PROG_CMP_DREG0_DREG1_NE :
1432 UDM_PROG_CMP_DREG0_DREG1_EQ))
1433 return UDM_FALSE;
1434 }
1435 return UDM_TRUE;
1436 }
1437
1438
1439 /*
1440 Store the value of (!expr) into ireg0.
1441 */
1442 static udm_bool_t
UdmGenerateIsNotTrueTest(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * handler)1443 UdmGenerateIsNotTrueTest(UDM_PROG_COMPILER *compiler,
1444 const UDM_VALUE_HANDLER *handler)
1445 {
1446 return UdmGenerateBooleanTest(compiler, handler, UDM_FALSE);
1447 }
1448
1449
1450 static udm_bool_t
UdmGenerateIsTrueTest(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * handler)1451 UdmGenerateIsTrueTest(UDM_PROG_COMPILER *compiler,
1452 const UDM_VALUE_HANDLER *handler)
1453 {
1454 return UdmGenerateBooleanTest(compiler, handler, UDM_TRUE);
1455 }
1456
1457
1458
1459 static udm_bool_t
UdmGenerateSwapNativeReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * handler)1460 UdmGenerateSwapNativeReg0Reg1(UDM_PROG_COMPILER *compiler,
1461 const UDM_VALUE_HANDLER *handler)
1462 {
1463 return UdmGenerateOp(compiler,
1464 handler->native_reg_type == UDM_VALUE_DATA_TYPE_DOUBLE ?
1465 UDM_PROG_SWP_DREG0_DREG1:
1466 UDM_PROG_SWP_IREG0_IREG1);
1467 }
1468
1469
1470 static udm_bool_t
UdmGenerateAddNativeReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** handler,udm_lex_t op)1471 UdmGenerateAddNativeReg0Reg1(UDM_PROG_COMPILER *compiler,
1472 const UDM_VALUE_HANDLER **handler,
1473 udm_lex_t op)
1474 {
1475 UDM_ASSERT(op == UDM_LEX_PLUS || op == UDM_LEX_MINUS);
1476 switch (handler[0]->native_reg_type)
1477 {
1478 case UDM_VALUE_DATA_TYPE_CHAR:
1479 case UDM_VALUE_DATA_TYPE_INT:
1480 return UDM_OK == UdmProgAddArg0SimpleOp(compiler->prg,
1481 op == UDM_LEX_PLUS ?
1482 UDM_PROG_ADD_IREG0_IREG1 :
1483 UDM_PROG_SUB_IREG0_IREG1);
1484
1485 case UDM_VALUE_DATA_TYPE_DOUBLE:
1486 return UDM_OK == UdmProgAddArg0SimpleOp(compiler->prg,
1487 op == UDM_LEX_PLUS ?
1488 UDM_PROG_ADD_DREG0_DREG1:
1489 UDM_PROG_SUB_DREG0_DREG1);
1490 case UDM_VALUE_DATA_TYPE_STR:
1491 case UDM_VALUE_DATA_TYPE_ENV:
1492 case UDM_VALUE_DATA_TYPE_RESULT:
1493 case UDM_VALUE_DATA_TYPE_DOCUMENT:
1494 case UDM_VALUE_DATA_TYPE_SQLRESULT:
1495 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
1496 break;
1497 }
1498 UDM_ASSERT(0);
1499 return UDM_FALSE;
1500 }
1501
1502
1503 static udm_bool_t
UdmGenerateMulNativeReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** handler,udm_lex_t op)1504 UdmGenerateMulNativeReg0Reg1(UDM_PROG_COMPILER *compiler,
1505 const UDM_VALUE_HANDLER **handler,
1506 udm_lex_t op)
1507 {
1508 UDM_ASSERT(op == UDM_LEX_ASTERISK || op == UDM_LEX_SLASH || op == UDM_LEX_PERCENT);
1509 switch (handler[0]->native_reg_type)
1510 {
1511 case UDM_VALUE_DATA_TYPE_CHAR:
1512 case UDM_VALUE_DATA_TYPE_INT:
1513 return UdmGenerateOp(compiler, op == UDM_LEX_ASTERISK ?
1514 UDM_PROG_MUL_IREG0_IREG1 :
1515 op == UDM_LEX_SLASH ?
1516 UDM_PROG_DIV_IREG0_IREG1 :
1517 UDM_PROG_REM_IREG0_IREG1);
1518 case UDM_VALUE_DATA_TYPE_DOUBLE:
1519 if (op == UDM_LEX_PERCENT)
1520 return UdmProgCompilerNotSupported(compiler, "binary operator % for the `double` data type");
1521 return UdmGenerateOp(compiler, op == UDM_LEX_ASTERISK ?
1522 UDM_PROG_MUL_DREG0_DREG1 :
1523 UDM_PROG_DIV_DREG0_DREG1);
1524 case UDM_VALUE_DATA_TYPE_STR:
1525 case UDM_VALUE_DATA_TYPE_ENV:
1526 case UDM_VALUE_DATA_TYPE_RESULT:
1527 case UDM_VALUE_DATA_TYPE_DOCUMENT:
1528 case UDM_VALUE_DATA_TYPE_SQLRESULT:
1529 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
1530 break;
1531 }
1532 UDM_ASSERT(0);
1533 return UDM_FALSE;
1534 }
1535
1536
1537 static udm_bool_t
UdmGenerateShiftNativeReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** handler,udm_lex_t op)1538 UdmGenerateShiftNativeReg0Reg1(UDM_PROG_COMPILER *compiler,
1539 const UDM_VALUE_HANDLER **handler,
1540 udm_lex_t op)
1541 {
1542 UDM_ASSERT(op == UDM_LEX_LSHIFT || op == UDM_LEX_RSHIFT);
1543 switch (handler[0]->native_reg_type)
1544 {
1545 case UDM_VALUE_DATA_TYPE_CHAR:
1546 case UDM_VALUE_DATA_TYPE_INT:
1547 return UdmGenerateOp(compiler, op == UDM_LEX_LSHIFT ?
1548 UDM_PROG_SHL_IREG0_IREG1 :
1549 UDM_PROG_SHR_IREG0_IREG1);
1550 case UDM_VALUE_DATA_TYPE_DOUBLE:
1551 return UdmProgCompilerNotSupported(compiler, "<< and >> for this data type");
1552 case UDM_VALUE_DATA_TYPE_STR:
1553 case UDM_VALUE_DATA_TYPE_ENV:
1554 case UDM_VALUE_DATA_TYPE_RESULT:
1555 case UDM_VALUE_DATA_TYPE_DOCUMENT:
1556 case UDM_VALUE_DATA_TYPE_SQLRESULT:
1557 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
1558 break;
1559 }
1560 UDM_ASSERT(0);
1561 return UDM_FALSE;
1562 }
1563
1564
1565 static udm_bool_t
UdmGenerateRelNativeReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** handler,udm_lex_t op)1566 UdmGenerateRelNativeReg0Reg1(UDM_PROG_COMPILER *compiler,
1567 const UDM_VALUE_HANDLER **handler,
1568 udm_lex_t op)
1569 {
1570 UDM_ASSERT(op == UDM_LEX_LE || op == UDM_LEX_LT ||
1571 op == UDM_LEX_GT || op == UDM_LEX_GE);
1572 switch (handler[0]->native_reg_type)
1573 {
1574 case UDM_VALUE_DATA_TYPE_CHAR:
1575 case UDM_VALUE_DATA_TYPE_INT:
1576 switch (op)
1577 {
1578 case UDM_LEX_LE: return UdmGenerateOp(compiler, UDM_PROG_CMP_IREG0_IREG1_LE);
1579 case UDM_LEX_LT: return UdmGenerateOp(compiler, UDM_PROG_CMP_IREG0_IREG1_LT);
1580 case UDM_LEX_GT: return UdmGenerateOp(compiler, UDM_PROG_CMP_IREG0_IREG1_GT);
1581 case UDM_LEX_GE: return UdmGenerateOp(compiler, UDM_PROG_CMP_IREG0_IREG1_GE);
1582 default:
1583 break;
1584 }
1585 break;
1586 case UDM_VALUE_DATA_TYPE_DOUBLE:
1587 *handler= &UdmValueHandlerInt;
1588 switch (op)
1589 {
1590 case UDM_LEX_LE: return UdmGenerateOp(compiler, UDM_PROG_CMP_DREG0_DREG1_LE);
1591 case UDM_LEX_LT: return UdmGenerateOp(compiler, UDM_PROG_CMP_DREG0_DREG1_LT);
1592 case UDM_LEX_GT: return UdmGenerateOp(compiler, UDM_PROG_CMP_DREG0_DREG1_GT);
1593 case UDM_LEX_GE: return UdmGenerateOp(compiler, UDM_PROG_CMP_DREG0_DREG1_GE);
1594 default:
1595 break;
1596 }
1597 break;
1598
1599 case UDM_VALUE_DATA_TYPE_STR:
1600 case UDM_VALUE_DATA_TYPE_ENV:
1601 case UDM_VALUE_DATA_TYPE_RESULT:
1602 case UDM_VALUE_DATA_TYPE_DOCUMENT:
1603 case UDM_VALUE_DATA_TYPE_SQLRESULT:
1604 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
1605 break;
1606 }
1607 UDM_ASSERT(0);
1608 return UDM_FALSE;
1609 }
1610
1611
1612 static udm_bool_t
UdmGenerateEqNativeReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** handler,udm_lex_t op)1613 UdmGenerateEqNativeReg0Reg1(UDM_PROG_COMPILER *compiler,
1614 const UDM_VALUE_HANDLER **handler,
1615 udm_lex_t op)
1616 {
1617 UDM_ASSERT(op == UDM_LEX_EQ_EQ || op == UDM_LEX_NOT_EQ);
1618 switch (handler[0]->native_reg_type)
1619 {
1620 case UDM_VALUE_DATA_TYPE_CHAR:
1621 case UDM_VALUE_DATA_TYPE_INT:
1622 switch (op)
1623 {
1624 case UDM_LEX_EQ_EQ: return UdmGenerateOp(compiler, UDM_PROG_CMP_IREG0_IREG1_EQ);
1625 case UDM_LEX_NOT_EQ: return UdmGenerateOp(compiler, UDM_PROG_CMP_IREG0_IREG1_NE);
1626 default:
1627 break;
1628 }
1629 break;
1630 case UDM_VALUE_DATA_TYPE_DOUBLE:
1631 *handler= &UdmValueHandlerInt;
1632 switch (op)
1633 {
1634 case UDM_LEX_EQ_EQ: return UdmGenerateOp(compiler, UDM_PROG_CMP_DREG0_DREG1_EQ);
1635 case UDM_LEX_NOT_EQ: return UdmGenerateOp(compiler, UDM_PROG_CMP_DREG0_DREG1_NE);
1636 default:
1637 break;
1638 }
1639 break;
1640 case UDM_VALUE_DATA_TYPE_STR:
1641 case UDM_VALUE_DATA_TYPE_ENV:
1642 case UDM_VALUE_DATA_TYPE_RESULT:
1643 case UDM_VALUE_DATA_TYPE_DOCUMENT:
1644 case UDM_VALUE_DATA_TYPE_SQLRESULT:
1645 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
1646 break;
1647 }
1648 UDM_ASSERT(0);
1649 return UDM_FALSE;
1650 }
1651
1652
1653 static udm_bool_t
UdmGenerateAndNativeReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** handler,udm_lex_t op)1654 UdmGenerateAndNativeReg0Reg1(UDM_PROG_COMPILER *compiler,
1655 const UDM_VALUE_HANDLER **handler,
1656 udm_lex_t op)
1657 {
1658 UDM_ASSERT(op == UDM_LEX_AMPERSAND);
1659 switch (handler[0]->native_reg_type)
1660 {
1661 case UDM_VALUE_DATA_TYPE_CHAR:
1662 case UDM_VALUE_DATA_TYPE_INT:
1663 return UdmGenerateOp(compiler, UDM_PROG_AND_IREG0_IREG1);
1664 case UDM_VALUE_DATA_TYPE_DOUBLE:
1665 return UdmProgCompilerNotSupported(compiler, "binary & for this data type");
1666 case UDM_VALUE_DATA_TYPE_STR:
1667 case UDM_VALUE_DATA_TYPE_ENV:
1668 case UDM_VALUE_DATA_TYPE_RESULT:
1669 case UDM_VALUE_DATA_TYPE_DOCUMENT:
1670 case UDM_VALUE_DATA_TYPE_SQLRESULT:
1671 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
1672 break;
1673 }
1674 UDM_ASSERT(0);
1675 return UDM_FALSE;
1676 }
1677
1678
1679 static udm_bool_t
UdmGenerateXorNativeReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** handler,udm_lex_t op)1680 UdmGenerateXorNativeReg0Reg1(UDM_PROG_COMPILER *compiler,
1681 const UDM_VALUE_HANDLER **handler,
1682 udm_lex_t op)
1683 {
1684 UDM_ASSERT(op == UDM_LEX_CARET);
1685 switch (handler[0]->native_reg_type)
1686 {
1687 case UDM_VALUE_DATA_TYPE_CHAR:
1688 case UDM_VALUE_DATA_TYPE_INT:
1689 return UdmGenerateOp(compiler, UDM_PROG_XOR_IREG0_IREG1);
1690 case UDM_VALUE_DATA_TYPE_DOUBLE:
1691 return UdmProgCompilerNotSupported(compiler, "binary ^ for this data type");
1692 case UDM_VALUE_DATA_TYPE_STR:
1693 case UDM_VALUE_DATA_TYPE_ENV:
1694 case UDM_VALUE_DATA_TYPE_RESULT:
1695 case UDM_VALUE_DATA_TYPE_DOCUMENT:
1696 case UDM_VALUE_DATA_TYPE_SQLRESULT:
1697 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
1698 break;
1699 }
1700 UDM_ASSERT(0);
1701 return UDM_FALSE;
1702 }
1703
1704
1705 static udm_bool_t
UdmGenerateOrNativeReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** handler,udm_lex_t op)1706 UdmGenerateOrNativeReg0Reg1(UDM_PROG_COMPILER *compiler,
1707 const UDM_VALUE_HANDLER **handler,
1708 udm_lex_t op)
1709 {
1710 UDM_ASSERT(op == UDM_LEX_VBAR);
1711 switch (handler[0]->native_reg_type)
1712 {
1713 case UDM_VALUE_DATA_TYPE_CHAR:
1714 case UDM_VALUE_DATA_TYPE_INT:
1715 return UdmGenerateOp(compiler, UDM_PROG_OR_IREG0_IREG1);
1716 case UDM_VALUE_DATA_TYPE_DOUBLE:
1717 return UdmProgCompilerNotSupported(compiler, "binary | for this data type");
1718 case UDM_VALUE_DATA_TYPE_STR:
1719 case UDM_VALUE_DATA_TYPE_ENV:
1720 case UDM_VALUE_DATA_TYPE_RESULT:
1721 case UDM_VALUE_DATA_TYPE_DOCUMENT:
1722 case UDM_VALUE_DATA_TYPE_SQLRESULT:
1723 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
1724 break;
1725 }
1726 UDM_ASSERT(0);
1727 return UDM_FALSE;
1728 }
1729
1730
1731 static udm_bool_t
UdmGenerateDiadicOperationNativeReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER ** handler,udm_lex_t op)1732 UdmGenerateDiadicOperationNativeReg0Reg1(UDM_PROG_COMPILER *compiler,
1733 const UDM_VALUE_HANDLER **handler,
1734 udm_lex_t op)
1735 {
1736 switch (op)
1737 {
1738 case UDM_LEX_VBAR:
1739 return UdmGenerateOrNativeReg0Reg1(compiler, handler, op);
1740 case UDM_LEX_CARET:
1741 return UdmGenerateXorNativeReg0Reg1(compiler, handler, op);
1742 case UDM_LEX_AMPERSAND:
1743 return UdmGenerateAndNativeReg0Reg1(compiler, handler, op);
1744 case UDM_LEX_EQ_EQ:
1745 case UDM_LEX_NOT_EQ:
1746 return UdmGenerateEqNativeReg0Reg1(compiler, handler, op);
1747 case UDM_LEX_LE:
1748 case UDM_LEX_GE:
1749 case UDM_LEX_LT:
1750 case UDM_LEX_GT:
1751 return UdmGenerateRelNativeReg0Reg1(compiler, handler, op);
1752 case UDM_LEX_ASTERISK:
1753 case UDM_LEX_SLASH:
1754 case UDM_LEX_PERCENT:
1755 return UdmGenerateMulNativeReg0Reg1(compiler, handler, op);
1756 case UDM_LEX_PLUS:
1757 case UDM_LEX_MINUS:
1758 return UdmGenerateAddNativeReg0Reg1(compiler, handler, op);
1759 case UDM_LEX_LSHIFT:
1760 case UDM_LEX_RSHIFT:
1761 return UdmGenerateShiftNativeReg0Reg1(compiler, handler, op);
1762 default:
1763 UDM_ASSERT(0);
1764 }
1765 return UDM_FALSE;
1766 }
1767
1768
1769 static udm_bool_t
UdmGenerateVarToNativeReg0(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * src)1770 UdmGenerateVarToNativeReg0(UDM_PROG_COMPILER *compiler,
1771 const UDM_PROG_VAR *src)
1772 {
1773 switch (UdmProgVarHandler(src)->datatype)
1774 {
1775 case UDM_VALUE_DATA_TYPE_INT:
1776 return UdmGenerateVariableOperationToIReg0(compiler, src);
1777 case UDM_VALUE_DATA_TYPE_CHAR:
1778 return UdmGenerateVariableOperation(compiler, src, &udm_tmpl_mov_ireg0_var0);
1779 case UDM_VALUE_DATA_TYPE_DOUBLE:
1780 return UdmGenerateVariableOperationToDReg0(compiler, src);
1781 default:
1782 return UdmGenerateVariableOperation(compiler, src, &udm_tmpl_get_var_to_cs0_z0);
1783 }
1784 UDM_ASSERT(0);
1785 return UDM_FALSE;
1786 }
1787
1788
1789 static udm_bool_t
UdmGenerateVarToNativeReg1(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * src)1790 UdmGenerateVarToNativeReg1(UDM_PROG_COMPILER *compiler,
1791 const UDM_PROG_VAR *src)
1792 {
1793 switch (UdmProgVarHandler(src)->datatype)
1794 {
1795 case UDM_VALUE_DATA_TYPE_INT:
1796 return UdmGenerateVariableOperationToIReg1(compiler, src);
1797 case UDM_VALUE_DATA_TYPE_CHAR:
1798 return UdmGenerateVariableOperation(compiler, src, &udm_tmpl_mov_ireg1_var0);
1799 case UDM_VALUE_DATA_TYPE_DOUBLE:
1800 return UdmGenerateVariableOperationToDReg1(compiler, src);
1801 default:
1802 return UdmProgCompilerNotSupported(compiler, "Variable of a complex type in this context");
1803 }
1804 UDM_ASSERT(0);
1805 return UDM_FALSE;
1806 }
1807
1808
1809 static udm_bool_t
UdmGenerateNativeReg0ToVar(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var)1810 UdmGenerateNativeReg0ToVar(UDM_PROG_COMPILER *compiler,
1811 const UDM_PROG_VAR *Var)
1812 {
1813 switch (UdmProgVarHandler(Var)->datatype)
1814 {
1815 case UDM_VALUE_DATA_TYPE_INT:
1816 case UDM_VALUE_DATA_TYPE_CHAR:
1817 return UdmGenerateVariableOperation(compiler, Var, &udm_tmpl_set_var_from_ireg0);
1818 case UDM_VALUE_DATA_TYPE_DOUBLE:
1819 return UdmGenerateVariableOperation(compiler, Var, &udm_tmpl_set_var_from_dreg0);
1820 default:
1821 UDM_ASSERT(0);
1822 return UDM_FALSE;
1823 }
1824 UDM_ASSERT(0);
1825 return UDM_FALSE;
1826 }
1827
1828
1829 static udm_bool_t
UdmGenerateLiteralToNativeRegNInt(UDM_PROG_COMPILER * compiler,const UDM_PROG_PRIMARY_EXPRESSION * expr,size_t regno)1830 UdmGenerateLiteralToNativeRegNInt(UDM_PROG_COMPILER *compiler,
1831 const UDM_PROG_PRIMARY_EXPRESSION *expr,
1832 size_t regno)
1833 {
1834 udm_tmpl_cmd_t cmd= !regno ? UDM_PROG_MOV_IREG0_INT : UDM_PROG_MOV_IREG1_INT;
1835 int tmp= udm_strntoi(expr->Var.name.str, expr->Var.name.end - expr->Var.name.str);
1836 if (UDM_OK != UdmProgAddArg1SimpleOpInt(compiler->prg, cmd, tmp))
1837 return UDM_FALSE;
1838 return UDM_TRUE;
1839 }
1840
1841
1842 static udm_bool_t
UdmGenerateLiteralToNativeRegNDbl(UDM_PROG_COMPILER * compiler,const UDM_PROG_PRIMARY_EXPRESSION * expr,size_t regno)1843 UdmGenerateLiteralToNativeRegNDbl(UDM_PROG_COMPILER *compiler,
1844 const UDM_PROG_PRIMARY_EXPRESSION *expr,
1845 size_t regno)
1846 {
1847 udm_tmpl_cmd_t cmd= !regno ? UDM_PROG_MOV_DREG0_DBL : UDM_PROG_MOV_DREG1_DBL;
1848 double tmp= udm_strntod(expr->Var.name.str, expr->Var.name.end - expr->Var.name.str);
1849 if (UDM_OK != UdmProgAddArg1SimpleOpDouble(compiler->prg, cmd, tmp))
1850 return UDM_FALSE;
1851 return UDM_TRUE;
1852 }
1853
1854
1855 static udm_bool_t
UdmGenerateLiteralToNativeRegNChar(UDM_PROG_COMPILER * compiler,const UDM_PROG_PRIMARY_EXPRESSION * expr,size_t regno)1856 UdmGenerateLiteralToNativeRegNChar(UDM_PROG_COMPILER *compiler,
1857 const UDM_PROG_PRIMARY_EXPRESSION *expr,
1858 size_t regno)
1859 {
1860 udm_tmpl_cmd_t cmd= !regno ? UDM_PROG_MOV_IREG0_INT : UDM_PROG_MOV_IREG1_INT;
1861 return UDM_OK == UdmProgAddArg1SimpleOpInt(compiler->prg,
1862 cmd, expr->Var.name.str[0]);
1863 }
1864
1865
1866 static udm_bool_t
UdmGenerateTextSegmentTo_cs0_z0(UDM_PROG_COMPILER * compiler,udm_offset_and_length_t addr)1867 UdmGenerateTextSegmentTo_cs0_z0(UDM_PROG_COMPILER *compiler,
1868 udm_offset_and_length_t addr)
1869 {
1870 UDM_PROG_ITEM i;
1871 UdmProgItemInit(&i);
1872 i.cmd= &udm_tmpl_textdata_to_cs0_z0;
1873 i.item_args.textdata_addr= addr;
1874 return UDM_OK == UdmProgAdd(compiler->prg, &i);
1875 }
1876
1877
1878 static udm_bool_t
UdmGenerateMovNativeReg0ToReg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * handler)1879 UdmGenerateMovNativeReg0ToReg1(UDM_PROG_COMPILER *compiler,
1880 const UDM_VALUE_HANDLER *handler)
1881 {
1882 switch (handler->native_reg_type)
1883 {
1884 case UDM_VALUE_DATA_TYPE_INT:
1885 return UDM_OK == UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_MOV_IREG1_IREG0);
1886 case UDM_VALUE_DATA_TYPE_DOUBLE:
1887 return UDM_OK == UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_MOV_DREG1_DREG0);
1888 default:
1889 UDM_ASSERT(0);
1890 }
1891 return UDM_FALSE;
1892 }
1893
1894
1895 static udm_bool_t
UdmGenerateClearNativeReg0(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * handler)1896 UdmGenerateClearNativeReg0(UDM_PROG_COMPILER *compiler,
1897 const UDM_VALUE_HANDLER *handler)
1898 {
1899 switch (handler->native_reg_type)
1900 {
1901 case UDM_VALUE_DATA_TYPE_INT:
1902 return UDM_OK == UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_MOV_IREG0_0);
1903 case UDM_VALUE_DATA_TYPE_DOUBLE:
1904 return UDM_OK == UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_MOV_DREG0_0);
1905 default:
1906 UDM_ASSERT(0);
1907 }
1908 return UDM_FALSE;
1909 }
1910
1911
1912 static udm_bool_t
UdmGenerateLiteralToNativeRegN(UDM_PROG_COMPILER * compiler,const UDM_PROG_PRIMARY_EXPRESSION * expr,size_t regno)1913 UdmGenerateLiteralToNativeRegN(UDM_PROG_COMPILER *compiler,
1914 const UDM_PROG_PRIMARY_EXPRESSION *expr,
1915 size_t regno)
1916 {
1917 switch (UdmPrimaryExprHandler(expr)->datatype)
1918 {
1919 case UDM_VALUE_DATA_TYPE_DOUBLE:
1920 return UdmGenerateLiteralToNativeRegNDbl(compiler, expr, regno);
1921 case UDM_VALUE_DATA_TYPE_INT:
1922 return UdmGenerateLiteralToNativeRegNInt(compiler, expr, regno);
1923 case UDM_VALUE_DATA_TYPE_CHAR:
1924 return UdmGenerateLiteralToNativeRegNChar(compiler, expr, regno);
1925 case UDM_VALUE_DATA_TYPE_STR:
1926 UDM_ASSERT(regno == 0);
1927 return UdmGenerateTextSegmentTo_cs0_z0(compiler, expr->textdata_addr);
1928 case UDM_VALUE_DATA_TYPE_ENV:
1929 case UDM_VALUE_DATA_TYPE_RESULT:
1930 case UDM_VALUE_DATA_TYPE_DOCUMENT:
1931 case UDM_VALUE_DATA_TYPE_SQLRESULT:
1932 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
1933 break;
1934 }
1935 UDM_ASSERT(0);
1936 return UDM_TRUE;
1937 }
1938
1939
1940 static udm_bool_t
UdmGenerateExpressionToNativeReg0(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,const UDM_PROG_VAR * func_result)1941 UdmGenerateExpressionToNativeReg0(UDM_PROG_COMPILER *compiler,
1942 UDM_PROG_EXPRESSION *expr,
1943 const UDM_PROG_VAR *func_result)
1944 {
1945 switch (expr->primary_expr.type)
1946 {
1947 case UDM_EXPRESSION_CONST:
1948 expr->primary_expr.type= UDM_EXPRESSION_COMPUTED;
1949 return UdmGenerateLiteralToNativeRegN(compiler, &expr->primary_expr, 0);
1950 case UDM_EXPRESSION_IDENT:
1951 expr->primary_expr.type= UDM_EXPRESSION_COMPUTED;
1952 return UdmGenerateVarToNativeReg0(compiler, &expr->primary_expr.Var);
1953 case UDM_EXPRESSION_OBJECT:
1954 expr->primary_expr.type= UDM_EXPRESSION_COMPUTED;
1955 if (func_result && UdmProgVarHandler(func_result))
1956 return UdmGenerateVarToNativeReg0(compiler, func_result);
1957 else
1958 return UDM_TRUE; /* Simple type: char, int, double */
1959 case UDM_EXPRESSION_COMPUTED:
1960 return UDM_TRUE;
1961 }
1962 UDM_ASSERT(0);
1963 return UdmProgCompilerNotSupported(compiler, "cout with postfix expression of this type");
1964 }
1965
1966
1967 static udm_bool_t
UdmGenerateNativeReg0TypeConversion(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * dst,const UDM_VALUE_HANDLER * src)1968 UdmGenerateNativeReg0TypeConversion(UDM_PROG_COMPILER *compiler,
1969 const UDM_VALUE_HANDLER *dst,
1970 const UDM_VALUE_HANDLER *src)
1971 {
1972 if (dst->native_reg_type == UDM_VALUE_DATA_TYPE_DOUBLE &&
1973 src->native_reg_type == UDM_VALUE_DATA_TYPE_INT)
1974 {
1975 if (UDM_OK != UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_MOV_DREG0_IREG0))
1976 return UDM_FALSE;
1977 }
1978 else if (dst->native_reg_type == UDM_VALUE_DATA_TYPE_INT &&
1979 src->native_reg_type == UDM_VALUE_DATA_TYPE_DOUBLE)
1980 {
1981 if (UDM_OK != UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_MOV_IREG0_DREG0))
1982 return UDM_FALSE;
1983 }
1984 return UDM_TRUE; /* No conversion needed */
1985 }
1986
1987
1988 static udm_bool_t
UdmGenerateNativeReg1TypeConversion(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * dst,const UDM_VALUE_HANDLER * src)1989 UdmGenerateNativeReg1TypeConversion(UDM_PROG_COMPILER *compiler,
1990 const UDM_VALUE_HANDLER *dst,
1991 const UDM_VALUE_HANDLER *src)
1992 {
1993 if (dst->native_reg_type == UDM_VALUE_DATA_TYPE_DOUBLE &&
1994 src->native_reg_type == UDM_VALUE_DATA_TYPE_INT)
1995 {
1996 if (UDM_OK != UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_MOV_DREG1_IREG1))
1997 return UDM_FALSE;
1998 }
1999 else if (dst->native_reg_type == UDM_VALUE_DATA_TYPE_INT &&
2000 src->native_reg_type == UDM_VALUE_DATA_TYPE_DOUBLE)
2001 {
2002 if (UDM_OK != UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_MOV_IREG1_DREG1))
2003 return UDM_FALSE;
2004 }
2005 return UDM_TRUE; /* No conversion needed */
2006 }
2007
2008
2009 static size_t
UdmValueHandlerAlignedDataSize(const UDM_VALUE_HANDLER * handler)2010 UdmValueHandlerAlignedDataSize(const UDM_VALUE_HANDLER *handler)
2011 {
2012 size_t data_size= handler->DataSize();
2013 if (data_size < sizeof(void*))
2014 data_size= sizeof(void*);
2015 return data_size;
2016 }
2017
2018
2019 static udm_bool_t
UdmGenerateDeclareNonInitializedVariableWithName(UDM_PROG_COMPILER * compiler,UDM_PROG_VARLIST * Vars,const UDM_PROG_VAR * PIVar,const char * name)2020 UdmGenerateDeclareNonInitializedVariableWithName(UDM_PROG_COMPILER *compiler,
2021 UDM_PROG_VARLIST *Vars,
2022 const UDM_PROG_VAR *PIVar,
2023 const char *name)
2024 {
2025 size_t data_size;
2026 UDM_ASSERT(compiler->Vars2.nitems);
2027 if (UdmProgVarListFind(Vars, name))
2028 {
2029 UDM_ASSERT(name[0] != '/'); /* Not a temporary variable */
2030 return UdmProgCompilerRedeclarationError(compiler, name);
2031 }
2032 /*fprintf(stderr, "stackaddr=%d name=%s type=%s\n",
2033 (int) UdmProgCompilerNextVarStackOffset(compiler),
2034 name, PIVar->handler->type_name);*/
2035
2036 data_size= UdmValueHandlerAlignedDataSize(UdmProgVarHandler(PIVar));
2037 if (UDM_OK != UdmProgCompilerNextVarStackOffsetIncrement(compiler, data_size) ||
2038 UDM_OK != UdmProgVarListAdd(Vars, name, &PIVar->value))
2039 return UDM_FALSE;
2040 return UDM_TRUE;
2041 }
2042
2043
2044 /**
2045 Create a named or a temporary variable on the last stack level.
2046 */
2047 static udm_bool_t
UdmGenerateDeclareNonInitializedVariable(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * PIVar)2048 UdmGenerateDeclareNonInitializedVariable(UDM_PROG_COMPILER *compiler,
2049 const UDM_PROG_VAR *PIVar)
2050 {
2051 char name[128];
2052 size_t name_length= UdmConstTokenLength(&PIVar->name);
2053 UDM_PROG_VARLIST *Vars= &compiler->Vars2.Item[compiler->Vars2.nitems - 1];
2054 if (name_length)
2055 udm_snprintf(name, sizeof(name), "%.*s",
2056 (int) (PIVar->name.end - PIVar->name.str), PIVar->name.str);
2057 else
2058 udm_snprintf(name, sizeof(name), "/tmp_%03X", (int) Vars->nitems);
2059 return UdmGenerateDeclareNonInitializedVariableWithName(compiler, Vars,
2060 PIVar, name);
2061 }
2062
2063
2064 static const UDM_PROG_VAR2 *
UdmProgCompilerFindVariable(UDM_PROG_COMPILER * compiler,UDM_CONST_TOKEN * str)2065 UdmProgCompilerFindVariable(UDM_PROG_COMPILER *compiler,
2066 UDM_CONST_TOKEN *str)
2067 {
2068 size_t i;
2069 char name[128]; /* TODO34: find by name+length */
2070 udm_snprintf(name, sizeof(name), "%.*s",
2071 (int) (str->end - str->str), str->str);
2072 for (i= compiler->Vars2.nitems; i > 0; i--)
2073 {
2074 const UDM_PROG_VAR2 *Var= UdmProgVarListFind(&compiler->Vars2.Item[i - 1],
2075 name);
2076 if (Var)
2077 return Var;
2078 }
2079 return NULL;
2080 }
2081
2082
2083 static udm_bool_t
ParseIdentifier(UDM_PROG_COMPILER * compiler,UDM_CONST_TOKEN * ident)2084 ParseIdentifier(UDM_PROG_COMPILER *compiler, UDM_CONST_TOKEN *ident)
2085 {
2086 if (UdmProgCompilerLastTokenType(compiler) == UDM_LEX_IDENT)
2087 *ident= compiler->scanner.token.token;
2088 return ParseTerm(compiler, UDM_LEX_IDENT);
2089 }
2090
2091
2092 static udm_bool_t
ParseUnsignedNumber(UDM_PROG_COMPILER * compiler,UDM_PROG_VAR * Var)2093 ParseUnsignedNumber(UDM_PROG_COMPILER *compiler, UDM_PROG_VAR *Var)
2094 {
2095 UDM_CONST_TOKEN exponent;
2096 if (UdmProgCompilerLastTokenType(compiler) != UDM_LEX_UINT)
2097 return UDM_FALSE;
2098 Var->name= compiler->scanner.token.token;
2099 UdmProgVarSetHandler(Var, &UdmValueHandlerInt);
2100 if (!ParseTerm(compiler, UDM_LEX_UINT))
2101 {
2102 UDM_ASSERT(0);
2103 return UDM_FALSE;
2104 }
2105 if (ParseTerm(compiler, UDM_LEX_DOT))
2106 {
2107 UdmProgVarSetHandler(Var, &UdmValueHandlerDouble);
2108 if (UdmProgCompilerLastTokenType(compiler) == UDM_LEX_UINT)
2109 {
2110 Var->name.end= compiler->scanner.token.token.end;
2111 if (!ParseTerm(compiler, UDM_LEX_UINT))
2112 {
2113 UDM_ASSERT(0);
2114 return UDM_FALSE;
2115 }
2116 }
2117 }
2118 if (UdmProgCompilerLastTokenType(compiler) != UDM_LEX_IDENT)
2119 return UDM_TRUE;
2120 UdmProgVarSetHandler(Var, &UdmValueHandlerDouble);
2121 exponent= compiler->scanner.token.token;
2122 UDM_ASSERT(exponent.end - exponent.str > 0);
2123 if (exponent.str[0] != 'E' && exponent.str[0] != 'e')
2124 return UDM_TRUE;
2125 if (!ParseTerm(compiler, UDM_LEX_IDENT))
2126 {
2127 UDM_ASSERT(0);
2128 return UDM_FALSE;
2129 }
2130 if (exponent.end - exponent.str > 1) /* e123 was scanned as UDM_LEX_IDENT*/
2131 {
2132 const char *e;
2133 if (!udm_isdigit(exponent.str[1]))
2134 return UdmProgCompilerExponentHasNoDigits(compiler);
2135 for (e= exponent.str + 2; e < exponent.end; e++)
2136 {
2137 if (!udm_isdigit(*e))
2138 {
2139 exponent.str= e;
2140 return UdmProgCompilerExponentInvalidSuffix(compiler, &exponent);
2141 }
2142 }
2143 Var->name.end= exponent.end;
2144 return UDM_TRUE;
2145 }
2146 if (!ParseTerm(compiler, UDM_LEX_MINUS) &&
2147 !ParseTerm(compiler, UDM_LEX_PLUS))
2148 return UdmProgCompilerExponentHasNoDigits(compiler); /* e.g. 123e; */
2149 if (UdmProgCompilerLastTokenType(compiler) != UDM_LEX_UINT)
2150 return UdmProgCompilerExponentHasNoDigits(compiler); /* e.g. 123e+; */
2151 Var->name.end= compiler->scanner.token.token.end;
2152 if (!ParseTerm(compiler, UDM_LEX_UINT))
2153 {
2154 UDM_ASSERT(0);
2155 return UDM_FALSE;
2156 }
2157 return UDM_TRUE;
2158 }
2159
2160
2161 static udm_bool_t
ParseString(UDM_PROG_COMPILER * compiler,UDM_CONST_TOKEN * string)2162 ParseString(UDM_PROG_COMPILER *compiler, UDM_CONST_TOKEN *string)
2163 {
2164 if (UdmProgCompilerLastTokenType(compiler) != UDM_LEX_STRING &&
2165 UdmProgCompilerLastTokenType(compiler) != UDM_LEX_ESCAPED_STRING)
2166 return UDM_FALSE;
2167 *string= compiler->scanner.token.token;
2168 UdmProgCompilerScan(compiler);
2169 return UDM_TRUE;
2170 }
2171
2172
2173 static udm_bool_t
ParseChar(UDM_PROG_COMPILER * compiler,UDM_CONST_TOKEN * string)2174 ParseChar(UDM_PROG_COMPILER *compiler, UDM_CONST_TOKEN *string)
2175 {
2176 if (UdmProgCompilerLastTokenType(compiler) == UDM_LEX_CHAR_LITERAL)
2177 {
2178 *string= compiler->scanner.token.token;
2179 if (UdmConstTokenLength(string) != 1 &&
2180 string->str[0] != '\\')
2181 return UdmProgCompilerErrorMultiCharacter(compiler);
2182 }
2183 return ParseTerm(compiler, UDM_LEX_CHAR_LITERAL);
2184 }
2185
2186
2187 static udm_bool_t
ParseLCB(UDM_PROG_COMPILER * compiler)2188 ParseLCB(UDM_PROG_COMPILER *compiler)
2189 {
2190 return ParseTerm(compiler, UDM_LEX_LCB);
2191 }
2192
2193
2194 static udm_bool_t
ParsePrimaryExpressionIdentifier(UDM_PROG_COMPILER * compiler,UDM_PROG_PRIMARY_EXPRESSION * expr)2195 ParsePrimaryExpressionIdentifier(UDM_PROG_COMPILER *compiler,
2196 UDM_PROG_PRIMARY_EXPRESSION *expr)
2197 {
2198 if (ParseIdentifier(compiler, &expr->Var.name))
2199 {
2200 const UDM_PROG_VAR2 *Var= UdmProgCompilerFindVariable(compiler,
2201 &expr->Var.name);
2202 if (Var)
2203 expr->Var.value= Var->value;
2204 else
2205 UDM_BZERO(&expr->Var.value, sizeof(expr->Var.value));
2206 expr->type= UDM_EXPRESSION_IDENT;
2207 return UDM_TRUE;
2208 }
2209 return UDM_FALSE;
2210 }
2211
2212
2213 static int
CharUnescape(int ch)2214 CharUnescape(int ch)
2215 {
2216 switch (ch)
2217 {
2218 case 'n': return '\n';
2219 case 'r': return '\r';
2220 case 't': return '\t';
2221 case '0': return '\0';
2222 }
2223 return ch;
2224 }
2225
2226
2227 static udm_bool_t
UdmCreateTextSegmentEntry(UDM_PROG_COMPILER * compiler,udm_offset_and_length_t * addr,const char * src,size_t length,udm_bool_t unescape,udm_bool_t append)2228 UdmCreateTextSegmentEntry(UDM_PROG_COMPILER *compiler,
2229 udm_offset_and_length_t *addr,
2230 const char *src, size_t length,
2231 udm_bool_t unescape,
2232 udm_bool_t append)
2233 {
2234 if (append)
2235 {
2236 UDM_ASSERT(UdmDSTRLength(&compiler->prg->textdata));
2237 UdmDSTRShrinkLast(&compiler->prg->textdata);
2238 }
2239 addr->offset= UdmDSTRLength(&compiler->prg->textdata);
2240 /*
2241 fprintf(stderr, "CREATE: pos=%d len=%d\n",
2242 (int) addr->offset,
2243 (int) length);
2244 */
2245 if (unescape)
2246 {
2247 const char *end;
2248 UdmDSTRReserve(&compiler->prg->textdata, length);
2249 for (end= src + length ; src < end; src++)
2250 {
2251 if (*src != '\\')
2252 UdmDSTRAppend(&compiler->prg->textdata, src, 1);
2253 else if (src + 1 < end)
2254 {
2255 char ch= CharUnescape(src[1]);
2256 UdmDSTRAppend(&compiler->prg->textdata, &ch, 1);
2257 src++;
2258 }
2259 }
2260 }
2261 else
2262 UdmDSTRAppend(&compiler->prg->textdata, src, length);
2263 addr->length= UdmDSTRLength(&compiler->prg->textdata) - addr->offset;
2264 UdmDSTRAppend(&compiler->prg->textdata, "\0", 1);
2265 return UDM_TRUE;
2266 }
2267
2268
2269 static udm_bool_t
UdmProgGenerateCoutStringFromTextSegment(UDM_PROG_COMPILER * compiler,udm_offset_and_length_t addr)2270 UdmProgGenerateCoutStringFromTextSegment(UDM_PROG_COMPILER *compiler,
2271 udm_offset_and_length_t addr)
2272 {
2273 return UdmGenerateTextSegmentTo_cs0_z0(compiler, addr) &&
2274 UDM_OK == UdmProgAddArg0Simple(compiler->prg, &udm_tmpl_cout_cs0_z0);
2275 }
2276
2277
2278 static udm_bool_t
UdmProgGenerateCoutText(UDM_PROG_COMPILER * compiler,const char * str,const char * strend,udm_bool_t unescape)2279 UdmProgGenerateCoutText(UDM_PROG_COMPILER *compiler,
2280 const char *str,
2281 const char *strend,
2282 udm_bool_t unescape)
2283 {
2284 if (str && str != strend)
2285 {
2286 udm_offset_and_length_t addr;
2287 UdmCreateTextSegmentEntry(compiler, &addr, str, strend - str, unescape, UDM_FALSE);
2288 return UdmProgGenerateCoutStringFromTextSegment(compiler, addr);
2289 }
2290 return UDM_OK;
2291 }
2292
2293
2294 static udm_bool_t
ParsePrimaryExpressionString(UDM_PROG_COMPILER * compiler,UDM_PROG_PRIMARY_EXPRESSION * expr)2295 ParsePrimaryExpressionString(UDM_PROG_COMPILER *compiler, UDM_PROG_PRIMARY_EXPRESSION *expr)
2296 {
2297 UDM_CONST_TOKEN chunk;
2298 udm_offset_and_length_t addr;
2299 if (!ParseString(compiler, &expr->Var.name))
2300 return UDM_FALSE;
2301 expr->type= UDM_EXPRESSION_CONST;
2302 UdmProgVarSetHandler(&expr->Var, &UdmValueHandlerSimple);
2303 if (!UdmCreateTextSegmentEntry(compiler, &expr->textdata_addr,
2304 expr->Var.name.str,
2305 expr->Var.name.end - expr->Var.name.str,
2306 UDM_TRUE, UDM_FALSE))
2307 return UDM_FALSE;
2308 while (ParseString(compiler, &chunk))
2309 {
2310 if (!UdmCreateTextSegmentEntry(compiler, &addr,
2311 chunk.str, chunk.end - chunk.str,
2312 UDM_TRUE, UDM_TRUE))
2313 return UDM_FALSE;
2314 expr->textdata_addr.length+= addr.length;
2315 }
2316 return UDM_TRUE;
2317 }
2318
2319
2320 static udm_bool_t
ParsePrimaryExpressionUnsignedNumber(UDM_PROG_COMPILER * compiler,UDM_PROG_PRIMARY_EXPRESSION * expr)2321 ParsePrimaryExpressionUnsignedNumber(UDM_PROG_COMPILER *compiler,
2322 UDM_PROG_PRIMARY_EXPRESSION *expr)
2323 {
2324 if (!ParseUnsignedNumber(compiler, &expr->Var))
2325 return UDM_FALSE;
2326 expr->type= UDM_EXPRESSION_CONST;
2327 return UdmCreateTextSegmentEntry(compiler, &expr->textdata_addr,
2328 expr->Var.name.str,
2329 expr->Var.name.end - expr->Var.name.str,
2330 UDM_FALSE, UDM_FALSE);
2331 }
2332
2333
2334 static void
CharToStr(char * dst,const UDM_CONST_TOKEN * src)2335 CharToStr(char *dst, const UDM_CONST_TOKEN *src)
2336 {
2337 UDM_ASSERT(UdmConstTokenLength(src) > 0);
2338 if (src->str[0] == '\\')
2339 {
2340 UDM_ASSERT(UdmConstTokenLength(src) > 1);
2341 dst[0]= CharUnescape(src->str[1]);
2342 }
2343 else
2344 dst[0]= src->str[0];
2345 dst[1]= '\0';
2346 }
2347
2348
2349 static udm_bool_t
ParsePrimaryExpressionChar(UDM_PROG_COMPILER * compiler,UDM_PROG_PRIMARY_EXPRESSION * expr)2350 ParsePrimaryExpressionChar(UDM_PROG_COMPILER *compiler,
2351 UDM_PROG_PRIMARY_EXPRESSION *expr)
2352 {
2353 if (!ParseChar(compiler, &expr->Var.name))
2354 return UDM_FALSE;
2355 CharToStr(expr->buf, &expr->Var.name);
2356 expr->Var.name.str= expr->buf;
2357 expr->Var.name.end= expr->buf + 1;
2358 expr->type= UDM_EXPRESSION_CONST;
2359 UdmProgVarSetHandler(&expr->Var, &UdmValueHandlerChar);
2360 return UdmCreateTextSegmentEntry(compiler, &expr->textdata_addr,
2361 expr->Var.name.str, 1,
2362 UDM_FALSE, UDM_FALSE);
2363 }
2364
2365
2366 /*
2367 <primary-expression> ::= <identifier>
2368 | <constant>
2369 | <string>
2370 | ( <expression> )
2371 */
2372 static udm_bool_t
ParsePrimaryExpressionLiteral(UDM_PROG_COMPILER * compiler,UDM_PROG_PRIMARY_EXPRESSION * expr)2373 ParsePrimaryExpressionLiteral(UDM_PROG_COMPILER *compiler,
2374 UDM_PROG_PRIMARY_EXPRESSION *expr)
2375 {
2376 if (ParsePrimaryExpressionString(compiler, expr))
2377 return UDM_TRUE;
2378 if (ParsePrimaryExpressionChar(compiler, expr))
2379 return UDM_TRUE;
2380 if (ParsePrimaryExpressionUnsignedNumber(compiler, expr))
2381 return UDM_TRUE;
2382 return UDM_FALSE;
2383 }
2384
2385 /*
2386 TODO: move parsing of parenthesized expression to here.
2387 */
2388 static udm_bool_t
ParsePrimaryExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_PRIMARY_EXPRESSION * expr)2389 ParsePrimaryExpression(UDM_PROG_COMPILER *compiler, UDM_PROG_PRIMARY_EXPRESSION *expr)
2390 {
2391 if (ParsePrimaryExpressionIdentifier(compiler, expr))
2392 return UDM_TRUE;
2393 if (ParsePrimaryExpressionLiteral(compiler, expr))
2394 return UDM_TRUE;
2395 return UDM_FALSE;
2396 }
2397
2398
2399 /*
2400 <function-call-argument> ::= <assignment-expression>
2401 */
2402 static udm_bool_t
ParseFunctionCallArgument(UDM_PROG_COMPILER * compiler,UDM_PROG_PRIMARY_EXPRESSION * expr)2403 ParseFunctionCallArgument(UDM_PROG_COMPILER *compiler,
2404 UDM_PROG_PRIMARY_EXPRESSION *expr)
2405 {
2406 if (ParsePrimaryExpressionIdentifier(compiler, expr))
2407 {
2408 if (!UdmPrimaryExprHandler(expr))
2409 return UdmProgCompilerUnknownIdentifierError(compiler, &expr->Var.name);
2410 return UDM_TRUE;
2411 }
2412 return ParsePrimaryExpressionLiteral(compiler, expr);
2413 }
2414
2415
2416 /*
2417 <function-call-argument> ::= <assignment-expression>
2418
2419 <function-call-argument-list> ::= <function-call-argument>
2420 {',' <function-call-argument>}*
2421
2422 <function-call-arguments> ::= '(' <function-call-argument-list>? ')'
2423 | '(' ')'
2424 */
2425 static udm_bool_t
ParseFunctionCallArguments(UDM_PROG_COMPILER * compiler,UDM_PROG_FUNCTION_CALL_ARGUMENTS * func)2426 ParseFunctionCallArguments(UDM_PROG_COMPILER *compiler,
2427 UDM_PROG_FUNCTION_CALL_ARGUMENTS *func)
2428 {
2429 if (!ParseTerm(compiler, UDM_LEX_LP))
2430 return UDM_FALSE;
2431 func->nargs= 0;
2432 if (!ParseFunctionCallArgument(compiler, &func->args[0]))
2433 {
2434 if (UdmProgCompilerError(compiler))
2435 return UDM_FALSE;
2436 goto rp;
2437 }
2438 func->nargs= 1;
2439 for ( ; ; )
2440 {
2441 if (!ParseTerm(compiler, UDM_LEX_COMMA))
2442 break;
2443 if (func->nargs >= UDM_PROG_MAXARG)
2444 {
2445 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
2446 "In <function-call-arguments>: Too many arguments");
2447 return UDM_FALSE;
2448 }
2449 func->nargs++;
2450 if (!ParseFunctionCallArgument(compiler, &func->args[func->nargs - 1]))
2451 return UdmProgCompilerExpectedRule(compiler, "<function-call-argument>");
2452 }
2453 rp:
2454 return ParseTermOrError(compiler, UDM_LEX_RP);
2455 }
2456
2457
2458 /**
2459 Check if a function prototype is compatible with the actual paramenter.
2460 Returns UDM_TRUE on failure (incompatible)
2461 Returns UDM_FALSE on success (compatible)
2462 */
2463 static udm_bool_t
UdmFunctionPrototypeCheck(const UDM_FUNCTION_PROTOTYPE * prototype,const UDM_PROG_FUNCTION_CALL_ARGUMENTS * arglist,size_t offset)2464 UdmFunctionPrototypeCheck(const UDM_FUNCTION_PROTOTYPE *prototype,
2465 const UDM_PROG_FUNCTION_CALL_ARGUMENTS *arglist,
2466 size_t offset)
2467 {
2468 size_t i;
2469 for (i= 0; i < arglist->nargs; i++)
2470 {
2471 if (prototype->args[i + offset].handler !=
2472 UdmPrimaryExprHandler(&arglist->args[i]))
2473 return UDM_TRUE;
2474 }
2475 return UDM_FALSE;
2476 }
2477
2478
2479 static const UDM_FUNCTION *
UdmFunctionListFind(const UDM_FUNCTION * functions,const char * name,size_t length,const UDM_VALUE_HANDLER * handler_for_this,const UDM_PROG_FUNCTION_CALL_ARGUMENTS * arglist,size_t offset)2480 UdmFunctionListFind(const UDM_FUNCTION *functions,
2481 const char *name, size_t length,
2482 const UDM_VALUE_HANDLER *handler_for_this,
2483 const UDM_PROG_FUNCTION_CALL_ARGUMENTS *arglist,
2484 size_t offset /* 0, or 1 in case of method */)
2485 {
2486 const UDM_FUNCTION *method;
2487 for (method= functions; method->name.str; method++)
2488 {
2489 if (handler_for_this &&
2490 handler_for_this != method->prototype.args[0].handler)
2491 continue;
2492 if (method->prototype.nargs == arglist->nargs + offset &&
2493 method->name.length == length &&
2494 !memcmp(method->name.str, name, length) &&
2495 !UdmFunctionPrototypeCheck(&method->prototype, arglist, offset))
2496 return method;
2497 }
2498 return NULL;
2499 }
2500
2501
2502 static const UDM_FUNCTION *
UdmValueHandlerMethodFind(const UDM_VALUE_HANDLER * ha,const char * name,size_t length,const UDM_PROG_FUNCTION_CALL_ARGUMENTS * arglist)2503 UdmValueHandlerMethodFind(const UDM_VALUE_HANDLER *ha,
2504 const char *name, size_t length,
2505 const UDM_PROG_FUNCTION_CALL_ARGUMENTS *arglist)
2506 {
2507 if (!ha->method)
2508 return NULL;
2509 return UdmFunctionListFind(ha->method, name, length, ha, arglist, 1);
2510 }
2511
2512
2513 typedef struct
2514 {
2515 udm_tmpl_cmd_t create_ident;
2516 UDM_PROG_CMD *create_value;
2517 UDM_PROG_CMD *delete_value;
2518 UDM_PROG_CMD *clear_value;
2519 } UDM_CALL_ARG_CMD;
2520
2521
2522 #define UDM_MAX_FUNC_ARG 5
2523
2524 static UDM_CALL_ARG_CMD call_arg_cmd[UDM_MAX_FUNC_ARG]=
2525 {
2526 {
2527 UDM_PROG_MOV_VREG0_STACK_OFFSET,
2528 &udm_method_make_arg0,
2529 &udm_method_free_arg0,
2530 &udm_method_clear_arg0
2531 },
2532 {
2533 UDM_PROG_MOV_VREG1_STACK_OFFSET,
2534 &udm_method_make_arg1,
2535 &udm_method_free_arg1,
2536 &udm_method_clear_arg1
2537 },
2538 {
2539 UDM_PROG_MOV_VREG2_STACK_OFFSET,
2540 &udm_method_make_arg2,
2541 &udm_method_free_arg2,
2542 &udm_method_clear_arg2
2543 },
2544 {
2545 UDM_PROG_MOV_VREG3_STACK_OFFSET,
2546 &udm_method_make_arg3,
2547 &udm_method_free_arg3,
2548 &udm_method_clear_arg3
2549 },
2550 {
2551 UDM_PROG_MOV_VREG4_STACK_OFFSET,
2552 &udm_method_make_arg4,
2553 &udm_method_free_arg4,
2554 &udm_method_clear_arg4
2555 }
2556 };
2557
2558
2559 /*
2560 Create a temporary value.
2561 */
2562 static udm_bool_t
UdmGenerateFunctionCallArgCreate(UDM_PROG_COMPILER * compiler,const UDM_PROG_PRIMARY_EXPRESSION * arg,size_t offset)2563 UdmGenerateFunctionCallArgCreate(UDM_PROG_COMPILER *compiler,
2564 const UDM_PROG_PRIMARY_EXPRESSION *arg,
2565 size_t offset)
2566 {
2567 UDM_PROG_ITEM item;
2568 UdmProgItemInit(&item);
2569 if (arg->type == UDM_EXPRESSION_IDENT)
2570 {
2571 return UdmGenerateOpOffset(compiler, call_arg_cmd[offset].create_ident,
2572 arg->Var.value.stack_offset);
2573 }
2574 else
2575 {
2576 item.cmd= call_arg_cmd[offset].create_value;
2577 UdmProgItemArgInitFromLiteralAndHandler(&item.item_args, arg);
2578 }
2579 return UDM_OK == UdmProgAdd(compiler->prg, &item);
2580 }
2581
2582
2583 /*
2584 Setup a pointer to a variable, or create a temporary value.
2585 */
2586 static udm_bool_t
UdmGenerateFunctionCallArgSetup(UDM_PROG_COMPILER * compiler,const UDM_FUNCTION * func,const UDM_PROG_PRIMARY_EXPRESSION * arg,size_t argno)2587 UdmGenerateFunctionCallArgSetup(UDM_PROG_COMPILER *compiler,
2588 const UDM_FUNCTION *func,
2589 const UDM_PROG_PRIMARY_EXPRESSION *arg,
2590 size_t argno)
2591 {
2592 if (arg->type == UDM_EXPRESSION_IDENT)
2593 {
2594 if (!UdmPrimaryExprHandler(arg))
2595 return UdmProgCompilerUnknownIdentifierError(compiler, &arg->Var.name);
2596 }
2597 if (func->prototype.args[argno].handler != UdmPrimaryExprHandler(arg))
2598 {
2599 return UdmProgCompilerBadDataTypeForArg(compiler, argno,
2600 func->prototype.args[argno].handler,
2601 UdmPrimaryExprHandler(arg));
2602 }
2603 return UdmGenerateFunctionCallArgCreate(compiler, arg, argno);
2604 }
2605
2606
2607 static udm_bool_t
UdmGenerateFunctionCallArgDelete(UDM_PROG_COMPILER * compiler,const UDM_PROG_PRIMARY_EXPRESSION * arg,size_t offset)2608 UdmGenerateFunctionCallArgDelete(UDM_PROG_COMPILER *compiler,
2609 const UDM_PROG_PRIMARY_EXPRESSION *arg,
2610 size_t offset)
2611 {
2612 UDM_PROG_ITEM item;
2613 UdmProgItemInit(&item);
2614 item.cmd= arg->type == UDM_EXPRESSION_IDENT ?
2615 call_arg_cmd[offset].clear_value :
2616 call_arg_cmd[offset].delete_value;
2617 if (arg->type != UDM_EXPRESSION_IDENT)
2618 item.item_args.handler= UdmPrimaryExprHandler(arg);
2619 /*item.item_args.stack_offset= arg->Var.value.stack_offset;*/
2620 return UDM_OK == UdmProgAdd(compiler->prg, &item);
2621 }
2622
2623
2624 /**
2625 Returns UDM_TRUE if a function returning a value
2626 of the handler requires an object.
2627 Returns UDM_FALSE if the function can simply return
2628 the value in registers.
2629 */
2630 static udm_bool_t
UdmValueHandlerIsComplex(const UDM_VALUE_HANDLER * handler)2631 UdmValueHandlerIsComplex(const UDM_VALUE_HANDLER *handler)
2632 {
2633 switch (handler->datatype)
2634 {
2635 case UDM_VALUE_DATA_TYPE_INT:
2636 case UDM_VALUE_DATA_TYPE_DOUBLE:
2637 case UDM_VALUE_DATA_TYPE_CHAR:
2638 return UDM_FALSE;
2639 case UDM_VALUE_DATA_TYPE_STR:
2640 case UDM_VALUE_DATA_TYPE_ENV:
2641 case UDM_VALUE_DATA_TYPE_RESULT:
2642 case UDM_VALUE_DATA_TYPE_DOCUMENT:
2643 case UDM_VALUE_DATA_TYPE_SQLRESULT:
2644 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
2645 break;
2646 }
2647 return UDM_TRUE;
2648 }
2649
2650
2651 /**
2652 Initialize everything but name.
2653 */
2654 static void
UdmProgStackVarInitAttributes(UDM_PROG_VAR * Var,UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * handler)2655 UdmProgStackVarInitAttributes(UDM_PROG_VAR *Var,
2656 UDM_PROG_COMPILER *compiler,
2657 const UDM_VALUE_HANDLER *handler)
2658 {
2659 UdmProgVarSetHandler(Var, handler);
2660 Var->value.stack_offset= UdmProgCompilerNextVarStackOffset(compiler);
2661 }
2662
2663
2664 /**
2665 Construct a temporary variable on stack.
2666 Return its address on result->stack_offset.
2667 */
2668 static udm_bool_t
UdmGenerateReserveNonInitializedTemporaryVariableOnStack(UDM_PROG_COMPILER * c,const UDM_VALUE_HANDLER * handler,UDM_PROG_VAR * result)2669 UdmGenerateReserveNonInitializedTemporaryVariableOnStack(UDM_PROG_COMPILER *c,
2670 const UDM_VALUE_HANDLER *handler,
2671 UDM_PROG_VAR *result)
2672 {
2673 UDM_BZERO(&result->name, sizeof(result->name));
2674 UdmProgStackVarInitAttributes(result, c, handler);
2675 if (!UdmGenerateDeclareNonInitializedVariable(c, result))
2676 return UDM_FALSE;
2677 if (UDM_OK != UdmProgAddValueHandler(c->prg, UDM_PROG_MOV_HREG0_PTR,
2678 handler))
2679 return UDM_FALSE;
2680 if (!UdmGenerateOpOffset(c, UDM_PROG_MOV_SREG0_STACK_OFFSET,
2681 result->value.stack_offset))
2682 return UDM_FALSE;
2683 return UDM_TRUE;
2684 }
2685
2686
2687 static udm_bool_t
UdmGenerateFunctionReturnValue(UDM_PROG_COMPILER * compiler,const UDM_FUNCTION * func,UDM_PROG_VAR * result,const UDM_PROG_VAR * dstvar)2688 UdmGenerateFunctionReturnValue(UDM_PROG_COMPILER *compiler,
2689 const UDM_FUNCTION *func,
2690 UDM_PROG_VAR *result,
2691 const UDM_PROG_VAR *dstvar)
2692 {
2693 /*
2694 TODO34: a better test for this. Perhaps a method in handler.
2695 */
2696
2697 if (func->prototype.result.handler &&
2698 UdmValueHandlerIsComplex(func->prototype.result.handler))
2699 {
2700 if (!(!result ^ !dstvar))
2701 {
2702 /*
2703 Called from UdmParseConditionalExpression,
2704 with both result==NULL and dstvar==NULL.
2705 */
2706 /*UDM_ASSERT(0);*/
2707 return UdmProgCompilerNotSupported(compiler, "function call of this type in this context (e.g. in a conditional expression)");
2708 }
2709 UDM_ASSERT(!result ^ !dstvar); /* At least on of them should be set */
2710 if (dstvar) /* string x= str.upper(); */
2711 {
2712 if (func->prototype.result.handler != UdmProgVarHandler(dstvar))
2713 return UdmCompilerErrorInvalidOperands(compiler,
2714 func->prototype.result.handler,
2715 UdmProgVarHandler(dstvar), "=");
2716 if (UDM_OK != UdmProgAddValueHandler(compiler->prg, UDM_PROG_MOV_HREG0_PTR,
2717 func->prototype.result.handler))
2718 return UDM_FALSE;
2719 if (!UdmGenerateOpOffset(compiler, UDM_PROG_MOV_SREG0_STACK_OFFSET,
2720 dstvar->value.stack_offset))
2721 return UDM_FALSE;
2722 }
2723 else if (result) /* Want complex return value on stack rather than to be alloced */
2724 {
2725 UDM_ASSERT(!UdmProgVarHandler(result)); /* Must be initialized */
2726 if (!UdmGenerateReserveNonInitializedTemporaryVariableOnStack(compiler,
2727 func->prototype.result.handler,
2728 result))
2729 return UDM_FALSE;
2730 }
2731 }
2732 return UDM_TRUE;
2733 }
2734
2735
2736 static udm_bool_t
UdmGenerateFunctionArgsSetup(UDM_PROG_COMPILER * compiler,const UDM_FUNCTION * func,const UDM_PROG_FUNCTION_CALL_ARGUMENTS * arglist,size_t offset)2737 UdmGenerateFunctionArgsSetup(UDM_PROG_COMPILER *compiler,
2738 const UDM_FUNCTION *func,
2739 const UDM_PROG_FUNCTION_CALL_ARGUMENTS *arglist,
2740 size_t offset)
2741 {
2742 size_t i;
2743 for (i= 0; i < arglist->nargs && i < UDM_MAX_FUNC_ARG; i++)
2744 {
2745 if (!UdmGenerateFunctionCallArgSetup(compiler, func,
2746 &arglist->args[i], i + offset))
2747 return UDM_FALSE;
2748 }
2749 return UDM_TRUE;
2750 }
2751
2752
2753 static udm_bool_t
UdmGenerateFunctionArgsDelete(UDM_PROG_COMPILER * compiler,const UDM_FUNCTION * func,const UDM_PROG_FUNCTION_CALL_ARGUMENTS * arglist,size_t offset)2754 UdmGenerateFunctionArgsDelete(UDM_PROG_COMPILER *compiler,
2755 const UDM_FUNCTION *func,
2756 const UDM_PROG_FUNCTION_CALL_ARGUMENTS *arglist,
2757 size_t offset)
2758 {
2759 size_t i;
2760 for (i= 0; i < arglist->nargs && i < UDM_MAX_FUNC_ARG; i++)
2761 {
2762 if (!UdmGenerateFunctionCallArgDelete(compiler,
2763 &arglist->args[i], i + offset))
2764 return UDM_FALSE;
2765 }
2766 return UDM_TRUE;
2767 }
2768
2769
2770 static udm_bool_t
UdmGenerateCallInstruction(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * classhandler,const UDM_FUNCTION * func)2771 UdmGenerateCallInstruction(UDM_PROG_COMPILER *compiler,
2772 const UDM_VALUE_HANDLER *classhandler,
2773 const UDM_FUNCTION *func)
2774 {
2775 UDM_PROG_ITEM item;
2776 char comment[128];
2777 UdmProgItemInit(&item);
2778 item.cmdarg.func= func;
2779 item.cmdnum= UDM_PROG_CALL;
2780 udm_snprintf(comment, sizeof(comment), "%s::%.*s()",
2781 classhandler ?
2782 classhandler->type_name : "",
2783 (int) func->name.length, func->name.str);
2784 return UDM_OK == UdmProgAdd(compiler->prg, &item);
2785 }
2786
2787
2788 /*
2789 @param [OUT] result - non-NULL means that we want the result on stack.
2790 A new stack variable is created and
2791 is returned in result[0].
2792 NULL means that we want the result on heap in (h0,s0).
2793 @param dstvar - non-NULL if the function call is directly assigned
2794 to a variable:
2795 string x= str.upper();
2796 A new variable is not created in this case,
2797 neither on stack, nor on heap.
2798
2799 Function call returns resuts as follows:
2800 - INT is returned in i0
2801 - DOUBLE is returned in d0
2802 - Other datatypes are returned in the register pair (h0,s0),
2803 where h0 stores the pointer to the data type handler,
2804 and s0 stores the pointer to the data.
2805 */
2806 static udm_bool_t
UdmGenerateNewFunctionCall(UDM_PROG_COMPILER * compiler,const UDM_FUNCTION * func,const UDM_PROG_VAR * thisptr,const UDM_PROG_FUNCTION_CALL_ARGUMENTS * arglist,UDM_PROG_VAR * result,const UDM_PROG_VAR * dstvar)2807 UdmGenerateNewFunctionCall(UDM_PROG_COMPILER *compiler,
2808 const UDM_FUNCTION *func,
2809 const UDM_PROG_VAR *thisptr,
2810 const UDM_PROG_FUNCTION_CALL_ARGUMENTS *arglist,
2811 UDM_PROG_VAR *result,
2812 const UDM_PROG_VAR *dstvar)
2813 {
2814 size_t offset= thisptr ? 1 : 0; /* 1 means method, 0 means function */
2815 if (!UdmGenerateFunctionReturnValue(compiler, func, result, dstvar))
2816 return UDM_FALSE;
2817
2818 if (thisptr)
2819 {
2820 /* Pass "this" as the first arg */
2821 if (!UdmGenerateOpOffset(compiler, UDM_PROG_MOV_VREG0_STACK_OFFSET,
2822 thisptr->value.stack_offset))
2823 return UDM_FALSE;
2824 }
2825 if (!UdmGenerateFunctionArgsSetup(compiler, func, arglist, offset))
2826 return UDM_FALSE;
2827
2828 if (!UdmGenerateCallInstruction(compiler,
2829 thisptr ?
2830 UdmProgVarHandler(thisptr) : NULL, func))
2831 return UDM_FALSE;
2832
2833 if (!UdmGenerateFunctionArgsDelete(compiler, func, arglist, offset))
2834 return UDM_FALSE;
2835
2836 if (thisptr)
2837 {
2838 if (UDM_OK != UdmProgAddArg0Simple(compiler->prg, &udm_method_clear_arg0))
2839 return UDM_FALSE;
2840 }
2841 if (func->func == UdmFunction_exit)
2842 {
2843 if (!UdmProgCompilerGenerateVarListListDestructors(compiler))
2844 return UDM_FALSE;
2845 UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_EXIT);
2846 }
2847 return UDM_TRUE;
2848 }
2849
2850
2851 static udm_bool_t
UdmGenerateFunctionCall(UDM_PROG_COMPILER * compiler,const UDM_CONST_TOKEN * name,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)2852 UdmGenerateFunctionCall(UDM_PROG_COMPILER *compiler,
2853 const UDM_CONST_TOKEN *name,
2854 UDM_PROG_EXPRESSION *expr,
2855 UDM_PROG_VAR *complex_func_result_on_stack,
2856 const UDM_PROG_VAR *dstvar)
2857 {
2858 const UDM_FUNCTION *func2;
2859 if (!(func2= UdmFunctionListFind(udm_builtin_functions,
2860 name->str, name->end - name->str,
2861 NULL, &expr->arglist, 0)))
2862 return UdmProgCompilerErrorUnknownFunction(compiler, name, &expr->arglist);
2863 if (!UdmGenerateNewFunctionCall(compiler, func2,
2864 NULL, &expr->arglist,
2865 complex_func_result_on_stack, dstvar))
2866 return UDM_FALSE;
2867 UdmExprSetHandler(expr, func2->prototype.result.handler);
2868 expr->primary_expr.type= UDM_EXPRESSION_OBJECT;
2869 return UDM_TRUE;
2870 }
2871
2872
2873 static udm_bool_t
UdmGenerateMethodCall(UDM_PROG_COMPILER * compiler,const UDM_CONST_TOKEN * name,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)2874 UdmGenerateMethodCall(UDM_PROG_COMPILER *compiler,
2875 const UDM_CONST_TOKEN *name,
2876 UDM_PROG_EXPRESSION *expr,
2877 UDM_PROG_VAR *complex_func_result_on_stack,
2878 const UDM_PROG_VAR *dstvar)
2879 {
2880 const UDM_FUNCTION *method;
2881
2882 if (!(method= UdmValueHandlerMethodFind(UdmExprHandler(expr),
2883 name->str, name->end - name->str,
2884 &expr->arglist)))
2885 return UdmProgCompilerUnknownMethodError(compiler, UdmExprHandler(expr),
2886 name, &expr->arglist);
2887 if (!UdmGenerateNewFunctionCall(compiler, method,
2888 &expr->primary_expr.Var, &expr->arglist,
2889 complex_func_result_on_stack, dstvar))
2890 return UDM_FALSE;
2891 UdmExprSetHandler(expr, method->prototype.result.handler);
2892 expr->primary_expr.type= UDM_EXPRESSION_OBJECT;
2893 return UDM_TRUE;
2894 }
2895
2896
2897 static udm_bool_t
UdmGenerateStackVarIncrement(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var)2898 UdmGenerateStackVarIncrement(UDM_PROG_COMPILER *compiler, const UDM_PROG_VAR *Var)
2899 {
2900 if (!UdmUnaryOperatorFindWithError(compiler, unary_operators,
2901 UDM_UNARY_OPERATOR_POSTFIX_INC,
2902 UdmProgVarHandler(Var), "++"))
2903 return UDM_FALSE;
2904 switch (UdmProgVarHandler(Var)->datatype)
2905 {
2906 case UDM_VALUE_DATA_TYPE_INT:
2907 return UdmGenerateVariableOp(compiler, Var, UDM_PROG_INC_INT_PTR_STACK_OFFSET);
2908 case UDM_VALUE_DATA_TYPE_DOUBLE:
2909 return UdmGenerateVariableOp(compiler, Var, UDM_PROG_INC_DBL_PTR_STACK_OFFSET);
2910 case UDM_VALUE_DATA_TYPE_CHAR:
2911 return UdmGenerateVariableOp(compiler, Var, UDM_PROG_INC_CHR_PTR_STACK_OFFSET);
2912 case UDM_VALUE_DATA_TYPE_STR:
2913 case UDM_VALUE_DATA_TYPE_ENV:
2914 case UDM_VALUE_DATA_TYPE_RESULT:
2915 case UDM_VALUE_DATA_TYPE_DOCUMENT:
2916 case UDM_VALUE_DATA_TYPE_SQLRESULT:
2917 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
2918 break;
2919 }
2920 UDM_ASSERT(0);
2921 return UDM_TRUE;
2922 }
2923
2924
2925 static udm_bool_t
UdmGenerateStackVarDecrement(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var)2926 UdmGenerateStackVarDecrement(UDM_PROG_COMPILER *compiler, const UDM_PROG_VAR *Var)
2927 {
2928 if (!UdmUnaryOperatorFindWithError(compiler, unary_operators,
2929 UDM_UNARY_OPERATOR_POSTFIX_DEC,
2930 UdmProgVarHandler(Var), "--"))
2931 return UDM_FALSE;
2932 switch (UdmProgVarHandler(Var)->datatype)
2933 {
2934 case UDM_VALUE_DATA_TYPE_INT:
2935 return UdmGenerateVariableOp(compiler, Var, UDM_PROG_DEC_INT_PTR_STACK_OFFSET);
2936 case UDM_VALUE_DATA_TYPE_DOUBLE:
2937 return UdmGenerateVariableOp(compiler, Var, UDM_PROG_DEC_DBL_PTR_STACK_OFFSET);
2938 case UDM_VALUE_DATA_TYPE_CHAR:
2939 return UdmGenerateVariableOp(compiler, Var, UDM_PROG_DEC_CHR_PTR_STACK_OFFSET);
2940 case UDM_VALUE_DATA_TYPE_STR:
2941 case UDM_VALUE_DATA_TYPE_ENV:
2942 case UDM_VALUE_DATA_TYPE_RESULT:
2943 case UDM_VALUE_DATA_TYPE_DOCUMENT:
2944 case UDM_VALUE_DATA_TYPE_SQLRESULT:
2945 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
2946 break;
2947 }
2948 UDM_ASSERT(0);
2949 return UDM_TRUE;
2950 }
2951
2952
2953 static udm_bool_t
UdmGenerateStackVarIncOrDec(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var,udm_lex_t op)2954 UdmGenerateStackVarIncOrDec(UDM_PROG_COMPILER *compiler,
2955 const UDM_PROG_VAR *Var,
2956 udm_lex_t op)
2957 {
2958 if (op == UDM_LEX_INC)
2959 return UdmGenerateStackVarIncrement(compiler, Var);
2960 if (op == UDM_LEX_DEC)
2961 return UdmGenerateStackVarDecrement(compiler, Var);
2962 UDM_ASSERT(0);
2963 return UDM_FALSE;
2964 }
2965
2966
2967 /*
2968 <postfix-expression-part2> ::= '[' <expression> ']'
2969 | <function-call-arguments>
2970 | '.' <identifier>
2971 | '->' <identifier>
2972 | '++'
2973 | '--'
2974 */
2975 static udm_bool_t
ParsePostfixExpressionVarPart2(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr)2976 ParsePostfixExpressionVarPart2(UDM_PROG_COMPILER *compiler,
2977 UDM_PROG_EXPRESSION *expr)
2978 {
2979 udm_lex_t cmd;
2980 if (ParseTerm(compiler, (cmd= UDM_LEX_INC)) ||
2981 ParseTerm(compiler, (cmd= UDM_LEX_DEC)))
2982 {
2983 expr->primary_expr.type= UDM_EXPRESSION_COMPUTED;
2984 return
2985 UdmGenerateVarToNativeReg0(compiler, &expr->primary_expr.Var) &&
2986 UdmGenerateStackVarIncOrDec(compiler, &expr->primary_expr.Var, cmd);
2987 }
2988 return UDM_TRUE;
2989 }
2990
2991
2992 static udm_bool_t
2993 UdmParseExpression(UDM_PROG_COMPILER *compiler,
2994 UDM_PROG_EXPRESSION *expr,
2995 UDM_PROG_VAR *complex_result_on_stack,
2996 const UDM_PROG_VAR *dstvar);
2997
2998 static udm_bool_t
ParseParenthesizedExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)2999 ParseParenthesizedExpression(UDM_PROG_COMPILER *compiler,
3000 UDM_PROG_EXPRESSION *expr,
3001 UDM_PROG_VAR *complex_func_result_on_stack,
3002 const UDM_PROG_VAR *dstvar)
3003 {
3004 if (TestParenthesizedTypeSpecifier(compiler))
3005 return UDM_FALSE; /* This is a type cast, e.g.: y= (int) x; */
3006 if (!ParseTerm(compiler, UDM_LEX_LP))
3007 return UDM_FALSE;
3008 if (!UdmParseExpression(compiler, expr,
3009 complex_func_result_on_stack, dstvar))
3010 return UDM_FALSE;
3011 return ParseTermOrError(compiler, UDM_LEX_RP);
3012 }
3013
3014
3015 static udm_bool_t
UdmParseMemberAccess(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3016 UdmParseMemberAccess(UDM_PROG_COMPILER *compiler,
3017 UDM_PROG_EXPRESSION *expr,
3018 UDM_PROG_VAR *complex_func_result_on_stack,
3019 const UDM_PROG_VAR *dstvar)
3020 {
3021 UDM_CONST_TOKEN name;
3022 if (ParseTerm(compiler, UDM_LEX_OPERATOR))
3023 {
3024 if (!ParseTermOrError(compiler, UDM_LEX_EQ))
3025 return UDM_FALSE;
3026 UdmConstTokenSet(&name, UDM_CSTR_WITH_LEN("operator="));
3027 }
3028 else if (!ParseIdentifier(compiler, &name))
3029 return UdmProgCompilerExpectedRule(compiler, "<method-name> or `operator`");
3030 if (!ParseFunctionCallArguments(compiler, &expr->arglist))
3031 return UDM_FALSE;
3032 return UdmGenerateMethodCall(compiler, &name, expr,
3033 complex_func_result_on_stack, dstvar);
3034 }
3035
3036
3037 static void
UdmPrepareFunctionResultForMethodCall(UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack)3038 UdmPrepareFunctionResultForMethodCall(UDM_PROG_EXPRESSION *expr,
3039 UDM_PROG_VAR *complex_func_result_on_stack)
3040 {
3041 /* Preserve expr->primary_expr.Var.handler */
3042 UdmConstTokenSet(&expr->primary_expr.Var.name, NULL, 0);
3043 expr->primary_expr.type= UDM_EXPRESSION_IDENT;
3044 expr->primary_expr.Var.value.stack_offset=
3045 complex_func_result_on_stack->value.stack_offset;
3046 UDM_BZERO(complex_func_result_on_stack, sizeof(*complex_func_result_on_stack));
3047
3048 }
3049
3050
3051 static udm_bool_t
UdmParseRecursiveMemberAccess(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3052 UdmParseRecursiveMemberAccess(UDM_PROG_COMPILER *compiler,
3053 UDM_PROG_EXPRESSION *expr,
3054 UDM_PROG_VAR *complex_func_result_on_stack,
3055 const UDM_PROG_VAR *dstvar)
3056 {
3057 if (!UdmParseMemberAccess(compiler, expr,
3058 complex_func_result_on_stack, dstvar))
3059 return UDM_FALSE;
3060 while (ParseTerm(compiler, UDM_LEX_DOT))
3061 {
3062 if (dstvar)
3063 return UdmProgCompilerNotSupported(compiler,
3064 "recursive member access in this context");
3065 UdmPrepareFunctionResultForMethodCall(expr, complex_func_result_on_stack);
3066 if (!UdmParseMemberAccess(compiler, expr,
3067 complex_func_result_on_stack, dstvar))
3068 return UDM_FALSE;
3069 }
3070 return UDM_TRUE;
3071 }
3072
3073 /*
3074
3075 <postfix-expression> ::= <primary-expression> {<postfix-expression-part2>}*
3076
3077 */
3078 static udm_bool_t
ParsePostfixExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3079 ParsePostfixExpression(UDM_PROG_COMPILER *compiler,
3080 UDM_PROG_EXPRESSION *expr,
3081 UDM_PROG_VAR *complex_func_result_on_stack,
3082 const UDM_PROG_VAR *dstvar)
3083 {
3084 if (ParseParenthesizedExpression(compiler, expr,
3085 complex_func_result_on_stack, dstvar))
3086 {
3087 if (ParseTerm(compiler, UDM_LEX_DOT))
3088 {
3089 UdmPrepareFunctionResultForMethodCall(expr, complex_func_result_on_stack);
3090 return UdmParseRecursiveMemberAccess(compiler, expr,
3091 complex_func_result_on_stack, dstvar);
3092 }
3093 return UDM_TRUE;
3094 }
3095 if (!ParsePrimaryExpression(compiler, &expr->primary_expr))
3096 return UDM_FALSE;
3097
3098 if (expr->primary_expr.type == UDM_EXPRESSION_IDENT)
3099 {
3100 if (!UdmExprHandler(expr))
3101 {
3102 if (!ParseFunctionCallArguments(compiler, &expr->arglist))
3103 {
3104 if (UdmProgCompilerError(compiler))
3105 return UDM_FALSE;
3106 return UdmProgCompilerUnknownIdentifierError(compiler, &expr->primary_expr.Var.name);
3107 }
3108 else
3109 {
3110 return UdmGenerateFunctionCall(compiler, &expr->primary_expr.Var.name, expr,
3111 complex_func_result_on_stack,
3112 dstvar);
3113 }
3114 }
3115
3116 if (ParseTerm(compiler, UDM_LEX_DOT))
3117 return UdmParseRecursiveMemberAccess(compiler, expr,
3118 complex_func_result_on_stack, dstvar);
3119 return ParsePostfixExpressionVarPart2(compiler, expr);
3120 }
3121 return UDM_TRUE;
3122 }
3123
3124
3125 static udm_bool_t
ExpressionHasEffect(const UDM_PROG_EXPRESSION * expr)3126 ExpressionHasEffect(const UDM_PROG_EXPRESSION *expr)
3127 {
3128 switch (expr->primary_expr.type)
3129 {
3130 case UDM_EXPRESSION_IDENT:
3131 case UDM_EXPRESSION_CONST:
3132 return UDM_FALSE;
3133 case UDM_EXPRESSION_OBJECT:
3134 case UDM_EXPRESSION_COMPUTED:
3135 return UDM_TRUE;
3136 }
3137 return UDM_FALSE;
3138 }
3139
3140
3141 static udm_bool_t ParseUnaryExpression(UDM_PROG_COMPILER *compiler,
3142 UDM_PROG_EXPRESSION *expr,
3143 UDM_PROG_VAR *complex_func_result_on_stack,
3144 const UDM_PROG_VAR *dstvar);
3145
3146 static udm_bool_t
3147 UdmParseCastExpression(UDM_PROG_COMPILER *compiler,
3148 UDM_PROG_EXPRESSION *expr,
3149 UDM_PROG_VAR *complex_func_result_on_stack,
3150 const UDM_PROG_VAR *dstvar);
3151
3152 /*
3153 <unary-operator> ::= &
3154 | *
3155 | +
3156 | -
3157 | ~
3158 | !
3159
3160 <prefix-expression> ::= <unary-operator> [<cast>] <cast-expression>
3161 | '++' <unary-expression>
3162 | '--' <unary-expression>
3163 | 'sizeof' <unary-expression>
3164 | 'sizeof' <type-name>
3165
3166 <unary-expression> ::= <postfix-expression>
3167 | <prefix-expression>
3168 */
3169 static udm_bool_t
ParseUnaryExpressionInternal(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3170 ParseUnaryExpressionInternal(UDM_PROG_COMPILER *compiler,
3171 UDM_PROG_EXPRESSION *expr,
3172 UDM_PROG_VAR *complex_func_result_on_stack,
3173 const UDM_PROG_VAR *dstvar)
3174 {
3175 if (ParseTerm(compiler, UDM_LEX_DEC))
3176 {
3177 if (!ParseUnaryExpression(compiler, expr,
3178 complex_func_result_on_stack, dstvar))
3179 return UdmProgCompilerExpectedRule(compiler, "<unary-expression>");
3180 expr->primary_expr.type= UDM_EXPRESSION_COMPUTED;
3181 return UdmGenerateStackVarDecrement(compiler, &expr->primary_expr.Var) &&
3182 UdmGenerateVarToNativeReg0(compiler, &expr->primary_expr.Var);
3183 }
3184 if (ParseTerm(compiler, UDM_LEX_INC))
3185 {
3186 if (!ParseUnaryExpression(compiler, expr,
3187 complex_func_result_on_stack, dstvar))
3188 return UdmProgCompilerExpectedRule(compiler, "<unary-expression>");
3189 expr->primary_expr.type= UDM_EXPRESSION_COMPUTED;
3190 return UdmGenerateStackVarIncrement(compiler, &expr->primary_expr.Var) &&
3191 UdmGenerateVarToNativeReg0(compiler, &expr->primary_expr.Var);
3192 }
3193 if (!ParsePostfixExpression(compiler, expr,
3194 complex_func_result_on_stack, dstvar))
3195 return UDM_FALSE;
3196
3197 return UDM_TRUE;
3198 }
3199
3200
3201 static udm_bool_t
ParseUnaryExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3202 ParseUnaryExpression(UDM_PROG_COMPILER *compiler,
3203 UDM_PROG_EXPRESSION *expr,
3204 UDM_PROG_VAR *complex_func_result_on_stack,
3205 const UDM_PROG_VAR *dstvar)
3206 {
3207 if (ParseTerm(compiler, UDM_LEX_EXCLAM))
3208 {
3209 if (!UdmParseCastExpression(compiler, expr,
3210 complex_func_result_on_stack, dstvar))
3211 return UDM_FALSE;
3212 if (!UdmGenerateExpressionToNativeReg0(compiler, expr, NULL) ||
3213 !UdmGenerateIsNotTrueTest(compiler, UdmExprHandler(expr)))
3214 return UDM_FALSE;
3215 UdmExprSetHandler(expr, &UdmValueHandlerInt);
3216 return UDM_TRUE;
3217 }
3218 if (ParseTerm(compiler, UDM_LEX_TILDE))
3219 {
3220 if (!UdmParseCastExpression(compiler, expr,
3221 complex_func_result_on_stack, dstvar))
3222 return UDM_FALSE;
3223 if (UdmExprHandler(expr)->native_reg_type != UDM_VALUE_DATA_TYPE_INT)
3224 return UdmProgCompilerNotSupported(compiler, "unary ~ for this data type");
3225 if (!UdmGenerateExpressionToNativeReg0(compiler, expr, NULL) ||
3226 !UdmGenerateOp(compiler, UDM_PROG_NOT_IREG0))
3227 return UDM_FALSE;
3228 UdmExprSetHandler(expr, &UdmValueHandlerInt);
3229 return UDM_TRUE;
3230 }
3231 if (ParseTerm(compiler, UDM_LEX_MINUS))
3232 {
3233 if (!UdmParseCastExpression(compiler, expr,
3234 complex_func_result_on_stack, dstvar))
3235 return UDM_FALSE;
3236 if (UdmValueHandlerIsComplex(UdmExprHandler(expr)))
3237 return UdmProgCompilerNotSupported(compiler, "unary '-' for this data type");
3238 if (!UdmGenerateExpressionToNativeReg0(compiler, expr, NULL))
3239 return UDM_FALSE;
3240 if (!UdmGenerateMovNativeReg0ToReg1(compiler, UdmExprHandler(expr)))
3241 return UDM_FALSE;
3242 if (!UdmGenerateClearNativeReg0(compiler, UdmExprHandler(expr)))
3243 return UDM_FALSE;
3244
3245 if (!UdmGenerateAddNativeReg0Reg1(compiler,
3246 &expr->primary_expr.Var.value.handler,
3247 UDM_LEX_MINUS))
3248 return UDM_FALSE;
3249 return UDM_TRUE;
3250 }
3251 if (ParseTerm(compiler, UDM_LEX_PLUS))
3252 {
3253 if (!UdmParseCastExpression(compiler, expr,
3254 complex_func_result_on_stack, dstvar))
3255 return UDM_FALSE;
3256 if (UdmValueHandlerIsComplex(UdmExprHandler(expr)))
3257 return UdmProgCompilerNotSupported(compiler, "unary '+' for this data type");
3258 return UDM_TRUE;
3259 }
3260 return ParseUnaryExpressionInternal(compiler, expr,
3261 complex_func_result_on_stack, dstvar);
3262 }
3263
3264
3265 /**
3266 <cast-expression> ::= <unary-expression>
3267 | ( <type-name> ) <cast-expression>
3268 */
3269 static udm_bool_t
UdmParseCastExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3270 UdmParseCastExpression(UDM_PROG_COMPILER *compiler,
3271 UDM_PROG_EXPRESSION *expr,
3272 UDM_PROG_VAR *complex_func_result_on_stack,
3273 const UDM_PROG_VAR *dstvar)
3274 {
3275 const UDM_VALUE_HANDLER *ha;
3276 /*
3277 The cast operator starts from parenthesis, so does the
3278 parenthesized expression. This rule needs one more look-ahead.
3279 TestParenthesizedTypeSpecifier() makes one more look-ahead with rollback.
3280 */
3281 if (!TestParenthesizedTypeSpecifier(compiler))
3282 return ParseUnaryExpression(compiler, expr,
3283 complex_func_result_on_stack, dstvar);
3284
3285 if (!ParseTerm(compiler, UDM_LEX_LP) ||
3286 !ParseTypeSpecifier(compiler, &ha) ||
3287 !ParseTermOrError(compiler, UDM_LEX_RP))
3288 return UDM_FALSE;
3289
3290 if (!UdmParseCastExpression(compiler, expr,
3291 complex_func_result_on_stack, dstvar))
3292 return UDM_FALSE;
3293 if (UdmExprHandler(expr) == ha)
3294 return UDM_TRUE;
3295
3296 if (UdmValueHandlerIsComplex(ha))
3297 return UdmProgCompilerNotSupported(compiler, "cast to this data type");
3298 if (UdmValueHandlerIsComplex(UdmExprHandler(expr)))
3299 return UdmProgCompilerNotSupported(compiler, "cast from this data type");
3300 if (!UdmGenerateExpressionToNativeReg0(compiler, expr, NULL) ||
3301 !UdmGenerateNativeReg0TypeConversion(compiler, ha, UdmExprHandler(expr)))
3302 return UDM_FALSE;
3303 UdmExprSetHandler(expr, ha);
3304 return UDM_TRUE;
3305 }
3306
3307
3308 static udm_bool_t
UdmGenerateSaveNativeReg0ToTempVariableOnStack(UDM_PROG_COMPILER * c,const UDM_VALUE_HANDLER * h,UDM_PROG_VAR * dst)3309 UdmGenerateSaveNativeReg0ToTempVariableOnStack(UDM_PROG_COMPILER *c,
3310 const UDM_VALUE_HANDLER *h,
3311 UDM_PROG_VAR *dst)
3312 {
3313 return UdmGenerateReserveNonInitializedTemporaryVariableOnStack(c, h, dst) &&
3314 UdmGenerateConstructor(c, dst) &&
3315 UdmGenerateNativeReg0ToVar(c, dst);
3316 }
3317
3318
3319 static udm_bool_t
UdmGenerateAggregateAndConvertReg0Reg1(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * b,const UDM_VALUE_HANDLER * a,const UDM_VALUE_HANDLER ** agg)3320 UdmGenerateAggregateAndConvertReg0Reg1(UDM_PROG_COMPILER *compiler,
3321 const UDM_VALUE_HANDLER *b,
3322 const UDM_VALUE_HANDLER *a,
3323 const UDM_VALUE_HANDLER **agg)
3324 {
3325 *agg= a->native_reg_type == UDM_VALUE_DATA_TYPE_DOUBLE ||
3326 b->native_reg_type == UDM_VALUE_DATA_TYPE_DOUBLE ?
3327 &UdmValueHandlerDouble : &UdmValueHandlerInt;
3328 return UdmGenerateNativeReg1TypeConversion(compiler, *agg, a) &&
3329 UdmGenerateNativeReg0TypeConversion(compiler, *agg, b);
3330 }
3331
3332
3333 static udm_bool_t
3334 ParseMultiplicativeExpression(UDM_PROG_COMPILER *compiler,
3335 UDM_PROG_EXPRESSION *expr,
3336 UDM_PROG_VAR *complex_func_result_on_stack,
3337 const UDM_PROG_VAR *dstvar);
3338 static udm_bool_t
3339 ParseAdditiveExpression(UDM_PROG_COMPILER *compiler,
3340 UDM_PROG_EXPRESSION *expr,
3341 UDM_PROG_VAR *complex_func_result_on_stack,
3342 const UDM_PROG_VAR *dstvar);
3343
3344 static udm_bool_t
3345 UdmParseShiftExpression(UDM_PROG_COMPILER *compiler,
3346 UDM_PROG_EXPRESSION *expr,
3347 UDM_PROG_VAR *complex_func_result_on_stack,
3348 const UDM_PROG_VAR *dstvar);
3349
3350
3351 static udm_bool_t
3352 UdmParseRelationalExpression(UDM_PROG_COMPILER *compiler,
3353 UDM_PROG_EXPRESSION *expr,
3354 UDM_PROG_VAR *complex_func_result_on_stack,
3355 const UDM_PROG_VAR *dstvar);
3356
3357 static udm_bool_t
3358 UdmParseEqualityExpression(UDM_PROG_COMPILER *compiler,
3359 UDM_PROG_EXPRESSION *expr,
3360 UDM_PROG_VAR *complex_func_result_on_stack,
3361 const UDM_PROG_VAR *dstvar);
3362
3363
3364 static udm_bool_t
3365 UdmParseAndExpression(UDM_PROG_COMPILER *compiler,
3366 UDM_PROG_EXPRESSION *expr,
3367 UDM_PROG_VAR *complex_func_result_on_stack,
3368 const UDM_PROG_VAR *dstvar);
3369
3370
3371 static udm_bool_t
3372 UdmParseOrExpression(UDM_PROG_COMPILER *compiler,
3373 UDM_PROG_EXPRESSION *expr,
3374 UDM_PROG_VAR *complex_func_result_on_stack,
3375 const UDM_PROG_VAR *dstvar);
3376
3377
3378 static udm_bool_t
UdmGenerateDiadicOperationPart2(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,udm_lex_t op)3379 UdmGenerateDiadicOperationPart2(UDM_PROG_COMPILER *compiler,
3380 UDM_PROG_EXPRESSION *expr,
3381 udm_lex_t op)
3382 {
3383 UDM_PROG_EXPRESSION expr2;
3384 UDM_PROG_VAR tmp;
3385 const UDM_VALUE_HANDLER *agg;
3386
3387 if (!UdmExprHandler(expr))
3388 return UdmProgCompilerVoidValueIsNotIgnored(compiler);
3389
3390 switch (UdmExprHandler(expr)->datatype)
3391 {
3392 case UDM_VALUE_DATA_TYPE_CHAR:
3393 case UDM_VALUE_DATA_TYPE_INT:
3394 case UDM_VALUE_DATA_TYPE_DOUBLE:
3395 break;
3396 case UDM_VALUE_DATA_TYPE_STR:
3397 case UDM_VALUE_DATA_TYPE_ENV:
3398 case UDM_VALUE_DATA_TYPE_RESULT:
3399 case UDM_VALUE_DATA_TYPE_DOCUMENT:
3400 case UDM_VALUE_DATA_TYPE_SQLRESULT:
3401 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
3402 return UdmProgCompilerNotSupported(compiler, "Dyadic operation for this data type");
3403 }
3404
3405 if (!UdmGenerateExpressionToNativeReg0(compiler, expr, NULL))
3406 return UDM_FALSE;
3407
3408 /* Save the current value in reg0 to a temporary variable */
3409 if (!UdmProgCompilerEnterBlock(compiler) ||
3410 !UdmGenerateSaveNativeReg0ToTempVariableOnStack(compiler,
3411 UdmExprHandler(expr),
3412 &tmp))
3413 return UDM_FALSE;
3414 /* Parse the second operand and bring its value to reg0 */
3415 switch (op)
3416 {
3417 case UDM_LEX_VBAR:
3418 if (!UdmParseOrExpression(compiler, &expr2, NULL, NULL))
3419 return UDM_FALSE;
3420 break;
3421 case UDM_LEX_CARET:
3422 if (!UdmParseAndExpression(compiler, &expr2, NULL, NULL))
3423 return UDM_FALSE;
3424 break;
3425 case UDM_LEX_AMPERSAND:
3426 if (!UdmParseEqualityExpression(compiler, &expr2, NULL, NULL))
3427 return UDM_FALSE;
3428 break;
3429 case UDM_LEX_EQ_EQ:
3430 case UDM_LEX_NOT_EQ:
3431 if (!UdmParseRelationalExpression(compiler, &expr2, NULL, NULL))
3432 return UDM_FALSE;
3433 break;
3434 case UDM_LEX_LE:
3435 case UDM_LEX_GE:
3436 case UDM_LEX_LT:
3437 case UDM_LEX_GT:
3438 if (!UdmParseShiftExpression(compiler, &expr2, NULL, NULL))
3439 return UDM_FALSE;
3440 break;
3441 case UDM_LEX_LSHIFT:
3442 case UDM_LEX_RSHIFT:
3443 if (!ParseAdditiveExpression(compiler, &expr2, NULL, NULL))
3444 return UDM_FALSE;
3445 break;
3446 case UDM_LEX_PLUS:
3447 case UDM_LEX_MINUS:
3448 case UDM_LEX_PERCENT:
3449 if (!ParseMultiplicativeExpression(compiler, &expr2, NULL, NULL))
3450 return UDM_FALSE;
3451 break;
3452 case UDM_LEX_ASTERISK:
3453 case UDM_LEX_SLASH:
3454 if (!UdmParseCastExpression(compiler, &expr2, NULL, NULL))
3455 return UDM_FALSE;
3456 break;
3457 default:
3458 UDM_ASSERT(0);
3459 return 0;
3460 }
3461
3462 if (!UdmExprHandler(&expr2))
3463 return UdmProgCompilerVoidValueIsNotIgnored(compiler);
3464
3465 if (!UdmGenerateExpressionToNativeReg0(compiler, &expr2, NULL))
3466 return UDM_FALSE;
3467 /* Restore the first operant to reg1 */
3468 if (!UdmGenerateVarToNativeReg1(compiler, &tmp))
3469 return UDM_FALSE;
3470 if (!UdmProgCompilerLeaveBlock(compiler))
3471 return UDM_FALSE;
3472
3473 /* Now we have the left operant in reg1 and the right operand in reg0 */
3474 if (!UdmGenerateAggregateAndConvertReg0Reg1(compiler,
3475 UdmExprHandler(&expr2),
3476 UdmExprHandler(expr),
3477 &agg))
3478 return UDM_FALSE;
3479
3480 switch (op)
3481 {
3482 case UDM_LEX_VBAR:
3483 case UDM_LEX_CARET:
3484 case UDM_LEX_AMPERSAND:
3485 case UDM_LEX_ASTERISK:
3486 case UDM_LEX_PLUS:
3487 case UDM_LEX_EQ_EQ:
3488 case UDM_LEX_NOT_EQ:
3489 break; /* Reverse operation, the order of arguments does not matter. */
3490 case UDM_LEX_SLASH:
3491 case UDM_LEX_PERCENT:
3492 case UDM_LEX_MINUS:
3493 case UDM_LEX_LSHIFT:
3494 case UDM_LEX_RSHIFT:
3495 case UDM_LEX_LE:
3496 case UDM_LEX_GE:
3497 case UDM_LEX_LT:
3498 case UDM_LEX_GT:
3499 if (!UdmGenerateSwapNativeReg0Reg1(compiler, agg))
3500 return UDM_FALSE;
3501 break;
3502 default:
3503 UDM_ASSERT(0);
3504 return UDM_FALSE;
3505 }
3506 if (!UdmGenerateDiadicOperationNativeReg0Reg1(compiler, &agg, op))
3507 return UDM_FALSE;
3508 UdmExprSetHandler(expr, agg);
3509 return UDM_TRUE;
3510 }
3511
3512
3513 /*
3514 <multiplicative-expression> ::= <cast-expression>
3515 { <mul-op> <cast-expression> }*
3516 <cast-expression> ::= [ ( <type-name> )] <unary-expression>
3517 */
3518 static udm_bool_t
ParseMultiplicativeExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3519 ParseMultiplicativeExpression(UDM_PROG_COMPILER *compiler,
3520 UDM_PROG_EXPRESSION *expr,
3521 UDM_PROG_VAR *complex_func_result_on_stack,
3522 const UDM_PROG_VAR *dstvar)
3523 {
3524 udm_lex_t cmd;
3525 if (!UdmParseCastExpression(compiler, expr,
3526 complex_func_result_on_stack, dstvar))
3527 return UDM_FALSE;
3528 for (; ParseTerm(compiler, (cmd= UDM_LEX_ASTERISK)) ||
3529 ParseTerm(compiler, (cmd= UDM_LEX_SLASH)) ||
3530 ParseTerm(compiler, (cmd= UDM_LEX_PERCENT)) ; )
3531 {
3532 if (!UdmGenerateDiadicOperationPart2(compiler, expr, cmd))
3533 return UDM_FALSE;
3534 }
3535 return UDM_TRUE;
3536 }
3537
3538
3539
3540 /*
3541 <additive-expression> ::= <multiplicative-expression>
3542 { <add-op> <multiplicative-expression> }*
3543 */
3544 static udm_bool_t
ParseAdditiveExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3545 ParseAdditiveExpression(UDM_PROG_COMPILER *compiler,
3546 UDM_PROG_EXPRESSION *expr,
3547 UDM_PROG_VAR *complex_func_result_on_stack,
3548 const UDM_PROG_VAR *dstvar)
3549 {
3550 udm_lex_t cmd;
3551 if (!ParseMultiplicativeExpression(compiler, expr,
3552 complex_func_result_on_stack, dstvar))
3553 return UDM_FALSE;
3554 for (; (ParseTerm(compiler, (cmd= UDM_LEX_PLUS)) ||
3555 ParseTerm(compiler, (cmd= UDM_LEX_MINUS))) ; )
3556 {
3557 if (!UdmGenerateDiadicOperationPart2(compiler, expr, cmd))
3558 return UDM_FALSE;
3559 }
3560 return UDM_TRUE;
3561 }
3562
3563
3564 /*
3565 <shift-expression> ::= <additive-expression>
3566 { <shift-op> <additive-expression> }*
3567 */
3568 static udm_bool_t
UdmParseShiftExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3569 UdmParseShiftExpression(UDM_PROG_COMPILER *compiler,
3570 UDM_PROG_EXPRESSION *expr,
3571 UDM_PROG_VAR *complex_func_result_on_stack,
3572 const UDM_PROG_VAR *dstvar)
3573 {
3574 udm_lex_t cmd;
3575 if (!ParseAdditiveExpression(compiler, expr,
3576 complex_func_result_on_stack, dstvar))
3577 return UDM_FALSE;
3578 for (; ParseTerm(compiler, (cmd= UDM_LEX_LSHIFT)) ||
3579 ParseTerm(compiler, (cmd= UDM_LEX_RSHIFT)); )
3580 {
3581 if (!UdmGenerateDiadicOperationPart2(compiler, expr, cmd))
3582 return UDM_FALSE;
3583 }
3584 return UDM_TRUE;
3585 }
3586
3587
3588 /*
3589 <relational-expression> ::= <shift-expression>
3590 { <rel-op> <shift-expression>
3591 */
3592 static udm_bool_t
UdmParseRelationalExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3593 UdmParseRelationalExpression(UDM_PROG_COMPILER *compiler,
3594 UDM_PROG_EXPRESSION *expr,
3595 UDM_PROG_VAR *complex_func_result_on_stack,
3596 const UDM_PROG_VAR *dstvar)
3597 {
3598 udm_lex_t cmd;
3599 if (!UdmParseShiftExpression(compiler, expr,
3600 complex_func_result_on_stack, dstvar))
3601 return UDM_FALSE;
3602 for (; ParseTerm(compiler, (cmd= UDM_LEX_LT)) ||
3603 ParseTerm(compiler, (cmd= UDM_LEX_LE)) ||
3604 ParseTerm(compiler, (cmd= UDM_LEX_GT)) ||
3605 ParseTerm(compiler, (cmd= UDM_LEX_GE)); )
3606 {
3607 if (!UdmGenerateDiadicOperationPart2(compiler, expr, cmd))
3608 return UDM_FALSE;
3609 }
3610 return UDM_TRUE;
3611 }
3612
3613
3614 /*
3615 <equality-expression> ::= <relational-expression>
3616 { <eq-op> <relational-expression> }*
3617 */
3618 static udm_bool_t
UdmParseEqualityExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3619 UdmParseEqualityExpression(UDM_PROG_COMPILER *compiler,
3620 UDM_PROG_EXPRESSION *expr,
3621 UDM_PROG_VAR *complex_func_result_on_stack,
3622 const UDM_PROG_VAR *dstvar)
3623 {
3624 udm_lex_t cmd;
3625 if (!UdmParseRelationalExpression(compiler, expr,
3626 complex_func_result_on_stack, dstvar))
3627 return UDM_FALSE;
3628 for (; ParseTerm(compiler, (cmd= UDM_LEX_EQ_EQ)) ||
3629 ParseTerm(compiler, (cmd= UDM_LEX_NOT_EQ)); )
3630 {
3631 if (!UdmGenerateDiadicOperationPart2(compiler, expr, cmd))
3632 return UDM_FALSE;
3633 }
3634 return UDM_TRUE;
3635 }
3636
3637
3638 /*
3639 <and-expression> ::= <equality-expression>
3640 { & <equality-expression> }*
3641 */
3642 static udm_bool_t
UdmParseAndExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3643 UdmParseAndExpression(UDM_PROG_COMPILER *compiler,
3644 UDM_PROG_EXPRESSION *expr,
3645 UDM_PROG_VAR *complex_func_result_on_stack,
3646 const UDM_PROG_VAR *dstvar)
3647 {
3648 udm_lex_t cmd;
3649 if (!UdmParseEqualityExpression(compiler, expr,
3650 complex_func_result_on_stack, dstvar))
3651 return UDM_FALSE;
3652 for (; ParseTerm(compiler, (cmd= UDM_LEX_AMPERSAND)); )
3653 {
3654 if (!UdmGenerateDiadicOperationPart2(compiler, expr, cmd))
3655 return UDM_FALSE;
3656 }
3657 return UDM_TRUE;
3658 }
3659
3660
3661 /*
3662 <exclusive-or-expression> ::= <and-expression> { ^ <and-expression> }*
3663 */
3664 static udm_bool_t
UdmParseXorExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3665 UdmParseXorExpression(UDM_PROG_COMPILER *compiler,
3666 UDM_PROG_EXPRESSION *expr,
3667 UDM_PROG_VAR *complex_func_result_on_stack,
3668 const UDM_PROG_VAR *dstvar)
3669 {
3670 udm_lex_t cmd;
3671 if (!UdmParseAndExpression(compiler, expr,
3672 complex_func_result_on_stack, dstvar))
3673 return UDM_FALSE;
3674 for (; ParseTerm(compiler, (cmd= UDM_LEX_CARET)); )
3675 {
3676 if (!UdmGenerateDiadicOperationPart2(compiler, expr, cmd))
3677 return UDM_FALSE;
3678 }
3679 return UDM_TRUE;
3680 }
3681
3682
3683 /*
3684 <inclusive-or-expression> ::= <exclusive-or-expression>
3685 { | <exclusive-or-expression> }*
3686 */
3687 static udm_bool_t
UdmParseOrExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)3688 UdmParseOrExpression(UDM_PROG_COMPILER *compiler,
3689 UDM_PROG_EXPRESSION *expr,
3690 UDM_PROG_VAR *complex_func_result_on_stack,
3691 const UDM_PROG_VAR *dstvar)
3692 {
3693 udm_lex_t cmd;
3694 if (!UdmParseXorExpression(compiler, expr,
3695 complex_func_result_on_stack, dstvar))
3696 return UDM_FALSE;
3697 for (; ParseTerm(compiler, (cmd= UDM_LEX_VBAR)); )
3698 {
3699 if (!UdmGenerateDiadicOperationPart2(compiler, expr, cmd))
3700 return UDM_FALSE;
3701 }
3702 return UDM_TRUE;
3703 }
3704
3705
3706 static udm_bool_t
UdmGenerateExpressionToBool(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr)3707 UdmGenerateExpressionToBool(UDM_PROG_COMPILER *compiler,
3708 UDM_PROG_EXPRESSION *expr)
3709 {
3710 if (!UdmGenerateExpressionToNativeReg0(compiler, expr, NULL) ||
3711 !UdmGenerateIsTrueTest(compiler, UdmExprHandler(expr)))
3712 return UDM_FALSE;
3713 UdmExprSetHandler(expr, &UdmValueHandlerInt);
3714 return UDM_TRUE;
3715 }
3716
3717
3718 static udm_bool_t
UdmParseBoolAndExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dst)3719 UdmParseBoolAndExpression(UDM_PROG_COMPILER *compiler,
3720 UDM_PROG_EXPRESSION *expr,
3721 UDM_PROG_VAR *complex_func_result_on_stack,
3722 const UDM_PROG_VAR *dst)
3723 {
3724 size_t start= UdmProgCompilerGetProg(compiler)->nitems;
3725 if (!UdmParseOrExpression(compiler, expr, complex_func_result_on_stack, dst))
3726 return UDM_FALSE;
3727 if (!ParseTerm(compiler, UDM_LEX_BOOL_AND))
3728 return UDM_TRUE;
3729 if (!UdmGenerateExpressionToBool(compiler, expr))
3730 return UDM_FALSE;
3731 if (!UdmGenerateOp(compiler, UDM_PROG_JE))
3732 return UDM_FALSE;
3733
3734 for ( ; ; )
3735 {
3736 UDM_PROG_EXPRESSION expr2;
3737 if (!UdmParseOrExpression(compiler, &expr2, NULL, dst))
3738 return UDM_FALSE;
3739 if (!UdmGenerateExpressionToBool(compiler, &expr2))
3740 return UDM_FALSE;
3741 if (!UdmGenerateOp(compiler, UDM_PROG_JE))
3742 return UDM_FALSE;
3743 if (!ParseTerm(compiler, UDM_LEX_BOOL_AND))
3744 break;
3745 }
3746 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler),
3747 start,
3748 UdmProgCompilerGetProg(compiler)->nitems);
3749 return UDM_TRUE;
3750 }
3751
3752
3753 static udm_bool_t
UdmParseBoolOrExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dst)3754 UdmParseBoolOrExpression(UDM_PROG_COMPILER *compiler,
3755 UDM_PROG_EXPRESSION *expr,
3756 UDM_PROG_VAR *complex_func_result_on_stack,
3757 const UDM_PROG_VAR *dst)
3758 {
3759 size_t start= UdmProgCompilerGetProg(compiler)->nitems;
3760 if (!UdmParseBoolAndExpression(compiler, expr, complex_func_result_on_stack, dst))
3761 return UDM_FALSE;
3762 if (!ParseTerm(compiler, UDM_LEX_BOOL_OR))
3763 return UDM_TRUE;
3764 if (!UdmGenerateExpressionToBool(compiler, expr))
3765 return UDM_FALSE;
3766 if (!UdmGenerateOp(compiler, UDM_PROG_JNE))
3767 return UDM_FALSE;
3768
3769 for ( ; ; )
3770 {
3771 UDM_PROG_EXPRESSION expr2;
3772 if (!UdmParseBoolAndExpression(compiler, &expr2, NULL, dst))
3773 return UDM_FALSE;
3774 if (!UdmGenerateExpressionToBool(compiler, &expr2))
3775 return UDM_FALSE;
3776 if (!UdmGenerateOp(compiler, UDM_PROG_JNE))
3777 return UDM_FALSE;
3778 if (!ParseTerm(compiler, UDM_LEX_BOOL_OR))
3779 break;
3780 }
3781 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler),
3782 start,
3783 UdmProgCompilerGetProg(compiler)->nitems);
3784 return UDM_TRUE;
3785 }
3786
3787
3788 static udm_bool_t
3789 UdmGenerateVarAssignmentFromExpression(UDM_PROG_COMPILER *compiler,
3790 const UDM_PROG_VAR *dst,
3791 const UDM_PROG_EXPRESSION *expr);
3792 static udm_bool_t
3793 UdmGenerateAssignmentOperator(UDM_PROG_COMPILER *compiler,
3794 const UDM_PROG_VAR *Var,
3795 const UDM_PROG_PRIMARY_EXPRESSION *Src,
3796 udm_expression_t type);
3797
3798 static udm_bool_t
3799 UdmParseAssignmentExpression(UDM_PROG_COMPILER *compiler,
3800 UDM_PROG_EXPRESSION *expr,
3801 UDM_PROG_VAR *complex_func_result_on_stack,
3802 const UDM_PROG_VAR *dstvar);
3803
3804
3805 /**
3806 <conditional-expression> ::= <logical-or-expression>
3807 { ? <expression> : <conditional-expression> }*
3808
3809 The conditional expression works like functions.
3810 - In case of a complex result type, it creates a temporary stack variable.
3811 - In case of a simple result type, the result is returned in registers.
3812
3813 For example:
3814 string0= cond ? string1 : string2;
3815
3816 The temporal stack variable is assigned to either string1 or string2,
3817 then copied to string 0.
3818
3819 NOTE: Interesting: The right choice expression cannot be an assignment.
3820 Only the left can be:
3821 cond ? x= 10 : y; // This is correct
3822 cond ? x : y= 10; // This is wrong
3823 */
3824 static udm_bool_t
UdmParseConditionalExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dst)3825 UdmParseConditionalExpression(UDM_PROG_COMPILER *compiler,
3826 UDM_PROG_EXPRESSION *expr,
3827 UDM_PROG_VAR *complex_func_result_on_stack,
3828 const UDM_PROG_VAR *dst)
3829 {
3830 size_t jmp0, jmp1;
3831 UDM_PROG_EXPRESSION expr2;
3832 if (!UdmParseBoolOrExpression(compiler, expr,
3833 complex_func_result_on_stack, dst))
3834 return UDM_FALSE;
3835 if (!ParseTerm(compiler, UDM_LEX_QUESTION))
3836 return UDM_TRUE;
3837
3838 if (!UdmGenerateExpressionToBool(compiler, expr))
3839 return UDM_FALSE;
3840 jmp0= UdmProgCompilerGetProg(compiler)->nitems;
3841 if (!UdmGenerateOp(compiler, UDM_PROG_JE)) /* To the second part */
3842 return UDM_FALSE;
3843
3844 UDM_BZERO(expr, sizeof(*expr));
3845 if (!UdmParseExpression(compiler, expr,
3846 complex_func_result_on_stack, dst))
3847 return UdmProgCompilerExpectedRule(compiler, "<expression>");
3848
3849 if (UdmExprHandler(expr))
3850 {
3851 if (UdmValueHandlerIsComplex(UdmExprHandler(expr)))
3852 {
3853 if (expr->primary_expr.type == UDM_EXPRESSION_OBJECT)
3854 {
3855 /* The result variable was created on stack */
3856 UDM_ASSERT(UdmProgVarHandler(complex_func_result_on_stack) ==
3857 UdmExprHandler(expr));
3858 }
3859 else
3860 {
3861 UDM_ASSERT(expr->primary_expr.type == UDM_EXPRESSION_IDENT ||
3862 expr->primary_expr.type == UDM_EXPRESSION_CONST);
3863 /* Create the result variable on stack */
3864 if (!UdmGenerateReserveNonInitializedTemporaryVariableOnStack(compiler,
3865 UdmExprHandler(expr),
3866 complex_func_result_on_stack))
3867 return UDM_FALSE;
3868
3869 if (!UdmGenerateConstructor(compiler, complex_func_result_on_stack))
3870 return UDM_FALSE;
3871 if (!UdmGenerateAssignmentOperator(compiler,
3872 complex_func_result_on_stack,
3873 &expr->primary_expr,
3874 expr->primary_expr.type))
3875 return UDM_FALSE;
3876 }
3877 }
3878 else
3879 {
3880 if (!UdmGenerateExpressionToNativeReg0(compiler, expr,
3881 complex_func_result_on_stack))
3882 return UDM_FALSE;
3883 }
3884 }
3885
3886 jmp1= UdmProgCompilerGetProg(compiler)->nitems;
3887 if (!UdmGenerateOp(compiler, UDM_PROG_JMP)) /* To the end */
3888 return UDM_FALSE;
3889
3890 if (!ParseTermOrError(compiler, UDM_LEX_COLON))
3891 return UDM_TRUE;
3892
3893 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler), jmp0, jmp0 + 1);
3894
3895 UDM_BZERO(&expr2, sizeof(expr2));
3896 /*
3897 If the left choice expression generated a new temporary variable
3898 (e.g. in case of a function or a method call), then the right
3899 choice expression should store the result into the same variable.
3900 */
3901 if (!UdmParseConditionalExpression(compiler, &expr2, NULL, complex_func_result_on_stack))
3902 return UdmProgCompilerExpectedRule(compiler, "<conditional-expression>");
3903
3904 if (UdmExprHandler(expr) != UdmExprHandler(&expr2))
3905 return UdmProgCompilerNotSupported(compiler, "conditional expression with different argument types");
3906
3907 if (UdmExprHandler(expr))
3908 {
3909 if (!UdmValueHandlerIsComplex(UdmExprHandler(expr)))
3910 {
3911 if (!UdmGenerateExpressionToNativeReg0(compiler, &expr2, NULL))
3912 return UDM_FALSE;
3913 }
3914 else
3915 {
3916 if (expr2.primary_expr.type != UDM_EXPRESSION_OBJECT)
3917 {
3918 /*
3919 Function call returns an initialized variable.
3920 For the other expression types call the costructor now.
3921 */
3922 if (!UdmGenerateConstructor(compiler, complex_func_result_on_stack))
3923 return UDM_FALSE;
3924 if (!UdmGenerateAssignmentOperator(compiler,
3925 complex_func_result_on_stack,
3926 &expr2.primary_expr,
3927 expr2.primary_expr.type))
3928 return UDM_FALSE;
3929 }
3930 }
3931 }
3932
3933 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler), jmp1, jmp1 + 1);
3934 expr->primary_expr.type= UDM_EXPRESSION_OBJECT;
3935 return UDM_TRUE;
3936 }
3937
3938
3939 /*
3940 <assignment-operator> ::= =
3941 | *=
3942 | /=
3943 | %=
3944 | +=
3945 | -=
3946 | <<=
3947 | >>=
3948 | &=
3949 | ^=
3950 | |=
3951 */
3952
3953 static udm_bool_t
ParseEqAssignmentOperator(UDM_PROG_COMPILER * compiler)3954 ParseEqAssignmentOperator(UDM_PROG_COMPILER *compiler)
3955 {
3956 return ParseTerm(compiler, UDM_LEX_EQ);
3957 }
3958
3959
3960 static udm_bool_t
ParseSpecialAssignmentOperator(UDM_PROG_COMPILER * compiler,udm_special_assignment_t * op,udm_tmpl_cmd_t * cmd)3961 ParseSpecialAssignmentOperator(UDM_PROG_COMPILER *compiler,
3962 udm_special_assignment_t *op,
3963 udm_tmpl_cmd_t *cmd)
3964 {
3965 *cmd= UdmProgCompilerLastTokenType(compiler);
3966 if (ParseTerm(compiler, UDM_LEX_MUL_EQ))
3967 {
3968 *op= UDM_ASSIGNMENT_MUL;
3969 return UDM_TRUE;
3970 }
3971 if (ParseTerm(compiler, UDM_LEX_DIV_EQ))
3972 {
3973 *op= UDM_ASSIGNMENT_DIV;
3974 return UDM_TRUE;
3975 }
3976 if (ParseTerm(compiler, UDM_LEX_REM_EQ))
3977 {
3978 *op= UDM_ASSIGNMENT_REM;
3979 return UDM_TRUE;
3980 }
3981 if (ParseTerm(compiler, UDM_LEX_INC_EQ))
3982 {
3983 *op= UDM_ASSIGNMENT_ADD;
3984 return UDM_TRUE;
3985 }
3986 if (ParseTerm(compiler, UDM_LEX_AND_EQ))
3987 {
3988 *op= UDM_ASSIGNMENT_AND;
3989 return UDM_TRUE;
3990 }
3991 if (ParseTerm(compiler, UDM_LEX_OR_EQ))
3992 {
3993 *op= UDM_ASSIGNMENT_OR;
3994 return UDM_TRUE;
3995 }
3996 if (ParseTerm(compiler, UDM_LEX_XOR_EQ))
3997 {
3998 *op= UDM_ASSIGNMENT_XOR;
3999 return UDM_TRUE;
4000 }
4001 if (ParseTerm(compiler, UDM_LEX_DEC_EQ))
4002 {
4003 *op= UDM_ASSIGNMENT_SUB;
4004 return UDM_TRUE;
4005 }
4006 if (ParseTerm(compiler, UDM_LEX_LSHIFT_EQ))
4007 {
4008 *op= UDM_ASSIGNMENT_LSHIFT;
4009 return UDM_TRUE;
4010 }
4011 if (ParseTerm(compiler, UDM_LEX_RSHIFT_EQ))
4012 {
4013 *op= UDM_ASSIGNMENT_RSHIFT;
4014 return UDM_TRUE;
4015 }
4016 return UDM_FALSE;
4017 }
4018
4019
4020 static udm_bool_t
UdmSpecialAssignmentOpDouble(UDM_PROG_COMPILER * c,udm_tmpl_cmd_t * cmd,udm_special_assignment_t op,const UDM_VALUE_HANDLER * dst,const UDM_VALUE_HANDLER * src)4021 UdmSpecialAssignmentOpDouble(UDM_PROG_COMPILER *c,
4022 udm_tmpl_cmd_t *cmd, udm_special_assignment_t op,
4023 const UDM_VALUE_HANDLER *dst,
4024 const UDM_VALUE_HANDLER *src)
4025 {
4026 switch (op)
4027 {
4028 case UDM_ASSIGNMENT_ADD: *cmd= UDM_PROG_ADD_DREG0_DREG1; return UDM_TRUE;
4029 case UDM_ASSIGNMENT_SUB: *cmd= UDM_PROG_SUB_DREG0_DREG1; return UDM_TRUE;
4030 case UDM_ASSIGNMENT_MUL: *cmd= UDM_PROG_MUL_DREG0_DREG1; return UDM_TRUE;
4031 case UDM_ASSIGNMENT_DIV: *cmd= UDM_PROG_DIV_DREG0_DREG1; return UDM_TRUE;
4032 case UDM_ASSIGNMENT_REM:
4033 return UdmProgCompilerBadDataTypeForOperator2(c, "%=", dst, src);
4034 case UDM_ASSIGNMENT_AND:
4035 return UdmProgCompilerBadDataTypeForOperator2(c, "&=", dst, src);
4036 case UDM_ASSIGNMENT_OR:
4037 return UdmProgCompilerBadDataTypeForOperator2(c, "|=", dst, src);
4038 case UDM_ASSIGNMENT_XOR:
4039 return UdmProgCompilerBadDataTypeForOperator2(c, "^=", dst, src);
4040 case UDM_ASSIGNMENT_LSHIFT:
4041 return UdmProgCompilerBadDataTypeForOperator2(c, "<<=", dst, src);
4042 case UDM_ASSIGNMENT_RSHIFT:
4043 return UdmProgCompilerBadDataTypeForOperator2(c, ">>=", dst, src);
4044 }
4045 UDM_ASSERT(0);
4046 return UDM_FALSE;
4047 }
4048
4049
4050 static udm_bool_t
UdmSpecialAssignmentOpInt(UDM_PROG_COMPILER * c,udm_tmpl_cmd_t * cmd,udm_special_assignment_t op,const UDM_VALUE_HANDLER * dst,const UDM_VALUE_HANDLER * src)4051 UdmSpecialAssignmentOpInt(UDM_PROG_COMPILER *c,
4052 udm_tmpl_cmd_t *cmd, udm_special_assignment_t op,
4053 const UDM_VALUE_HANDLER *dst,
4054 const UDM_VALUE_HANDLER *src)
4055 {
4056 switch (op)
4057 {
4058 case UDM_ASSIGNMENT_ADD: *cmd= UDM_PROG_ADD_IREG0_IREG1; return UDM_TRUE;
4059 case UDM_ASSIGNMENT_SUB: *cmd= UDM_PROG_SUB_IREG0_IREG1; return UDM_TRUE;
4060 case UDM_ASSIGNMENT_MUL: *cmd= UDM_PROG_MUL_IREG0_IREG1; return UDM_TRUE;
4061 case UDM_ASSIGNMENT_DIV: *cmd= UDM_PROG_DIV_IREG0_IREG1; return UDM_TRUE;
4062 case UDM_ASSIGNMENT_REM: *cmd= UDM_PROG_REM_IREG0_IREG1; return UDM_TRUE;
4063 case UDM_ASSIGNMENT_AND: *cmd= UDM_PROG_AND_IREG0_IREG1; return UDM_TRUE;
4064 case UDM_ASSIGNMENT_OR: *cmd= UDM_PROG_OR_IREG0_IREG1; return UDM_TRUE;
4065 case UDM_ASSIGNMENT_XOR: *cmd= UDM_PROG_XOR_IREG0_IREG1; return UDM_TRUE;
4066 case UDM_ASSIGNMENT_LSHIFT: *cmd= UDM_PROG_SHL_IREG0_IREG1; return UDM_TRUE;
4067 case UDM_ASSIGNMENT_RSHIFT: *cmd= UDM_PROG_SHR_IREG0_IREG1; return UDM_TRUE;
4068 }
4069 UDM_ASSERT(0);
4070 return UDM_FALSE;
4071 }
4072
4073
4074 static udm_bool_t
UdmSpecialAssignmentOp(UDM_PROG_COMPILER * c,udm_tmpl_cmd_t * cmd,udm_special_assignment_t op,const UDM_VALUE_HANDLER * dst,const UDM_VALUE_HANDLER * src,const UDM_VALUE_HANDLER * agg)4075 UdmSpecialAssignmentOp(UDM_PROG_COMPILER *c,
4076 udm_tmpl_cmd_t *cmd,
4077 udm_special_assignment_t op,
4078 const UDM_VALUE_HANDLER *dst,
4079 const UDM_VALUE_HANDLER *src,
4080 const UDM_VALUE_HANDLER *agg)
4081 {
4082 UDM_ASSERT(!UdmValueHandlerIsComplex(agg));
4083 UDM_ASSERT(!UdmValueHandlerIsComplex(agg));
4084 return agg->native_reg_type == UDM_VALUE_DATA_TYPE_DOUBLE ?
4085 UdmSpecialAssignmentOpDouble(c, cmd, op, dst, src):
4086 UdmSpecialAssignmentOpInt(c, cmd, op, dst, src);
4087 }
4088
4089
4090 static udm_bool_t
UdmGenerateSpecialAssignmentConvertAndPerform(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * dst,const UDM_VALUE_HANDLER * src,udm_special_assignment_t op)4091 UdmGenerateSpecialAssignmentConvertAndPerform(UDM_PROG_COMPILER *compiler,
4092 const UDM_PROG_VAR *dst,
4093 const UDM_VALUE_HANDLER *src,
4094 udm_special_assignment_t op)
4095 {
4096 UDM_VALUE_HANDLER *agg=
4097 src->native_reg_type == UDM_VALUE_DATA_TYPE_DOUBLE ||
4098 UdmProgVarHandler(dst)->native_reg_type == UDM_VALUE_DATA_TYPE_DOUBLE ?
4099 &UdmValueHandlerDouble : &UdmValueHandlerInt;
4100 UDM_PROG_CMD *cmdstore= agg == &UdmValueHandlerDouble ?
4101 &udm_tmpl_set_var_from_dreg0 :
4102 &udm_tmpl_set_var_from_ireg0;
4103 udm_tmpl_cmd_t cmd;
4104 UDM_ASSERT(!UdmValueHandlerIsComplex(UdmProgVarHandler(dst)));
4105 UDM_ASSERT(!UdmValueHandlerIsComplex(src));
4106 return
4107 UdmSpecialAssignmentOp(compiler, &cmd, op,
4108 UdmProgVarHandler(dst), src, agg) &&
4109 UdmGenerateNativeReg0TypeConversion(compiler, agg,
4110 UdmProgVarHandler(dst)) &&
4111 UdmGenerateNativeReg1TypeConversion(compiler, agg, src) &&
4112 UDM_OK == UdmProgAddArg0SimpleOp(compiler->prg, cmd) &&
4113 UdmGenerateVariableOperation(compiler, dst, cmdstore);
4114 }
4115
4116
4117 /*
4118 Generate expression value in reg1,
4119 or move expression result from reg0 to reg1.
4120 Used to handle source expressions in special assignment operators,
4121 e.g. x<<=1.
4122 */
4123 static udm_bool_t
UdmGenerateExpressionToNativeReg1(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var,UDM_PROG_EXPRESSION * expr)4124 UdmGenerateExpressionToNativeReg1(UDM_PROG_COMPILER *compiler,
4125 const UDM_PROG_VAR *Var,
4126 UDM_PROG_EXPRESSION *expr)
4127 {
4128 switch (expr->primary_expr.type)
4129 {
4130 case UDM_EXPRESSION_CONST:
4131 expr->primary_expr.type= UDM_EXPRESSION_COMPUTED;
4132 return UdmGenerateLiteralToNativeRegN(compiler, &expr->primary_expr, 1);
4133 case UDM_EXPRESSION_IDENT:
4134 expr->primary_expr.type= UDM_EXPRESSION_COMPUTED;
4135 return UdmGenerateVarToNativeReg1(compiler, &expr->primary_expr.Var);
4136 case UDM_EXPRESSION_OBJECT:
4137 expr->primary_expr.type= UDM_EXPRESSION_COMPUTED;
4138 if (UdmValueHandlerIsComplex(UdmExprHandler(expr)))
4139 return UdmProgCompilerNotSupported(compiler, "Function of a complex return type in this context");
4140 case UDM_EXPRESSION_COMPUTED:
4141 return
4142 UdmGenerateMovNativeReg0ToReg1(compiler, UdmExprHandler(expr));
4143 }
4144 UDM_ASSERT(0);
4145 return UDM_FALSE;
4146 }
4147
4148
4149 static udm_bool_t
UdmGenerateExpressionSpecialAssignment(UDM_PROG_COMPILER * c,const UDM_PROG_VAR * Var,UDM_PROG_EXPRESSION * expr,udm_special_assignment_t op)4150 UdmGenerateExpressionSpecialAssignment(UDM_PROG_COMPILER *c,
4151 const UDM_PROG_VAR *Var,
4152 UDM_PROG_EXPRESSION *expr,
4153 udm_special_assignment_t op)
4154 {
4155
4156 return
4157 UdmGenerateExpressionToNativeReg1(c, Var, expr) &&
4158 UdmGenerateVarToNativeReg0(c, Var) &&
4159 UdmGenerateSpecialAssignmentConvertAndPerform(c, Var,
4160 UdmExprHandler(expr), op);
4161 }
4162
4163
4164 static udm_bool_t
UdmGenerateVarFromNativeReg0(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * dst)4165 UdmGenerateVarFromNativeReg0(UDM_PROG_COMPILER *compiler,
4166 const UDM_PROG_VAR *dst)
4167 {
4168 switch (UdmProgVarHandler(dst)->datatype)
4169 {
4170 case UDM_VALUE_DATA_TYPE_INT:
4171 case UDM_VALUE_DATA_TYPE_CHAR:
4172 return UdmGenerateVariableOperation(compiler, dst, &udm_tmpl_set_var_from_ireg0);
4173 case UDM_VALUE_DATA_TYPE_DOUBLE:
4174 return UdmGenerateVariableOperation(compiler, dst, &udm_tmpl_set_var_from_dreg0);
4175 default:
4176 return UdmGenerateVariableOperation(compiler, dst, &udm_tmpl_set_var_from_cs0_z0);
4177 }
4178 UDM_ASSERT(0);
4179 return UDM_FALSE;
4180 }
4181
4182
4183 /*
4184 @param name - variable name
4185 @param vname - value name (e.g. function)
4186 @param handler - value handler
4187 */
4188 static udm_bool_t
UdmGenerateVarAssignedFromFunctionCallResult(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * dst,const UDM_VALUE_HANDLER * function_type_handler)4189 UdmGenerateVarAssignedFromFunctionCallResult(UDM_PROG_COMPILER *compiler,
4190 const UDM_PROG_VAR *dst,
4191 const UDM_VALUE_HANDLER *function_type_handler)
4192 {
4193 switch (function_type_handler->datatype)
4194 {
4195 case UDM_VALUE_DATA_TYPE_INT:
4196 case UDM_VALUE_DATA_TYPE_DOUBLE:
4197 return
4198 UdmGenerateNativeReg0TypeConversion(compiler,
4199 UdmProgVarHandler(dst),
4200 function_type_handler) &&
4201 UdmGenerateVarFromNativeReg0(compiler, dst);
4202 case UDM_VALUE_DATA_TYPE_STR:
4203 {
4204 return
4205 UDM_OK == UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_MOV_HREG0_0) &&
4206 UDM_OK == UdmProgAddArg0SimpleOp(compiler->prg, UDM_PROG_MOV_SREG0_0);
4207 }
4208 case UDM_VALUE_DATA_TYPE_CHAR:
4209 case UDM_VALUE_DATA_TYPE_ENV:
4210 case UDM_VALUE_DATA_TYPE_RESULT:
4211 case UDM_VALUE_DATA_TYPE_DOCUMENT:
4212 case UDM_VALUE_DATA_TYPE_SQLRESULT:
4213 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
4214 break;
4215 }
4216 UDM_ASSERT(0);
4217 return UDM_FALSE;
4218 }
4219
4220
4221 static udm_bool_t
GenerateVarAssignedFromLiteral(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * dst,const UDM_PROG_PRIMARY_EXPRESSION * expr)4222 GenerateVarAssignedFromLiteral(UDM_PROG_COMPILER *compiler,
4223 const UDM_PROG_VAR *dst,
4224 const UDM_PROG_PRIMARY_EXPRESSION *expr)
4225 {
4226 UDM_PROG_ITEM i;
4227 switch (UdmPrimaryExprHandler(expr)->datatype)
4228 {
4229 case UDM_VALUE_DATA_TYPE_INT:
4230 case UDM_VALUE_DATA_TYPE_CHAR:
4231 case UDM_VALUE_DATA_TYPE_DOUBLE:
4232 return UdmGenerateLiteralToNativeRegN(compiler, expr, 0) &&
4233 UdmGenerateNativeReg0TypeConversion(compiler,
4234 UdmProgVarHandler(dst),
4235 UdmPrimaryExprHandler(expr)) &&
4236 UdmGenerateVarFromNativeReg0(compiler, dst);
4237 case UDM_VALUE_DATA_TYPE_ENV:
4238 case UDM_VALUE_DATA_TYPE_RESULT:
4239 case UDM_VALUE_DATA_TYPE_DOCUMENT:
4240 case UDM_VALUE_DATA_TYPE_SQLRESULT:
4241 case UDM_VALUE_DATA_TYPE_EXCERPT_FRAGMENT:
4242 UDM_ASSERT(0);
4243 /* Pass through */
4244 case UDM_VALUE_DATA_TYPE_STR:
4245 break;
4246 }
4247 UdmProgItemInit(&i);
4248 UdmProgItemArgInitFromVar(&i.item_args, dst);
4249 UdmProgItemArgInitFromLiteral(&i.item_args, &expr->Var.name, &expr->textdata_addr);
4250 i.cmd= &udm_tmpl_set_var_from_text0;
4251 return UdmProgAdd(compiler->prg, &i) == UDM_OK;
4252 }
4253
4254
4255 static udm_bool_t
GenerateVarAssignedFromVar(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * dst,const UDM_PROG_VAR * src)4256 GenerateVarAssignedFromVar(UDM_PROG_COMPILER *compiler,
4257 const UDM_PROG_VAR *dst,
4258 const UDM_PROG_VAR *src)
4259 {
4260 return UdmGenerateVarToNativeReg0(compiler, src) &&
4261 UdmGenerateNativeReg0TypeConversion(compiler,
4262 UdmProgVarHandler(dst),
4263 UdmProgVarHandler(src)) &&
4264 UdmGenerateVarFromNativeReg0(compiler, dst);
4265 }
4266
4267
4268 /**
4269 Generate an assignment:
4270 x= expr;
4271 The variable must be initialized
4272 (i.e. a contructor call was previously generated).
4273 */
4274 static udm_bool_t
UdmGenerateVarAssignmentFromExpression(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * dst,const UDM_PROG_EXPRESSION * expr)4275 UdmGenerateVarAssignmentFromExpression(UDM_PROG_COMPILER *compiler,
4276 const UDM_PROG_VAR *dst,
4277 const UDM_PROG_EXPRESSION *expr)
4278 {
4279 switch (expr->primary_expr.type)
4280 {
4281 case UDM_EXPRESSION_IDENT:
4282 return GenerateVarAssignedFromVar(compiler, dst, &expr->primary_expr.Var);
4283 case UDM_EXPRESSION_CONST:
4284 return GenerateVarAssignedFromLiteral(compiler, dst, &expr->primary_expr);
4285 case UDM_EXPRESSION_OBJECT:
4286 UDM_ASSERT(!UdmValueHandlerIsComplex(UdmExprHandler(expr)));
4287 return UdmGenerateVarAssignedFromFunctionCallResult(compiler, dst,
4288 UdmExprHandler(expr));
4289 case UDM_EXPRESSION_COMPUTED:
4290 return UdmGenerateNativeReg0TypeConversion(compiler,
4291 UdmProgVarHandler(dst),
4292 UdmExprHandler(expr)) &&
4293 UdmGenerateVarFromNativeReg0(compiler, dst);
4294 }
4295 UDM_ASSERT(0);
4296 return UdmProgCompilerNotSupported(compiler, "This type of <postfix epxression> as a variable initializer");
4297 }
4298
4299
4300 static udm_bool_t
UdmProgAddAssignmentNone(UDM_PROG_COMPILER * compiler,const UDM_PROG_EXPRESSION * expr)4301 UdmProgAddAssignmentNone(UDM_PROG_COMPILER *compiler,
4302 const UDM_PROG_EXPRESSION *expr)
4303 {
4304 if (0 && !ExpressionHasEffect(expr))
4305 {
4306 char tmp[128];
4307 size_t tmplen;
4308 tmplen= udm_snprintf(tmp, sizeof(tmp),
4309 "WARNING: statement has no effect: '%.*s'\n",
4310 (int) UdmConstTokenLength(&expr->primary_expr.Var.name),
4311 UdmConstTokenStr(&expr->primary_expr.Var.name));
4312 UdmProgGenerateCoutText(compiler, tmp, tmp + tmplen, UDM_TRUE);
4313 return UDM_TRUE;
4314 }
4315 return UDM_TRUE;
4316 }
4317
4318
4319 /**
4320 Parsee the right side of an assignment:
4321
4322 int x= expr;
4323 x= expr;
4324 x+= expr;
4325 */
4326 static udm_bool_t
UdmParseAssignmentSource(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_func_result_on_stack,const UDM_PROG_VAR * dstvar)4327 UdmParseAssignmentSource(UDM_PROG_COMPILER *compiler,
4328 UDM_PROG_EXPRESSION *expr,
4329 UDM_PROG_VAR *complex_func_result_on_stack,
4330 const UDM_PROG_VAR *dstvar)
4331 {
4332 UDM_BZERO(expr, sizeof(*expr));
4333 /* Notice, it's <assignment-expression> here, not <expression> */
4334 if (!UdmParseAssignmentExpression(compiler, expr,
4335 complex_func_result_on_stack, dstvar))
4336 return UdmProgCompilerExpectedRule(compiler, "<assignment-expression>");
4337 if (!UdmExprHandler(expr))
4338 return UdmProgCompilerVoidValueIsNotIgnored(compiler);
4339 return UDM_TRUE;
4340 }
4341
4342
4343 static udm_bool_t
UdmExpressionIsGoodAssignmentTarget(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr)4344 UdmExpressionIsGoodAssignmentTarget(UDM_PROG_COMPILER *compiler,
4345 UDM_PROG_EXPRESSION *expr)
4346 {
4347 switch (expr->primary_expr.type)
4348 {
4349 case UDM_EXPRESSION_IDENT:
4350 return UDM_TRUE;
4351 case UDM_EXPRESSION_CONST:
4352 case UDM_EXPRESSION_OBJECT:
4353 case UDM_EXPRESSION_COMPUTED:
4354 break;
4355 }
4356 return UdmProgCompilerNotSupported(compiler,
4357 "This type of expression as an assignment target");
4358 }
4359
4360
4361 static udm_bool_t
UdmFindAssignmentOperatorForArgs(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * handler,const UDM_PROG_FUNCTION_CALL_ARGUMENTS * args,const UDM_FUNCTION ** func)4362 UdmFindAssignmentOperatorForArgs(UDM_PROG_COMPILER *compiler,
4363 const UDM_VALUE_HANDLER *handler,
4364 const UDM_PROG_FUNCTION_CALL_ARGUMENTS *args,
4365 const UDM_FUNCTION **func)
4366 {
4367 if (!(func[0]= UdmValueHandlerMethodFind(handler,
4368 UDM_CSTR_WITH_LEN("operator="),
4369 args)))
4370 {
4371 UDM_CONST_TOKEN name;
4372 UdmConstTokenSet(&name, UDM_CSTR_WITH_LEN("operator="));
4373 return UdmProgCompilerUnknownMethodError(compiler, handler, &name, args);
4374 }
4375 return UDM_TRUE;
4376 }
4377
4378
4379 static udm_bool_t
UdmFindAssignmentOperator(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * dst,const UDM_VALUE_HANDLER * src,const UDM_FUNCTION ** func)4380 UdmFindAssignmentOperator(UDM_PROG_COMPILER *compiler,
4381 const UDM_VALUE_HANDLER *dst,
4382 const UDM_VALUE_HANDLER *src,
4383 const UDM_FUNCTION **func)
4384 {
4385 UDM_PROG_FUNCTION_CALL_ARGUMENTS args;
4386 UDM_BZERO(&args, sizeof(args));
4387 UdmProgVarSetHandler(&args.args[0].Var, src);
4388 args.args[0].type= UDM_EXPRESSION_IDENT;
4389 args.nargs= 1;
4390 return UdmFindAssignmentOperatorForArgs(compiler, dst, &args, func);
4391 }
4392
4393
4394 static udm_bool_t
UdmGenerateAssignmentOperator(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var,const UDM_PROG_PRIMARY_EXPRESSION * Src,udm_expression_t type)4395 UdmGenerateAssignmentOperator(UDM_PROG_COMPILER *compiler,
4396 const UDM_PROG_VAR *Var,
4397 const UDM_PROG_PRIMARY_EXPRESSION *Src,
4398 udm_expression_t type)
4399 {
4400 const UDM_FUNCTION *func;
4401 UDM_PROG_FUNCTION_CALL_ARGUMENTS args;
4402 UDM_BZERO(&args, sizeof(args));
4403 args.args[0].Var= Src[0].Var;
4404 args.args[0].textdata_addr= Src->textdata_addr;
4405 args.args[0].type= type;
4406 args.nargs= 1;
4407 return
4408 UdmFindAssignmentOperatorForArgs(compiler, UdmProgVarHandler(Var),
4409 &args, &func) &&
4410 UdmGenerateNewFunctionCall(compiler, func, Var, &args, NULL, Var);
4411 }
4412
4413
4414 /**
4415 Assign an expression to a variable.
4416 The variable must be initialized
4417 (i.e. a constructor call was previously generated).
4418 */
4419 static udm_bool_t
UdmGenerateAssignment(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var,const UDM_PROG_EXPRESSION * value,const UDM_PROG_PRIMARY_EXPRESSION * tmp)4420 UdmGenerateAssignment(UDM_PROG_COMPILER *compiler,
4421 const UDM_PROG_VAR *Var,
4422 const UDM_PROG_EXPRESSION *value,
4423 const UDM_PROG_PRIMARY_EXPRESSION *tmp)
4424 {
4425 if (UdmPrimaryExprHandler(tmp))
4426 {
4427 /*
4428 The expression was a function call returning a complex object.
4429 Copy temporary variable to the destination variable.
4430 */
4431 UDM_ASSERT(UdmValueHandlerIsComplex(UdmPrimaryExprHandler(tmp)));
4432 return UdmGenerateAssignmentOperator(compiler, Var, tmp,
4433 UDM_EXPRESSION_IDENT);
4434 }
4435 else if (!UdmValueHandlerIsComplex(UdmProgVarHandler(Var)))
4436 {
4437 if (!UdmDyadicOperatorFindWithError(compiler, assignment_operators,
4438 UdmProgVarHandler(Var),
4439 UdmExprHandler(value),
4440 "="))
4441 return UDM_FALSE;
4442 if (!UdmGenerateVarAssignmentFromExpression(compiler, Var, value))
4443 return UDM_FALSE;
4444
4445 }
4446 else
4447 {
4448 UDM_ASSERT(UdmValueHandlerIsComplex(UdmProgVarHandler(Var)));
4449 switch (value->primary_expr.type)
4450 {
4451 case UDM_EXPRESSION_IDENT:
4452 case UDM_EXPRESSION_CONST:
4453 return UdmGenerateAssignmentOperator(compiler, Var,
4454 &value->primary_expr,
4455 value->primary_expr.type);
4456 case UDM_EXPRESSION_OBJECT:
4457 UDM_ASSERT(0);
4458 return UDM_FALSE;
4459 case UDM_EXPRESSION_COMPUTED:
4460 {
4461 /*
4462 TODO: get rid of this.
4463 <conditional-expression> currenly returns complex values in cs0/z0.
4464 This is limited to string type only and should be changed
4465 to support all other complex data types.
4466 */
4467 const UDM_FUNCTION *func;
4468 if (!UdmFindAssignmentOperator(compiler,
4469 UdmProgVarHandler(Var),
4470 UdmExprHandler(value), &func))
4471 return UDM_FALSE;
4472 if (!UdmGenerateVarAssignmentFromExpression(compiler, Var, value))
4473 return UDM_FALSE;
4474 }
4475 break;
4476 }
4477 }
4478
4479 return UDM_TRUE;
4480 }
4481
4482
4483
4484 /**
4485 Parse the expression in the right side of an assignment,
4486 and generate the assignment.
4487 TODO: this crashes:
4488 string x= "abcd";
4489 string y;
4490 y= x.substr(1,3).substr(0,2).length();
4491 */
4492 static udm_bool_t
UdmParseAssignmentPart2(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * dst)4493 UdmParseAssignmentPart2(UDM_PROG_COMPILER *compiler,
4494 const UDM_PROG_VAR *dst)
4495 {
4496 /*
4497 For an expression like this:
4498 string x= "test"; x= x.left();
4499 we create a temporary variable for the function/method result,
4500 which then copied to the final destination.
4501 If there are multiple temporary values in the same <assignment-expression>:
4502 x= x.left(), y= y.left();
4503 then all temporary values destructed at once at the end
4504 (e.g. when the semicolon is read).
4505 */
4506 UDM_PROG_EXPRESSION rvalue;
4507 UDM_PROG_PRIMARY_EXPRESSION tmp;
4508 UDM_BZERO(&tmp, sizeof(tmp));
4509 tmp.type= UDM_EXPRESSION_IDENT; /*TODO: get rid if this, pass UDM_PROG_VAR*/
4510 return UdmParseAssignmentSource(compiler, &rvalue, &tmp.Var, NULL) &&
4511 UdmGenerateAssignment(compiler, dst, &rvalue, &tmp);
4512 }
4513
4514
4515 /**
4516 <assignment-expression> ::=
4517 <conditional-expression>
4518 | <unary-expression> <assignment-operator> <assignment-expression>
4519 */
4520 static udm_bool_t
UdmParseAssignmentExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_result_on_stack,const UDM_PROG_VAR * dstvar)4521 UdmParseAssignmentExpression(UDM_PROG_COMPILER *compiler,
4522 UDM_PROG_EXPRESSION *expr,
4523 UDM_PROG_VAR *complex_result_on_stack,
4524 const UDM_PROG_VAR *dstvar)
4525 {
4526 udm_special_assignment_t op;
4527 udm_tmpl_cmd_t cmd;
4528 if (!UdmParseConditionalExpression(compiler, expr,
4529 complex_result_on_stack, dstvar))
4530 return UDM_FALSE;
4531 if (ParseEqAssignmentOperator(compiler)) /* x= expression; */
4532 {
4533 return UdmExpressionIsGoodAssignmentTarget(compiler, expr) &&
4534 UdmParseAssignmentPart2(compiler, &expr->primary_expr.Var);
4535 }
4536 if (ParseSpecialAssignmentOperator(compiler, &op, &cmd)) /* e.g. x+= expression; */
4537 {
4538 UDM_PROG_EXPRESSION rvalue;
4539 UDM_PROG_VAR complex_result_on_stack2;
4540 UDM_BZERO(&complex_result_on_stack2, sizeof(complex_result_on_stack2));
4541 if (!UdmExpressionIsGoodAssignmentTarget(compiler, expr))
4542 return UDM_FALSE;
4543 if (!UdmParseAssignmentSource(compiler, &rvalue,
4544 &complex_result_on_stack2, NULL))
4545 return UDM_FALSE;
4546 if (!UdmDyadicOperatorFindWithError(compiler, assignment_operators,
4547 UdmExprHandler(expr),
4548 UdmExprHandler(&rvalue),
4549 UdmLex2str(cmd)))
4550 return UDM_FALSE;
4551 /* Special assignment operators for complex types are not supported yet */
4552 UDM_ASSERT(!UdmValueHandlerIsComplex(UdmExprHandler(&rvalue)));
4553 UDM_ASSERT(!UdmProgVarHandler(&complex_result_on_stack2));
4554 return UdmGenerateExpressionSpecialAssignment(compiler,
4555 &expr->primary_expr.Var,
4556 &rvalue, op);
4557 }
4558 if (!UdmProgAddAssignmentNone(compiler, expr))
4559 return UDM_FALSE;
4560 return UDM_TRUE;
4561 }
4562
4563
4564 /*
4565 <expression> ::= <assignment-expression> {, <assignment-expression> }
4566 */
4567 static udm_bool_t
UdmParseExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,UDM_PROG_VAR * complex_result_on_stack,const UDM_PROG_VAR * dstvar)4568 UdmParseExpression(UDM_PROG_COMPILER *compiler,
4569 UDM_PROG_EXPRESSION *expr,
4570 UDM_PROG_VAR *complex_result_on_stack,
4571 const UDM_PROG_VAR *dstvar)
4572 {
4573 if (!UdmParseAssignmentExpression(compiler, expr,
4574 complex_result_on_stack, dstvar))
4575 return UDM_FALSE;
4576 for ( ; ; )
4577 {
4578 if (!ParseTerm(compiler, UDM_LEX_COMMA))
4579 return UDM_TRUE;
4580 UDM_BZERO(expr, sizeof(*expr));
4581 if (!UdmParseAssignmentExpression(compiler, expr,
4582 complex_result_on_stack, dstvar))
4583 return UdmProgCompilerExpectedRule(compiler, "<assignment-expression>");
4584 }
4585 return UDM_TRUE;
4586 }
4587
4588
4589 /**
4590 Parse an assignment expression in its own block.
4591 If the expression returns a value which is not used,
4592 it needs to be destructed immediately, e.g.:
4593 {
4594 string str= "xxx";
4595 str.left();
4596 }
4597 UdmProgCompilerLeaveBlock makes sure it's destructed.
4598 This effectively converts expressions like:
4599 str.left();
4600 into
4601 {
4602 string str= str.left(); // str is destructed here
4603 }
4604 */
4605 static udm_bool_t
UdmParseExpressionIgnoreResult(UDM_PROG_COMPILER * compiler)4606 UdmParseExpressionIgnoreResult(UDM_PROG_COMPILER *compiler)
4607 {
4608 udm_bool_t rc;
4609 UDM_PROG_EXPRESSION expr;
4610 UDM_PROG_VAR complex_result_on_stack;
4611 UDM_BZERO(&expr, sizeof(expr));
4612 UDM_BZERO(&complex_result_on_stack, sizeof(complex_result_on_stack));
4613 if (!UdmProgCompilerEnterBlock(compiler))
4614 return UDM_FALSE;
4615 rc= UdmParseExpression(compiler, &expr,
4616 &complex_result_on_stack, NULL);
4617 if (!UdmProgCompilerLeaveBlock(compiler))
4618 return UDM_FALSE;
4619 return rc;
4620 }
4621
4622
4623 static udm_bool_t
UdmGenerateCoutReg0(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * handler)4624 UdmGenerateCoutReg0(UDM_PROG_COMPILER *compiler,
4625 const UDM_VALUE_HANDLER *handler)
4626 {
4627 switch (handler->type)
4628 {
4629 case UDM_VALUE_HANDLER_TYPE_CHAR:
4630 return UDM_OK == UdmProgAddArg0Simple(compiler->prg, &udm_tmpl_cout_ireg0_char);
4631 case UDM_VALUE_HANDLER_TYPE_INT:
4632 return UDM_OK == UdmProgAddArg0Simple(compiler->prg, &udm_tmpl_cout_ireg0);
4633 case UDM_VALUE_HANDLER_TYPE_DOUBLE:
4634 return UDM_OK == UdmProgAddArg0Simple(compiler->prg, &udm_tmpl_cout_dreg0);
4635 case UDM_VALUE_HANDLER_TYPE_STR:
4636 case UDM_VALUE_HANDLER_TYPE_ENV:
4637 case UDM_VALUE_HANDLER_TYPE_RESULT:
4638 case UDM_VALUE_HANDLER_TYPE_DOCUMENT:
4639 case UDM_VALUE_HANDLER_TYPE_SQLRESULT:
4640 case UDM_VALUE_HANDLER_TYPE_EXCERPT_FRAGMENT:
4641 return UDM_OK == UdmProgAddArg0Simple(compiler->prg, &udm_tmpl_cout_cs0_z0);
4642 }
4643 UDM_ASSERT(0);
4644 return UDM_FALSE;
4645 }
4646
4647
4648 /*
4649 Return UDM_TRUE on success, UDM_FALSE on error.
4650 */
4651 static udm_bool_t
UdmGenerateCoutExpression(UDM_PROG_COMPILER * compiler,UDM_PROG_EXPRESSION * expr,const UDM_PROG_VAR * func_result)4652 UdmGenerateCoutExpression(UDM_PROG_COMPILER *compiler,
4653 UDM_PROG_EXPRESSION *expr,
4654 const UDM_PROG_VAR *func_result)
4655 {
4656 udm_expression_t orig_type= expr->primary_expr.type;
4657 if (!UdmGenerateExpressionToNativeReg0(compiler, expr, func_result))
4658 return UDM_FALSE;
4659 switch (orig_type)
4660 {
4661 case UDM_EXPRESSION_IDENT:
4662 case UDM_EXPRESSION_CONST:
4663 case UDM_EXPRESSION_COMPUTED:
4664 return UdmGenerateCoutReg0(compiler, UdmExprHandler(expr));
4665 case UDM_EXPRESSION_OBJECT:
4666 if (!UdmExprHandler(expr))
4667 return UdmProgCompilerVoidValueIsNotIgnored(compiler);
4668 if (UdmProgVarHandler(func_result))
4669 {
4670 UDM_ASSERT(UdmProgVarHandler(func_result) == UdmExprHandler(expr));
4671 UDM_ASSERT(UdmValueHandlerIsComplex(UdmExprHandler(expr)));
4672 return UdmGenerateCoutReg0(compiler, UdmProgVarHandler(func_result));
4673 }
4674 else
4675 {
4676 UDM_ASSERT(!UdmValueHandlerIsComplex(UdmExprHandler(expr)));
4677 return UdmGenerateCoutReg0(compiler, UdmExprHandler(expr));
4678 }
4679 }
4680 UDM_ASSERT(0);
4681 return UDM_FALSE;
4682 }
4683
4684
4685 static udm_bool_t
ParseEchoExpression(UDM_PROG_COMPILER * compiler)4686 ParseEchoExpression(UDM_PROG_COMPILER *compiler)
4687 {
4688 UDM_PROG_EXPRESSION expr;
4689 if (!ParseTerm(compiler, UDM_LEX_COUT))
4690 return UDM_FALSE;
4691 if (!ParseTermOrError(compiler, UDM_LEX_LSHIFT))
4692 return UDM_FALSE;
4693 for ( ; ; )
4694 {
4695 UDM_PROG_VAR func_result;
4696 bzero(&func_result, sizeof(UDM_PROG_VAR));
4697 if (!UdmProgCompilerEnterBlock(compiler)) /* In case if expr is a function call */
4698 return UDM_FALSE;
4699 if (!ParseAdditiveExpression(compiler, &expr, &func_result, NULL))
4700 return UDM_FALSE;
4701 if (!UdmGenerateCoutExpression(compiler, &expr, &func_result))
4702 return UDM_FALSE;
4703 if (!UdmProgCompilerLeaveBlock(compiler))
4704 return UDM_FALSE;
4705 if (!ParseTerm(compiler, UDM_LEX_LSHIFT))
4706 break;
4707 }
4708 return UDM_TRUE;
4709 }
4710
4711
4712 /*
4713 <expression-statement> ::= {<expression>}? ;
4714 */
4715 static udm_bool_t
ParseExpressionStatement(UDM_PROG_COMPILER * compiler)4716 ParseExpressionStatement(UDM_PROG_COMPILER *compiler)
4717 {
4718 if (ParseEchoExpression(compiler))
4719 return ParseTermOrError(compiler, UDM_LEX_SEMICOLON);
4720 if (UdmParseExpressionIgnoreResult(compiler))
4721 return ParseTermOrError(compiler, UDM_LEX_SEMICOLON);
4722 return ParseTerm(compiler, UDM_LEX_SEMICOLON);
4723 }
4724
4725
4726 static udm_bool_t ParseStatement(UDM_PROG_COMPILER *compiler);
4727
4728
4729 static udm_bool_t
ParseIfCondition(UDM_PROG_COMPILER * compiler)4730 ParseIfCondition(UDM_PROG_COMPILER *compiler)
4731 {
4732 UDM_PROG_EXPRESSION expr;
4733 return
4734 UdmParseExpression(compiler, &expr, NULL, NULL) &&
4735 UdmGenerateExpressionToBool(compiler, &expr);
4736 }
4737
4738
4739 static udm_bool_t
ParseParenthesizedCondition(UDM_PROG_COMPILER * compiler)4740 ParseParenthesizedCondition(UDM_PROG_COMPILER *compiler)
4741 {
4742 if (!ParseTermOrError(compiler, UDM_LEX_LP))
4743 return UDM_FALSE;
4744 if (!ParseIfCondition(compiler))
4745 return UDM_FALSE;
4746 if (!ParseTermOrError(compiler, UDM_LEX_RP))
4747 return UDM_FALSE;
4748 return UDM_TRUE;
4749 }
4750
4751
4752 /*
4753 <selection-statement> ::= if ( <expression> ) <statement>
4754 | if ( <expression> ) <statement> else <statement>
4755 | switch ( <expression> ) <statement>
4756 */
ParseSelectionStatement(UDM_PROG_COMPILER * compiler)4757 static udm_bool_t ParseSelectionStatement(UDM_PROG_COMPILER *compiler)
4758 {
4759 size_t jne_to_end_of_if_block;
4760 if (!ParseTerm(compiler, UDM_LEX_IF))
4761 return UDM_FALSE;
4762 if (!ParseParenthesizedCondition(compiler))
4763 return UDM_FALSE;
4764
4765 /* jne to end_of_if_block if the condition failed */
4766 jne_to_end_of_if_block= UdmProgCompilerGetProg(compiler)->nitems;
4767 if (UdmProgAddJmp(compiler->prg, UDM_PROG_JE, 0))
4768 return UDM_FALSE;
4769
4770 if (!ParseStatement(compiler))
4771 return UdmProgCompilerExpectedRule(compiler, "<statement>");
4772
4773 if (ParseTerm(compiler, UDM_LEX_ELSE))
4774 {
4775 /*
4776 We are at the end of the "if" block, and there is "else".
4777 Add unconditional JMP to the end of "else".
4778 */
4779 size_t start_of_else= UdmProgCompilerGetProg(compiler)->nitems;
4780 if (UdmProgAddJmp(compiler->prg, UDM_PROG_JMP, 0))
4781 return UDM_FALSE;
4782
4783 /*
4784 Now we know the start address of the "else" block.
4785 Fix the jump address of the command pointed by jne_to_end_of_if_block
4786 to the current address, which is the beginning of the "else" block.
4787 */
4788 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler),
4789 jne_to_end_of_if_block,
4790 jne_to_end_of_if_block + 1);
4791 if (!ParseStatement(compiler))
4792 return UdmProgCompilerExpectedRule(compiler, "<statement>");
4793
4794 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler),
4795 start_of_else, start_of_else + 1);
4796 }
4797 else
4798 {
4799 /*
4800 No else, just fix the command pointed by
4801 jne_to_end_of_if_block to jump to the current address,
4802 which is the end of the entire "if" statement.
4803 */
4804 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler),
4805 jne_to_end_of_if_block,
4806 jne_to_end_of_if_block + 1);
4807 }
4808 return UDM_TRUE;
4809 }
4810
4811
4812 /*
4813 while ( <expression> ) <statement>
4814 */
4815 static udm_bool_t
ParseWhileStatement(UDM_PROG_COMPILER * compiler)4816 ParseWhileStatement(UDM_PROG_COMPILER *compiler)
4817 {
4818 size_t backup_current_loop_continue;
4819 if (!ParseTerm(compiler, UDM_LEX_WHILE))
4820 return UDM_FALSE;
4821 backup_current_loop_continue= compiler->current_loop_continue;
4822 compiler->current_loop_continue= UdmProgCompilerGetProg(compiler)->nitems;
4823 if (!ParseParenthesizedCondition(compiler))
4824 return UDM_FALSE;
4825
4826 /* Break the loop if the condition failed */
4827 if (UdmProgAddJmpWithComment(compiler->prg,
4828 UDM_PROG_JE, 0, "while condition failed"))
4829 return UDM_FALSE;
4830
4831 if (!ParseStatement(compiler))
4832 return UdmProgCompilerExpectedRule(compiler, "<statement>");
4833
4834 /* Jump to the beginning */
4835 if (UdmProgAddJmpWithComment(compiler->prg, UDM_PROG_JMP,
4836 compiler->current_loop_continue,
4837 "implicit continue"))
4838 return UDM_FALSE;
4839
4840 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler),
4841 compiler->current_loop_continue,
4842 UdmProgCompilerGetProg(compiler)->nitems - 1);
4843 compiler->current_loop_continue= backup_current_loop_continue;
4844 return UDM_TRUE;
4845 }
4846
4847
4848 static udm_bool_t
4849 ParseDeclaration(UDM_PROG_COMPILER *compiler);
4850
4851
4852 static udm_bool_t
UdmParseForStatementInitialization(UDM_PROG_COMPILER * compiler)4853 UdmParseForStatementInitialization(UDM_PROG_COMPILER *compiler)
4854 {
4855 return ParseDeclaration(compiler) ||
4856 UdmParseExpressionIgnoreResult(compiler);
4857 }
4858
4859
4860 /*
4861 The C grammar looks like:
4862 for ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>
4863
4864 We allow declaraions:
4865 for ( {<declaration>|<expression>}? ;
4866 {<expression>}? ;
4867 {<expression>}? )
4868 <statement>
4869 */
4870 static udm_bool_t
ParseForStatement(UDM_PROG_COMPILER * compiler)4871 ParseForStatement(UDM_PROG_COMPILER *compiler)
4872 {
4873 udm_bool_t has_finalize_expression;
4874 size_t condition, finalize_expression, backup_current_loop_continue;
4875 if (!ParseTerm(compiler, UDM_LEX_FOR))
4876 return UDM_FALSE;
4877 if (!ParseTermOrError(compiler, UDM_LEX_LP))
4878 return UDM_FALSE;
4879 /*
4880 Create its own level, in case the initialization part will
4881 declare variables.
4882 */
4883 if (!UdmProgCompilerEnterBlock(compiler))
4884 return UDM_FALSE;
4885 /* Optional for-init expression */
4886 if (!UdmParseForStatementInitialization(compiler) &&
4887 UdmProgCompilerError(compiler))
4888 return UDM_FALSE;
4889 if (!ParseTermOrError(compiler, UDM_LEX_SEMICOLON))
4890 return UDM_FALSE;
4891
4892 /* Condition expression, currently non-optional */
4893 condition= UdmProgCompilerGetProg(compiler)->nitems;
4894 if (!ParseIfCondition(compiler))
4895 return UDM_FALSE;
4896 /* Break the loop if the condition <expression> failed */
4897 if (UdmProgAddJmpWithComment(compiler->prg,
4898 UDM_PROG_JE, 0, "to the FOR end"))
4899 return UDM_FALSE;
4900 if (!ParseTermOrError(compiler, UDM_LEX_SEMICOLON))
4901 return UDM_FALSE;
4902
4903 /* Jump to the body <statement> */
4904 if (UdmProgAddJmpWithComment(compiler->prg,
4905 UDM_PROG_JMP, 0, "to the FOR body statement"))
4906 return UDM_FALSE;
4907
4908 /* Optional for-finalize <expression> */
4909 finalize_expression= UdmProgCompilerGetProg(compiler)->nitems;
4910 if (!(has_finalize_expression= UdmParseExpressionIgnoreResult(compiler)) &&
4911 UdmProgCompilerError(compiler))
4912 return UDM_FALSE;
4913 /* Go to the condition <expression> after for-finalize <expression> is done */
4914 if (UdmProgAddJmpWithComment(compiler->prg,
4915 UDM_PROG_JMP, condition,
4916 "to the FOR condition"))
4917 return UDM_FALSE;
4918 if (!ParseTermOrError(compiler, UDM_LEX_RP))
4919 return UDM_FALSE;
4920
4921 /*
4922 Fix JMP after condition and before finalize_expression
4923 to the address of the body <statement>.
4924 */
4925 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler),
4926 finalize_expression - 1,
4927 finalize_expression);
4928 backup_current_loop_continue= compiler->current_loop_continue;
4929 compiler->current_loop_continue= has_finalize_expression ?
4930 finalize_expression : condition;
4931 if (!ParseStatement(compiler))
4932 return UdmProgCompilerExpectedRule(compiler, "<statement>");
4933
4934 /* Jump to for_finalize <expression> or to the condition <expression> */
4935 if (UdmProgAddJmpWithComment(compiler->prg, UDM_PROG_JMP,
4936 has_finalize_expression ?
4937 finalize_expression : condition,
4938 has_finalize_expression ?
4939 "to the FOR finalize expression" :
4940 "to the FOR condition"))
4941 return UDM_FALSE;
4942
4943 /* Fix the jump after the condition failure to the end of the loop */
4944 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler),
4945 condition,
4946 UdmProgCompilerGetProg(compiler)->nitems - 1);
4947
4948 compiler->current_loop_continue= backup_current_loop_continue;
4949 return UdmProgCompilerLeaveBlock(compiler);
4950 }
4951
4952
4953 /*
4954 do <statement> while ( <expression> ) ;
4955 */
4956 static udm_bool_t
ParseDoStatement(UDM_PROG_COMPILER * compiler)4957 ParseDoStatement(UDM_PROG_COMPILER *compiler)
4958 {
4959 size_t backup_current_loop_continue;
4960 if (!ParseTerm(compiler, UDM_LEX_DO))
4961 return UDM_FALSE;
4962
4963 backup_current_loop_continue= compiler->current_loop_continue;
4964 compiler->current_loop_continue= UdmProgCompilerGetProg(compiler)->nitems;
4965
4966 if (!ParseStatement(compiler))
4967 return UdmProgCompilerExpectedRule(compiler, "<statement>");
4968
4969 if (!ParseTermOrError(compiler, UDM_LEX_WHILE))
4970 return UDM_FALSE;
4971
4972 if (!ParseParenthesizedCondition(compiler))
4973 return UDM_FALSE;
4974
4975 /* Jump to the beginning if the condition is true */
4976 if (UdmProgAddJmp(compiler->prg, UDM_PROG_JNE, compiler->current_loop_continue))
4977 return UDM_FALSE;
4978 /* Fix jumps for "break" statements */
4979 UdmProgFixJumpInRange(UdmProgCompilerGetProg(compiler),
4980 compiler->current_loop_continue,
4981 UdmProgCompilerGetProg(compiler)->nitems - 1);
4982 compiler->current_loop_continue= backup_current_loop_continue;
4983 return UDM_TRUE;
4984 }
4985
4986
4987 /*
4988 <iteration-statement> ::= while ( <expression> ) <statement>
4989 | do <statement> while ( <expression> ) ;
4990 | for ( {<expression>}? ; {<expression>}? ; {<expression>}? ) <statement>
4991 */
4992 static udm_bool_t
ParseIterationStatement(UDM_PROG_COMPILER * compiler)4993 ParseIterationStatement(UDM_PROG_COMPILER *compiler)
4994 {
4995 return
4996 ParseWhileStatement(compiler) ||
4997 ParseDoStatement(compiler) ||
4998 ParseForStatement(compiler);
4999 }
5000
5001
5002 static udm_bool_t
UdmProgCompilerNotWithin(UDM_PROG_COMPILER * compiler,const char * item,const char * where)5003 UdmProgCompilerNotWithin(UDM_PROG_COMPILER *compiler, const char *item, const char *where)
5004 {
5005 udm_snprintf(compiler->errstr, sizeof(compiler->errstr),
5006 "'%s' not within a %s", item, where);
5007 return UDM_FALSE;
5008 }
5009
5010
5011 static udm_bool_t
ParseJumpStatement(UDM_PROG_COMPILER * compiler)5012 ParseJumpStatement(UDM_PROG_COMPILER *compiler)
5013 {
5014 if (ParseTerm(compiler, UDM_LEX_CONTINUE))
5015 {
5016 if (!compiler->current_loop_continue)
5017 return UdmProgCompilerNotWithin(compiler, "continue", "loop");
5018 return UDM_OK == UdmProgAddJmpWithComment(compiler->prg,
5019 UDM_PROG_JMP,
5020 compiler->current_loop_continue,
5021 "explicit continue");
5022 }
5023 if (ParseTerm(compiler, UDM_LEX_BREAK))
5024 {
5025 if (!compiler->current_loop_continue)
5026 return UdmProgCompilerNotWithin(compiler, "continue", "loop or switch");
5027 return UDM_OK == UdmProgAddJmpWithComment(compiler->prg,
5028 UDM_PROG_JMP, 0, "break");
5029 }
5030 return UDM_FALSE;
5031 }
5032
5033
5034 static udm_bool_t
UdmLexScannerScanUntilNativePIStart(UDM_PROG_COMPILER * compiler)5035 UdmLexScannerScanUntilNativePIStart(UDM_PROG_COMPILER *compiler)
5036 {
5037 const UDM_CONST_STR native= {UDM_CSTR_WITH_LEN("<?mnogosearch")};
5038 return UdmLexScannerScanUntil(&compiler->scanner, &native,
5039 UDM_LEX_TEXT, UDM_LEX_EOF);
5040 }
5041
5042
5043 /*
5044 Embedded text:
5045 ?>some text<?mnogosearch
5046
5047 */
5048 static udm_bool_t
ParseEmbeddedTextStatement(UDM_PROG_COMPILER * compiler)5049 ParseEmbeddedTextStatement(UDM_PROG_COMPILER *compiler)
5050 {
5051 const char *start, *end;
5052 if (UdmProgCompilerLastTokenType(compiler) != UDM_LEX_QUESTION)
5053 return UDM_FALSE;
5054 if (UdmLexScannerCur(&compiler->scanner)[0] != '>')
5055 return UDM_FALSE;
5056 start= UdmLexScannerCur(&compiler->scanner) + 1; /* Skip '>' */
5057 UdmLexScannerScanUntilNativePIStart(compiler);
5058 end= compiler->scanner.token.token.end;
5059 /* Skip the newline that immediately follows the closing '?>' */
5060 if (start < end && *start == '\r')
5061 start++;
5062 if (start < end && *start == '\n')
5063 start++;
5064 UdmProgGenerateCoutText(compiler, start, end, UDM_FALSE);
5065 UdmProgCompilerScan(compiler);
5066 return UDM_TRUE;
5067 }
5068
5069
5070 static udm_bool_t ParseCompoundStatement(UDM_PROG_COMPILER *compilerarser);
5071 /*
5072 <statement> ::= <labeled-statement>
5073 | <expression-statement>
5074 | <compound-statement>
5075 | <selection-statement>
5076 | <iteration-statement>
5077 | <jump-statement>
5078 */
5079 static udm_bool_t
ParseStatement(UDM_PROG_COMPILER * compiler)5080 ParseStatement(UDM_PROG_COMPILER *compiler)
5081 {
5082 return ParseExpressionStatement(compiler) ||
5083 ParseSelectionStatement(compiler) ||
5084 ParseIterationStatement(compiler) ||
5085 ParseJumpStatement(compiler) ||
5086 ParseCompoundStatement(compiler) ||
5087 ParseEmbeddedTextStatement(compiler);
5088 }
5089
5090
5091 static udm_bool_t
ParseStatementList(UDM_PROG_COMPILER * compiler)5092 ParseStatementList(UDM_PROG_COMPILER *compiler)
5093 {
5094 for ( ; ; )
5095 {
5096 if (!ParseStatement(compiler))
5097 {
5098 if (UdmProgCompilerError(compiler))
5099 return UDM_FALSE;
5100 break;
5101 }
5102 }
5103 return UDM_TRUE;
5104 }
5105
5106
5107 /*
5108 <direct-declarator> ::= <identifier>
5109 | ( <declarator> )
5110 | <direct-declarator> [ {<constant-expression>}? ]
5111 | <direct-declarator> ( <parameter-type-list> )
5112 | <direct-declarator> ( {<identifier>}* )
5113 */
5114 static udm_bool_t
ParseDirectDeclarator(UDM_PROG_COMPILER * compiler,UDM_CONST_TOKEN * Var)5115 ParseDirectDeclarator(UDM_PROG_COMPILER *compiler, UDM_CONST_TOKEN *Var)
5116 {
5117 if (UdmProgCompilerLastTokenType(compiler) == UDM_LEX_IDENT)
5118 *Var= compiler->scanner.token.token;
5119 return ParseTerm(compiler, UDM_LEX_IDENT);
5120 }
5121
5122
5123 /*
5124 <declarator> ::= {<pointer>}? <direct-declarator>
5125 */
5126 static udm_bool_t
ParseDeclarator(UDM_PROG_COMPILER * compiler,UDM_CONST_TOKEN * Var)5127 ParseDeclarator(UDM_PROG_COMPILER *compiler, UDM_CONST_TOKEN *Var)
5128 {
5129 return ParseDirectDeclarator(compiler, Var);
5130 }
5131
5132
5133 /*
5134 TODO:
5135 <initializer> ::= <assignment-expression>
5136 | { <initializer-list> }
5137 | { <initializer-list> , }
5138 */
5139 static udm_bool_t
ParseVarInitializer(UDM_PROG_COMPILER * compiler,const UDM_PROG_VAR * Var)5140 ParseVarInitializer(UDM_PROG_COMPILER *compiler, const UDM_PROG_VAR *Var)
5141 {
5142 return UdmParseAssignmentPart2(compiler, Var);
5143 }
5144
5145
5146 /*
5147 <init-declarator> ::= <declarator>
5148 | <declarator> = <initializer>
5149 */
5150 static udm_bool_t
ParseInitDeclarator(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * ha)5151 ParseInitDeclarator(UDM_PROG_COMPILER *compiler, const UDM_VALUE_HANDLER *ha)
5152 {
5153 UDM_PROG_VAR Var;
5154 if (!ParseDeclarator(compiler, &Var.name))
5155 return UDM_FALSE;
5156
5157 UdmProgStackVarInitAttributes(&Var, compiler, ha);
5158 if (!UdmGenerateDeclareNonInitializedVariable(compiler, &Var))
5159 return UDM_FALSE;
5160 if (!UdmGenerateConstructor(compiler, &Var))
5161 return UDM_FALSE;
5162 if (!ParseTerm(compiler, UDM_LEX_EQ))
5163 return UDM_TRUE;
5164 if (!ParseVarInitializer(compiler, &Var))
5165 return UdmProgCompilerExpectedRule(compiler, "<initializer>");
5166 return UDM_TRUE;
5167 }
5168
5169
5170 static udm_bool_t
ParseOptInitDeclaratorList(UDM_PROG_COMPILER * compiler,const UDM_VALUE_HANDLER * ha)5171 ParseOptInitDeclaratorList(UDM_PROG_COMPILER *compiler,
5172 const UDM_VALUE_HANDLER *ha)
5173 {
5174 /*
5175 Check for an empty declaration,
5176 type not followed by an identifier name, e.g.:
5177 { int; }
5178 */
5179 if (!ParseInitDeclarator(compiler, ha))
5180 return UdmProgCompilerGenericError(compiler,
5181 "declaration does not declare anything");
5182 while (ParseTerm(compiler, UDM_LEX_COMMA))
5183 {
5184 if (!ParseInitDeclarator(compiler, ha))
5185 return UdmProgCompilerExpectedRule(compiler, "<init-declarator>");
5186 }
5187 return UDM_TRUE;
5188 }
5189
5190
5191 /*
5192 <declaration> ::= {<declaration-specifier>}+ {<init-declarator>}*
5193 */
5194 static udm_bool_t
ParseDeclaration(UDM_PROG_COMPILER * compiler)5195 ParseDeclaration(UDM_PROG_COMPILER *compiler)
5196 {
5197 const UDM_VALUE_HANDLER *ha;
5198 if (!ParseDeclarationSpecifier(compiler, &ha))
5199 return UDM_FALSE;
5200 if (!ParseOptInitDeclaratorList(compiler, ha) &&
5201 UdmProgCompilerError(compiler))
5202 return UDM_FALSE;
5203 return UDM_TRUE;
5204 }
5205
5206
5207 static udm_bool_t
ParseOptDeclarationList(UDM_PROG_COMPILER * compiler)5208 ParseOptDeclarationList(UDM_PROG_COMPILER *compiler)
5209 {
5210 for ( ; ; )
5211 {
5212 if (!ParseDeclaration(compiler))
5213 {
5214 if (UdmProgCompilerError(compiler))
5215 return UDM_FALSE;
5216 break;
5217 }
5218 if (!ParseTermOrError(compiler, UDM_LEX_SEMICOLON))
5219 return UDM_FALSE;
5220 }
5221 return UDM_TRUE;
5222 }
5223
5224
5225 /*
5226 <compound-statement> ::= { {<declaration>}* {<statement>}* }
5227 */
5228 static udm_bool_t
ParseCompoundStatement(UDM_PROG_COMPILER * compiler)5229 ParseCompoundStatement(UDM_PROG_COMPILER *compiler)
5230 {
5231 if (!ParseLCB(compiler))
5232 return UDM_FALSE;
5233 if (!UdmProgCompilerEnterBlock(compiler))
5234 return UDM_FALSE;
5235 if (!ParseOptDeclarationList(compiler))
5236 return UDM_FALSE;
5237 if (!ParseStatementList(compiler))
5238 return !UdmProgCompilerError(compiler);
5239 if (!UdmProgCompilerLeaveBlock(compiler))
5240 return UDM_FALSE;
5241 return ParseTermOrError(compiler, UDM_LEX_RCB);
5242 }
5243
5244
5245 static udm_bool_t
ParsePI(UDM_PROG_COMPILER * compiler)5246 ParsePI(UDM_PROG_COMPILER *compiler)
5247 {
5248 if (!UdmProgCompilerEnterBlock(compiler))
5249 return UDM_FALSE;
5250 if (!ParseOptDeclarationList(compiler))
5251 return UDM_FALSE;
5252 if (!ParseStatementList(compiler))
5253 return UDM_FALSE;
5254 if (!UdmProgCompilerLeaveBlock(compiler))
5255 return UDM_FALSE;
5256 return ParseTermOrError(compiler, UDM_LEX_EOF);
5257 }
5258
5259
5260 udm_rc_t
UdmCompilePI(UDM_PROG_COMPILER * compiler,const UDM_CONST_STR * src)5261 UdmCompilePI(UDM_PROG_COMPILER *compiler, const UDM_CONST_STR *src)
5262 {
5263 udm_bool_t rc;
5264 UdmPIParserInit(compiler, src->str, src->length);
5265 UdmProgCompilerScan(compiler);
5266 if (!(rc= ParsePI(compiler)))
5267 {
5268 char tmp[124];
5269 size_t tmplen;
5270 tmplen= udm_snprintf(tmp, sizeof(tmp), "%s\n", compiler->errstr);
5271 UdmProgGenerateCoutText(compiler, tmp, tmp + tmplen, UDM_FALSE);
5272 }
5273 /*
5274 for (UdmProgCompilerScan(&parser);
5275 parser.scanner.token.type != UDM_LEX_UNKNOWN &&
5276 parser.scanner.token.type != UDM_LEX_EOF ;
5277 UdmProgCompilerScan(&parser))
5278 {
5279 }
5280 */
5281 UdmPIParserFree(compiler);
5282 return UDM_OK;
5283 }
5284
5285
5286 static udm_bool_t
UdmProgCompilerScanPrefixText(UDM_PROG_COMPILER * compiler)5287 UdmProgCompilerScanPrefixText(UDM_PROG_COMPILER *compiler)
5288 {
5289 if (!UdmLexScannerScanUntilNativePIStart(compiler))
5290 return UDM_TRUE;
5291 UdmProgGenerateCoutText(compiler,
5292 compiler->scanner.token.token.str,
5293 compiler->scanner.token.token.end,
5294 UDM_FALSE);
5295 compiler->pi_count++;
5296 UdmProgCompilerScan(compiler); /* For look-ahead */
5297 return UDM_TRUE;
5298 }
5299
5300
5301 static udm_bool_t
ParsePIProgram(UDM_PROG_COMPILER * compiler)5302 ParsePIProgram(UDM_PROG_COMPILER *compiler)
5303 {
5304 if (!UdmProgCompilerEnterBlock(compiler))
5305 return UDM_FALSE;
5306 if (!UdmProgCompilerScanPrefixText(compiler))
5307 return UDM_FALSE;
5308 if (!ParseOptDeclarationList(compiler))
5309 return UDM_FALSE;
5310 if (!ParseStatementList(compiler))
5311 return UDM_FALSE;
5312 if (!UdmProgCompilerLeaveBlock(compiler))
5313 return UDM_FALSE;
5314 return ParseTermOrError(compiler, UDM_LEX_EOF);
5315 }
5316
5317
5318 udm_rc_t
UdmCompilePIProgram(UDM_PROG_COMPILER * compiler,const UDM_CONST_STR * src)5319 UdmCompilePIProgram(UDM_PROG_COMPILER *compiler, const UDM_CONST_STR *src)
5320 {
5321 udm_bool_t rc;
5322 UdmPIParserInit(compiler, src->str, src->length);
5323 if (!(rc= ParsePIProgram(compiler)))
5324 {
5325 char tmp[124];
5326 size_t tmplen;
5327 tmplen= udm_snprintf(tmp, sizeof(tmp), "%s\n", compiler->errstr);
5328 UdmProgGenerateCoutText(compiler, tmp, tmp + tmplen, UDM_FALSE);
5329 }
5330 UdmPIParserFree(compiler);
5331 return rc == UDM_TRUE ? UDM_OK : UDM_ERROR;
5332 }
5333