"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 }