"Fossies" - the Fresh Open Source Software Archive

Member "ncc-2.8/cdb.C" (11 Oct 2008, 36155 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     data collected from the parser
    4 
    5 *****************************************************************************/
    6 #include <stdlib.h>
    7 #include <string.h>
    8 #include <stdio.h>
    9 #include <unistd.h>
   10 #include <assert.h>
   11 
   12 #include "global.h"
   13 #include "dbstree.h"
   14 #include "inttree.h"
   15 #include "mem_pool.h"
   16 
   17 /*****************************************************************************
   18 #
   19 #   the most complex part in a C compiler is the data structures
   20 #   storing what is introduced from the declarations.
   21 #
   22 #   the base to understanding how the program works, is understanding
   23 #   the way data is stored and retrieved from this cdb.
   24 #
   25 #   what this file provides is described in global.h at
   26 #   `CDB interface' 
   27 #
   28 #   this is where all the money went...
   29 *****************************************************************************/
   30 
   31 /*****************************************************************************
   32 #
   33 #   In many parts of the program, there is multiplexing of
   34 #   different kind of pointers in integers.
   35 #   Thats a thing we can do in 32-bit architectures
   36 #   ==> A register can have values up to 4 billion
   37 #       and thus, when used as an index of arrays, it
   38 #       can actually store much more.
   39 #
   40 #   For example. Suppose a program is using foo[]s and
   41 #   zoo[]s and at some point we have something that may
   42 #   be either a foo or a zoo. That can be multiplexed
   43 #   into an integer 'x', where:
   44 #       if it is a foo, x = index in foo []
   45 #       if it is a zoo, x = 10000000 + index in zoo []
   46 #
   47 #   This situation is common in many programs and 32-bit
   48 #   architectures are not only about "4Gb of memory"
   49 #
   50 #   Here are basic indexes used:
   51 #
   52 # typeID:   integer describing index in the types [] table of
   53 #       basetype+pointers/arrays/arguments
   54 # ObjPtr:   integer which multiplexes possible base-types into one
   55 #       Bitfield:   if < -32
   56 #       Builtin:    <BASETYPE> if < _BTLIMIT
   57 #       Structure:  <RegionPtr> if < TYPEDEF_BASE && positive
   58 #       Typedef:    <typeID> if > TYPEDEF_BASE
   59 #           in the latter case typeID = ObjPtr - TYPEDEF_BASE
   60 # RegionPtr:    integer describing index in regions [] table
   61 # NormPtr:  integer describing index in the CODE[] normalized C source
   62 # ArglPtr:  integer describing index in arglists[] table
   63 # Symbol:   integer describing value of CODE[]
   64 #
   65 *****************************************************************************/
   66 bool INGLOBAL, INSTRUCT;
   67 typeID VoidType, SIntType;
   68 ArglPtr NoArgSpec;
   69 
   70 /*****************************************************************************
   71 #   type pool   (typeID)
   72 #
   73 #   here we allocate types. Types of X are:
   74 #       int X
   75 #       int **X
   76 #       int * X [32][64][]
   77 #       struct foo *X
   78 #       int X (int, char*, struct bar**)
   79 #       struct foo **(*X[3]) (int, char)
   80 #
   81 #   abstract declarations for the above are described with a
   82 #   'struct type' object, which includes basetype (ObjPtr)
   83 #   and specifications (pointer, array-size, function-ArglistPtr).
   84 #   For example, the latter foo has specifications:
   85 #       '[', 3, '*', '(', <ArglPtr>, '*', '*', -1
   86 #   which sais: array 3 of pointer to function with arguments
   87 #           at <ArglPtr> returning pointer to pointer to basetype
   88 #
   89 #   the types[] table, does not include typedef basetypes.
   90 #   typedefs are expanded before things are inserted into types[]
   91 #   with use of the gettype(type&) function.
   92 *****************************************************************************/
   93 static earray<type> types;
   94 class utype;
   95 static dbsTree<utype> typetree;
   96 struct utype
   97 {
   98     utype *less, *more;
   99 static  type Query;
  100     utype ();
  101     typeID ID;
  102     int compare (utype*);
  103     int compare ();
  104 };
  105 
  106 utype::utype ()
  107 {
  108     typetree.addself (this);
  109     ID = types.alloc ();
  110     types.x [ID].base = Query.base;
  111     types.x [ID].spec = intdup (Query.spec);
  112 }
  113 
  114 int base_of (typeID i)
  115 {
  116     return types.x [i].base;
  117 }
  118 
  119 int *spec_of (typeID i)
  120 {
  121     return types.x [i].spec;
  122 }
  123 
  124 type utype::Query;
  125 int utype::compare (utype *u)
  126 {
  127     RegionPtr p = base_of (ID);
  128     RegionPtr p2 = base_of (u->ID);
  129     if (p == p2) return intcmp (spec_of (ID), spec_of (u->ID));
  130     return p < p2 ? -1 : 1;
  131 }
  132 
  133 int utype::compare ()
  134 {
  135     RegionPtr p = base_of (ID);
  136     RegionPtr p2 = Query.base;
  137     if (p == p2) return intcmp (spec_of (ID), Query.spec);
  138     return p < p2 ? -1 : 1;
  139 }
  140 
  141 typeID newtype (type &t)
  142 {
  143     utype::Query.base = t.base;
  144     utype::Query.spec = t.spec;
  145     utype *u = (utype*) typetree.dbsFind ();
  146     if (!u) u = new utype;
  147     return u->ID;
  148 }
  149 
  150 typeID gettype (type &t)
  151 {
  152     if (t.base < TYPEDEF_BASE) return newtype (t);
  153 
  154     type nt;
  155     typeID td = t.base - TYPEDEF_BASE;
  156     int newspec [MSPEC];
  157 
  158     // check incomplete typedef
  159     intcpycat (newspec, t.spec, types.x [td].spec);
  160     nt.base = base_of (td);
  161     nt.spec = newspec;
  162     return newtype (nt);
  163 }
  164 
  165 typeID gettype (int base, int *spec)
  166 {
  167     type t;
  168     t.base = base;
  169     t.spec = spec;
  170     return gettype (t);
  171 }
  172 
  173 void opentype (typeID ti, type &t)
  174 {
  175     t.base = base_of (ti);
  176     t.spec = spec_of (ti);
  177 }
  178 /*****************************************************************************
  179 #   argument lists.
  180 #
  181 #   Array of typeIDs terminated at -1.
  182 #   also stored in a dbstree for log(N) insert
  183 *****************************************************************************/
  184 static earray<typeID*>  arglists;
  185 class argNode;
  186 static dbsTree<argNode>     argTree;
  187 
  188 class argNode
  189 {
  190    public:
  191     argNode *less, *more;
  192 static  Vspec Query;
  193     argNode ();
  194     int compare (argNode*);
  195     int compare ();
  196     ArglPtr ID;
  197 };
  198 
  199 Vspec argNode::Query;
  200 
  201 int argNode::compare (argNode *d)
  202 {
  203     return intcmp (arglists.x [ID], arglists.x [d->ID]);
  204 }
  205 
  206 int argNode::compare ()
  207 {
  208     return intcmp (arglists.x [ID], Query);
  209 }
  210 
  211 argNode::argNode ()
  212 {
  213     argTree.addself (this);
  214     ID = arglists.alloc ();
  215     arglists.x [ID] = intdup (Query);
  216 }
  217 
  218 ArglPtr make_arglist (typeID *t)
  219 {
  220     argNode::Query = t;
  221     argNode *a = argTree.dbsFind ();
  222     if (!a) a = new argNode;
  223     return a->ID;
  224 }
  225 
  226 typeID *ret_arglist (ArglPtr n)
  227 {
  228     return arglists.x [n];
  229 }
  230 /*****************************************************************************
  231 #   identifier lookup
  232 #
  233 #   for each identifier, there is a list including:
  234 #       what this identifier is, and
  235 #       which region (scope) this applies to
  236 #   there is also an array of regions, each with the
  237 #   index of its parent region.
  238 #
  239 #   with these, here we deal with lookups.
  240 #   Introducing new names in regions is done later.
  241 #
  242 #   RECORD uses info.rp which shows which region it is about
  243 #   ENUMCONST uses info.eval for the value
  244 #   ENUMTAG is only useful for its existance
  245 *****************************************************************************/
  246 static RegionPtr current_region;
  247 
  248 enum ITYPE {
  249     RECORD, ENUMTAG, TYPEDEF, OBJECT, EOBJECT,
  250     ENUMCONST, EFUNCTION, IFUNCTION
  251 };
  252 #define ISTAG(x) (x <= ENUMTAG)
  253 
  254 static struct lookup_t {
  255     lookup_t *next;
  256     RegionPtr cp;
  257     lookup_t (Symbol, ITYPE, RegionPtr);
  258     union {
  259         RegionPtr rp;
  260         typeID tdf;
  261         int eval;
  262         bool fwd;
  263     } info;
  264     int placement;
  265     char kind, incomplete, defspec;
  266 } **lookup_table;
  267 
  268 lookup_t::lookup_t (Symbol s, ITYPE i, RegionPtr r)
  269 {
  270     next = lookup_table [s - SYMBASE];
  271     lookup_table [s - SYMBASE] = this;
  272     kind = i;
  273     cp = r;
  274 }
  275 
  276 struct memb_li
  277 {
  278     Symbol s;
  279     memb_li *next;
  280 };
  281 
  282 enum REGION {
  283     GLOBAL, CCODE, FUNCTIONAL, RECORD_S, RECORD_U
  284 };
  285 
  286 struct region {
  287     RegionPtr parent;
  288     REGION kind;
  289     int aligned_top, nn;
  290     char used, bits, incomplete;
  291     NormPtr dcls, dcll;
  292     memb_li *first, *last;
  293     int add_object (typeID);
  294     int add_field (typeID, typeID&);
  295     void add_member (Symbol);
  296 };
  297 #define ISRECORD(x) (x >= RECORD_S)
  298 
  299 int region::add_object (typeID t)
  300 {
  301     if (usage_only) return nn++;
  302     if (kind == RECORD_U) {
  303         int i = sizeof_typeID (t);
  304         if (i > aligned_top) aligned_top = i;
  305         return 0;
  306     }
  307     int r = aligned_top;
  308     int i = sizeof_typeID (t);
  309     nn++;
  310     if (i == 0) ;
  311     else if (i == 1) aligned_top++;
  312     else if (i == 2) aligned_top += aligned_top % 2 ? 3 : 2;
  313     else {
  314         int a = aligned_top % 4;
  315         if (a == 0) aligned_top += i;
  316         else aligned_top += 4 - a + i;
  317     }
  318     return r;
  319 }
  320 
  321 int region::add_field (typeID ti, typeID &ret)
  322 {
  323     type t = types.x [ti];
  324     type nt;
  325     int spec [3] = { -1, 0, -1 }, r = aligned_top;
  326 
  327     if (t.spec [1] == 0) {
  328         bits = 0;
  329         nt.base = S_INT;
  330         spec [0] = '[';
  331         nt.spec = spec;
  332         ret = gettype (nt);
  333         if (kind != RECORD_U) aligned_top += 4;
  334         return r;
  335     }
  336     if ((bits += t.spec [1]) > BITFIELD_Q) {
  337         bits = 0;
  338         if (kind != RECORD_U) aligned_top += 4;
  339     }
  340     nt.base = -(bits + 32 * t.spec [1]);
  341     nt.spec = spec;
  342     ret = gettype (nt);
  343     return r;
  344 }
  345 
  346 static mem_pool<region> regions;
  347 
  348 void struct_location (typeID t, NormPtr s, int l)
  349 {
  350     regions [t].dcls = s;
  351     regions [t].dcll = l;
  352 }
  353 
  354 static struct {
  355     RegionPtr cc [32];
  356     int cci;
  357 } p_region;
  358 
  359 RegionPtr open_region (RegionPtr r)
  360 {
  361     p_region.cc [p_region.cci++] = current_region;
  362 
  363     current_region = r;
  364     INGLOBAL = false;
  365     INSTRUCT = ISRECORD (regions [r].kind);
  366     return r;
  367 }
  368 
  369 RegionPtr new_region (REGION kind, RegionPtr r)
  370 {
  371     RegionPtr n;
  372     regions [n = regions.alloc ()].parent = r;
  373     regions [n].kind = kind;
  374     regions [n].nn = regions [n].aligned_top = regions [n].bits = 0;
  375     regions [n].incomplete = 1;
  376     regions [n].used = 0;
  377     regions [n].dcll = 0;
  378     regions [n].first = regions [n].last = NULL;
  379     return n;
  380 }
  381 
  382 RegionPtr open_region (REGION kind, RegionPtr r)
  383 {
  384     return open_region (new_region (kind, r));
  385 }
  386 
  387 void close_region ()
  388 {
  389     regions [current_region].incomplete = 0;
  390     current_region = p_region.cc [--p_region.cci];
  391     INGLOBAL = current_region == 0;
  392     INSTRUCT = !INGLOBAL && ISRECORD (regions [current_region].kind);
  393 }
  394 
  395 lookup_t *Lookup (Symbol s, bool tagged, RegionPtr r)
  396 {
  397     lookup_t *t = lookup_table [s - SYMBASE];
  398 
  399     if (tagged) for (; t; t = t->next) {
  400         if (t->cp == r && ISTAG(t->kind)) {
  401             regions [r].used = 1;
  402             return t;
  403         }
  404     } else for (; t; t = t->next)
  405         if (t->cp == r && !ISTAG(t->kind)) {
  406             regions [r].used = 1;
  407             return t;
  408         }
  409 
  410     return NULL;
  411 }
  412 
  413 lookup_t *Lookup_foruse (Symbol s, bool tagged, RegionPtr r)
  414 {
  415     lookup_t *t;
  416     for (;;) {
  417         if ((t = Lookup (s, tagged, r))) return t;
  418         if (r == 0) break;
  419         r = regions [r].parent;
  420     }
  421     return NULL;
  422 }
  423 /*****************************************************************************
  424 #   small utility : comparison of types
  425 #
  426 #   Normally, comparison one by one would be plentyly enough, but a
  427 #   function declaration w/o arguments is a wildcard that should
  428 #   match with any other argument list
  429 #   Moreover, incomplete arrays match with complete arrays
  430 *****************************************************************************/
  431 static Ok speccmp (Vspec s1, Vspec s2)
  432 {
  433     while (*s1 != -1) {
  434         if (*s1 != *s2) return false;
  435         if (*s1 == '(') {
  436             ++s1, ++s2;
  437             // In the very rare case of:
  438             //  "int foo (float*);"
  439             //  "typedef float v3d [3];"
  440             //  "int foo (v3d x) { ... }"
  441             //  we will fail.
  442             //  Instead of fixing, comment out.
  443             //if (*s1 != *s2 && *s1 != NoArgSpec && *s2 != NoArgSpec)
  444                 //return false;
  445         } else if (*s1 == '[') {
  446             ++s1, ++s2;
  447             // why bother?
  448             //if (*s1 != *s2 && *s1 != 0 && *s2 != 0)
  449                 //return false;
  450         }
  451         ++s1, ++s2;
  452     }
  453     return *s1 == *s2;
  454 }
  455 
  456 static Ok typecmp (typeID ti1, typeID ti2)
  457 {
  458     type t1 = types.x [ti1];
  459     type t2 = types.x [ti2];
  460 
  461     return t1.base == t2.base && speccmp (t1.spec, t2.spec);
  462 }
  463 /******************************************************************************
  464 #   functions
  465 #
  466 #   functions are compiled after global has been parsed
  467 #   so that in expressions we know which variables are external.
  468 #
  469 #   At each function definition, we store the location to the
  470 #   function body and the function arguments in CODE[].
  471 #
  472 #   after the entire translation unit, function_no()
  473 #   will be called for each function, which will return the
  474 #   pointers to argument list, function body and open a
  475 #   region ready to receive the argument objects.
  476 ******************************************************************************/
  477 struct cfunc {
  478     Symbol name;
  479     NormPtr args, body, ends, txt;
  480 };
  481 
  482 static earray<cfunc> functions;
  483 
  484 Ok function_definition (Symbol name, NormPtr args, NormPtr body, NormPtr ends, NormPtr txt)
  485 {
  486     int i;
  487     lookup_t *L = Lookup (name, false, 0);
  488 
  489     if (L->kind != EFUNCTION) return false;
  490     L->kind = IFUNCTION;
  491 
  492     i = functions.alloc ();
  493     functions.x [i].name = name;
  494     functions.x [i].args = args;
  495     functions.x [i].body = body;
  496     functions.x [i].ends = ends;
  497     functions.x [i].txt = txt;
  498     L->placement = i;
  499     return true;
  500 }
  501 
  502 Ok function_no (int i, NormPtr *ra, NormPtr *rb)
  503 {
  504     if (i >= functions.nr) return false;
  505     *ra = functions.x [i].args;
  506     *rb = functions.x [i].body;
  507     open_region (FUNCTIONAL, 0);
  508     ncc->new_function (functions.x [i].name);
  509     return true;
  510 }
  511 
  512 void open_compound ()
  513 {
  514     open_region (CCODE, current_region);
  515 }
  516 
  517 void functions_of_file ()
  518 {
  519     int prevfile = -1;
  520     PRINTF ("\n\n");
  521     for (int i = 0; i < functions.nr; i++) {
  522         if (cfile_of (functions.x [i].body) != prevfile)
  523             PRINTF ("\nP: %s\n", C_Files [prevfile = 
  524              cfile_of (functions.x [i].body)].file);
  525         PRINTF ("L: %s() %i %i\n",
  526              expand (functions.x [i].name),
  527              cline_of (functions.x [i].txt),
  528              cline_of (functions.x [i].ends));
  529     }
  530 }
  531 /*****************************************************************************
  532 #
  533 #   Structure member list. This was not included until 1.1
  534 #   It's needed in initializers where we have to assign values
  535 #   to members in their natural order or by designators
  536 #
  537 *****************************************************************************/
  538 void region::add_member (Symbol s)
  539 {
  540     memb_li *m = new memb_li;
  541     m->s = s;
  542     m->next = NULL;
  543     if (!first) {
  544         first = last = m;
  545     } else {
  546         last->next = m;
  547         last = m;
  548     }
  549 }
  550 /*****************************************************************************
  551 #   declaration of new names to the program
  552 #
  553 #   which are: objects (variables and functions), typedefs
  554 #   enumeration tags, enumeration constants and structure tags.
  555 #
  556 #   structure tag can be declared at declaration or at forward
  557 #   declaration (use). Check for recursion (incomplete base type), is
  558 #   done at the sizeof calculation elsewhere.
  559 #
  560 #   the items are semantically correct, and the only error that
  561 #   can happen here is if something is already declared
  562 #   in the same region
  563 *****************************************************************************/
  564 
  565 static Ok function_declaration (Symbol s, typeID t, VARSPC v)
  566 {
  567     lookup_t *L;
  568 
  569     if ((L = Lookup (s, false, 0))) {
  570         if (L->kind < EFUNCTION) return false;
  571         typeID tt = L->info.tdf;
  572         if (!typecmp (t, tt)) return false;
  573         if (L->kind == EFUNCTION && spec_of (tt)[1] == NoArgSpec)
  574             L->info.tdf = t;
  575         return true;
  576     }
  577 
  578 
  579     L = new lookup_t (s, EFUNCTION, 0);
  580     L->info.tdf = t;
  581     L->defspec = v;
  582     return true;
  583 }
  584 
  585 static Ok field_member (Symbol s, typeID t)
  586 {
  587     typeID nt;
  588     int p;
  589 
  590     if (s != -1 && Lookup (s, false, current_region))
  591         return false;
  592     p = regions [current_region].add_field (t, nt);
  593     if (s != -1) {
  594         lookup_t *L = new lookup_t (s, OBJECT, current_region);
  595         L->info.tdf = nt;
  596         L->placement = p;
  597     }
  598     return true;
  599 }
  600 
  601 Ok introduce_obj (Symbol s, typeID t, VARSPC v = DEFAULT)
  602 {
  603     if (ISFUNCTION (types.x [t]))
  604         return function_declaration (s, t, v);
  605 
  606     if (INSTRUCT) regions [current_region].add_member (s);
  607     if (spec_of (t)[0] == ':')
  608         return field_member (s, t);
  609 
  610     lookup_t *L;
  611     if ((L = Lookup (s, false, current_region))) {
  612         if (L->kind != EOBJECT && L->kind != OBJECT) return false;
  613         typeID et = L->info.tdf;
  614         if (!typecmp (t, et)) return false;
  615         //if (current_region == 0) return true;
  616         if (spec_of (et)[0] == '[' && spec_of (et)[1] == 0) {
  617     //if (L->kind == OBJECT) {
  618                 L->info.tdf = t;
  619                 return true;
  620     //}
  621     //L->kind = OBJECT;
  622     //L->placement = regions
  623     // [current_region].add_object (t);
  624     //return true;
  625         }
  626         //if (L->kind == OBJECT) return v == EXTERN;
  627         if (v != EXTERN) {
  628             // instantiation
  629             L->kind = OBJECT;
  630             L->info.tdf = t;
  631             L->placement = regions
  632              [current_region].add_object (t);
  633         }
  634         return true;
  635     }
  636 
  637     if (v == EXTERN) {
  638         L = new lookup_t (s, EOBJECT, current_region);
  639         L->info.tdf = t;
  640     } else {
  641         L = new lookup_t (s, OBJECT, current_region);
  642         L->info.tdf = t;
  643         L->placement = regions
  644             [current_region].add_object (t);
  645     }
  646 
  647     return true;
  648 }
  649 
  650 Ok introduce_tdef (Symbol s, typeID t)
  651 {
  652     lookup_t *L = Lookup (s, false, current_region);
  653     if (L) return L->kind == TYPEDEF && typecmp (t, L->info.tdf);
  654     L = new lookup_t (s, TYPEDEF, current_region);
  655     L->info.tdf = t;
  656     return true;
  657 }
  658 
  659 ObjPtr lookup_typedef (Symbol s)
  660 {
  661     lookup_t *t = Lookup_foruse (s, false, current_region);
  662     if ((t) && t->kind == TYPEDEF)
  663         return TYPEDEF_BASE + t->info.tdf;
  664     RegionPtr r = current_region;
  665     do {
  666         r = regions [r].parent;
  667         t = Lookup_foruse (s, false, r);
  668         if ((t) && t->kind == TYPEDEF)
  669             return TYPEDEF_BASE + t->info.tdf;
  670     } while (r);
  671     return -1;
  672 }
  673 
  674 Ok is_typedef (Symbol s)
  675 {
  676     lookup_t *t = Lookup_foruse (s, false, current_region);
  677     return (t) && t->kind == TYPEDEF;
  678 }
  679 
  680 Ok introduce_enumconst (Symbol s, int value)
  681 {
  682     RegionPtr r = current_region;
  683     while (ISRECORD (regions [r].kind)) r = regions [r].parent;
  684     if (Lookup (s, false, r)) return false;
  685     lookup_t *L = new lookup_t (s, ENUMCONST, r);
  686     L->info.eval = value;
  687     return true;
  688 }
  689 
  690 Ok introduce_enumtag (Symbol s, bool fwd)
  691 {
  692     lookup_t *L = Lookup (s, true, current_region);
  693     if (L)
  694         if (!L->info.fwd)
  695             return false;
  696         else L->info.fwd = fwd;
  697     else {
  698         L = new lookup_t (s, ENUMTAG, current_region);
  699         L->info.fwd = fwd;
  700     }
  701     return true;
  702 }
  703 
  704 Ok valid_enumtag (Symbol s)
  705 {
  706     lookup_t *t = Lookup_foruse (s, true, current_region);
  707     return (t) && t->kind == ENUMTAG;
  708 }
  709 
  710 /******************************************************************************
  711 #   records (struct, union)
  712 #
  713 #   Normally, structure by name is not needed. But in the
  714 #   case of usage report the user wants to know which
  715 #   structure is structure #234
  716 #   Thus the inttree.
  717 ******************************************************************************/
  718 static intTree struct_names;
  719 class sname : public intNode
  720 {
  721    public:
  722     int symbol;
  723     sname (int s) : intNode (&struct_names) { symbol = s; }
  724 };
  725 
  726 Symbol struct_by_name (RegionPtr p)
  727 {
  728     sname *s = (sname*) struct_names.intFind (p);
  729     return !s ? -2 : s->symbol;
  730 }
  731 
  732 bool rename_struct (typeID t, Symbol s)
  733 {
  734     sname *sn = (sname*) struct_names.intFind (base_of (t));
  735     if (sn && sn->symbol == -1)
  736         sn->symbol = s;
  737     return true;
  738 }
  739 
  740 static inline void name_struct (RegionPtr p, Symbol s)
  741 {
  742     if (usage_only) if (!struct_names.intFind (p)) new sname (s);
  743 }
  744 
  745 //#
  746 //# Show structure declaration locations
  747 //#
  748 void structs_of_file ()
  749 {
  750     int i, n = regions.nr ();
  751     int prevfile = -1;
  752     PRINTF ("\n");
  753 
  754     for (i = 0; i < n; i++)
  755         if (regions [i].used && regions [i].dcll) {
  756             if (cfile_of (regions [i].dcls) != prevfile)
  757                 PRINTF ("\nP: %s\n", C_Files [prevfile = 
  758                  cfile_of (regions [i].dcls)].file);
  759             PRINTF ("Y: %s %i %i\n",
  760                  expand (struct_by_name (i)),
  761                  cline_of (regions [i].dcls),
  762                  cline_of (regions [i].dcls + regions [i].dcll));
  763         }
  764 }
  765 //
  766 //
  767 //
  768 
  769 RegionPtr introduce_anon_struct (bool isst)
  770 {
  771     RegionPtr r;
  772     for (r = current_region; ISRECORD (regions [r].kind);
  773         r = regions [r].parent);
  774     r = open_region (new_region (isst ? RECORD_S : RECORD_U, r));
  775     name_struct (r, -1);
  776     return r;
  777 }
  778 
  779 RegionPtr introduce_named_struct (Symbol s, bool isst)
  780 {
  781     RegionPtr r;
  782     lookup_t *L;
  783     for (r = current_region; ISRECORD (regions [r].kind);
  784         r = regions [r].parent);
  785 
  786     L = Lookup_foruse (s, true, r);
  787     if (L) {
  788         if (L->kind == ENUMTAG) return -1;
  789         name_struct (L->info.rp, s);
  790         return open_region (L->info.rp);
  791     }
  792     L = new lookup_t (s, RECORD, r);
  793     L->incomplete = 0;
  794     L->info.rp = open_region (isst ? RECORD_S:RECORD_U, r);
  795     name_struct (L->info.rp, s);
  796     return L->info.rp;
  797 }
  798 
  799 RegionPtr use_struct_tag (Symbol s, bool isst)
  800 {
  801     RegionPtr r;
  802     lookup_t *L;
  803     for (r = current_region; ISRECORD (regions [r].kind);
  804         r = regions [r].parent);
  805     L = Lookup_foruse (s, true, r);
  806     if (L) return (L->kind == ENUMTAG) ? -1 : L->info.rp;
  807     L = new lookup_t (s, RECORD, r);
  808     L->incomplete = 1;
  809     return L->info.rp = new_region (isst ? RECORD_S : RECORD_U, r);
  810 }
  811 
  812 RegionPtr fwd_struct_tag (Symbol s, bool isst)
  813 {
  814     RegionPtr r;
  815     lookup_t *L;
  816     for (r = current_region; ISRECORD (regions [r].kind);
  817         r = regions [r].parent);
  818     L = Lookup (s, true, r);
  819     if (L) return (L->kind == ENUMTAG) ? -1 : L->info.rp;
  820     L = new lookup_t (s, RECORD, r);
  821     L->incomplete = 1;
  822     return L->info.rp = new_region (isst ? RECORD_S : RECORD_U, r);
  823 }
  824 
  825 /*****************************************************************************
  826 #   lookup_object
  827 #
  828 #   this is the kind of lookup needed in expressions.
  829 #   expressions do not need: structure tags, typedefs, etc
  830 #   but only objects or enumeration constants
  831 #
  832 #   for functions there is the additional rule that if a
  833 #   declaration does not exist, it is implictly declared as
  834 #   extern int f ();
  835 #
  836 #   for structure members it is the same but the lookup is
  837 #   restricted only inside the scope and it does not do it's best
  838 #   to find a matching declaration
  839 #
  840 #   have_function is like lookup_function except the function
  841 #   is not declared if it doesn't exist
  842 *****************************************************************************/
  843 lookup_object::lookup_object (Symbol s, bool f2ptr)
  844 {
  845     lookup_t *L;
  846 
  847     if (!(L = Lookup_foruse (s, false, current_region)))
  848         half_error ("Undefined object", expand (s));
  849 
  850     if ((enumconst = L->kind == ENUMCONST)) {
  851         ec = L->info.eval;
  852         return;
  853     }
  854 
  855     typeID t = L->info.tdf;
  856     base = types.x [t].base;
  857     if (L->kind == OBJECT) {
  858         FRAME = L->cp;
  859         displacement = L->placement;
  860         intcpy (spec, spec_of (t));
  861     } else if (L->kind == EOBJECT) {
  862         FRAME = -1;
  863         displacement = 0;
  864         intcpy (spec, spec_of (t));
  865     } else if (L->kind == IFUNCTION || L->kind == EFUNCTION) {
  866         FRAME = -1;
  867         displacement = L->placement;
  868         if (f2ptr) {
  869             spec [0] = '*';
  870             intcpy (spec + 1, spec_of (t));
  871         } else
  872             intcpy (spec, spec_of (t));
  873     } else half_error ("Undefined object", expand (s));
  874 }
  875 
  876 lookup_function::lookup_function (Symbol s, bool fatalerror)
  877 {
  878     lookup_t *L;
  879 
  880     found = true;
  881     ARGFUNC = fptr = false;
  882     if (!(L = Lookup_foruse (s, false, current_region))) {
  883         type t;
  884         spec [0] = '(', spec [1] = NoArgSpec, spec [2] = -1;
  885         base = t.base = S_INT;
  886         t.spec = spec;
  887         introduce_obj (s, gettype (t), EXTERN);
  888         FRAME = -1;
  889         displacement = 0;
  890     } else if (L->kind == EFUNCTION) {
  891         FRAME = -1;
  892         displacement = 0;
  893         typeID t = L->info.tdf;
  894         base = base_of (t);
  895         intcpy (spec, spec_of (t));
  896     } else if (L->kind == IFUNCTION) {
  897         FRAME = -1;
  898         displacement = L->placement;
  899         typeID t = L->info.tdf;
  900         base = base_of (t);
  901         intcpy (spec, spec_of (t));
  902     } else if (L->kind == EOBJECT || L->kind == OBJECT) {
  903         typeID t = L->info.tdf;
  904         if (!(types.x [t].spec [0] == '*'
  905         &&  types.x [t].spec [1] == '('))
  906             if (fatalerror)
  907                 half_error ("Not a pointer to function", expand (s));
  908             else
  909                 intcpy (spec, spec_of (t));
  910         else
  911             intcpy (spec, spec_of (t) + 1);
  912         base = base_of (t);
  913         FRAME = L->cp;
  914         ARGFUNC = FRAME && !regions [FRAME].parent;
  915         displacement = L->placement;
  916         fptr = true;
  917     } else if (fatalerror)
  918         half_error ("Not a function", expand (s));
  919     else    found = false;
  920 }
  921 
  922 lookup_member::lookup_member (Symbol s, RegionPtr r)
  923 {
  924     lookup_t *L = Lookup (s, false, r);
  925 
  926     if (!L) half_error ("Undefined member", expand (s));
  927 
  928     displacement = L->placement;
  929     typeID t = L->info.tdf;
  930     base = base_of (t);
  931     intcpy (spec, spec_of (t));
  932 }
  933 
  934 void spill_anonymous (RegionPtr r)
  935 {
  936     memb_li *m;
  937     for (m = regions [r].first; m; m=m->next) {
  938         lookup_t *L = Lookup (m->s, false, r);
  939         if (L->kind == OBJECT)
  940             introduce_obj (m->s, L->info.tdf);
  941     }
  942 }
  943 
  944 bool have_function (Symbol s)
  945 {
  946     lookup_t *L = Lookup_foruse (s, false, current_region);
  947     return L && (L->kind == EFUNCTION || L->kind == IFUNCTION);
  948 }
  949 /*****************************************************************************
  950 #   sizeof
  951 #
  952 #   - esizeof_objptr (), is used for the case the sizeof the
  953 #   base declarator is needed to compute the size of an incomplete
  954 #   type from initializer. For example:
  955 #
  956 #       typedef struct { int x, y } foo;
  957 #       foo bar [] = { 1, 2, 3, 4, 5, 6 };
  958 #   were bar is array [3] of struct foo.
  959 #
  960 #   - sizeof_typeID (), is used by sizeof (typename)
  961 #
  962 #   - the function ptr_incremenet () take as an argument a type
  963 #   which MUST be a pointer to something, and return how
  964 #   much will the ++ operator on the pointer increase it.
  965 ******************************************************************************/
  966 static bool just_count;
  967 
  968 static const int sizez [] = {
  969     sizeof (char), sizeof (char), sizeof (short int), sizeof (short int),
  970     sizeof (int), sizeof (int), sizeof (long int), sizeof (long int),
  971     sizeof (long long), sizeof (long long), sizeof (float),
  972     sizeof (double), 0
  973 };
  974 
  975 static inline int sizeof_btype (BASETYPE b)
  976 {
  977     return (just_count) ? 1 : sizez [b - S_CHAR];
  978 }
  979 
  980 static inline int sizeof_ptr ()
  981 {
  982     return (just_count) ? 1 : sizeof (void*);
  983 }
  984 
  985 static int sizeof_struct (RegionPtr p)
  986 {
  987     if (regions [p].incomplete)
  988         syntax_error (ExpressionPtr, "incomplete structure");
  989     return (just_count) ? regions [p].nn : regions [p].aligned_top;
  990 }
  991 
  992 static int sizeof_type (type &t)
  993 {
  994     int i, na = 1, st, *spec = t.spec;
  995 
  996     if (spec [0] == '(') return 0;
  997 
  998     for (i = 0; spec [i] == '['; i += 2)
  999         na *= spec [i + 1];
 1000 
 1001     //if (!na) half_error ("sizeof Incomplete type attempted");
 1002 
 1003     st = (spec [i] == '*') ? sizeof_ptr ()
 1004         : (T_BASETYPE (t)) ? sizeof_btype ((BASETYPE) t.base)
 1005         : sizeof_struct (t.base);
 1006 
 1007     return na * st;
 1008 }
 1009 
 1010 int sizeof_typeID (typeID ti)
 1011 {
 1012     type t = types.x [ti];
 1013     return sizeof_type (t);
 1014 }
 1015 // *************************************************
 1016 
 1017 int esizeof_objptr (ObjPtr o)
 1018 {
 1019     if (o < _BTLIMIT) return 1;
 1020 
 1021     just_count = true;
 1022     int r = (o < TYPEDEF_BASE) ? sizeof_struct (o) :
 1023         sizeof_typeID (o - TYPEDEF_BASE);
 1024     just_count = false;
 1025     return r;
 1026 }
 1027 
 1028 int sizeof_type (int base, Vspec spec)
 1029 {
 1030     type t;
 1031     t.base = base;
 1032     t.spec = spec;
 1033     return sizeof_type (t);
 1034 }
 1035 
 1036 int ptr_increment (int b, Vspec spec)
 1037 {
 1038     type t;
 1039     int tspec [50];
 1040 
 1041     if (spec [0] == -1)
 1042         half_error ("invalid pointer arithmetic");
 1043 
 1044     t.base = b;
 1045     intcpy (tspec, spec [0] == '*' ? spec + 1: spec + 2);
 1046     t.spec = tspec;
 1047 
 1048     return sizeof_type (t);
 1049 }
 1050 
 1051 /*****************************************************************************
 1052 #
 1053 #   initialization of various things
 1054 #
 1055 *****************************************************************************/
 1056 void init_cdb ()
 1057 {
 1058     lookup_table = new lookup_t* [C_Nsyms];
 1059     for (int i = 0; i < C_Nsyms; i++)
 1060         lookup_table [i] = NULL;
 1061 
 1062     // global, region 0, parent of self, etc
 1063     open_region (GLOBAL, 0);
 1064     INGLOBAL = true;
 1065 
 1066     // Void type
 1067     int x [1];
 1068     x [0] = -1;
 1069     type t = { VOID, &x[0] };
 1070     VoidType = newtype (t);
 1071     t.base = S_INT;
 1072     SIntType = newtype (t);
 1073 
 1074     // argument list with no arguments --old style
 1075     typeID ta [2];
 1076     ta [0] = ARGLIST_OPEN; ta [1] = -1;
 1077     NoArgSpec = make_arglist (ta);
 1078     ta [0] = SIntType;
 1079     ArglPtr sizet_arg = make_arglist (ta);
 1080 
 1081 #define DEFBUILTIN(B, S1, S2, S3, S4, T) \
 1082     if (ccbuiltins.bt ## B!= -1) {\
 1083         int s [] = { S1, S2, S3, S4 }; type t;\
 1084         t.base = T; t.spec = s;\
 1085         introduce_obj (ccbuiltins.bt ## B, gettype (t), STATIC);\
 1086     }
 1087 
 1088     DEFBUILTIN(__FUNCTION__, '*', -1, -1, -1, S_CHAR)
 1089     DEFBUILTIN(__func__, '*', -1, -1, -1, S_CHAR)
 1090     DEFBUILTIN(__PRETTY_FUNCTION__, '*', -1, -1, -1, S_CHAR)
 1091     DEFBUILTIN(__builtin_return_address, '(', NoArgSpec, '*', -1, VOID)
 1092     DEFBUILTIN(__builtin_alloca, '(', sizet_arg, '*', -1, VOID)
 1093 }
 1094 
 1095 //
 1096 // this routine here, shows what is included in the lookup table ---
 1097 // useful for debugging cdb
 1098 //
 1099 
 1100 void show_lookups ()
 1101 {
 1102     lookup_t *L;
 1103     int i;
 1104 
 1105     for (i = 0; i < C_Nsyms; i++) {
 1106         PRINTF ("* * * * * Symbol [%s]\n", C_Syms [i]);
 1107         for (L = lookup_table [i]; L; L = L->next) {
 1108         PRINTF ("- Inside %i: ", L->cp);
 1109         switch (L->kind) {
 1110         case RECORD:
 1111             PRINTF ("Record no %i\n", L->info.rp);
 1112             break;
 1113         case ENUMTAG:
 1114             PRINTF ("Enumeration tag\n");
 1115             break;
 1116         case TYPEDEF:
 1117             PRINTF ("typedef\n");
 1118             printtype (L->info.tdf);
 1119             break;
 1120         case OBJECT:
 1121         case EOBJECT:
 1122             PRINTF ("variable %i\n", L->placement);
 1123             printtype (L->info.tdf);
 1124             break;
 1125         case ENUMCONST:
 1126             PRINTF ("enumeration constant %i\n", L->info.eval);
 1127             break;
 1128         case EFUNCTION:
 1129         case IFUNCTION:
 1130             PRINTF ("function %i\n", L->placement);
 1131             printtype (L->info.tdf);
 1132             break;
 1133         default:;
 1134         } }
 1135     }
 1136 }
 1137 
 1138 /**************************************************************************
 1139 #   expand the fields of an aggregate type for initializer
 1140 #
 1141 #   The reason for the complexity of the code below, is the Standard
 1142 #       P = { .x.y { 2, [1].e.[1] { 32 }, 27 }, };
 1143 #   is a valid initializer. But where shall '27' be assigned?
 1144 #
 1145 #   ISOC99 sais:
 1146 #   ``30. Note that the fully bracketed and minimally bracketed
 1147 #     form of initalization are, in general, less likely to cause
 1148 #     confusion''
 1149 #   which is translated to :
 1150 #   ``Don't do initializations like P because we are not sure
 1151 #     if your compiler can implement this correctly''
 1152 #
 1153 #   Hopefully this works
 1154 ***************************************************************************/
 1155 
 1156 class aeqn {
 1157     Symbol txt [1024];
 1158     int txti;
 1159     void prstruct (RegionPtr);
 1160     void prarr (int,int*);
 1161    public:
 1162     aeqn (Symbol);
 1163     Symbol *dclstr;
 1164 };
 1165 
 1166 #define UNI '/'
 1167 
 1168 void aeqn::prstruct (RegionPtr p)
 1169 {
 1170     int base, *spec;
 1171     lookup_t *L;
 1172     memb_li *m;
 1173 
 1174     if (regions [p].kind == RECORD_U)
 1175         txt [txti++] = UNI;
 1176     for (m = regions [p].first; m; m=m->next) {
 1177         L = Lookup (m->s, false, p);
 1178         txt [txti++] = m->s;
 1179         base = base_of (L->info.tdf);
 1180         spec = spec_of (L->info.tdf);
 1181         txt [txti++] = '{';
 1182         if (spec [0] == '[')
 1183             prarr (base, spec);
 1184         else if (spec [0] == -1 && base > _BTLIMIT)
 1185             prstruct (base);
 1186         else txt [txti++] = '!';
 1187         txt [txti++] = '}';
 1188     }
 1189 }
 1190 
 1191 void aeqn::prarr (int base, int *spec)
 1192 {
 1193     txt [txti++] = INUMBER + spec[1];
 1194     txt [txti++] = '[';
 1195     if (spec [2] == '[') prarr (base, spec+2);
 1196     else if (spec [2] == -1 && base > _BTLIMIT)
 1197         prstruct (base);
 1198     else txt [txti++] = '!';
 1199     txt [txti++] = ']';
 1200 }
 1201 
 1202 aeqn::aeqn (Symbol s)
 1203 {
 1204     lookup_t *L = Lookup (s, false, current_region);
 1205     int base, *spec;
 1206     base = base_of (L->info.tdf);
 1207     spec = spec_of (L->info.tdf);
 1208     txt [0] = s;
 1209     txt [1] = '{';
 1210     txti = 2;
 1211     if (spec [0] == '[') prarr (base, spec);
 1212     else if (spec [0] == -1 && base > _BTLIMIT)
 1213         prstruct (base);
 1214     txt [txti++] = '}';
 1215     txt [txti++] = -1;
 1216     memcpy (dclstr = new int [txti], txt, txti * sizeof (txt [0]));
 1217 }
 1218 
 1219 Symbol *mk_dclstr (Symbol s)
 1220 {
 1221     aeqn A (s);
 1222     if (0) {
 1223         int i;
 1224         PRINTF ("[XYZZY]: ");
 1225         for (i = 0; A.dclstr [i] != -1; i++)
 1226             PRINTF ("%s", expand (A.dclstr[i]));
 1227         PRINTF ("\t\t(txtlen=%i,i=%s)\n", i,expand(s));
 1228     }
 1229     return A.dclstr;
 1230 }
 1231 
 1232 dcle::dcle (Symbol s)
 1233 {
 1234     dclstr = mk_dclstr (s);
 1235     p = 0;
 1236     ni = -1;
 1237 }
 1238 
 1239 dcle::~dcle ()
 1240 {
 1241     delete [] dclstr;
 1242 }
 1243 
 1244 #define PRFUN(x) \
 1245 //printf("Entering "#x"\t at %i [%s]",p,expand(dclstr[p]));printf(" [%s]",expand(dclstr[p+1]));printf(" [%s]\n",expand(dclstr[p+2]));
 1246 
 1247 
 1248 NormPtr dcle::skipbracket (NormPtr p)
 1249 {
 1250 PRFUN(skipbracket)
 1251     // ts is '[' or '{'
 1252     Symbol ts = dclstr [p++];
 1253     Symbol tc = ts == '[' ? ']' : '}';
 1254     int c;
 1255     for (c = 1; c; p++)
 1256         if (dclstr [p] == ts) c++;
 1257         else if (dclstr [p] == tc) c--;
 1258     return p;
 1259 }
 1260 
 1261 void dcle::openarray ()
 1262 {
 1263 PRFUN(openarray)
 1264     nests [++ni].max = dclstr [p++] - INUMBER;
 1265     nests [ni].c = 0;
 1266     nests [ni].p = p++;
 1267     nests [ni].marked = false;
 1268 }
 1269 
 1270 void dcle::openstruct ()
 1271 {
 1272 PRFUN(openstruct)
 1273     nests [++ni].s = dclstr [p++];
 1274     nests [ni].p = p++;
 1275     nests [ni].max = -1;
 1276     nests [ni].marked = false;
 1277 }
 1278 
 1279 bool dcle::opennest ()
 1280 {
 1281 PRFUN(opennest)
 1282     // nested types open with '2[' or 'x{'
 1283     // for arrays and structures
 1284     if (dclstr [p] >= INUMBER) openarray ();
 1285     else if (ISSYMBOL (dclstr [p])) openstruct ();
 1286     else if (dclstr [p] == '[') p++;
 1287     else return false;
 1288     if (dclstr [p] == UNI) p++;
 1289     return true;
 1290 }
 1291 
 1292 bool dcle::open_bracket ()
 1293 {
 1294 PRFUN(open_bracket)
 1295     // marks the nested type
 1296     if (!opennest ()) return false;
 1297     nests [ni].marked = true;
 1298     return true;
 1299 }
 1300 
 1301 bool dcle::close_bracket ()
 1302 {
 1303 PRFUN(close_bracket)
 1304 
 1305     // takes you at the closing bracket of the
 1306     // topmost marked nested type
 1307     while (ni >= 0 && !nests [ni].marked)
 1308         ni--;
 1309     if (ni <= 0) return
 1310         false;
 1311     nests [ni].marked = false;
 1312     p = skipbracket (nests [ni].p) - 1;
 1313     return true;
 1314 }
 1315 
 1316 bool dcle::closenest ()
 1317 {
 1318 PRFUN(closenest)
 1319     // closes a nested type and takes you after it
 1320     // or recycle in the case of array
 1321     if (dclstr [p] == '}') {
 1322         if (nests [ni].marked)
 1323             return false;
 1324         ni--;
 1325         p++;
 1326         return true;
 1327     }
 1328     if (nests [ni].marked) return
 1329         false;
 1330     if (++nests [ni].c < nests [ni].max || nests [ni].max == 0) {
 1331        /*   direct-declarator [] without constant-expression is assumed to accept any number
 1332             of initializers in initializer-list.
 1333 
 1334             Ben Lau <benlau@linux.org.hk> */
 1335 
 1336         p = nests [ni].p;
 1337         return true;
 1338     }
 1339     ni--;
 1340     p++;
 1341     return true;
 1342 }
 1343 
 1344 bool dcle::comma ()
 1345 {
 1346 PRFUN(comma)
 1347     // takes you to the next point of interest
 1348     if (dclstr [p] == '!') p++;
 1349 again:
 1350     while (dclstr [p] == '}' || dclstr [p] == ']')
 1351         if (!closenest ()) return true;
 1352     if (dclstr [nests [ni].p + 1] == UNI && dclstr [p] != '[') {
 1353         int po = p = skipbracket (nests [ni].p) - 1;
 1354         if (closenest () && po < p)
 1355             goto again;
 1356     }
 1357     return true;
 1358 }
 1359 
 1360 bool dcle::tofield ()
 1361 {
 1362 PRFUN(tofield)
 1363     // takes you to the next '!'
 1364     int dp;
 1365     while ((dp = dclstr [p]) != '!')
 1366         if (opennest ()) continue;
 1367         else if (dp == ']' || dp == '}') {
 1368             if (!closenest ()) return
 1369                 false;
 1370         } else return false;
 1371     return true;
 1372 }
 1373 
 1374 bool dcle::designator (Symbol D[])
 1375 {
 1376 PRFUN(designator)
 1377     // takes you where the designator points
 1378     int i;
 1379     while (ni >= 0 && !nests [ni].marked)
 1380         ni--;
 1381     if (dclstr [p = nests [ni].p + 1] == UNI) p++;
 1382     for (i = 0; D [i] != -1; i++)
 1383         if (ISSYMBOL (D [i])) {
 1384             while (ISSYMBOL (dclstr [p]) && dclstr [p] != D [i])
 1385                 p = skipbracket (p + 1);
 1386             if (dclstr [p] != D [i]) return
 1387                 false;
 1388             if (D [i+1] != -1) opennest ();
 1389         } else {
 1390             if (nests [ni].max != -1) {
 1391                 if (D [i] < INUMBER) D [i] = nests [ni].max;//hack
 1392                 nests [ni].c = D [i] - INUMBER;
 1393                 if (dclstr [p = nests [ni].p + 1] == UNI)
 1394                     p++;
 1395             } else {
 1396                 if (!opennest ()) return false;
 1397                 if (D [i] < INUMBER) D [i] = nests [ni].max;//hack
 1398                 nests [ni].c = D [i] - INUMBER;
 1399                 if (D [i+1] == -1)
 1400                     if (dclstr [--p] == UNI) p--;
 1401                 // br0ken standard *&#@*#@&^%&
 1402             }
 1403         }
 1404     return true;
 1405 }
 1406 
 1407 bool dcle::tostruct (RegionPtr)
 1408 {
 1409 PRFUN(tostruct)
 1410     // this is done the lazy way
 1411     //  struct { struct { struct { int a, b; } S1; } S2; }
 1412     //  S3 = { ((struct S1) {1,2}) };
 1413     // is not supported and ?maybe? rightly so
 1414     if (!ISSYMBOL (dclstr [p])) return false;
 1415     opennest ();
 1416     p = skipbracket (nests [ni].p) - 1;
 1417     return true;
 1418 }
 1419 
 1420 Symbol *dcle::mk_current ()
 1421 {
 1422 PRFUN(mk_current)
 1423     // create the current field as a postfix expression
 1424     int i, p;
 1425     for (i = 0, p = 0; i <= ni; i++)
 1426         if (nests [i].max != -1) {
 1427             pexpr [p++] = '[';
 1428             pexpr [p++] = INUMBER + nests [i].c;
 1429             pexpr [p++] = ']';
 1430         } else {
 1431             pexpr [p++] = '.';
 1432             pexpr [p++] = nests [i].s;
 1433         }
 1434     pexpr [p++] = ';';
 1435     pexpr [p] = -1;
 1436     return &pexpr [1];
 1437 }
 1438 
 1439 void dcle::printexpr ()
 1440 {
 1441     // debug routine
 1442     int i;
 1443     PRINTF ("XYZZY: ");
 1444     for (i=0;pexpr[i]!=-1;i++)
 1445         PRINTF ("%s", expand (pexpr [i]));
 1446     PRINTF ("\t\t%i\n", i);
 1447 }
 1448 /*****************************************************************************
 1449 
 1450 *****************************************************************************/
 1451 
 1452 void showdb ()
 1453 {
 1454 //show_lookups ();
 1455 PRINTF ("#%i types\n", types.nr);
 1456 PRINTF ("#%i arglists\n", arglists.nr);
 1457 PRINTF ("#%i regions\n", regions.nr ());
 1458 PRINTF ("#%i function definitions\n", functions.nr);
 1459 
 1460 }
 1461 
 1462 //****************************************************************************
 1463 //  debugging routine, print a type
 1464 //****************************************************************************
 1465 
 1466 #define U "unsigned "
 1467 #define S "short "
 1468 #define L "long "
 1469 #define I "int"
 1470 #define C "char"
 1471 
 1472 static const char *btn [] = {
 1473     // some ppl are lazy
 1474     C, U C, S I, U S I, I, U I, L I,
 1475     U L I, L L, U L L, "float", "double", "void"
 1476 };
 1477 
 1478 void printtype (int base, int *spec)
 1479 {
 1480 #define STDE stderr
 1481     int i;
 1482     if (base < -32) fprintf (STDE, "blitfield\n");
 1483     else if (base < _BTLIMIT) fprintf (STDE, "%s ", btn [base - S_CHAR]);
 1484     else fprintf (STDE, "record #%i ", base);
 1485     for (i = 0; spec [i] != -1; i++)
 1486         if (spec [i] == '*') fprintf (STDE, "*");
 1487         else if (spec [i] == '[')
 1488             fprintf (STDE, "[%i]", spec [++i]);
 1489         else if (spec [i] == '(')
 1490             fprintf (STDE, "(%i)", spec [++i]);
 1491         else if (spec [i] == ':')
 1492             fprintf (STDE, ":%i", spec [++i]);
 1493         else { printf ("fuck %i", spec [i]); break; }
 1494     fprintf (STDE, "\n");
 1495 }
 1496 
 1497 void printtype (typeID ti)
 1498 {
 1499     type t = types.x [ti];
 1500     printtype (t.base, t.spec);
 1501 }