"Fossies" - the Fresh Open Source Software Archive

Member "ncc-2.8/usage.C" (11 Oct 2008, 22213 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 $   C-flow and data usage analysis.
    3 $
    4 $   Stripped-down version of ccexpr. expressions are compiled but
    5 $   without producing bytecode assembly. just inform about
    6 $   function calls, use of global variables and use of members
    7 $   of structures
    8 *****************************************************************************/
    9 #include <stdio.h>
   10 #include <assert.h>
   11 
   12 #include "global.h"
   13 #include "inttree.h"
   14 
   15 bool infuncs = false;
   16 
   17 static intTree printed;
   18 static intTree printed_function;
   19 
   20 //***********************************************************
   21 // Output Formats & Text
   22 //***********************************************************
   23 
   24 static char *txt_func =     "\nD: %s()\n";
   25 static char *txt_fcall =    "F: %s()\n";
   26 static char *txt_virt =     "F: (*virtual)()\n";
   27 static char *txt_error =    "F: NCC:syntax_error()\n";
   28 static char *txt_gvar_r =   "g: %s\n";
   29 static char *txt_evar_r =   "g: %s\n";
   30 static char *txt_gvar_ra =  "g: %s[]\n";
   31 static char *txt_evar_ra =  "g: %s[]\n";
   32 static char *txt_gvar =     "G: %s\n";
   33 static char *txt_gvar_a =   "G: %s[]\n";
   34 static char *txt_evar =     "G: %s\n";
   35 static char *txt_evar_a =   "G: %s[]\n";
   36 static char *txt_memb_r =   "s: %s.%s\n";
   37 static char *txt_memb =     "S: %s.%s\n";
   38 static char *txt_memb_ra =  "s: %s.%s[]\n";
   39 static char *txt_memb_a =   "S: %s.%s[]\n";
   40 static char *txt_fpcall =   "F: *%s()\n";
   41 static char *txt_fcallback =    "F: *%s.%s()\n";
   42 static char *farg_named_call =  "F: %s/%s()\n";
   43 static char *farg_call_redirect = "\nD: %s/%s()\nF: *%s()__farg%i()\n";
   44 static char *txt_argval =   "R: *%s()__farg%i() %s()\n";
   45 static char *txt_argvalf =  "R: *%s()__farg%i() *%s()\n";
   46 static char *txt_argvalfl = "R: *%s()__farg%i() %s/%s()\n";
   47 static char *txt_argvalargval = "R: *%s()__farg%i() *%s()__farg%i()\n";
   48 static char *txt_membargval =   "R: *%s()__farg%i() *%s.%s()\n";
   49 
   50 //********************************************
   51 
   52 char *structname (Symbol s)
   53 {
   54     return s == -1 ? (char*) "{anonymous}" : C_Syms [SYMBOLID (s)];
   55 }
   56 
   57 void report (Symbol s, int frame, bool wrt, bool arr)
   58 {
   59     if (INGLOBAL || !infuncs) return;
   60     if (!multiple) {
   61         if (printed.intFind ((wrt ? 1000000 : 0) + (arr ? 2000000 : 0) +
   62             frame * 100000 + s))
   63             return;
   64         else new intNode (&printed);
   65     }
   66 
   67     if (frame == -1 ) PRINTF (wrt ? (arr ? txt_evar_a : txt_evar) :
   68                  arr ? txt_evar_ra : txt_evar_r, C_Syms [SYMBOLID (s)]);
   69     else if (frame == 0 ) PRINTF (wrt ? (arr ? txt_gvar_a : txt_gvar) :
   70                  arr ? txt_gvar_ra : txt_gvar_r, C_Syms [SYMBOLID (s)]);
   71     else PRINTF (wrt ? (arr ? txt_memb_a : txt_memb) : arr ? txt_memb_ra : txt_memb_r, 
   72                  structname (struct_by_name (frame)), C_Syms [SYMBOLID (s)]);
   73     if (arr) report (s, frame, false, false);
   74 }
   75 
   76 static Symbol current_function;
   77 
   78 void newfunction (Symbol s)
   79 {
   80     current_function = s;
   81     PRINTF (txt_func, C_Syms [SYMBOLID (s)]);
   82     if (printed.root) {
   83         delete printed.root;
   84         printed.root = NULL;
   85     }
   86     if (printed_function.root) {
   87         delete printed_function.root;
   88         printed_function.root = NULL;
   89     }
   90 }
   91 
   92 static bool local_object (Symbol s)
   93 {
   94     lookup_object L (s);
   95     return L.FRAME > 0;
   96 }
   97 
   98 void report_call (Symbol s, bool pointer)
   99 {
  100         Symbol func = pointer && local_object (s) ? current_function : 0;
  101     if (!multiple)
  102         if (printed_function.intFind (s + func)) return;
  103         else new intNode (&printed_function);
  104     if (func)
  105         PRINTF (farg_named_call, C_Syms [SYMBOLID (func)], C_Syms [SYMBOLID (s)]);
  106     else
  107         PRINTF (pointer ? txt_fpcall : txt_fcall, C_Syms [SYMBOLID (s)]);
  108 }
  109 
  110 void report_callback (Symbol rec, Symbol s)
  111 {
  112     PRINTF (txt_fcallback, structname (rec), C_Syms [SYMBOLID (s)]);
  113 }
  114 
  115 struct argnameassign { Symbol s1, s2; int argi; };
  116 static earray<argnameassign> arg_names;
  117 
  118 static void stor_named_conv (Symbol f, Symbol a, int n)
  119 {
  120     int i = arg_names.alloc ();
  121     arg_names.x [i].s1 = SYMBOLID (f);
  122     arg_names.x [i].s2 = SYMBOLID (a);
  123     arg_names.x [i].argi = n;
  124 }
  125 
  126 void report_named_convert ()
  127 {
  128     int i;
  129     if (arg_names.nr) PRINTF ("\n");
  130     for (i = 0; i < arg_names.nr; i++)
  131         PRINTF (farg_call_redirect, C_Syms [arg_names.x [i].s1], C_Syms [arg_names.x [i].s2],
  132             C_Syms [arg_names.x [i].s1], arg_names.x [i].argi);
  133 }
  134 
  135 void report_fargcall (int a, Symbol s)
  136 {
  137     stor_named_conv (current_function, s, a);
  138     PRINTF (farg_named_call, C_Syms [SYMBOLID (current_function)], C_Syms [SYMBOLID (s)]);
  139 }
  140 
  141 struct fptrassign { Symbol s1, s2, m1, m2, fn, fn1; bool sptr, a1, a2; };
  142 static earray<fptrassign> fptr_assignments;
  143 
  144 // some help with the arguments
  145 // 's1' and 's2' are the names of the functions assigned.
  146 //   For example 'funcptr=foo', s1=funcptr and s2=foo
  147 // 'm1' and 'm2' are useful for the case one of the two is a member
  148 //   For example 'obj->funcptr=foo' or 'obj->funcptr=x.f'
  149 // if 'fn' is present then the second call is converted to 'fn/s2()'
  150 // if 'fn1' is present then the first call is of 'f1/s1()' form
  151 //  This is all too hairy but this function is the result of hacking
  152 //  and extending ncc itself.
  153 //
  154 void functionptr (Symbol s1, Symbol s2, bool pointer, Symbol m1, Symbol m2, Symbol fn, Symbol fn1, bool a1, bool a2)
  155 {
  156     int i;
  157     for (i = 0; i < fptr_assignments.nr; i++) {
  158         fptrassign fp = fptr_assignments.x [i];
  159         if (fp.s1 == s1 && fp.s2 == s2
  160         && fp.fn == fn && fp.fn1 == fn1
  161         && fp.a1 == a1 && fp.a2 == a2
  162         && fp.m1 == m1 && fp.m2 == m2) return;
  163     }
  164 
  165     i = fptr_assignments.alloc ();
  166     fptr_assignments.x [i].s1 = s1;
  167     fptr_assignments.x [i].s2 = s2;
  168     fptr_assignments.x [i].m1 = m1;
  169     fptr_assignments.x [i].m2 = m2;
  170     fptr_assignments.x [i].sptr = pointer;
  171     fptr_assignments.x [i].fn = fn;
  172     fptr_assignments.x [i].a1 = a1;
  173     fptr_assignments.x [i].a2 = a2;
  174     fptr_assignments.x [i].fn1 = fn1;
  175 }
  176 
  177 void report_fptrs ()
  178 {
  179     int i;
  180     for (i = 0; i < fptr_assignments.nr; i++) {
  181         fptrassign fp = fptr_assignments.x [i];
  182 
  183         PRINTF ("\nD: ");
  184         if (fp.m1 == -1 && fp.fn1 != -1)
  185             PRINTF ("%s/", C_Syms [SYMBOLID (fp.fn1)]);
  186         else if (fp.m1 != -1)
  187             PRINTF ("*%s.", structname (fp.s1));
  188         else PRINTF ("*");
  189         PRINTF ("%s", C_Syms [fp.m1 == -1 ? SYMBOLID (fp.s1) : SYMBOLID (fp.m1)]);
  190         if (fp.a1) PRINTF ("[]");
  191         PRINTF ("()\n");
  192         
  193         PRINTF ("F: ");
  194         if (fp.m2 == -1 && fp.fn != -1)
  195             PRINTF ("%s/", C_Syms [SYMBOLID (fp.fn)]);
  196         else if (fp.m2 == -1 && fp.fn == -1 && fp.sptr)
  197             PRINTF ("*");
  198         else if (fp.m2 != -1)
  199             PRINTF ("*%s.", structname (fp.s2));
  200         PRINTF ("%s", C_Syms [fp.m2 == -1 ? SYMBOLID (fp.s2) : SYMBOLID (fp.m2)]);
  201         if (fp.a2) PRINTF ("[]");
  202         PRINTF ("()\n");
  203     }
  204 }
  205 
  206 void report_virtual ()
  207 {
  208     PRINTF (txt_virt);
  209 }
  210 
  211 void report_error ()
  212 {
  213     PRINTF (txt_error);
  214 }
  215 
  216 struct fargsave { Symbol f, f2, s, lf; int ia, ia2; bool ptr; };
  217 static earray<fargsave> farg_saves;
  218 
  219 void report_fargval (Symbol f, int ia, Symbol f2, int ia2, bool ptr = false)
  220 {
  221     int i = farg_saves.alloc ();
  222     farg_saves.x [i].f = f;
  223     farg_saves.x [i].f2 = f2;
  224     farg_saves.x [i].ia = ia;
  225     farg_saves.x [i].ia2 = ia2;
  226     farg_saves.x [i].ptr = ptr;
  227     farg_saves.x [i].lf = farg_saves.x [i].s = -1;
  228 }
  229 
  230 void report_fargval_memb (Symbol f, int ia, Symbol s, Symbol m)
  231 {
  232     int i = farg_saves.alloc ();
  233     farg_saves.x [i].f = f;
  234     farg_saves.x [i].f2 = m;
  235     farg_saves.x [i].ia = ia;
  236     farg_saves.x [i].s = s;
  237     farg_saves.x [i].lf = -1;
  238 }
  239 
  240 void report_fargval_locf (Symbol f, int ia, Symbol f2, Symbol l)
  241 {
  242     int i = farg_saves.alloc ();
  243     farg_saves.x [i].f = f;
  244     farg_saves.x [i].f2 = f2;
  245     farg_saves.x [i].ia = ia;
  246     farg_saves.x [i].lf = l;
  247     farg_saves.x [i].s = -1;
  248 }
  249 
  250 void report_argument_calls ()
  251 {
  252     int i;
  253     if (farg_saves.nr) PRINTF ("\n");
  254     for (i = 0; i < farg_saves.nr; i++)
  255         if (farg_saves.x [i].s != -1)
  256         PRINTF (txt_membargval, C_Syms [SYMBOLID (farg_saves.x [i].f)],
  257             farg_saves.x [i].ia, C_Syms [SYMBOLID (farg_saves.x [i].s)],
  258             C_Syms [SYMBOLID (farg_saves.x [i].f2)]);
  259         else if (farg_saves.x [i].lf != -1)
  260         PRINTF (txt_argvalfl, C_Syms [SYMBOLID (farg_saves.x [i].f)],
  261             farg_saves.x [i].ia, C_Syms [SYMBOLID (farg_saves.x [i].lf)],
  262             C_Syms [SYMBOLID (farg_saves.x [i].f2)]);
  263         else if (farg_saves.x [i].ia2 == -1)
  264         PRINTF (farg_saves.x [i].ptr ? txt_argvalf : txt_argval,
  265             C_Syms [SYMBOLID (farg_saves.x [i].f)],
  266             farg_saves.x [i].ia,  C_Syms [SYMBOLID (farg_saves.x [i].f2)]);
  267         else
  268         PRINTF (txt_argvalargval, C_Syms [SYMBOLID (farg_saves.x [i].f)],
  269             farg_saves.x [i].ia,  C_Syms [SYMBOLID (farg_saves.x [i].f2)],
  270             farg_saves.x [i].ia2);
  271 }
  272 
  273 class ccsub_small
  274 {
  275 inline  void fconv ();
  276 inline  void iconv ();
  277 inline  void settype (int);
  278 inline  void lvaluate ();
  279 inline  void copytype (ccsub_small&);
  280 inline  void degrade (ccsub_small&);
  281 inline  void arithmetic_convert (ccsub_small&, ccsub_small&);
  282 inline  bool arithmetic ();
  283 inline  bool voidp ();
  284 inline  bool structure ();
  285 inline  void assign_convert (ccsub_small&);
  286     bool op1return;
  287 static  ccsub_small op1;
  288 inline  void cc_binwconv (ccsub_small&, ccsub_small&);
  289 inline  void cc_addptr (ccsub_small&, ccsub_small&);
  290     bool lv, modify, array;
  291     void cc_fcall (exprID);
  292     void cc_prepostfix (exprID);
  293 inline  void cc_terminal (exprID);
  294 inline  void cc_dot (exprID);
  295 inline  void cc_array (exprID);
  296 inline  void cc_star (exprID);
  297 inline  void cc_addrof (exprID);
  298 inline  void cc_ecast (exprID);
  299 inline  void cc_usign (exprID);
  300 inline  void cc_nbool (exprID);
  301 inline  void cc_compl (exprID);
  302 inline  void cc_add (exprID, bool = false);
  303     void cc_sub (exprID, bool = false);
  304     void cc_muldiv (exprID, bool = false);
  305     void cc_bintg (exprID, bool = false);
  306 inline  void cc_cmp (exprID);
  307     void cc_bool (exprID);
  308     void cc_conditional (exprID, exprID = -2);
  309     void cc_assign (exprID);
  310     void cc_oassign (exprID);
  311 inline  void cc_compound (exprID);
  312    public:
  313 inline  ccsub_small (exprID, bool = false, bool = false);
  314     ccsub_small () {}
  315     ccsub_small (typeID, char*);
  316 
  317     int base, spec [MSPEC];
  318 };
  319 
  320 ccsub_small ccsub_small::op1;
  321 
  322 void ccsub_small::cc_terminal (exprID ei)
  323 {
  324     subexpr e = ee [ei];
  325     lookup_object ll (e.voici.symbol);
  326     if (ll.enumconst) {
  327         settype (S_INT);
  328         return;
  329     }
  330     base = ll.base;
  331     intcpy (spec, ll.spec);
  332     if (ll.FRAME <= 0)
  333         report (e.voici.symbol, ll.FRAME, modify, array);
  334     lvaluate ();
  335 }
  336 
  337 void ccsub_small::cc_addrof (exprID ei)
  338 {
  339     ccsub_small o (ee [ei].voici.e);
  340 
  341     base = o.base;
  342     if (o.lv || o.structure ()) {
  343         spec [0] = '*';
  344         intcpy (&spec [1], o.spec);
  345     } else if (o.spec [0] != -1)
  346         intcpy (spec, o.spec);
  347     else half_error ("&address_of not addressable");
  348 }
  349 
  350 void ccsub_small::cc_star (exprID e)
  351 {
  352     ccsub_small o (ee [e].voici.e);
  353     degrade (o);
  354     lvaluate ();
  355 }
  356 
  357 void ccsub_small::cc_array (exprID ei)
  358 {
  359     ccsub_small o1 (ee [ei].voici.e, modify, true), o2 (ee [ei].e);
  360     cc_addptr (o1, o2);
  361     degrade (*this);
  362     lvaluate ();
  363 }
  364 
  365 void ccsub_small::cc_dot (exprID ei)
  366 {
  367     subexpr e = ee [ei];
  368     ccsub_small o (e.voici.e, modify);
  369     lookup_member lm (e.voila.member, o.base);
  370     base = lm.base;
  371     intcpy (spec, lm.spec);
  372     report (e.voila.member, o.base, modify, array);
  373     lvaluate ();
  374 }
  375 
  376 void ccsub_small::cc_ecast (exprID ei)
  377 {
  378     subexpr e = ee [ei];
  379     ccsub_small o (e.voici.e), pseudo (e.voila.cast, "");
  380     o.assign_convert (pseudo);
  381     copytype (o);
  382     *this = o;
  383 }
  384 
  385 void ccsub_small::cc_usign (exprID ei)
  386 {
  387     subexpr e = ee [ei];
  388     ccsub_small o (e.voici.e);
  389     copytype (o);
  390 }
  391 
  392 void ccsub_small::cc_nbool (exprID ei)
  393 {
  394     ccsub_small o (ee [ei].voici.e);
  395     (void) o;
  396     settype (S_INT);
  397 }
  398 
  399 void ccsub_small::cc_compl (exprID ei)
  400 {
  401     ccsub_small o (ee [ei].voici.e);
  402     (void) o;
  403     settype (S_INT);
  404 }
  405 
  406 void ccsub_small::cc_bintg (exprID ei, bool m1)
  407 {
  408     subexpr e = ee [ei];
  409     ccsub_small o1 (e.voici.e, m1), o2 (e.e);
  410     (void) o2;
  411     if (op1return) op1 = o1;
  412     settype (S_INT);
  413 }
  414 
  415 void ccsub_small::cc_muldiv (exprID ei, bool m1)
  416 {
  417     subexpr e = ee [ei];
  418     ccsub_small o1 (e.voici.e, m1), o2 (e.e);
  419     if (op1return) op1 = o1;
  420     cc_binwconv (o1, o2);
  421 }
  422 
  423 void ccsub_small::cc_prepostfix (exprID ei)
  424 {
  425     subexpr e = ee [ei];
  426     ccsub_small o (e.voici.e, true);
  427     copytype (o);
  428 }
  429 
  430 void ccsub_small::cc_add (exprID ei, bool m1)
  431 {
  432     subexpr e = ee [ei];
  433     ccsub_small o1 (e.voici.e, m1), o2 (e.e);
  434 
  435     if (op1return) op1 = o1;
  436     if (o1.arithmetic () && o2.arithmetic ())
  437         cc_binwconv (o1, o2);
  438     else    cc_addptr (o1, o2);
  439 }
  440 
  441 void ccsub_small::cc_sub (exprID ei, bool m1)
  442 {
  443     subexpr e = ee [ei];
  444     ccsub_small o1 (e.voici.e, m1), o2 (e.e);
  445 
  446     if (op1return) op1 = o1;
  447 
  448     if (o1.arithmetic () && o2.arithmetic ()) {
  449         cc_binwconv (o1, o2);
  450         return;
  451     }
  452 
  453     if (!o1.arithmetic () && !o2.arithmetic ()) settype (S_INT);
  454     else copytype (o1);
  455 }
  456 
  457 void ccsub_small::cc_cmp (exprID ei)
  458 {
  459     subexpr e = ee [ei];
  460     ccsub_small o1 (e.voici.e), o2 (e.e);
  461 
  462     if (o1.arithmetic () && o1.arithmetic ())
  463         arithmetic_convert (o1, o2);
  464     settype (S_INT);
  465 }
  466 
  467 void ccsub_small::cc_bool (exprID ei)
  468 {
  469     subexpr e = ee [ei];
  470     ccsub_small o1 (e.voici.e);
  471     ccsub_small o2 (e.e);
  472     (void) o1;
  473     (void) o2;
  474     settype (S_INT);
  475 }
  476 
  477 void ccsub_small::cc_conditional (exprID ei, exprID args)
  478 {
  479     subexpr e = ee [ei];
  480     if (args != -2) {
  481         //   we have the:
  482         // (i ? a : b) ()
  483         //   case. Convert it to:
  484         // (i ? a () : b ())
  485         ee [NeTop] = ee [e.e];
  486         ee [e.e].action = FCALL;
  487         ee [e.e].voici.e = NeTop++;
  488         ee [e.e].e = args;
  489         ee [NeTop] = ee [e.voila.eelse];
  490         ee [e.voila.eelse].action = FCALL;
  491         ee [e.voila.eelse].voici.e = NeTop++;
  492         ee [e.voila.eelse].e = args;
  493     }
  494     ccsub_small o (e.voici.e);
  495     ccsub_small o1 (e.e);
  496     ccsub_small o2 (e.voila.eelse);
  497     ccsub_small *po = e.e==-1 ? &o : &o1;
  498     (void) o1;
  499     (void) o2;
  500     (void) o;
  501     if (po->arithmetic () || po->voidp ()) copytype (o2);
  502     else copytype (*po);
  503 }
  504 
  505 static void callbacks (exprID e1, exprID e2)
  506 {
  507     Symbol s1, s2, m1 = -1, m2 = -1, fn = -1, fn1 = -1;
  508     bool ptrs = false;
  509     int a1 = 0, a2 = 0;
  510 
  511     again1: if (ee [e1].action == SYMBOL) {
  512         --a1;
  513         s1 = ee [e1].voici.symbol;
  514         if (local_object (s1))
  515             fn1 = current_function;
  516     } else if (ee [e1].action == MEMB) {
  517         ccsub_small os (ee [e1].voici.e);
  518         --a1;
  519         s1 = struct_by_name (os.base);
  520         m1 = ee [e1].voila.member;
  521     } else if (ee [e1].action == ARRAY || ee [e1].action == PTRIND) {
  522         e1 = ee [e1].voici.e;
  523         a1 = 2;
  524         goto again1;
  525     } else return;
  526 
  527     bool casted = false;
  528     again: if (ee [e2].action == SYMBOL) {
  529         --a2;
  530         s2 = ee [e2].voici.symbol;
  531         if ((ptrs = !have_function (s2))) {
  532             lookup_function lf (s2, false);
  533             if (!lf.found) return;
  534             if (lf.ARGFUNC) {
  535                 fn = current_function;
  536 //              fn = s2;
  537 //              s2 = current_function;
  538                 stor_named_conv (s2, fn, lf.displacement);
  539             } else if (lf.fptr && lf.FRAME > 0) {
  540 //              fn = s2;
  541 //              s2 = current_function;
  542                 fn = current_function;
  543             }
  544         }
  545     } else if (ee [e2].action == MEMB) {
  546         --a2;
  547         ccsub_small os (ee [e2].voici.e);
  548         s2 = struct_by_name (os.base);
  549         m2 = ee [e2].voila.member;
  550     } else if (casted = ee [e2].action == CAST) {
  551         e2 = ee [e2].voici.e;
  552         goto again;
  553     } else if (ee [e2].action == ARRAY || ee [e2].action == PTRIND) {
  554         e2 = ee [e2].voici.e;
  555         a2 = 2;
  556         goto again;
  557     } else if (ee [e2].action == COND) {
  558         callbacks (e1, ee [e2].e == -1 ? ee [e2].voici.e : ee [e2].e);
  559         callbacks (e1, ee [e2].voila.eelse);
  560         return;
  561     } else return;
  562 
  563     functionptr (s1, s2, ptrs, m1, m2, fn, fn1, a1 == 1, a2 == 1);
  564 }
  565 
  566 void ccsub_small::cc_assign (exprID ei)
  567 {
  568     subexpr e = ee [ei];
  569     ccsub_small o1 (e.voici.e, true), o2 (e.e);
  570 
  571     if (o1.spec[0] == '*' && o1.spec [1] == '(')
  572         callbacks (e.voici.e, e.e);
  573 
  574     (void) o2.lv;
  575     copytype (o1);
  576 }
  577 
  578 void ccsub_small::cc_oassign (exprID ei)
  579 {
  580     op1return = true;
  581     switch (ee [ei].action) {
  582         case ASSIGNA:   cc_add (ei, true); break;
  583         case ASSIGNS:   cc_sub (ei, true); break;
  584         case ASSIGNM:
  585         case ASSIGND:   cc_muldiv (ei, true); break;
  586         case ASSIGNBA: case ASSIGNBX: case ASSIGNBO:
  587         case ASSIGNRS: case ASSIGNLS:
  588         case ASSIGNR:   cc_bintg (ei, true); break;
  589     }
  590     copytype (op1);
  591 }
  592 
  593 static void fargs (exprID ei, Symbol fs, int i)
  594 {
  595     again: if (ee [ei].action == SYMBOL) {
  596         Symbol t = ee [ei].voici.symbol;
  597         if (have_function (t))
  598             report_fargval (fs, i, t, -1);
  599         else {
  600             lookup_function lf (t, false);
  601             if (!lf.found) return;
  602             if (lf.ARGFUNC)
  603                 report_fargval (fs, i, current_function, lf.displacement);
  604             else if (!local_object (t))
  605                 report_fargval (fs, i, t, -1, true);
  606             else
  607                 report_fargval_locf (fs, i, t, current_function);
  608         }
  609     } else if (ee [ei].action == MEMB) {
  610         ccsub_small oo (ee [ei].voici.e);
  611         report_fargval_memb (fs, i, struct_by_name (oo.base),
  612                      ee [ei].voila.member);
  613     } else if (ee [ei].action == CAST) {
  614         ei = ee [ei].voici.e;
  615         goto again;
  616     }
  617 }
  618 
  619 void ccsub_small::cc_fcall (exprID ei)
  620 {
  621     int i = 2;
  622     subexpr e = ee [ei];
  623     subexpr fe = ee [e.voici.e];
  624     Symbol fs = -1;
  625 
  626     if (fe.action == SYMBOL) {
  627         lookup_function lf (fe.voici.symbol);
  628         fs = fe.voici.symbol;
  629         if (!lf.ARGFUNC)
  630             report_call (fe.voici.symbol, lf.fptr);
  631         else
  632             report_fargcall (lf.displacement, fe.voici.symbol);
  633         base = lf.base;
  634         intcpy (spec, lf.spec + 2);
  635     } else if (fe.action == COND) {
  636         cc_conditional (e.voici.e, e.e);
  637         return;
  638     } else {
  639         ccsub_small fn (e.voici.e);
  640 
  641         if (fn.spec [0] != '(') {
  642             if (fn.spec [0] == '*' && fn.spec [1] == '(')
  643                 i = 3;
  644             else half_error ("not a function");
  645         }
  646         base = fn.base;
  647         intcpy (spec, fn.spec + i);
  648 
  649         if (fe.action == MEMB) {
  650             ccsub_small os (fe.voici.e);
  651             report_callback (struct_by_name (os.base), fe.voila.member);
  652         } else if (fe.action == PTRIND) {
  653             if (ee [fe.voici.e].action == MEMB) {
  654                 subexpr effi = ee [fe.voici.e];
  655                 ccsub_small os (effi.voici.e);
  656                 report_callback (struct_by_name (os.base), effi.voila.member);
  657             } else if (ee [fe.voici.e].action == SYMBOL) {
  658                 lookup_function lf (ee [fe.voici.e].voici.symbol, false);
  659                 if (!lf.ARGFUNC)
  660                     report_call (fs = ee [fe.voici.e].voici.symbol, true);
  661                 else
  662                     report_fargcall (lf.displacement, ee [fe.voici.e].voici.symbol);
  663             }
  664         } else report_virtual ();
  665     }
  666 
  667     if ((ei = e.e) != -1) {
  668         int i;
  669         bool fsok = fs != -1 && fs != current_function;
  670 
  671         for (i = 0; ee [ei].action == ARGCOMMA; ei = ee [ei].e, i++) {
  672             exprID eii = ee [ei].voici.e;
  673             ccsub_small o (eii);
  674             o.lv = o.lv;
  675             if (fsok && o.spec [0] == '*' && o.spec [1] == '(')
  676                 fargs (eii, fs, i);
  677         }
  678         ccsub_small o (ei);
  679         o.lv = o.lv;
  680         if (fsok && o.spec [0] == '*' && o.spec [1] == '(')
  681             fargs (ei, fs, i);
  682     }
  683 }
  684 
  685 void ccsub_small::cc_compound (exprID ei)
  686 {
  687     base = base_of (ee [ei].voila.result_type);
  688     intcpy (spec, spec_of (ee [ei].voila.result_type));
  689 }
  690 
  691 ////////////////////////////////////////////////////////////////////////////
  692 
  693 void ccsub_small::cc_binwconv (ccsub_small &o1, ccsub_small &o2)
  694 {
  695     arithmetic_convert (o1, o2);
  696     settype (o1.base);
  697 }
  698 
  699 void ccsub_small::cc_addptr (ccsub_small &o1, ccsub_small &o2)
  700 {
  701     bool b2 = o2.arithmetic ();
  702     if (b2) {
  703         o2.lv = false;
  704         copytype (o1);
  705     } else {
  706         o1.lv = false;
  707         copytype (o2);
  708     }
  709 }
  710 
  711 void ccsub_small::copytype (ccsub_small &o)
  712 {
  713     base = o.base;
  714     intcpy (spec, o.spec);
  715 }
  716 
  717 void ccsub_small::degrade (ccsub_small &o)
  718 {
  719     base = o.base;
  720     if (o.spec [0] == -1) half_error ("Not a pointer");
  721     intcpy (spec, o.spec + (o.spec [0] == '(' ? 0 : o.spec [0] == '*' ? 1 : 2));
  722 }
  723 
  724 bool ccsub_small::structure ()
  725 {
  726     return spec [0] == -1 && base >= 0;
  727 }
  728 
  729 bool ccsub_small::arithmetic ()
  730 {
  731     return spec [0] == -1 && base < VOID || spec [0] == ':';
  732 }
  733 
  734 bool ccsub_small::voidp ()
  735 {
  736     return spec [0] == '*' && base == VOID;
  737 }
  738 
  739 void ccsub_small::lvaluate ()
  740 {
  741     lv = !(spec [0] =='[' || spec [0] ==-1 && base >=0 || spec [0] =='(');
  742 }
  743 
  744 void ccsub_small::settype (int b)
  745 {
  746     base = b;
  747     spec [0] = -1;
  748 }
  749 
  750 void ccsub_small::assign_convert (ccsub_small &o)
  751 {
  752     if (o.arithmetic ())
  753         if (o.base != FLOAT) iconv ();
  754         else fconv ();
  755     base = o.base;
  756     intcpy (spec, o.spec);
  757 }
  758 
  759 void ccsub_small::arithmetic_convert (ccsub_small &o1, ccsub_small &o2)
  760 {
  761     if (o1.base == FLOAT || o2.base == FLOAT) {
  762         if (o1.base != o2.base)
  763             if (o1.base == FLOAT) o2.fconv ();
  764             else o1.fconv ();
  765     }
  766 }
  767 
  768 void ccsub_small::fconv ()
  769 {
  770     settype (FLOAT);
  771 }
  772 
  773 void ccsub_small::iconv ()
  774 {
  775     settype (S_INT);
  776 }
  777 
  778 //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  779 
  780 ccsub_small::ccsub_small (exprID ei, bool mod, bool arr)
  781 {
  782     modify = mod;
  783     array = arr;
  784     if (ei == -1) return;
  785 advance:
  786     subexpr e = ee [ei];
  787 
  788     lv = false;
  789     op1return = false;
  790     switch (e.action) {
  791         case VALUE:
  792         case UVALUE:    settype (S_INT);    break;
  793         case FVALUE:    settype (FLOAT);    break;
  794         case SVALUE:    base = S_CHAR; spec [0] = '*'; spec [1] = -1;
  795                 break;
  796         case AVALUE:    base = VOID; spec [0] = '*'; spec [1] = -1;
  797                 break;
  798         case SYMBOL:    cc_terminal (ei);   break;
  799         case FCALL: cc_fcall (ei);      break;
  800         case MEMB:  cc_dot (ei);        break;
  801         case ARRAY: cc_array (ei);      break;
  802         case ADDROF:    cc_addrof (ei);     break;
  803         case PTRIND:    cc_star (ei);       break;
  804         case MMPOST: case PPPOST:
  805         case PPPRE:
  806         case MMPRE: cc_prepostfix (ei); break;
  807         case CAST:  cc_ecast (ei);      break;
  808         case LNEG:  cc_nbool (ei);      break;
  809         case OCPL:  cc_compl (ei);      break;
  810         case UPLUS:
  811         case UMINUS:    cc_usign (ei);      break;
  812         case SIZEOF:    settype (S_INT);    break;
  813         case MUL:
  814         case DIV:   cc_muldiv (ei);     break;
  815         case ADD:   cc_add (ei);        break;
  816         case SUB:   cc_sub (ei);        break;
  817         case SHR: case SHL: case BOR: case BAND: case BXOR:
  818         case REM:   cc_bintg (ei);  break;
  819         case IAND:
  820         case IOR:   cc_bool (ei);       break;
  821         case BNEQ: case CGR: case CGRE: case CLE: case CLEE:
  822         case BEQ:   cc_cmp (ei);    break;
  823         case COND:  cc_conditional (ei);    break;
  824         case COMPOUND_RESULT:   cc_compound (ei); break;
  825         case COMMA: {
  826             ccsub_small o (e.voici.e);
  827             ei = e.e;
  828             (void) o;
  829             goto advance;
  830         }
  831         default:
  832             if (e.action == '=') cc_assign (ei);
  833             else cc_oassign (ei);
  834     }
  835 }
  836 
  837 
  838 ccsub_small::ccsub_small (typeID t, char*)
  839 {
  840     base = base_of (t);
  841     intcpy (spec, spec_of (t));
  842 }
  843 
  844 //
  845 //
  846 //
  847 //
  848 
  849 class ncci_usage : public ncci
  850 {
  851     public:
  852     void cc_expression ();
  853     void new_function (Symbol);
  854     void inline_assembly (NormPtr, int);
  855     void finir ();
  856 };
  857 
  858 void ncci_usage::cc_expression ()
  859 {
  860     try {
  861         if (CExpr.first != -1)  {
  862             ccsub_small CC (CExpr.first);
  863 #ifdef GNU_VIOLATIONS
  864             last_result_type.base = CC.base;
  865             intcpy (last_result_type.spec, CC.spec);
  866 #endif
  867         }
  868     } catch (EXPR_ERROR) { }
  869     last_result++;
  870 }
  871 
  872 void ncci_usage::new_function (Symbol s)
  873 {
  874     newfunction (s);
  875 }
  876 
  877 void ncci_usage::inline_assembly (NormPtr p, int n)
  878 {
  879 // hoping that inline assembly won't use global variables,
  880 // nor call functions, it is ignored (for now at least)
  881 }
  882 
  883 void ncci_usage::finir ()
  884 {
  885     report_fptrs ();
  886     report_named_convert ();
  887     report_argument_calls ();
  888 }
  889 
  890 void set_usage_report ()
  891 {
  892     ncc = new ncci_usage;
  893 }