"Fossies" - the Fresh Open Source Software Archive 
Member "ncc-2.8/ccexpr.C" (13 Sep 2006, 30195 Bytes) of package /linux/privat/old/ncc-2.8.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*****************************************************************************
2
3 compiler of C expressions to bytecode
4
5 *****************************************************************************/
6 #include <stdio.h>
7 #include <assert.h>
8
9 #include "global.h"
10
11 int last_result;
12 /******************************************************************************
13
14
15
16
17
18 ******************************************************************************/
19
20 int *assembly;
21 int ap;
22
23 # define TSI 's'
24 # define TUI 'u'
25 # define TFP 'f'
26 # define TPTR 'p'
27 # define TREC 'r'
28 # define TBF 'b'
29 #define CONVI '}'
30 #define CONVF '\\'
31 #define EST '$'
32 #define ENI 'N'
33 #define ENP 'P'
34 #define EIN 'I'
35 #define ENF 'F'
36 #define ESMB 'S'
37 #define ENL 'A'
38 #define JMP 'J' // escape to JMP[TFA]
39 # define JMPT 't'
40 # define JMPF 'f'
41 # define JMPA 'a'
42 #define LABEL 'L'
43 #define TEST 'T'
44 #define CALL 'C'
45 #define COPYREC 'Q'
46 #define RESULT 'R'
47 #define NOOP ' '
48 #define EEND '\n'
49 // ZNPIFSAJLTCQR
50
51 #define PASM1(x1) assembly[ap++] = x1
52 #define PASM2(x1,x2) PASM1 (x1); PASM1 (x2)
53 #define PASM3(x1,x2,x3) PASM2 (x1,x2); PASM1 (x3)
54 #define PASM4(x1,x2,x3,x4) PASM3 (x1,x2,x3); PASM1 (x4)
55 #define PASM5(x1,x2,x3,x4,x5) PASM3 (x1,x2,x3); PASM2 (x4,x5)
56 #define PASM6(x1,x2,x3,x4,x5,x6) PASM3 (x1,x2,x3); PASM3 (x4,x5,x6)
57 #define ENDASM PASM1 (EEND)
58
59 static int LP, SP;
60 class ccsub
61 {
62 void fconv ();
63 void iconv ();
64 inline int sub_ptri (ccsub&, ccsub&);
65 inline void settype (int);
66 inline void lvaluate ();
67 inline void copytype (ccsub&);
68 inline void lvcopy (ccsub&);
69 inline int putthis (int*);
70 inline void putthis (int);
71 inline void degrade (ccsub&);
72 inline void arithmetic_convert (ccsub&, ccsub&);
73 inline void ptr_compare (ccsub&, ccsub&);
74 inline bool integral ();
75 inline bool arithmetic ();
76 inline bool structure ();
77 inline bool constant ();
78 inline void assign_convert (ccsub&, bool = false);
79 inline void argtype (typeID);
80 bool op1return;
81 static ccsub op1;
82 void cc_binwconv (exprID, ccsub&, ccsub&);
83 void cc_addptr (ccsub&, ccsub&);
84 int ptrfix (ccsub&);
85 bool lv;
86
87 void cc_fcall (exprID);
88 void cc_prefix (exprID);
89 void cc_postfix (exprID);
90 void cc_tival (exprID);
91 void cc_tfval (exprID);
92 void cc_tsval (exprID);
93 void cc_tlval (exprID);
94 void cc_terminal (exprID);
95 void cc_sizeof (exprID);
96 void cc_dot (exprID);
97 void cc_array (exprID);
98 void cc_star (exprID);
99 void cc_addrof (exprID);
100 void cc_ecast (exprID);
101 void cc_usign (exprID);
102 void cc_nbool (exprID);
103 void cc_compl (exprID);
104 void cc_add (exprID);
105 void cc_sub (exprID);
106 void cc_muldiv (exprID);
107 void cc_bintg (exprID, int);
108 void cc_cmp (exprID, int);
109 void cc_bool (exprID);
110 void cc_conditional (exprID);
111 void cc_assign (exprID);
112 void cc_assign (ccsub&, ccsub&);
113 void cc_oassign (exprID);
114 void cc_compound_result (exprID);
115
116 public:
117 ccsub (exprID);
118 ccsub () {}
119 ccsub (typeID, bool);
120
121 int base, spec [MSPEC];
122 int pobj, obj;
123
124 inline void putthis ();
125 };
126
127 ccsub ccsub::op1;
128
129 void ccsub::cc_tival (exprID e)
130 {
131 settype (S_INT);
132 pobj = ENI;
133 obj = e;
134 }
135
136 void ccsub::cc_tfval (exprID e)
137 {
138 settype (FLOAT);
139 pobj = ENF;
140 obj = e;
141 }
142
143 void ccsub::cc_tsval (exprID e)
144 {
145 base = S_CHAR;
146 spec [0] = '*';
147 spec [1] = -1;
148 pobj = ENP;
149 obj = e;
150 }
151
152 void ccsub::cc_tlval (exprID e)
153 {
154 base = VOID;
155 spec [0] = '*';
156 spec [1] = -1;
157 pobj = ENL;
158 obj = e;
159 }
160
161 //###################################
162 // sizeof expression
163 //###################################
164 void ccsub::cc_sizeof (exprID e)
165 {
166 int sap = ap;
167 ccsub o (ee [e].voici.e);
168 ap = sap;
169 settype (S_INT);
170 pobj = ENI;
171 ee [e].action = VALUE;
172 ee [e].voici.value = sizeof_type (o.base, o.spec);
173 obj = e;
174 }
175
176 //###################################
177 // terminal symbol
178 //###################################
179 void ccsub::cc_terminal (exprID ei)
180 {
181 subexpr e = ee [ei];
182 lookup_object ll (e.voici.symbol, false);
183 if (ll.enumconst) {
184 settype (S_INT);
185 pobj = ENI;
186 ee [ei].voici.value = ll.ec;
187 ee [ei].action = VALUE;
188 cc_tival (ei);
189 } else {
190 base = ll.base;
191 intcpy (spec, ll.spec);
192 pobj = ESMB;
193 lvaluate ();
194 }
195 obj = ei;
196 }
197
198 //###################################
199 // address operator &
200 //###################################
201 void ccsub::cc_addrof (exprID ei)
202 {
203 ccsub o (ee [ei].voici.e);
204
205 pobj = o.pobj;
206 obj = o.obj;
207 base = o.base;
208 if (o.lv || o.structure () || o.spec [0] != -1) {
209 spec [0] = '*';
210 intcpy (&spec [1], o.spec);
211 }// else if (o.spec [0] != -1)
212 // intcpy (spec, o.spec);
213 else half_error ("&address_of not addressable");
214 }
215
216 //###################################
217 // pointer indirection *
218 //###################################
219 void ccsub::cc_star (exprID e)
220 {
221 ccsub o (ee [e].voici.e);
222
223 if (o.lv) {
224 putthis (SP++);
225 PASM1 ('=');
226 o.putthis ();
227 PASM1 (EEND);
228 } else {
229 pobj = o.pobj;
230 obj = o.obj;
231 }
232
233 degrade (o);
234 lvaluate ();
235 }
236
237 //###################################
238 // array reference []
239 //###################################
240 void ccsub::cc_array (exprID ei)
241 {
242 ccsub o1 (ee [ei].voici.e), o2 (ee [ei].e);
243 cc_addptr (o1, o2);
244 degrade (*this);
245 lvaluate ();
246 }
247
248 //###################################
249 // structure reference .
250 //###################################
251 void ccsub::cc_dot (exprID ei)
252 {
253 subexpr e = ee [ei];
254 ccsub o (e.voici.e);
255
256 if (!o.structure ()) half_error ("member of no structure");
257
258 lookup_member lm (e.voila.member, o.base);
259 base = lm.base;
260 intcpy (spec, lm.spec);
261
262 putthis (SP++);
263 PASM4 ('=', EIN, lm.displacement, '+');
264 o.putthis ();
265 ENDASM;
266
267 lvaluate ();
268 }
269
270 //###################################
271 // cast (type-name)
272 //###################################
273 void ccsub::cc_ecast (exprID ei)
274 {
275 subexpr e = ee [ei];
276 ccsub o (e.voici.e), pseudo (e.voila.cast, true);
277 o.assign_convert (pseudo, true);
278 copytype (o);
279 *this = o;
280 }
281
282 //###################################
283 // unary +/-
284 //###################################
285 void ccsub::cc_usign (exprID ei)
286 {
287 subexpr e = ee [ei];
288 ccsub o (e.voici.e);
289
290 if (!o.arithmetic ()) half_error ("sign on pointer");
291
292 copytype (o);
293 if (e.action == UPLUS) lvcopy (o);
294 else if (o.pobj == ENI) {
295 pobj = ENI;
296 ee [ei].voici.value = -ee [o.obj].voici.value;
297 ee [ei].action = VALUE;
298 obj = ei;
299 } else if (o.pobj == ENF) {
300 pobj = ENF;
301 ee [ei].action = FVALUE;
302 ee [ei].voici.fvalue = -ee [o.obj].voici.fvalue;
303 obj = ei;
304 } else {
305 putthis (SP++);
306 PASM2 ('=', '-');
307 o.putthis ();
308 ENDASM;
309 }
310 }
311
312 //###################################
313 // logical negation !
314 //###################################
315 void ccsub::cc_nbool (exprID ei)
316 {
317 ccsub o (ee [ei].voici.e);
318 if (o.pobj == ENI || o.pobj == ENF) {
319 pobj = ENI;
320 ee [obj = ei].voici.value = !ee [o.obj].voici.value;
321 ee [ei].action = VALUE;
322 } else {
323 putthis (SP++);
324 PASM2 ('=', '!');
325 o.putthis ();
326 ENDASM;
327 }
328 settype (S_INT);
329 }
330
331 //###################################
332 // one's complement ~
333 //###################################
334 void ccsub::cc_compl (exprID ei)
335 {
336 ccsub o (ee [ei].voici.e);
337 if (!o.integral ()) half_error ("~integral");
338 if (o.pobj == ENI) {
339 pobj = ENI;
340 ee [obj = ei].voici.value = ~ee [o.obj].voici.value;
341 ee [ei].action = VALUE;
342 } else {
343 putthis (SP++);
344 PASM2 ('=', '~');
345 o.putthis ();
346 ENDASM;
347 }
348 settype (S_INT);
349 }
350
351 //###################################
352 // binary operators with integral
353 // operands <<%&|^>>
354 //###################################
355 void ccsub::cc_bintg (exprID ei, int op)
356 {
357 subexpr e = ee [ei];
358 ccsub o1 (e.voici.e), o2 (e.e);
359
360 if (op1return) op1 = o1;
361 if (!o1.integral () || !o2.integral ())
362 half_error ("<<, %, &, |, ^, >> need intergal operands");
363
364 if (o1.pobj == ENI && o2.pobj == ENI) {
365 int v = 0, v1 = ee [o1.obj].voici.value;
366 int v2 = ee [o2.obj].voici.value;
367 pobj = ENI;
368 switch (e.action) {
369 case REM: v = v1 % v2; break;
370 case SHR: v = v1 >> v2; break;
371 case SHL: v = v1 << v2; break;
372 case BOR: v = v1 | v2; break;
373 case BAND: v = v1 & v2; break;
374 case BXOR: v = v1 ^ v2; break;
375 }
376 ee [obj = ei].voici.value = v;
377 ee [ei].action = VALUE;
378 } else {
379 putthis (SP++);
380 PASM1 ('=');
381 o1.putthis ();
382 PASM1 (op);
383 o2.putthis ();
384 ENDASM;
385 }
386
387 settype (S_INT);
388 }
389
390 //###################################
391 // multiply divide * /
392 //###################################
393 void ccsub::cc_muldiv (exprID ei)
394 {
395 subexpr e = ee [ei];
396 ccsub o1 (e.voici.e), o2 (e.e);
397 if (op1return) op1 = o1;
398 if (!o1.arithmetic () || !o2.arithmetic ())
399 half_error ("*,/ need arithmetic operands");
400 cc_binwconv (ei, o1, o2);
401 }
402
403 //###################################
404 // prefix ++ --
405 //###################################
406 void ccsub::cc_prefix (exprID ei)
407 {
408 int pi = 1;
409 subexpr e = ee [ei];
410 ccsub o (e.voici.e);
411
412 if (!o.lv) half_error ("(++/--) no-lvalue");
413 if (o.arithmetic ()) {
414 if (!o.integral ()) half_error ("++float");
415 } else pi = ptr_increment (o.base, o.spec);
416 o.putthis ();
417 PASM1 ('=');
418 o.putthis ();
419 PASM4 (e.action == PPPRE ? '+' : '-', EIN, pi, EEND);
420 copytype (o);
421 lvcopy (o);
422 }
423
424 //###################################
425 // postfix ++ --
426 //###################################
427 void ccsub::cc_postfix (exprID ei)
428 {
429 int pi = 1;
430 subexpr e = ee [ei];
431 ccsub o (e.voici.e);
432
433 if (!o.lv) half_error ("no-lvalue (++/--)");
434 if (o.arithmetic ()) {
435 if (!o.integral ()) half_error ("--float");
436 } else pi = ptr_increment (o.base, o.spec);
437 copytype (o);
438 putthis (SP++);
439 PASM1 ('=');
440 o.putthis ();
441 ENDASM;
442 o.putthis ();
443 PASM1 ('=');
444 o.putthis ();
445 PASM4 (e.action == PPPOST ? '+' : '-', EIN, pi, EEND);
446 }
447
448 //###################################
449 // addition +
450 //###################################
451 void ccsub::cc_add (exprID ei)
452 {
453 subexpr e = ee [ei];
454 ccsub o1 (e.voici.e), o2 (e.e);
455
456 if (op1return) op1 = o1;
457 if (o1.arithmetic () && o2.arithmetic ())
458 cc_binwconv (ei, o1, o2);
459 else cc_addptr (o1, o2);
460 }
461
462 //###################################
463 // subtract -
464 //###################################
465 void ccsub::cc_sub (exprID ei)
466 {
467 subexpr e = ee [ei];
468 ccsub o1 (e.voici.e), o2 (e.e);
469
470 if (op1return) op1 = o1;
471
472 if (o1.arithmetic () && o2.arithmetic ()) {
473 cc_binwconv (ei, o1, o2);
474 return;
475 }
476
477 if (!o1.arithmetic () && !o2.arithmetic ()) {
478 // (p1 - p2) / sizeof (*p1)
479 int pi = sub_ptri (o1, o2), tobj;
480 PASM3 (EST, tobj = SP++, '=');
481 o1.putthis ();
482 PASM1 ('-');
483 o2.putthis ();
484 ENDASM;
485 putthis (SP++);
486 PASM6 ('=', EST, tobj, '/', EIN, pi);
487 ENDASM;
488 settype (S_INT);
489 } else if (o2.integral ()) {
490 // p - sizeof (*p) * v
491 o2.ptrfix (o1);
492 copytype (o1);
493 putthis (SP++);
494 PASM1 ('=');
495 o1.putthis ();
496 PASM1 ('-');
497 o2.putthis ();
498 ENDASM;
499 } else if (o1.arithmetic ()) half_error ("integer - pointer");
500 else half_error ("pointer - shit");
501 }
502
503 //###################################
504 // compare == != < <= >= >
505 //###################################
506 void ccsub::cc_cmp (exprID ei, int op)
507 {
508 subexpr e = ee [ei];
509 ccsub o1 (e.voici.e), o2 (e.e);
510
511 if (o1.arithmetic () && o1.arithmetic ())
512 arithmetic_convert (o1, o2);
513 else ptr_compare (o1, o2);
514
515 if (o1.pobj == ENI && o2.pobj == ENI) {
516 int v = 0, v1 = ee [o1.obj].voici.value;
517 int v2 = ee [o2.obj].voici.value;
518 pobj = ENI;
519 switch (e.action) {
520 case BEQ: v = v1 == v2; break; case BNEQ: v = v1 != v2; break;
521 case CGR: v = v1 > v2; break; case CGRE: v = v1 >= v2; break;
522 case CLE: v = v1 < v2; break; case CLEE: v = v1 <= v2; break;
523 }
524 ee [obj = ei].voici.value = v;
525 ee [ei].action = VALUE;
526 } else {
527 putthis (SP++);
528 PASM1 ('=');
529 o1.putthis ();
530 PASM1 (op);
531 o2.putthis ();
532 ENDASM;
533 }
534
535 settype (S_INT);
536 }
537
538 //###################################
539 // early termination && ||
540 //###################################
541 void ccsub::cc_bool (exprID ei)
542 {
543 subexpr e = ee [ei];
544 int jlabel, oror = e.action == IOR;
545
546 ccsub o1 (e.voici.e);
547 if (o1.pobj == ENI) {
548 int v = ee [o1.obj].voici.value;
549 if (oror ? v != 0 : v == 0) {
550 ee [ei].action = VALUE;
551 ee [ei].voici.value = (oror) ? 1 : 0;
552 pobj = ENI;
553 obj = ei;
554 } else {
555 ccsub o2 (e.e);
556 if (o2.pobj == ENI) {
557 ee [ei].action = VALUE;
558 ee [ei].voici.value =
559 ee [o2.obj].voici.value != 0;
560 pobj = ENI;
561 obj = ei;
562 } else {
563 putthis (SP++);
564 PASM4 ('=', EIN, 1, EEND);
565 PASM1 (TEST);
566 o2.putthis ();
567 PASM4 (EEND, JMP, JMPT, LP);
568 putthis ();
569 PASM4 ('=', EIN, 0, EEND);
570 PASM2 (LABEL, LP++);
571 }
572 }
573 } else {
574 putthis (SP++);
575 PASM4 ('=', EIN, oror ? 0 : 1, EEND);
576 PASM1 (TEST);
577 o1.putthis ();
578 PASM4 (EEND, JMP, oror ? JMPT : JMPF, jlabel = LP++);
579
580 ccsub o2 (e.e);
581 PASM1 (TEST);
582 o2.putthis ();
583 PASM4 (EEND, JMP, oror ? JMPF : JMPT, LP);
584
585 PASM2 (LABEL, jlabel);
586 putthis ();
587 PASM4 ('=', EIN, oror ? 1 : 0, EEND);
588 PASM2 (LABEL, LP++);
589 }
590
591 settype (S_INT);
592 }
593
594 //###################################
595 // conditional ? :
596 //###################################
597 void ccsub::cc_conditional (exprID ei)
598 {
599 subexpr e = ee [ei];
600 int jlabel1, jlabel2;
601 bool o1float, o2float;
602 ccsub o (e.voici.e);
603
604 if (o.pobj == ENI) {
605 if (ee [o.obj].voici.value)
606 if (e.e == -1)
607 *this = o;
608 else {
609 ccsub o1 (e.e);
610 *this = o1;
611 }
612 else {
613 ccsub o1 (e.voila.eelse);
614 *this = o1;
615 }
616 return;
617 }
618 PASM1 (TEST);
619 o.putthis ();
620 PASM4 (EEND, JMP, JMPF, jlabel1 = LP++);
621
622 ccsub o1 (e.e), *ufo = e.e == -1 ? &o : &o1;
623 o1float = ufo->arithmetic () && ufo->base == FLOAT;
624 putthis (SP++);
625 PASM1 ('=');
626 ufo->putthis ();
627 PASM4 (EEND, JMP, JMPA, jlabel2 = LP++);
628 PASM2 (LABEL, jlabel1);
629 ccsub o2 (e.voila.eelse);
630 o2float = o2.arithmetic () && o2.base == FLOAT;
631 if (o1float || o2float && o1float != o2float)
632 if (o1float) { // ? float : int
633 o2.fconv ();
634 putthis ();
635 PASM1 ('=');
636 o2.putthis ();
637 PASM3 (EEND, LABEL, jlabel2);
638 settype (FLOAT);
639 } else { // ? int : float
640 putthis (SP++);
641 PASM1 ('=');
642 o2.putthis ();
643 PASM6 (EEND, JMP, JMPA, LP, LABEL, jlabel2);
644 ufo->fconv ();
645 putthis ();
646 PASM1 ('=');
647 ufo->putthis ();
648 PASM3 (EEND, LABEL, LP++);
649 settype (FLOAT);
650 }
651 else {
652 putthis ();
653 PASM1 ('=');
654 o2.putthis ();
655 PASM3 (EEND, LABEL, jlabel2);
656 if (ufo->arithmetic ()) copytype (o2);
657 else copytype (*ufo);
658 }
659 }
660
661 //###################################
662 // assignment =
663 //###################################
664 void ccsub::cc_assign (exprID ei)
665 {
666 subexpr e = ee [ei];
667 ccsub o1 (e.voici.e), o2 (e.e);
668 cc_assign (o1, o2);
669 }
670
671 void ccsub::cc_assign (ccsub &o1, ccsub &o2)
672 {
673 o2.assign_convert (o1);
674
675 if (o1.lv) {
676 o1.putthis ();
677 PASM1 ('=');
678 o2.putthis ();
679 ENDASM;
680 } else {
681 if (!o1.structure ())
682 half_error ("not lvalue in assignment");
683 if (o1.base != o2.base)
684 half_error ("incompatible");
685 PASM2 (COPYREC, o1.base);
686 o1.putthis ();
687 o2.putthis ();
688 ENDASM;
689 }
690 copytype (o1);
691 obj = o2.obj;
692 pobj = o2.pobj;
693 }
694
695 //###################################
696 // op assignment += -= *= /= ...
697 //###################################
698 void ccsub::cc_oassign (exprID ei)
699 {
700 op1return = true;
701 switch (ee [ei].action) {
702 case ASSIGNA: ee [ei].action = ADD; cc_add (ei); break;
703 case ASSIGNS: ee [ei].action = SUB; cc_sub (ei); break;
704 case ASSIGNM: ee [ei].action = MUL; cc_muldiv (ei); break;
705 case ASSIGND: ee [ei].action = DIV; cc_muldiv (ei); break;
706 case ASSIGNR: cc_bintg (ei, '%'); break;
707 case ASSIGNBA: cc_bintg (ei, '&'); break;
708 case ASSIGNBX: cc_bintg (ei, '^'); break;
709 case ASSIGNBO: cc_bintg (ei, '|'); break;
710 case ASSIGNRS: cc_bintg (ei, RSH); break;
711 case ASSIGNLS: cc_bintg (ei, LSH); break;
712 }
713 cc_assign (op1, *this);
714 }
715
716 //###################################
717 // function call ()
718 //###################################
719 void ccsub::cc_fcall (exprID ei)
720 {
721 int argcc [100], aap = 0, i;
722 typeID *tp;
723 subexpr e = ee [ei];
724
725 if (ee [e.voici.e].action == SYMBOL) {
726 lookup_function lf (ee [e.voici.e].voici.symbol);
727 base = lf.base;
728 intcpy (spec, lf.spec + 2);
729 tp = ret_arglist (lf.spec [1]);
730 argcc [aap++] = ESMB;
731 argcc [aap++] = e.voici.e;
732 } else {
733 ccsub fn (ee [ei].voici.e);
734 base = fn.base;
735 if (fn.spec [0] != '(') {
736 if (fn.spec [0] != '*' || fn.spec [1] != '(')
737 half_error ("not a function");
738 intcpy (spec, fn.spec + 3);
739 tp = ret_arglist (fn.spec [2]);
740 } else {
741 intcpy (spec, fn.spec + 2);
742 tp = ret_arglist (fn.spec [1]);
743 }
744 aap += fn.putthis (argcc + aap);
745 }
746
747 argcc [aap++] = '(';
748 if ((ei = ee [ei].e) != -1) {
749 for (; ee [ei].action == ARGCOMMA; ei = ee [ei].e) {
750 ccsub o (ee [ei].voici.e);
751 aap += o.putthis (argcc + aap);
752 if (*tp == -1) half_error ("too many arguments");
753 if (*tp > 0) o.argtype (*tp++);
754 }
755 ccsub o (ei);
756 aap += o.putthis (argcc + aap);
757 if (*tp == -1) half_error ("too many arguments");
758 if (*tp > 0) o.argtype (*tp++);
759 }
760 if (*tp > 0) half_error ("too few arguments");
761 argcc [aap++] = ')';
762
763 putthis (SP++);
764 PASM2 ('=', CALL);
765 for (i = 0; i < aap; i++)
766 PASM1 (argcc [i]);
767 ENDASM;
768 }
769
770 //###################################
771 // result of the last subexpression
772 // of a compound statement in expression
773 // (a horrible violation)
774 //###################################
775 void ccsub::cc_compound_result (exprID ei)
776 {
777 type t;
778 opentype (ee [ei].voila.result_type, t);
779 base = t.base;
780 intcpy (spec, t.spec);
781 pobj = RESULT;
782 obj = ee [ei].voici.using_result;
783 }
784
785 ////////////////////////////////////////////////////////////////////////////
786 ////////////////////////////////////////////////////////////////////////////
787
788 void ccsub::cc_binwconv (exprID ei, ccsub &o1, ccsub &o2)
789 {
790 if (!o2.arithmetic () || !o1.arithmetic ())
791 half_error ("Need arithmetic operands");
792 arithmetic_convert (o1, o2);
793
794 if (o1.pobj == ENI && o2.pobj == ENI) {
795 int v = 0, v1 = ee [o1.obj].voici.value;
796 int v2 = ee [o2.obj].voici.value;
797 pobj = ENI;
798 switch (ee [ei].action) {
799 case ADD: v = v1 + v2; break;
800 case SUB: v = v1 - v2; break;
801 case MUL: v = v1 * v2; break;
802 case DIV: if (v2 == 0) {
803 if (include_values && !usage_only)
804 fprintf (stderr, "Divizion by zero"
805 " in arithmetic\n");
806 v = v1;
807 } else v = v1 / v2; break;
808 }
809 ee [obj = ei].voici.value = v;
810 ee [ei].action = VALUE;
811 } else if (o1.pobj == ENF && (o2.pobj == ENF || o2.pobj == ENI)
812 || o2.pobj == ENF && o1.pobj == ENI) {
813 float v = 0;
814 float v1 = (o1.pobj == ENF) ? ee [o1.obj].voici.fvalue
815 : (float) ee [o1.obj].voici.value;
816 float v2 = (o2.pobj == ENF) ? ee [o2.obj].voici.fvalue
817 : (float) ee [o2.obj].voici.value;
818 pobj = ENF;
819 switch (ee [ei].action) {
820 case ADD: v = v1 + v2; break;
821 case SUB: v = v1 - v2; break;
822 case MUL: v = v1 * v2; break;
823 case DIV: v = v1 / v2; break;
824 }
825 ee [obj = ei].voici.fvalue = v;
826 ee [ei].action = FVALUE;
827 } else {
828 putthis (SP++);
829 PASM1 ('=');
830 o1.putthis ();
831 switch (ee [ei].action) {
832 case ADD: PASM1 ('+'); break; case SUB: PASM1 ('-'); break;
833 case MUL: PASM1 ('*'); break; case DIV: PASM1 ('/'); break;
834 }
835 o2.putthis ();
836 ENDASM;
837 }
838
839 settype (o1.base);
840 }
841
842 void ccsub::cc_addptr (ccsub &o1, ccsub &o2)
843 {
844 bool b1 = o1.arithmetic (), b2 = o2.arithmetic ();
845
846 if (b1 && b2) half_error ("No pointer operand");
847 if (!b1 && !b2) half_error ("pointer + pointer");
848
849 if (b2) {
850 o2.ptrfix (o1);
851 copytype (o1);
852 } else {
853 o1.ptrfix (o2);
854 copytype (o2);
855 }
856
857 putthis (SP++);
858 PASM1 ('=');
859 o1.putthis ();
860 PASM1 ('+');
861 o2.putthis ();
862 PASM1 (EEND);
863 }
864
865 void ccsub::copytype (ccsub &o)
866 {
867 base = o.base;
868 intcpy (spec, o.spec);
869 }
870
871 void ccsub::degrade (ccsub &o)
872 {
873 base = o.base;
874 if (o.spec [0] == -1 || o.spec [0] == '(')
875 half_error ("* not effective");
876
877 intcpy (spec, o.spec + (o.spec [0] == '*' ? 1 : 2));
878 }
879
880 int ccsub::ptrfix (ccsub &o)
881 {
882 int pi = ptr_increment (o.base, o.spec);
883
884 if (!integral ()) half_error ("pointer + float");
885 if (pobj == ENI) {
886 pobj = EIN;
887 obj = pi * ee [obj].voici.value;
888 } else {
889 PASM6 (EST, SP, '=', EIN, pi, '*');
890 putthis ();
891 PASM1 (EEND);
892 pobj = EST;
893 obj = SP++;
894 lv = false;
895 }
896 return pi;
897 }
898
899 int ccsub::sub_ptri (ccsub &o1, ccsub &o2)
900 {
901 int i = ptr_increment (o1.base, o1.spec);
902 if (ptr_increment (o2.base, o2.spec) != i)
903 half_error ("'-' on different pointers");
904 return i;
905 }
906
907 int ccsub::putthis (int *p)
908 {
909 int *sa = assembly;
910 int sap = ap, r;
911 assembly = p;
912 ap = 0;
913 putthis ();
914 assembly = sa;
915 r = ap;
916 ap = sap;
917 return r;
918 }
919
920 void ccsub::putthis ()
921 {
922 if (lv) {
923 PASM1 ('*');
924 if (spec [0] == '*') {
925 PASM1 (TPTR);
926 } else if (base >= 0) {
927 PASM2 (TREC, base);
928 } else switch (base) {
929 case S_CHAR: PASM2 (TSI, 1); break;
930 case U_CHAR: PASM2 (TUI, 1); break;
931 case S_SINT: PASM2 (TSI, 2); break;
932 case U_SINT: PASM2 (TUI, 2); break;
933 case S_LINT: PASM2 (TSI, 4); break;
934 case U_LINT: PASM2 (TUI, 4); break;
935 case S_INT : PASM2 (TSI, 4); break;
936 case U_INT : PASM2 (TUI, 4); break;
937 case S_LONG: PASM2 (TSI, 8); break;
938 case U_LONG: PASM2 (TUI, 8); break;
939 case FLOAT : PASM1 (TFP); break;
940 default: PASM2 (TBF, base); break;
941 }
942 }
943 PASM2 (pobj, obj);
944 }
945
946 void ccsub::putthis (int nobj)
947 {
948 PASM2 (pobj, obj = nobj);
949 }
950
951 void ccsub::lvcopy (ccsub &o)
952 {
953 if (o.lv) {
954 PASM3 (EST, obj = SP++, '=');
955 o.putthis ();
956 PASM1 (EEND);
957 } else {
958 obj = o.obj;
959 pobj = o.pobj;
960 }
961 }
962
963 bool ccsub::structure ()
964 {
965 return spec [0] == -1 && base >= 0;
966 }
967
968 bool ccsub::arithmetic ()
969 {
970 return spec [0] == -1 && base < VOID || spec [0] == ':';
971 }
972
973 bool ccsub::integral ()
974 {
975 return spec [0] == -1 && base < FLOAT || spec [0] == ':';
976 }
977
978 bool ccsub::constant ()
979 {
980 return pobj == ENI || pobj == ENF;
981 }
982
983 void ccsub::lvaluate ()
984 {
985 lv = !(spec [0] =='[' || spec [0] ==-1 && base >=0 || spec [0] =='(');
986 }
987
988 void ccsub::settype (int b)
989 {
990 base = b;
991 spec [0] = -1;
992 }
993
994 void ccsub::assign_convert (ccsub &o, bool casted)
995 {
996 if (o.arithmetic ()) {
997 if (o.base != FLOAT) {
998 if (arithmetic ()) {
999 if (base == FLOAT) iconv ();
1000 }
1001 } else {
1002 if (arithmetic ()) {
1003 if (base != FLOAT) fconv ();
1004 } else half_error ("ptr to float conv");
1005 }
1006 } else if (o.spec [0] == -1) {
1007 if (!casted)
1008 if (spec [0] != -1 || o.base != base)
1009 half_error ("incompatible types");
1010 } else {
1011 if (arithmetic ()) {
1012 if (base == FLOAT) half_error ("make ptr from float");
1013 //else if (!casted) warning...
1014 }
1015 }
1016 base = o.base;
1017 intcpy (spec, o.spec);
1018 }
1019
1020 void ccsub::argtype (typeID i)
1021 {
1022 ccsub pseudo (i, true);
1023 assign_convert (pseudo, false);
1024 }
1025
1026 void ccsub::ptr_compare (ccsub &o1, ccsub &o2)
1027 {
1028 if (o1.arithmetic () && !o1.integral ()
1029 || o2.arithmetic () && !o2.integral ())
1030 half_error ("compare pointer w/ float, duh???");
1031 }
1032
1033 void ccsub::arithmetic_convert (ccsub &o1, ccsub &o2)
1034 {
1035 if (o1.base == FLOAT || o2.base == FLOAT) {
1036 if (o1.base != o2.base)
1037 if (o1.base == FLOAT) o2.fconv ();
1038 else o1.fconv ();
1039 }
1040 }
1041
1042 void ccsub::fconv ()
1043 {
1044 if (pobj == ENI) {
1045 ee [obj].voici.fvalue = (double) ee [obj].voici.value;
1046 pobj = ENF;
1047 } else {
1048 PASM4 (EST, SP, '=', CONVF);
1049 putthis ();
1050 ENDASM;
1051 pobj = EST;
1052 obj = SP++;
1053 lv = false;
1054 }
1055 settype (FLOAT);
1056 }
1057
1058 void ccsub::iconv ()
1059 {
1060 if (pobj == ENF) {
1061 ee [obj].voici.value = (int) ee [obj].voici.fvalue;
1062 pobj = ENI;
1063 } else {
1064 PASM4 (EST, SP, '=', CONVI);
1065 putthis ();
1066 PASM1 (EEND);
1067 pobj = EST;
1068 obj = SP++;
1069 lv = false;
1070 }
1071 settype (S_INT);
1072 }
1073
1074 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
1075
1076 ccsub::ccsub (exprID ei)
1077 {
1078 if (ei == -1) return;
1079 advance:
1080 subexpr e = ee [ei];
1081
1082 pobj = EST;
1083 lv = false;
1084 op1return = false;
1085 switch (e.action) {
1086 case VALUE:
1087 case UVALUE: cc_tival (ei); break;
1088 case FVALUE: cc_tfval (ei); break;
1089 case SVALUE: cc_tsval (ei); break;
1090 case AVALUE: cc_tlval (ei); break;
1091 case SYMBOL: cc_terminal (ei); break;
1092 case PPPOST:
1093 case MMPOST: cc_postfix (ei); break;
1094 case FCALL: cc_fcall (ei); break;
1095 case MEMB: cc_dot (ei); break;
1096 case ARRAY: cc_array (ei); break;
1097 case ADDROF: cc_addrof (ei); break;
1098 case PTRIND: cc_star (ei); break;
1099 case PPPRE:
1100 case MMPRE: cc_prefix (ei); break;
1101 case CAST: cc_ecast (ei); break;
1102 case LNEG: cc_nbool (ei); break;
1103 case OCPL: cc_compl (ei); break;
1104 case UPLUS:
1105 case UMINUS: cc_usign (ei); break;
1106 case SIZEOF: cc_sizeof (ei); break;
1107 case MUL:
1108 case DIV: cc_muldiv (ei); break;
1109 case ADD: cc_add (ei); break;
1110 case SUB: cc_sub (ei); break;
1111 case REM: cc_bintg (ei, '%'); break;
1112 case SHR: cc_bintg (ei, RSH); break;
1113 case SHL: cc_bintg (ei, LSH); break;
1114 case BOR: cc_bintg (ei, '|'); break;
1115 case BAND: cc_bintg (ei, '&'); break;
1116 case BXOR: cc_bintg (ei, '^'); break;
1117 case IAND:
1118 case IOR: cc_bool (ei); break;
1119 case BEQ: cc_cmp (ei, EQCMP); break;
1120 case BNEQ: cc_cmp (ei, NEQCMP); break;
1121 case CGR: cc_cmp (ei, '>'); break;
1122 case CGRE: cc_cmp (ei, GEQCMP); break;
1123 case CLE: cc_cmp (ei, '<'); break;
1124 case CLEE: cc_cmp (ei, LEQCMP); break;
1125 case COND: cc_conditional (ei); break;
1126 case COMPOUND_RESULT: cc_compound_result (ei); break;
1127 case COMMA: {
1128 ccsub o (e.voici.e);
1129 ei = e.e; (void) o.lv;
1130 goto advance;
1131 }
1132 default: if (e.action == '=') cc_assign (ei);
1133 else cc_oassign (ei);
1134 }
1135 }
1136
1137 ccsub::ccsub (typeID ti, bool)
1138 {
1139 type t;
1140 opentype (ti, t);
1141 base = t.base;
1142 intcpy (spec, t.spec);
1143 }
1144
1145 /* ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
1146 now we can implement typeof expression
1147 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ */
1148
1149 typeID typeof_expression ()
1150 {
1151 if (CExpr.first == -1) syntax_error (ExpressionPtr, "this has no type");
1152 typeID ret = 0;
1153 SP = LP = 0;
1154 ap = 0;
1155 assembly = (int*) alloca (17 * CExpr.ne * sizeof (int) + 4);
1156 try {
1157 ccsub CC (CExpr.first);
1158 type t;
1159 t.base = CC.base;
1160 t.spec = CC.spec;
1161 ret = gettype (t) + TYPEDEF_BASE;
1162 } catch (EXPR_ERROR) {
1163 syntax_error (ExpressionPtr, "expression trivial for typeof()");
1164 }
1165 return ret;
1166 }
1167
1168 /******************************************************************************
1169
1170 (note to self: attempt not to reorder commands unless sure)
1171
1172 ******************************************************************************/
1173 //
1174 // this here, is a mini parser of the bytecode assembly object code
1175 // to readable bytecode assembly, for now the only interesting thing
1176 // is to show the generated bytecode readably. In the future, we may
1177 // just dump the assembly tokens to an object file, so this here will
1178 // be gone
1179 //
1180
1181 static inline bool opstart (int o)
1182 {
1183 return o=='*'||o==EST||o==EIN||o==ENI||
1184 o==ENF||o==ESMB||o==ENP||o==ENL || o==RESULT;
1185 }
1186
1187 int putoperand (int i)
1188 {
1189 if (assembly [i] == '*') {
1190 ++i;
1191 if (assembly [i] == TFP || assembly [i] == TPTR) {
1192 printf (" *{%c}", assembly [i]);
1193 } else {
1194 printf (" *{%c%i}", assembly [i], assembly [i+1]);
1195 i++;
1196 }
1197 i++;
1198 }
1199 switch (assembly [i++]) {
1200 case EST: printf ("$%i ", assembly [i]); break;
1201 case EIN: printf ("%i ", assembly [i]); break;
1202 case ENI: printf ("%li ", ee [assembly [i]].voici.value); break;
1203 case ENF: printf ("%f ", ee [assembly [i]].voici.fvalue);break;
1204 case ENP: printf ("\"%s\" ",
1205 C_Strings [ee [assembly [i]].voici.value]);break;
1206 case ESMB: printf ("%s ", expand (ee [assembly [i]].voici.symbol));
1207 break;
1208 case ENL: printf (".label %s ",
1209 expand (ee [assembly [i]].voici.symbol));
1210 break;
1211 case RESULT: printf (".result_%i ", assembly [i]); break;
1212 }
1213 return i + 1;
1214 }
1215
1216 void putthis ()
1217 {
1218 int *i;
1219 for (i = assembly; *i!= -1;) {
1220 if (*i == EEND) {
1221 printf ("\n");
1222 i++;
1223 continue;
1224 }
1225 if (*i == NOOP) {
1226 i++;
1227 continue;
1228 }
1229 if (*i == LABEL) {
1230 printf ("L%i:\t", *++i);
1231 i++;
1232 } else printf ("\t");
1233 if (*i == TEST) {
1234 printf ("test ");
1235 i = assembly + putoperand (i - assembly + 1);
1236 continue;
1237 }
1238 if (*i == JMP) {
1239 switch (*++i) {
1240 case JMPT: printf ("jmpt "); break;
1241 case JMPF: printf ("jmpf "); break;
1242 case JMPA: printf ("jmp "); break;
1243 }
1244 printf ("L%i\n", *++i);
1245 i++;
1246 continue;
1247 }
1248 if (*i == RESULT) {
1249 printf (".result_%i ", *++i);
1250 i = assembly + putoperand (i - assembly + 1);
1251 continue;
1252 }
1253 if (*i == COPYREC) {
1254 printf (".copyrec %i: ", *++i);
1255 i = assembly + putoperand (i - assembly + 1);
1256 i = assembly + putoperand (i - assembly);
1257 continue;
1258 }
1259 i = assembly + putoperand (i - assembly);
1260 if (*i != '=') continue;
1261 printf (" = ");
1262 i++;
1263 if (*i == CALL) {
1264 printf (".call ");
1265 i = assembly + putoperand (i - assembly + 1) + 1;
1266 printf ("(");
1267 while (*i != ')')
1268 i = assembly + putoperand (i - assembly);
1269 printf (")");
1270 i++;
1271 continue;
1272 }
1273 if (!opstart (*i)) {
1274 if (*i == CONVI) printf ("\\int ");
1275 else if (*i == CONVF) printf ("\\float ");
1276 else printf (" %s ", expand (*i));
1277 i++;
1278 }
1279 i = assembly + putoperand (i - assembly);
1280 if (*i == EEND) continue;
1281 printf (" %s ", expand (*i));
1282 i = assembly + putoperand (i - assembly + 1);
1283 }
1284 printf ("\n");
1285 }
1286
1287 /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
1288 ok, we did that. Tomorrow we must go see the persons in
1289 charge. They want to speak to us
1290 --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */
1291
1292 void compile (exprID e)
1293 {
1294 SP = LP = 0;
1295 ap = 1;
1296 assembly [0] = EEND;
1297 ccsub CC (e);
1298
1299 #ifdef GNU_VIOLATIONS
1300 last_result_type.base = CC.base;
1301 intcpy (last_result_type.spec, CC.spec);
1302 #endif
1303 PASM2 (RESULT, ++last_result);
1304
1305 CC.putthis ();
1306 assembly [ap++] = EEND;
1307 assembly [ap++] = -1;
1308 assembly [ap++] = -1;
1309 putthis ();
1310 }
1311
1312 //
1313 //
1314 //
1315 //
1316
1317 class ncci_cc : public ncci
1318 {
1319 public:
1320 void cc_expression ();
1321 void new_function (Symbol);
1322 void inline_assembly (NormPtr, int);
1323 };
1324
1325 void ncci_cc::cc_expression ()
1326 {
1327 assembly = (int*) alloca (17 * CExpr.ne * sizeof (int) + 4);
1328 try {
1329 if (CExpr.first != -1) compile (CExpr.first);
1330 } catch (EXPR_ERROR) { }
1331 }
1332
1333 int cc_int_expression ()
1334 {
1335 int r = 112;
1336 assembly = (int*) alloca (17 * CExpr.ne * sizeof (int) + 4);
1337 try {
1338 SP = LP = 0;
1339 ap = 1;
1340 assembly [0] = EEND;
1341 ccsub CC (CExpr.first);
1342 #ifndef FAKE_VARIABLE_ARRAYS
1343 if (CC.pobj != ENI)
1344 half_error ("couldn't compute constant integer expr");
1345 #endif
1346 r = ee [CC.obj].voici.value;
1347 } catch (EXPR_ERROR) {
1348 syntax_error (ExpressionPtr, "Expression Trivial to continue");
1349 }
1350 return r;
1351 }
1352
1353 void ncci_cc::new_function (Symbol s)
1354 {
1355 printf ("#########################################################\n");
1356 printf ("# Function %s\n", expand (s));
1357 printf ("#########################################################\n");
1358 }
1359
1360 void ncci_cc::inline_assembly (NormPtr p, int n)
1361 {
1362 printf ("#inline assembly\n");
1363 while (n--) printf ("%s ", expand (CODE [p++]));
1364 printf ("\n\n");
1365 }
1366
1367 void set_compilation ()
1368 {
1369 ncc = new ncci_cc;
1370 }