Annotation of researchv10no/cmd/cfront/xptcfront/cfront.cpio, revision 1.1.1.1

1.1       root        1: 0707071010112043441004440001630000160000010075200466055374000001000000013411alloc.c/*ident    "@(#)ctrans:src/alloc.c 1.4" */
                      2: /**************************************************************************
                      3: 
                      4:         C++ source for cfront, the C++ compiler front-end
                      5:         written in the computer science research center of Bell Labs
                      6: 
                      7:         Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                      8:         THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                      9: 
                     10: alloc.c:
                     11: 
                     12: *****************************************************************************/
                     13: #include "cfront.h"
                     14: #include "size.h"
                     15: #include "sysent.h"
                     16: 
                     17: const int NBITE = (CHUNK-8)/sizeof(name)-1;
                     18: const int EBITE = (CHUNK-8)/sizeof(expr)-1;
                     19: const int SBITE = (CHUNK-8)/sizeof(stmt)-1;
                     20: const int TBITE = (CHUNK-8)/sizeof(table)-1;
                     21: const int VBITE = (CHUNK-8)/sizeof(vec)-1;
                     22: const int FBITE = (CHUNK-8)/sizeof(fct)-1;
                     23: const int PBITE = (CHUNK-8)/sizeof(ptr)-1;
                     24: 
                     25: #define  mzero(p,l)  memset(p,0,l)
                     26: 
                     27: void* chunk(int i)     // get memory that is not to be freed
                     28: {
                     29:        register char* cp = malloc(i*CHUNK-8);
                     30:        if (cp == 0) {                  // no space
                     31:                free((char*)gtbl);      // get space for error message
                     32:                error('i',"free store exhausted");
                     33:        }
                     34:        return cp;
                     35: }
                     36: 
                     37: #ifdef __HAVE_SIZE_T
                     38: #include <new.h>
                     39: #define NEW_SIZE size_t
                     40: #else
                     41: #define NEW_SIZE long
                     42: #endif
                     43: 
                     44: void* operator new(NEW_SIZE sz)        // get memory that might be freed
                     45: {
                     46:        char* p = calloc((unsigned)sz,1);
                     47: 
                     48: //fprintf(stderr,"alloc(%d)->%d\n",sz,p);
                     49: 
                     50:        if (p == 0) {                   // no space
                     51:                free((char*)gtbl);      // get space for error message
                     52:                error('i',"free store exhausted");
                     53:        }
                     54:        return p;
                     55: }
                     56: 
                     57: void operator delete (void* p)
                     58: {
                     59:        if (p == 0) return;
                     60: 
                     61: //fprintf(stderr,"free(%d) %d\n",p,((int*)p)[-1]-(int)p-1+sizeof(int*));
                     62: 
                     63:        free((char*)p);
                     64: }
                     65: 
                     66: // class new and delete operators
                     67: 
                     68: void*
                     69: expr::operator new(size_t sz)
                     70: {
                     71:        register Pexpr p;
                     72: 
                     73:         if ( (p=expr_free) == 0 ) {
                     74:                 register Pexpr q = (Pexpr) chunk(1);
                     75:                 for (p=expr_free=&q[EBITE-1]; q<p; p--) {
                     76:                         p->e1 = p-1;
                     77:                         DB(p->node::allocated=0);
                     78:                }
                     79:                (p+1)->e1 = 0;
                     80:                DB(p->node::allocated=0);
                     81:        }
                     82:        else
                     83:                expr_free = p->e1;
                     84: 
                     85:        mzero(p,sz);
                     86:        return p;
                     87: }
                     88: 
                     89: void
                     90: expr::operator delete(void* vp, size_t)
                     91: {
                     92:        Pexpr p = (Pexpr)vp;
                     93: 
                     94:        DB( if(!p->node::allocated) error('i',"deleting unallocated expr:%k! -- id==%d",p->base,p->node::id);
                     95:            p->node::allocated = 0;
                     96:        );
                     97:        p->e1 = expr_free;
                     98:        expr_free = p;
                     99:        vp = 0;
                    100: }
                    101: 
                    102: void*
                    103: stmt::operator new(size_t sz)
                    104: {
                    105:        register Pstmt p;
                    106:        if ( (p=stmt_free) == 0 ) {
                    107:                register Pstmt q = (Pstmt) chunk(1);
                    108:                for (p=stmt_free=&q[SBITE-1]; q<p; p--) {
                    109:                        p->s_list = p-1;
                    110:                        DB(p->node::allocated=0);
                    111:                }
                    112:                (p+1)->s_list = 0;
                    113:                DB(p->node::allocated=0);
                    114:        }
                    115:        else
                    116:                stmt_free = p->s_list;
                    117: 
                    118:        mzero(p,sz);
                    119:        return p;
                    120: }
                    121: 
                    122: void
                    123: stmt::operator delete(void* vp,size_t)
                    124: {
                    125:        Pstmt p = (Pstmt)vp;
                    126:        DB( if(!p->node::allocated) error('i',"deleting unallocated stmt:%k! -- id==%d",p->base,p->node::id);
                    127:            p->node::allocated = 0;
                    128:        );
                    129:        p->s_list = stmt_free;
                    130:        stmt_free = p;
                    131:        vp = 0;
                    132: }
                    133: 
                    134: void*
                    135: name::operator new(size_t sz)
                    136: {
                    137:        register Pname p;
                    138: 
                    139:        if ( (p=name_free) == 0 ) {
                    140:                register Pname q = (Pname) chunk(1);
                    141:                for (p=name_free=&q[NBITE-1]; q<p; p--) {
                    142:                        p->n_tbl_list = p-1;
                    143:                        DB(p->node::allocated=0);
                    144:                }
                    145:                (p+1)->n_tbl_list = 0;
                    146:                DB(p->node::allocated=0);
                    147:        }
                    148:        else
                    149:                name_free = p->n_tbl_list;
                    150: 
                    151:        mzero(p,sz);
                    152:        return p;
                    153: }
                    154: 
                    155: void
                    156: name::operator delete(void* vp,size_t)
                    157: {
                    158:        Pname p = (Pname)vp;
                    159:        DB( if(!p->node::allocated) error('i',"deleting unallocated name %s! -- id==%d",p->string?p->string:"???",p->node::id);
                    160:            p->node::allocated = 0;
                    161:        );
                    162:        p->n_tbl_list = name_free;
                    163:        name_free = p;
                    164:        vp = 0;
                    165: }
                    166: 
                    167: void*
                    168: table::operator new(size_t sz)
                    169: {
                    170:        register Ptable p;
                    171: 
                    172:        if ( (p=table_free) == 0 ) {
                    173:                register Ptable q = (Ptable) chunk(1);
                    174:                for (p=table_free=&q[TBITE-1]; q<p; p--) {
                    175:                        p->next = p-1;
                    176:                        DB(p->node::allocated=0);
                    177:                }
                    178:                (p+1)->next = 0;
                    179:                DB(p->node::allocated=0);
                    180:        }
                    181:        else
                    182:                table_free = p->next;
                    183: 
                    184:        mzero(p, sz);
                    185:        return p;
                    186: }
                    187: 
                    188: void
                    189: table::operator delete(void* vp,size_t)
                    190: {
                    191:        Ptable p = (Ptable)vp;
                    192:        DB( if(!p->node::allocated) error('i',"deleting unallocated table %d! -- id==%d",p->base,p->node::id);
                    193:            p->node::allocated = 0;
                    194:        );
                    195:        p->next = table_free;
                    196:        table_free = p;
                    197:        vp = 0;
                    198: }
                    199: 
                    200: void*
                    201: vec::operator new(size_t sz)
                    202: {
                    203:        register Pvec p;
                    204: 
                    205:        if ( (p=vec_free) == 0 ) {
                    206:                register Pvec q = (Pvec) chunk(1);
                    207:                for (p=vec_free=&q[VBITE-1]; q<p; p--) {
                    208:                        p->tlist = p-1;
                    209:                        DB(p->node::allocated=0);
                    210:                }
                    211:                (p+1)->tlist = 0;
                    212:                DB(p->node::allocated=0);
                    213:        }
                    214:        else
                    215:                vec_free = (Pvec) p->tlist;
                    216: 
                    217:        mzero(p, sz);
                    218:        return p;
                    219: }
                    220: 
                    221: void
                    222: vec::operator delete(void* vp,size_t)
                    223: {
                    224:        Pvec p = (Pvec)vp;
                    225:        DB( if(!p->node::allocated) error('i',"deleting unallocated vec %d! -- id==%d",p->base,p->node::id);
                    226:            p->node::allocated = 0;
                    227:        );
                    228:        p->tlist = vec_free;
                    229:        vec_free = p;
                    230:        vp = 0;
                    231: }
                    232: 
                    233: void*
                    234: fct::operator new(size_t sz)
                    235: {
                    236:        register Pfct p;
                    237: 
                    238:        if ( (p=fct_free) == 0 ) {
                    239:                register Pfct q = (Pfct) chunk(1);
                    240:                for (p=fct_free=&q[FBITE-1]; q<p; p--) {
                    241:                        p->tlist = p-1;
                    242:                        DB(p->node::allocated=0);
                    243:                }
                    244:                (p+1)->tlist = 0;
                    245:                DB(p->node::allocated=0);
                    246:        }
                    247:        else
                    248:                fct_free = (Pfct) p->tlist;
                    249: 
                    250:        mzero(p, sz);
                    251:        return p;
                    252: }
                    253: 
                    254: void
                    255: fct::operator delete(void* vp,size_t)
                    256: {
                    257:        Pfct p = (Pfct)vp;
                    258:        DB( if(!p->node::allocated) error('i',"deleting unallocated fct %d! -- id==%d",p->base,p->node::id);
                    259:            p->node::allocated = 0;
                    260:        );
                    261:        p->tlist = fct_free;
                    262:        fct_free = p;
                    263:        vp = 0;
                    264: }
                    265: 
                    266: void*
                    267: ptr::operator new(size_t sz)
                    268: {
                    269:        register Pptr p;
                    270: 
                    271: //error('d',"ptr new");
                    272:        if ( (p=ptr_free) == 0 ) {
                    273:                register Pptr q = (Pptr) chunk(1);
                    274:                for (p=ptr_free=&q[PBITE-1]; q<p; p--) {
                    275:                        p->tlist = p-1;
                    276:                        DB(p->node::allocated=0);
                    277:                }
                    278:                (p+1)->tlist = 0;
                    279:                DB(p->node::allocated=0);
                    280:        }
                    281:        else 
                    282:                ptr_free = (Pptr) p->tlist;
                    283: 
                    284:        mzero(p, sz);
                    285:        return p;
                    286: }
                    287: 
                    288: void
                    289: ptr::operator delete(void* vp,size_t)
                    290: {
                    291:        Pptr p = (Pptr)vp;
                    292:        DB( if(!p->node::allocated) error('i',"deleting unallocated ptr %d! -- id==%d",p->base,p->node::id);
                    293:            p->node::allocated = 0;
                    294:        );
                    295:        p->tlist = ptr_free;
                    296:        ptr_free = p;
                    297:        vp = 0;
                    298: }
                    299: 0707071010112043451004440001630000160000010070500466055374500001100000070343cfront.h/*ident   "@(#)ctrans:src/cfront.h        1.12" */
                    300: /***********************************************************************
                    301: 
                    302:        C++ source for cfront, the C++ compiler front-end
                    303:        written in the computer science research center of Bell Labs
                    304: 
                    305:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                    306:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                    307: 
                    308:        When reading cfront code please remember that C++ was not available
                    309:        when it was originally written. Out of necessity cfront is written
                    310:        in a style that takes advantage of only few of C++'s features.
                    311: 
                    312:        WARNING: This program relies on non-initialized class members being ZERO.
                    313:        This will be true as long as they are allocated using the "new" operator
                    314:        from alloc.c
                    315: 
                    316: cfront.h:
                    317: 
                    318:        Here is all the class definitions for cfront, and most of the externs
                    319: 
                    320: ***********************************************************************/
                    321: 
                    322: #ifndef _CFRONT_H
                    323: #define _CFRONT_H
                    324: 
                    325: #include "token.h"
                    326: #include "typedef.h"
                    327: 
                    328: #ifndef GRAM
                    329: extern char* prog_name;                // compiler name and version
                    330: extern int inline_restr;       // inline expansion restrictions 
                    331: #endif
                    332: 
                    333: extern TOK     tlex();
                    334: extern Pname   syn();
                    335: 
                    336: extern void    ext(int);
                    337: 
                    338: extern char*   make_name(TOK);
                    339: extern void    make_dummy();
                    340: extern Pname   dummy_fct;
                    341: extern Pname    really_dominate(Pname, Pname, bit);
                    342: extern int      exact1(Pname, Ptype);
                    343: 
                    344: extern int friend_check(Pclass start,Pclass stop, Pfct f);
                    345: 
                    346: struct loc             // a source file location
                    347: {
                    348:        short   file;   // index into file_name[], or zero
                    349:        short   line;
                    350: #ifndef GRAM
                    351:        void    put(FILE*);
                    352:        void    putline();
                    353: #endif
                    354: };
                    355: 
                    356: extern Loc curloc;
                    357: extern int curr_file;
                    358: extern char* src_file_name;
                    359: extern loc noloc; // dummy null location
                    360: extern bit binary_val;
                    361: extern bit stmtno;
                    362: 
                    363: struct ea {    // fudge portable printf-like formatting for error()
                    364:        union {
                    365:                void* p;
                    366:                long i;
                    367:        };
                    368: 
                    369:        ea(const void* pp) { p = pp; }
                    370:        ea(long ii)   { i = ii; }
                    371:        ea() {}
                    372: };
                    373: 
                    374: extern ea* ea0;
                    375: 
                    376: overload error;
                    377: int error(const char*);
                    378: int error(const char*, const ea&, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
                    379: int error(int, const char*);
                    380: int error(int, const char*, const ea&, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
                    381: int error(loc*, const char*, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
                    382: int error(int, loc*, const char*, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0);
                    383: extern char emode;
                    384: 
                    385: extern int error_count;
                    386: extern int vtbl_opt;
                    387: extern int debug_opt;
                    388: extern int warning_opt;
                    389: extern int ansi_opt;
                    390: extern int strict_opt;
                    391: extern FILE* out_file;
                    392: extern FILE* in_file;
                    393: extern char scan_started;
                    394: 
                    395: extern int bl_level;
                    396: extern Ptable ktbl;            // keywords and typedef names
                    397: extern Ptable gtbl;            // global names
                    398: extern Ptable ptbl;            
                    399: extern Ptable lcl_tbl;
                    400: extern char* oper_name(TOK);
                    401: extern Pname def_name;
                    402: extern Pname pdef_name;
                    403: extern Pclass ccl;
                    404: extern Pbase defa_type;
                    405: extern Pbase moe_type;
                    406: extern Pbase mptr_type;
                    407: 
                    408: #ifndef GRAM
                    409: extern Pstmt Cstmt;            // current statement, or 0
                    410: extern Pname Cdcl;             // name currently being declared, or 0
                    411: 
                    412: extern Pbase any_type;
                    413: extern int largest_int;
                    414: #endif
                    415: 
                    416: extern Pbase int_type;
                    417: extern Pbase char_type;
                    418: extern Pbase short_type;
                    419: extern Pbase long_type;
                    420: extern Pbase uint_type;
                    421: extern Pbase float_type;
                    422: extern Pbase double_type;
                    423: extern Pbase ldouble_type;
                    424: extern Pbase void_type;
                    425: 
                    426: #ifndef GRAM
                    427: extern Pbase uchar_type;
                    428: extern Pbase ushort_type;
                    429: extern Pbase ulong_type;
                    430: extern Ptype Pchar_type;
                    431: extern Ptype Pint_type;
                    432: extern Ptype Pvptr_type;
                    433: extern Ptype Pfctvec_type;
                    434: extern Ptype Pvoid_type;
                    435: extern Pbase zero_type;
                    436: extern Ptype size_t_type;
                    437: 
                    438: extern int byte_offset;
                    439: extern int bit_offset;
                    440: extern int max_align;
                    441: extern int const_save;
                    442: extern int const_ptr;
                    443: extern int cm_const_save;
                    444: extern bit const_problem;
                    445: #endif
                    446: 
                    447: extern Pexpr dummy;    /* the empty expression */
                    448: extern Pexpr zero;
                    449: extern Pexpr one;
                    450: extern Pname sta_name; /* qualifier for unary :: */
                    451: 
                    452: #define DEL(p) if (p && (p->permanent==0)) p->del()
                    453: #define PERM(p) p->permanent=1
                    454: #define UNPERM(p) p->permanent=0
                    455: 
                    456: struct node {
                    457:        TOK     base;
                    458:        bit     permanent;
                    459:         bit     baseclass; // base classes have NAME in their base ...
                    460: #ifdef DBG
                    461:        bit     displayed;      // avoid infinite recursion in display functions
                    462:        bit     allocated;      // set when not on free list
                    463:        long    id;
                    464: #endif
                    465: };
                    466: #ifdef DBG
                    467: extern long node_id;
                    468: extern int Adebug;
                    469: #define DBID() { node::id = ++::node_id; node::allocated=1; displayed=0; \
                    470:        if(Adebug>=1)fprintf(stderr,"\n*** allocated %d base %d\n",id,base); }
                    471: #else
                    472: #define DBID() /**/
                    473: #endif
                    474: 
                    475: struct table : node {
                    476: /*     a table is a node only to give it a "base" for debugging */
                    477:        bit     init_stat;      /* ==0 if block(s) of table not simplified,
                    478:                                   ==1 if simplified but had no initializers,
                    479:                                   ==2 if simplified and had initializers.
                    480:                                */
                    481:        short   size;
                    482:        short   hashsize;
                    483:        short   free_slot;      /* next free slot in entries */
                    484:        Pname*  entries;
                    485:        short*  hashtbl;
                    486:        Pstmt   real_block;     /* the last block the user wrote,
                    487:                                   not one of the ones cfront created
                    488:                                */
                    489:        Ptable  next;           /* table for enclosing scope */
                    490:        Pname   t_name;         /* name of the table */
                    491: 
                    492:        static Ptable table_free;
                    493:        void* operator new(size_t);
                    494:        void operator delete(void*,size_t);
                    495: 
                    496:        table(short, Ptable, Pname);
                    497:        ~table();
                    498: 
                    499:        Pname   look(char*, TOK);
                    500:        Pname   insert(Pname, TOK);
                    501: #ifndef GRAM
                    502:        void    grow(int);
                    503:        void    set_name(Pname n)       { t_name = n; };
                    504:        Pname   get_mem(int);
                    505:        int     max()                   { return free_slot-1; };
                    506:        void    dcl_print(TOK,TOK);
                    507: #endif
                    508:        void    del();
                    509: };
                    510: 
                    511: #ifndef GRAM
                    512: extern bit Nold;
                    513: extern bit vec_const, fct_const;
                    514: #endif
                    515: 
                    516: extern void restore();
                    517: extern void set_scope(Pname);
                    518: extern Plist modified_tn;
                    519: 
                    520: // local class
                    521: extern Plist local_tn;
                    522: extern Plist local_blk;
                    523: extern Plist local_class;
                    524: extern void local_hide( Pname ); 
                    525: extern char *make_local_name(Pclass, int=0);
                    526: 
                    527: // nested type
                    528: extern Plist nested_tn;
                    529: extern Plist nested_type;
                    530: extern Pname curr_scope; 
                    531: extern Pname curr_fct; 
                    532: extern void nested_hide(Pname); 
                    533: extern int is_empty(Pclass,bit=0);
                    534: 
                    535: extern Pbase start_cl(TOK, Pname, Pbcl);
                    536: extern void end_cl();
                    537: extern Pbase end_enum(Pname, nlist*);
                    538: 
                    539: /************ types : basic types, aggregates, declarators ************/
                    540: 
                    541: #ifndef GRAM
                    542: extern bit new_type;
                    543: extern Pname cl_obj_vec;
                    544: extern Pname eobj;
                    545: #endif
                    546: 
                    547: 
                    548: #define DEFINED 01     /* definition fed through ?::dcl() */
                    549: #define SIMPLIFIED 02  /* in ?::simpl() */
                    550: #define DEF_SEEN 04    /* definition seen, but not processed */
                    551: #define REF_SEEN 010   /* reference seen (classdef) */
                    552:                        /*   used for class members in norm.c */
                    553: #define IN_ERROR 010
                    554: 
                    555: struct type : node {
                    556:        bit     defined;        /* flags DEF_SEEN, DEFINED, SIMPLIFIED, IN_ERROR
                    557:                                        not used systematically yet
                    558:                                */
                    559:        bit     lex_level;
                    560:        Pclass  in_class;       // nested type
                    561:        Pname   in_fct;         // local type
                    562:        char    *lcl;
                    563:        char    *nested_sig;
                    564:        char    *signature(char*);
                    565:        Ptype   tlist;
                    566:        bit     check(Ptype, TOK);
                    567: #ifndef GRAM
                    568:        void    print();
                    569:        void    dcl_print(Pname);
                    570:        void    base_print();
                    571: 
                    572:        Pname   is_cl_obj();    /* sets cl_obj_vec */
                    573:        Pptr    is_ref();
                    574:        Pptr    is_ptr();
                    575:        Pptr    is_ptr_or_ref();
                    576:        bit     is_unsigned();
                    577:        void    dcl(Ptable);
                    578:        int     tsizeof(int = 0);
                    579:        bit     tconst();
                    580:        TOK     set_const(bit);
                    581:        int     align();
                    582:        TOK     kind(TOK,TOK);
                    583:        TOK     integral(TOK oo)        { return kind(oo,'I'); };
                    584:        TOK     numeric(TOK oo)         { return kind(oo,'N'); };
                    585:        TOK     num_ptr(TOK oo)         { return kind(oo,'P'); };
                    586:        bit     vec_type();
                    587:        Ptype   deref();
                    588:        inline Pptr     addrof();
                    589:        Pfct    memptr();
                    590: #endif
                    591:        void    del();
                    592: };
                    593: 
                    594: struct enumdef : type {        /* ENUM */
                    595:        bit     e_body;
                    596:        short   no_of_enumerators;
                    597:        unsigned char strlen;   // strlen(string)
                    598:        char*   string;         // name of enum
                    599:        Pname   mem;
                    600:        Pbase   e_type;         // type representing the enum
                    601:                enumdef(Pname n)        { base=ENUM; mem=n; };
                    602: #ifndef GRAM
                    603:        void    print();
                    604:        void    dcl_print(Pname);
                    605:        void    dcl(Pname, Ptable);
                    606:        void    simpl();
                    607: #endif
                    608: };
                    609: 
                    610: struct velem {
                    611:        Pname   n;
                    612:        int     offset;
                    613: };
                    614: 
                    615: struct virt : node {
                    616:        Pvirt   next;
                    617:        int     n_init;
                    618:        velem*  virt_init;      // vector of vtbl initializers (zero-terminated)
                    619:        Pclass  vclass;         // for class vclass
                    620:        char*   string;
                    621:        bit     is_vbase;       // vtable for virtual base
                    622:        bit     printed;
                    623:        virt(Pclass cl, velem* v, char* s, bit flag, int ni) {base = XVIRT; vclass=cl; virt_init=v; string=s; is_vbase=flag; next=0; n_init = ni;}
                    624: };
                    625: 
                    626: enum { C_VPTR=1, C_XREF=2, C_ASS=4, C_VBASE=8 };
                    627: 
                    628: // An enumeration of the types of classes for Objectstore
                    629: enum class_type_enum { vanilla_class,   // A regular class
                    630:                        template_class,
                    631:                        instantiated_template_class,
                    632:                        uninstantiated_template_class,
                    633:                        relationship_class,
                    634:                        defining_class 
                    635: };
                    636: class type_extension;
                    637: 
                    638: struct classdef : type {       /* CLASS */
                    639:         class_type_enum  class_base; // An extension of "base" to further define
                    640:                                 // the real subtype of the class
                    641:        bit     c_body;         /* print definition only once */
                    642:        TOK     csu;            /* CLASS, STRUCT, UNION, or ANON */
                    643:        bit     obj_align;
                    644:        bit     c_xref;
                    645:                // 1 set:       has vptr(s) 
                    646:                // 2 set:       X(X&) exists
                    647:                // 4 set:       operator=(X&) exists
                    648:                // 8 set:       has vbaseptr(s)
                    649:                
                    650:        bit     virt_count;     // number of virtual functions
                    651:                                // starting at max base class virt_count in
                    652:        bit     virt_merge;     // set when no virtual functions, but
                    653:                                // need to merge virtual base classes
                    654:        bit     c_abstract;     // abstract class: don't instantiate
                    655:        bit     has_vvtab;      // set if class has vtable from virtual base
                    656:        unsigned char strlen;   // strlen(string)
                    657:        Pbcl    baselist;       // list of base classes
                    658:        char*   string;         /* name of class */
                    659:        Pname   mem_list;
                    660:        Ptable  memtbl;
                    661:        int     obj_size;
                    662:        int     real_size;      /* obj_size - alignment waste */
                    663:        Plist   friend_list;
                    664:        Pname   pubdef;
                    665:        Plist   tn_list;        // list of member names hiding type names
                    666:        Plist   nest_list;      // list of nested types
                    667:        Ptype   this_type;
                    668:        Pvirt   virt_list;      // vtbl initializers
                    669:        Pname   c_ctor;         // constuctor:
                    670:                                // possibly overloaded, possibly inherited
                    671:        Pname   c_dtor;         // destructor
                    672:        Pname   c_itor;         /* constructor X(X&) */
                    673:        Pname   conv;           /* operator T() chain */
                    674:        struct toknode *c_funqf, *c_funqr; // token Q for parsing function defs after class def
                    675: 
                    676:        classdef(TOK);
                    677:        ~classdef();
                    678:        TOK     is_simple()     { return (csu==CLASS)?0:csu; };
                    679: #ifndef GRAM
                    680:        void    print();
                    681:        void    dcl_print(Pname);
                    682:        void    simpl();
                    683: 
                    684:        void    print_members();
                    685:        void    dcl(Pname, Ptable);
                    686: 
                    687: //     bit     has_friend(Pname);
                    688:        bit     has_friend(Pclass);
                    689:        bit     has_friend(Pfct);
                    690: 
                    691:        bit     has_base(Pclass cl);
                    692:        bit     baseof(Pname);
                    693:        bit     baseof(Pclass);
                    694:        Pclass  is_base(char*);
                    695: 
                    696:        Pname   has_oper(TOK);
                    697:        Pname   has_ctor()      { return c_ctor; }
                    698:        Pname   has_dtor()      { return c_dtor; }
                    699:        Pname   has_itor()      { return c_itor; }
                    700:        Pname   has_ictor();
                    701:        Pname   make_itor(int);
                    702:        Pexpr   find_name(char*, Pclass, int=0);
                    703:        int     do_virtuals(Pvirt, char*, int, bit);
                    704:        int     all_virt(Pclass, char*, int, bit);
                    705:        void    add_vtbl(velem*, char*, bit, int);
                    706:        void    print_all_vtbls(Pclass);
                    707:        void    print_vtbl(Pvirt);
                    708:        void    really_print(Pvirt);
                    709:        int     check_dup(Pclass, TOK);
                    710:        int     has_allocated_base(Pclass);
                    711:        char    *has_allocated_base(char*);
                    712:        int     get_offset(char*);
                    713:        Pbcl    get_base(char*);
                    714:        Pexpr   get_vptr_exp(char*);
                    715:        Pexpr   find_in_base(char*, Pclass);
                    716:         void    modify_inst_names(char *s); // Adjust ctor names for instantiation
                    717:         bit     parametrized_class();
                    718:         bit    same_class(Pclass p);
                    719: #endif
                    720: };
                    721: 
                    722: #ifndef GRAM
                    723: 
                    724: class clist {
                    725:        Pclass cl;
                    726:        clist* next;
                    727: public:
                    728:        clist(Pclass c, clist* n) { cl=c; next=n; }
                    729:        int onlist(Pclass);
                    730:        void clear();
                    731: };
                    732:        
                    733: extern clist * vcllist;
                    734: 
                    735: struct vl {
                    736:        struct vl* next;
                    737:        Pvirt vt;
                    738:        classdef* cl;
                    739: 
                    740:        vl(classdef* c, Pvirt v, struct vl* n)
                    741:                { cl = c; vt = v; next = n; }
                    742: };
                    743: 
                    744: extern vl* vlist;
                    745: 
                    746: extern int nin;
                    747: extern int Nvis;
                    748: extern int Noffset;
                    749: extern TOK Nvirt;
                    750: extern Pexpr Nptr;
                    751: extern Pbcl Nvbc_alloc;
                    752: extern char *Nalloc_base;
                    753: extern Pexpr rptr(Ptype,Pexpr,int);
                    754: extern Pexpr vbase_args(Pfct, Pname);
                    755: extern Pexpr cdvec(Pname,Pexpr,Pclass,Pname,int,Pexpr,Pexpr=0);
                    756: 
                    757: extern Pexpr find(char*, Pclass, int);
                    758: extern Pexpr find_name(Pname, Pclass, Ptable, int, Pname);
                    759: extern Pname find_virtual(Pclass,Pname);
                    760: extern Pname vfct(Pclass, char*);
                    761: extern int Vcheckerror;
                    762: extern int ignore_const;       
                    763: 
                    764: extern int mex;
                    765: extern Pclass mec;
                    766: extern Pclass tcl;
                    767: #endif
                    768: 
                    769: struct basetype : type
                    770:        /*      ZTYPE CHAR SHORT INT LONG FLOAT DOUBLE
                    771:                FIELD EOBJ COBJ TYPE ANY
                    772:        */
                    773:        /*      used for gathering all the attributes
                    774:                for a list of declarators
                    775: 
                    776:                ZTYPE is the (generic) type of ZERO
                    777:                ANY is the generic type of an undeclared name
                    778:        */
                    779: {
                    780:        bit     b_unsigned;
                    781:        bit     b_signed;
                    782:        bit     b_volatile;
                    783:        bit     b_const;
                    784:        bit     b_typedef;
                    785:        bit     b_inline;
                    786:        bit     b_virtual;
                    787:        bit     b_short;
                    788:        bit     b_long;
                    789:        bit     b_bits;         /* number of bits in field */
                    790:        bit     b_offset;       // bit offset of field
                    791:        TOK     b_sto;          /* AUTO STATIC EXTERN REGISTER 0 */
                    792:        Pname   b_name;         /* name of non-basic type */
                    793:        Ptable  b_table;        /* memtbl for b_name, or 0 */
                    794:        Pname   b_xname;        /* extra name */
                    795:        union {
                    796:        Ptype   b_fieldtype;
                    797:        char*   b_linkage;
                    798:        };
                    799: 
                    800:        basetype(TOK, Pname);
                    801: 
                    802:        Pbase   type_adj(TOK);
                    803:        Pbase   base_adj(Pbase);
                    804:        Pbase   name_adj(Pname);
                    805:        Pname   aggr();
                    806:        Pbase   check(Pname);
                    807: #ifndef GRAM
                    808:        void    dcl_print();
                    809:        Pbase   arit_conv(Pbase);
                    810:         bit     parametrized_class();
                    811: #endif
                    812:        int     discriminator(int); // union discriminator fcn 
                    813: };
                    814: 
                    815: enum Linkage { linkage_default, linkage_C, linkage_Cplusplus };
                    816: extern Linkage linkage;
                    817: void set_linkage(char*);
                    818: 
                    819: struct fct : type              // FCT
                    820: {
                    821:        TOK     nargs;
                    822:        TOK     nargs_known;    // 0 if unknown, 1 if known, or ELLIPSIS
                    823:        bit     last_stmt;
                    824:        bit     f_vdef;         // 1 if this is the first virtual definition
                    825:                                // of this function
                    826:        bit     f_inline;       // 1 if inline, 2 if being expanded, else 0
                    827:        bit     f_const;        // one if member function that may be called for
                    828:                                // a const object, else 0
                    829:        bit     f_static;       // 1 if static member function, else 0
                    830:        short   f_virtual;      // index in virtual table, or 0 meaning non-virtual
                    831:        short   f_imeasure;     // some measure of the size of an inline function
                    832:        Ptype   returns;
                    833:        Pname   argtype;
                    834:        Ptype   s_returns;
                    835:        Pname   f_this;
                    836:        Pclass  memof;          // member of class memof
                    837:        Pblock  body;
                    838:        Pname   f_init;         // base and member initializers
                    839:        Pexpr   f_expr;         // body expanded into an expression
                    840:        Pexpr   last_expanded;
                    841:        Pname   f_result;       // extra second argument of type X&
                    842:        Pname   f_args;         // argument list including args added by cfront
                    843:        Linkage f_linkage;
                    844:        char*   f_signature;    // character encoding of function type
                    845:        Plist local_class;      // list of local classes
                    846:        static Pfct fct_free;
                    847:        void*   operator new(size_t);
                    848:        void    operator delete(void*,size_t);
                    849: 
                    850:        fct(Ptype, Pname, TOK);
                    851:        void    argdcl(Pname,Pname);
                    852: #ifndef GRAM
                    853:        Ptype   normalize(Ptype);
                    854:        void    dcl_print();
                    855:        void    dcl(Pname);
                    856:        Pexpr   base_init(Pclass, Pexpr, Ptable, int);
                    857:        Pexpr   mem_init(Pname, Pexpr, Ptable);
                    858:        void    init_bases(Pclass, Pexpr);
                    859:        bit     declared() { return nargs_known; };
                    860:        void    simpl();
                    861:        int     ctor_simpl(Pclass, Pexpr);
                    862:        Pstmt   dtor_simpl(Pclass, Pexpr);
                    863:        Pexpr   expand(Pname,Ptable,Pexpr);
                    864:        void    sign();
                    865: #endif
                    866:        int     discriminator(int); // union discriminator fcn 
                    867: };
                    868: 
                    869: struct name_list : node {
                    870:        Pname   f;
                    871:        Plist   l;
                    872:         name_list(Pname ff, Plist ll) { base = XNLIST; f=ff; l=ll; };
                    873: };
                    874: 
                    875: #ifndef GRAM
                    876: struct gen : type {            // OVERLOAD
                    877:        Plist   fct_list;
                    878: 
                    879:        gen() { base = OVERLOAD; }
                    880:        Pname   add(Pname);
                    881:        Pname   find(Pfct, bit);
                    882:        Pname   match(Pname, Pfct, bit);
                    883: };
                    884: #endif
                    885: 
                    886: struct pvtyp : type {
                    887:        Ptype typ;
                    888: };
                    889: 
                    890: struct vec : pvtyp             // VEC
                    891:                                // typ [ dim ]
                    892: {
                    893:        Pexpr   dim;
                    894:        int     size;   
                    895: 
                    896:        static Pvec vec_free;
                    897:        void*   operator new(size_t);
                    898:        void    operator delete(void*,size_t);
                    899: 
                    900:        vec(Ptype t, Pexpr e) { base=VEC; typ=t; dim=e; DBID(); }
                    901: #ifndef GRAM
                    902:        Ptype   normalize(Ptype);
                    903: #endif
                    904: };
                    905: 
                    906: struct ptr : pvtyp             // PTR, RPTR i.e. reference
                    907: {
                    908:        Pclass  memof;          // pointer to member of memof: memof::*
                    909:        bit     rdo;            // "*const"
                    910: 
                    911:        static Pptr ptr_free;
                    912:        void*   operator new(size_t);
                    913:        void    operator delete(void*,size_t);
                    914: 
                    915:        ptr(TOK b, Ptype t) { base=b; typ=t; DBID(); }
                    916: #ifndef GRAM
                    917:        Ptype   normalize(Ptype);
                    918: #endif
                    919: };
                    920: 
                    921: #ifndef GRAM
                    922: inline Pptr type::addrof() { return new ptr(PTR,this); }
                    923: 
                    924: extern bit vrp_equiv;
                    925: #endif
                    926: 
                    927: 
                    928: /****************************** constants ********************************/
                    929: 
                    930:                /* STRING ZERO ICON FCON CCON ID */
                    931:                /* IVAL FVAL LVAL */
                    932: 
                    933: /***************************** expressions ********************************/
                    934: 
                    935: #ifndef GRAM
                    936: extern Pexpr next_elem();
                    937: extern void new_list(Pexpr);
                    938: extern void list_check(Pname, Ptype, Pexpr, Ptable=0);
                    939: extern Pexpr ref_init(Pptr,Pexpr,Ptable);
                    940: extern Pexpr class_init(Pexpr,Ptype,Pexpr,Ptable);
                    941: extern Pexpr check_cond(Pexpr, TOK, Ptable);
                    942: extern Pexpr ptof(Pfct,Pexpr,Ptable);
                    943: extern void dosimpl(Pexpr, Pname);
                    944: extern int ref_initializer;
                    945: extern int ntok;
                    946: 
                    947: extern void ptbl_init(int);
                    948: extern void ptbl_add_pair(char*,char*);
                    949: extern char *ptbl_lookup(char*);
                    950: extern char *st_name(char*);
                    951: #endif
                    952: 
                    953: struct expr : node     /* PLUS, MINUS, etc. */
                    954:        /* IMPORTANT:   all expressions are of sizeof(expr) */
                    955:        /*      DEREF           =>      *e1 (e2==0) OR e1[e2]
                    956:                UMINUS          =>      -e2
                    957:                INCR (e1==0)    =>      ++e2
                    958:                INCR (e2==0)    =>      e1++
                    959:                CM              =>      e1 , e2
                    960:                ILIST           =>      LC e1 RC   (an initializer list)
                    961:                a Pexpr may denote a name
                    962:        */
                    963: {
                    964:        union {
                    965:                Ptype   tp;
                    966:                char    *string4;
                    967:        };
                    968:        union {
                    969:                Pexpr   e1;
                    970:                long    i1;
                    971:                char*   string;
                    972:        };
                    973:        union {
                    974:                Pexpr   e2;
                    975:                int     i2;
                    976:                char*   string2;
                    977:                Pexpr   n_initializer;
                    978:                Ptype   tpdef;  // local and nested typedef info
                    979:        };
                    980:        union {                 /* used by the derived classes */
                    981:                Ptype   tp2;    
                    982:                Pname   fct_name;
                    983:                Pexpr   cond;
                    984:                Pexpr   mem;
                    985:                Ptype   as_type;
                    986:                Ptable  n_table;
                    987:                Pin     il;
                    988:                Pname   query_this; 
                    989:        };
                    990: 
                    991:        static Pexpr expr_free;
                    992:        void* operator new(size_t);
                    993:        void operator delete(void*,size_t);
                    994:        expr(TOK, Pexpr, Pexpr);
                    995:        void    del();
                    996: #ifndef GRAM
                    997:        void    print();
                    998:         Pexpr   typ0(Ptable);
                    999:        Pexpr   typ(Ptable);
                   1000:        long    eval();
                   1001:        unsigned long ueval(long,long);
                   1002:        int     lval(TOK);
                   1003:        Ptype   call_fct(Ptable);
                   1004:        Pexpr   address();
                   1005:        Pexpr   contents();
                   1006:        void    simpl();
                   1007:        Pexpr   expand();
                   1008:        bit     not_simple();
                   1009:        Pexpr   try_to_overload(Ptable);
                   1010:        Pexpr   docast(Ptable);
                   1011:        Pexpr   dovalue(Ptable);
                   1012:        Pexpr   donew(Ptable);
                   1013:        void    simpl_new();
                   1014:        void    simpl_delete();
                   1015: #endif
                   1016:        int     discriminator(int); // union discriminator fcn 
                   1017: };
                   1018: 
                   1019: struct texpr : expr {          // CAST NEW VALUE (also ICALL)
                   1020:        texpr(TOK bb, Ptype tt, Pexpr ee) : expr (bb,ee,0) { tp2=tt; }
                   1021: };
                   1022: 
                   1023: struct cast : expr {           // CAST
                   1024:        cast(Ptype tt, Pexpr ee) : expr (CAST,ee,0) { tp=tp2=tt; }
                   1025: };
                   1026: 
                   1027: struct ival : expr {           // IVAL
                   1028:        ival(long ii) : expr (IVAL,0,0) { i1 = ii;}
                   1029: };
                   1030: 
                   1031: struct call : expr {           // CALL
                   1032:        call(Pexpr aa, Pexpr bb) : expr (CALL,aa,bb) { }
                   1033: #ifndef GRAM
                   1034:        void    simpl();
                   1035:        Pexpr   expand(Ptable);
                   1036: #endif
                   1037: };
                   1038: 
                   1039: struct qexpr : expr {          // QUEST        cond ? e1 : e2
                   1040:        qexpr(Pexpr ee, Pexpr ee1, Pexpr ee2) : expr (QUEST,ee1,ee2) { cond=ee; }
                   1041: };
                   1042: 
                   1043: struct ref : expr {            // REF DOT      e1->mem OR e1.mem
                   1044:        ref(TOK ba, Pexpr a, Pexpr b) : expr (ba,a,0) { mem=b; }
                   1045: };
                   1046: 
                   1047: struct mdot : expr {           // MDOT         a.b
                   1048:        mdot(char* a, Pexpr b) : expr (MDOT,0,0) { string2=a; mem=b; }
                   1049: };
                   1050: 
                   1051: struct text_expr : expr        {       // TEXT (vtbl_name)
                   1052:        text_expr(char* a, char* b) : expr (TEXT,0,0)
                   1053:        { string=a; string2=b; }
                   1054: };
                   1055: char* vtbl_name(char*,char*);
                   1056: /************************* names (are expressions) ****************************/
                   1057: 
                   1058: struct basecl : node { // NAME         => base class
                   1059:                        // VIRTUAL      => virtual base class
                   1060:        TOK     ppp;            // private / public / protected
                   1061:        bit     allocated;      // allocated virtual base
                   1062:         bit     promoted;       // non-explicit, promoted virtual base
                   1063:        Pclass  bclass;
                   1064:        Pexpr   init;           // base class initializers for ctors
                   1065:        int     ptr_offset;     // pointer's relative position in derived class
                   1066:        int     obj_offset;     // object's relative position in derived class
                   1067:        Pname*  virt_init;      // vector of vtbl table initializers
                   1068:        basecl* next;
                   1069: 
                   1070:         basecl(Pclass cl, basecl* n) { baseclass=1; bclass=cl; next=n; promoted=0; init=0;}
                   1071: };
                   1072: 
                   1073: enum template_formal_types { 
                   1074:        template_type_formal =1 , template_expr_formal,
                   1075:         template_stmt_tree_formal, template_expr_tree_formal,
                   1076:         template_actual_arg_dummy // used during the parse
                   1077: };
                   1078: extern TOK ppbase;
                   1079: 
                   1080: struct name : expr {   // NAME TNAME and the keywords in the ktbl
                   1081:        TOK     n_oper;         // name of operator or 0
                   1082:        TOK     n_sto;          // EXTERN STATIC AUTO REGISTER ENUM 0
                   1083:        TOK     n_stclass;      // STATIC AUTO REGISTER 0
                   1084:        TOK     n_scope;        // EXTERN STATIC FCT ARG PUBLIC 0 
                   1085:        TOK     n_key;  /* for names in table: class */
                   1086:        bit     n_evaluated;    // 0 or n_val holds the value
                   1087:        bit     n_xref;         // argument of type X(X&)
                   1088:        unsigned char   lex_level;
                   1089:        TOK     n_protect;      // PROTECTED (<=>n_scope==0) or 0
                   1090:        bit     n_dcl_printed;  // 1: declaration printed
                   1091:                                // 2: definition printed
                   1092:                                // 0: declaration not printed
                   1093: 
                   1094:         // if this is set it implies that n_template_arg == template_type_formal
                   1095:        char    n_template_arg; // One of template_formal_types for template arguments
                   1096:         bit     n_template_formal_must_be_class ;
                   1097:         bit     n_redefined ;   // set only for PT function names where an explict
                   1098:                                 // definition was provided.
                   1099:         char    *n_anon;       // nested anonymous unions
                   1100:        short   n_union;        // 0, or union index
                   1101:        short   n_addr_taken;
                   1102:        short   n_used;
                   1103:        short   n_assigned_to;
                   1104:        Loc     where;
                   1105:        int     n_offset;       // byte offset in frame or struct
                   1106:        Pname   n_list;
                   1107:        Pname   n_tbl_list;
                   1108:        char    *n_gen_fct_name; // used to be punned with n_tbl_list.
                   1109:         char    *n_template_arg_string ; // the mangled string name
                   1110:        union {
                   1111:        /* 
                   1112:         * n_qualifier: name of containing class
                   1113:         * n_realscope: for labels (always entered in function table) 
                   1114:          *             the table for the actual scope in which label occurred.
                   1115:         * syn_class: lex table only
                   1116:         */
                   1117:                Pname   n_qualifier;    
                   1118:                 Ptable  n_realscope;    
                   1119:                int     syn_class; 
                   1120:         };
                   1121: 
                   1122:        /* n_val: the value of n_initializer; also the argument 
                   1123:         * number for inline arguments (when base == ANAME) */
                   1124:        long    n_val;          
                   1125:        static Pname name_free;
                   1126:        void* operator new(size_t);
                   1127:        void operator delete(void*,size_t);
                   1128:        name(char* =0);
                   1129: 
                   1130: 
                   1131:        Pname   normalize(Pbase, Pblock, bit);
                   1132:        Pname   tdef();
                   1133:        Pname   tname(TOK);
                   1134:        void    hide();
                   1135:        void    unhide()        { n_key=0; n_list=0; };
                   1136: #ifndef GRAM
                   1137:        Pname   dcl(Ptable,TOK);
                   1138:        int     no_of_names();
                   1139:        void    use()           { n_used++; };
                   1140:        void    assign();
                   1141:        void    take_addr();
                   1142:        void    check_oper(Pname);
                   1143:        void    simpl();
                   1144:        void    print();
                   1145:        void    dcl_print(TOK);
                   1146:        void    field_align();
                   1147:        Pname   dofct(Ptable,TOK);
                   1148: #endif
                   1149:        void    del();
                   1150:        int     discriminator(int); // union discriminator fcn 
                   1151: };
                   1152: 
                   1153: extern int friend_in_class;
                   1154: extern int in_class_dcl;
                   1155: 
                   1156: // from parser
                   1157: extern int in_class_decl;
                   1158: extern int parsing_class_members;
                   1159: extern int in_mem_fct;
                   1160: extern int in_arg_list;
                   1161: extern Ptype in_typedef;
                   1162: extern int     defer_check;     // redefinition typedef check delay
                   1163: extern int     declTag;         // !1: inline, virtual mod permitted
                   1164: extern Pname in_tag;
                   1165: extern Pname statStat;
                   1166: extern int DECL_TYPE;
                   1167: 
                   1168: /******************** statements *********************************/
                   1169: 
                   1170: struct stmt : node {   /* BREAK CONTINUE DEFAULT */
                   1171: /*     IMPORTANT: all statement nodes have sizeof(stmt) */
                   1172:        Pstmt   s;
                   1173:        Pstmt   s_list;
                   1174:        Loc     where;
                   1175:        union {
                   1176:                Pname   d; // goto/block -- destination
                   1177:                Pexpr   e2; // for iteration
                   1178:                Pstmt   has_default; // switch statement default
                   1179:                int     case_value; 
                   1180:                Ptype   ret_tp; // pair
                   1181:        };
                   1182:        union {
                   1183:                Pexpr   e;
                   1184:                bit     own_tbl;
                   1185:                Pstmt   s2;
                   1186:        };
                   1187:        Ptable  memtbl;
                   1188:        union {
                   1189:                Pstmt   for_init;
                   1190:                Pstmt   else_stmt;
                   1191:                Pstmt   case_list;
                   1192:                Loc     where2; // location of } at end of block
                   1193:        };
                   1194: 
                   1195:        static Pstmt stmt_free;
                   1196:        void* operator new(size_t);
                   1197:        void operator delete(void*,size_t);
                   1198:        stmt(TOK, loc, Pstmt);
                   1199:        void    del();
                   1200: #ifndef GRAM
                   1201:        void    print();
                   1202:        void    dcl();
                   1203:         void    dcl1(Pstmt&);
                   1204:        void    reached();
                   1205:        Pstmt   simpl();
                   1206:        Pstmt   expand();
                   1207:        Pstmt   copy();
                   1208: #endif
                   1209:        int     discriminator(int); // union discriminator fcn 
                   1210: };
                   1211: 
                   1212: #ifndef GRAM
                   1213: extern char* Neval;
                   1214: extern Ptable scope;
                   1215: extern Ptable expand_tbl;
                   1216: extern Pname expand_fn;
                   1217: #endif
                   1218: 
                   1219: struct estmt : stmt    /* SM WHILE DO SWITCH RETURN CASE */
                   1220:        /*      SM (e!=0)       =>      e;
                   1221:                in particular assignments and function calls
                   1222:                SM (e==0)       =>      ;       (the null statement)
                   1223:                CASE            =>      case e : s ;
                   1224:                SM_PARAM        => e is the template_statement_tree_formal name
                   1225:        */
                   1226: {
                   1227:        estmt(TOK t, loc ll, Pexpr ee, Pstmt ss) : stmt (t,ll,ss) { e=ee; }
                   1228: };
                   1229: 
                   1230: struct ifstmt : stmt   /* IF */
                   1231:        // else_stme==0 =>      if (e) s
                   1232:        // else_stmt!=0 =>      if (e) s else else_stmt
                   1233: {
                   1234:        ifstmt(loc ll, Pexpr ee, Pstmt ss1, Pstmt ss2)
                   1235:                : stmt (IF,ll,ss1) { e=ee; else_stmt=ss2; };
                   1236: };
                   1237: 
                   1238: struct lstmt : stmt    /* LABEL GOTO */
                   1239:        /*
                   1240:                d : s
                   1241:                goto d
                   1242:        */
                   1243: {
                   1244:        lstmt(TOK bb, loc ll, Pname nn, Pstmt ss) : stmt (bb,ll,ss) { d=nn; }
                   1245: };
                   1246: 
                   1247: struct forstmt : stmt {        // FOR
                   1248:        forstmt(loc ll, Pstmt fss, Pexpr ee1, Pexpr ee2, Pstmt ss)
                   1249:                : stmt (FOR,ll,ss) { for_init=fss; e=ee1; e2=ee2; }
                   1250: };
                   1251: 
                   1252: struct block : stmt {  // BLOCK        { d s }
                   1253:        block(loc ll, Pname nn, Pstmt ss, loc rr = noloc ) : stmt (BLOCK,ll,ss)
                   1254:                { d=nn; where2=rr; }
                   1255: #ifndef GRAM
                   1256:        void    dcl(Ptable);
                   1257:        Pstmt   simpl();
                   1258: #endif
                   1259: };
                   1260: 
                   1261: #ifndef GRAM
                   1262: struct pair : public stmt {    // PAIR
                   1263:        pair(loc ll, Pstmt a, Pstmt b) : stmt (PAIR,ll,a) { s2 = b; }
                   1264: };
                   1265: #endif
                   1266: 
                   1267: struct nlist {
                   1268:        Pname   head;
                   1269:        Pname   tail;
                   1270:                nlist(Pname);
                   1271:        void    add(Pname n)    { tail->n_list = n; tail = n; };
                   1272:        void    add_list(Pname);
                   1273: };
                   1274: 
                   1275: extern Pname name_unlist(nlist*);
                   1276: 
                   1277: struct slist {
                   1278:        Pstmt   head;
                   1279:        Pstmt   tail;
                   1280:                slist(Pstmt s)  { /*Nl++;*/ head = tail = s; };
                   1281:        void    add(Pstmt s)    { tail->s_list = s; tail = s; };
                   1282: };
                   1283: 
                   1284: extern Pstmt stmt_unlist(slist*);
                   1285: 
                   1286: struct elist {
                   1287:        Pexpr   head;
                   1288:        Pexpr   tail;
                   1289:                elist(Pexpr e)  { /*Nl++;*/ head = tail = e; };
                   1290:        void    add(Pexpr e)    { tail->e2 = e; tail = e; };
                   1291: };
                   1292: 
                   1293: extern Pexpr expr_unlist(elist*);
                   1294: 
                   1295: #ifndef GRAM 
                   1296: extern class dcl_context * cc;
                   1297: 
                   1298: struct dcl_context {
                   1299:        Pname   c_this; /* current fct's "this" */
                   1300:        Ptype   tot;    /* type of "this" or 0 */
                   1301:        Pname   not;    /* name of "this"'s class or 0 */
                   1302:        Pclass  cot;    /* the definition of "this"'s class */
                   1303:        Ptable  ftbl;   /* current fct's symbol table */
                   1304:        Pname   nof;    /* current fct's name */
                   1305: 
                   1306:        void    stack()         { cc++; *cc = *(cc-1); };
                   1307:        void    unstack()       { cc--; };
                   1308: };
                   1309: 
                   1310: #define MAXCONT        20
                   1311: extern dcl_context ccvec[MAXCONT];
                   1312: #endif 
                   1313: 
                   1314: extern void yyerror(char*);
                   1315: 
                   1316: 
                   1317: #ifndef GRAM
                   1318: extern char* line_format;
                   1319: 
                   1320: extern Plist stat_mem_list;
                   1321: extern Plist isf_list;
                   1322: extern Pstmt st_ilist;
                   1323: extern Pstmt st_dlist;
                   1324: extern Ptable sti_tbl;
                   1325: extern Ptable std_tbl;
                   1326: extern int need_sti( Pexpr e, Ptable tbl = 0, bit is_static_ok = 0 ); 
                   1327: Pexpr try_to_coerce(Ptype, Pexpr, char*, Ptable);
                   1328: extern bit can_coerce(Ptype, Ptype);
                   1329: extern Ptype np_promote(TOK, TOK, TOK, Ptype, Ptype, TOK);
                   1330: extern bit enum_promote;
                   1331: extern int suppress_error;
                   1332: extern void delete_local();
                   1333: 
                   1334: extern int over_call(Pname, Pexpr);
                   1335: extern Pname overFound;
                   1336: extern Pname Nover;
                   1337: extern Pname Ncoerce;
                   1338: extern Nover_coerce;
                   1339: struct ia : node {
                   1340:        Pname   local;  // local variable for argument
                   1341:        Pexpr   arg;    // actual arguments for call
                   1342:        Ptype   tp;     // type of formal argument
                   1343:         ia() { base = XIA; };
                   1344: };
                   1345: 
                   1346: struct iline : node {
                   1347:        Pname   fct_name;       /* fct called */
                   1348:        Pin     i_next;
                   1349:        Ptable  i_table;
                   1350:        int     i_slots;        // no of arg slots pointer to by i_args
                   1351:        ia*     i_args;
                   1352:         iline() { base = XILINE; };
                   1353: };
                   1354: 
                   1355: extern Pexpr curr_expr;
                   1356: extern Pin curr_icall;
                   1357: #define FUDGE111 11111
                   1358: #define VTOK 22222
                   1359: #define ITOR 77
                   1360: 
                   1361: extern Pstmt curr_loop;
                   1362: extern Pblock curr_block;
                   1363: extern Pstmt curr_switch;
                   1364: extern loc last_line;  // last #line + number of '\n's output since
                   1365: extern int last_ll;    // 0 or line of current stmt/dcl being printed
                   1366: extern FILE* out_file; // output file descriptor
                   1367: extern bit Cast;
                   1368: extern loc no_where;
                   1369: 
                   1370: extern no_of_undcl;
                   1371: extern no_of_badcall;
                   1372: extern Pname undcl, badcall;
                   1373: 
                   1374: extern long str_to_long(const char*);
                   1375: extern int c_strlen(const char* s);
                   1376: #endif
                   1377: 
                   1378: #ifndef GRAM
                   1379: extern Pname vec_new_fct;
                   1380: extern Pname new_fct;
                   1381: extern Pname del_fct;
                   1382: extern Pname vec_del_fct;
                   1383: 
                   1384: extern int Nstd; // standard coercion used (derived* =>base* or int=>long or ...)
                   1385: 
                   1386: extern int stcount;    // number of names generated using make_name()
                   1387: 
                   1388: Pexpr replace_temp(Pexpr,Pexpr);
                   1389: void make_res(Pfct);
                   1390: 
                   1391: extern int Pchecked;
                   1392: Pexpr ptr_init(Pptr,Pexpr,Ptable);
                   1393: Pexpr call_ctor(Ptable, Pexpr p, Pexpr ctor, Pexpr args, int d = REF, Pexpr vb_args = 0);
                   1394: Pexpr call_dtor(Pexpr p, Pexpr dtor, Pexpr arg = 0, int d = DOT, Pexpr vb_args = 0);
                   1395: void check_visibility(Pname, Pname, Pclass, Ptable, Pname);
                   1396: 
                   1397: int make_assignment(Pname);
                   1398: 
                   1399: extern Pname make_tmp(char, Ptype, Ptable);
                   1400: Pexpr init_tmp(Pname, Pexpr, Ptable);
                   1401: 
                   1402: extern int is_unique_base(Pclass, char*, int, int = 0);
                   1403: extern Pexpr rptr(Ptype, Pexpr, int);
                   1404: 
                   1405: extern int read_align(char*);
                   1406: extern void new_init();
                   1407: 
                   1408: extern void Eprint(Pexpr);
                   1409: extern Pexpr cast_cptr(Pclass ccl, Pexpr ee, Ptable tbl, int real_cast);
                   1410: extern Pexpr mptr_assign(Pexpr,Pexpr);
                   1411: extern Pclass Mptr;
                   1412: 
                   1413: #endif
                   1414: 
                   1415: extern bit fake_sizeof;        // suppress error message for ``int v[];''
                   1416: 
                   1417: extern TOK lalex();
                   1418: 
                   1419: 
                   1420: #ifdef DBG
                   1421: extern void display_expr( Pexpr, char* = 0, int = 0 );
                   1422: extern void display_stmt( Pstmt, char* = 0, int = 0 );
                   1423: extern void display_type( Ptype );
                   1424: extern void display_namelist( Plist, char* = 0, int = 0 );
                   1425: 
                   1426: extern fprintf(const FILE*, const char* ...);
                   1427: extern void process_debug_flags( char* );
                   1428: #define DB(a) if(scan_started){a;}
                   1429: extern int Adebug; // allocation (ctor/del) debugging
                   1430: extern int Ddebug; // dcl debugging
                   1431: extern int Edebug; // expr debugging
                   1432: extern int Ldebug; // lex/lalex debugging
                   1433: extern int Mdebug; // trace function matching
                   1434: extern int Ndebug; // norm debugging
                   1435: extern int Pdebug; // print debugging
                   1436: extern int Rdebug; // run() debugging
                   1437: extern int Sdebug; // simpl debugging
                   1438: extern int Tdebug; // typ debugging
                   1439: #define Ydebug yydebug
                   1440: extern int Ydebug; // yacc debugging
                   1441: 
                   1442: #else
                   1443: 
                   1444: #define DB(a) /**/
                   1445: 
                   1446: #endif
                   1447: 
                   1448: #endif
                   1449: /* end */
                   1450: 0707071010112043661004440001630000160000010071100466055375100000600000112027dcl.c/*ident      "@(#)ctrans:src/dcl.c   1.5" */
                   1451: /**************************************************************************
                   1452: 
                   1453:        C++ source for cfront, the C++ compiler front-end
                   1454:        written in the computer science research center of Bell Labs
                   1455: 
                   1456:        Copyright (c) 1984 AT&T, Inc. All rights Reserved
                   1457:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   1458: 
                   1459: dcl.c:
                   1460: 
                   1461:        ``declare'' all names, that is insert them in the appropriate symbol tables.
                   1462: 
                   1463:        Calculate the size for all objects (incl. stack frames),
                   1464:        and find store the offsets for all members (incl. auto variables).
                   1465:        "size.h" holds the constants needed for calculating sizes.
                   1466: 
                   1467:        Note that (due to errors) functions may nest
                   1468: 
                   1469: *****************************************************************************/
                   1470: 
                   1471: 
                   1472: #include "cfront.h"
                   1473: #include "size.h"
                   1474: 
                   1475: class dcl_context ccvec[MAXCONT], * cc = ccvec;
                   1476: int byte_offset;
                   1477: int bit_offset;
                   1478: int max_align;
                   1479: int friend_in_class;
                   1480: static Pstmt itail;
                   1481: 
                   1482: Pname dclass(Pname, Ptable);
                   1483: Pname denum(Pname, Ptable);
                   1484: void merge_init(Pname, Pfct, Pfct);
                   1485: 
                   1486: void dosimpl(Pexpr e, Pname n)
                   1487: {
                   1488: //error('d',"dosimpl %k %n",e?e->base:0,n);
                   1489:        if (n==0) {
                   1490:                if (dummy_fct == 0) make_dummy();
                   1491:                n = dummy_fct;
                   1492:        }
                   1493:        Pname cf = curr_fct;
                   1494:        curr_fct = n;
                   1495:        e->simpl();
                   1496:        curr_fct = cf;
                   1497: }
                   1498: 
                   1499: static Pexpr co_array_init(Pname n, Ptable tbl)
                   1500: /*
                   1501:        handle simple arrays only. To be done well list_check() must
                   1502:        be rewritten to handle dynamic initialization.
                   1503: */
                   1504: {
                   1505: // error('d',"Ir forCO%n\[\]",n);
                   1506:        Pexpr init = n->n_initializer;
                   1507: 
                   1508:        if (init->base != ILIST) {
                   1509:                error("badIr for array ofCOs %n",n);
                   1510:                return 0;
                   1511:        }
                   1512: 
                   1513:        Pexpr el = 0;
                   1514:        Pvec v = Pvec(n->tp);
                   1515:        while (v->base==TYPE) v = Pvec(Pbase(v)->b_name->tp);
                   1516:        Pname cn = v->typ->is_cl_obj();
                   1517:        Pclass cl = cn ? Pclass(cn->tp) : 0;
                   1518: //error('d',"v %t cl %d %t",v,cl,cl);
                   1519:        int i = v->size;
                   1520: 
                   1521:        int count = 0;
                   1522:        Pexpr il2;
                   1523:        for (Pexpr il = init->e1; il; il = il2) {
                   1524:                        // generate     n[0].cl(initializer),
                   1525:                        //              ...
                   1526:                        //              n[max].cl(initializer),
                   1527:                Pexpr e = il->e1;
                   1528:                il2 = il->e2;
                   1529:                il->e2 = 0;
                   1530:                if  (e == dummy) break;
                   1531: //error('d',"il %k e %k",il->base,e?e->base:0);
                   1532:                if (e->base == VALUE) {
                   1533:                        switch (e->tp2->base) {
                   1534:                        case CLASS:
                   1535:                                if (Pclass(e->tp2)!=cl) e = new texpr(VALUE,cl,il);
                   1536:                                break;
                   1537:                        default:
                   1538:                                Pname n2 = e->tp2->is_cl_obj();
                   1539:                                if (n2==0 || Pclass(n2->tp)!=cl) e = new texpr(VALUE,cl,il);
                   1540:                        }
                   1541:                }
                   1542:                else
                   1543:                        e = new texpr(VALUE,cl,il);
                   1544:                e->e2 = new expr(DEREF,n,new ival(count++));
                   1545:                e = e->typ(tbl);
                   1546:                dosimpl(e,cc->nof);
                   1547:        //      e->simpl();
                   1548:                if (sti_tbl == tbl) {
                   1549:                        Pstmt ist = new estmt(SM,no_where,e,0);
                   1550:                        if (st_ilist == 0)
                   1551:                                st_ilist = ist;
                   1552:                        else
                   1553:                                itail->s_list = ist;
                   1554:                        itail = ist;
                   1555:                }
                   1556:                else {
                   1557:                        el = el ? new expr(G_CM,el,e) : e;
                   1558:                }
                   1559:        }
                   1560: 
                   1561:        if (i==0)
                   1562:                v->size = count;
                   1563:        else if (i==count)
                   1564:                ;
                   1565:        else if (i<count) {
                   1566:                 error("too manyIrs for%n (%d)",n, count);
                   1567:                return 0;
                   1568:        }       
                   1569:        else {
                   1570: //              error('d',"too fewIrs for%n (%d)",n, count);
                   1571:                if (cl->has_ictor())
                   1572:                        error('s',"too fewIrs for%n",n);
                   1573:                else error( "too fewIrs for%n (C %srequires a defaultK)", n, cl->string );
                   1574:                return 0;
                   1575:        }
                   1576:        return el;
                   1577: }
                   1578: 
                   1579: int need_sti(Pexpr e, Ptable tbl, bit accept_name)
                   1580: /*
                   1581:        check if non-static variables or operations are used
                   1582:        INCOMPLETE 
                   1583: */
                   1584: {
                   1585:        if (e == 0) return 0;
                   1586: // error('d',"need_sti: %d - %d %k %t",tbl?1:0,accept_name,e->base,e->tp);
                   1587: 
                   1588:        switch (e->base) {
                   1589:        case QUEST:
                   1590:                if (need_sti(e->cond,tbl,0) && tbl==0) return 1;
                   1591:        case PLUS:
                   1592:        case MINUS:
                   1593:        case MUL:
                   1594:        case DIV:
                   1595:        case MOD:
                   1596:        case ER:
                   1597:        case OR:
                   1598:        case ANDAND:
                   1599:        case OROR:
                   1600:        case LS:
                   1601:        case RS:
                   1602:        case EQ:
                   1603:        case NE:
                   1604:        case LT:
                   1605:        case LE:
                   1606:        case GT:
                   1607:        case GE:
                   1608:        case INCR:
                   1609:        case DECR:
                   1610:        case ASSIGN:
                   1611:                if (need_sti(e->e1,tbl,accept_name) && tbl==0) return 1;
                   1612:                // no break;
                   1613: 
                   1614:        case UMINUS:
                   1615:        case UPLUS:
                   1616:        case NOT:
                   1617:        case COMPL:
                   1618:                if (need_sti(e->e2,tbl,accept_name) && tbl==0) return 1;
                   1619:                // no break
                   1620: 
                   1621:        case SIZEOF:
                   1622:        default:
                   1623: 
                   1624:                return 0;
                   1625: 
                   1626:        case CAST:
                   1627: 
                   1628:                return need_sti(e->e1,tbl,accept_name);
                   1629: 
                   1630:        case ADDROF:
                   1631:        {
                   1632:                int i = need_sti(e->e2,tbl,1);
                   1633:                return i;
                   1634:        }
                   1635: 
                   1636:        case NAME:
                   1637:                if (accept_name && Pname(e)->n_stclass==STATIC) return 0;
                   1638: 
                   1639: //             if ((Pname(e)->n_stclass==AUTO || Pname(e)->n_stclass==REGISTER)
                   1640: //             &&   strncmp(Pname(e)->string,"__Q",3) != 0 ) {
                   1641: //                     error("localN%n inIr for static",e);
                   1642: //                     return 0;
                   1643: //             }
                   1644: 
                   1645:                if (e->tp->tconst()) {
                   1646:                        if (vec_const || fct_const) return 0;
                   1647:                        Neval = 0;
                   1648:                        e->eval();
                   1649:                        if (Neval == 0) return 0;
                   1650:                }
                   1651:                return 1;
                   1652: 
                   1653:        case DEREF:
                   1654:        case REF:
                   1655:        case DOT:
                   1656:                if (accept_name||(e->tp && e->tp->base==VEC)) {
                   1657:                        int x1 = need_sti(e->e1,tbl,e->base == DOT);
                   1658:                        int x2 = need_sti(e->e2,tbl,0);
                   1659:                        return x1 || x2;
                   1660:                }
                   1661:                // no break
                   1662: 
                   1663:        case ELIST:
                   1664: //     case ILIST:
                   1665:        case G_CM:
                   1666:        case CM:
                   1667:                if (e->base==CM) {
                   1668:                        if (need_sti(e->e1,tbl,0) || need_sti(e->e2,tbl,0))
                   1669:                                return 1;
                   1670:                        else
                   1671:                                return 0;
                   1672:                }
                   1673:        case CALL:
                   1674:        case G_CALL:
                   1675:        case NEW:
                   1676:        case GNEW:
                   1677:        case 0:                 // hack for `new type (expr)'
                   1678:                if (tbl) {
                   1679:                        need_sti(e->e1,tbl,accept_name);
                   1680:                        need_sti(e->e2,tbl,accept_name);
                   1681:                        if ( e->tp && e->tp->base == VEC &&
                   1682:                                e->base == NEW || e->base == GNEW )
                   1683:                                // preserve ICON,STRING,CCON,FCON
                   1684:                                need_sti(Pvec(e->tp)->dim,tbl);
                   1685:                }
                   1686:                 else if (e->base == 0)
                   1687:                       return 0;
                   1688:                // no break
                   1689:        case ICALL:
                   1690:                return 1;
                   1691:        case ICON:
                   1692:        case STRING:
                   1693:        case CCON:
                   1694:        case FCON:
                   1695: //error('d',"save %k tbl %d",e->base,tbl);
                   1696:                if (tbl) {
                   1697:                        char* p = new char[strlen(e->string)+1];
                   1698:                        strcpy(p,e->string);
                   1699:                        e->string = p;
                   1700:                }
                   1701:                return 0;
                   1702:        }
                   1703: }
                   1704: 
                   1705: static void check_def_name( Pname nn, int scope ) 
                   1706: {
                   1707: // error('d', "check_def_name: nn: %n n_sto: %k scope: %k", nn,nn->n_sto,scope );
                   1708:        if ( def_name==0 && pdef_name==0 && friend_in_class == 0 &&
                   1709:                scope == EXTERN && nn->n_scope != STATIC &&  
                   1710:                nn->n_oper != NEW && nn->n_oper != DELETE ) { 
                   1711:                        Pfct f = Pfct(nn->tp);
                   1712:                        if (f->body && 
                   1713:                                f->f_inline == 0 && 
                   1714:                                f->f_imeasure == 0) {
                   1715: // error('d', "check_def_name: do it: %n", nn );
                   1716:                                        pdef_name = def_name = nn;
                   1717:                                        ptbl_init(0);
                   1718:                                        def_name = 0;
                   1719:                        }
                   1720:        }
                   1721: }
                   1722: 
                   1723: int stat_init = 0; // in an expression initializing a local static
                   1724: Pname name::dcl(Ptable tbl, TOK scope)
                   1725: /*
                   1726:        enter a copy of this name into symbol table "tbl";
                   1727:                - create local symbol tables as needed
                   1728:        
                   1729:        "scope" gives the scope in which the declaration was found
                   1730:                - EXTERN, FCT, ARG, PUBLIC, or 0
                   1731:        Compare "scope" with the specified storage class "n_sto"
                   1732:                - AUTO, STATIC, REGISTER, EXTERN, OVERLOAD, FRIEND, or 0
                   1733: 
                   1734:        After name::dcl()
                   1735:        n_stclass ==    0               class or enum member
                   1736:                        REGISTER        auto variables declared register
                   1737:                        AUTO            auto variables not registers
                   1738:                        STATIC          statically allocated object
                   1739:        n_scope ==      0               private class member
                   1740:                        PUBLIC          public class member
                   1741:                        EXTERN          name valid in this and other files
                   1742:                        STATIC          name valid for this file only
                   1743:                        FCT             name local to a function
                   1744:                        ARG             name of a function argument
                   1745:                        ARGT            name of a type defined in an
                   1746:                                        argument list
                   1747:                         ARGS            temporary class object with dtor in
                   1748:                                         initialization of a local static
                   1749: 
                   1750: 
                   1751:        typecheck function bodies;
                   1752:        typecheck initializers;
                   1753: 
                   1754:        note that functions (error recovery) and classes (legal) nest
                   1755: 
                   1756:        The return value is used to chain symbol table entries, but cannot
                   1757:        be used for printout because it denotes the sum of all type information
                   1758:        for the name
                   1759: 
                   1760:        names of typenames are marked with n_oper==TNAME
                   1761: 
                   1762:        WARNING: The handling of scope and storage class is cursed!
                   1763: */
                   1764: {
                   1765:        Pname nn;
                   1766:        Ptype nnt = 0;
                   1767:        Pname odcl = Cdcl;
                   1768:        int sti_vb = 0; // set if initialize with virtual base class
                   1769: 
                   1770: //     if (this == 0) error('i',"0->N::dcl()");
                   1771: //     if (tbl == 0) error('i',"%n->N::dcl(tbl=0,%k)",this,scope);
                   1772: //     if (tbl->base != TABLE) error('i',"%n->N::dcl(tbl=%d,%k)",this,tbl->base,scope);
                   1773: //     if (tp == 0) error('i',"N::dcl(%n,%k)T missing",this,scope);
                   1774: 
                   1775:        Cdcl = this;
                   1776:        Ptype tx = tp;
                   1777: 
                   1778:        DB( if(Ddebug>=1) error('d',"dcl %n %t",this,tx); );
                   1779: // error('d',"dcl %n %t cc->cot: %d",this,tx,cc?cc->cot:0); 
                   1780:        while (tx->base == TYPE) tx = Pbase(tx)->b_name->tp;
                   1781: 
                   1782:        switch (base) {
                   1783:        case TNAME:
                   1784:                nn = tbl->look(string,0);
                   1785:                tp->dcl(tbl);
                   1786:                 if (nn && nn->lex_level == lex_level) {
                   1787: //error('d', "dcl: cot: %s ccl: %s", cc->cot?cc->cot->string:"notset", ccl?ccl->string:"notset");
                   1788: 
                   1789:                         if ( tp->check(nn->tp,0) )
                   1790:                                 error("%n declared as %t and %t",nn,nn->tp,tp);
                   1791:                         else if ( nn->base == NAME && cc->cot == 0 &&
                   1792:                        (tp->base != COBJ || tp->base != EOBJ))
                   1793:                                 error("%n declared as identifier and typedef", nn );
                   1794:                         Cdcl = odcl;
                   1795:                         return 0;
                   1796: 
                   1797:                 }
                   1798:                PERM(tp);
                   1799:                nn = new name(string);
                   1800:                nn->base = TNAME;
                   1801:                nn->tp = tp;
                   1802:                Pname tn = tbl->insert(nn,0);
                   1803:                if (n_key == NESTED) {
                   1804:                        tn->n_key = NESTED;
                   1805:                        tn->tpdef = tpdef;
                   1806:                }
                   1807:                delete nn;
                   1808:                Cdcl = odcl;
                   1809:                return this;
                   1810:        
                   1811:        case NAME:
                   1812:                switch (n_oper) {
                   1813:                case COMPL:
                   1814:                        if (tp->base != FCT) {
                   1815:                                error("~%s notF",string);
                   1816:                                n_oper = 0;
                   1817:                        }
                   1818:                        break;
                   1819:                case TNAME:
                   1820:                        if (tp->base != FCT) n_oper = 0;
                   1821:                        break;
                   1822:                }
                   1823:                break;
                   1824:        default:
                   1825:                error('i',"NX in N::dcl()");
                   1826:        }
                   1827: 
                   1828:        if (n_qualifier) {      
                   1829:                                // c::f()
                   1830:                                // class function,
                   1831:                                // friend declaration, or 
                   1832:                                // static member initializer
                   1833:                Pname cn = n_qualifier;
                   1834: 
                   1835:                switch (cn->base) {
                   1836:                case TNAME:
                   1837:                        break;
                   1838:                case NAME:
                   1839:                        cn = gtbl->look(cn->string,0);
                   1840:                        if (cn && cn->base==TNAME) break;
                   1841:                default:
                   1842:                        error("badQr%n for%n",n_qualifier,this);
                   1843:                        Cdcl = odcl;
                   1844:                        return 0;
                   1845:                }
                   1846: 
                   1847:                while (cn->tp->base == TYPE) cn->tp = Pbase(cn->tp)->b_name->tp;
                   1848: // error('d',"actualQr%n %t",cn,cn->tp);
                   1849:                if (cn->tp->base != COBJ) {
                   1850:                        error(&where,"Qr%nnot aCN",n_qualifier);
                   1851:                        Cdcl = odcl;
                   1852:                        return 0;
                   1853:                }
                   1854: 
                   1855:                cn = Pbase(cn->tp)->b_name;
                   1856:                if (n_oper) check_oper(cn);
                   1857: 
                   1858:                Pclass cl = Pclass(cn->tp);
                   1859:                if (cl == cc->cot) {
                   1860:                        n_qualifier = 0;
                   1861:                        goto xdr;
                   1862:                }
                   1863:                else if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) {
                   1864:                        error("C%nU",cn);
                   1865:                        Cdcl = odcl;
                   1866:                        return 0;
                   1867:                }
                   1868:                else if (cl->c_body==1) //III
                   1869:                        cl->dcl_print(0);
                   1870: 
                   1871:                Ptable etbl = cl->memtbl;
                   1872:                Pname x = etbl->look(string,0);
                   1873:                if (x==0 || x->n_table!=etbl) {
                   1874:                        error("%n is not aM of%n",this,cn);
                   1875:                        Cdcl = odcl;
                   1876:                        return 0;
                   1877:                }
                   1878: 
                   1879:                if (tp->base == FCT) {  //III
                   1880:                //      if (friend_in_class==0 && Pfct(tp)->body==0) {  // c::f(); needed for friend
                   1881:                        if (friend_in_class==0
                   1882:                        && n_sto!=FRIEND
                   1883:                        && Pfct(tp)->body==0) { // c::f(); needed for friend
                   1884:                                error("QdN%n inFD",x);
                   1885:                                Cdcl = odcl;
                   1886:                                return 0;
                   1887:                        }
                   1888: 
                   1889:                        if (Pfct(tp)->body==0) {
                   1890:                                Pfct(tp)->memof = cl;
                   1891:                                int xx;
                   1892:                                if (x->tp->base==OVERLOAD)
                   1893:                                        xx = Pgen(x->tp)->find(Pfct(tp),0)==0;
                   1894:                                else
                   1895:                                        xx = x->tp->check(tp,0);
                   1896: 
                   1897:                                if (xx) {
                   1898:                                        error("%n is not aM of%n",this,cn);
                   1899:                                        Cdcl = odcl;
                   1900:                                        return 0;
                   1901:                                }
                   1902:                        }
                   1903:                }
                   1904:                else {
                   1905:                        if (x->n_stclass != STATIC) {   // e.g. int c::i = 7
                   1906:                                error("D of non staticCM %n",this);
                   1907:                                Cdcl = odcl;
                   1908:                                return 0;
                   1909:                        }
                   1910:                        if (n_sto) error("staticCM declared%k",n_sto);
                   1911:                        tbl = etbl;
                   1912:                }
                   1913:        }
                   1914: xdr:
                   1915:        if (n_oper
                   1916:        && tp->base!=FCT
                   1917:        && n_sto!=OVERLOAD) error("operator%k not aF",n_oper);
                   1918: 
                   1919: 
                   1920:        /*      if a storage class was specified
                   1921:                        check that it is legal in the scope 
                   1922:                else
                   1923:                        provide default storage class
                   1924:                some details must be left until the type of the object is known
                   1925:        */
                   1926: 
                   1927:        n_stclass = n_sto;
                   1928:        n_scope = scope;        /* default scope & storage class */
                   1929: 
                   1930:        switch (n_sto) {
                   1931:        default:
                   1932:                error('i',"unX %k",n_sto);
                   1933:        case FRIEND:
                   1934:        {
                   1935:                Pclass cl = cc->cot;
                   1936: 
                   1937:                switch (scope) {
                   1938:                case 0:
                   1939:                case PUBLIC:
                   1940:                        break;
                   1941:                default:
                   1942:                        error("friend%n not inCD(%k)",this,scope);
                   1943:                        base = 0;
                   1944:                        Cdcl = odcl;
                   1945:                        return 0;
                   1946:                }
                   1947: 
                   1948:                switch (n_oper) {
                   1949:                case 0:
                   1950:                case NEW:
                   1951:                case DELETE:
                   1952:                case CTOR:
                   1953:                case DTOR:
                   1954:                case TYPE:
                   1955:                        n_sto = 0;
                   1956:                        break;
                   1957:                default:
                   1958:                        n_sto = OVERLOAD;
                   1959:                }
                   1960: 
                   1961:                switch (tx->base) {
                   1962:                case COBJ:
                   1963:                        nn = Pbase(tx)->b_name;
                   1964:                        break;
                   1965:                case CLASS:
                   1966:                        nn = this;
                   1967:                        break;
                   1968:                case FCT:
                   1969:                        cc->stack();
                   1970:                        cc->not = 0;
                   1971:                        cc->tot = 0;
                   1972:                        cc->cot = 0;
                   1973:                        friend_in_class++;
                   1974:                //      n_sto = EXTERN;
                   1975:                        n_sto = 0;
                   1976:                        nn = dcl(gtbl,EXTERN);
                   1977:                        if (nn == 0) {
                   1978:                                Cdcl = odcl;
                   1979:                                return 0;
                   1980:                        }
                   1981:                        friend_in_class--;
                   1982:                        cc->unstack();
                   1983:                        if (nn->tp->base == OVERLOAD) nn = Pgen(nn->tp)->find(Pfct(tx),1);
                   1984:                        break;
                   1985:                default:
                   1986:                        error("badT%tof friend%n",tp,this);
                   1987:                        Cdcl = odcl;
                   1988:                        return 0;
                   1989:                }
                   1990:                PERM(nn);
                   1991:                cl->friend_list = new name_list(nn,cl->friend_list);
                   1992:                Cdcl = odcl;
                   1993:                return nn;
                   1994:        }
                   1995:        case OVERLOAD:
                   1996:                if (strict_opt||warning_opt)
                   1997:                        error(strict_opt?0:'w',"`overload' used (anachronism)");
                   1998:                n_sto = 0;
                   1999:                // ignore overload!
                   2000:                switch (tp->base) {
                   2001:                case FCT:
                   2002:                        break;
                   2003:                default:
                   2004:                        base = 0;
                   2005:                        Cdcl = odcl;
                   2006:                        return this;
                   2007:                }
                   2008:                break;
                   2009:        case REGISTER:
                   2010:                if (tp->base == FCT) {
                   2011:                        error('w',"%n: register (ignored)",this);
                   2012:                        goto ddd;
                   2013:                }
                   2014:        case AUTO:
                   2015:                switch (scope) {
                   2016:                case 0:
                   2017:                case PUBLIC:
                   2018:                case EXTERN:
                   2019:                        error("%k not inF",n_sto);
                   2020:                        goto ddd;
                   2021:                }
                   2022:                if (n_sto==AUTO) n_sto = 0;     // always redundant
                   2023:                break;
                   2024:        case EXTERN:
                   2025:                switch (scope) {
                   2026:                case ARG:
                   2027:                        //error("externA");
                   2028:                        goto ddd;
                   2029:                case 0:
                   2030:                case PUBLIC:
                   2031:                        /* extern is provided as a default for functions without body */
                   2032:                        if (tp->base != FCT) error("externM%n",this);
                   2033:                        goto ddd;
                   2034:                case FCT:
                   2035:                        {
                   2036:                        Pname nn = gtbl->look( string, 0 );
                   2037:                        tp->dcl(tbl);
                   2038:                        if ( nn && tp->base != FCT &&
                   2039:                                tp->check(nn->tp,0)) 
                   2040:                                {
                   2041:                                error("twoDs of%n;Ts:%t and%t",this,nn->tp,tp);
                   2042:                                Cdcl = odcl;
                   2043:                                return 0;
                   2044:                                }
                   2045:                        }
                   2046:                }
                   2047:                n_stclass = STATIC;
                   2048:                n_scope = EXTERN;       /* avoid FCT scoped externs to allow better checking */
                   2049:                break;
                   2050:        case STATIC:
                   2051:                switch (scope) {
                   2052:                case ARG:
                   2053:                        //error("static used forA%n",this);
                   2054:                        goto ddd;
                   2055:                case 0:
                   2056:                case PUBLIC:
                   2057:                        n_stclass = STATIC;
                   2058:                        n_scope = scope;
                   2059:                        break;
                   2060:                default:
                   2061:                        n_scope = STATIC;
                   2062:                }
                   2063:                break;
                   2064:        case 0:
                   2065:        ddd:
                   2066:                switch (scope) {        /* default storage classes */
                   2067:                case EXTERN:
                   2068:                        n_scope = EXTERN;
                   2069:                        n_stclass = STATIC;
                   2070:                        break;
                   2071:                case FCT:
                   2072:                        if (tp->base == FCT) {
                   2073:                                n_stclass = STATIC;
                   2074:                                n_scope = EXTERN;
                   2075:                        }
                   2076:                        else
                   2077:                                n_stclass = AUTO;
                   2078:                        break;
                   2079:                case ARG:
                   2080:                        n_stclass = AUTO;
                   2081:                        break;
                   2082:                case 0:
                   2083:                case PUBLIC:
                   2084:                        n_stclass = 0;
                   2085:                        break;
                   2086:                }
                   2087:        }
                   2088: 
                   2089:        
                   2090:        /*
                   2091:                now insert the name into the appropriate symbol table,
                   2092:                and compare types with previous declarations of that name
                   2093: 
                   2094:                do type dependent adjustments of the scope
                   2095:        */
                   2096: //error('d',"sw %d",tx->base);
                   2097:        static int warn_ldouble=0;
                   2098: 
                   2099:        switch (tx->base) {
                   2100:        case ASM:
                   2101:        {       Pbase b = Pbase(tp);
                   2102:                Pname n = tbl->insert(this,0);
                   2103:                n->assign();
                   2104:                n->use();
                   2105:                char* s = (char*) b->b_name;    // save asm string. Shoddy
                   2106:                int ll = strlen(s);
                   2107:                char* s2 = new char[ll+1];
                   2108:                strcpy(s2,s);
                   2109:                b->b_name = Pname(s2);
                   2110:                Cdcl = odcl;
                   2111:                return this;
                   2112:        }
                   2113: 
                   2114:        case CLASS:
                   2115:                tp = tx;
                   2116:                nn = dclass(this,tbl);
                   2117:                Cdcl = odcl;
                   2118:                return nn;
                   2119: 
                   2120:        case ENUM:
                   2121:                tp = tx;
                   2122:                nn = denum(this,tbl);
                   2123:                Cdcl = odcl;
                   2124:                return nn;
                   2125:        
                   2126:        case FCT:
                   2127:                tp = tx;
                   2128:                nn = dofct(tbl,scope);
                   2129:                if (nn == 0) {
                   2130:                        Cdcl = odcl;
                   2131:                        return 0;
                   2132:                }
                   2133: 
                   2134: // error('d', "%s n_oper: %k, scope: %k", string, n_oper, scope );
                   2135:                if (pdef_name == 0) check_def_name(nn, scope);
                   2136:                break;
                   2137: 
                   2138:        case FIELD:
                   2139:                switch (n_stclass) {
                   2140:                case 0:
                   2141:                case PUBLIC:
                   2142:                        break;
                   2143:                default:
                   2144:                        error("%k field",n_stclass);
                   2145:                        n_stclass = 0;
                   2146:                }
                   2147: 
                   2148:                if (cc->not==0 || cc->cot->csu==UNION || cc->cot->csu==ANON) {
                   2149:                        error(cc->not?"field in union":"field not inC");
                   2150:                        PERM(tp);
                   2151:                        Cdcl = odcl;
                   2152:                        return this;
                   2153:                }
                   2154: 
                   2155:                if (string) {
                   2156:                        nn = tbl->insert(this,0);
                   2157:                        n_table = nn->n_table;
                   2158:                        if (Nold) error("twoDs of field%n",this);
                   2159:                }
                   2160: 
                   2161:                tp->dcl(tbl);
                   2162:                field_align();
                   2163:                break;
                   2164:        
                   2165:        case COBJ:
                   2166:        {       Pclass cl = Pclass(Pbase(tx)->b_name->tp);
                   2167: //error('d',&where,"dcl %n; tx->base == cobj",this);
                   2168:                if (cl->lex_level > lex_level) 
                   2169:                        error("C%t is not visible in this scope",cl);
                   2170: 
                   2171:                if (cl->csu == ANON) {  // export member names to enclosing scope
                   2172:                         if (tbl==gtbl && n_sto!=STATIC) error("extern anonymous union (declare as static)");
                   2173:                        char* p = cl->string;
                   2174:                        while (*p++ != 'C');    /* sneaky */
                   2175:                        int uindex = (int)str_to_long(p);
                   2176: 
                   2177: // error('d', "%n->dcl() n_scope: %k n_protect: %k", this, n_scope, n_protect );
                   2178:                // cannot cope with use counts for ANONs:
                   2179:                        Pbase(tp)->b_name->n_used = 1;
                   2180:                        Pbase(tp)->b_name->n_assigned_to = 1;
                   2181: 
                   2182:                        Ptable mtbl = cl->memtbl;
                   2183:                         int i, err_msg = 0;
                   2184:                        for (Pname nn=mtbl->get_mem(i=1); nn; nn=mtbl->get_mem(++i)) {
                   2185:                                if (nn->tp->base == FCT) {
                   2186:                                        error("FM%n for anonymous union",nn);
                   2187:                                        break;
                   2188:                                }
                   2189:                                Ptable tb = nn->n_table;
                   2190:                                nn->n_table = 0;
                   2191:                                nn->n_scope = n_protect?n_protect:n_scope; 
                   2192:                                Pname n = tbl->insert(nn,0);
                   2193:                                if (Nold) {
                   2194:                                        error("twoDs of%n (one in anonymous union)",nn);
                   2195:                                        break;
                   2196:                                }
                   2197: 
                   2198:                                Pclass tc;
                   2199:                                if (tc = cl->in_class) 
                   2200:                                        --n->lex_level;
                   2201:                                if ( tc && tc->csu == ANON) {
                   2202: //error('d', "tc->csu anon %k %s", tc->csu, string );
                   2203:                                        if ( n->n_anon ) {
                   2204:                                                if ( !err_msg ) 
                   2205:                                                        error('s', "anonymous unions nested deeper than 2 levels" );
                   2206:                                                err_msg = 1;
                   2207:                                        }
                   2208:                                        n->n_anon = string;
                   2209:                                }
                   2210: 
                   2211:                                n->n_union = uindex;
                   2212:                                nn->n_table = tb;
                   2213:                        }
                   2214:                }
                   2215:                if (cl->c_abstract) error("D ofO of abstractC%t",cl);
                   2216:                goto cde;
                   2217:        }
                   2218: 
                   2219:        case VOID:
                   2220:                if (n_scope != ARG) {
                   2221:                        error("badBT:%k%n",tx->base,this);
                   2222:                        Cdcl = odcl;
                   2223:                        return 0;
                   2224:                }
                   2225:                break;
                   2226: 
                   2227:        case LDOUBLE:
                   2228:                 if (warn_ldouble==0 && ansi_opt==0) {
                   2229:                         ++warn_ldouble;
                   2230:                         error('w',"long double supported under ``+a1'' option only, generating ``double%n''", this);
                   2231:                 }
                   2232:                goto cde;
                   2233: 
                   2234:        case PTR:
                   2235:        case VEC:
                   2236:        case RPTR:
                   2237:                tp->dcl(tbl);
                   2238: 
                   2239:        default:
                   2240:        cde:
                   2241: //error('d',"cde: %n %t",this,tp);
                   2242:                nn = tbl->insert(this,0);
                   2243:                n_table = nn->n_table;
                   2244: 
                   2245:                if (Nold) {
                   2246: 
                   2247:                        if ( nn->base == PUBLIC ) { // X::i
                   2248:                                error("twoDs ofCM%n", nn);
                   2249:                                Cdcl = odcl;
                   2250:                                return 0;
                   2251:                        }
                   2252: 
                   2253:                        if (nn->tp->base == ANY) goto zzz;
                   2254: 
                   2255:                        if (tp->check(nn->tp,0)) {
                   2256:                                error("twoDs of%n;Ts:%t and%t",this,nn->tp,tp);
                   2257:                                Cdcl = odcl;
                   2258:                                return 0;
                   2259:                        }
                   2260: //error('d',"%n: %k %k scope %k",this,n_sto,nn->n_sto,nn->n_scope);
                   2261:                        if (n_sto && n_sto!=nn->n_scope) {
                   2262:                                if (n_sto==EXTERN && nn->n_scope==STATIC) {
                   2263:                                        error('w',"%n declared extern after being declared static",this);
                   2264:                                        goto ext_fudge;
                   2265:                                }
                   2266:                                else
                   2267:                                        error("%n declared as both%k and%k",this,n_sto,(nn->n_sto)?nn->n_sto:(scope==FCT?AUTO:EXTERN));
                   2268:                        }
                   2269:                        else if (nn->n_scope==STATIC && n_scope==EXTERN) {
                   2270:                                error('w',"static%n followed by definition",this);
                   2271:                        ext_fudge:
                   2272:                                if (n_initializer) {
                   2273: //                                     error('d',"static%n redefined (WIr)",this);
                   2274:                                        n_initializer = 0;
                   2275:                                }
                   2276:                                n_sto = EXTERN;
                   2277:                        }
                   2278:                        else if (nn->n_sto==STATIC && n_sto==STATIC ) 
                   2279:                                error("static%n declared twice",this);
                   2280:                        else {
                   2281:                                if (n_sto==0
                   2282:                                && nn->n_sto==EXTERN
                   2283:                                && n_initializer
                   2284:                                && tp->tconst())
                   2285:                                        n_sto = EXTERN;
                   2286:                                n_scope = nn->n_scope;
                   2287: 
                   2288:                                switch (scope) {
                   2289:                                case FCT:
                   2290:                                        if (n_sto != EXTERN) {
                   2291:                                                error("twoDs of%n",this);
                   2292:                                                Cdcl = odcl;
                   2293:                                                return 0;
                   2294:                                        }
                   2295:                                        break;
                   2296:                                case ARG:
                   2297:                                        error("twoAs%n",this);
                   2298:                                        Cdcl = odcl;
                   2299:                                        return 0;
                   2300:                                case 0:
                   2301:                                case PUBLIC:
                   2302:                                        error("twoDs ofM%n",this);
                   2303:                                        Cdcl = odcl;
                   2304:                                        return 0;
                   2305:                                case EXTERN:
                   2306:                                        if (n_sto==0) {
                   2307:                                                switch(nn->n_sto) {
                   2308:                                                case 0:
                   2309:                                                        error("two definitions of%n",this);
                   2310:                                                        Cdcl = odcl;
                   2311:                                                        return 0;
                   2312:                                                case EXTERN:
                   2313:                                                        if(nn->n_initializer) {
                   2314:                                                                error("two definitions of%n",this);
                   2315:                                                                Cdcl = odcl;
                   2316:                                                        }
                   2317:                                                        else
                   2318:                                                                nn->n_sto=0;
                   2319:                                                        break;
                   2320:                                                }
                   2321:                                        }
                   2322:                                        else if(n_sto==EXTERN && n_initializer) {
                   2323:                                                switch(nn->n_sto) {
                   2324:                                                case 0:
                   2325:                                                        error("two definitions of%n",this);
                   2326:                                                        Cdcl = odcl;
                   2327:                                                        return 0;
                   2328:                                                case EXTERN:
                   2329:                                                        nn->n_sto=0;
                   2330:                                                        break;
                   2331:                                                }
                   2332:                                        }
                   2333:                                        break;
                   2334:                                }
                   2335:                        }
                   2336:                        n_scope = nn->n_scope;
                   2337: /* n_val */
                   2338:                        if (n_initializer) {
                   2339:                                if (nn->n_initializer || nn->n_val) error("twoIrs for%n",this);
                   2340:                                nn->n_initializer = n_initializer;
                   2341:                        }
                   2342:                        if (tp->base == VEC) {
                   2343:                        //      handle:  extern v[]; v[200];
                   2344:                        //      and     extern u[10]; u[11];
                   2345: 
                   2346:                                Ptype ntp = nn->tp;
                   2347:                                while (ntp->base == TYPE) ntp = Pbase(ntp)->b_name->tp;
                   2348:                                if (Pvec(ntp)->dim == 0) Pvec(ntp)->dim = Pvec(tp)->dim;
                   2349:                                if (Pvec(ntp)->size) {
                   2350:                                        if (Pvec(tp)->size
                   2351:                                        && Pvec(ntp)->size!=Pvec(tp)->size)
                   2352:                                                error("bad array size for%n: %d %dX",this,Pvec(tp)->size,Pvec(ntp)->size);
                   2353:                                }
                   2354:                                else
                   2355:                                        Pvec(ntp)->size = Pvec(tp)->size;
                   2356:                        }
                   2357:                }
                   2358:                else {
                   2359: //error('d',"%n %t scope %d sto %k",this,tp,scope,n_sto);              
                   2360:                        if (scope!=ARG
                   2361:                        && n_sto!=EXTERN
                   2362:                        && (!((scope==0 || scope==PUBLIC) && n_sto==STATIC)) // static member
                   2363:                        && n_initializer==0
                   2364:                        && tp->base==VEC
                   2365:                        && Pvec(tp)->size==0)
                   2366:                                error(&where,"dimension missing for array%n",this);
                   2367: 
                   2368:                        if (scope==EXTERN
                   2369:                        && n_sto==0
                   2370:                        && tp->tconst()
                   2371:                        && vec_const==0
                   2372:                        && fct_const==0)
                   2373:                                nn->n_sto = n_sto = STATIC;
                   2374:                }
                   2375:        
                   2376:        zzz:
                   2377:                if (base != TNAME) {
                   2378:                        Ptype t = nn->tp;
                   2379: 
                   2380:                        if (t->base == TYPE) {
                   2381:                                Ptype tt = Pbase(t)->b_name->tp;
                   2382:                                if (tt->base == FCT) nn->tp = t = tt;
                   2383:                        }
                   2384: 
                   2385:                        switch (t->base) {
                   2386:                        case FCT:
                   2387:                        case OVERLOAD:
                   2388:                                break;
                   2389:                        default:
                   2390:                                fake_sizeof = 1;
                   2391:                                switch (nn->n_stclass) {
                   2392:                                default:
                   2393:                                        if (nn->n_scope != ARG) {
                   2394:                                                int x = t->align();
                   2395:                                                int y = t->tsizeof();
                   2396: 
                   2397:                                                if (max_align < x) max_align = x;
                   2398: 
                   2399:                                                while (0 < bit_offset) {
                   2400:                                                        byte_offset++;
                   2401:                                                        bit_offset -= BI_IN_BYTE;
                   2402:                                                }
                   2403:                                                bit_offset = 0;
                   2404: 
                   2405:                                                if (byte_offset && 1<x) byte_offset = ((byte_offset-1)/x)*x+x;
                   2406:                                                nn->n_offset = byte_offset;
                   2407:                                                byte_offset += y;
                   2408:                                        }
                   2409:                                        break;
                   2410:                                case STATIC:
                   2411:                                        if (n_sto != EXTERN
                   2412:                                        && nn->n_scope
                   2413:                                        && nn->n_scope!=PUBLIC)
                   2414:                                        t->tsizeof();   // check that size is known
                   2415:                                }
                   2416:                                fake_sizeof = 0;
                   2417:                        }
                   2418:                }
                   2419: 
                   2420:        {       Ptype t = nn->tp;
                   2421:                int const_old = const_save;
                   2422:                bit vec_seen = 0;
                   2423:                Pexpr init = n_initializer;
                   2424: 
                   2425:        lll:
                   2426: // error('d',"lll %n %t init %d %k",this,t,init,init?init->base:0);
                   2427:                switch (t->base) {
                   2428:                case COBJ:
                   2429:                {       Pname cn = Pbase(t)->b_name;
                   2430:                        Pclass cl = (Pclass)cn->tp;
                   2431:                        Pname ctor = cl->has_ctor();
                   2432:                        Pname dtor = cl->has_dtor();
                   2433:                        int stct = 0;
                   2434: //error('d',"obj %n; class '%s'; ctor '%s'; dtor '%s'",nn,cn->string,ctor?ctor->string:"???",dtor?dtor->string:"???");
                   2435:                        if (dtor) {
                   2436:                                Pstmt dls;
                   2437: 
                   2438:                                // if dtor is not public check scope of class object
                   2439: 
                   2440: //error('d',"dcl %n has dtor",nn);
                   2441:                                if (dtor->n_scope != PUBLIC)  {
                   2442: //error('d',"dcl %n->n_scope: %d fct %n",nn,nn->n_scope,cc->nof);
                   2443:                                        switch (nn->n_scope) {
                   2444:                                        case ARG:
                   2445:                                        case 0:
                   2446:                                        case PUBLIC:
                   2447:                                                break;
                   2448:                                        default: 
                   2449:                                                check_visibility( dtor, 0, cl, tbl, cc->nof );
                   2450:                                        }
                   2451:                        //              if (nn->n_scope == FCT) 
                   2452:                        //                      check_visibility( dtor, 0, cl, tbl, cc->nof );
                   2453:                        //              else if ( nn->n_sto != EXTERN )
                   2454:                        //                      error("%k%n cannot access%n: %sM",nn->n_scope,nn,dtor,dtor->n_protect?"protected":"private");
                   2455:                                }
                   2456: 
                   2457:                                switch ( nn->n_scope ) {
                   2458:                                case 0:
                   2459:                                case PUBLIC:
                   2460:                                        if (n_stclass==STATIC) { //III
                   2461:                                                Pclass cl = Pclass(nn->n_table->t_name->tp);
                   2462:                                                if (cl->defined&DEFINED) goto dtdt;
                   2463:                                        }
                   2464:                                        break;
                   2465:                                case EXTERN:
                   2466:                                        if (n_sto==EXTERN) break;
                   2467: 
                   2468:                                case STATIC:
                   2469:                                {       Pexpr c;
                   2470:                                dtdt:
                   2471: // local static class objects have destructors set up in simpl2.c
                   2472: // special case: temporary class object generated in init expression
                   2473:                                        if (stat_init && scope == ARGS ) {
                   2474:                                                nn->n_scope = ARGS;
                   2475:                                                goto ggg;
                   2476:                                        }
                   2477: 
                   2478:                                        if ( nn->lex_level
                   2479:                                        &&   nn->n_sto == STATIC ) {
                   2480:                                                if (ctor==0) 
                   2481:                                                    error('s',"local static%n has%n but noK(add%n::%n())", nn, dtor, cn, cn );
                   2482:                                                goto static_init;
                   2483:                                        }
                   2484: 
                   2485:                                        Ptable otbl = tbl;
                   2486:                                            // to collect temporaries generated
                   2487:                                            // in static destructors where we
                   2488:                                            // can find them again (in std_tbl)
                   2489:                                        if (std_tbl == 0) std_tbl = new table(8,gtbl,0);
                   2490:                                        tbl = std_tbl;
                   2491:                                        if (vec_seen) {
                   2492:                                                c = cdvec(vec_del_fct,nn,cl,dtor,0,zero);
                   2493:                                        } else {        // nn->cl::~cl(0);
                   2494:                                                c = call_dtor(nn,dtor,0,DOT,one);
                   2495:                                        }
                   2496:                                        c->tp = any_type; // avoid another check
                   2497:                                        dls = new estmt(SM,nn->where,c,0);
                   2498:                                        
                   2499:                                        // destructors for statics are executed in reverse order
                   2500:                                        if (st_dlist) dls->s_list = st_dlist;
                   2501:                                        st_dlist = dls;
                   2502:                                        tbl = otbl;
                   2503:                                } // case STATIC
                   2504:                                } // switch nn->n_scope
                   2505:                        } // if dtor
                   2506: 
                   2507: // local static class objects must defer setting up static dtor
                   2508: static_init:
                   2509:                        if (ctor) {
                   2510: // error('d',"ctor %n scope %k",ctor,nn->n_scope);
                   2511:                                Pexpr oo = nn;
                   2512:                                for (int vi=vec_seen; vi; vi--) oo = oo->contents();
                   2513:                                int sti = 0;
                   2514:                                switch (nn->n_scope) {
                   2515:                                case EXTERN:
                   2516:                                        if (init==0 && n_sto==EXTERN) goto ggg;
                   2517:                                case STATIC:
                   2518:                                        if (tbl == gtbl)
                   2519:                                                sti = 1;
                   2520:                                        else
                   2521:                                                stct = 1;
                   2522:                                default:
                   2523:                                        if (vec_seen && init) {
                   2524:                                                if (1<vec_seen) {
                   2525: /* ?????
                   2526:                                                        if (init->base != ILIST)
                   2527:                                                                error("badIr forO ofC %t withK%n",cl,this);
                   2528:                                                        else
                   2529: */
                   2530:                                                                error('s',"Ir for multi-dimensional array%n ofOsofC %t withK",this,cl);
                   2531:                                                        }
                   2532:                                                else {
                   2533:                                                        if (sti) {
                   2534:                                                                if (sti_tbl==0) sti_tbl = new table(8,gtbl,0);
                   2535:                                                                const_save = 1;
                   2536:                                                                (void) co_array_init(nn,sti_tbl);
                   2537:                                                                const_save = 0;
                   2538:                                                                n_initializer = init = 0;
                   2539:                                                        }
                   2540:                                                        else {
                   2541:                                                                n_initializer = init = co_array_init(nn,tbl);
                   2542:                                                                if (stct)  
                   2543:                                                                        nn->n_initializer = n_initializer = init = new expr( STAT_INIT, init, 0 );
                   2544:                                                        }
                   2545:                                                }
                   2546:                                                goto ggg;
                   2547:                                        }
                   2548:                                        break;
                   2549:                                case PUBLIC:
                   2550:                                case 0:
                   2551:                                        if (n_stclass==STATIC) { //III
                   2552:                                                Pclass cl = Pclass(nn->n_table->t_name->tp);
                   2553:                                                if (cl->defined&DEFINED) {
                   2554:                                                        sti = 1;
                   2555:                                                        break;
                   2556:                                                }
                   2557:                                        }
                   2558:                                        {
                   2559:                                                Pname c;
                   2560:                                                if (vec_seen) {
                   2561:                                                        c = cl->has_ictor();
                   2562:                                                        if (c == 0)
                   2563:                                                                error("array ofC%n that does not have aK taking noAs",cn);
                   2564:                                                        else if (Pfct(c->tp)->nargs)
                   2565:                                                                error("defaultAs forK for array ofC%n",cn);
                   2566:                                                }
                   2567:                                        }
                   2568:                                        // no break
                   2569:                                case ARG:
                   2570:                                        goto ggg;
                   2571:                                }
                   2572: 
                   2573:                                const_save = 1;
                   2574:                                nn->assign();
                   2575:                                Ptable otbl = tbl;
                   2576:                                if (sti) {      // to collect temporaries generated
                   2577:                                                // in static initializers where we
                   2578:                                                // can find them again (in sti_tbl)
                   2579:                                        if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0);
                   2580:                                        tbl = sti_tbl;
                   2581:                                        if (n_sto == EXTERN) nn->n_sto = n_sto = 0;
                   2582:                                }
                   2583: 
                   2584:                                if (init) {
                   2585: // error('d',"init %k",init->base);
                   2586:                                        if (init->base==VALUE) {
                   2587:                                                switch (init->tp2->base) {
                   2588:                                                case CLASS:
                   2589: // error('d',"class %t %t",Pclass(init->tp2),cl);
                   2590:                                                        if (Pclass(init->tp2)!=cl) goto inin;
                   2591:                                                        break;
                   2592:                                                default:
                   2593:                                                        Pname  n2 = init->tp2->is_cl_obj();
                   2594: // error('d',"default %t %t",n2->tp,cl);
                   2595:                                                        if (n2==0 || Pclass(n2->tp)!=cl) goto inin;
                   2596:                                                }
                   2597: 
                   2598:                                                Pexpr ee = init->e1;
                   2599: // error('d',"init->e1 %k",ee->base);
                   2600:                                                if (ee && vec_seen==0)
                   2601:                                                switch (ee->base) {
                   2602:                                                case CALL:      // T a = f();
                   2603:                                                        init = ee;
                   2604:                                                        goto inin;
                   2605:                                                case ELIST:     // T a(f());
                   2606:                                                        if (ee->e1->base==CALL
                   2607:                                                        && ee->e2 == 0) {
                   2608:                                                                init = ee->e1;
                   2609:                                                                goto inin;
                   2610:                                                        }
                   2611:                                                } // end switch
                   2612: 
                   2613:                                                init->e2 = oo;
                   2614:                                                init = init->typ(tbl);
                   2615: 
                   2616:                                                if (init->base == G_CM) // beware of type conversion operators
                   2617:                                                switch (init->tp2->base) {
                   2618:                                                case CLASS:
                   2619:                                                        if (Pclass(init->tp2)!=cl) goto inin;
                   2620:                                                        break;
                   2621:                                                default:
                   2622:                                                        Pname  n2 = init->tp2->is_cl_obj();
                   2623:                                                        if (n2==0 || Pclass(n2->tp)!=cl) goto inin;
                   2624:                                                }
                   2625:                                        }
                   2626:                                        else {
                   2627:                                        inin:
                   2628: // error('d',"inin %k",init->base);
                   2629:                                                init = init->typ(tbl);
                   2630: //error('d', "inin: init->typ: %d %k n->tp %t init->tp %t",init->base,init->base,nn->tp,init->tp);
                   2631:                                                if (init->base==G_CM
                   2632:                                                && nn->tp->check(init->tp,0)==0)
                   2633:                                                        (void) replace_temp(init,nn->address());
                   2634:                                                else
                   2635:                                                        init = class_init(nn,nn->tp,init,tbl);
                   2636:                                        }
                   2637:                                }
                   2638:                                else if (vec_seen == 0) {
                   2639: //error('d',"make value");
                   2640:                                        init = new texpr(VALUE,cl,0);
                   2641:                                        init->e2 = oo;
                   2642:                                        init = init->typ(tbl);
                   2643:                                }
                   2644: 
                   2645:                                Pname c;
                   2646:                                if (vec_seen) {
                   2647:                                        c = cl->has_ictor();
                   2648:                                        if (c == 0)
                   2649:                                                error("array ofC%n that does not have aK taking noAs",cn);
                   2650:                                        else if (Pfct(c->tp)->nargs)
                   2651:                                                error("defaultAs forK for array ofC%n",cn);
                   2652:                                }
                   2653: 
                   2654: // error( 'd', "stct: %d init: %d", stct, init );
                   2655:                                if (stct) {
                   2656:                                        if (tbl!=gtbl && nn->n_sto==EXTERN) {
                   2657:                                                error(&where,"Id local extern%n",this);
                   2658:                                                init = 0;
                   2659:                                        }
                   2660:                                        else if (init) 
                   2661:                                                init->base = STAT_INIT;
                   2662:                                        else {
                   2663:                                                if (tp->base == VEC && Pvec(tp)->size ) {
                   2664:                                                        Pexpr ilist = 0;
                   2665:                                                        for (int i=Pvec(tp)->size; i>0; i--) {
                   2666:                                                                Pexpr e = new texpr(VALUE,cl,0);
                   2667:                                                                ilist = new expr(ELIST, e, ilist);
                   2668:                                                        }
                   2669:                                                        nn->n_initializer=new expr(ILIST,ilist,0);
                   2670:                                                        init = co_array_init(nn,tbl);
                   2671:                                                        nn->n_initializer = n_initializer = init = new expr( STAT_INIT, init, 0 );
                   2672:                                                }
                   2673:                                                else
                   2674:                                                error('s',"local staticC%n (%t)",this, tp);
                   2675:                                        }
                   2676:                                }
                   2677: 
                   2678: // error('d', "%n->sti: %d vec_seen: %d n_stclass: %k", this, sti, vec_seen, n_stclass );
                   2679:        if (sti) {
                   2680:                if (vec_seen) { // _vec_new(vec,noe,sz,ctor);
                   2681: // error('d', "%n->dcl: n_stclass: %k ", this, n_stclass );
                   2682:                        if ( n_stclass == STATIC && n_initializer ) {
                   2683:                                const_save = 1;
                   2684:                                (void) co_array_init(nn,sti_tbl);
                   2685:                                const_save = 0;
                   2686:                                n_initializer = init = 0;
                   2687:                                goto ggg;
                   2688:                        }
                   2689: 
                   2690:                        init = cdvec(vec_new_fct,nn,cl,c,-1,0);
                   2691:                        init->tp = any_type;
                   2692:                }
                   2693:                else {
                   2694:                        switch (init->base) {
                   2695:                        case DEREF:             // *constructor?
                   2696:                                if (init->e1->base == G_CALL) { 
                   2697:                                        Pname fn = init->e1->fct_name;
                   2698:                                        if (fn==0 || fn->n_oper!=CTOR) goto as;
                   2699:                                        init = init->e1;
                   2700:                                        break;
                   2701:                                }
                   2702:                                goto as;
                   2703:                        case G_CM:
                   2704:                                init = init->e1;
                   2705:                                        // suppress further type checking
                   2706:                                if (init->tp == 0) init->tp= any_type; 
                   2707:                                break;
                   2708:                        case ASSIGN:
                   2709:                                if (init->e1 == nn) break;      // simple assignment
                   2710:                        as:     
                   2711:                        default:        
                   2712:                                init = new expr(ASSIGN,nn,init);
                   2713:                        }
                   2714:                }
                   2715:                Pstmt ist = new estmt(SM,nn->where,init,0);
                   2716:                // constructors for statics are executed in order
                   2717:                if (st_ilist == 0)
                   2718:                        st_ilist = ist;
                   2719:                else
                   2720:                        itail->s_list = ist;
                   2721:                itail = ist;
                   2722:                init = 0;       // suppress further processing
                   2723:        } // if (sti)
                   2724:                                nn->n_initializer = n_initializer = init;
                   2725:                                const_save = const_old;
                   2726:                                tbl = otbl;
                   2727:                        }
                   2728:                        else if (init == 0)             // no initializer
                   2729:                                goto str;
                   2730:                        else if (cl->is_simple()
                   2731:                        //      && cl->csu!=UNION       // accept ANSIism
                   2732:                                && cl->csu!=ANON
                   2733:                                ) {     // struct
                   2734:                                init = init->typ(tbl);
                   2735:                                if (nn->tp->check(init->tp,0)==0
                   2736:                                && init->base==G_CM) 
                   2737:                                        (void) replace_temp(init,nn->address());
                   2738:                                else {
                   2739:                                        if (ansi_opt==0
                   2740:                                        && init->base==ILIST
                   2741:                                        && cl->csu==UNION)
                   2742:                                                error('s',"initialization of union withIL");
                   2743:                                        goto str;
                   2744:                                }
                   2745:                        }
                   2746:                        else if (init->base == ILIST) { // class or union
                   2747:                                error("cannotI%nWIrL",nn);
                   2748:                        }
                   2749:                        else {                  // bitwise copy ok?
                   2750:                                                // possible to get here?
                   2751:                                init = init->typ(tbl);
                   2752: //error('d',"init22 %t %t",nn->tp,init->tp);
                   2753:                                if (nn->tp->check(init->tp,0)==0) {
                   2754:                                        if (init->base==G_CM) 
                   2755:                                                (void) replace_temp(init,nn->address());
                   2756:                                        else
                   2757:                                                goto str;
                   2758:                                }
                   2759:                                goto str;
                   2760:                        //      else
                   2761:                        //              error("cannotI%n:%k %s has noK",nn,cl->csu,cl->string);
                   2762:                        }
                   2763:                        break;
                   2764:                }
                   2765:                case VEC:       
                   2766:                        t = Pvec(t)->typ;
                   2767:                        vec_seen++;
                   2768:                        goto lll;
                   2769:                case TYPE:
                   2770:                        if (init==0 && Pbase(t)->b_const) {
                   2771:                                switch (n_scope) {
                   2772:                                case ARG:
                   2773:                                        break;
                   2774:                                case 0:
                   2775:                                case PUBLIC:
                   2776:                                        if ( cc->cot ) break;
                   2777:                                default: {
                   2778:                                        Pname n = t->is_cl_obj();
                   2779:                                        Pclass cl;
                   2780:                                        if ( n ) cl = Pclass( n->tp );
                   2781: 
                   2782:                                        if (n_sto!=EXTERN && 
                   2783:                                           (n==0 || (cl->has_ctor()==0 && is_empty(cl,1)==0))) 
                   2784:                                                error("uninitialized const%n",this);
                   2785:                                        }
                   2786:                                }
                   2787:                        }
                   2788:                        t = Pbase(t)->b_name->tp;
                   2789:                        goto lll;
                   2790:                case RPTR:
                   2791:                        if (init) {
                   2792:                                if (nn->n_scope == ARG) break;
                   2793:                                if (Pptr(nn->tp)->memof) error("R toCM%n ofT%t illegal",nn,nn->tp);
                   2794:                                ref_initializer++;
                   2795:                                init = init->typ(tbl);
                   2796:                                ref_initializer--;
                   2797:                                Nvirt = 0; // set within ref_init() call
                   2798:                                const_ptr = Pbase(Pptr(t)->typ)->tconst(); 
                   2799: 
                   2800:                                if (n_sto==STATIC
                   2801:                                && init->lval(0)==0
                   2802:                                && fct_const==0)
                   2803:                                        error("Ir for staticR%n not an lvalue",this);
                   2804:                                else
                   2805:                                        nn->n_initializer = n_initializer = init = ref_init(Pptr(t),init,tbl);
                   2806: 
                   2807:                                const_ptr = 0;
                   2808:                                if (Nvirt == VIRTUAL) sti_vb = 1;
                   2809:                                nn->assign();
                   2810: 
                   2811:                                if (init->base==ILIST && init->e2==0) {
                   2812:                                        new_list(init);
                   2813:                                        list_check(nn,nn->tp,0,tbl);
                   2814:                                        if (next_elem()) error(&where,"IrL too long");
                   2815:                                }
                   2816: 
                   2817:                        }
                   2818:                        else {
                   2819:                                switch (nn->n_scope) {
                   2820:                                default:
                   2821:                                        if (n_sto == EXTERN) break;
                   2822:                                        error("uninitializedR%n",this);
                   2823:                                case ARG:
                   2824:                                        break;
                   2825:                                case PUBLIC:
                   2826:                                case 0:
                   2827:                        //III           if (n_sto == STATIC) error("a staticM%n cannot be aR",this);
                   2828: // error('d', "%n->dcl cot: %s", this, cc->cot?cc->cot->string:"notset");
                   2829:                                        if ( cc->cot == 0 )
                   2830:                                                error("uninitializedR%n",this);
                   2831:                                        break;
                   2832:                                }
                   2833:                        }
                   2834:                        goto stgg;
                   2835:                default:
                   2836:                str:
                   2837: // error('d',"str %n %t %k %t",this,tp,init?init->base:0,init?init->tp:0);
                   2838:                        if (init == 0) {
                   2839:                                switch (n_scope) {
                   2840:                                case ARG:
                   2841:                                        break;
                   2842:                                case 0:
                   2843:                                case PUBLIC:
                   2844:                                        if ( cc->cot ) break;
                   2845:                                default:
                   2846:                                        if (n_sto!=EXTERN && t->tconst()) error("uninitialized const%n",this);
                   2847:                                }
                   2848: 
                   2849:                                break;
                   2850:                        }
                   2851: 
                   2852:                        const_save =       const_save
                   2853:                                        || n_scope==ARG
                   2854:                                        || (t->tconst() && vec_const==0);
                   2855: 
                   2856:                        if ( tp->base == PTR ) {
                   2857:                                if ( cc && cc->nof 
                   2858:                                        && Pfct(cc->nof->tp)->f_const ) 
                   2859:                                                cm_const_save = Pbase(Pptr(tp)->typ)->b_const; 
                   2860:                                const_ptr = Pbase(Pptr(tp)->typ)->b_const; 
                   2861:                        }
                   2862: 
                   2863:                        if (n_sto==STATIC) stat_init++;
                   2864:                         nn->n_initializer = n_initializer = init = init->typ(tbl);
                   2865:                        if (n_sto==STATIC) stat_init--;
                   2866: 
                   2867:                        cm_const_save = 0;
                   2868:                        const_ptr = 0;
                   2869: 
                   2870:                        if (const_save) PERM(init);
                   2871:                        nn->assign();
                   2872:                        const_save = const_old;
                   2873: //error('d',"init2 %k %t",init->base,init->tp);
                   2874:                        switch (init->base) {
                   2875:                        case ILIST:
                   2876:                                if (init->e2) goto dfdf;//break; // pointer to member
                   2877:                                new_list(init);
                   2878:                                list_check(nn,nn->tp,0,tbl);
                   2879:                                if (next_elem()) error(&where,"IrL too long");
                   2880:                                break;
                   2881:                        case STRING:
                   2882:                        {       Ptype v = nn->tp;
                   2883:                                while (v->base == TYPE) v = Pbase(v)->b_name->tp;
                   2884:                                if (v->base==VEC) {
                   2885:                                        Ptype vv = Pvec(v)->typ;
                   2886:                                        while(vv->base==TYPE) vv = Pbase(vv)->b_name->tp;
                   2887:                                        if(vv->base==CHAR) {
                   2888:                                                int sz = Pvec(v)->size;
                   2889:                                                int isz = Pvec(init->tp)->size;
                   2890:                                                if (sz == 0)
                   2891:                                                        Pvec(v)->size = isz;
                   2892:                                                else if (sz < isz)
                   2893:                                                        error(&where,"Ir too long (%d characters) for%n[%d]",isz,nn,sz);
                   2894:                                                break;
                   2895:                                        }
                   2896:                                }
                   2897:                                // no break
                   2898:                        }
                   2899:                        default:
                   2900:                        dfdf:
                   2901:                        {       Ptype nt = nn->tp;
                   2902:                                int ntc = Pbase(nt)->b_const;
                   2903: 
                   2904:                                if (vec_seen) {
                   2905:                                        error("badIr for array%n",nn);
                   2906:                                        break;
                   2907:                                }
                   2908:                        tlx:
                   2909:                                switch (nt->base) {
                   2910:                                case TYPE:
                   2911:                                        nt = Pbase(nt)->b_name->tp;
                   2912:                                        ntc |= Pbase(nt)->b_const;
                   2913:                                        goto tlx;
                   2914:                                case INT:
                   2915:                                case CHAR:
                   2916:                                case SHORT:
                   2917:                                case EOBJ:
                   2918:                                //      if (init->base==ICON && init->tp==long_type)
                   2919:                                //              error('w',"longIr constant for%k%n",nn->tp->base,nn);
                   2920:                                {       Ptype t = init->tp;
                   2921:                                csi:
                   2922:                                        switch (t->base) {
                   2923:                                        case TYPE:
                   2924:                                                t = Pbase(t)->b_name->tp; goto csi;
                   2925:                                        case LONG:
                   2926:                                        case FLOAT:
                   2927:                                        case DOUBLE:
                   2928:                                        case LDOUBLE:
                   2929:                                                error('w',"%tIdW %t",nt,init->tp);
                   2930:                                        }
                   2931:                                }
                   2932:                                        // no break
                   2933:                                case LONG:
                   2934:                                        if (Pbase(nt)->b_unsigned
                   2935:                                        && init->base==UMINUS
                   2936:                                        && init->e2->base==ICON)
                   2937:                                                error('w',"negativeIr for unsigned%n",nn);
                   2938:                                        if (ntc && scope!=ARG) {
                   2939:                                                long i;
                   2940:                                                Neval = 0;
                   2941:                                                i = init->eval();
                   2942:                                                if (Neval == 0) {
                   2943:                                                        DEL(init);
                   2944:                                                        nn->n_evaluated = n_evaluated = 1;
                   2945:                                                        nn->n_val = n_val = i;
                   2946:                                                        DEL(init);
                   2947:                                                        nn->n_initializer = n_initializer = 0;
                   2948:                                                }
                   2949:                                        }
                   2950:                                        break;
                   2951:                                case PTR:
                   2952:                                        Nvirt = 0;
                   2953:                                        nn->n_initializer = n_initializer = init = ptr_init(Pptr(nt),init,tbl);
                   2954: //display_expr(init,string);
                   2955:                                        if (Nvirt == VIRTUAL) sti_vb = 1;
                   2956:                                        if (Pchecked) goto stgg;
                   2957:                                } 
                   2958: 
                   2959:                        {       Pexpr x = try_to_coerce(nt,init,"initializer",tbl);
                   2960:                                if (x) {
                   2961:                                        nn->n_initializer = n_initializer = init = x;
                   2962:                                        goto stgg;
                   2963:                                }
                   2964:                        }
                   2965: //error('d',"check %t %t %k",nt,init->tp,init->base);
                   2966:                //      if (nt->check(init->tp,ASSIGN)) {
                   2967:                                Pname c1 = nt->is_cl_obj();
                   2968:                                Pname c2 = init->tp->is_cl_obj();
                   2969:                                if (c1
                   2970:                                && c2
                   2971:                                && Pclass(c2->tp)->has_base(Pclass(c1->tp))) {
                   2972:                                        init = new texpr(CAST,new ptr(PTR,nt),init->address());
                   2973:                                        init = init->typ(tbl);
                   2974:                                        nn->n_initializer = n_initializer = init = init->contents();
                   2975:                                        goto stgg;
                   2976:                                }
                   2977: 
                   2978:                                if (nt->check(init->tp,ASSIGN)) {
                   2979:                                        error("badIrT%t for%n (%tX)",init->tp,this,nn->tp);
                   2980:                                        break;
                   2981:                                }
                   2982:                }
                   2983: 
                   2984:                stgg:
                   2985: // error('d',"stgg %n init %k %t Nvirt: %k",this,init?init->base:0,init?init->tp:0, Nvirt);
                   2986:                        if (init && n_stclass==STATIC && (sti_vb || need_sti(init))) {
                   2987:                                /* check if non-static variables are used */
                   2988:                                int local = (0<lex_level);
                   2989: // error('d',"init %n %t local %d",nn,init->tp,local);
                   2990:                                if (local==0) need_sti(init,tbl);       // save consts
                   2991: 
                   2992:                                Pptr r = nn->tp->is_ref();      //III
                   2993: 
                   2994:                                if (r) init = init->address();
                   2995:                                init = new expr(ASSIGN,nn,init);
                   2996: // error('d',"init r %t: nn %n %t init %t",r,nn,nn->tp,init->tp);
                   2997:                                if (r)
                   2998:                                        init->tp = nn->tp;
                   2999:                                else if (nn->tp!=init->tp) { // static member refs
                   3000:                                        TOK t = nn->tp->set_const(0);   //JJJ
                   3001:                                        init = init->typ(tbl);
                   3002:                                        nn->tp->set_const(t);           //JJJ
                   3003:                                }
                   3004: 
                   3005:                                if (local) {
                   3006:                                        if (init->base != ASSIGN) error('s',"Ir for local static too complicated");
                   3007:                                        if (nn->n_sto == EXTERN) {
                   3008:                                                error(&where,"Id local extern%n",this);
                   3009:                                                        init = 0;
                   3010:                                        }
                   3011:                                        else init->base = STAT_INIT;
                   3012:                                        nn->n_initializer = n_initializer = init;
                   3013:                                        
                   3014:                                }
                   3015:                                else {
                   3016:                                        Pstmt ist = new estmt(SM,nn->where,init,0);
                   3017:                                        // constructors for statics are executed in order
                   3018:                
                   3019:                                        if (st_ilist == 0)
                   3020:                                                st_ilist = ist;
                   3021:                                        else
                   3022:                                                itail->s_list = ist;
                   3023:                                        itail = ist;
                   3024:                                        nn->n_initializer = n_initializer = init = 0;   // suppress further processing
                   3025:                                        nn->n_val = n_val = 1;
                   3026:                                }
                   3027:                        }
                   3028:                        
                   3029:                
                   3030:                } /* switch */
                   3031:        } /* block */
                   3032:        } /* default */
                   3033: 
                   3034:        } /* switch */
                   3035: ggg:
                   3036: //error('d',"ggg");
                   3037:        PERM(nn);
                   3038:        switch (n_scope) {
                   3039:        case FCT:
                   3040:                nn->n_initializer = n_initializer;
                   3041:                break;
                   3042:        default:
                   3043:        {       Ptype t = nn->tp;
                   3044:        px:
                   3045:                PERM(t);
                   3046:                switch (t->base) {
                   3047:                case PTR:
                   3048:                case RPTR:
                   3049:                case VEC:       t = Pptr(t)->typ; goto px;
                   3050:                case TYPE:      t = Pbase(t)->b_name->tp; goto px;
                   3051:                case FCT:       t = Pfct(t)->returns; goto px; /* args? */
                   3052:                } 
                   3053:        }
                   3054:        }
                   3055:        
                   3056:        Cdcl = odcl;
                   3057:        return nn;
                   3058: }
                   3059: 0707071010112043671004440001630000160000010172100466055375400000700000067044dcl2.c/*ident     "@(#)ctrans:src/dcl2.c  1.2" */
                   3060: /**************************************************************************
                   3061: 
                   3062:        C++ source for cfront, the C++ compiler front-end
                   3063:        written in the computer science research center of Bell Labs
                   3064: 
                   3065:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   3066:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   3067: 
                   3068: dcl2.c:
                   3069: 
                   3070: *************************************************************************/
                   3071: 
                   3072: #include "cfront.h"
                   3073: #include "size.h"
                   3074: 
                   3075: Pname conv_dominates(Pname on1, Pname on2)
                   3076: /*
                   3077:        compare for duplicates and dominance:
                   3078: 
                   3079:        on1 and on2 are two conversion operator functions
                   3080:        return the the one that dominates the other (according to the
                   3081:        class hierarchy) otherwise 0 (0 thus indicats ambiguous conversion)
                   3082: */
                   3083: { 
                   3084:        Ptype r1 = on1->tp->base==FCT ? Pfct(on1->tp)->returns 
                   3085:                        : Pfct(Pgen(on1->tp)->fct_list->f->tp)->returns;
                   3086:        Ptype r2 = on2->tp->base==FCT ? Pfct(on2->tp)->returns 
                   3087:                        : Pfct(Pgen(on2->tp)->fct_list->f->tp)->returns;
                   3088: //error('d',"conv_dominates(%n,%n)",on1,on2);
                   3089:        if (r1==r2 || r1->check(r2,0)==0) return on1;
                   3090:        Pptr p1 = r1->is_ptr_or_ref();
                   3091:        Pptr p2 = r2->is_ptr_or_ref();
                   3092:        if (p1 && p2) {
                   3093:                Pname cn1 = p1->typ->is_cl_obj();
                   3094:                Pname cn2 = p2->typ->is_cl_obj();
                   3095:                if (cn1 && cn2) {
                   3096: // is_cl_obj() returns b_name
                   3097: //                     Pclass c1 = Pclass(Pbase(cn1->tp)->b_name->tp);
                   3098: //                     Pclass c2 = Pclass(Pbase(cn2->tp)->b_name->tp);
                   3099:                        Pclass c1 = Pclass(cn1->tp);
                   3100:                        Pclass c2 = Pclass(cn2->tp);
                   3101:                        if (c1 && c2) {
                   3102:                                //if (c1==c2 || c1->has_base(c2)) 
                   3103:                                if (c1->has_base(c2)) 
                   3104:                                        return on1;
                   3105:                                else if (c2->has_base(c1)) 
                   3106:                                        return on2;
                   3107:                        }
                   3108:                }
                   3109:        }
                   3110:        return 0;
                   3111: }
                   3112: 
                   3113: 
                   3114: Pstmt curr_loop;
                   3115: Pstmt curr_switch;
                   3116: Pblock curr_block;
                   3117: 
                   3118: void stmt::reached()
                   3119: {
                   3120:        register Pstmt ss = s_list;
                   3121: 
                   3122:        if (ss == 0) return;
                   3123: 
                   3124:        switch (ss->base) {
                   3125:        case LABEL:
                   3126:        case CASE:
                   3127:        case DEFAULT:
                   3128:                break;
                   3129:        default:
                   3130:                error('w',&ss->where,"S after%k not reached",base);
                   3131:                for (; ss; ss=ss->s_list) {     // delete unreacheable code
                   3132:                        switch (ss->base) {
                   3133:                        case LABEL:
                   3134:                        case CASE:
                   3135:                        case DEFAULT:           // reachable
                   3136:                                s_list = ss;
                   3137:                                return;
                   3138:                        case DCL:               // the dcl may be used later
                   3139:                                                // keep to avoid cascading errors
                   3140:                        case IF:
                   3141:                        case DO:
                   3142:                        case WHILE:
                   3143:                        case SWITCH:
                   3144:                        case FOR:
                   3145:                        case BLOCK:             // may hide a label
                   3146:                                s_list = ss;
                   3147:                                return;
                   3148:                        }
                   3149:                }
                   3150:                s_list = 0;
                   3151:        }
                   3152: }
                   3153: 
                   3154: Pexpr check_cond(Pexpr e, TOK b, Ptable tbl)
                   3155: {
                   3156: //error('d',"check_cond(%k %k) tbl %d",e->base,b,tbl);
                   3157:        Pname cn;
                   3158:        if (e == dummy) error("empty condition for %k",b);
                   3159: 
                   3160:        int const_obj = 0;
                   3161:        const_obj = e->tp->tconst();
                   3162:        Pexpr ee = e;
                   3163:         while (ee && (ee->base==DOT || ee->base==REF)) {
                   3164:                        Pexpr m = ee->mem;
                   3165:                        if ( ee->base==REF && m->tp &&  m->tp->is_ptr())
                   3166:                                break;
                   3167:                        ee = ee->e1;
                   3168:         }
                   3169:         if (ee) {
                   3170:                        Ptype ttt = ee->tp;
                   3171:                        switch (e->base) {
                   3172:                        case REF:
                   3173:                                Pptr p = ttt?ttt->is_ptr():0;
                   3174:                                if (p && p->typ->tconst())
                   3175:                                        const_obj = 1;
                   3176:                                break;
                   3177:                        case DOT:
                   3178:                                if (ttt && ttt->tconst())
                   3179:                                        const_obj = 1;
                   3180:                        }
                   3181:         }
                   3182: 
                   3183:        if (cn = e->tp->is_cl_obj()) {  
                   3184:                Pclass cl = Pclass(cn->tp);
                   3185:                int i = 0;
                   3186:                Pname found = 0;
                   3187:                for (Pname on = cl->conv; on; on=on->n_list) {
                   3188:                        Pfct f = on->tp->base == FCT ? Pfct(on->tp)
                   3189:                                 : Pfct(Pgen(on->tp)->fct_list->f->tp);
                   3190:                        Ptype t = f->returns;
                   3191:                xx:
                   3192:                        switch (t->base) {
                   3193:                        case TYPE:
                   3194:                                t = Pbase(t)->b_name->tp;
                   3195:                                goto xx;
                   3196:                        case FLOAT:
                   3197:                        case DOUBLE:
                   3198:                        case LDOUBLE:
                   3199:                        case PTR:
                   3200:                                if (b == DEREF) break;
                   3201:                        case CHAR:
                   3202:                        case SHORT:
                   3203:                        case INT:
                   3204:                        case LONG:
                   3205:                        case EOBJ:
                   3206: //                              if (found==0 || found->tp->check(on->tp,0)) {
                   3207: //error('d',"found %n on %n",found,on);
                   3208:                        {       Pname xx = found;
                   3209:                                 if (found == 0) {
                   3210:                                         i = 1;
                   3211:                                         found = on;
                   3212:                                 }
                   3213:                                 else if ((found = really_dominate(found,on,const_obj)) == 0) {
                   3214:                                         i = 2;
                   3215:                                         found = on;
                   3216:                                         error("two conversions for%nO in%kE: %n and %n",cn,b,xx,on);
                   3217:                                        return e;
                   3218:                                }
                   3219:                        }
                   3220:                        }
                   3221:                }
                   3222: //error('d',"i %d",i);
                   3223:                switch (i) {
                   3224:                case 0:
                   3225:                        error("%nO in%kE",cn,b);
                   3226:                        return e;
                   3227: /*
                   3228:                case 1:
                   3229:                {       Pname xx = new name(found->string);
                   3230:                        Pref r = new ref(DOT,e,xx);
                   3231:                        Pexpr rr = r->typ(tbl);
                   3232:                        Pexpr c = new expr(G_CALL,rr,0);
                   3233: 
                   3234:                        if (e->lval(0)) {
                   3235:                        //      Pref r = new ref(DOT,e,found);
                   3236:                        //      r->tp = found->tp;
                   3237:                        //      Pexpr c = new expr(G_CALL,r,0);
                   3238:                        //      c->fct_name = found;
                   3239:                                return c->typ(tbl);
                   3240:                        }
                   3241:                        else {  // (temp=init,temp.coerce())
                   3242:                                Pname tmp = make_tmp('U',e->tp,tbl); 
                   3243:                                Pexpr ass = init_tmp(tmp,e,tbl);
                   3244:                        //      Pref r = new ref(DOT,tmp,found);
                   3245:                        //      Pexpr rr = r->typ(tbl);
                   3246:                        //      Pexpr c = new expr(G_CALL,rr,0);
                   3247:                        //      c->fct_name = found;
                   3248:                                ass = new expr(CM,ass,c);
                   3249:                                return ass->typ(tbl);
                   3250:                        }
                   3251:                }
                   3252: */
                   3253:                case 1:
                   3254:                {       Pname xx = new name(found->string);
                   3255:                        Pexpr c;
                   3256: 
                   3257:                        if (e->lval(0)) {
                   3258:                                Pref r = new ref(DOT,e,xx);
                   3259:                                Pexpr rr = r->typ(tbl);
                   3260:                                c = new expr(G_CALL,rr,0);
                   3261:                        }
                   3262:                        else {  // (temp=init,temp.coerce())
                   3263:                                Pname tmp = make_tmp('U',e->tp,tbl); 
                   3264:                                Pexpr ass = init_tmp(tmp,e,tbl);
                   3265:                                Pref r = new ref(DOT,tmp,xx);
                   3266:                                Pexpr rr = r->typ(tbl);
                   3267:                                c = new expr(G_CALL,rr,0);
                   3268:                                c = new expr(CM,ass,c);
                   3269:                        }
                   3270:                        return c->typ(tbl);
                   3271:                }
                   3272:        //      default:
                   3273:        //              error("%d possible conversions for%nO in%kE",i,cn,b);
                   3274:        //              return e;
                   3275:                }
                   3276:                
                   3277:        }
                   3278:        if (e->tp->memptr()) {
                   3279:                e = new mdot("i",e);
                   3280:                e->i1 = 9;
                   3281:                e = new expr(NE,e,zero);
                   3282:        }
                   3283:        else if (e->tp->num_ptr(b) == FCT)
                   3284:                error("%k(F)",b);
                   3285:        return e;
                   3286: }
                   3287: 
                   3288: void stmt::dcl()
                   3289: /*
                   3290:        typecheck statement "this" in scope "curr_block->tbl"
                   3291: */
                   3292: {
                   3293:        Pstmt ss;
                   3294:        Pname n;
                   3295:        Pname nn;
                   3296:        Pstmt ostmt = Cstmt;
                   3297:        DB( if(Ddebug>=1) error('d',&where,"'%k'->stmt::dcl()",base); );
                   3298:        for (ss=this; ss; ss=ss->s_list) {
                   3299:                Pstmt old_loop, old_switch;
                   3300:                Cstmt = ss;
                   3301:                enum_promote = 0;
                   3302:                Ptable tbl = curr_block->memtbl;
                   3303: //error('d',"stmt::dcl %k",ss->base);
                   3304:                switch (ss->base) {
                   3305:                case BREAK:
                   3306:                        inline_restr |= 16;
                   3307:                        if (curr_loop==0 && curr_switch==0)
                   3308:                                error("break not in loop or switch");
                   3309:                        ss->reached();
                   3310:                        break;
                   3311: 
                   3312:                case CONTINUE:
                   3313:                        inline_restr |= 32;
                   3314:                        if (curr_loop == 0) error("continue not in loop");
                   3315:                        ss->reached();
                   3316:                        break;
                   3317: 
                   3318:                case DEFAULT:
                   3319:                        if (curr_switch == 0) {
                   3320:                                error("default not in switch");
                   3321:                                break;
                   3322:                        }
                   3323:                        if (curr_switch->has_default) error("two defaults in switch");
                   3324:                        curr_switch->has_default = ss;
                   3325:                        ss->s->s_list = ss->s_list;
                   3326:                        ss->s_list = 0;
                   3327:                        ss->s->dcl();
                   3328:                        break;
                   3329: 
                   3330:                case SM:
                   3331:                {       if (ss->e ==0) break;
                   3332:                        TOK b = ss->e->base;
                   3333:                        switch (b) {
                   3334:                        case DUMMY:
                   3335:                                ss->e = 0;
                   3336:                                break;
                   3337:                                        // check for unused results
                   3338:                                        // don't check operators that are likely
                   3339:                                        // to be overloaded to represent "actions":
                   3340:                                        // ! ~ < <= > >= << >>
                   3341:                        case EQ:
                   3342:                        case NE:
                   3343:                        case PLUS:
                   3344:                        case MINUS:
                   3345:                        case REF:
                   3346:                        case DOT:
                   3347:                        case MUL:
                   3348:                        case DIV:
                   3349:                        case ADDROF:
                   3350:                        case AND:
                   3351:                        case OR:
                   3352:                        case ER:
                   3353:                        case DEREF:
                   3354:                        case ANDAND:
                   3355:                        case OROR:
                   3356:                        case NAME:
                   3357:                        case VALUE:
                   3358:                                if (ss->e->tp) break;   // avoid looking at generated code
                   3359:                                ss->e = ss->e->typ(tbl);
                   3360:                                if (ss->e->base == CALL) break;
                   3361:                                if (ss->e->tp->base != VOID) {
                   3362:                                        if ( ss->e->base == DEREF )
                   3363:                                           error('w',"result of %sE not used",ss->e->e2?"[]":"*");
                   3364:                                        else 
                   3365:                                           error('w',"result of%kE not used",b);
                   3366:                                        if (ss->e->not_simple()==0) ss->e = dummy;
                   3367:                                }
                   3368:                                break;
                   3369:                        default:
                   3370:                                ss->e = ss->e->typ(tbl);
                   3371:                        }
                   3372:                        break;
                   3373:                }
                   3374:                case RETURN:
                   3375:                {       Pname fn = cc->nof;
                   3376:                        Pfct f = Pfct(fn->tp);
                   3377:                        Ptype rt = f->returns;
                   3378:                        Pexpr v = ss->e;
                   3379: //error('d',"rt %t",rt);
                   3380:                        while (rt->base == TYPE) rt = Pbase(rt)->b_name->tp;
                   3381:                        if (v != dummy) {
                   3382:                                if (rt->base == RPTR || rt->base == PTR) {
                   3383:                                        const_ptr = Pbase(Pptr(rt)->typ)->tconst();
                   3384:                                }
                   3385:                                if (rt->base == RPTR) {
                   3386:                                        ref_initializer++;
                   3387:                                        v = v->typ(tbl);
                   3388:                                        ref_initializer--;
                   3389:                                } else
                   3390:                                        v = v->typ(tbl);
                   3391:                                const_ptr = 0;
                   3392: 
                   3393:                                if (fn->n_oper==CTOR
                   3394:                                || fn->n_oper==DTOR
                   3395:                                || (rt->base==VOID && v->tp!=void_type)) {
                   3396:                                        error("unexpected return value");
                   3397:                                        // refuse to return the value:
                   3398:                                        ss->e = dummy;
                   3399:                                }
                   3400:                                else {
                   3401:                                        switch (rt->base) {
                   3402:                                        // case TYPE: laready done above
                   3403:                                        case RPTR:
                   3404:                                                switch (v->base) {
                   3405:                                                case NAME:
                   3406:                                                        if (Pname(v)->n_scope==FCT
                   3407:                                                        || Pname(v)->n_scope==ARG)
                   3408:                                                                error('w',"R to localV returned");
                   3409:                                                        break;
                   3410:                                                case ICON:
                   3411:                                                case CCON:
                   3412:                                                case FCON:
                   3413:                                                case STRING:
                   3414:                                                        if (Pptr(rt)->typ->tconst()==0)
                   3415:                                                                error('w',"R to literal returned");
                   3416:                                                }
                   3417:                                                v = ref_init(Pptr(rt),v,tbl);
                   3418:                                                if (v->base==G_CM
                   3419:                                                && v->e2->base==G_ADDROF
                   3420:                                                && v->e2->e2->base==NAME)
                   3421:                                                        error('w',"R to temporary returned (return value is not lvalue or of wrongT)");
                   3422:                                        case ANY:
                   3423:                                                break;
                   3424:                                        case COBJ:
                   3425: if (v->base == DEREF) {
                   3426:        Pexpr v1 = v->e1;
                   3427:        if (v1->base==CAST) {
                   3428:                Pexpr v2 = v1->e1;
                   3429:                if (v2->base == G_CM) { // *(T)(e1,e2) => (e1,*(T)e2)
                   3430:                        Pexpr v3 = v2->e2;
                   3431:                        v2->e2 = v;
                   3432:                        v2->tp = v->tp;
                   3433:                        v = v2;
                   3434:                        v1->e1 = v3;
                   3435:                }
                   3436:        }
                   3437: }
                   3438:        if (f->f_result) {
                   3439:                if (v->base==G_CM && rt->check(v->tp,0/*ASSIGN*/)==0)
                   3440:                        v = replace_temp(v,f->f_result);
                   3441:                else {
                   3442:                        v = class_init(f->f_result->contents(),rt,v,tbl);
                   3443:                        Pname rcn = rt->is_cl_obj();
                   3444:                        if (Pclass(rcn->tp)->has_itor()==0) {
                   3445:                                // can happen for virtuals and for user defined conversions
                   3446:                                v->tp = rt;
                   3447:                                v = new expr(ASSIGN,f->f_result->contents(),v);
                   3448:                                v->tp = rt;
                   3449:                        }
                   3450:                }
                   3451:        }
                   3452:        else
                   3453:                v = class_init(0,rt,v,tbl);
                   3454:                                                break;
                   3455:                                        case PTR:
                   3456:                                        {       Pexpr x = v;
                   3457:                                                v = ptr_init(Pptr(rt),v,tbl);
                   3458:                                                if (v->base == ADDROF
                   3459:                                                && v->e2->base == NAME
                   3460:                                                && Pname(v->e2)->n_stclass == AUTO)
                   3461:                                                        error('w',"P to local variable%n returned",Pname(v->e2));
                   3462:                                        //      if (v==x ||v->e2==x) goto def;
                   3463:                                                if (Pchecked == 0) goto def;
                   3464:                                                goto ret_save;
                   3465:                                        //      break;
                   3466:                                        }
                   3467:                                        case INT:
                   3468:                                        case CHAR:
                   3469:                                        case LONG:
                   3470:                                        case SHORT:
                   3471:                                                if (Pbase(rt)->b_unsigned
                   3472:                                                && v->base==UMINUS
                   3473:                                                && v->e2->base==ICON)
                   3474:                                                        error('w',"negative returned fromF returning unsigned");
                   3475:                                        default:
                   3476:                                        def:
                   3477:                                        {
                   3478:                                                Pexpr x = try_to_coerce(rt,v,"return value",tbl);
                   3479:                                                if (x)
                   3480:                                                        v = x;
                   3481:                                                else if (rt->check(v->tp,ASSIGN))
                   3482:                                                        error("bad return valueT for%n:%t (%tX)",fn,v->tp,rt);
                   3483:                                        }
                   3484: 
                   3485:                                        }
                   3486:                                ret_save:
                   3487:                                        ss->ret_tp = rt;
                   3488:                                        ss->e = v;
                   3489:                                }
                   3490:                        }
                   3491:                        else {
                   3492:                                if (rt->base != VOID) error("return valueX");
                   3493:                        }
                   3494:                        ss->reached();
                   3495:                        break;
                   3496:                }
                   3497: 
                   3498:                case DO:        // in DO the stmt is before the test
                   3499:                        inline_restr |= 8;
                   3500:                        old_loop = curr_loop;
                   3501:                        curr_loop = ss;
                   3502:                        { Pstmt st = ss->s;
                   3503:                          while(st && st->base == FOR) st = st->for_init;
                   3504:                          if (st && st->base == DCL)
                   3505:                                if (st==ss->s) error("D as onlyS in do-loop");
                   3506:                        }
                   3507:                        ss->s->dcl();
                   3508:                        ss->e = ss->e->typ(tbl);
                   3509:                        ss->e = check_cond(ss->e,DO,tbl);
                   3510:                        curr_loop = old_loop;
                   3511:                        break;
                   3512: 
                   3513:                case WHILE:
                   3514:                        inline_restr |= 8;
                   3515:                        old_loop = curr_loop;
                   3516:                        curr_loop = ss;
                   3517:                        ss->e = ss->e->typ(tbl);
                   3518:                        ss->e = check_cond(ss->e,WHILE,tbl);
                   3519:                        { Pstmt st = ss->s;
                   3520:                          while(st && st->base == FOR) st = st->for_init;
                   3521:                          if (st && st->base == DCL)
                   3522:                                if(st==ss->s) error("D as onlyS in while-loop");
                   3523:                        }
                   3524:                        ss->s->dcl();
                   3525:                        curr_loop = old_loop;
                   3526:                        break;
                   3527: 
                   3528:                case SWITCH:
                   3529:                {       int ne = 0;
                   3530:                        inline_restr |= 4;
                   3531:                        old_switch = curr_switch;
                   3532:                        curr_switch = ss;
                   3533:                        ss->e = ss->e->typ(tbl);
                   3534:                        ss->e = check_cond(ss->e,SWITCH,tbl);
                   3535:                        { Pstmt st = ss->s;
                   3536:                          while(st && st->base == FOR) st = st->for_init;
                   3537:                          if (st && st->base == DCL)
                   3538:                                if(st==ss->s) error("D as onlyS in switchS");
                   3539:                        }
                   3540:                        {       Ptype tt = ss->e->tp;
                   3541:                        sii:
                   3542:                                switch (tt->base) {
                   3543:                                case TYPE:
                   3544:                                        tt = Pbase(tt)->b_name->tp; goto sii;
                   3545:                                case EOBJ:
                   3546:                                        ne = Penum(Pbase(tt)->b_name->tp)->no_of_enumerators;
                   3547:                                case ZTYPE:
                   3548:                                case ANY:
                   3549:                                case CHAR:
                   3550:                                case SHORT:
                   3551:                                case INT:
                   3552:                                case LONG:
                   3553:                                case FIELD:
                   3554:                                        break;
                   3555:                                default:
                   3556:                                        error("%t switchE",ss->e->tp);
                   3557:                                }
                   3558:                        }
                   3559:                        ss->s->dcl();
                   3560:                        if (ne) {       /* see if the number of cases is "close to"
                   3561:                                           but not equal to the number of enumerators
                   3562:                                        */
                   3563:                                int i = 0;
                   3564:                                Pstmt cs;
                   3565:                                for (cs=ss->case_list; cs; cs=cs->case_list) i++;
                   3566:                                if (i && i!=ne) {
                   3567:                                        if (ne < i) {
                   3568:                                ee:             error('w',"switch (%t)W %d cases (%d enumerators)",ss->e->tp,i,ne);
                   3569:                                        }
                   3570:                                        else {
                   3571:                                                switch (ne-i) {
                   3572:                                                case 1: if (3<ne) goto ee;
                   3573:                                                case 2: if (7<ne) goto ee;
                   3574:                                                case 3: if (23<ne) goto ee;
                   3575:                                                case 4: if (60<ne) goto ee;
                   3576:                                                case 5: if (99<ne) goto ee;
                   3577:                                                }
                   3578:                                        }
                   3579:                                }
                   3580:                        }
                   3581:                        curr_switch = old_switch;
                   3582:                        break;
                   3583:                }
                   3584:                case CASE:
                   3585:                        if (curr_switch == 0) {
                   3586:                                error("case not in switch");
                   3587:                                break;
                   3588:                        }
                   3589:                        ss->e = ss->e->typ(tbl);
                   3590:                        ss->e->tp->num_ptr(CASE);
                   3591:                        {       Ptype tt = ss->e->tp;
                   3592:                        iii:
                   3593:                                switch (tt->base) {
                   3594:                                case TYPE:
                   3595:                                        tt = Pbase(tt)->b_name->tp; goto iii;
                   3596:                                case ZTYPE:
                   3597:                                case ANY:
                   3598:                                case CHAR:
                   3599:                                case SHORT:
                   3600:                                case INT:
                   3601:                                case LONG:
                   3602:                                case EOBJ:
                   3603:                                        Neval = 0;
                   3604:                                        long i = ss->e->eval();
                   3605:                                        if (Neval == 0) {
                   3606:                                                Pstmt cs;
                   3607:                                                if (largest_int<i) error("long case value");
                   3608:                                                for (cs=curr_switch->case_list; cs; cs=cs->case_list) {
                   3609:                                                        if (cs->case_value == i) error("case %d used twice in switch",i);
                   3610:                                                }
                   3611:                                                ss->case_value = int(i);
                   3612:                                                ss->case_list = curr_switch->case_list;
                   3613:                                                curr_switch->case_list = ss;
                   3614:                                        }
                   3615:                                        else
                   3616:                                                error("bad case label: %s",Neval);
                   3617:                                        break;
                   3618:                                default:
                   3619:                                        error("%t caseE",ss->e->tp);
                   3620:                                }
                   3621:                        }
                   3622:                //      if (1) {
                   3623:                //              Neval = 0;
                   3624:                //              long i = ss->e->eval();
                   3625:                //              if (Neval == 0) {
                   3626:                //                      Pstmt cs;
                   3627:                //                      if (largest_int<i) error("long case value");
                   3628:                //                      for (cs=curr_switch->case_list; cs; cs=cs->case_list) {
                   3629:                //                              if (cs->case_value == i) error("case %d used twice in switch",i);
                   3630:                //                      }
                   3631:                //                      ss->case_value = int(i);
                   3632:                //                      ss->case_list = curr_switch->case_list;
                   3633:                //                      curr_switch->case_list = ss;
                   3634:                //              }
                   3635:                //              else
                   3636:                //                      error("bad case label: %s",Neval);
                   3637:                //      }
                   3638:                        if (ss->s->s_list) error('i',"case%k",ss->s->s_list->base);
                   3639:                        ss->s->s_list = ss->s_list;
                   3640:                        ss->s_list = 0;
                   3641:                        ss->s->dcl();
                   3642:                        break;
                   3643: 
                   3644:                case GOTO:
                   3645:                        inline_restr |= 2;
                   3646:                        ss->reached();
                   3647:                case LABEL:
                   3648:                        /* Insert label in function mem table;
                   3649:                           labels have function scope.
                   3650:                        */
                   3651:                        n = ss->d;
                   3652:                        nn = cc->ftbl->insert(n,LABEL);
                   3653: 
                   3654:                        /* Set a ptr to the mem table corresponding to the scope
                   3655:                           in which the label actually occurred.  This allows the
                   3656:                           processing of goto's in the presence of ctors and dtors
                   3657:                        */
                   3658:                        if (ss->base == LABEL) {
                   3659:                                nn->n_realscope = curr_block->memtbl;
                   3660:                                inline_restr |= 1;
                   3661:                        }
                   3662: 
                   3663:                        if (Nold) {
                   3664:                                if (ss->base == LABEL) {
                   3665:                                        if (nn->n_initializer) error("twoDs of label%n",n);
                   3666:                                        nn->n_initializer = (Pexpr)1;
                   3667:                                }
                   3668:                                if (n != nn) ss->d = nn;
                   3669:                        }
                   3670:                        else {
                   3671:                                if (ss->base == LABEL) nn->n_initializer = (Pexpr)1;
                   3672:                                nn->where = ss->where;
                   3673:                        }
                   3674:                        if (ss->base == GOTO)
                   3675:                                nn->use();
                   3676:                        else {
                   3677:                                if (ss->s->s_list) error('i',"label%k",ss->s->s_list->base);
                   3678:                                ss->s->s_list = ss->s_list;
                   3679:                                ss->s_list = 0;
                   3680:                                nn->assign();
                   3681:                        }
                   3682:                        if (ss->s) ss->s->dcl();
                   3683:                        break;
                   3684: 
                   3685:                case IF:
                   3686:                {       
                   3687:                        Pexpr ee = ss->e->typ(tbl);
                   3688:                        if (ee->base == ASSIGN) {
                   3689:                                Neval = 0;
                   3690:                                (void)ee->e2->eval();
                   3691:                                if (Neval == 0)
                   3692:                                        error('w',"constant assignment in condition");
                   3693:                        }
                   3694:                        ss->e = ee = check_cond(ee,IF,tbl);
                   3695: 
                   3696:                        if (ss->s->base == DCL) error("D as onlyS after `if'");
                   3697: 
                   3698:                        // pointer to member returns with a tp set to 0
                   3699:                        if ( ee->tp ) switch (ee->tp->base) {
                   3700:                        case INT:
                   3701:                        case EOBJ:
                   3702:                        case ZTYPE:
                   3703:                        {       long i;
                   3704:                                Neval = 0;
                   3705:                                i = ee->eval();
                   3706: 
                   3707:                                if (Neval == 0) {
                   3708:                                        Pstmt sl = ss->s_list;
                   3709:                                        if (i) {
                   3710:                                                DEL(ss->else_stmt);
                   3711:                                                ss->s->dcl();
                   3712:                                                *ss = *ss->s;
                   3713:                                        }
                   3714:                                        else {
                   3715:                                                DEL(ss->s);
                   3716:                                                if (ss->else_stmt) {
                   3717:                                                        ss->else_stmt->dcl();
                   3718:                                                        *ss = *ss->else_stmt;
                   3719:                                                }
                   3720:                                                else {
                   3721:                                                        ss->base = SM;
                   3722:                                                        ss->e = dummy;
                   3723:                                                        ss->s = 0;
                   3724:                                                }
                   3725:                                        }
                   3726:                                        ss->s_list = sl;
                   3727:                                        continue;
                   3728:                                }
                   3729:                        }
                   3730:                        }
                   3731:                        ss->s->dcl();
                   3732:                        if (ss->else_stmt) {
                   3733:                                if (ss->else_stmt->base == DCL) error("D as onlyS after `else'");
                   3734:                                ss->else_stmt->dcl();
                   3735:                        }
                   3736:                        break;
                   3737:                }
                   3738:                case FOR:
                   3739:                        inline_restr |= 8;
                   3740:                        old_loop = curr_loop;
                   3741:                        curr_loop = ss;
                   3742:                        if (ss->for_init) {
                   3743:                                Pstmt fi = ss->for_init;
                   3744:                                switch (fi->base) {
                   3745:                                case SM:
                   3746:                                        if (fi->e == dummy) {
                   3747:                                                ss->for_init = 0;
                   3748:                                                break;
                   3749:                                        }
                   3750:                                        fi->dcl();
                   3751:                                        break;
                   3752:                                default:
                   3753:                                        // for (stmt; e1; e2) stmt1 stmt2
                   3754:                                        // => {stmt; for(; e1; e2) stmt1 stmt2}
                   3755:                                        //    if stmt != declaration
                   3756:                                        // if stmt == declaration, temporarily
                   3757:                                        //    rewrite to avoid symbol table
                   3758:                                        //    problems in some contexts.
                   3759:                                        //    Then put decl back to avoid
                   3760:                                        //    extraneous {}.
                   3761:                                        // Note: to maintain pointers, ss
                   3762:                                        //       must not change
                   3763:                                {       Pstmt tmp = new stmt (SM,curloc,0);
                   3764:                                        *tmp = *ss;     // tmp = original for
                   3765:                                        tmp->for_init = 0;
                   3766:                                        fi->s_list = tmp;
                   3767:                                        *ss = *fi;
                   3768:                                        curr_loop = old_loop;
                   3769:                                        ss->dcl();
                   3770:                                        tmp = ss->s_list;
                   3771:                                        if ( ss->base == DCL
                   3772:                                        &&   tmp->base == FOR   // sanity check
                   3773:                                        &&   tmp->for_init == 0 // sanity check
                   3774:                                        ) {
                   3775:                                                // put DCL back in for init
                   3776:                                                *fi = *ss;
                   3777:                                                *ss = *tmp;
                   3778:                                                ss->for_init = fi;
                   3779:                                                fi->s_list = 0;
                   3780:                                        } else {
                   3781:                                                // non-decl stmt in for init
                   3782:                                                // put stmts in block in case
                   3783:                                                //    they follow a condition...
                   3784:                                                // allocate tmp to be sure
                   3785:                                                //    fields are initialized
                   3786:                                                *fi = *ss;
                   3787:                                                tmp = new block(ss->where,0,fi);
                   3788:                                                tmp->own_tbl = 0;
                   3789:                                                tmp->memtbl = curr_block->memtbl;
                   3790:                                                tmp->permanent = ss->permanent;
                   3791:                                                *ss = *tmp;
                   3792:                                                tmp->permanent = 0; delete tmp;
                   3793:                                        }
                   3794:                                        // don't repeat stmt::dcl() for
                   3795:                                        //    remaining stmts
                   3796:                                        goto done;
                   3797:                                }
                   3798:                                }
                   3799:                        }
                   3800:                        if (ss->e == dummy)
                   3801:                                ss->e = 0;
                   3802:                        else {
                   3803:                                ss->e = ss->e->typ(tbl);
                   3804:                                ss->e = check_cond(ss->e,FOR,tbl);
                   3805:                        }
                   3806:                        { Pstmt st = ss->s;
                   3807:                          while(st && st->base == FOR) st = st->for_init;
                   3808:                          if (st && st->base == DCL)
                   3809:                                if(st==ss->s) error("D as onlyS in for-loop");
                   3810:                        }
                   3811:                        ss->s->dcl();
                   3812:                        ss->e2 = (ss->e2 == dummy) ? 0 : ss->e2->typ(tbl);
                   3813:                        curr_loop = old_loop;
                   3814:                        break;
                   3815: 
                   3816:                case DCL:       /* declaration after statement */
                   3817:                {
                   3818:                        /*      collect all the contiguous DCL nodes from the
                   3819:                                head of the s_list. find the next statement
                   3820:                        */
                   3821:                        int non_trivial = 0;
                   3822:                        int count = 0;
                   3823:                        Pname tail = ss->d;
                   3824:                        for (Pname nn=tail; nn; nn=nn->n_list) {
                   3825:                                //      find tail;
                   3826:                                //      detect non-trivial declarations
                   3827:                                count++;
                   3828: 
                   3829:                                if (nn->n_list) tail = nn->n_list;
                   3830:                                Pname n = tbl->look(nn->string,0);
                   3831: 
                   3832:                                if (n && n->n_table==tbl) non_trivial = 2;
                   3833:                                if (non_trivial == 2) continue;
                   3834:                                if ((nn->n_sto==STATIC && nn->tp->base!=FCT)
                   3835:                                || nn->tp->is_ref()
                   3836:                                || (nn->tp->tconst() && fct_const==0)) {
                   3837:                                        non_trivial = 2;
                   3838:                                        continue;
                   3839:                                }
                   3840: 
                   3841:                                Pexpr in = nn->n_initializer;
                   3842:                                if (in)
                   3843:                                        switch (in->base) {
                   3844:                                        case ILIST:
                   3845:                                        case STRING:
                   3846:                                                non_trivial = 2;
                   3847:                                                continue;
                   3848:                                        }
                   3849:                                non_trivial = 1;
                   3850:                                Pname cln = nn->tp->is_cl_obj();
                   3851:                                if (cln == 0) cln = cl_obj_vec;
                   3852:                                if (cln == 0) continue;
                   3853:                                if (Pclass(cln->tp)->has_ctor()) {
                   3854:                                        non_trivial = 2;
                   3855:                                        continue;
                   3856:                                }
                   3857:                                if (Pclass(cln->tp)->has_dtor()) non_trivial = 2;
                   3858:                        }
                   3859: 
                   3860:                        while( ss->s_list && ss->s_list->base==DCL ) {
                   3861:                                Pstmt sx = ss->s_list;
                   3862:                                tail = tail->n_list = sx->d;    // add to tail
                   3863:                                for (nn=sx->d; nn; nn=nn->n_list) {
                   3864:                                        //      find tail;
                   3865:                                        //      detect non-trivial declarations
                   3866:                                        count++;
                   3867:                                        if (nn->n_list) tail = nn->n_list;
                   3868:                                        Pname n = tbl->look(nn->string,0);
                   3869:                                        if (n && n->n_table==tbl) non_trivial = 2;
                   3870:                                        if (non_trivial == 2) continue;
                   3871:                                        if ((nn->n_sto==STATIC && nn->tp->base!=FCT)
                   3872:                                        || nn->tp->is_ref()
                   3873:                                        || (nn->tp->tconst() && fct_const==0)) {
                   3874:                                                non_trivial = 2;
                   3875:                                                continue;
                   3876:                                        }
                   3877:                                        Pexpr in = nn->n_initializer;
                   3878:                                        if (in)
                   3879:                                                switch (in->base) {
                   3880:                                                case ILIST:
                   3881:                                                case STRING:
                   3882:                                                        non_trivial = 2;
                   3883:                                                        continue;
                   3884:                                                }
                   3885:                                        non_trivial = 1;
                   3886:                                        Pname cln = nn->tp->is_cl_obj();
                   3887:                                        if (cln == 0) cln = cl_obj_vec;
                   3888:                                        if (cln == 0) continue;
                   3889:                                        if (Pclass(cln->tp)->has_ctor()) {
                   3890:                                                non_trivial = 2;
                   3891:                                                continue;
                   3892:                                        }
                   3893:                                        if (Pclass(cln->tp)->has_dtor()) non_trivial = 2;
                   3894:                                }
                   3895:                                ss->s_list = sx->s_list;
                   3896:                        /*      delete sx;      */
                   3897:                        }
                   3898: 
                   3899:                        Pstmt next_st = ss->s_list;
                   3900: //error('d',"dcl stmt : d %n  non_trivial %d  curr own_tbl %d  inline_restr 0%o",ss->d,non_trivial,curr_block->own_tbl,inline_restr);
                   3901:                        if (non_trivial==2      // must
                   3902:                        || (non_trivial==1      // might
                   3903:                                && ( curr_block->own_tbl==0     // why not?
                   3904:                                || inline_restr&3       /* label seen */)
                   3905:                                )
                   3906:                        ) {
                   3907:                                if (curr_switch && non_trivial==2) {
                   3908:                                        Pstmt cs = curr_switch->case_list;
                   3909:                                        Pstmt ds = curr_switch->has_default;
                   3910:                                        Pstmt bl;
                   3911:                                        if (cs == 0)
                   3912:                                                bl = ds;
                   3913:                                        else if (ds == 0)
                   3914:                                                bl = cs;
                   3915:                                        else if (cs->where.line<ds->where.line)
                   3916:                                                bl = ds;
                   3917:                                        else
                   3918:                                                bl = cs;
                   3919: 
                   3920:                                        if ((bl==0 || bl->s->base!=BLOCK) && curr_switch->s->memtbl==tbl)
                   3921:                                                error('s',"non trivialD in switchS (try enclosing it in a block)");
                   3922:                                }
                   3923: 
                   3924:                                /*      Create a new block,
                   3925:                                        put all the declarations at the head,
                   3926:                                        and the remainder of the slist as the
                   3927:                                        statement list of the block.
                   3928:                                */
                   3929:                                //ss->base = BLOCK; //DCL 
                   3930: 
                   3931:                                /*      check that there are no redefinitions
                   3932:                                        since the last "real" (user-written,
                   3933:                                        non-generated) block
                   3934:                                */
                   3935:                                { Pname lastnn = 0;
                   3936:                                  for( nn=ss->d; nn; nn=nn->n_list ) {
                   3937:                                        Pname n;
                   3938: //n=curr_block->memtbl->look(nn->string,0);
                   3939: //error('d',"checking %n  lex_level: %d  n: %n  n->lex_level: %d",nn,nn->lex_level,n,n?n->lex_level:0);
                   3940: //error('d',"   own_tbl: %d  curr_block: %d  n->n_table: %d",curr_block->own_tbl,curr_block,n->n_table);
                   3941: //error('d',"   real_block: %d  n's real_block: %d",curr_block->memtbl->real_block,n->n_table->real_block);
                   3942:                                        //if( curr_block->own_tbl
                   3943:                                        if ( (n=curr_block->memtbl->look(nn->string,0))
                   3944:                                        && n->n_table->real_block==curr_block->memtbl->real_block
                   3945:                                        && n->tp->base!=FCT
                   3946:                                        && n->tp->base!=OVERLOAD
                   3947:                                        && nn->lex_level == n->lex_level ) {
                   3948:                                                error("twoDs of%n",n);
                   3949:                                                if (lastnn==0) ss->d=nn->n_list;
                   3950:                                                else lastnn->n_list=nn->n_list;
                   3951:                                        } else lastnn = nn;
                   3952:                                  } // for nn
                   3953:                                }
                   3954: 
                   3955:                                /*      attach the remainder of the s_list
                   3956:                                        as the statement part of the block.
                   3957:                                */
                   3958:                                ss->s = next_st;
                   3959:                                ss->s_list = 0;
                   3960: 
                   3961:                                /*      create the table in advance,
                   3962:                                        in order to set the real_block
                   3963:                                        ptr to that of the enclosing table
                   3964:                                */
                   3965:                                ss->memtbl = new table(count+4,tbl,0);
                   3966:                                ss->memtbl->real_block = curr_block->memtbl->real_block;
                   3967:                                Pblock(ss)->dcl(ss->memtbl);
                   3968:                        }
                   3969:                        else {  /*      to reduce the number of symbol tables,
                   3970:                                        do not make a new block,
                   3971:                                        instead insert names in enclosing block,
                   3972:                                        and make the initializers into expression
                   3973:                                        statements.
                   3974:                                */
                   3975:                                Pstmt sss = ss;
                   3976:                                { Pname lastnn = 0;
                   3977:                                  for( nn=ss->d; nn; nn=nn->n_list ) {
                   3978:                                        Pname n;
                   3979: //error('d',"nn %n",nn);
                   3980:                                        //if( curr_block->own_tbl
                   3981:                                        if ( (n=curr_block->memtbl->look(nn->string,0))
                   3982:                                        && n->n_table->real_block==curr_block->memtbl->real_block
                   3983:                                        && n->tp->base!=FCT && n->tp->base!=OVERLOAD
                   3984:                                        && nn->lex_level == n->lex_level ) {
                   3985:                                                error("twoDs of%n",n);
                   3986:                                                n = 0;
                   3987:                                                if (lastnn==0) ss->d=nn->n_list;
                   3988:                                                else lastnn->n_list=nn->n_list;
                   3989:                                        } else {
                   3990:                                                n = nn->dcl(tbl,FCT);
                   3991:                                                lastnn=nn;
                   3992:                                        }
                   3993: 
                   3994:                                        if (n == 0) {
                   3995:                                                if (ss) {
                   3996:                                                        ss->base = SM;
                   3997:                                                        ss->e = 0;
                   3998:                                                }
                   3999:                                                continue;
                   4000:                                        }
                   4001: //error('d',"hoisted %n to outer blk",n);
                   4002: 
                   4003:                                        Pexpr in = n->n_initializer;
                   4004:                                        n->n_initializer = 0;
                   4005: 
                   4006:                                        if (ss) {
                   4007:                                                sss->base = SM;
                   4008:                                                ss = 0;
                   4009:                                        }
                   4010:                                        else
                   4011:                                                sss = sss->s_list = new estmt(SM,sss->where,0,0);
                   4012:                                        if (in) {
                   4013:                                                switch (in->base) {
                   4014:                                                case G_CALL:    /* constructor? */
                   4015:                                                {
                   4016:                                                        Pname fn = in->fct_name;
                   4017:                                                        if (fn && fn->n_oper==CTOR) break;
                   4018:                                                }
                   4019:                                                default:
                   4020:                                                        in = new expr(ASSIGN,n,in);
                   4021:                                                        in->tp = n->tp;
                   4022:                                                }
                   4023:                                        //      sss->e = in->typ(tbl);
                   4024:                                                sss->e = in;
                   4025:                                        }
                   4026:                                        else
                   4027:                                                sss->e = dummy;
                   4028:                                  } // for nn
                   4029:                                }
                   4030: 
                   4031:                                ss = sss;
                   4032:                                ss->s_list = next_st;
                   4033:                        }
                   4034:                        break;
                   4035:                }
                   4036: 
                   4037:                case BLOCK:
                   4038:                        Pblock(ss)->dcl(tbl);
                   4039:                        break;
                   4040: 
                   4041:                case ASM:
                   4042:                        /* save string */
                   4043:                {
                   4044:                        char* s = (char*)ss->e;
                   4045:                        int ll = strlen(s);
                   4046:                        char* s2 = new char[ll+1];
                   4047:                        strcpy(s2,s);
                   4048:                        ss->e = Pexpr(s2);
                   4049:                        break;
                   4050:                }
                   4051:                default:
                   4052:                        error('i',"badS(%p %d)",ss,ss->base);
                   4053:                }
                   4054:        }
                   4055: done:
                   4056:        Cstmt = ostmt;
                   4057: }
                   4058: 
                   4059: void block::dcl(Ptable tbl)
                   4060: /*
                   4061:        Note: for a block without declarations memtbl denotes the table
                   4062:        for the enclosing scope.
                   4063:        A function body has its memtbl created by fct::dcl().
                   4064: */
                   4065: {
                   4066:        int bit_old = bit_offset;
                   4067:        int byte_old = byte_offset;
                   4068:        int max_old = max_align;
                   4069:        Pblock block_old = curr_block;
                   4070: 
                   4071:        if (base != BLOCK && base != DCL) error('i',"block::dcl(%d)",base);
                   4072: 
                   4073:        curr_block = this;
                   4074: //error('d',"%d->block::dcl(%d) base %k",this,tbl,base);
                   4075: //error('d',"    memtbl %d  own_tbl %d  d %n  s %k",memtbl,own_tbl,d,s?s->base:0);
                   4076:        if (d) {
                   4077:                own_tbl = 1;
                   4078:                base = BLOCK;
                   4079:                if (memtbl == 0) {
                   4080:                        int nmem = d->no_of_names()+4;
                   4081:                        memtbl = new table(nmem,tbl,0);
                   4082:                        memtbl->real_block = this;
                   4083:                        /*      this is a "real" block from the
                   4084:                                source text, and not one created by DCL's
                   4085:                                inside a block. */
                   4086:                }
                   4087:                else
                   4088:                        if (memtbl != tbl) error('i',"block::dcl(?)");
                   4089: 
                   4090:                Pname nx;
                   4091:                for (Pname n=d; n; n=nx) {
                   4092:                        nx = n->n_list;
                   4093:                        n->dcl(memtbl,FCT);
                   4094:                        switch (n->tp->base) {
                   4095:                        case CLASS:
                   4096:                        case ANON:
                   4097:                        case ENUM:
                   4098:                                break;
                   4099:                        default:
                   4100:                                delete n;
                   4101:                        }
                   4102:                }
                   4103:        }
                   4104:        else if ( base == BLOCK ) {
                   4105:                own_tbl = 1;
                   4106:                if (memtbl == 0) {
                   4107:                        int nmem = 4;
                   4108:                        memtbl = new table(nmem,tbl,0);
                   4109:                        memtbl->real_block = this;
                   4110:                        /*      this is a "real" block from the
                   4111:                                source text, and not one created by DCL's
                   4112:                                inside a block. */
                   4113:                } else
                   4114:                        if (memtbl != tbl) error('i',"block::dcl(?)");
                   4115:        } else {
                   4116:                base = BLOCK;
                   4117:                memtbl = tbl;
                   4118:        }
                   4119: 
                   4120:        Pname odcl = Cdcl;
                   4121:        if (s) s->dcl();
                   4122:        if (own_tbl) {
                   4123:                Pname m;
                   4124:                int i;
                   4125:                for (m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i)) {
                   4126:                        Ptype t = m->tp;
                   4127: 
                   4128: if (in_class_dcl) m->lex_level -= 1;
                   4129: 
                   4130:                        if (t == 0) {
                   4131:                                if (m->n_assigned_to == 0)
                   4132:                                   error("label %sU",m->string);
                   4133:                                if (m->n_used == 0)
                   4134:                                   error('w',"label %s not used", m->string);
                   4135:                                continue;
                   4136:                        }
                   4137:                ll:
                   4138:                        switch (t->base) {
                   4139:                        case TYPE:      t = Pbase(t)->b_name->tp; goto ll;
                   4140:                        case CLASS:
                   4141:                        case ANON:
                   4142:                        case ENUM:
                   4143:                        case FCT:
                   4144:                        //case VEC:
                   4145:                                continue;
                   4146:                        }
                   4147: 
                   4148:                        if (m->n_addr_taken == 0) {
                   4149:                                if (m->n_used) {
                   4150:                                        if (m->n_assigned_to) {
                   4151:                                        }
                   4152:                                        else if ( t->base != VEC ) {
                   4153:                                                switch (m->n_scope) {
                   4154:                                                case FCT:
                   4155:                                                        Cdcl = m;
                   4156:                                                        if (m->string[0] != '_' && m->string[1] != '_' )
                   4157:                                                                error('w',&m->where,"%n used but not set",m);
                   4158:                                                }
                   4159:                                        }
                   4160:                                }
                   4161:                                else {
                   4162:                                        if (m->n_assigned_to) {
                   4163:                                        }
                   4164:                                        else if (m->string[0]!='_' || m->string[1]!='_') {
                   4165:                                                switch (m->n_scope) {
                   4166:                                                case ARG:
                   4167:                                                case FCT:
                   4168:                                                        Cdcl = m;
                   4169:                                                        error('w',&m->where,"%n not used",m);
                   4170:                                                }
                   4171:                                        }
                   4172:                                }
                   4173:                        }
                   4174:                }
                   4175:        }
                   4176:        Cdcl = odcl;
                   4177: 
                   4178:        d = 0;
                   4179: 
                   4180:        if (bit_offset) byte_offset += SZ_WORD;
                   4181:        bit_offset = bit_old;
                   4182:        byte_offset = byte_old;
                   4183:        curr_block = block_old;
                   4184: }
                   4185: 
                   4186: void name::field_align()
                   4187: /*
                   4188:         adjust alignment
                   4189: */
                   4190: {
                   4191:        Pbase fld = (Pbase)tp;
                   4192:        int nbits = fld->b_bits;
                   4193: 
                   4194:        int a = (F_SENSITIVE) ? fld->b_fieldtype->align() : SZ_WORD;
                   4195:        if (max_align < a) max_align = a;
                   4196: 
                   4197:        if (nbits == 0) {               // force word alignment
                   4198:                int b;
                   4199:                if (bit_offset)
                   4200:                        nbits = BI_IN_WORD - bit_offset;
                   4201:                else if (b = byte_offset%SZ_WORD)
                   4202:                        nbits = b * BI_IN_BYTE;
                   4203:        //      else
                   4204:        //              nbits = BI_IN_WORD;
                   4205:                if (max_align < SZ_WORD) max_align = SZ_WORD;
                   4206:        }
                   4207:        else if (bit_offset == 0) {     // take care of part of word
                   4208:                int b = byte_offset%SZ_WORD;
                   4209:                if (b) {
                   4210:                        byte_offset -= b;
                   4211:                        bit_offset = b*BI_IN_BYTE;
                   4212:                }
                   4213:        }
                   4214: //error('d',"byteoff %d bitoff %d bits %d",byte_offset,bit_offset,nbits);
                   4215:        int x = (bit_offset += nbits);
                   4216:        if (BI_IN_WORD < x) {
                   4217:                fld->b_offset = 0;
                   4218:                byte_offset += SZ_WORD;
                   4219:                bit_offset = nbits;
                   4220:        }
                   4221:        else {
                   4222:                fld->b_offset = bit_offset;
                   4223:                if (BI_IN_WORD == x) {
                   4224:                        bit_offset = 0;
                   4225:                        byte_offset += SZ_WORD;
                   4226:                }
                   4227:                else
                   4228:                        bit_offset = x;
                   4229:        }
                   4230:        n_offset = byte_offset;
                   4231: }
                   4232: 0707071010112043701004440001630000160000010172500466055376100000700000171674dcl3.c/*ident     "@(#)ctrans:src/dcl3.c  1.7" */
                   4233: /**************************************************************************
                   4234: 
                   4235:        C++ source for cfront, the C++ compiler front-end
                   4236:        written in the computer science research center of Bell Labs
                   4237: 
                   4238:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   4239:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   4240: 
                   4241: dcl3.c:
                   4242:        Routines used by ::dcl fucntions: fct::dcl() etc.
                   4243: 
                   4244: *****************************************************************************/
                   4245: 
                   4246: #include "cfront.h"
                   4247: #include "size.h"
                   4248: #include "template.h"
                   4249: 
                   4250: static void vbase_pointers(Pname fn, Pclass cl)
                   4251: /*
                   4252:        insert argument for virtual base pointers (if any)
                   4253:        after f_this and before f_argtype
                   4254: */
                   4255: {
                   4256: //error('d',"vbase_pointers(%n,%t) %d %k",fn,cl,fn->tp,fn->n_oper);
                   4257:        Pfct f = Pfct(fn->tp);
                   4258:        if (fn->n_oper == CTOR) {
                   4259:                Pname d = 0;
                   4260:                for (Pbcl b = cl->baselist; b; b=b->next) {
                   4261:                        if (b->base != VIRTUAL) continue;
                   4262:                        Pname a = new name(b->bclass->string);
                   4263:                        a->tp = b->bclass->this_type;
                   4264:                        a->n_list = d;
                   4265:                        a->n_table = f->body ? f->body->memtbl : 0;
                   4266:                        a->where = fn->where;
                   4267:                        d = a;
                   4268:                }       
                   4269:                                
                   4270:                if (d) {
                   4271:                        for (Pname dd =d;;) {
                   4272:                                if (d->n_list == 0) {
                   4273:                                        d->n_list = f->f_args->n_list;
                   4274:                                        break;
                   4275:                                }
                   4276:                                d = d->n_list;
                   4277:                        }
                   4278:                        f->f_args->n_list = dd;
                   4279:                }
                   4280:        }
                   4281:        if (fn->n_oper == DTOR) {       // add __free argument
                   4282: //error('d',"add __free to %n",fn);
                   4283:                Pname fa = new name;
                   4284:                fa->tp = int_type;
                   4285:                fa->n_scope = ARG;
                   4286:                fa->where = fn->where;
                   4287: 
                   4288:                Pname a = f->f_args;
                   4289:                if (a == 0)
                   4290:                        f->f_args = fa;
                   4291:                else {
                   4292:                        for(;;a = a->n_list) {
                   4293: // error('d',"a %d %t",a,a->tp);
                   4294:                                if (a->n_list == 0) {
                   4295:                                        a->n_list = fa;
                   4296:                                        break;
                   4297:                                }
                   4298:                        }
                   4299:                }
                   4300:        }
                   4301: }
                   4302: 
                   4303: void make_res(Pfct f)
                   4304: /*
                   4305:        returns X where X(X&) has been declared
                   4306:        add "_result" argument of type X*
                   4307: */
                   4308: {
                   4309:        Pname cl = f->returns->is_cl_obj();
                   4310:        if (cl==0 || Pclass(cl->tp)->has_itor()==0) return;
                   4311: 
                   4312:        Pname rv = new name("_result");
                   4313:        rv->tp  = f->returns->addrof();
                   4314:        rv->n_scope = FCT;      // not a ``real'' argument
                   4315:        rv->n_used = 1;
                   4316:        rv->n_list = f->argtype;
                   4317:        if (f->f_this)
                   4318:                f->f_this->n_list = rv;
                   4319:        else
                   4320:                f->f_args = rv;
                   4321:        f->f_result = rv;
                   4322:        f->s_returns = void_type;
                   4323: }
                   4324: 
                   4325: void name::check_oper(Pname cn)
                   4326: /*
                   4327:        check declarations of operators, ctors, dtors
                   4328: */
                   4329: {
                   4330: // error('d', "%n->check_oper( %n ): n_oper: %k", this, cn, n_oper );
                   4331:        switch (n_oper) {
                   4332:        case CALL:
                   4333:        case DEREF:
                   4334:        case REF:
                   4335:                if (cn == 0) error("operator%s must be aM",keys[n_oper]);
                   4336:                break;
                   4337:        case ASPLUS:
                   4338:        case ASMINUS:
                   4339:        case ASMUL:
                   4340:        case ASDIV:
                   4341:        case ASMOD:
                   4342:        case ASAND:
                   4343:        case ASOR:
                   4344:        case ASER:
                   4345:        case ASLS:
                   4346:        case ASRS:
                   4347:                if ( warning_opt ) {
                   4348:                        if ( cn == 0 || Pfct(tp)->f_static )
                   4349:                                error('w', "operator%s should be a non-staticMF",keys[n_oper]);
                   4350:                }
                   4351:                break;
                   4352:        case ASSIGN:
                   4353:                if (cn == 0) 
                   4354:                        error(strict_opt?0:'w',"non-member operator%k() (anachronism)",n_oper);
                   4355:                break;
                   4356:        case NOT:       /* unary operators only */
                   4357:        case COMPL:
                   4358:        // case INCR:
                   4359:        // case DECR:
                   4360:                Pfct f = Pfct(tp);
                   4361:                if (cn && f->argtype) 
                   4362:                        error("%n::%n takes noA",cn, this);
                   4363:                else if (f->nargs == 2)
                   4364:                        error("%n takes 1A only",this);
                   4365:                break;
                   4366:        case INCR:
                   4367:        case DECR:
                   4368:                // check for postscript instance
                   4369:                f = Pfct(tp);
                   4370:                if (cn) { // member
                   4371:                        if ( f->argtype && f->nargs == 1 ) {
                   4372:                                Pname n = f->argtype;
                   4373:                                if ( n->tp->base != INT )
                   4374:                                        error("%n must takeA ofT int, not %t",this,n->tp);
                   4375:                        }
                   4376:                }
                   4377:                else 
                   4378:                if (f->nargs == 2) { // non-member
                   4379:                        Pname n = f->argtype->n_list;
                   4380:                        if ( n->tp->base != INT )
                   4381:                                error("%n must takeA ofT int, not %t",this,n->tp);
                   4382:                }
                   4383:                break;
                   4384: 
                   4385:        case 0:
                   4386:        case TNAME:     /* may be a constructor */
                   4387:                if (cn && ((strcmp(cn->string,string)==0) ||
                   4388:                        ((Pclass(cn->tp)->class_base == 
                   4389:                                instantiated_template_class) &&
                   4390:                        (strcmp(string, 
                   4391:                                Ptclass(cn->tp)->unparametrized_tname()->string) == 0)))) 
                   4392:                {
                   4393:                        if (tp->base == FCT) {
                   4394:                                Pfct f = Pfct(tp);
                   4395:                                if (f->returns!=defa_type)
                   4396:                                        error("%s::%s()W returnT",string,string);
                   4397:                                f->returns = void_type;
                   4398:                                string = "__ct";
                   4399:                                n_oper = CTOR;
                   4400:                        }
                   4401:                        else
                   4402:                                error('s',"struct%nM%n",cn,cn);
                   4403:                }
                   4404:                else
                   4405:                        n_oper = 0;
                   4406:                break;
                   4407:        case DTOR:      /* must be a destructor */
                   4408: //error('d',"dtor %s",string);
                   4409:                if (cn == 0) {
                   4410:                        n_oper = 0;
                   4411:                        error("destructor ~%s() not inC",string);
                   4412:                }
                   4413:                 else 
                   4414:                if ((strcmp(cn->string,string) == 0) ||
                   4415:                        ((Pclass(cn->tp)->class_base ==
                   4416:                                instantiated_template_class) &&
                   4417:                          (strcmp(string,
                   4418:                                Ptclass(cn->tp)->unparametrized_tname()->string)==0)))
                   4419:                {
                   4420:                dto:
                   4421:                        Pfct f = (Pfct)tp;
                   4422:                        string = "__dt";
                   4423:                        if (tp->base != FCT) {
                   4424:                                error("%s::~%s notF",cn->string,cn->string);
                   4425:                                tp = new fct(void_type,0,1);
                   4426:                        }
                   4427:                        else if (f->returns!=defa_type/* && f->returns!=void_type*/) {
                   4428:                                if ( f->returns != void_type ||
                   4429:                                        f->body != 0 || friend_in_class == 0 ) 
                   4430:                                                error("%s::~%s()W returnT",cn->string,cn->string);
                   4431:                        }
                   4432: 
                   4433:                        if (f->argtype) {
                   4434:                                error("%s::~%s()WAs",cn->string,cn->string);
                   4435:                                f->nargs = 0;
                   4436:                                f->nargs_known = 1;
                   4437:                                f->argtype = 0;
                   4438:                        }
                   4439:                        f->returns = void_type;
                   4440:                }
                   4441:                else {
                   4442:                        if (strcmp(string,"__dt") == 0) goto dto;
                   4443:                        error("~%s in %s",string,cn->string);
                   4444:                        n_oper = 0;
                   4445:                }
                   4446:                break;
                   4447:        case TYPE:
                   4448: // cond stores the type of the operator function
                   4449: // error('d',"type %t",cond);
                   4450:                if (cn == 0) {
                   4451:                        // error("operator%t() not aM",Ptype(n_initializer));
                   4452:                        error("operator%t() not aM",Ptype(cond));
                   4453:                        n_oper = 0;
                   4454:                        // n_initializer = 0;
                   4455:                        cond = 0;
                   4456:                }
                   4457:                else {
                   4458:                        Pfct f = Pfct(tp);
                   4459:                        // n_initializer = 0;
                   4460:                        Ptype tx = Ptype(cond);
                   4461:                        cond = 0;
                   4462:                        if (f->base != FCT) error("badT for%n::operator%t()",cn,tx);
                   4463:                        if (f->returns != defa_type) {
                   4464:                        //      if (f->returns->check(tx,0)) error("bad resultT for%n::operator%t()",cn,tx);
                   4465:                                error("resultT for%n::operator%t()",cn,tx);
                   4466:                                DEL(f->returns);
                   4467:                        }
                   4468:                        if (f->argtype) {
                   4469:                                error("%n::operator%t()WAs",cn,tx);
                   4470:                                f->argtype = 0;
                   4471:                        }
                   4472:                        f->returns = tx;
                   4473:                        Pname nx = tx->is_cl_obj();
                   4474:                        if (nx && can_coerce(tx,cn->tp)) error("both %n::%n(%n) and %n::operator%t()",cn,cn,nx,tx);
                   4475:                        char buf[1024];
                   4476:                        char* bb = tx->signature(buf);
                   4477:                        int l2 = bb-buf;
                   4478:                        if (1023<l2) error('i',"N::check_oper():N buffer overflow");
                   4479:                        char* p = new char[l2+5];
                   4480:                        p[0] = '_';
                   4481:                        p[1] = '_';
                   4482:                        p[2] = 'o';
                   4483:                        p[3] = 'p';
                   4484:                        strcpy(p+4,buf);
                   4485:                        string = p;
                   4486:                }
                   4487:                break;
                   4488:        }
                   4489: }
                   4490: 
                   4491: Pexpr vbase_args(Pfct a, Pname bn)
                   4492: /*
                   4493:        constructor a calls the constructor bn for a base class
                   4494:        generate argument list needed for virtual base arguments
                   4495: */
                   4496: {
                   4497:        Pfct b = Pfct(bn->tp);
                   4498: //error('d',"vbase_args%n: %t %k",bn,b,b->base);
                   4499:        Pexpr args = 0;
                   4500:        Pexpr tail = 0;
                   4501:        if (b->base == OVERLOAD) b = Pfct(Pgen(b)->fct_list->f->tp);    // doesn't matter which
                   4502:        for (Pname d = b->f_args->n_list; d!=b->argtype; d=d->n_list) {
                   4503:                for (Pname dd = a->f_args->n_list; dd; dd=dd->n_list)
                   4504:                        // using strcmp is a trick
                   4505:                        if (strcmp(dd->string,d->string)==0) break;
                   4506: 
                   4507:                Pexpr aa = new expr(ELIST,dd,0);
                   4508:                if (args == 0)
                   4509:                        args = aa;
                   4510:                else
                   4511:                        tail->e2 = aa;
                   4512:                tail = aa;
                   4513:        }
                   4514:        return args;
                   4515: }
                   4516: 
                   4517: void fct::init_bases(Pclass cl, Pexpr)
                   4518: /*
                   4519:        in "cl"'s constructor "this" generate code to initialize base classes
                   4520:        and members using the initializers "f->f_init"
                   4521:        
                   4522:        this->f_init == list of names of classes to be initialized
                   4523:                COLON(b)        => base class b
                   4524:                                => constructor call in f_init->n_initializer
                   4525:                COLON()         => unnamed base class
                   4526:                                => constructor call in f_init->n_initializer
                   4527:                NAME(m)         => member m
                   4528:                                => constructor call in m->n_initializer
                   4529: */
                   4530: {
                   4531:        Ptable ftbl = body->memtbl;
                   4532:        DB( if(Ddebug>=1) error('d',"init_bases %t init %d",cl,f_init); );
                   4533: 
                   4534:        // explicit initializers
                   4535:        if ( cl && cl->csu == UNION && f_init && f_init->n_list )
                   4536:                error(&f_init->where,"multipleIrs in unionK %s:: %s",cl->string,cl->string);
                   4537:        for (Pname nx, nn=f_init; nn; delete nn,(nn=nx) ) {
                   4538:                Pexpr i = nn->n_initializer;
                   4539:                nn->n_initializer = 0;
                   4540:                nx = nn->n_list;
                   4541: 
                   4542: // error('d',"init_base %s %d",nn->string,i);
                   4543:                if (nn->string) {
                   4544:                        // lookup in case type name hides a "real" member
                   4545:                        { Pname mmm = cl->memtbl->look(nn->string,0);
                   4546:                          if ( mmm ) nn->base = mmm->base;
                   4547:                        }
                   4548:                        if (nn->base == TNAME) {        // base class
                   4549:                                char *bn;
                   4550:                                while ( nn->tp && nn->tp->base == TYPE )
                   4551:                                        nn->tp = Pbase(nn->tp)->b_name->tp;
                   4552:                                if ( nn->tp && nn->tp->base == COBJ )
                   4553:                                    bn = Pbase(nn->tp)->b_name->string;
                   4554:                                else
                   4555:                                    bn = nn->string;
                   4556:                                for (Pbcl l = cl->baselist; l; l=l->next) {
                   4557:                                        Pclass bcl = l->bclass;
                   4558:                                        if ((strcmp(bcl->string,bn) == 0) ||
                   4559:                                                ((bcl->class_base ==
                   4560:                                                        instantiated_template_class) &&
                   4561:                                                ((strcmp(nn->string,
                   4562:                                                        Ptclass(bcl)->unparametrized_tname()->string)) == 0)))
                   4563:                                        {
                   4564: 
                   4565:                                                // l->init is zeroed out in ctor_simpl
                   4566:                                                // if error_count, simpl() not invoked
                   4567:                                                if (l->init && error_count == 0) 
                   4568:                                                        error("twoIrs for%t",bcl);
                   4569:                                                else
                   4570:                                                        l->init = base_init(bcl,i,ftbl,l->obj_offset);
                   4571:                                                goto con;
                   4572:                                        }
                   4573:                                }
                   4574:                                error(&nn->where,"unexpectedAL: noBC%n",nn);
                   4575:                        con:
                   4576:                                continue;
                   4577:                        }
                   4578:                        else {  // member initializer
                   4579:                                Pname m = cl->memtbl->look(nn->string,0);
                   4580:                                if (m && m->n_table==cl->memtbl)
                   4581:                                        m->n_initializer = mem_init(m,i,ftbl);
                   4582:                                else
                   4583:                                        error(&nn->where,"%n not inC %s",nn,cl->string);
                   4584:                        }
                   4585:                }
                   4586:                else {                  // unnamed base class
                   4587:                        Pbcl l = cl->baselist;
                   4588:                        if (l == 0) {
                   4589:                                error("unexpectedAL: noBC called");
                   4590:                                continue;
                   4591:                        }
                   4592: 
                   4593:                        if (l->next) {
                   4594:                                bit cnt = 0, rvb = 0; // remote virtual base classes
                   4595:                                for (Pbcl ll = l; ll; ll = ll->next, ++cnt ) 
                   4596:                                        if (ll->base==VIRTUAL && ll->promoted) ++rvb;
                   4597:                                if ( rvb ) 
                   4598:                                        error("unnamedBCIr: %dBCes(%d non-explicit virtualBC%s)",cnt,rvb,rvb==1?"":"es");
                   4599:                                else error("unnamedBCIr: %dBCes",cnt);
                   4600:                                continue;
                   4601:                        }
                   4602:                        
                   4603:                        if (l->init)
                   4604:                                error("twoIrs for%t",l->bclass);
                   4605:                        else {
                   4606:                                error(strict_opt?0:'w',&nn->where,"N ofBC%t missing from BCIr (anachronism)",l->bclass);
                   4607:                                l->init = base_init(l->bclass,i,ftbl,l->obj_offset);
                   4608:                        }
                   4609:                }
                   4610:        } // for
                   4611: 
                   4612:        for (Pbcl l = cl->baselist; l; l=l->next) {
                   4613:                // default initialization of base classes
                   4614:                Pname ctor;
                   4615:                Pclass bcl = l->bclass;
                   4616:                if (l->init==0 && (ctor=bcl->has_ctor()))
                   4617:                        l->init = base_init(bcl,0,ftbl,l->obj_offset);
                   4618:        }
                   4619: }
                   4620: 
                   4621: int inline_restr;      /* report use of constructs that the inline expanded
                   4622:                           cannot handle here */
                   4623: 
                   4624: void fct::dcl(Pname n)
                   4625: {
                   4626:        int nmem = TBLSIZE;
                   4627:        Pname a;
                   4628:        Pname ll;
                   4629:        Ptable ftbl;
                   4630: 
                   4631:        Pptr cct = 0;
                   4632:        int const_old = const_save;
                   4633: 
                   4634:        int bit_old = bit_offset;
                   4635:        int byte_old = byte_offset;
                   4636:        int max_old = max_align;
                   4637: 
                   4638:        if (base != FCT) error('i',"F::dcl(%d)",base);
                   4639:        if (body == 0) error('i',"F::dcl(body=%d)",body);
                   4640:        if (n==0 || n->base!=NAME) error('i',"F::dcl(N=%d %d)",n,(n)?n->base:0);
                   4641:        DB( if(Ddebug>=1) error('d',"fct::dcl(%n) %k %d %t",n,n->n_scope,body->own_tbl,this); );
                   4642:        if (body->own_tbl) return;      // done already
                   4643: 
                   4644: //     if (f_inline==0 ) n->n_dcl_printed = 1; // beware of recursive calls, no decl needed
                   4645: //     if (f_inline && debug_opt) n->n_dcl_printed = 2;
                   4646:        if (body->memtbl == 0) body->memtbl = new table(nmem+3,gtbl,0);
                   4647:        body->own_tbl = 1;
                   4648:        ftbl = body->memtbl;
                   4649:        ftbl->real_block = body;
                   4650: 
                   4651:        max_align = 0;//AL_FRAME;
                   4652:        bit_offset = 0;
                   4653: 
                   4654:        cc->stack();
                   4655:        cc->nof = n;
                   4656:        cc->ftbl = ftbl;
                   4657: 
                   4658:        switch (n->n_scope) {
                   4659:        case 0:
                   4660:        case PUBLIC:
                   4661:        {       cc->not = n->n_table->t_name;
                   4662:                cc->cot = Pclass(cc->not->tp);
                   4663:                cc->tot = cc->cot->this_type;
                   4664:        //      if (f_this==0 || cc->tot==0) error('i',"F::dcl(%n): f_this=%d cc->tot=%d",n,f_this,cc->tot);
                   4665:                if (f_this) f_this->n_table = ftbl;     // fake for inline printout
                   4666:                cc->c_this = f_this;
                   4667: 
                   4668: 
                   4669:                Pclass cl = Pclass(cc->not->tp);
                   4670: 
                   4671:                if (cl->c_body!=3
                   4672:                || n->n_initializer
                   4673:                || n->n_sto==STATIC
                   4674:                || f_inline
                   4675:                || f_imeasure
                   4676:                || f_virtual==0)
                   4677:                        ;
                   4678:                else {          // could be the function where we need to
                   4679:                                // output the vtbl
                   4680:                        int i;
                   4681:                        for (Pname nn=cl->memtbl->get_mem(i=1); nn; nn=cl->memtbl->get_mem(++i) ) {
                   4682:                        Ptype t = nn->tp;
                   4683:                        if (t)
                   4684:                        switch (t->base) {
                   4685:                        case FCT:
                   4686:                                if (nn == n) goto prnt;
                   4687:                                if (nn->n_initializer
                   4688:                                || nn->n_sto==STATIC
                   4689:                                || Pfct(nn->tp)->f_inline
                   4690:                                || Pfct(nn->tp)->f_imeasure
                   4691:                                || Pfct(nn->tp)->f_virtual==0) break;
                   4692:                                goto zaq;
                   4693: 
                   4694:                        case OVERLOAD:
                   4695:                        {       for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) {
                   4696:                                        Pname nn = gl->f;
                   4697:                                        if (nn == n) goto prnt;
                   4698:                                        if (nn->n_initializer
                   4699:                                        || nn->n_sto==STATIC
                   4700:                                        || Pfct(nn->tp)->f_inline
                   4701:                                        || Pfct(nn->tp)->f_imeasure
                   4702:                                        || Pfct(nn->tp)->f_virtual==0) continue;
                   4703:                                        goto zaq;
                   4704:                                }
                   4705:                        }
                   4706:                        }
                   4707:                }
                   4708:                        goto zaq;
                   4709:                prnt:
                   4710:                        cl->print_all_vtbls(cl);
                   4711:                        goto zaq;
                   4712:                }
                   4713:        }
                   4714:        }
                   4715: zaq:
                   4716:                // protect against: class x; x f(); class x { x(x&); ....
                   4717:        if (f_result == 0) make_res(this);
                   4718:        if (f_result) f_result->n_table = ftbl;         // fake for inline printout
                   4719: 
                   4720:        returns->tsizeof();     // make sure size is known
                   4721: 
                   4722:        Pname ax;
                   4723:        for (a=argtype, ll=0; a; a=ax) {
                   4724:                ax = a->n_list;
                   4725:                Pname nn = a->dcl(ftbl,ARG);
                   4726:                Pname cn = nn->tp->is_cl_obj();
                   4727:                if (cn == 0) cn = cl_obj_vec;
                   4728:                if (cn) (void)cn->tp->tsizeof();        // make sure it is printed
                   4729:                nn->n_assigned_to = nn->n_used = nn->n_addr_taken = 0;
                   4730:                nn->n_list = 0;
                   4731: 
                   4732:                switch (nn->tp->base) {
                   4733:                case CLASS:
                   4734:                case ENUM:      /* unlink types declared in arg list */
                   4735:                        nn->dcl_print(0);
                   4736:                        break;
                   4737:                default:
                   4738:                        if (ll)
                   4739:                                ll->n_list = nn;
                   4740:                        else
                   4741:                                f_args = argtype = nn;
                   4742:                        ll = nn;
                   4743:                }
                   4744:                delete a;
                   4745:        }
                   4746: 
                   4747:        if (f_result) {         // link in f_result
                   4748:                f_args = f_result;
                   4749:                f_result->n_list = argtype;
                   4750:        }
                   4751: 
                   4752:        if (f_this) {           // link in f_this
                   4753:                f_args = f_this;
                   4754:                f_this->n_list = f_result ? f_result : argtype;
                   4755:        }
                   4756: 
                   4757:        if (n->n_oper==CTOR || n->n_oper==DTOR) vbase_pointers(n,cc->cot);
                   4758: 
                   4759:        if (n->n_oper == CTOR) {
                   4760:                const_save = 1;
                   4761:                init_bases(cc->cot,f_init);
                   4762:        }
                   4763:        else if (f_init)
                   4764:                error(0,"unexpectedAL: not aK");
                   4765: 
                   4766:        PERM(returns);
                   4767:        const_save = f_inline&&debug_opt==0;
                   4768:        inline_restr = 0;
                   4769:        body->dcl(ftbl);
                   4770:        
                   4771:        defined |= DEFINED;
                   4772:        if (f_inline && inline_restr && returns->base!=VOID) {
                   4773:                f_inline = 0;
                   4774:                char* s = (inline_restr & 32) ? "continue"
                   4775:                        : (inline_restr & 16) ? "break"
                   4776:                        : (inline_restr & 8) ? "loop"
                   4777:                        : (inline_restr & 4) ? "switch"
                   4778:                        : (inline_restr & 2) ? "goto"
                   4779:                        : (inline_restr & 1) ? "label"
                   4780:                        : "" ;
                   4781:                if (warning_opt) {
                   4782:                        error('w', "\"inline\" ignored, %n contains %s",n,s);
                   4783:                        error('w', "out-of-line copy of %n created",n);
                   4784:                }
                   4785:        //      if (cc->cot)
                   4786:                n->simpl();     //BS6
                   4787:                n->dcl_print(0);
                   4788:        }
                   4789:        const_save = const_old;
                   4790: 
                   4791:        if (f_inline && debug_opt==0) isf_list = new name_list(n,isf_list);
                   4792: 
                   4793:        bit_offset = bit_old;
                   4794:        byte_offset = byte_old;
                   4795:        max_align = max_old;
                   4796:        cc->unstack();
                   4797: 
                   4798: //error('d',"fct-> returns %t",returns);
                   4799: }
                   4800: 
                   4801: Pexpr fct::base_init(Pclass bcl, Pexpr i, Ptable ftbl, int offset)
                   4802: /*
                   4803:        have base class bcl and expr list i
                   4804:        return "( *(base*)this ) . ctor( i )"
                   4805:        ctor call generated in expr.typ()
                   4806: */
                   4807: {
                   4808:        Ptype ty = bcl->this_type;
                   4809:        Pexpr th = rptr(ty,f_this,offset);              // base*
                   4810:        Pname ctor = bcl->has_ctor();
                   4811: 
                   4812: //error('d',"fct::B_init(C %t, i %d, %d) ctor %n",bcl,i,i?i->tp:0,ctor);
                   4813: 
                   4814:        Pexpr ii = (i && i->base==ELIST)?i->e1:i;
                   4815: 
                   4816:        if (ii
                   4817:        && ii->base==DEREF
                   4818:        && ii->e1->base==CAST
                   4819:        && th->base==CAST) th->i2 = ii->e1->i2;
                   4820: 
                   4821:        if (ctor == 0) {
                   4822:                if (i && i->base!=ELIST) i = new expr(ELIST,i,0);
                   4823: 
                   4824:                Pexpr v = new texpr(VALUE,bcl,i);       // ?.base(i)
                   4825:                v->e2 = new expr(DEREF,th,0);           // (*(base*)this).base(i)
                   4826:                v = v->typ(ftbl);                       // *base(&*(base*)this,i)
                   4827: //error('d',"v %k",v->base);
                   4828:                switch (v->base) {
                   4829:                case DEREF:
                   4830:                        return v->e1;                   // base(&*(base*)this,i)
                   4831:                case ASSIGN:            // degenerate base(base&): *(base*)this=i
                   4832:                        th = new texpr(CAST,ty,f_this);
                   4833:                        v = new expr(CM,v,th);          // (*(base*)this=i,(base*)this);
                   4834:                        return v->typ(ftbl);
                   4835:                default:
                   4836:                        return 0;
                   4837:                }
                   4838:        }
                   4839: 
                   4840: 
                   4841:        Pname icn;
                   4842:        if (i) {
                   4843:                ii = ii->typ(ftbl);
                   4844:                if (bcl->has_itor()==0
                   4845:                && (icn=ii->tp->is_cl_obj())
                   4846:                && (Pclass(icn->tp)==bcl || Pclass(icn->tp)->has_base(bcl))) {
                   4847:                        // degenerate base(base&): *(base*)this=i
                   4848:                        // memberwise copy
                   4849: //error('d',"copy %t",ty);
                   4850:                //      th = new cast(ty,f_this);
                   4851:                //      th = th->contents();
                   4852:                        th = new texpr(CAST,ty,f_this);
                   4853:                        th = th->contents();
                   4854:                        th = th->typ(ftbl);
                   4855:                        if (Pclass(icn->tp)!=bcl) {     // cast needed
                   4856:                                Pptr r = new ptr(RPTR,Pptr(ty)->typ);
                   4857:                                ii = new texpr(CAST,r,ii);
                   4858:                                ii = ii->typ(ftbl);
                   4859:                        }
                   4860:                        ii = new expr(ASSIGN,th,ii);
                   4861:                        ii->tp = th->tp;
                   4862:                                        // simulate `return this':
                   4863:                                        // *(base*)this=i,(base*)this
                   4864:                        ii = new expr(CM,ii,new cast(ty,f_this));
                   4865:                        ii->tp = th->tp;
                   4866:                        return ii;
                   4867:                //      return ii->typ(ftbl);   // don't find cl::operator=()
                   4868:                }
                   4869:                if (i->base == ELIST) i->e1 = ii;
                   4870:        }
                   4871: //Pexpr x = call_ctor(ftbl,th,ctor,i,REF,vbase_args(this,ctor));
                   4872: //error('d',"call %n %t -> %d %k",ctor,ctor->tp,x,x->base);
                   4873: //     return x;
                   4874:        return call_ctor(ftbl,th,ctor,i,REF,vbase_args(this,ctor));
                   4875: }
                   4876: 
                   4877: 
                   4878: Pexpr fct::mem_init(Pname mn, Pexpr i, Ptable ftbl)
                   4879: /*
                   4880:        return "member_ctor( m, i )"
                   4881: */
                   4882: {
                   4883: // a new entry for B::B_pub, in general, has no tp and no
                   4884: // real info: all the tp-> only work on our systems because
                   4885: // 0 pointer dereference isn't system memory.  it core dumps
                   4886: // in set_const since no test is made on this == 0.
                   4887: //error('d',"mem_init %n",mn);
                   4888: 
                   4889: //     if (mn->n_stclass == STATIC) error('s',"MIr for static%n",mn);
                   4890:         switch (mn->n_stclass) {
                   4891:         case STATIC:
                   4892:                 error("MIr for static%n",mn);
                   4893:                 break;
                   4894:         case ENUM:
                   4895:                 error("MIr for enumeration constant%n", mn);     
                   4896:                 break;
                   4897:         }
                   4898: 
                   4899:        Pname member = (mn->base==PUBLIC && mn->n_qualifier) ? mn->n_qualifier : mn;
                   4900: 
                   4901:        if (i) i = i->typ(ftbl);
                   4902:        Pname cn = member->tp->is_cl_obj();     // first find the class name
                   4903: 
                   4904: //     if (member->n_stclass == STATIC) error('s',"MIr for static%n",member);
                   4905: //     if (i) i = i->typ(ftbl);
                   4906: //     Pname cn = member->tp->is_cl_obj();     // first find the class name
                   4907:        Pref tn = new ref(REF,f_this,member);
                   4908:        tn->tp = member->tp;
                   4909: //error('d',"MI for %n %t = %t",member,member->tp,i?i->tp:0);
                   4910: //error('d',"fthis %d %t member %n tp %t",f_this,f_this->tp,member,tn->tp);
                   4911:        if (cn) {
                   4912:                Pclass mcl = Pclass(cn->tp);    // then find the classdef
                   4913:                Pname ctor = mcl->has_ctor();
                   4914:                Pname icn;
                   4915: 
                   4916:                if (i
                   4917:                && mcl->has_itor()==0
                   4918:                && (icn=i->tp->is_cl_obj())
                   4919:                && Pclass(icn->tp)==mcl) {      // bitwise copy
                   4920:                        Pexpr init = new expr(ASSIGN,tn,i);
                   4921:                        init->tp = tn->tp;
                   4922:                //      return init->typ(ftbl); // don't look for mcl.operator=()
                   4923:                        member->assign();
                   4924:                        return init;
                   4925:                }
                   4926:                
                   4927:                if (ctor) return call_ctor(ftbl,tn,ctor,i,DOT);
                   4928: 
                   4929:                error("Ir forM%nW noK",member);
                   4930:                return 0;
                   4931:        }
                   4932: 
                   4933:        if (cl_obj_vec) {
                   4934:                if (i && i->base == ELIST)
                   4935:                        error("illegalIrL for %t%nWinM initializationL",mn->tp,mn);
                   4936:                else error('s',"Ir forCM %t%nWK",mn->tp,mn);
                   4937:                return 0;
                   4938:        }
                   4939: 
                   4940:        if (i && i->base == ELIST) {
                   4941:                if (i->e2) error("Ir for%n not a simpleE",member);
                   4942:                i = i->e1;
                   4943:        }
                   4944: 
                   4945:        if (member->tp->is_ref() && (i == 0)) {
                   4946:                error("empty Ir for reference %n", member);
                   4947:                return 0 ;
                   4948:        }
                   4949: 
                   4950: // error( 'd', "fct_mem_init: %n %k", member, member->tp->base );
                   4951:        switch (member->tp->base) {
                   4952:        // case RPTR:
                   4953:        //      if ( i == 0 ) {
                   4954:        //              error( "empty Ir for reference %n", member );
                   4955:        //              return 0;
                   4956:        //      }
                   4957:        //      break;
                   4958:        case VEC:
                   4959:        case FCT:
                   4960:        case OVERLOAD:
                   4961:                error("Ir for%n ofT %t",member,member->tp);
                   4962:                return 0;
                   4963:        }
                   4964: 
                   4965: //error('d',"tp %t",member->tp);
                   4966:        if (member->tp->tconst()) {
                   4967:                 int save_ignore_const = ignore_const;
                   4968:                 ignore_const = 1;
                   4969:                 i = new expr(ASSIGN,tn,i);
                   4970:                 i = i->typ(ftbl);
                   4971:                 ignore_const = save_ignore_const;
                   4972:                 return i;
                   4973:        }
                   4974: 
                   4975:        Pptr pt;
                   4976:        if (pt = member->tp->is_ref()) {
                   4977:                switch (pt->typ->base) {
                   4978:                case FCT:
                   4979:                case OVERLOAD:
                   4980:                        i = ptr_init(pt,i,ftbl);
                   4981:                        break;
                   4982:                default:
                   4983:                        i = ref_init(pt,i,ftbl);
                   4984:                }
                   4985:                i = new expr(ASSIGN,tn,i);
                   4986:                i->tp = tn->tp;
                   4987:                member->assign();       // cannot call typ: would cause dereference
                   4988:                return i;
                   4989:        }
                   4990: 
                   4991:        i = new expr(ASSIGN,tn,i);
                   4992:        return i->typ(ftbl);    // typ performs the type check on the assignment
                   4993: }
                   4994: 
                   4995: Pexpr replace_temp(Pexpr e, Pexpr n)
                   4996: /*
                   4997:        e is on the form
                   4998:                                f(&temp,arg) , temp
                   4999:                        or
                   5000:                                &temp->ctor(arg) , temp
                   5001:                        or
                   5002:                                x->f(&temp,arg) , temp
                   5003:        change it to
                   5004:                                f(n,arg)
                   5005:                        or
                   5006:                                n->ctor(arg)
                   5007: */
                   5008: {
                   5009:        Pexpr c = e->e1;        // f(&temp,arg) or &temp->ctor(args)
                   5010:        Pexpr ff = c->e1;
                   5011:        Pexpr a = c->e2;        // maybe ELIST(&temp,arg)
                   5012:        Pexpr tmp = e->e2;
                   5013: 
                   5014: //error('d',"suppress(%d %k) %n",tmp->base,tmp->base,tmp->base==NAME?tmp:0);
                   5015:        if (tmp->base==DEREF) tmp = tmp->e1;
                   5016:        if (tmp->base==CAST) tmp = tmp->e1;
                   5017:        if (tmp->base==ADDROF || tmp->base==G_ADDROF) tmp = tmp->e2;
                   5018:         if (tmp->base != NAME) return e; //error('i',"replace %k",tmp->base);
                   5019:        tmp->tp = any_type;     // temporary not used: suppress it
                   5020: 
                   5021: //error('d',"replace_temp(%k %k) c %k ff %k",e->base,n->base,c->base,ff->base);
                   5022:        switch (ff->base) {
                   5023:        case REF:
                   5024:                if (ff->e1->base==G_ADDROF && ff->e1->e2==tmp)
                   5025:                        a = ff;                         // &tmp -> f()
                   5026:                break;
                   5027:        case DOT:
                   5028:                if (ff->e1->base==NAME && ff->e1==tmp) {
                   5029:                        a = ff;                         // tmp . f()
                   5030:                        a->base = REF;
                   5031:                }
                   5032:                break;
                   5033:        }
                   5034:        a->e1 = n;
                   5035:        return c;
                   5036: }
                   5037: 
                   5038: Pname classdef::has_ictor()
                   5039: /*
                   5040:        does this class have a constructor taking no arguments?
                   5041: */
                   5042: {
                   5043:        Pname c = has_ctor();
                   5044:        if (c == 0) return 0;
                   5045:        
                   5046:        Pfct f = Pfct(c->tp);
                   5047: 
                   5048:        switch (f->base) {
                   5049:        default:
                   5050:                error('i',"%s: badK (%k)",string,c->tp->base);
                   5051:        
                   5052:        case FCT:
                   5053:                switch (f->nargs) {
                   5054:                case 0:         return c;
                   5055:                default:        if (f->argtype->n_initializer) return c;
                   5056:                }
                   5057:                return 0;
                   5058: 
                   5059:        case OVERLOAD:
                   5060:        {       for (Plist l=Pgen(f)->fct_list; l; l=l->l) {
                   5061:                        Pname n = l->f;
                   5062:                        f = (Pfct)n->tp;
                   5063:                        switch (f->nargs) {
                   5064:                        case 0:         return n;
                   5065:                        default:        if (f->argtype->n_initializer) return n;
                   5066:                        }
                   5067:                }
                   5068:                return 0;
                   5069:        }
                   5070:        }
                   5071: }
                   5072: 
                   5073: int add_first; // fudge, use ctor arg instead
                   5074: Pname gen::add(Pname n)
                   5075: /*
                   5076:        add "n" to the tail of "fct_list"
                   5077:        (overloaded names are searched in declaration order)
                   5078: 
                   5079:        detect:         multiple identical declarations
                   5080:                        declaration after use
                   5081:                        multiple definitions
                   5082: */
                   5083: {
                   5084:        Pfct f = Pfct(n->tp);
                   5085:        Pname nx;
                   5086: //error('d',"add(%n) %d",n,add_first);
                   5087:        if (f->base != FCT) error("%n: overloaded nonF",n);
                   5088: 
                   5089:        if ( fct_list && (nx=find(f,1)) ) {
                   5090: //error('d',"found %n %t",nx,nx->tp);
                   5091:                Linkage l1 = Pfct(nx->tp)->f_linkage;
                   5092:                Linkage l2 = f->f_linkage;
                   5093:                if ( l2 != linkage_default && l1 != l2 )
                   5094:                        error("inconsistent linkage specifications for%n",n);
                   5095:                Nold = 1;
                   5096:        }
                   5097:        else {
                   5098:                if (add_first==0 && f->f_signature==0) f->sign();
                   5099: //error('d',"signature: %d \"%s\" fct_list %d",f->f_signature,f->f_signature,fct_list);
                   5100:                nx = new name;
                   5101:                *nx = *n;
                   5102:                // nx->n_tbl_list = Pname(n->string);
                   5103:                 nx->n_gen_fct_name = n->string;
                   5104:                PERM(nx);
                   5105:                Nold = 0;
                   5106:                if (fct_list) {
                   5107:                        int clink = (f->f_linkage==linkage_C);
                   5108:                        Plist gl=fct_list;
                   5109:                        for(;;) {
                   5110:                                if (clink
                   5111:                                && Pfct(gl->f->tp)->f_linkage == linkage_C ) {
                   5112:                                        error("two%ns with c linkage",n);
                   5113:                                        if(f->f_signature==0) f->sign();
                   5114:                                }
                   5115:                                if (gl->l)
                   5116:                                        gl = gl->l;
                   5117:                                else
                   5118:                                        break;
                   5119:                        }
                   5120:                        gl->l = new name_list(nx,0); 
                   5121:                }
                   5122:                else
                   5123:                        fct_list = new name_list(nx,0);
                   5124:                nx->n_list = 0;
                   5125:        }
                   5126:        return nx;
                   5127: }
                   5128: 
                   5129: void fct::sign()
                   5130: {
                   5131:        switch ( f_linkage ) {
                   5132:        case linkage_C:
                   5133:                f_signature = "";
                   5134:                return;
                   5135:        case linkage_Cplusplus:
                   5136:        case linkage_default:
                   5137:                break;
                   5138:        }
                   5139:        char buf[1024];
                   5140:        char* bb = signature(buf);
                   5141:        int ll = bb-buf;
                   5142:        if (1023 < ll) error('i',"gen::add():N buffer overflow");
                   5143:        char* p = new char[ll+1];
                   5144:        strcpy(p,buf);
                   5145:        f_signature = p;
                   5146: //error('d',"fct::sign %s",p);
                   5147: }
                   5148: 
                   5149: Pname gen::find(Pfct f, bit warn)
                   5150: {      
                   5151:        for (Plist gl=fct_list; gl; gl=gl->l) {
                   5152:                Pname n = match(gl->f,f,warn);
                   5153:                if (n) return n;
                   5154:        }
                   5155:        return 0;
                   5156: }
                   5157: 
                   5158: Pname gen::match(Pname nx, Pfct f, bit warn)
                   5159: {
                   5160:        Pfct fx = Pfct(nx->tp);
                   5161:        Pname a, ax;
                   5162:        int op = 0;     // overloading problem: const, ref, vec/ptr, or basetype
                   5163: //error('d',"fx %d %d f %d %d",fx->nargs_known,fx->nargs,f->nargs_known,f->nargs);
                   5164: 
                   5165:        if (f->nargs_known != fx->nargs_known) return 0; // the bets are off
                   5166:                                                         // must rely on checks at
                   5167:                                                         // call points
                   5168:        if (f->f_const != fx->f_const) return 0;
                   5169: 
                   5170:        if (fx->nargs != f->nargs
                   5171:        && fx->nargs_known==1
                   5172:        && f->nargs_known==1) return 0; // no warning for potential
                   5173:                                        // problems due to default args
                   5174:        
                   5175:        for (ax=fx->argtype, a=f->argtype; a&&ax; ax=ax->n_list, a=a->n_list) {
                   5176:                Ptype at = ax->tp;
                   5177:                Ptype atp = a->tp;
                   5178: //error('d',"at %t atp %t",at,atp);
                   5179:                if (at->check(atp,OVERLOAD) == 0) {
                   5180: //error('d',"at %t atp %t cp %d vrp %d",at,atp,const_problem,vrp_equiv);
                   5181:                        continue;
                   5182:                }
                   5183: //error('d',"warn %d",warn);
                   5184:                if (warn == 0) goto xx;
                   5185: 
                   5186:                /*
                   5187:                        warn against:
                   5188:                                overload f(X&), f(X);           error
                   5189:                                overload f(int), f(const);      error
                   5190:                                overload f(int*), f(int[10]);   warn
                   5191:                        etc.
                   5192:                */
                   5193: 
                   5194: //error('d',"vrp_equiv %d const_problem %d",vrp_equiv,const_problem);
                   5195:                if (const_problem) {    // differ only in X vs const X
                   5196:                        if (at->is_ptr_or_ref()) return 0;
                   5197:                        op++;
                   5198:                        continue;
                   5199:                }
                   5200: 
                   5201:        aaa:
                   5202:                switch (atp->base) {
                   5203:                case TYPE:
                   5204:                        atp = Pbase(atp)->b_name->tp;
                   5205:                        goto aaa;
                   5206:        //      case EOBJ:
                   5207:        //              atp = Penum(Pbase(atp)->b_name->tp)->e_type;
                   5208:        //              goto aaa;
                   5209:                case RPTR:      // differ only by X vs X& ?
                   5210:                        if (Pptr(atp)->typ->check(at,0)==0) {
                   5211:                                op++;
                   5212:                                continue;
                   5213:                        }
                   5214:                }
                   5215: 
                   5216:        atl:
                   5217:                switch (at->base) {
                   5218:                case TYPE:
                   5219:                        at = Pbase(at)->b_name->tp;
                   5220:                        goto atl;
                   5221:        //      case EOBJ:
                   5222:        //              at = Penum(Pbase(at)->b_name->tp)->e_type;
                   5223:        //              goto atl;
                   5224:                case RPTR:      // differ only by X& vs X ?
                   5225:                        if (Pptr(at)->typ->check(atp,0)==0) {
                   5226:                                op++;
                   5227:                                continue;
                   5228:                        }
                   5229:                        break;
                   5230:        //      case CHAR:      // differ only by int vs char ?
                   5231:        //      case SHORT:
                   5232:        //      case INT:
                   5233:                //      if (atp->base!=at->base && atp->base==EOBJ) {
                   5234:                //              op++;
                   5235:                //              continue;
                   5236:                //      }
                   5237:        //              break;
                   5238:                }
                   5239: //error('d',"return 0");
                   5240:                //goto xx;
                   5241:                // some argument is really different
                   5242:                // e.g. f(int), f(char*);
                   5243:                return 0;
                   5244:        }
                   5245: 
                   5246:        // arguments checked. Now look at leftover args, return type,etc.
                   5247: 
                   5248: //     if (warn && a && fx->nargs_known==ELLIPSIS) error('w',"... in%n'sAT hidesATs from the overloading mechanism",nx);
                   5249: 
                   5250:        if (a || ax) return 0;
                   5251: 
                   5252:        if (op == 0) {
                   5253:                if (warn && fx->returns->check(f->returns,0))
                   5254:                        error("two different return valueTs for%n: %t and %t",nx,fx->returns,f->returns);
                   5255: 
                   5256:                return nx;
                   5257:        }
                   5258: xx:
                   5259:        if (warn && op)
                   5260:                error("the overloading mechanism cannot tell a%t from a%t",fx,f);
                   5261: 
                   5262:        return 0;
                   5263: }
                   5264: 
                   5265: int name::no_of_names()
                   5266: {
                   5267:        register int i = 0;
                   5268:        register Pname n;
                   5269:        for (n=this; n; n=n->n_list) i++;
                   5270:        return i;
                   5271: }
                   5272: 
                   5273: static Pexpr lvec[20], *lll, *curr_e;
                   5274: static Pexpr last_il = 0;
                   5275: static Pexpr list_back = 0;
                   5276: static Pexpr last_el = 0, *last_lll;
                   5277: 
                   5278: void new_list(Pexpr lx)
                   5279: {
                   5280:        if (lx->base != ILIST) error('i',"IrLX");
                   5281: 
                   5282:        lll = last_lll = lvec;
                   5283:        lll++;
                   5284:        *lll = last_el = lx->e1;
                   5285: }
                   5286: 
                   5287: Pexpr next_elem()
                   5288: {
                   5289:        Pexpr e;
                   5290:        Pexpr lx;
                   5291: 
                   5292:        if (lll == lvec) return 0;
                   5293: 
                   5294:        lx = *lll;
                   5295: 
                   5296:        if (list_back) {
                   5297:                e = list_back;
                   5298:                list_back = 0;
                   5299:                return e;
                   5300:        }
                   5301: 
                   5302:        if (lx == 0) {                          /* end of list */
                   5303:                lll--;
                   5304:                return 0;
                   5305:        }
                   5306: 
                   5307:        switch (lx->base) {
                   5308:        case ELIST:
                   5309:                e = lx->e1;
                   5310:                curr_e = &lx->e1;
                   5311:                last_el = lx;
                   5312:                last_lll = lll;
                   5313:                *lll = lx->e2;
                   5314:                switch (e->base) {
                   5315:                case ILIST:
                   5316:                        lll++;
                   5317:                        *lll = e->e1;
                   5318:                        last_il = e;
                   5319:                        return Pexpr(1);        // start of new ILIST
                   5320:                case ELIST:
                   5321:                        error("nestedEL");
                   5322:                        return 0;
                   5323:                default:
                   5324:                {
                   5325:                        if (need_sti(e)) error('s',"generalIr inIrL");
                   5326:                        return e;
                   5327:                }
                   5328:                }
                   5329:        case IVAL:
                   5330:        case ZERO:
                   5331:                lll--;
                   5332:                return 0;
                   5333:        default:
                   5334:                error('i',"IrL %k",lx->base);
                   5335:        }
                   5336: }
                   5337: 
                   5338: static Pexpr insert_init(Pexpr newval) {
                   5339: // splice an initializer in front of the next element in the
                   5340: // initializer list.  Provides initializers for unnamed bitfields.
                   5341:        Pexpr t = new expr(ELIST,last_el->e1,last_el->e2);
                   5342: 
                   5343:        last_el->e1=newval;
                   5344:        last_el->e2=t;
                   5345:        lll = last_lll;
                   5346:        *lll = last_el;
                   5347:        return next_elem();
                   5348: }
                   5349: 
                   5350: void skip_ilist()
                   5351: // skip ilist use to represent pointer to member function literal
                   5352: {
                   5353:        Pexpr e = next_elem();
                   5354:        e = next_elem();
                   5355: }
                   5356: 
                   5357: void list_check(Pname nn, Ptype t, Pexpr il, Ptable tbl)
                   5358: /*
                   5359:        see if the list "lll" can be assigned to something of type "t"
                   5360:        "nn" is the name of the variable for which the assignment is taking place.
                   5361:        "il" is the last list element returned by next_elem()
                   5362: */
                   5363: {
                   5364:        Pexpr e;
                   5365:        bit lst = 0;
                   5366:        int i;
                   5367:        Pclass cl;
                   5368:        int tdef = 0;
                   5369: 
                   5370: //error('d',"list_check%n: %t (%d)",nn,t,il);
                   5371:        if (il == Pexpr(1)) {
                   5372:                lst = 1;
                   5373:                e = il;
                   5374:        }
                   5375:        else if (il)
                   5376:                list_back = il;
                   5377: 
                   5378: zzz:
                   5379:        switch (t->base) {
                   5380:        case TYPE:
                   5381:                t = Pbase(t)->b_name->tp;
                   5382:                tdef = 1;
                   5383: 
                   5384:                // did it used to be a VEC before arg_fudge was applied?
                   5385:                 if (t->base==PTR && Pvec(t)->size)
                   5386:                         t->base=VEC;
                   5387:                 goto zzz;
                   5388: 
                   5389:        case VEC:
                   5390:        {       Pvec v = Pvec(t);
                   5391:                Ptype vt = v->typ;
                   5392: 
                   5393:                if (v->size) {  /* get at most v->size initializers */
                   5394:                        if (v->typ->base == CHAR) {
                   5395:                                e = next_elem();
                   5396:                                if (e->base == STRING) {        // v[size] = "..."
                   5397:                                        int isz = Pvec(e->tp)->size;
                   5398:                                        if (v->size < isz) error("Ir too long (%d characters) for%n[%d]",isz,nn,v->size);
                   5399:                                        break;
                   5400:                                }
                   5401:                                else
                   5402:                                        list_back = e;
                   5403:                        }
                   5404:                        for (i=0; i<v->size; i++) { // check next list element type
                   5405:                                Pfct MP = 0;
                   5406:                        ee:
                   5407:                                e = next_elem();
                   5408:                                if (e == 0) goto xsw; // too few initializers are ok
                   5409:                        vtz:
                   5410: //error('d',"vtz: %d",vt->base);
                   5411:                                switch (vt->base) {
                   5412:                                case TYPE:
                   5413:                                        vt = Pbase(vt)->b_name->tp;
                   5414:                                        goto vtz;
                   5415:                                case VEC:
                   5416:                                case COBJ:
                   5417:                                        list_check(nn,vt,e);
                   5418:                                        break;
                   5419:                                case PTR:
                   5420:                                        if ((MP = vt->memptr()) &&
                   5421:                                            e==Pexpr(1)) {
                   5422:                                                if (vt->check(last_il->tp,ASSIGN))
                   5423:                                                        error("badIrT for%n:%t (%tX)",v,last_il->tp,vt);
                   5424:                                                skip_ilist();
                   5425:                                                break;
                   5426:                                        }
                   5427:                                        if (MP && e && e->base==ZERO) {
                   5428:                                                *curr_e = new expr(ELIST,zero,zero);
                   5429:                                                *curr_e = new expr(ILIST,*curr_e,zero);
                   5430:                                                (*curr_e)->tp = zero_type;
                   5431:                                                break;
                   5432:                                        }
                   5433:                                        if (MP && e && e->tp->base==OVERLOAD) {
                   5434:                                                Pexpr op = ptof(Pfct(Pptr(vt)->typ),e,tbl);
                   5435:                                                if(op) {
                   5436:                                                        *curr_e = op;
                   5437:                                                        break;
                   5438:                                                }
                   5439:                                        }
                   5440:                                        // no break
                   5441:                                default:
                   5442:                                {
                   5443:                                        if (e == (Pexpr)1) {
                   5444:                                                error("unexpectedIrL");
                   5445:                                                goto ee;
                   5446:                                        }
                   5447: 
                   5448:                                        if (vt->check(e->tp,ASSIGN))
                   5449:                                                error("badIrT for%n:%t (%tX)",nn,e->tp,vt);
                   5450: 
                   5451:                                        Pptr p;
                   5452:                                        if (vt->check(e->tp,0)
                   5453:                                        && (p=vt->is_ptr())
                   5454:                                        && Ptype(p)!=zero_type
                   5455:                                        && p->typ!=char_type) {
                   5456:                                                Pexpr te = e;
                   5457:                                                Ptype t = p->typ;
                   5458:                                                while ( t->base == TYPE ) t = Pbase(t)->b_name->tp;
                   5459:                                                if ( t->base == COBJ )
                   5460:                                                        te = ptr_init( p, e, tbl );
                   5461:                                                if ( te == e )
                   5462:                                                        *curr_e = new cast(vt,e);
                   5463:                                                else *curr_e = te;
                   5464:                                        }
                   5465:                                }
                   5466:                                }
                   5467:                        }
                   5468:                        if ( lst && (e=next_elem()) ) error("end ofIrLX after array");
                   5469:                xsw:;
                   5470:                }
                   5471:                else {          /* determine v->size */
                   5472:                        i = 0;
                   5473:                        (void) v->typ->tsizeof();
                   5474:                xx:
                   5475:                        while ( e=next_elem() ) {       // get another initializer
                   5476:                                Pfct MP = 0;
                   5477:                                i++;
                   5478:                        vtzz:
                   5479: //error('d',"vtzz");
                   5480:                                switch (vt->base) {
                   5481:                                case TYPE:
                   5482:                                        vt = Pbase(vt)->b_name->tp;
                   5483:                                        goto vtzz;
                   5484:                                case VEC:
                   5485:                                case COBJ:
                   5486:                                        list_check(nn,vt,e);
                   5487:                                        break;
                   5488:                                case PTR:
                   5489:                                        if((MP = vt->memptr()) &&
                   5490:                                            e==Pexpr(1)) {
                   5491:                                                if (vt->check(last_il->tp,ASSIGN))
                   5492:                                                        error("badIrT for%n:%t (%tX)",v,last_il->tp,vt);
                   5493:                                                skip_ilist();
                   5494:                                                break;
                   5495:                                        }
                   5496:                                        if (MP && e && e->base==ZERO) {
                   5497:                                                *curr_e = new expr(ELIST,zero,zero);
                   5498:                                                *curr_e = new expr(ILIST,*curr_e,zero);
                   5499:                                                (*curr_e)->tp = zero_type;
                   5500:                                                break;
                   5501:                                        }
                   5502:                                        if (MP && e && e->tp->base==OVERLOAD) {
                   5503:                                                Pexpr op = ptof(Pfct(Pptr(vt)->typ),e,tbl);
                   5504:                                                if(op) {
                   5505:                                                        *curr_e = op;
                   5506:                                                        break;
                   5507:                                                }
                   5508:                                        }
                   5509:                                        // no break
                   5510:                                default:
                   5511:                                {       if (e == Pexpr(1)) {
                   5512:                                                error("unexpectedIrL");
                   5513:                                                goto xx;
                   5514:                                        }
                   5515: 
                   5516:                                        if (vt->check(e->tp,ASSIGN))
                   5517:                                                error("badIrT for%n:%t (%tX)",nn,e->tp,vt);
                   5518: 
                   5519:                                        Pptr p;
                   5520:                                        if (vt->check(e->tp,0)
                   5521:                                        && (p=vt->is_ptr())
                   5522:                                        && Ptype(p)!=zero_type
                   5523:                                        && p->typ!=char_type) {
                   5524:                                                Pexpr te = e;
                   5525:                                                Ptype t = p->typ;
                   5526:                                                while ( t->base == TYPE ) t = Pbase(t)->b_name->tp;
                   5527:                                                if ( t->base == COBJ )
                   5528:                                                        te = ptr_init( p, e, tbl );
                   5529:                                                if ( te == e )
                   5530:                                                        *curr_e = new cast(vt,e);
                   5531:                                                else *curr_e = te;
                   5532:                                        }
                   5533:                                }
                   5534:                                }
                   5535:                        }
                   5536:                        if (tdef==0) v->size = i;
                   5537:                }
                   5538:                break;
                   5539:        }
                   5540: 
                   5541:        case CLASS:
                   5542:                cl = Pclass(t);
                   5543:                goto ccc;
                   5544: 
                   5545:        case COBJ:      /* initialize members */
                   5546:                cl = Pclass(Pbase(t)->b_name->tp);
                   5547:        ccc:
                   5548:                if (cl->defined == 0) {
                   5549:                        lll = lvec;     // we are lost: ignore rest of list
                   5550:                        return;
                   5551:                }
                   5552: 
                   5553:                if (cl->c_body == 1) cl->dcl_print(0);
                   5554: 
                   5555:        {       Ptable tbl = cl->memtbl;
                   5556:                Pname m;
                   5557: 
                   5558:                if (cl->baselist) {
                   5559:                        if (cl->baselist->next) error("IrL forO ofC with multipleBCs");
                   5560:                        list_check(nn,cl->baselist->bclass,0);
                   5561:                }
                   5562: 
                   5563:                for (m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i)) {
                   5564:                        Ptype mt = m->tp;
                   5565:                        Pfct MP = 0;
                   5566:                        switch (mt->base) {
                   5567:                        case FCT:
                   5568:                        case OVERLOAD:
                   5569:                        case CLASS:
                   5570:                        case ENUM:
                   5571:                                continue;
                   5572:                        }
                   5573:                        if (m->n_stclass == STATIC ||
                   5574:                                m->n_stclass == ENUM ) continue;
                   5575:                        /* check assignment to next member */
                   5576:                dd:
                   5577:                        while (mt->base == TYPE)
                   5578:                                mt = Pbase(mt)->b_name->tp;
                   5579: 
                   5580:                        if ((MP = mt->memptr()) &&
                   5581:                            e==Pexpr(1) &&
                   5582:                                last_il->tp->base == PTR) {
                   5583:                                if(i==1) lst=0;
                   5584:                        }
                   5585:                        else e = next_elem();
                   5586: 
                   5587:                        if (e == 0) return; //break;
                   5588: 
                   5589:                        if(
                   5590:                                mt->base == FIELD
                   5591:                                        &&
                   5592:                                m->string[0]=='_'
                   5593:                                        &&
                   5594:                                m->string[1]=='_'
                   5595:                                        &&
                   5596:                                m->string[2]=='F'       // unnamed bitfield
                   5597:                        ) {
                   5598:                                e = insert_init(zero);
                   5599:                        }
                   5600: 
                   5601: //error('d',"mtz%n: %d",m,mt->base);
                   5602:                        switch (mt->base) {
                   5603:                        case CLASS:
                   5604:                        case ENUM:
                   5605:                                break;
                   5606:                        case VEC:
                   5607:                        case COBJ:
                   5608:                                list_check(nn,m->tp,e);
                   5609:                                break;
                   5610:                        case PTR:
                   5611:                                if (MP && e==Pexpr(1)) {
                   5612:                                        if (mt->check(last_il->tp,ASSIGN))
                   5613:                                                error("badIrT for%n:%t (%tX)",m,last_il->tp,mt);
                   5614:                                        skip_ilist();
                   5615:                                        break;
                   5616:                                }
                   5617:                                if (MP && e && e->base==ZERO) {
                   5618:                                        *curr_e = new expr(ELIST,zero,zero);
                   5619:                                        *curr_e = new expr(ILIST,*curr_e,zero);
                   5620:                                        (*curr_e)->tp = zero_type;
                   5621:                                        break;
                   5622:                                }
                   5623:                                if (MP && e && e->tp->base==OVERLOAD) {
                   5624:                                        Pexpr op = ptof(Pfct(Pptr(mt)->typ),e,tbl);
                   5625:                                        if(op) {
                   5626:                                                *curr_e = op;
                   5627:                                                break;
                   5628:                                        }
                   5629:                                }
                   5630:                                // no break
                   5631:                        default:
                   5632:                        {       if (e == Pexpr(1)) {
                   5633:                                        error("unexpectedIrL");
                   5634:                                        goto dd;
                   5635:                                }
                   5636: 
                   5637:                                if (mt->check(e->tp,ASSIGN))
                   5638:                                        error("badIrT for%n:%t (%tX)",m,e->tp,m->tp);
                   5639: 
                   5640:                                if(MP && e && e->base==CAST)
                   5641:                                        *curr_e = e->e1;
                   5642: 
                   5643:                                Pptr p;
                   5644:                                if (mt->check(e->tp,0)
                   5645:                                && (p=mt->is_ptr())
                   5646:                                && Ptype(p)!=zero_type
                   5647:                                && p->typ!=char_type)
                   5648:                                        *curr_e = new cast(mt,e);
                   5649:                        }
                   5650:                        }
                   5651:                }
                   5652:                if (lst && (e=next_elem()) ) error("end ofIrLX afterCO");
                   5653:                break;
                   5654:        }
                   5655:        default:
                   5656:                e = next_elem();
                   5657: 
                   5658:                if (e == 0) {
                   5659:                        error("noIr forO");
                   5660:                        break;
                   5661:                }
                   5662:                
                   5663:                if (e == Pexpr(1)) {
                   5664:                        error("unexpectedIrL");
                   5665:                        break;
                   5666:                }
                   5667: //error('d',"t %t e->tp %t",t,e->tp);
                   5668:                if (t->check(e->tp,ASSIGN)) error("badIrT for%n:%t (%tX)",nn,e->tp,t);
                   5669:                Pptr p;
                   5670:                if (t->check(e->tp,0)
                   5671:                && (p=t->is_ptr())
                   5672:                && Ptype(p)!=zero_type
                   5673:                && p->typ!=char_type)
                   5674:                        *curr_e = new cast(t,e);
                   5675:                if (lst && (e=next_elem()) ) error("end ofIrLX afterO");
                   5676:                break;
                   5677:        }
                   5678: }
                   5679: 
                   5680: int
                   5681: is_anon(char* string) {
                   5682: // error('d',"is_anon: %s", string );
                   5683:        if ( string == 0 )
                   5684:                return 0;
                   5685: 
                   5686:        if ( string[0]=='_' && string[1]=='_' &&
                   5687:                (string[2]=='C' || string[2]=='E')) 
                   5688:                        return 1;
                   5689:        return 0;
                   5690: }
                   5691: 
                   5692: Pname dclass(Pname n, Ptable tbl)
                   5693: {      
                   5694:        Pclass cl;
                   5695:        Pbase bt;
                   5696:        Pname bn;
                   5697:        Pname ntbl = tbl->t_name;
                   5698:        Ptype ntp = 0; 
                   5699:        TOK tscope;
                   5700: 
                   5701:        Pname nx = ktbl->look(n->string,0);             // TNAME
                   5702:        if (ntbl && ntbl->tp) ntp = ntbl->tp;
                   5703: 
                   5704:        tscope = ntp&&ntp->base==CLASS?NESTED:(n->lex_level?LOCAL:HIDDEN);
                   5705: 
                   5706:        DB( if(Ddebug>=1) error( 'd', &n->where, "dclass n %n %d nx %d", n,n->lex_level, nx); );
                   5707: // error( 'd', &n->where, "dclass n %n ll %d nx %d tbl: %n", n,n->lex_level, nx, tbl->t_name); 
                   5708:        if (nx == 0 || n->lex_level || 
                   5709:                ntp && is_anon(n->string) == 0 && ntp->base == CLASS 
                   5710:                && (ktbl->look(n->string,tscope))) 
                   5711:        {
                   5712:                if ( nx && ntp && ntp->base == CLASS ) { 
                   5713:                        bt = (Pbase)nx->tp;
                   5714:                        bn = bt->b_name;
                   5715:                        cl = bn ? (Pclass)bn->tp : 0;
                   5716:                        if (cl && cl->lcl && 
                   5717:                                strcmp(cl->lcl,"FUDGE007")==0)
                   5718:                                        goto bbb;
                   5719:                        else { bt=0; bn=0; cl=0; }
                   5720:                }
                   5721: 
                   5722:                int tn = 0;
                   5723:                for (nx=ktbl->look(n->string,tscope); nx; nx=nx->n_tbl_list) 
                   5724:                {
                   5725:                        if (nx->n_key != tscope) continue;
                   5726:                        if (tscope==LOCAL && 
                   5727:                                nx->lex_level != n->lex_level ) continue;
                   5728: 
                   5729:                        if (nx->tp->base != COBJ) {
                   5730:                                tn = 1;
                   5731:                                continue;
                   5732:                        }
                   5733: 
                   5734:                        bt = (Pbase)nx->tp;
                   5735:                        bn = bt->b_name;
                   5736:                        cl = (Pclass)bn->tp;
                   5737: 
                   5738:                        if (cl == 0) continue;
                   5739: 
                   5740:                        // is this class nested within class table?
                   5741:                        if (tscope==NESTED && 
                   5742:                                strcmp(ntbl->string,cl->in_class->string))
                   5743:                                        continue;
                   5744:                        else
                   5745:                        if ( tscope==LOCAL && 
                   5746:                                (cl->lcl==0 || strcmp(cl->lcl,Pclass(n->tp)->lcl))) 
                   5747:                                        continue;
                   5748: 
                   5749:                        goto bbb;
                   5750:                }
                   5751: 
                   5752:                if (tn)
                   5753:                        error("%n redefined using Tdef",n);
                   5754:                else
                   5755:                        error('i',"%n is not aCN",n);
                   5756:        }
                   5757:        else {
                   5758:                bt = Pbase(nx->tp);                     // COBJ
                   5759:                 if ( bt->base != COBJ ) {
                   5760:                         error("%n redefined using typedef",n);
                   5761:                         Pname tn = ktbl->look(n->string,HIDDEN); 
                   5762:                         if ( tn->tp->base == COBJ )  
                   5763:                                 bt = Pbase(tn->tp);
                   5764:                         else error('i',"%n is not a CN", n );
                   5765:                 }
                   5766:                bn = bt->b_name;
                   5767:        }
                   5768: bbb:
                   5769:        bn->where = nx->where;
                   5770:        Pname bnn = tbl->insert(bn,CLASS);              // copy for member lookup
                   5771:        cl = Pclass(bn->tp);
                   5772: 
                   5773:        if (cl->class_base == template_class)
                   5774:                error("C%n defined previously asYC", bn);
                   5775:                                                        
                   5776:        if (cl->defined&(DEFINED|SIMPLIFIED))
                   5777:                error("C%n defined twice",n);
                   5778:        else {
                   5779:                if (bn->n_scope == ARG) bn->n_scope = ARGT;
                   5780:                cl->dcl(bn,tbl);
                   5781:        }
                   5782:        n->tp = cl;
                   5783:        return bnn;
                   5784: }
                   5785: 
                   5786: Pname denum(Pname n, Ptable tbl)
                   5787: {
                   5788:        Penum en;
                   5789:        Pbase bt;
                   5790:        Pname bn;
                   5791:        Pname ntbl = tbl->t_name;
                   5792:        Ptype ntp = 0; 
                   5793:        TOK tscope;
                   5794: 
                   5795:        Pname nx = ktbl->look(n->string,0);             // TNAME
                   5796:        if (ntbl && ntbl->tp) ntp = ntbl->tp;
                   5797: 
                   5798: // note: ***** add for local enumeration declaration
                   5799: // error( 'd', &n->where, "denum n %n ll %d nx %d tbl: %n", n,n->lex_level, nx, tbl->t_name); 
                   5800:        if (nx == 0 || /* n->lex_level ||*/ 
                   5801:                ntp && is_anon(n->string)==0 && ntp->base == CLASS ) 
                   5802:        {
                   5803:                int tn = 0;
                   5804:                tscope = ntp&&ntp->base==CLASS?NESTED:(/*n->lex_level?LOCAL:*/HIDDEN);
                   5805:                for (nx=ktbl->look(n->string,tscope); nx; nx=nx->n_tbl_list) 
                   5806:                {
                   5807:                        if (nx->n_key != tscope) continue;
                   5808: //                     if (tscope==LOCAL && 
                   5809: //                             nx->lex_level != n->lex_level ) continue;
                   5810: 
                   5811:                        bt = (Pbase)nx->tp;
                   5812:                        bn = bt->b_name;
                   5813:                        en = (Penum)bn->tp;
                   5814: 
                   5815:                        // is this class nested within class table?
                   5816:                        if (tscope==NESTED && en->in_class &&
                   5817:                                strcmp(ntbl->string,en->in_class->string))
                   5818:                                        continue;
                   5819:                }
                   5820:        }
                   5821:        else {
                   5822:                        bt = (Pbase)nx->tp;
                   5823:                        bn = bt->b_name;
                   5824:                        en = (Penum)bn->tp;
                   5825:        }
                   5826: 
                   5827:        Pname bnn = tbl->insert(bn,CLASS);
                   5828:        if (en->defined&(DEFINED|SIMPLIFIED))
                   5829:                error("enum%n defined twice",n);
                   5830:        else {
                   5831:                if (bn->n_scope == ARG) bn->n_scope = ARGT;
                   5832:                en->dcl(bn,tbl);
                   5833:        }
                   5834:        n->tp = en;
                   5835:        return bnn;
                   5836: }
                   5837: 
                   5838: static int
                   5839: is_probably_temp( char *str ) 
                   5840: {
                   5841: // error( 'd', "is_probably_temp( %s )", str );
                   5842: 
                   5843:        if ( str[0] != '_' || str[1] != '_' )
                   5844:                return 0;
                   5845: 
                   5846:        switch (str[2]) {
                   5847:                default:
                   5848:                        return 0;
                   5849:                case 'A': case 'C': case 'D': case 'E': case 'F': 
                   5850:                case 'I': case 'K': case 'L': case 'M': case 'N': 
                   5851:                case 'Q': case 'R': case 'S': case 'T': case 'U': 
                   5852:                case 'V': case 'W': case 'X':
                   5853:                        return 1;
                   5854:        }
                   5855: 
                   5856: }
                   5857: 
                   5858: static void
                   5859: check_for_local( Pexpr ee )
                   5860: {
                   5861:        static Pname n[2] = {0,0}; // try not to flag multiple errors 
                   5862:        static index = 0;
                   5863: 
                   5864:        if ( ee==0 ) return; 
                   5865: 
                   5866: // error('d', "check_for_local( %k ) e1: %d e2: %d", ee->base, ee->e1, ee->e2);
                   5867: 
                   5868:        switch ( ee->base ) {
                   5869:                case NAME:  
                   5870:                {
                   5871:                        Pname nn = Pname(ee);
                   5872:                        if ((nn->n_scope==FCT || nn->n_scope==ARG) 
                   5873:                            && is_probably_temp(nn->string) == 0  
                   5874:                            && n[0]!=nn && n[1]!=nn) 
                   5875:                        {
                   5876:                                error("local%n used as defaultA", nn );
                   5877:                                n[index] = nn;
                   5878:                                index = index==0?1:0;
                   5879:                        }       
                   5880:                        // no break;
                   5881:                }
                   5882:                case TNAME: case STRING: case IVAL:
                   5883:                case ICON: case CCON: case FCON:
                   5884:                case ZERO: case DUMMY: case SIZEOF:
                   5885:                        return;
                   5886:                case QUEST:
                   5887:                        check_for_local( ee->cond );
                   5888:                        break;
                   5889:                case MDOT:
                   5890:                        check_for_local( ee->mem );
                   5891:                        return;
                   5892:        }
                   5893: 
                   5894:        check_for_local( ee->e1 );
                   5895:        check_for_local( ee->e2 );
                   5896: }
                   5897: 
                   5898: void dargs(Pname, Pfct f, Ptable tbl)
                   5899: {
                   5900:        int argnamesize = 0; // if +a1, make sure arg names can be printed
                   5901:        int oo = const_save;
                   5902:        const_save = 1;
                   5903:        if ( ansi_opt ) {
                   5904:            Pname th = f->f_this;
                   5905:            if ( th && th->string ) argnamesize += strlen(th->string) + 1;
                   5906:            th = f->f_result;
                   5907:            if ( th && th->string ) argnamesize += strlen(th->string) + 1;
                   5908:        }
                   5909: 
                   5910:        for (Pname a=f->argtype; a; a=a->n_list) {
                   5911:                Pexpr init;
                   5912: 
                   5913:                if (a->tp == 0) {
                   5914:                        error( "A has noT" );
                   5915:                        a->tp = any_type;
                   5916:                        continue;
                   5917:                }
                   5918:                if (ansi_opt && a->string) argnamesize += strlen(a->string) + 1;
                   5919: 
                   5920:                Pname cln = a->tp->is_cl_obj();
                   5921: //error('d',"dargs %t",a->tp);
                   5922:                if (cln && Pclass(cln->tp)->has_itor()) // mark X(X&) arguments
                   5923:                        a->n_xref = 1;
                   5924:                else {
                   5925:                        Ptype t = a->tp;
                   5926:                        while (t->base == TYPE) t = Pbase(t)->b_name->tp;
                   5927:                        if (t->base == FCT) a->tp = new ptr(PTR,a->tp);
                   5928:                }
                   5929: 
                   5930: //             if (init = a->n_initializer) {  // default argument
                   5931:                 if ( a->n_key != NESTED &&
                   5932:                     (init = a->n_initializer)) { // default argument
                   5933:                        Pptr pt;
                   5934:                        if (init == dummy) {
                   5935:                                error("emptyIr");
                   5936:                                a->n_initializer = 0;
                   5937:                                continue;
                   5938:                        }
                   5939:                        if (cln) {
                   5940:                                if (init->base==VALUE) {
                   5941:                                        switch (init->tp2->base) {
                   5942:                                        case CLASS:
                   5943:                                                if (Pclass(init->tp2)!=Pclass(cln->tp)) goto inin2;
                   5944:                                                break;
                   5945:                                        default:
                   5946:                                                Pname n2 = init->tp2->is_cl_obj();
                   5947:                                                if (n2==0 || Pclass(n2->tp)!=Pclass(cln->tp)) goto inin2;
                   5948:                                        }
                   5949: 
                   5950:                                        a->n_initializer = init = 0;
                   5951:                                        error('s',"K as defaultA");
                   5952:                                }
                   5953:                                else {
                   5954:                                inin2:
                   5955:                                        if (init->base == ILIST) error("list as AIr");
                   5956:                                        Pexpr i = init->typ(tbl);
                   5957:                                        init = class_init(a,a->tp,i,tbl);
                   5958:                                        if (i!=init && init->base==DEREF) {
                   5959:                                                error('s',"K needed forAIr");
                   5960:                                                init = 0;
                   5961:                                        }
                   5962:                                        else {
                   5963:                                                dosimpl(init,cc->nof);
                   5964:                                        //      init->simpl();
                   5965:                                                init->permanent = 2;
                   5966:                                        }
                   5967:                                        a->n_initializer = init;
                   5968:                                }
                   5969:                        }
                   5970:                        else if (pt = a->tp->is_ref()) {
                   5971:                                ref_initializer++;
                   5972:                                init = init->typ(tbl);
                   5973:                                ref_initializer--;
                   5974:                                int tcount = stcount;
                   5975:                                init = ref_init(pt,init,tbl);
                   5976:                                if (tcount != stcount) {
                   5977:                                        error('s',"needs temporaryV to evaluateAIr");
                   5978:                                        init = 0;
                   5979:                                }
                   5980:                                else {
                   5981:                                        dosimpl(init,cc->nof);
                   5982:                                //      init->simpl();
                   5983:                                        init->permanent = 2;
                   5984:                                }
                   5985:                                a->n_initializer = init;
                   5986:                        }
                   5987:                        else {
                   5988:                                Pptr p = a->tp->is_ptr();
                   5989:                                init = init->typ(tbl);
                   5990:                                if (p) init = ptr_init(p,init,tbl);
                   5991: 
                   5992:                                if (a->tp->check(init->tp,ARG)) {
                   5993:                                        int i = can_coerce(a->tp,init->tp);
                   5994: 
                   5995:                                        switch (i) {
                   5996:                                        case 1:
                   5997:                                                if (Ncoerce) {
                   5998:                                                        Pname cn = init->tp->is_cl_obj();
                   5999:                                                        Pname xx = new name(Ncoerce->string);
                   6000:                                                        Pref r = new ref(DOT,init,xx);
                   6001:                                                        init = new expr(G_CALL,r,0);
                   6002:                                                        init = init->typ(tbl);
                   6003:                                                }
                   6004:                                                break;
                   6005:                                        default:
                   6006:                                                error("%d possible conversions for defaultA",i);
                   6007:                                        case 0:
                   6008:                                                error("badIrT%t forA%n (%tX)",init->tp,a,a->tp);
                   6009:                                                DEL(init);
                   6010:                                                a->n_initializer = init = 0;
                   6011:                                        }
                   6012:                                }
                   6013:                                
                   6014:                                if (init) {
                   6015:                                        dosimpl(init,cc->nof);
                   6016:                                //      init->simpl();
                   6017:                                        init->permanent = 2;
                   6018:                                        a->n_initializer = init;
                   6019:                                        Neval = 0;
                   6020:                                        long i = init->eval();
                   6021:                                        if (Neval == 0) {
                   6022:                                                a->n_evaluated = 1;
                   6023:                                                a->n_val = i;
                   6024:                                        }
                   6025:                                }
                   6026:                        }
                   6027:                        if ( a->n_initializer ) 
                   6028:                                check_for_local(a->n_initializer);
                   6029:                }
                   6030:        }
                   6031:        if ( ansi_opt && argnamesize ) {
                   6032:                char* ps = new char[ argnamesize ];
                   6033:                Pname a = f->f_this;
                   6034:                if ( a && a->string ) {
                   6035:                        int i = strlen(a->string) + 1;
                   6036:                        if ( (argnamesize -= i) < 0 ) goto bad;
                   6037:                        strcpy(ps,a->string);
                   6038:                        a->string = ps;
                   6039:                        ps += i;
                   6040:                }
                   6041:                a = f->f_result;
                   6042:                if ( a && a->string ) {
                   6043:                        int i = strlen(a->string) + 1;
                   6044:                        if ( (argnamesize -= i) < 0 ) goto bad;
                   6045:                        strcpy(ps,a->string);
                   6046:                        a->string = ps;
                   6047:                        ps += i;
                   6048:                }
                   6049:                for ( a = f->argtype;  a;  a = a->n_list ) {
                   6050:                        if ( a->string == 0 ) continue;
                   6051:                        int i = strlen(a->string) + 1;
                   6052:                        if ( (argnamesize -= i) < 0 ) goto bad;
                   6053:                        strcpy(ps,a->string);
                   6054:                        a->string = ps;
                   6055:                        ps += i;
                   6056:                }
                   6057:                if ( argnamesize ) bad:error('i',"bad argN size for%t",f);
                   6058:        }
                   6059:        const_save = oo;
                   6060: }
                   6061: 
                   6062: void merge_init(Pname nn, Pfct f, Pfct nf)
                   6063: {
                   6064: //     Pname a1 = f->f_args; if (a1==0) a1 = f->argtype;
                   6065: //     Pname a2 = nf->f_args;//nf->argtype; 
                   6066:        Pname a1 = f->argtype;
                   6067:        Pname a2 = nf->argtype; 
                   6068: 
                   6069:        for (; a1; a1=a1->n_list, a2=a2->n_list) {
                   6070:                int i1 = a1->n_initializer || a1->n_evaluated;
                   6071:                int i2 = a2->n_initializer || a2->n_evaluated;
                   6072: 
                   6073:                if (i1 && i2) error(&a1->where,"twoIrs for%nA%n",nn,a1);
                   6074: 
                   6075:                if (i1) {
                   6076:                        a2->n_initializer = a1->n_initializer;
                   6077:                        a2->n_evaluated = a1->n_evaluated;
                   6078:                        a2->n_val = a1->n_val;
                   6079:                }
                   6080:                if (i2) {
                   6081:                        a1->n_initializer = a2->n_initializer;
                   6082:                        a1->n_evaluated = a2->n_evaluated;
                   6083:                        a1->n_val = a2->n_val;
                   6084:                }
                   6085: 
                   6086:        }
                   6087: }
                   6088: 
                   6089: Pexpr try_to_coerce(Ptype rt, Pexpr e, char* s, Ptable tbl)
                   6090: /*
                   6091:        ``e'' is of class ``cn'' coerce it to type ``rt''
                   6092: */
                   6093: {
                   6094:        int i;
                   6095:        Pname cn;
                   6096: //error('d',"try_to_coerce(%t, %t, %s, %d)",rt,e->tp,s,tbl);
                   6097: 
                   6098:        if ((cn=e->tp->is_cl_obj()) && (i=can_coerce(rt,e->tp)) && Ncoerce) {
                   6099:                if (1 < i) error("%d possible conversions for %s",i,s);
                   6100: //error('d',"coerce %n",Ncoerce);
                   6101:                Pclass cl = Pclass(cn->tp);
                   6102:        //      Pref r = new ref(DOT,e,Ncoerce);
                   6103:        //      Pexpr rr = r->typ(tbl);
                   6104:        //      Pexpr c = new expr(G_CALL,rr,0);
                   6105:        //      c->fct_name = Ncoerce;
                   6106:                Pname xx = new name(Ncoerce->string);
                   6107:                Pref r = new ref(DOT,e,xx);
                   6108:                Pexpr c = new expr(G_CALL,r,0);
                   6109:        //      return c->typ(tbl);
                   6110:                c = c->typ(tbl);
                   6111: //error('d',"coerce -> %k %t",c->base,c->tp);
                   6112:                return c;
                   6113:        }
                   6114: //error('d',"coerce ->0");
                   6115:        return 0;
                   6116: }
                   6117: 
                   6118: int in_class_dcl;
                   6119: 
                   6120: Pname name::dofct(Ptable tbl, TOK scope)
                   6121: {      
                   6122:        Pfct f = Pfct(tp);
                   6123:        Pname class_name;
                   6124:        Ptable etbl;
                   6125:        in_class_dcl = cc->not!=0;
                   6126:        int just_made = 0;
                   6127: //     int fvirt = 0;  //BSopt
                   6128:        DB( if(Ddebug>=1) error('d',"dofct %n %d %t %s",this,tp,tp,tbl==gtbl?"global":""); );
                   6129: // error( 'd', "%n->dofct(): n_initializer: %d f->f_virtual: %d", this, n_initializer, f->f_virtual);
                   6130: 
                   6131:        if (f->f_inline) n_sto = STATIC;
                   6132: 
                   6133:        if (n_stclass)
                   6134:                switch (n_stclass) {
                   6135:                case EXTERN:
                   6136:                case STATIC:
                   6137:                case OVERLOAD:
                   6138:                        break;
                   6139:                default:
                   6140:                        error("%n declared%k",this,n_stclass);
                   6141:                        n_stclass = EXTERN;
                   6142:                }
                   6143: 
                   6144:        tp->dcl(tbl);           // must be done before the type check
                   6145: 
                   6146:        if (n_qualifier) {      // qualified name: c::f() checked above
                   6147:                class_name = Pbase(n_qualifier->tp)->b_name;
                   6148:                etbl = Pclass(class_name->tp)->memtbl;
                   6149: 
                   6150:                if (f->f_virtual) {
                   6151:                          error("virtual specifier illegal outsideCD(%n::%s())",class_name,this->string);
                   6152:                         f->f_virtual = 0;
                   6153:                }
                   6154: 
                   6155: 
                   6156:                if (n_sto
                   6157:                && n_sto!=FRIEND        // friend X::f();
                   6158:                && f->f_inline==0) {    // inline causes n_sto==STATIC
                   6159:                        error("%k specified for QdN%n",n_sto,this);
                   6160:                        n_sto = 0;
                   6161:                }
                   6162:        }
                   6163:        else {
                   6164:                class_name = cc->not;
                   6165: 
                   6166:                // beware of local function declarations in member functions
                   6167:                if (class_name && tbl!=cc->cot->memtbl) {
                   6168:                        class_name = 0;
                   6169:                        in_class_dcl = 0;
                   6170:                }
                   6171: 
                   6172:                if (f->f_static && f->f_virtual) {
                   6173:                         error("virtual staticM");
                   6174:                         f->f_virtual = 0;
                   6175:                }
                   6176: 
                   6177:                if (n_oper) check_oper(class_name);
                   6178:                etbl = tbl;
                   6179:        }
                   6180: 
                   6181: //     Pfct(tp)->memof = class_name ? Pclass(class_name->tp) : 0;
                   6182: 
                   6183:        if (class_name) {
                   6184:                Pclass cl;
                   6185:                f->memof = cl = Pclass(class_name->tp);
                   6186:                if (f->f_virtual==0 && find_virtual(f->memof,this))
                   6187:                        f->f_virtual = VTOK;
                   6188: //error('d',"class_name: %s fct: %s virtual: %d", class_name->string, string, f->f_virtual );
                   6189: 
                   6190:                if (f->f_static && f->f_virtual) {
                   6191:                         error("virtual staticM");
                   6192:                         f->f_virtual = 0;
                   6193:                }
                   6194: 
                   6195:                if ( cl->csu == UNION && f->f_virtual ) // don't worry about ANON
                   6196:                        error( "%n: cannot declare a virtualFWin union", this ); 
                   6197:         }
                   6198: 
                   6199:        if(f->f_const && f->memof==0) {
                   6200:                error("onlyMFs can be constant");
                   6201:        }
                   6202: 
                   6203:        if (etbl==0 || etbl->base!=TABLE) error('i',"N::dcl: etbl=%d",etbl);
                   6204: 
                   6205:        switch (n_oper) {
                   6206:        case CTOR:
                   6207:                if (f->f_virtual) {
                   6208:                        error("virtualK");
                   6209:                        f->f_virtual = 0;
                   6210:                }
                   6211: 
                   6212: //     case DTOR:
                   6213: //             f->f_const = 1;
                   6214:                break;
                   6215: 
                   6216:        case REF:
                   6217:                if (f->argtype) 
                   6218:                        error("%n takes no argument",this);
                   6219:                else if (f->returns->is_ptr() == 0) {
                   6220:                        Pname cn = f->returns->is_cl_obj();
                   6221:                        if (cn==0 && f->returns->base==RPTR) cn = Pptr(f->returns)->typ->is_cl_obj();
                   6222:                        if (cn==0 || Pclass(cn->tp)->has_oper(REF)==0) {
                   6223:                                if ( cn && class_name &&  // B B::operator->();
                   6224:                                        strcmp(cn->string, class_name->string)==0 )
                   6225:                                                error("%s::%n cannot return aR orCO ofC%n",cn->string,this,cn);
                   6226:                                else error("%n must return aP toCO, aR toCO, or aCO",this);
                   6227:                                tp = any_type; // suppress further checking
                   6228:                        }
                   6229:                }
                   6230:                break;
                   6231: 
                   6232:        case NEW:       // void* operator new(long)
                   6233:                if (f->f_virtual)
                   6234:                        error("virtual%n (operator new() is static)",this);
                   6235:                if (class_name) f->f_static = 1;        // if member: static by default
                   6236:                if (f->nargs_known != 1)
                   6237:                        error("ATs must be fully specified for%n",this);
                   6238:                else if (f->nargs<1)
                   6239:                        error("%n requires a firstA ofT size_t",this);
                   6240:                else if (f->argtype->tp->check(size_t_type,0)) {
                   6241:                                if (strict_opt==0
                   6242:                                && ( f->argtype->tp->check(long_type,0)==0 ||
                   6243:                                     f->argtype->tp->check(ulong_type,0)==0)) {
                   6244:                                        error('w',"%n firstA should be size_t (anachronism)",this);
                   6245:                                        f->argtype->tp = size_t_type;
                   6246:                                        if (f->f_signature) f->sign();
                   6247:                                }
                   6248:                                else
                   6249:                                        error("%n requires a firstA ofT size_t",this);
                   6250:                }
                   6251:                else {
                   6252:                        Ptype t = f->s_returns  ? f->s_returns : f->returns;
                   6253:                        if (t->check(Pvoid_type,0)) error("bad returnT for %n",this);
                   6254:                }
                   6255:                break;
                   6256: 
                   6257:                case DELETE:    // void operator delete(void*) or
                   6258:                                // void operator delete(void*, long)
                   6259:                        if (f->f_virtual)
                   6260:                                error("virtual%n (operator delete() is static)",this);
                   6261:                        if (class_name) f->f_static = 1;        // if member: static by default
                   6262:                        if (f->nargs_known != 1)
                   6263:                                        error("ATs must be fully specified for%n",this);
                   6264:                        else {
                   6265:                                Ptype t = f->s_returns ? f->s_returns : f->returns;
                   6266:                                if (t->base != VOID)
                   6267:                                        error("bad returnT for %n", this);
                   6268:                                else {
                   6269:                                        switch (f->nargs) {
                   6270:                                        default:
                   6271:                                                error("%n takes 1 or 2As",this);
                   6272:                                                break;
                   6273:                                        case 1:
                   6274:                                        case 2:
                   6275:                                        {       Pname a = f->argtype;
                   6276:                                                if (a->tp->check(Pvoid_type,0))
                   6277:                                                                error("%n's 1stA must be a void*",this);
                   6278:                                                else if (a = a->n_list) {
                   6279:                                                        if (class_name == 0)
                   6280:                                                                error("%n takes only oneA",this);
                   6281:                                                        else if (a->tp->check(size_t_type,0)) {
                   6282:                                                                if (strict_opt==0
                   6283:                                                                && a->tp->check(long_type,0)==0) {
                   6284:                                                                        error('w',"%n's 2ndA should be a size_t (anachronism)",this);
                   6285:                                                                        a->tp = size_t_type;
                   6286:                                                                        if (f->f_signature) f->sign();
                   6287:                                                                }
                   6288:                                                                else
                   6289:                                                                        error("%n's 2ndA must be a size_t",this);
                   6290:                                                        }
                   6291:                                                }
                   6292:                                        }
                   6293:                                        }
                   6294:                                }
                   6295:                                }
                   6296:                break;
                   6297: 
                   6298:        case ASSIGN:
                   6299:                if (class_name && f->nargs==1) {
                   6300:                        Ptype t = f->argtype->tp;
                   6301:                        Pname an = t->is_cl_obj();  // X::operator=(X) ?
                   6302:                        if (an==0 && (t=t->is_ref())) { // X::operator=(X&) ?
                   6303:                                t = Pptr(t)->typ;
                   6304:                        rx1:
                   6305:                                switch (t->base) {
                   6306:                                case TYPE:      t = Pbase(t)->b_name->tp; goto rx1;
                   6307:                                case COBJ:      an = Pbase(t)->b_name;
                   6308:                                }
                   6309:                        }
                   6310:                        if (an && an==class_name) Pclass(an->tp)->c_xref |= C_ASS;
                   6311:                }
                   6312:                else if (f->nargs == 2) {
                   6313:                        Ptype t = f->argtype->tp;
                   6314:                        Pname an1;
                   6315:                        if (t=t->is_ref()) { // operator=(X&,?) ?
                   6316:                                t = Pptr(t)->typ;
                   6317:                        rx2:
                   6318:                                switch (t->base) {
                   6319:                                case TYPE:      t = Pbase(t)->b_name->tp; goto rx2;
                   6320:                                case COBJ:      an1 = Pbase(t)->b_name;
                   6321:                                }
                   6322:                        }
                   6323:                        t = f->argtype->n_list->tp;
                   6324:                        Pname an2 = t->is_cl_obj(); // operator=(X&,X) ?
                   6325:                        if (an2==0 && (t=t->is_ref())) { // operator=(X&,X&) ?
                   6326:                                t = Pptr(t)->typ;
                   6327:                        rx3:
                   6328:                                switch (t->base) {
                   6329:                                case TYPE:      t = Pbase(t)->b_name->tp; goto rx3;
                   6330:                                case COBJ:      an2 = Pbase(t)->b_name;
                   6331:                                }
                   6332:                        }
                   6333:                        if (an1 && an1==an2) Pclass(an1->tp)->c_xref |= C_ASS;
                   6334:                }
                   6335:        }
                   6336: 
                   6337:        switch (scope) {
                   6338:        case FCT:
                   6339:        case ARG:
                   6340:                if (n_sto == STATIC) error("D of staticF in aF");
                   6341:                else { // detect local re-definition
                   6342:                        Pname nx = gtbl->look(string,0);
                   6343:                        if (nx) {
                   6344:                                switch (nx->tp->base) {
                   6345:                                case FCT:
                   6346:                                        if (tp->check(nx->tp,0))
                   6347:                                                error('w',"%n has been locally re-declared as%t",this,tp);
                   6348:                                        else {
                   6349:                                                if(Pfct(nx->tp)->f_signature==0)
                   6350:                                                        Pfct(nx->tp)->sign();
                   6351:                                                if (Pfct(tp)->f_signature == 0)
                   6352:                                                        Pfct(tp)->sign();
                   6353:                                                if ( strcmp(Pfct(nx->tp)->f_signature,Pfct(tp)->f_signature))
                   6354:                                                        error('w',"%n of type %t has been locally re-declared with different linkage",this,tp);
                   6355:                                        }
                   6356:                                        break;
                   6357:                                case OVERLOAD:
                   6358:                                {       Pname ny = Pgen(nx->tp)->find(f,0);
                   6359:                                        if (ny == 0)
                   6360:                                                error('w',"overloadedF%n has been locally declared as%t",this,tp);
                   6361:                                        else {
                   6362:                                                if(Pfct(ny->tp)->f_signature==0)
                   6363:                                                        Pfct(ny->tp)->sign();
                   6364:                                                if (Pfct(tp)->f_signature == 0)
                   6365:                                                        Pfct(tp)->sign();
                   6366:                                                if (strcmp(Pfct(ny->tp)->f_signature,Pfct(tp)->f_signature))
                   6367:                                                        error('w',"overloadedF%n of type %t has been locally re-declared with different linkage",this,tp);
                   6368:                                        }
                   6369:                                }
                   6370:                                        break;
                   6371:                                } // switch nx->base
                   6372:                        } // if nx
                   6373:                } // else
                   6374:        } // switch scope
                   6375: 
                   6376:        Pname nn = etbl->insert(this,0);
                   6377:        if ( f->body ) nn->where = where;
                   6378:        nn->assign();
                   6379:        n_table = etbl;
                   6380: //error('d',"%n->dofct(): n_initializer:%d f->f_virtual:%d",this,n_initializer,f->f_virtual);
                   6381:        if (n_initializer) {
                   6382:                if (f->f_virtual == 0) error("Ir for non-virtualF%n",this);
                   6383:                if (n_initializer != zero) error("virtualFIr must be 0");
                   6384:        }
                   6385:                        
                   6386:        if (Nold) {
                   6387:                Pfct nf = Pfct(nn->tp);
                   6388: // error('d',"old %n: %t and %t",nn,nf,tp);
                   6389:                int flag = 0;
                   6390:                Pname af=0,anf=0;
                   6391:                if (nf->base==ANY || f->base==ANY)
                   6392:                        ; // wild card -- do nothing
                   6393:                else 
                   6394:                if (nf->base == OVERLOAD) {
                   6395:                        string = nn->string;
                   6396:                        nn = Pgen(nf)->add(this);
                   6397: 
                   6398:                        if (Nold == 0) {
                   6399:                                if (f->body && n_qualifier) {
                   6400:                                        error("badAL for%n",this);
                   6401:                                        return 0;
                   6402:                                }
                   6403:                                goto thth;
                   6404:                        }
                   6405:                //      else {
                   6406:                //              if (f->body==0 && friend_in_class==0) error('w',"%n redeclared",nn);
                   6407:                //      }
                   6408:                        nf = Pfct(nn->tp);
                   6409:                        if (f->body && nf->body) {
                   6410:                                // Preserve the original definition 
                   6411:                                // in the case of a PT class; i.e, 
                   6412:                                // the one supplied by the user
                   6413:                                if (!(class_name &&
                   6414:                                        (Pclass(class_name->tp)->class_base ==
                   6415:                                                instantiated_template_class) && 
                   6416:                                        nn->n_redefined))
                   6417:                                        {
                   6418:                                        error("two definitions of%n",nn);
                   6419:                                        f->body = 0;
                   6420:                                }
                   6421:                                return 0;
                   6422:                        }
                   6423:                        if (f->body) goto bdbd;
                   6424:                        goto stst;
                   6425:                }
                   6426:                else if (nf->base != FCT) {
                   6427:                        error("%n declared both as%t and asF",this,nf);
                   6428:                        f->body = 0;
                   6429:                }
                   6430:                else  {
                   6431: // error('d',"%t->check(%t) -> %d %d",nf,f,nf->check(f,OVERLOAD));
                   6432:                        if (nf->check(f,OVERLOAD) || const_problem) {
                   6433:                                if (f->body && n_qualifier) {
                   6434:                                        error("%nT mismatch: %t and %t",nn,nf,f);
                   6435:                                        return 0;
                   6436:                                }
                   6437:                                Pgen g = new gen;
                   6438:                                add_first = 1;
                   6439:                                Pname n1 = g->add(nn);
                   6440:                                add_first = 0;
                   6441:                                string = nn->string;
                   6442:                                Pname n2 = g->add(this);
                   6443:                                nn->tp = g;
                   6444:                                nn = n2;
                   6445:                                goto thth;
                   6446:                        }
                   6447: 
                   6448:                         af = f->argtype;
                   6449:                         anf = nf->argtype;
                   6450:                        for (; af && anf; af=af->n_list,anf=anf->n_list) {
                   6451:                                Ptype at = af->tp;
                   6452:                                Ptype atp = anf->tp;
                   6453:                                if(!exact1(af,atp)) break;
                   6454:                                if(at->base!=PTR || 
                   6455:                                   Pptr(at)->rdo == Pptr(atp)->rdo) continue;
                   6456:                                int k = Pptr(at)->typ->tconst();
                   6457:                                int l = Pptr(atp)->typ->tconst();
                   6458:                                if(k==l) flag=1;
                   6459:                        }
                   6460:                        if ( flag && !af && !anf) {
                   6461:                                error("the overloading mechanism cannot tell a%t from a%t",nf,f);
                   6462:                        }
                   6463:                                
                   6464:                        if (in_class_dcl) {
                   6465:                        //      error("twoDs of%n",this);
                   6466:                        //      f->body = 0;
                   6467:                        //      return 0;
                   6468:                        }
                   6469:                        else if (nf->f_static && f->f_inline==0 && n_sto==STATIC) {
                   6470:                                //error('d',"MF%n declared static outsideF",this);
                   6471:                                n_sto = 0;
                   6472:                        }
                   6473:                        else if (n_sto && n_sto!=nn->n_scope) {
                   6474:                                if (n_sto==EXTERN && nn->n_scope==STATIC)
                   6475:                                        error('w',"%n declared extern after being declared static",this);
                   6476:                                else if (nf->f_inline==0 && f->f_inline==0) {
                   6477:                                        if (nn->tp==new_fct->tp || nn->tp==del_fct->tp)
                   6478:                                                nn->n_sto = n_sto;
                   6479:                                        else
                   6480:                                                error("%n declared as both%k and%k",this,n_sto,(nn->n_sto)?nn->n_sto:EXTERN);
                   6481:                                }
                   6482:                        }
                   6483: 
                   6484: //error('d',"fct %n: %k %k scope %k",this,n_sto,nn->n_sto,nn->n_scope);        
                   6485: //error('d',"link %d lcount %d sig %s",linkage,lcount,nf->f_signature);
                   6486: 
                   6487:                        { 
                   6488:                                Linkage l1 = nf->f_linkage;
                   6489:                                Linkage l2 = f->f_linkage;
                   6490:                                if ( l2!=linkage_default && l1!=l2)
                   6491:                                        error("inconsistent linkage specifications for%n",this);
                   6492:                        }
                   6493:                        if (nf->body && f->body) {
                   6494:                                // Preserve the original definition 
                   6495:                                // in the case of a PT class; i.e, 
                   6496:                                // the one supplied by the user
                   6497:                                if (!(class_name &&
                   6498:                                        (Pclass(class_name->tp)->class_base ==
                   6499:                                                instantiated_template_class) && 
                   6500:                                        nn->n_redefined))
                   6501:                                        {
                   6502:                                error("two definitions of%n",this);
                   6503:                                f->body = 0;
                   6504:                                }
                   6505:                                return 0;
                   6506:                        }
                   6507:                                
                   6508:                        if (f->body) goto bdbd;
                   6509: 
                   6510:                        goto stst;
                   6511:        
                   6512:                bdbd: 
                   6513: // error('d',"nn %n init: %d f_virt: %d f->body: %d", nn,nn->n_initializer,nf->f_virtual,f->body);
                   6514:                        if (f->nargs_known && nf->nargs_known) merge_init(nn,f,nf);
                   6515:                        f->f_virtual = nf->f_virtual;
                   6516:                        f->f_this = nf->f_this;
                   6517:                        f->f_result = nf->f_result;
                   6518:                        f->s_returns = nf->s_returns;
                   6519:                        f->f_args = nf->f_args;
                   6520:                //      f->argtype = nf->argtype;
                   6521:                        f->f_signature = nf->f_signature;
                   6522:                        f->f_const = nf->f_const;
                   6523:                        f->f_static = nf->f_static;
                   6524:                        nn->tp = f;
                   6525:                        if (f->f_inline) {
                   6526:                                if (nf->f_inline==0) {
                   6527:                                           if (nn->n_used && nn->n_sto!=STATIC)
                   6528:                                                error("%n declared with external linkage and called before defined as inline",nn);
                   6529:                                //      else if (nf->memof)
                   6530:                                //              error('w',"%n declared as non-inline but defined as inline",nn);
                   6531:                                        else if (nn->n_used) {
                   6532:                                                nn->take_addr(); // force printout
                   6533:                                                if (warning_opt) error('w',"%n called before defined as inline",nn);
                   6534:                                }
                   6535:                                }
                   6536:                                nf->f_inline = 1;
                   6537:                                nn->n_sto = STATIC;
                   6538:                        }
                   6539:                        else if (nf->f_inline) {
                   6540:                //              error('w',"%n defined as inline but not declared as inline",this);
                   6541:                                f->f_inline = 1;
                   6542:                        }
                   6543:                        goto stst2;
                   6544: 
                   6545:                stst:
                   6546: //error('d',"stst");
                   6547:                        if (f->nargs_known && nf->nargs_known) merge_init(nn,f,nf);
                   6548:                        f->f_args = nf->f_args;
                   6549:                //      f->argtype = nf->argtype;
                   6550:                stst2:
                   6551: //error('d',"stst2 %n printed %d",nn,nn->n_dcl_printed);
                   6552:                        if (f->f_inline) n_sto = STATIC;
                   6553: 
                   6554: /* superceded above (line 1978 and following)
                   6555:                        if (n_sto
                   6556:                        && nn->n_scope!=n_sto
                   6557:                        && friend_in_class==0
                   6558:                        && f->f_inline==0){ // allow re-def to "static"
                   6559:                                if (n_sto == STATIC)
                   6560:                                        nn->n_sto = STATIC;
                   6561:                                else {
                   6562:                                        error("%n both%k and%k",this,n_sto,nn->n_scope);
                   6563:                                }
                   6564:                        }
                   6565: */
                   6566: 
                   6567: //// addition for 2.1
                   6568: 
                   6569:                        if(n_sto == STATIC && nn->n_sto == EXTERN &&
                   6570:                            (!strcmp(string,"__nw") || !strcmp(string,"__dl")))
                   6571:                                nn->n_sto = STATIC;
                   6572: 
                   6573: //// end of addition
                   6574: 
                   6575:                        n_scope = nn->n_scope; // first specifier wins
                   6576:                        n_sto = nn->n_sto;
                   6577:                }
                   6578:        }
                   6579:        else {  // new function: make f_this for member functions
                   6580:        thth:
                   6581:                just_made = 1;
                   6582:                if (f->f_inline)
                   6583:                        nn->n_sto = STATIC;
                   6584:                else if (class_name==0 && n_sto==0 && f->body==0)
                   6585:                        nn->n_sto = EXTERN;
                   6586: //error('d',"thth %n %t static %d sto %k",nn,f,f->f_static,nn->n_sto);
                   6587:                if (f->f_static)
                   6588:                        switch (n_oper) {       // what about + ??
                   6589:                        case CTOR:
                   6590:                        case DTOR:
                   6591:                        case TYPE:
                   6592:                        case CALL:
                   6593:                        case DEREF:
                   6594:                        case REF:
                   6595:                        case ASSIGN:
                   6596:                                error("%n cannot be a staticMF",nn);
                   6597:                                f->f_static = 0;
                   6598:                        }
                   6599: 
                   6600:                if (class_name
                   6601:                && f->f_static==0       // no ``this'' in static members
                   6602:                && n_oper!=NEW          // X::operator new() static by default
                   6603:                && n_oper!=DELETE       // X::operator delete() static by default
                   6604:                && etbl!=gtbl) {        // beware of implicit declaration 
                   6605:                        Pname cn = nn->n_table->t_name;
                   6606:                        Pname tt = new name("this");
                   6607:                        tt->n_scope = ARG;
                   6608:                        tt->where = no_where;
                   6609:                //      tt->n_sto = ARG;
                   6610:                        tt->tp = Pclass(class_name->tp)->this_type;
                   6611:                        PERM(tt);
                   6612:                        Pfct(nn->tp)->f_this = f->f_this = Pfct(nn->tp)->f_args = f->f_args = tt;
                   6613:                        tt->n_list = f->argtype;
                   6614: //error('d',"nn %n tp %t const %d",nn,nn->tp,f->f_const);
                   6615:                        if (f->f_const /*&& n_oper!=CTOR && n_oper!=DTOR*/) {
                   6616:                                Pbase x = Pbase(Pptr(tt->tp)->typ);
                   6617:                                Pbase y = new basetype(COBJ,0);
                   6618:                                *y = *x;
                   6619:                                y->b_const = 1;
                   6620:                                tt->tp = new ptr(PTR,y);
                   6621:                                Pptr(tt->tp)->rdo = 1;
                   6622:                                PERM(tt->tp);
                   6623:                        }
                   6624:                }
                   6625:                else {
                   6626:                        Pfct(nn->tp)->f_args = f->f_args = f->f_result?f->f_result:f->argtype;
                   6627:                        Pfct(nn->tp)->f_signature = f->f_signature;
                   6628:                        Pfct(nn->tp)->f_const = f->f_const;
                   6629:                        Pfct(nn->tp)->f_static = f->f_static;
                   6630:                }
                   6631: 
                   6632:                // if C++ linkage encode type in function name
                   6633:                if (Pfct(nn->tp)->f_signature==0) Pfct(nn->tp)->sign();
                   6634: 
                   6635:                if (f->f_result == 0) {
                   6636: //error('d',"re1 %n %t %d",this,f,f);
                   6637:                        make_res(f);
                   6638:                }
                   6639:                else if (f->f_this)
                   6640:                        f->f_this->n_list = f->f_result;
                   6641: 
                   6642:                if (nn->n_oper==CTOR || nn->n_oper==DTOR) vbase_pointers(nn,Pclass(class_name->tp));
                   6643: 
                   6644:                if (f->f_virtual) {
                   6645:                        switch (nn->n_scope) {
                   6646:                        default:
                   6647:                                error("nonC virtual%n",this);
                   6648:                                break;
                   6649:                        case 0:
                   6650:                        case PUBLIC:
                   6651:                                //      if (fvirt)      //BSopt
                   6652:                                cc->cot->virt_count = 1;
                   6653:                                Pfct(nn->tp)->f_virtual = f->f_virtual;
                   6654:                                break;
                   6655:                        }
                   6656:                }
                   6657:        }
                   6658: 
                   6659:                /*      an operator must take at least one class object or
                   6660:                        reference to class object argument
                   6661:                */
                   6662: 
                   6663:        if (just_made)
                   6664:        switch (n_oper) {
                   6665:        case CTOR:
                   6666:                switch (f->nargs) {     // check for X(X) and X(X&)
                   6667:                case 0:
                   6668:                        break;
                   6669:                default:                // handle X(X&, int i = 0)
                   6670:                {       Pname n2 = f->argtype->n_list;
                   6671:                        if (n2->n_initializer==0 && n2->n_evaluated==0) break;
                   6672:                }
                   6673:                case 1:
                   6674:                {
                   6675:                        Ptype t = f->argtype->tp;
                   6676:                clll:
                   6677:                        switch (t->base) {
                   6678:                        case TYPE:
                   6679:                                t = Pbase(t)->b_name->tp;
                   6680:                                goto clll;
                   6681:                        case RPTR:                      /* X(X&) ? */
                   6682:                                t = Pptr(t)->typ;
                   6683:                        cxll:
                   6684:                                switch (t->base) {
                   6685:                                case TYPE:
                   6686:                                        t = Pbase(t)->b_name->tp;
                   6687:                                        goto cxll;
                   6688:                                case COBJ:
                   6689:                                        if (class_name == Pbase(t)->b_name)
                   6690:                                                Pclass(class_name->tp)->c_itor = nn;
                   6691:                                }
                   6692:                                break;
                   6693:                        case COBJ:                      /* X(X) ? */
                   6694:                                if (class_name == Pbase(t)->b_name) {
                   6695:                                        error("badK %s(%s) use %s(%s&)",class_name->string,class_name->string,class_name->string,class_name->string);
                   6696:                                        f->argtype->tp = any_type;
                   6697:                                }
                   6698:                        }
                   6699:                }
                   6700:                }
                   6701:                if (Pclass(class_name->tp)->c_ctor == 0) Pclass(class_name->tp)->c_ctor = nn;
                   6702:                break;
                   6703: 
                   6704:        case TYPE:
                   6705:                // somewhat simple minded solution to the inheritance of
                   6706:                // conversion operator problem
                   6707:                nn->n_list = Pclass(class_name->tp)->conv;
                   6708:                Pclass(class_name->tp)->conv = nn;
                   6709:                break;
                   6710: 
                   6711:        case DTOR:
                   6712:                Pclass(class_name->tp)->c_dtor = nn;
                   6713:                break;
                   6714: 
                   6715:        case NEW:       
                   6716:        case DELETE:
                   6717:        case CALL:
                   6718:        case 0:
                   6719:                break;
                   6720: 
                   6721:        default:
                   6722:                for (Pname a=f->argtype; a; a=a->n_list) {
                   6723:                        if ( a->n_initializer )
                   6724:                                error( "%n: operatorFs cannot take defaultA", this );
                   6725:                }
                   6726: 
                   6727:                if (f->nargs_known != 1) {
                   6728:                        error("ATs must be fully specified for%n",nn);
                   6729:                }
                   6730:                // this doesn't catch unary operator off by one errors
                   6731:                // for simplicity, placed that check in check_oper(), above
                   6732:                else if (class_name == 0) {
                   6733:                        switch (f->nargs) {
                   6734:                        case 1:
                   6735:                        case 2:
                   6736:                                for (a=f->argtype; a; a=a->n_list) {
                   6737:                                        Ptype tx = a->tp;
                   6738:                                        while (tx->base == TYPE) tx = Pbase(tx)->b_name->tp;
                   6739:                                        if (tx->is_ref()) tx = Pptr(tx)->typ;
                   6740:                                        if (tx->is_cl_obj()) goto cok;
                   6741:                                }
                   6742:                                error("%n must take at least oneCTA",nn);
                   6743:                                break;
                   6744:                        default:
                   6745:                                error("%n must take 1 or 2As",nn);
                   6746:                        }
                   6747:                }
                   6748:                else {
                   6749:                        switch (f->nargs) {
                   6750:                        case 0:
                   6751:                        case 1:
                   6752:                                break;
                   6753:                        default:
                   6754:                                error("%n must take 0 or 1As",nn);
                   6755:                        }
                   6756:                }
                   6757:        cok:;
                   6758:        }
                   6759: 
                   6760:        int i = 0;      // check that every argument after an argument with
                   6761:                        // initializer have an initializer
                   6762:        for (Pname a = f->f_args/*f->argtype*/; a; a=a->n_list) {
                   6763:                if (a->n_initializer)
                   6764:                        i = 1;
                   6765:                else if (i)
                   6766:                        error("trailingA%n withoutIr",a);
                   6767:        }
                   6768: 
                   6769:        /*
                   6770:                the body cannot be checked until the name
                   6771:                has been checked and entered into its table
                   6772:        */
                   6773:        if (f->body) f->dcl(nn);
                   6774:        return nn;
                   6775: }
                   6776: 
                   6777: 0707071010112043711004440001630000160000010174600466055376600000700000154273dcl4.c/*ident     "@(#)ctrans:src/dcl4.c  1.4" */
                   6778: /**************************************************************************
                   6779: 
                   6780:        C++ source for cfront, the C++ compiler front-end
                   6781:        written in the computer science research center of Bell Labs
                   6782: 
                   6783:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   6784:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   6785: 
                   6786: dcl4.c:
                   6787:        Declaration of class and enum
                   6788: 
                   6789: *************************************************************************/
                   6790: 
                   6791: #include "cfront.h"
                   6792: #include "size.h"
                   6793: #include "template.h"
                   6794: 
                   6795: Pname find_vptr(Pclass);
                   6796: void fix_args(Pfct f, Pclass cl)
                   6797: /*
                   6798:        This function is used to cope with the case where cl::cl(cl&) is
                   6799:        declared AFTER f has been declared
                   6800:        set n_xref bit for f
                   6801: */
                   6802: {
                   6803:        for (Pname a = f->argtype; a; a = a->n_list) {
                   6804:                Pname n = a->tp->is_cl_obj();
                   6805:                if (n && Pclass(n->tp)==cl) a->n_xref = 1;
                   6806:        }
                   6807: }
                   6808: 
                   6809: Pname merge_conv(Pname c1, Pname c2)
                   6810: {
                   6811:        if (c1 == 0) return c2;
                   6812:        if (c2 == 0) return c1;
                   6813:        if (c1 == c2) return c1;
                   6814:        error('s',"cannot merge lists of conversion functions");
                   6815:        return c1;
                   6816: }
                   6817: 
                   6818: static Eppp;
                   6819: 
                   6820: char* get_classname(char* s)
                   6821: /*
                   6822:        retrieve the outermost class name in a vtable name
                   6823: */
                   6824: {
                   6825: //error('d',"get_classname(%s)",s);
                   6826:        char* s1 = 0;
                   6827: 
                   6828:        while (*s) {
                   6829:                s1 = s;
                   6830:                for ( ; s[0] && (s[0] != '_' || s[1] && s[1] != '_'); s++);
                   6831:                if (*s) s += 2; // bypass "__"
                   6832:        }
                   6833: 
                   6834:        return s1;
                   6835: }
                   6836: 
                   6837: char* drop_classname(char* s)
                   6838: /*
                   6839:        retrieve all but the outermost class name in a vtable name
                   6840: */
                   6841: {
                   6842: //error('d',"drop_classname(%s)",s);
                   6843:        char* r = new char[strlen(s)+1];
                   6844:        sprintf(r,s);
                   6845:        s = r;
                   6846: 
                   6847:        char* s1 = s;
                   6848:        while (*s) {
                   6849:                for ( ; s[0] && (s[0] != '_' || s[1] && s[1] != '_'); s++);
                   6850:                if (*s) {
                   6851:                        s1 = s;
                   6852:                        s += 2; // bypass "__"
                   6853:                }
                   6854:        }
                   6855: 
                   6856:        *s1 = '\0';
                   6857: 
                   6858:        return (*r) ? r : 0;
                   6859: }
                   6860:                
                   6861: Pbcl classdef::get_base( char *s )
                   6862: /*
                   6863:        Find the base class whose name matches the argument
                   6864: */
                   6865: {
                   6866: //error('d',"%t::get_base(%s)",this,s);
                   6867:        for (Pbcl b = baselist; b; b = b->next) {
                   6868:                for ( char *s1 = s, *s2 = b->bclass->string;
                   6869:                     *s1 && *s2 && *s1 == *s2;
                   6870:                     s1++, s2++);
                   6871:                
                   6872:                if (!(*s1 || *s2))
                   6873:                        break;
                   6874:        }
                   6875: 
                   6876:        return b;
                   6877: }
                   6878: 
                   6879: int classdef::get_offset(char* s)
                   6880: /*
                   6881:        Get offset represented by string as viewed from "this"
                   6882: */
                   6883: {
                   6884: //error('d',"%t::get_offset(%s)",this,s);
                   6885:        if (!s) return 0;
                   6886: 
                   6887:        Pbcl b = get_base(get_classname(s));
                   6888: 
                   6889:        return b->obj_offset + b->bclass->get_offset(drop_classname(s));
                   6890: }
                   6891: 
                   6892: char* vtbl_str(char* s1, char* s2)
                   6893: /*
                   6894:        combine two pieces of a vtbl name
                   6895: */
                   6896: {
                   6897: //error('d',"vtbl_str(%s,%s)",s1,s2);
                   6898:        char* s3;
                   6899:        if (s1)
                   6900:                if (s2) {
                   6901:                        s3 = new char[strlen(s1)+strlen(s2)+3];
                   6902:                        sprintf(s3,"%s__%s",s1,s2);
                   6903:                        return s3;
                   6904:                }
                   6905:                else
                   6906:                        return s1;
                   6907:        else
                   6908:                return s2;
                   6909: }
                   6910: 
                   6911: void classdef::add_vtbl(velem* v, char* s, bit virt_flag, int n_init)
                   6912: /*
                   6913:        add vtbl to virt_list
                   6914: */
                   6915: {
                   6916: // error('d',"%t->add_vtbl(%d,%s)",this,v,s);
                   6917:        Pvirt vtab = new virt(this, v, s, virt_flag, n_init);
                   6918: 
                   6919:        if (virt_flag) has_vvtab = 1;
                   6920: 
                   6921:        if (!virt_list) {
                   6922:                virt_list = vtab;
                   6923:                return;
                   6924:        }
                   6925: 
                   6926:        // If conficting vtable entries are made because of
                   6927:        // a virtual base class, must be considered an error.
                   6928:        for (Pvirt vt = virt_list; vt; vt = vt->next )
                   6929: //             if (strcmp(vt->string,s)==0) {
                   6930:                 if (vt->string && strcmp(vt->string,s)==0) {
                   6931:                        velem* ivec = vt->virt_init;
                   6932:                        Pname on = ivec[0].n;
                   6933:                        Pname nn = v[0].n;
                   6934:                        Pclass ocl,ncl;
                   6935:                        for (int i=0; on && nn; i++,on=ivec[i].n,nn=v[i].n) {
                   6936:                                ocl = Pfct(on->tp)->memof;
                   6937:                                ncl = Pfct(nn->tp)->memof;
                   6938:                                if (on != nn)
                   6939:                                        if (!ocl->has_base(ncl))
                   6940:                                                if (!ncl->has_base(ocl))
                   6941:                                                        break;
                   6942:                                                else {
                   6943:                                                        ivec[i].n = nn;
                   6944:                                                        ivec[i].offset = v[i].offset;
                   6945:                                                }
                   6946:                        }
                   6947:                        if (on || nn)
                   6948:                                error("virtualB: ambiguous%n and%n", on, nn);
                   6949:                        return;
                   6950:                }
                   6951: 
                   6952:        vtab->next = virt_list->next;
                   6953:        virt_list->next = vtab;
                   6954: }
                   6955: 
                   6956: static int Voffset;    // cope with offsets of virtuals in deep nests
                   6957: int vcounter;
                   6958: static vmax;
                   6959: const vpChunk = 32;
                   6960: 
                   6961: int classdef::do_virtuals(Pvirt vtab, char* str, int leftmost, bit virt_flag)
                   6962: /*
                   6963:        make vtbl for b in "this"
                   6964:        match up virtuals and assign virtual indices for the base or delegate "bcl"
                   6965:        first base class shares ``this'' and vtbl with this class
                   6966: */
                   6967: {
                   6968:        if (vmax<vcounter) vmax = vcounter;
                   6969:         int vpsz = (vmax+vcounter)/vpChunk+1;   // fragmentation prevention
                   6970:         vpsz *= vpChunk;
                   6971:        Pname* vp = new Pname[vpsz];
                   6972:        velem* ivec = vtab ? vtab->virt_init : 0;
                   6973:        int vo = Voffset;
                   6974:        int vc = 0;
                   6975:        int changed = 0;
                   6976: 
                   6977: // error('d',"%t->do_virtuals(%d,%s) voffset %d",this,vtab,str,Voffset);
                   6978: // error('d',"virt_count %d vpsz %d vcounter %d",virt_count,vpsz,vcounter);
                   6979: 
                   6980: if (ivec) {    // vtbl replacement for ivec
                   6981: 
                   6982:        if (vtab->is_vbase) {
                   6983:                str = 0;
                   6984:                Voffset = get_offset(vtab->string);
                   6985:        }
                   6986:        else
                   6987:                Voffset = Voffset + vtab->vclass->get_offset(vtab->string);
                   6988:        Pname vn;
                   6989:        for (int i=0; vn=ivec[i].n; i++) {
                   6990: 
                   6991:        /*      go through virtual table's list of virtuals:
                   6992:                first see if the function is simply inherited
                   6993:                if not, check for a match
                   6994:                if not, then add as new
                   6995:        */
                   6996:        //      Pname vn = ivec[i];
                   6997:                 if ( i >= vpsz ) { // resize vp vector
                   6998:                         int tvpsz = vpsz + vpChunk;
                   6999:                         Pname *tvp = new Pname[ tvpsz ];
                   7000:                         for ( int j = 0; j < i; ++j )
                   7001:                                 tvp[ j ] = vp[ j ];
                   7002:                         delete [vpsz] vp;
                   7003:                         vp = tvp;
                   7004: //error( 'd',"resizing: i: %d vpsz: %d tvpsz: %d", i, vpsz, tvpsz );
                   7005:                         vpsz = tvpsz;
                   7006:                 }
                   7007: 
                   7008:                // char* s = Pchar(vn->n_tbl_list);
                   7009:                 char* s = vn->n_gen_fct_name;
                   7010:                Pname n = memtbl->look(s?s:vn->string, 0);
                   7011: 
                   7012: // error('d',"vn %n %s n %n %d",vn,s,n,Voffset);
                   7013: // error('d',"n %n %k", n, n?n->base:0 );
                   7014:                if (n == 0 ||                           // FCT + FCT
                   7015:                        n->base == PUBLIC ) {           // base::FCT
                   7016:                inher:                  // inherit
                   7017: //                     if (vn->n_initializer) error("cannot inherit pure virtualF%n",vn);
                   7018:                         if (vn->n_initializer) c_abstract = 1;
                   7019:                        vp[i] = vn;
                   7020:                         if ( ivec[i].offset && vtab->is_vbase )
                   7021:                                 vp[i]->n_offset = Voffset - vo;
                   7022:                         else
                   7023:                                 vp[i]->n_offset = ivec[i].offset;
                   7024:                        continue;
                   7025:                }
                   7026: 
                   7027:                Pfct f = Pfct(n->tp);
                   7028: // error ('d', "f %d", f );
                   7029:                if (f == 0 ) continue;
                   7030: // error('d',"f %t %d",f,f->f_virtual);
                   7031: 
                   7032:                if (s && f->base==OVERLOAD) {   // OVERLOAD + OVERLOAD
                   7033:                        // vn is overloaded and s is its name
                   7034:                        for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l)
                   7035:                                if (gl->f == vn)  goto inher;
                   7036:                }
                   7037: 
                   7038:                Pfct vnf = Pfct(vn->tp);
                   7039:                                                // re-define?
                   7040:                switch (f->base) {
                   7041:                default:
                   7042:                        error('w',&n->where,"%n hides virtual%n",n,vn);
                   7043:                        vp[i] = vn;     // not a new overloaded: inherit 
                   7044:                        if ( ivec[i].offset && vtab->is_vbase )
                   7045:                                        vp[i]->n_offset = Voffset - vo;
                   7046:                        else
                   7047:                                        vp[i]->n_offset = ivec[i].offset;
                   7048:                        break;
                   7049:                case FCT:                       // derived::FCT
                   7050:                {
                   7051:                        if (vnf->check(f,VIRTUAL) == 0) { // derived::FCT match base::FCT
                   7052: // error('d',"vnf1 %t f %t vcheck %d",vnf,f,Vcheckerror);
                   7053:                                // VTOK: virtual, but no index assigned
                   7054:                                // you can only inherit an index from your first base
                   7055:                                if (Vcheckerror) error("bad virtualT match for %n",vn);
                   7056:                                if (f->f_virtual==VTOK) f->f_virtual = i+1;
                   7057:                                vp[i] = n;
                   7058:                                vp[i]->n_offset = Voffset;
                   7059:                                changed = 1;
                   7060:                        }
                   7061:                        else {
                   7062: // error('d',"vnf2 %t f %t vcheck %d",vnf,f,Vcheckerror);
                   7063:                                if (Vcheckerror)
                   7064:                                        error("bad virtualT match for %n",vn);
                   7065:                                else
                   7066:                                        switch (f->f_virtual) {
                   7067:                                                case 0:
                   7068:                                                case VTOK:
                   7069:                                                        error('w',&n->where,"%n hides virtual%n",n,vn);
                   7070:                                        }
                   7071:                                vp[i] = vn;     // not a new overloaded: inherit
                   7072:                                 if ( ivec[i].offset && vtab->is_vbase )
                   7073:                                         vp[i]->n_offset = Voffset - vo;
                   7074:                                 else
                   7075:                                         vp[i]->n_offset = ivec[i].offset;
                   7076:                        }
                   7077:                        break;
                   7078:                }
                   7079:                case OVERLOAD:                  // derived::OVERLOAD
                   7080:                {                               
                   7081:                        int hit = 0;
                   7082:                        for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) {
                   7083:                                // try each fct from derived class
                   7084:                                Pname fn = gl->f;
                   7085:                                Pfct f = Pfct(fn->tp);
                   7086:                        
                   7087:                                if (f->check(vnf,VIRTUAL) == 0) {       // derived::FCT
                   7088:                                        if (Vcheckerror) error("bad virtualT match for %n",vn);
                   7089:                                        if  (f->f_virtual==VTOK) f->f_virtual = i+1;
                   7090:                                        vp[i] = fn;
                   7091:                                        vp[i]->n_offset = Voffset;
                   7092:                                        changed = 1;
                   7093:                                        goto found;
                   7094:                                }
                   7095:                                else {
                   7096:                                        if (Vcheckerror) error("bad virtualT match for %n",vn);
                   7097:                                }
                   7098:                                if (Vcheckerror == 0)
                   7099:                                        switch (f->f_virtual) {
                   7100:                                                case 0:
                   7101:                                                case VTOK:
                   7102:                                                        hit = 1;
                   7103:                                }
                   7104:        
                   7105:                        }
                   7106: 
                   7107:                        if (hit) 
                   7108:                                error('w',&n->where,"%n hides virtual%n ofT %t",n,vn,vn->tp);
                   7109: 
                   7110:                        vp[i] = vn;     // not a new overloaded: inherit
                   7111:                         if ( ivec[i].offset && vtab->is_vbase )
                   7112:                                 vp[i]->n_offset = Voffset - vo;
                   7113:                         else
                   7114:                                 vp[i]->n_offset = ivec[i].offset;
                   7115:                found:
                   7116:                        break;
                   7117:                }
                   7118:                }
                   7119:        }
                   7120: 
                   7121:        Voffset = vo;
                   7122:        vc = i;
                   7123: }
                   7124: 
                   7125: // error( 'd', "do_virtuals: out of loop: vc: %d vpsz: %d changed: %d", vc, vpsz,changed );
                   7126: 
                   7127:        if (leftmost) {
                   7128:                /*
                   7129:                        add new virtuals:
                   7130:                        `VTOK' marks ``new virtual, no index assigned''.
                   7131:                        You can only be new once (no base or first base).
                   7132:                */
                   7133:                int i;
                   7134:                for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
                   7135:                        Pfct f = Pfct(nn->tp);
                   7136: 
                   7137:                        if ( vc >= vpsz ) { // resize vp vector
                   7138:                                int tvpsz = vpsz + vpChunk;
                   7139:                                Pname *tvp = new Pname[ tvpsz ];
                   7140:                                for ( int j = 0; j < vc; ++j )
                   7141:                                        tvp[ j ] = vp[ j ];
                   7142:                                delete [vpsz] vp;
                   7143:                                vp = tvp;
                   7144:                                vpsz = tvpsz;
                   7145:                        }
                   7146: 
                   7147: // error('d',"f %n %t",nn,f);
                   7148:                         if (f)
                   7149:                         switch (f->base) {
                   7150:                        case FCT:
                   7151: //error('d',"fv %d",f->f_virtual);
                   7152:                                if (f->f_virtual == VTOK) {
                   7153:                                        // declared virtual, or
                   7154:                                        // virtual in some base
                   7155:                                        f->f_virtual = ++vc;
                   7156:                                        vp[f->f_virtual-1] = nn;
                   7157:                                         vp[f->f_virtual-1]->n_offset = 0;
                   7158:                                        f->f_vdef = 1;
                   7159:                                        changed = 2;
                   7160:                                }
                   7161:                                break;
                   7162:                        case OVERLOAD:
                   7163:                        {       for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) {
                   7164:                                        Pname fn = gl->f;
                   7165:                                        Pfct f = Pfct(fn->tp);
                   7166: 
                   7167:  
                   7168:                                if ( vc >= vpsz ) { // resize vp vector
                   7169:                                        int tvpsz = vpsz + vpChunk;
                   7170:                                        Pname *tvp = new Pname[ tvpsz ];
                   7171:                                        for ( int j = 0; j < vc; ++j ) {
                   7172:                                                tvp[ j ] = vp[ j ];
                   7173:                                        }
                   7174:                                        delete [vpsz] vp;
                   7175:                                        vp = tvp;
                   7176:                                        vpsz = tvpsz;
                   7177:                                }
                   7178:  
                   7179: 
                   7180:                                        if (f->f_virtual == VTOK) {
                   7181:                                                f->f_virtual = ++vc;
                   7182:                                                vp[f->f_virtual-1] = fn;
                   7183:                                                vp[f->f_virtual-1]->n_offset = 0;
                   7184:                                                f->f_vdef = 1;
                   7185:                                                changed = 2;
                   7186:                                        }
                   7187:                                }
                   7188:                                break;
                   7189:                        }
                   7190:                        }
                   7191:                }
                   7192: // error('d',"%s changed %d has_vvtab %d",string,changed,has_vvtab);
                   7193: // error('d',"vc %d vpsz %d",vc,vpsz);
                   7194:                virt_count = 0;
                   7195:                if (changed)
                   7196:                        virt_count = vc;
                   7197:                else if (has_vvtab) {
                   7198:                        virt_merge = 1;
                   7199:                        if (vc && vtab->is_vbase)
                   7200:                                leftmost = 0;
                   7201:                }
                   7202:        }
                   7203: 
                   7204: // error('d',"vc %d ch %d vp[%d] virt_count %d",vc,changed,vpsz,virt_count);
                   7205:        if (changed || !leftmost) {
                   7206:                // vc==0 if all explicit virtuals in fact were declared in base
                   7207:                velem* v = new velem[vc+1];
                   7208: 
                   7209:                for (int i=0; i<vc; i++) {
                   7210:                        v[i].n = vp[i];
                   7211:                        v[i].offset = vp[i]->n_offset;
                   7212:                }
                   7213:                v[vc].n = 0;
                   7214: 
                   7215:                if (leftmost)
                   7216:                        add_vtbl(v,0,0,0);
                   7217:                else
                   7218:                        add_vtbl(v,vtbl_str(vtab->string,str),virt_flag||vtab->is_vbase,vc+1);
                   7219:                delete vp;
                   7220:                vcounter = 0;
                   7221:                return 1;
                   7222:        }
                   7223: 
                   7224:        delete vp;
                   7225:        vcounter = 0;
                   7226:        return 0;
                   7227: }
                   7228: 
                   7229: int classdef::all_virt(Pclass bcl, char* s, int leftmost, bit virt_flag)
                   7230: {
                   7231:        int i = 0;
                   7232:        if (bcl->virt_count) {
                   7233:                for (Pvirt blist = bcl->virt_list; blist; blist = blist->next) {
                   7234:                        // if (has_base(blist->vclass))
                   7235:                        //      if (blist->vclass==bcl
                   7236:                        //              // bcl is virtual in both
                   7237:                        //      || ((Nvirt=0,blist->vclass->has_base(bcl)) && Nvirt==VIRTUAL
                   7238:                        //              && (Nvirt=0,has_base(bcl)) && Nvirt==VIRTUAL
                   7239:                        //         )
                   7240:                        //      )
                   7241:                        if (virt_merge && !(virt_flag || blist->is_vbase))
                   7242:                                continue;
                   7243: 
                   7244:                        i += do_virtuals(blist, s, leftmost, virt_flag);
                   7245:                        if (!i && leftmost && !virt_merge)
                   7246:                                return 0;
                   7247: 
                   7248:                        leftmost = 0;
                   7249:                }
                   7250:        }
                   7251: 
                   7252:        // finding virt_list stops recursive step
                   7253:        // if vtables found and updated, return number
                   7254:        if (i) return i;
                   7255: 
                   7256:        for (Pbcl b = bcl->baselist; b; b = b->next) {
                   7257:        //      if (b->base==PTR) continue;
                   7258:                if (b->promoted) continue;
                   7259: // error('d',"b %t vl %d bl %d",b->bclass,b->bclass->virt_list,b->bclass->baselist);
                   7260:                if (leftmost && b->base == VIRTUAL) {
                   7261:                        i += do_virtuals(0, 0, 1, 0);
                   7262:                        if (!i && !virt_merge)
                   7263:                                return 0;
                   7264:                        leftmost = 0;
                   7265:                }
                   7266:                int vo = Voffset;
                   7267:                Voffset += b->obj_offset;
                   7268: // error('d',"offset %t %d",b->bclass,Voffset);
                   7269: 
                   7270:                if (b->base==VIRTUAL)
                   7271:                        i += all_virt(b->bclass, b->bclass->string, leftmost, 1);
                   7272:                else
                   7273:                        i += all_virt(b->bclass, vtbl_str(b->bclass->string,s), leftmost, virt_flag);
                   7274:                if (!i && leftmost && !virt_merge)
                   7275:                        return 0;
                   7276: 
                   7277:                Voffset = vo;
                   7278:                leftmost = 0;
                   7279:        }
                   7280: 
                   7281:        // if recursion updated vtables, return number
                   7282:        if (i) return i;
                   7283: 
                   7284:        // no vtables updated in recursion
                   7285:        // look for new virtuals
                   7286:        if (leftmost)
                   7287:                return do_virtuals(0, 0, 1, 0);
                   7288:        else
                   7289:                return 0;
                   7290: }
                   7291: 
                   7292: Pexpr copy_obj(Pexpr l, Pexpr r, int sz)
                   7293: /*
                   7294:        generate:
                   7295:        struct _s { char[sz]; };
                   7296:        *(struct _s*)this->m = *(struct _s*)arg.mem;
                   7297: */
                   7298: {
                   7299:        if ( !sz ) sz = 1;
                   7300: //error('d',"copy(%d)",sz);
                   7301:        char* s = make_name('S');
                   7302:        fprintf(out_file,"struct %s { char v[%d]; };\n",s,sz);
                   7303:        Pname n = new name(s);
                   7304:        Ptype t = new basetype(COBJ,n);
                   7305:        t = new ptr(PTR,t);
                   7306: 
                   7307:        l = new texpr(CAST,t,l);//new cast(t,l);
                   7308:        l = l->contents();
                   7309: 
                   7310:        r = new texpr(CAST,t,r);//new cast(t,r);
                   7311:        r = r->contents();
                   7312: 
                   7313:        return new expr(ASSIGN,l,r);
                   7314: }
                   7315: 
                   7316: /*
                   7317: Pname make_default_ctor(Pclass cl)
                   7318: {
                   7319: //error('d',"make_ctor %t",cl);
                   7320:        Pname cn = ktbl->look(cl->string,0);
                   7321:        if (cn) cn = Pbase(cn->tp)->b_name;
                   7322:        cc->stack();
                   7323:        cc->not = cn;
                   7324:        cc->cot = cl;
                   7325:        Pname fn = new name(cl->string);
                   7326:        Pfct f = new fct(defa_type,0,1);
                   7327:        fn->tp = f;
                   7328:        fn->n_oper = TNAME;
                   7329: //     fn->n_sto = STATIC;
                   7330: 
                   7331:        Pfct(f)->f_inline = 1;
                   7332:        f->body = new block(curloc,0,0);
                   7333: 
                   7334:        Pname nn = fn->dcl(cl->memtbl,PUBLIC);
                   7335:        delete fn;
                   7336: 
                   7337:        cc->unstack();
                   7338:        nn->simpl();
                   7339:        if (debug_opt) nn->dcl_print(0);
                   7340: //error('d',"make_ctor->");
                   7341:        return nn;
                   7342: }
                   7343: 
                   7344: Pname make_default_dtor(Pclass cl)
                   7345: {
                   7346: //error('d',"make_dtor %t",cl);
                   7347:        Pname cn = ktbl->look(cl->string,0);
                   7348:        if (cn) cn = Pbase(cn->tp)->b_name;
                   7349:        cc->stack();
                   7350:        cc->not = cn;
                   7351:        cc->cot = cl;
                   7352:        Pname fn = new name(cl->string);
                   7353:        Pfct f = new fct(defa_type,0,1);
                   7354:        fn->tp = f;
                   7355:        fn->n_oper = DTOR;
                   7356: //     fn->n_sto = STATIC;
                   7357: 
                   7358:        Pfct(f)->f_inline = 1;
                   7359:        f->body = new block(curloc,0,0);
                   7360: 
                   7361:        Pname nn = fn->dcl(cl->memtbl,PUBLIC);
                   7362:        delete fn;
                   7363: 
                   7364:        cc->unstack();
                   7365:        nn->simpl();
                   7366:        if (debug_opt) nn->dcl_print(0);
                   7367: //error('d',"make_dtor->");
                   7368:        return nn;
                   7369: }
                   7370: */
                   7371: 
                   7372: Ptype find_arg_type(Pclass cl)
                   7373: // first determine argument type
                   7374: {
                   7375:        int i;
                   7376:        int mod = 0;
                   7377:        for (Pbcl b = cl->baselist; b; b = b->next) {
                   7378:                Pclass bcl = b->bclass;
                   7379:                switch (b->base) {
                   7380:                case VIRTUAL:
                   7381:                case NAME:      //      generate :b(*(b*)&arg)
                   7382:                {
                   7383:                        Pname itor = bcl->has_itor();
                   7384:                        if (itor && itor->tp->base==FCT) {
                   7385:                                Pname a = Pfct(itor->tp)->argtype;
                   7386:                                Pptr p = a->tp->is_ref();
                   7387:                                if (p && p->typ->tconst()==0) {
                   7388:                                        mod = 1;
                   7389:                                        goto ll1;
                   7390:                                }
                   7391:                        }
                   7392:                }
                   7393:                }
                   7394:        }
                   7395: ll1:
                   7396:     if (mod == 0) {
                   7397:        for (Pname m=cl->memtbl->get_mem(i=1); m; m=cl->memtbl->get_mem(++i) ) {
                   7398:                Pname cln;
                   7399:                // ignore static members
                   7400:                if (m->n_evaluated || m->n_stclass==STATIC) continue;
                   7401: 
                   7402:                if (cln = m->tp->is_cl_obj()) {
                   7403:                        Pname itor = Pclass(cln->tp)->has_itor();
                   7404:                        if (itor && itor->tp->base==FCT) {
                   7405:                                Pname a = Pfct(itor->tp)->argtype;
                   7406:                                Pptr p = a->tp->is_ref();
                   7407:                                if (p && p->typ->tconst()==0) {
                   7408:                                        mod = 1;
                   7409:                                        goto ll2;
                   7410:                                }
                   7411:                        }
                   7412:                }
                   7413:        }
                   7414:     }
                   7415: ll2:
                   7416: //error('d',"mod %d",mod);
                   7417:                Pbase bp = new basetype(INT,0);
                   7418:                *bp = *Pbase(Pptr(cl->this_type)->typ);
                   7419:                if (mod == 0) bp->b_const = 1;
                   7420:                return new ptr(RPTR,bp);
                   7421: }
                   7422: 
                   7423: Pname classdef::make_itor(int def)
                   7424: /*
                   7425:        make cn::cn(const cn&) :bases_and_members_of_cn {}
                   7426: */
                   7427: {
                   7428: //error('d',"%t->make_itor(%d) %d",this,def,obj_size);
                   7429:        Pstmt s;
                   7430:        Pname e;
                   7431:        int i;
                   7432:        Pname arg = new name(make_name('A'));
                   7433:        arg->tp = find_arg_type(this);
                   7434: 
                   7435: //     c_xref = 2;  // now it has X(X&)
                   7436:        c_xref |= C_XREF;  // now it has X(X&)
                   7437: 
                   7438:     if (def) {
                   7439:        // define itor
                   7440:        int slow = 0;   // slow==0 => copy using vector copy
                   7441:        int first = 1;
                   7442:        Pexpr es = 0;
                   7443:        s = new estmt(SM,no_where,0,0);
                   7444:        e = 0;
                   7445: 
                   7446: 
                   7447:        if (warning_opt && 128<obj_size)
                   7448:                error('w',"copying a %d byte object (ofC %s)",obj_size,string);
                   7449: 
                   7450:        if (baselist) slow = 1;
                   7451:                
                   7452:        //for (Pbcl v = baselist; v; v = v->next)
                   7453:        //      if (v->base == VIRTUAL) {
                   7454:        //              slow = 1;
                   7455:        //              break;
                   7456:        //      }
                   7457: 
                   7458:        // initialize bases:
                   7459:     if (slow) {
                   7460:        for (Pbcl b = baselist; b; b = b->next) {
                   7461:                Pclass bcl = b->bclass;
                   7462:                Ptype pt = bcl->this_type;
                   7463: //error('d',"base %t %k offset %d ptroffset %d",bcl,b->base,b->obj_offset,b->ptr_offset);
                   7464:                switch (b->base) {
                   7465:                case VIRTUAL:
                   7466:                case NAME:      //      generate :b(*(b*)&arg)
                   7467:                {
                   7468:                        Pexpr b2 = new name(arg->string);
                   7469:                        b2 = b2->address();
                   7470:                        b2 = new texpr(CAST,pt,b2);//new cast(pt,b2);
                   7471:                        b2->i2 = 1;
                   7472:                        b2 = b2->contents();
                   7473: 
                   7474:                        Pname ee = new name(bcl->string);
                   7475:                        ee->base = TNAME;
                   7476:                        ee->n_initializer = b2;
                   7477:                        if (e) ee->n_list = e;
                   7478:                        e = ee;
                   7479:                        break;
                   7480:                }
                   7481:                }
                   7482:        }
                   7483:     }
                   7484: 
                   7485:        // initialize members
                   7486:        for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) {
                   7487:                // ignore static members
                   7488:                if (m->n_evaluated || m->n_stclass==STATIC) continue;
                   7489: 
                   7490:                if (strcmp(m->string,"__vptr")==0) {
                   7491: // error('d',"%t vptr: %d",this,first);
                   7492:                        if (first==0 && m->n_offset) {
                   7493:                                Pexpr th = new expr(THIS,0,0);
                   7494:                                Pexpr a = new name(arg->string);
                   7495:                                a = a->address();
                   7496:                                Pexpr ee = copy_obj(th,a,m->n_offset);
                   7497:                                es = es ? new expr(CM,es,ee) : ee;
                   7498:                        }
                   7499:                        slow = 1;
                   7500:                        first = 0;
                   7501:                        continue;
                   7502:                }
                   7503:                Ptype mt = m->tp;
                   7504:        tx:
                   7505:                switch (mt->base) {
                   7506:                case TYPE:
                   7507:                        mt = Pbase(mt)->b_name->tp;
                   7508:                        goto tx;
                   7509:                case VEC:
                   7510:                {       Pname cn = Pvec(mt)->typ->is_cl_obj();
                   7511: //error('d',"vec %n %t xref %d",m,mt,cn?Pclass(cn->tp)->c_xref:0);
                   7512:                        if (cn && Pclass(cn->tp)->c_xref&(C_XREF|C_VBASE)) {
                   7513:                                error('s',"copy of %n[], no memberwise copy for%n",cn,cn);
                   7514:                                slow = 1;       // make sure an assignment operator
                   7515:                                                // is generated so that there will
                   7516:                                                // be no more error messages
                   7517:                        }
                   7518: 
                   7519:                        if (slow && mt->tsizeof()) {
                   7520:                        /*
                   7521:                                generate:
                   7522:                                struct _s { char[sizeof(m)]; };
                   7523:                                *(struct _s*)this->m = *(struct _s*)arg.mem;
                   7524:                        */
                   7525:                                Pexpr l = new name(m->string);
                   7526:                                Pexpr r = new name(m->string);
                   7527:                                r = new ref(DOT,new name(arg->string),r);
                   7528:                                Pexpr ee = copy_obj(l,r,mt->tsizeof());
                   7529:                                es = es ? new expr(CM,es,ee) : ee;
                   7530:                                break;
                   7531:                        }
                   7532:                }
                   7533:                case FCT:
                   7534:                case OVERLOAD:
                   7535:                case CLASS:
                   7536:                case ENUM:
                   7537:                        break;
                   7538:                case COBJ:
                   7539:                {       Pclass mcl = Pclass(Pbase(mt)->b_name->tp);
                   7540:                        if (slow==0     // if slow, previous members have
                   7541:                                        // already been copied
                   7542:                        && mcl->c_xref&(C_VBASE|C_XREF)) {
                   7543:                                slow = 1;
                   7544:                                if (first==0 && m->n_offset) {
                   7545:                                                //AAA copy up to here
                   7546:                                        Pexpr th = new expr(THIS,0,0);
                   7547:                                        Pexpr a = new name(arg->string);
                   7548:                                        a = a->address();
                   7549:                                        Pexpr ee = copy_obj(th,a,m->n_offset);
                   7550:                                        es = es ? new expr(CM,es,ee) : ee;
                   7551:                                }
                   7552:                        }
                   7553:                        // no break
                   7554:                }
                   7555: 
                   7556:                default:
                   7557:                        if (slow) {
                   7558: //error('d',"slow %s %s",m->string,arg->string);
                   7559:                                Pname ee = new name(m->string);
                   7560:                                ee->n_initializer = new ref(DOT,new name(arg->string),new name(m->string));
                   7561:                                if (e) ee->n_list = e;
                   7562:                                e = ee;
                   7563:                        }
                   7564:                }
                   7565:                first = 0;
                   7566:        }
                   7567:        
                   7568:        if (slow == 0) {
                   7569:        /*      really simple just copy:
                   7570:                the only problem was a vptr which can be
                   7571:                ignored since X(X&) is going to reset it anyway
                   7572:                don't use assignment of this struct to avoid operator=
                   7573:        */
                   7574:                Pexpr th = new expr(THIS,0,0);
                   7575:                Pexpr a = new name(arg->string);
                   7576:                a = a->address();
                   7577:                Pexpr ee = copy_obj(th,a,obj_size);
                   7578:                es = es ? new expr(CM,es,ee) : ee;
                   7579:        }
                   7580: 
                   7581:        s->e = es;
                   7582:        Pname cn = ktbl->look(string,0);
                   7583:        if (cn) cn = Pbase(cn->tp)->b_name;
                   7584:        cc->stack();
                   7585:        cc->not = cn;
                   7586:        cc->cot = this;
                   7587: }
                   7588:        Pname fn = new name(string);
                   7589:        Pfct f = new fct(defa_type,arg,1);
                   7590:        fn->tp = f;
                   7591:        fn->n_oper = TNAME;
                   7592: //     fn->n_sto = STATIC;
                   7593: 
                   7594:        Pfct(f)->f_inline = def?1:ITOR; // ITOR means ``define itor() if used''
                   7595:        if (def) {
                   7596:                f->body = new block(curloc,0,s);
                   7597:                f->f_init = e;
                   7598:        }
                   7599: 
                   7600:        Pname nn = fn->dcl(memtbl,PUBLIC);
                   7601:        delete fn;
                   7602: 
                   7603:        if (def) {
                   7604:                cc->unstack();
                   7605:                nn->simpl();
                   7606:                if (debug_opt) nn->dcl_print(0);
                   7607:        }
                   7608: //error('d',"make_itor->");
                   7609:        return nn;
                   7610: }
                   7611: 
                   7612: int make_assignment(Pname cn)
                   7613: /*
                   7614:        write the function:
                   7615: 
                   7616:        X& X::operator=(const X&) { assign all bases and members }
                   7617: 
                   7618:        return 1 is a function is really synthesized
                   7619: */
                   7620: {
                   7621:        Pclass cl = Pclass(cn->tp);
                   7622:        Pstmt s = new estmt(SM,no_where,0,0);
                   7623:        Pexpr e = 0;
                   7624:        Pname arg = new name(make_name('A'));
                   7625:        basetype* bp = new basetype(INT,0);
                   7626:        *bp = *Pbase(Pptr(cl->this_type)->typ);
                   7627:        bp->b_const = 1;
                   7628: //     arg->tp = new ptr(RPTR,bp);
                   7629:        arg->tp = find_arg_type(cl);
                   7630: //error('d',"make_assignment %t %d",cl,cl->obj_size);
                   7631: //     cl->c_xref |= 4;  // now it has X::operator=(const X&)
                   7632: 
                   7633:        if (warning_opt && 128<cl->obj_size)
                   7634:                error('w',"copying a %d byte object (ofC %s)",
                   7635:                        cl->obj_size,cl->string);
                   7636: {
                   7637:        int slow = 0;   // slow==0 => copy using vector copy
                   7638:        int first = 1;  // first==1 => first member of (derived) class
                   7639: 
                   7640:        if (cl->baselist) slow = 1;     // be dumb and safe
                   7641: //     for (Pbcl v = cl->baselist; v; v = v->next)
                   7642: //             if (v->base==VIRTUAL || v->c_xref&(C_VBASE|C_ASS)) {
                   7643: //                     slow = 1;
                   7644: //                     break;
                   7645: //             }
                   7646: 
                   7647:     if (slow) {
                   7648:        for (Pbcl b = cl->baselist; b; b = b->next) {
                   7649:                Pclass bcl = b->bclass;
                   7650:                Ptype pt = bcl->this_type;
                   7651:                switch (b->base) {
                   7652:                case NAME:
                   7653:                {       // generate: *(bcl*)this = *(bcl*)&arg;
                   7654: //error('d',"base %t",bcl);
                   7655:                        Pexpr b1 = new expr(THIS,0,0);
                   7656:                        b1 = new texpr(CAST,pt,b1);
                   7657:                        b1 = b1->contents();
                   7658: 
                   7659:                        Pexpr b2 = new name(arg->string);
                   7660:                        b2 = b2->address();
                   7661:                        b2 = new texpr(CAST,pt,b2);
                   7662:                        b2->i2 = 1;
                   7663:                        b2 = b2->contents();
                   7664: 
                   7665:                        Pexpr ee = new expr(ASSIGN,b1,b2);
                   7666:                        e = e ? new expr(CM,e,ee) : ee;
                   7667:                        break;
                   7668:                }
                   7669:                case VIRTUAL:
                   7670:                        if (warning_opt)
                   7671:                                error('w',"copying an object ofC%n with a virtualBC",cn);
                   7672:                        if (b->ptr_offset) {
                   7673:                                // copy object, but not pointer
                   7674:                                // generate: *(bcl*)this->Pw = *(bcl*)arg->Pw;
                   7675: 
                   7676:                                // I don't know how to avoid copying the object
                   7677:                                // once for each pointer
                   7678: 
                   7679:                                Pexpr b1 = new expr(THIS,0,0);
                   7680:                                b1 = new mdot(bcl->string,b1);
                   7681:                                b1->i1 = 3;
                   7682:                                b1->tp = pt;
                   7683:                                b1 = new expr(DEREF,b1,0);//b1->contents();
                   7684: 
                   7685:                                Pexpr b2 = new name(arg->string);
                   7686:                                b2 = b2->address();
                   7687:                                b2 = new mdot(bcl->string,b2);
                   7688:                                b2->i1 = 3;
                   7689:                                b2->tp = pt;
                   7690:                                b2 = new expr(DEREF,b2,0);//b2->contents();
                   7691: 
                   7692:                                Pexpr ee = new expr(ASSIGN,b1,b2);
                   7693:                                e = e ? new expr(CM,e,ee) : ee;
                   7694:                        }
                   7695:                        break;
                   7696:                }
                   7697:        }
                   7698:     }
                   7699: 
                   7700:        int i;
                   7701:        for (Pname m=cl->memtbl->get_mem(i=1); m; m=cl->memtbl->get_mem(++i) ) {
                   7702:                // ignore static members
                   7703:                if (m->n_evaluated || m->n_stclass==STATIC) continue;
                   7704: 
                   7705:                if (strcmp(m->string,"__vptr")==0) {    // don't copy vptrs
                   7706:                                                        // we may be copying
                   7707:                                                        // into a base class object
                   7708:                if (first==0 && m->n_offset) {
                   7709:                                        // copy up to (but not including) vptr
                   7710:                                        // don't copy if first member
                   7711:                                Pexpr th = new expr(THIS,0,0);
                   7712:                                Pexpr a = new name(arg->string);
                   7713:                                a = a->address();
                   7714:                                Pexpr ee = copy_obj(th,a,m->n_offset);
                   7715:                                e = e ? new expr(CM,e,ee) : ee;
                   7716:                        }
                   7717:                        slow = 1;
                   7718:                        first = 0;
                   7719:                        continue;
                   7720:                }
                   7721:                Ptype mt = m->tp;
                   7722:        tx:
                   7723:                switch (mt->base) {
                   7724:                case TYPE:
                   7725:                        mt = Pbase(mt)->b_name->tp;
                   7726:                        goto tx;
                   7727:                case VEC:
                   7728:                {       Pname cn = Pvec(mt)->typ->is_cl_obj();
                   7729:                        if (cn && Pclass(cn->tp)->c_xref&(C_ASS|C_VBASE)) {
                   7730:                                error('s',"copy of %n[], no memberwise copy for%n",cn,cn);
                   7731:                                slow = 1;       // make sure an assignment operator
                   7732:                                                // is generated so that there will
                   7733:                                                // be no more error messages
                   7734:                        }
                   7735: 
                   7736:                        if (slow && mt->tsizeof()) {
                   7737:                                // protect against sizeof(mt)==0: char[]
                   7738:                        /*
                   7739:                                generate:
                   7740:                                        struct _s { char[sizeof(m)]; };
                   7741:                                        *(struct _s*)this->m = *(struct _s*)arg.mem;
                   7742:                        */      
                   7743:                                Pexpr l = new name(m->string);
                   7744:                                Pexpr r = new name(m->string);
                   7745:                                r = new ref(DOT,new name(arg->string),r);
                   7746:                                Pexpr ee = copy_obj(l,r,mt->tsizeof());
                   7747:                                e = e ? new expr(CM,e,ee) : ee;
                   7748:                                break;
                   7749:                        }
                   7750:                }
                   7751:                case FCT:
                   7752:                case OVERLOAD:
                   7753:                case CLASS:
                   7754:                case ENUM:
                   7755:                        break;
                   7756:                case RPTR:
                   7757:                        error("cannot assignC%t:RM%n",cl,m);
                   7758:                        break;
                   7759:                case COBJ:
                   7760: //error('d',"cobj %n %d %d",m,slow,Pclass(Pbase(mt)->b_name->tp)->c_xref);
                   7761:                        if (slow==0
                   7762:                        && Pclass(Pbase(mt)->b_name->tp)->c_xref&(C_VBASE|C_ASS)) {
                   7763:                                // must use its assignment operation
                   7764:                                if (first==0 && m->n_offset) {
                   7765:                                                // copy up to this member 
                   7766:                                        Pexpr th = new expr(THIS,0,0);
                   7767:                                        Pexpr a = new name(arg->string);
                   7768:                                        a = a->address();
                   7769:                                        e = copy_obj(th,a,m->n_offset);
                   7770:                                }
                   7771:                                slow = 1;
                   7772:                        }
                   7773:                        // no break: copy cobj itself
                   7774:                default:
                   7775:  //error('d',"defa %n %d",m,slow);
                   7776:                        if (slow) {
                   7777:                                if (m->tp->tconst()) error("cannot assignC%t: const M%n",cl,m);
                   7778:                                Pname ms = new name(m->string);
                   7779:                                Pname as = new name(arg->string);
                   7780:                                Pexpr ee = new ref(DOT,as,new name(m->string));
                   7781:                                ee = new expr(ASSIGN,ms,ee);
                   7782:                                e = e ? new expr(CM,e,ee) : ee;
                   7783:                        }
                   7784:                }
                   7785:                first = 0;
                   7786:        }
                   7787: 
                   7788:         if (slow == 0) {
                   7789:         /*      really simple just copy:
                   7790:         */
                   7791: //error('d',"slow");
                   7792: /*
                   7793:                 Pexpr th = new expr(THIS,0,0);
                   7794:                 Pexpr a = new name(arg->string);
                   7795:                 a = a->address();
                   7796:                 Pexpr ee = copy_obj(th,a,cl->tsize());
                   7797:                 e = e ? new expr(CM,e,ee) : e;
                   7798: */
                   7799: //error('d',"%n simple assignment",cn);
                   7800:        //      cl->c_xref ^= C_ASS; // Didn't mean it: No X::operator=(X&)
                   7801:                return 0;
                   7802:         }
                   7803: 
                   7804: }
                   7805: 
                   7806:        Pexpr rv = new expr(THIS,0,0);
                   7807:        rv = new expr(DEREF,rv,0);//b1->contents();
                   7808:        
                   7809:        s->e = e ? new expr(CM,e,rv) : e;
                   7810:        s->s_list = new estmt(RETURN,no_where,rv,0);
                   7811: 
                   7812:        cc->stack();
                   7813:        cc->not = cn;
                   7814:        cc->cot = cl;
                   7815: 
                   7816:        cl->c_xref |= C_ASS;  // now it has X::operator=(const X&)
                   7817: 
                   7818:        Pname fn = new name(oper_name(ASSIGN));
                   7819:        Pfct f = new fct(new ptr(RPTR,Pptr(cl->this_type)->typ),arg,1);
                   7820:        f->f_inline = 1;
                   7821:        fn->tp = f;
                   7822:        fn->n_oper = ASSIGN;
                   7823:        fn->n_sto = STATIC;
                   7824:        Pname nn = fn->dcl(cl->memtbl,PUBLIC);
                   7825:        delete fn;
                   7826:        Pfct(nn->tp)->body = new block(curloc,0,s);
                   7827:        Pfct(nn->tp)->dcl(nn);
                   7828: 
                   7829:        cc->unstack();
                   7830:        nn->simpl();
                   7831: //error('d',"make_assign->");
                   7832:        return 1;
                   7833: }
                   7834: 
                   7835: void classdef::dcl(Pname cname, Ptable tbl)
                   7836: {
                   7837:        int bvirt = 0;
                   7838:        int dvirt = 0;
                   7839:        int scope = PUBLIC;
                   7840:        int protect = 0;
                   7841:        int st = 1;             // nothing private or protected seen: a struct
                   7842:        // int nstd = (in_class && nested_sig)?2:(in_class?1:0); // nested class
                   7843: 
                   7844:        int byte_old = byte_offset;
                   7845:        int bit_old = bit_offset;
                   7846:        int max_old = max_align;
                   7847:        int boff = 0;
                   7848: 
                   7849:        int in_union = 0;
                   7850:        int usz;
                   7851:        int make_ctor = 0;
                   7852:        int make_dtor = 0;
                   7853: 
                   7854:        /* this is the place for paranoia */
                   7855:        if (this == 0) error('i',"0->Cdef::dcl(%p)",tbl);
                   7856:        if (base != CLASS) error('i',"Cdef::dcl(%d)",base);
                   7857:        if (cname == 0) error('i',"unNdC");
                   7858:        if (cname->tp != this) error('i',"badCdef");
                   7859:        if (tbl == 0) error('i',"Cdef::dcl(%n,0)",cname);
                   7860:        if (tbl->base != TABLE) error('i',"Cdef::dcl(%n,tbl=%d)",cname,tbl->base);
                   7861:        DB( if(Ddebug>=1) error('d',&cname->where,"classdef::dcl %s tbl %d gtbl %d",string,tbl,gtbl); );
                   7862: // error('d',&cname->where,"classdef::dcl %s tbl %d gtbl %d",string,tbl,gtbl); 
                   7863: 
                   7864:        switch (csu) {
                   7865:        case UNION:
                   7866:                in_union = UNION;
                   7867:                break;
                   7868:        case ANON:
                   7869:                in_union = ANON;
                   7870:                break;
                   7871:        case CLASS:
                   7872:                scope = 0;
                   7873:        }
                   7874: 
                   7875:        max_align = AL_STRUCT;
                   7876: 
                   7877:        if (lex_level) {
                   7878: // error('d',&cname->where,"%t::dcl in_class: %t lex_level %d ",this,in_class, lex_level); 
                   7879:                if ( in_class )
                   7880:                        lex_level = 0;
                   7881:                else {
                   7882:                        in_fct = cc->nof;
                   7883:                        if ( lcl == 0 ) lcl = make_name( 'L' );
                   7884:                }
                   7885:        }
                   7886: 
                   7887:        if (strlen == 0) strlen = ::strlen(string);
                   7888:        if (baselist) {
                   7889:                /*
                   7890:                        check base classes.
                   7891:                        duplicates were removed in start_cl() in norm.c.
                   7892:                        remove bad classes.
                   7893:                        add virtual bases from bases to the list.
                   7894: 
                   7895:                        check against
                   7896:                                class b : a {}
                   7897:                                class c : a, b {}       // first a inaccessible
                   7898:                */
                   7899:                
                   7900:                Pbcl ll = 0;
                   7901:                Pbcl lll = 0;
                   7902:                Pbcl vlist = 0;
                   7903:                for (Pbcl lx, l=baselist; l; l=lx) {    // remove bad bases
                   7904:                        Pclass cl = l->bclass;
                   7905:                        /* restriction lifted: nested and local classes
                   7906:                        int b_nstd = (cl->in_class && cl->nested_sig) 
                   7907:                                        ?2:(cl->in_class?1:0); 
                   7908: 
                   7909:                        if (b_nstd) 
                   7910:                                error((b_nstd==2)?0:'w',"%s derived from nestedC %s", string, cl->string);
                   7911:                        if (cl->lex_level) 
                   7912:                                error('w',"%s derived from localC  %s", string, cl->string);
                   7913:                        */
                   7914: 
                   7915:                        lx = l->next;
                   7916: 
                   7917: //error('d',"base1 %t %k init %d",cl,l->ppp,l->init);
                   7918:                        // ``class'' => private base ``struct'' => public base
                   7919:                        if (l->ppp == 0) {
                   7920:                                l->ppp = csu==CLASS ? PRIVATE : PUBLIC;
                   7921: #ifndef OLD
                   7922:                                if (l->ppp == PRIVATE) error('w',"B%t private by default: please be explicit ``: private%t",cl,cl);
                   7923: #endif
                   7924:                        }
                   7925:                        // if you have a ``class'' as base you cannot remain a
                   7926:                        // ``mere struct''
                   7927:                        if (cl && cl->csu == CLASS) st = 0;
                   7928: 
                   7929:                        if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) {
                   7930:                                error("BC %sU",cl->string);
                   7931:                                continue;
                   7932:                        }
                   7933:                        else
                   7934:                                (void)cl->tsizeof();    // ensure printout
                   7935: 
                   7936:                        if (cl->csu==UNION || cl->csu==ANON) {
                   7937:                                error("C derived from union");
                   7938:                                continue;
                   7939:                        }
                   7940: 
                   7941:                        if (in_union) {
                   7942:                                error("derived union");
                   7943:                                continue;
                   7944:                        }
                   7945: 
                   7946:                        if (l->base==VIRTUAL) {
                   7947:                        // constraint removed ...
                   7948:                        //      if (cl->has_ictor()==0 && cl->has_ctor()) {
                   7949:                        //              error("virtualB%t has no defaultIr",cl);
                   7950:                        //              continue;
                   7951:                        //      }
                   7952:                                // order of virtual classes doesn't matter
                   7953:                                l->next = vlist;
                   7954:                                vlist = l;
                   7955:                        }
                   7956:                        else {  // keep ordinary base classes in order
                   7957:                                if (ll == 0) {
                   7958:                                        lll = l;
                   7959:                                        l->next = 0;
                   7960:                                }
                   7961:                                else
                   7962:                                        ll->next = l;
                   7963:                                ll = l;
                   7964:                        }
                   7965:                }
                   7966:                if (ll) {
                   7967:                        ll->next = vlist;       // put virtual bases at end
                   7968:                        baselist = lll;
                   7969:                }
                   7970:                else
                   7971:                        baselist = vlist;
                   7972: 
                   7973:                lll = 0;
                   7974:                for (l=baselist; l; l=l->next) {        // detect unmanageable duplicates
                   7975:                        Pclass b = l->bclass;
                   7976:                        for (ll=baselist; ll; ll=ll->next)
                   7977:                                if (b!=ll->bclass && ll->bclass->check_dup(b,l->base)) {
                   7978:                                        if (lll)
                   7979:                                                lll->next = l->next;
                   7980:                                        else
                   7981:                                                baselist = l->next;
                   7982:                                        goto mmm;
                   7983:                                }
                   7984:                                                
                   7985:                        lll = l;
                   7986:                        mmm:;
                   7987:                }
                   7988: 
                   7989:                for (l=baselist; l; l=l->next) {        // promote virtual bases
                   7990:                        Pclass b = l->bclass;
                   7991:                        for (ll=b->baselist; ll; ll=ll->next) {
                   7992:                                if (ll->base == VIRTUAL) {
                   7993:                                        Pclass v = ll->bclass;
                   7994:                                        for (Pbcl lll=baselist; lll; lll=lll->next)
                   7995:                                                if (lll->bclass == v) goto nnn;
                   7996:                //                      error('w',"%t is virtualB of%t",v,this);
                   7997:                                        baselist = new basecl(v,baselist);
                   7998:                                        baselist->base = VIRTUAL;
                   7999:                                        baselist->promoted = 1;
                   8000: // needs a more complete check of visibility rules
                   8001: //error('d',"promote %t %k",v,ll->ppp);
                   8002:                                        baselist->ppp = ll->ppp;
                   8003:                                }
                   8004:                                nnn:;
                   8005:                        }
                   8006:                }
                   8007: 
                   8008:                ll = 0;
                   8009:                lll = 0;
                   8010:                l=baselist;
                   8011:                baselist = 0;
                   8012:                vlist = 0;
                   8013:                for (; l; l=lx) {
                   8014:                        // sort virtual bases so that no virtual base
                   8015:                        // is ahead of its own virtual base
                   8016:                        lx = l->next;
                   8017:                        if (l->base == VIRTUAL) { // add to sorted vlist
                   8018:                                                  // each class before its bases
                   8019:                                if (vlist == 0) {
                   8020:                                        vlist = l;
                   8021:                                        l->next = 0;
                   8022:                                }
                   8023:                                else {
                   8024:                                        Pclass lb = l->bclass;
                   8025:                                        Pbcl v_prev = 0;
                   8026:                                        for (Pbcl vx, v = vlist; v; v=vx) {
                   8027:                                                Pclass vb = v->bclass;
                   8028:                                                vx = v->next;
                   8029: 
                   8030:                                                if (lb->has_base(vb)) {
                   8031:                                                        // put l ahead of v
                   8032:                                                        l->next = v;
                   8033:                                                        if (v_prev)
                   8034:                                                                v_prev->next = l;
                   8035:                                                        else
                   8036:                                                                vlist = l;
                   8037:                                                        break;
                   8038:                                                }
                   8039:                                                if (vx == 0) {
                   8040:                                                        // stick l at end
                   8041:                                                        v->next = l;
                   8042:                                                        l->next = 0;
                   8043:                                                        break;
                   8044:                                                }       
                   8045:                                                v_prev = v;
                   8046:                                        }
                   8047:                                }
                   8048:                        }
                   8049:                        else {  // keep in order
                   8050:                                if (ll == 0) {
                   8051:                                        lll = l;
                   8052:                                        l->next = 0;
                   8053:                                }
                   8054:                                else
                   8055:                                        ll->next = l;
                   8056:                                ll = l;
                   8057:                        }
                   8058:                }
                   8059: 
                   8060:                if (ll) {
                   8061:                        ll->next = vlist;       // put virtual bases at end
                   8062:                        baselist = lll;
                   8063:                }
                   8064:                else
                   8065:                        baselist = vlist;
                   8066: 
                   8067:                for (l=baselist; l; l=l->next) { // allocate base class objects
                   8068:                        Pclass cl = l->bclass;
                   8069: //error('d',"base %t %k init %d",cl,l->ppp,l->init);
                   8070:                        if (l->base == VIRTUAL) {       // : virtual bclass
                   8071:                                // pointer and object for virtual base MAY
                   8072:                                // be allocated at the end - but not here
                   8073:                                c_xref |= C_VBASE;
                   8074:                                dvirt += cl->virt_count;
                   8075:                        }
                   8076:                        else {                          // : bclass =>allocate
                   8077:                                int ba = cl->align();
                   8078:                                if (max_align<ba) max_align = ba;
                   8079: 
                   8080:                                if (cl == baselist->bclass) {
                   8081:                                        // pad to ensure alignment:
                   8082:                                        boff = cl->real_size;
                   8083:                                        // not obj_size-real_size, we can
                   8084:                                        // optimize vbase object away
                   8085:                                        int xtra = boff%ba;
                   8086:                                        // align
                   8087:                                        if (xtra) boff += ba-xtra;
                   8088:                                }
                   8089:                                else {  // let C handle the padding:
                   8090:                                        int xtra = boff%ba;
                   8091:                                        if (xtra) boff += ba-xtra;      // align
                   8092:                                        l->obj_offset = boff;
                   8093:                                        // don't use waste
                   8094:                                        boff += cl->obj_size;
                   8095:                                }
                   8096:                                bvirt += cl->virt_count;
                   8097:                        }
                   8098: 
                   8099:                         if (cl->has_vvtab) has_vvtab = 1;
                   8100:                        c_xref |= cl->c_xref;
                   8101: 
                   8102: //error('d',"%t: base %t conv %d base conv %d",this,cl,conv,cl->conv);
                   8103:                        conv = merge_conv(conv,cl->conv);
                   8104:                }
                   8105:        }
                   8106: 
                   8107:        memtbl->set_name(cname);
                   8108: 
                   8109: //     int nmem = mem_list->no_of_names();
                   8110:        int nmem = 0;
                   8111:        int fct_mem = 0;
                   8112:        {       for (Pname m = mem_list; m; m=m->n_list) {
                   8113:                        nmem++;
                   8114:                        if (m->tp && m->tp->base==FCT) fct_mem++;
                   8115:                }
                   8116:        }
                   8117:        if (nmem) memtbl->grow((nmem<=2)?3:nmem);
                   8118: 
                   8119:        cc->stack();
                   8120:        cc->not = cname;
                   8121:        cc->cot = this;
                   8122: 
                   8123:        byte_offset = usz = boff;
                   8124:        bit_offset = 0;
                   8125:        
                   8126:        int real_virts = 0;
                   8127:        Pbase bt = new basetype(COBJ,cname);
                   8128:        bt->b_table = memtbl;
                   8129:        Ptype cct = bt->addrof();
                   8130:        // for strict opt type of `this': X *const
                   8131:        // '2' distinguishes this case from a real constant object
                   8132:        if (strict_opt) Pptr(cct)->rdo = 2;
                   8133:        this_type = cc->tot = cct;
                   8134:        PERM(cct);
                   8135:        PERM(bt);
                   8136: 
                   8137:        for (Pname px, p=mem_list; p; p=px) {
                   8138:        /*
                   8139:                look at each member;
                   8140:                declare it and determine its visibility
                   8141:                calculate offsets and sizes
                   8142:        */
                   8143:                px = p->n_list;
                   8144: // error( 'd', "p: %n %k n_scope: %d", p, p->base, p->n_scope );
                   8145: 
                   8146:                switch (p->base) {
                   8147:                case PUBLIC:
                   8148:                        scope = PUBLIC;
                   8149:                        protect = 0;
                   8150:                        goto prpr;
                   8151: 
                   8152:                case PRIVATE:
                   8153:                        scope = 0;
                   8154:                        protect = 0;
                   8155:                        goto prpr;
                   8156: 
                   8157:                case PROTECTED:
                   8158:                        scope = 0;
                   8159:                        protect = PROTECTED;
                   8160:                prpr:
                   8161:                        if (in_union == ANON) error(&p->where,"%k in anonymous unionD",p->base);
                   8162:                        continue;
                   8163: 
                   8164:                case PR:        // visibility control:  C::M
                   8165:                {
                   8166:                        char* qs = p->n_qualifier->string;
                   8167:                        char* ms = p->string;
                   8168:                        TOK ppp = scope?PUBLIC:(protect?PROTECTED:PRIVATE);
                   8169: 
                   8170:                        p->base = NAME;
                   8171:                        p->n_scope = scope;
                   8172:                        p->n_protect = protect;
                   8173: 
                   8174:                        if (strcmp(ms,qs) == 0) ms = "__ct";
                   8175: 
                   8176:                        ppbase = PUBLIC;
                   8177: 
                   8178:                        if (is_base(qs) == 0) {
                   8179:                                error("%kQr %s not aBC of %s",ppp,qs,string);
                   8180:                                continue;
                   8181:                        }
                   8182: 
                   8183:                        mex = 1;
                   8184:                        tcl = mec = this;
                   8185:                        c_body = 0; // this search must not be interpreted as a use
                   8186:                        Pname os = Cdcl;
                   8187:                        Cdcl = p;
                   8188:                        Pexpr ee = find_name(ms,0,1);
                   8189:                        Cdcl = os;
                   8190:                        c_body = 1;
                   8191: 
                   8192: // error('d', "ee: %k ", ee->base );
                   8193: 
                   8194: //                     while (ee->base == MDOT || ee->base == REF) 
                   8195:                         while (ee && (ee->base == MDOT || ee->base == REF))
                   8196:                                ee = ee->mem;
                   8197:                        Pname mx = Pname(ee);
                   8198: 
                   8199: // error('d', "ee: %k mx: %n", ee->base, mx );
                   8200: 
                   8201:                        if (mx == 0) {
                   8202:                                error("C %s does not have aM %s",qs,ms);
                   8203:                                continue;
                   8204:                        }
                   8205: 
                   8206:                        if (mx->tp->base == OVERLOAD) {
                   8207:                                error('s',"%k specification of overloaded%n",ppp,mx);
                   8208:                                continue;
                   8209:                        }
                   8210: 
                   8211:                        TOK pp = mx->n_scope?PUBLIC:mx->n_protect?PROTECTED:PRIVATE;
                   8212:                        
                   8213: // error('d',"mx %n pp %k ppp %k",mx,pp,ppp);
                   8214:                        if (ppp != pp) {
                   8215:                                error(&p->where,"%kM%n specified%k",pp,mx,ppp);
                   8216:                                continue;
                   8217:                        }       
                   8218:                        
                   8219:                
                   8220:                        p->n_qualifier = mx;
                   8221:                        Pname m = memtbl->insert(p,0);
                   8222:                        m->base = PUBLIC;
                   8223:                        if (Nold) error("twoDs ofCM%n",p);
                   8224:                        continue;
                   8225:                }
                   8226:                }
                   8227: 
                   8228: // error('d',"mem%n tp %d %k scope %d",p,p->tp->base,p->tp->base,scope);
                   8229: 
                   8230:                if (scope==0) { 
                   8231:                        if (p->n_sto != STATIC) st = 0;
                   8232:                }
                   8233:                else 
                   8234:                if ( p->tp->base == TYPE ) {
                   8235:                        Pname nn = p->tp->is_cl_obj();
                   8236:                        if (nn) { 
                   8237: // error( 'd', "nn: %n %k tp %t %k", nn, nn->base, nn->tp, nn->tp->base );
                   8238:                                 if ((Pclass(nn->tp)->csu == CLASS) && (strcmp(this->string,nn->string))) st = 0;
                   8239:                        }
                   8240:                }
                   8241: 
                   8242:                if (p->tp->base == FCT) {
                   8243:                        int ff = 0;
                   8244:                        Pfct f = Pfct(p->tp);
                   8245:                        Pblock b = f->body;
                   8246:                        f->body = 0;
                   8247:                        if (b) 
                   8248:                                f->f_inline = 1;
                   8249:                        /* restriction lifted: nested classes
                   8250:                        else
                   8251:                        if (nstd) 
                   8252:                                error((nstd==2)?0:'w',&p->where,"non-inlineMF%n in nestedC %s",p,string);
                   8253:                        */
                   8254:                        else
                   8255:                        if (lex_level) 
                   8256:                                error('w',&p->where,"non-inlineMF%n in localC %s",p,string);
                   8257: 
                   8258:                        switch (p->n_sto) {
                   8259:                        case FRIEND:
                   8260:                                ff = 1;
                   8261:                                break;
                   8262:                        case STATIC:    // accept static member functions
                   8263: //error('d',"inline %d",f->f_inline);
                   8264:                        //      if (f->f_inline==0)
                   8265:                                /* restriction lifted: nested classes
                   8266:                                if (nstd) 
                   8267:                                        error((nstd==2)?0:'w',"staticMF%n in nestedC %s",p,string);
                   8268:                                else
                   8269:                                */
                   8270:                                if (lex_level) 
                   8271:                                        error('w',"staticMF%n in localC %s",p,string);
                   8272:                                f->f_static = 1;
                   8273:                                p->n_sto = 0;
                   8274:                                break;
                   8275:                        case AUTO:
                   8276:                //      case STATIC:
                   8277:                        case REGISTER:
                   8278:                        case EXTERN:
                   8279:                                error(&p->where,"M%n cannot be%k",p,p->n_sto);
                   8280:                                p->n_sto = 0;
                   8281:                        }
                   8282: 
                   8283:                        if (f->f_virtual) real_virts++;
                   8284: 
                   8285:                        Pname m = p->dcl(memtbl,scope);
                   8286:                        if (m == 0 || m->tp->base != FCT) continue;
                   8287:                         if (m->n_initializer) {
                   8288:                                 c_abstract = 1;
                   8289:                                 if (m->n_oper == DTOR)
                   8290:                                        error('w',"please provide an out-of-line definition: %n {}; which is needed by derived classes",m);
                   8291:                         }
                   8292:                        if (ff == 0) m->n_protect = protect;
                   8293:                        if (b) {
                   8294:                                if (m->tp->defined&DEFINED || Pfct(m->tp)->body )
                   8295:                                        error(&p->where,"two definitions of%n",m);
                   8296:                                else
                   8297:                                        Pfct(m->tp)->body = b;
                   8298:                        //      Pfct(m->tp)->f_inline = 1;
                   8299:                        }
                   8300:                        if (ff==0 && p->where.line!=m->where.line)
                   8301:                                error(&p->where,"%n cannot be redeclared inCD",p);
                   8302:                }
                   8303:                else {
                   8304:                        Eppp = scope?scope:protect?protect:0;
                   8305: 
                   8306:                        if (p->base == TNAME) {
                   8307:                                // typedef names are exported to
                   8308:                                // surrounding non-class scope
                   8309:                                // NOTE: name should actually be declared in
                   8310:                                //       the innermost block of the current
                   8311:                                //       function, but this info isn't available
                   8312:                                if ( cc->nof ) {
                   8313:                                        if (p->tp && 
                   8314:                                                Pbase(p->tp)->base != COBJ && 
                   8315:                                                Pbase(p->tp)->base != EOBJ) {
                   8316:                                                        Pname n = cc->ftbl->look(p->string,0);
                   8317:                                                        if (n && n->base != TNAME && 
                   8318:                                                                  n->lex_level &&
                   8319:                                                                n->tp != p->tp ) {
                   8320:                                                                        error('s',"transitional model of nestedTs within%n (%s asTdef and%t)",cc->nof,p->string,n->tp); 
                   8321:                                                                        error('i', "cannot recover from previous errors" );
                   8322:                                                        }
                   8323:                                        }
                   8324:                                        else p->dcl(cc->ftbl,scope);
                   8325:                                }
                   8326:                                else
                   8327:                                        p->dcl(gtbl,scope);
                   8328: 
                   8329:                                // typedefs need to be generated outside class
                   8330:                                 if ( p->tp && Pbase(p->tp)->base != COBJ ) {
                   8331:                                         Pname n = gtbl->look(p->string,0);
                   8332:                                        if ( n && lex_level == 0 && n->base != TNAME )
                   8333:                                                 error(&p->where,"%nredefined: identifier and typedef",p); 
                   8334:                                        p->dcl_print(0);
                   8335:                                 }
                   8336:                                 continue;
                   8337:                         };
                   8338: 
                   8339:                        if (p->n_initializer) {
                   8340:                                error(&p->where,"Ir forM%n",p);
                   8341:                                p->n_initializer = 0;
                   8342:                        }
                   8343: 
                   8344:                        if (p->tp->base==OVERLOAD) {
                   8345:                                for (Plist gl=Pgen(p->tp)->fct_list; gl; gl=gl->l) { 
                   8346:                                        Pname nn = gl->f;
                   8347:                                        Pfct ff = Pfct(nn->tp);
                   8348:                                        if ( ff->f_virtual ) real_virts++;
                   8349:                                }
                   8350:                        }
                   8351: 
                   8352: // error('d',"lex_level %d p %n lex %d nested_scope: %k",lex_level,p,p->lex_level, nested_scope);
                   8353: 
                   8354:                        TOK is_friend = p->n_sto;
                   8355:                        if ( lex_level && p->tp->base == VEC ) lcl_tbl = tbl;
                   8356:                        if ( protect && p->tp->base == COBJ && 
                   8357:                                Pclass(Pbase(p->tp)->b_name->tp)->csu == ANON ) 
                   8358:                                        p->n_protect = protect;
                   8359:                        Pname m = p->dcl(memtbl,scope);
                   8360:                        lcl_tbl = 0;
                   8361:                        Eppp = 0;
                   8362:                        if (m == 0) continue;
                   8363: 
                   8364:                        m->n_protect = protect;
                   8365: 
                   8366:                        if (m->n_stclass==STATIC) {
                   8367:                                if (in_union) error("staticM%n in union",m);
                   8368:                                if ( is_friend != FRIEND ) {
                   8369:                                        /* restriction lifted: nested classes
                   8370:                                        if (nstd)
                   8371:                                                error((nstd==2)?0:'w',"staticM%n in nestedC %s",m,string);
                   8372:                                        else
                   8373:                                        */
                   8374:                                        if (lex_level)
                   8375:                                                error(strict_opt?0:'w',"staticM%n in localC %s (anachronism)",m,string);
                   8376:                                }
                   8377:                        //      Ptype t = m->tp;
                   8378:                        //      Pname cn = t->is_cl_obj();
                   8379:                        //      if ((cn && Pclass(cn->tp)->has_ctor())
                   8380:                        //      || t->is_ref()
                   8381:                        //      || (t->tconst() && vec_const == 0))
                   8382:                                m->n_sto = EXTERN;
                   8383:                                if (tbl == gtbl) stat_mem_list = new name_list(m,stat_mem_list);
                   8384:                                if (m->n_initializer) error('s',"staticM%nWIr",m);
                   8385:                        }
                   8386: 
                   8387:                        if (in_union) {
                   8388:                                if (usz < byte_offset) usz = byte_offset;
                   8389:                                byte_offset = 0;
                   8390:                                if(in_union==ANON) m->n_offset+=byte_old;
                   8391:                        }
                   8392:                }
                   8393:        }
                   8394: 
                   8395:        /* restriction lifted: nested and local classes
                   8396:        if (real_virts) {
                   8397:                if (nstd)
                   8398:                        error((nstd==2)?0:'w',"nestedC%s contains%d virtualF",string,real_virts);
                   8399:                else
                   8400:                if (lex_level)
                   8401:                        error('w',"localC%s contains%d virtualF",string,real_virts);
                   8402:        }
                   8403:        */
                   8404: 
                   8405:        if (st && csu==CLASS) csu = STRUCT;     // nothing private => STRUCT
                   8406:        if (st==0 && csu==STRUCT) csu = CLASS;  // all is not public => CLASS
                   8407: 
                   8408:        if (in_union) byte_offset = usz;
                   8409: 
                   8410:        // now look look at the members
                   8411: 
                   8412:        Pname ct = has_ctor();
                   8413:        Pname dt = has_dtor();
                   8414: 
                   8415:        int i;
                   8416: 
                   8417:        int omex = mex; mex = 0;
                   8418:        Pname on = has_oper(NEW);
                   8419:        Pname od = has_oper(DELETE);
                   8420:        mex = omex;
                   8421: 
                   8422:        if (dt && ct==0 && Pfct(dt->tp)->f_virtual == 0 ) error('w',"%s has%n but noK",string,dt);
                   8423:        if (on && od==0) error('w',"%s has%n but no operator delete()",string,on);
                   8424:        if (od && on==0) error('w',"%s has%n but no operator new()",string,od);
                   8425: 
                   8426:        if (dt==0 && od && od && od->n_table==memtbl) make_dtor = 1;
                   8427: 
                   8428:        for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) {
                   8429:        /*
                   8430:                The members have been declared.
                   8431:                now look at each to see if it needs defining
                   8432:        */
                   8433:                Ptype t = m->tp;
                   8434: 
                   8435:                if (t == 0) continue;   // public declarations
                   8436: // error('d', "m %n %d", m, m->n_scope );
                   8437: 
                   8438:                switch (t->base) {
                   8439:                default:
                   8440:                        if (ct==0
                   8441:                        && m->n_stclass!=ENUM
                   8442:                        && m->n_stclass!=STATIC) {
                   8443:                                if (t->is_ref()) error("R%n inC %sWoutK",m,string);
                   8444:                                if (t->tconst()
                   8445:                                && vec_const==0
                   8446:                                && m->n_evaluated==0)
                   8447:                                        error("const%n inC %sWoutK",m,string);
                   8448:                        }
                   8449:                case VEC:
                   8450:                        break;
                   8451:                case FCT:
                   8452:                case OVERLOAD:
                   8453:                case CLASS:
                   8454:                case ENUM:
                   8455:                        continue;
                   8456:                }
                   8457: 
                   8458:                Pname cn = t->is_cl_obj();
                   8459:                if (cn == 0) cn = cl_obj_vec;
                   8460:                if (cn == 0) continue;
                   8461: 
                   8462:                Pclass cl = Pclass(cn->tp);
                   8463:                 c_xref |= cl->c_xref;
                   8464: //error('d',"m %n %t %d",m,cl,cl->c_xref);
                   8465:                if (cl->has_ctor()) {
                   8466:                        if (m->n_stclass == STATIC)
                   8467:                                ; // error('s',"staticM%n ofC%nWK",m,cn);
                   8468:                        else if (in_union) {
                   8469:                                if (strncmp("__C",string,3) == 0)
                   8470:                                    error("M %s ofC%nWK in union",m->string,cn); // tagless union
                   8471:                                else error("M%n ofC%nWK in union",m,cn);
                   8472:                        }
                   8473:                        else if (ct == 0) {
                   8474:                                // does mctor have a default constructor?
                   8475:                                if (make_ctor==0 && cl->has_ictor()==0)
                   8476:                                        error("%t needs aK; it has aMWK requiringAs",this);
                   8477:                                make_ctor = 1;
                   8478:                        }
                   8479:                }
                   8480: 
                   8481:                if (cl->has_dtor()) {
                   8482:                        if (m->n_stclass==STATIC)
                   8483:                                ; // error('s',"staticM%n ofC%nW destructor",m,cn);
                   8484:                        else if (in_union) {
                   8485:                                if (strncmp("__C",string,3) == 0) // tagless union
                   8486:                                    error("M %s ofC%nW destructor in union",m->string,cn);
                   8487:                                else error("M%n ofC%nW destructor in union",m,cn);
                   8488:                        }
                   8489:                        else if (dt==0)
                   8490:                                make_dtor = 1;
                   8491:                }
                   8492:        }
                   8493: 
                   8494:        if (has_dtor()==0 && make_dtor==0) {
                   8495:                // can dtor be inherited (from single base class)?
                   8496:                Pclass bcl = 0;
                   8497:                for (Pbcl b = baselist; b; b = b->next) {
                   8498:                        switch (b->base) {
                   8499:                        case NAME:
                   8500:                                if (bcl == 0) {
                   8501:                                        Pname d = b->bclass->has_dtor();
                   8502:                                        if (d==0) break;
                   8503:                                        if (strict_opt == 0) {
                   8504:                                                if (d->n_scope==PUBLIC
                   8505:                                                && Pfct(d->tp)->f_virtual==0) {
                   8506:                                                        bcl = b->bclass;
                   8507:                                                        break;
                   8508:                                                }
                   8509:                                        }
                   8510:                                }
                   8511:                                // two dtors or non-public dtors force creation
                   8512:                                 make_dtor = 1;
                   8513:                                 goto zbzb;
                   8514:                         case VIRTUAL:
                   8515:                                 if (b->bclass->has_dtor()) make_dtor = 1;
                   8516:                                 goto zbzb;
                   8517:                        }
                   8518:                }
                   8519:                if (bcl) c_dtor = bcl->has_dtor();
                   8520:        zbzb:;
                   8521:        }
                   8522: 
                   8523:        if (make_dtor && dt==0) {       // make x::~x() {}
                   8524: 
                   8525:                // must be done before vtbls are made in case dtor is virtual
                   8526: //error('d',"%t: make_dtor",this);
                   8527:                Pname n = new name(string);
                   8528:                Pfct f = new fct(defa_type,0,1);
                   8529:                f->f_inline = /*IDTOR; */ 1;
                   8530:                n->tp = f;
                   8531:                n->n_oper = DTOR;
                   8532:                dt = n->dcl(memtbl,PUBLIC);
                   8533:                delete n;
                   8534:                Pfct(dt->tp)->body  = /*0; */ new block(curloc,0,0);
                   8535:                dt = has_dtor();
                   8536:        }
                   8537: 
                   8538:        if (virt_count && find_vptr(this)==0) {
                   8539:                // we only need a vptr if this class has virtual
                   8540:                // functions and none of its first bases have vptrs
                   8541: //error('d',"%s virt_count %d",string,virt_count);
                   8542:                Pname vp = new name("__vptr");
                   8543:                vp->tp = Pvptr_type;
                   8544:                (void) vp->dcl(memtbl,0);
                   8545:                delete vp;
                   8546:                c_xref |= C_VPTR;
                   8547:        }
                   8548:        else {
                   8549: //error("byte_offset %d bit_offset %d bitsinbyte %d",byte_offset,bit_offset,BI_IN_BYTE);
                   8550: //error("   div %d mod %d",bit_offset/BI_IN_BYTE,bit_offset%BI_IN_BYTE);
                   8551:            // no more bit fields. absorb bit_offset
                   8552:            if (bit_offset) {
                   8553:                byte_offset += (bit_offset/BI_IN_BYTE + (bit_offset%BI_IN_BYTE?1:0));
                   8554:                bit_offset = 0;
                   8555:            }
                   8556:        }
                   8557: //error("byte_offset %d bit_offset %d",byte_offset,bit_offset);
                   8558: 
                   8559:        for (Pbcl b = baselist; b; b = b->next) { // allocate virtual base pointers
                   8560:                if (b->base != VIRTUAL) continue;
                   8561:                Pclass bcl = b->bclass;
                   8562: 
                   8563:                // search non-virtual bases for this virtual base
                   8564:                for (Pbcl bb = baselist; bb; bb = bb->next)
                   8565:                        if (bb->base == NAME) {
                   8566:                                for (Pbcl l = bb->bclass->baselist; l; l=l->next)
                   8567:                                        if (l->base==VIRTUAL && l->bclass==bcl) goto eee;
                   8568:                        }
                   8569:                {
                   8570:                if (obj_align<AL_WPTR) obj_align = AL_WPTR;
                   8571:                if (max_align<AL_WPTR) max_align = AL_WPTR;
                   8572:                int waste = byte_offset%AL_WPTR;
                   8573:                if (waste) byte_offset += AL_WPTR-waste;        // align
                   8574:                b->ptr_offset = byte_offset+1;                  // ensure != 0
                   8575:                byte_offset += sizeof(int*);
                   8576:                }
                   8577:        eee:;
                   8578:        }
                   8579: 
                   8580:        real_size = byte_offset;        // the rest may be optimized away
                   8581: 
                   8582:        for (b = baselist; b; b = b->next) {    // allocate virtual class objects
                   8583:                if (b->base != VIRTUAL) continue;
                   8584:                Pclass bcl = b->bclass;
                   8585: 
                   8586:                // if necessary
                   8587:                if (b->obj_offset = has_allocated_base(bcl)) continue;
                   8588: 
                   8589:                int ba = bcl->align();
                   8590:                if (obj_align<ba) obj_align = ba;
                   8591:                if (max_align<ba) max_align = ba;
                   8592:                int waste = byte_offset%ba;
                   8593:                if (waste) byte_offset += ba-waste;     // align
                   8594:                b->obj_offset = byte_offset;            // offset in this
                   8595:                b->allocated = 1;
                   8596: //error('d',"virtual %t in %t at %d",bcl,this,b->obj_offset);
                   8597:                byte_offset += bcl->tsizeof();
                   8598:        }
                   8599: 
                   8600:        // no more data members.
                   8601:        // pad object (so that copying into a base object
                   8602:        // doesn't destroy derevid class members):
                   8603:        if (byte_offset==0) {   // empty struct: waste a member
                   8604:                Pname c = new name (make_name('W'));
                   8605:                c->tp = char_type;
                   8606:                (void) c->dcl(memtbl,0);
                   8607:                real_size = byte_offset = 1;
                   8608:        }
                   8609:        if (byte_offset < SZ_STRUCT) byte_offset = SZ_STRUCT;
                   8610:        int waste = byte_offset%max_align;
                   8611: //error('d',"max_align %d waste %d byte_offset %d",max_align,waste,byte_offset);
                   8612:        if (waste) byte_offset += max_align-waste;
                   8613:        obj_size = byte_offset;
                   8614:        obj_align = max_align;
                   8615: 
                   8616:        // make vtbls
                   8617:        // this cannot be done until the bases
                   8618:        // have been allocated in this class
                   8619:        // so that the offsets (deltas) are known
                   8620:        if (all_virt(this,0,1,0)) {
                   8621:                if (has_ctor()==0) make_ctor = 1;
                   8622:        }
                   8623:        else if (has_vvtab)
                   8624:                error("virtualB: conflicting vtable initialization");
                   8625: 
                   8626: // error('d',"%t->classdef: virt_count: %d virt_merge: %d",this,virt_count,virt_merge);
                   8627: 
                   8628:        Pname hito = has_itor();
                   8629: 
                   8630:        if (hito) c_xref |= C_XREF;     // has user defined X(X&)
                   8631: //error('d',"%t hito %d ctor %d",this,hito,make_ctor);
                   8632:        if (hito==0 && c_xref&(C_VPTR|C_VBASE|C_XREF)) {
                   8633:                // X(X&) needed if bitwise copy is illegal
                   8634:                // or if any constructor is defined
                   8635:                
                   8636:                hito = make_itor(0);
                   8637:                        // if the base has B::B(void)
                   8638:                        // the derived should have D::D(void)
                   8639:                if (baselist) {
                   8640:                        int mc = 1;     // can make and ictor
                   8641:                        for (Pbcl b = baselist; b; b = b->next) {
                   8642:                                if (b->bclass->has_ctor()
                   8643:                                && b->bclass->has_ictor()==0)
                   8644:                                                mc = 0;
                   8645:                        }
                   8646:                        make_ctor = mc;
                   8647: /*
                   8648:                        int mc = 1;     // can make an ictor
                   8649:                        for (Pbcl b = baselist; b; b = b->next) {
                   8650:                                if (b->bclass->has_ctor()) {
                   8651:                                        Pname c = b->bclass->has_ictor();
                   8652:                                                // no copy constructor?
                   8653:                                                // non-public copy constructor?
                   8654:                                        if (c==0 || c->n_scope==0) mc = 0;
                   8655:                                }
                   8656:                        }
                   8657:                        make_ctor = mc;
                   8658: */
                   8659:                }
                   8660:                else
                   8661:                        make_ctor =  1;
                   8662:        }
                   8663: 
                   8664:        if (c_ctor==0 && make_ctor==0) {        // can ctor be inherited (from single base class)?
                   8665: /*
                   8666:                int bb = 0;
                   8667:                for (Pbcl b = baselist; b; b = b->next) {
                   8668:                        switch (b->base) {
                   8669:                        case NAME:
                   8670:                        {       Pname c = b->bclass->has_ctor();
                   8671:                        //      if (b->bclass->has_ctor() == 0) break;
                   8672:                                if (c == 0) break;
                   8673:                                if (c->n_scope==PUBLIC && bb++==0) break;
                   8674:                        }
                   8675:                                // no break: two bases: needs ctor
                   8676:                        case VIRTUAL:
                   8677:                                make_ctor = 1;  // virtual base: need ctor
                   8678:                                goto zaza;
                   8679:                        }
                   8680:                }
                   8681: */
                   8682:                Pname btor = 0;
                   8683:                Pclass bc = 0;
                   8684:                for (Pbcl b = baselist; b; b = b->next) {
                   8685:                        switch (b->base) {
                   8686:                        case NAME:
                   8687:                        {       Pname c = b->bclass->has_ctor();
                   8688:                                if (c == 0) break;
                   8689:                                if (c->n_scope==PUBLIC && b==baselist) {
                   8690:                                        bc = b->bclass;
                   8691:                                        btor = bc->has_ictor();
                   8692:                                        break;
                   8693:                                }
                   8694:                        }
                   8695:                                // no break: two bases: needs ctor
                   8696:                        case VIRTUAL:
                   8697:                                make_ctor = 1;  // virtual base: need ctor
                   8698:                                goto zaza;
                   8699:                        }
                   8700:                }
                   8701:        //      c_ctor = btor;
                   8702: //error('d',"btor %n",btor);
                   8703:                if (bc) {
                   8704:                        if (btor)
                   8705:                                make_ctor = 1;
                   8706:                        else
                   8707:                                error("K needed for %s, BC%t hasK",string,bc);
                   8708:                }
                   8709:        zaza:;
                   8710:        }
                   8711: 
                   8712:        if (make_ctor && ct==0) {       // make x::x() {}
                   8713: //error('d',"%t: make_ctor",this);
                   8714:                Pname n = new name(string);
                   8715:                Pfct f = new fct(defa_type,0,1);
                   8716:                f->f_inline = 1; // ICTOR; // ICTOR means ``define ctor() if used''
                   8717:                n->tp = f;
                   8718:                n->n_oper = TNAME;
                   8719:                ct = n->dcl(memtbl,PUBLIC);
                   8720:                delete n;
                   8721:                Pfct(ct->tp)->body = /* 0; */ new block(curloc,0,0);
                   8722:        }
                   8723: 
                   8724:        defined |= DEFINED;
                   8725: 
                   8726:        if (ansi_opt) {
                   8727:                char* s = csu==UNION || csu==ANON ? "union" : "struct";
                   8728:                fprintf(out_file,"%s %s;",s,string);
                   8729:        }
                   8730: //error('d',"defined %s",string);
                   8731: 
                   8732:        // fix argument lists for inlines
                   8733:        for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) {
                   8734:                Pfct f = Pfct(p->tp);
                   8735:                if (f==0) continue;     // public declarations
                   8736: 
                   8737:                switch (f->base) {
                   8738:                case FCT:
                   8739:                        /* prohibit something like the following:
                   8740:                                typedef int t1;
                   8741:                                class x {
                   8742:                                        typedef int t1;
                   8743:                                        t1 foo();
                   8744:                                };
                   8745:                        */
                   8746:                        if (f->returns->base == TYPE) {
                   8747:                                Pname nn = Pbase(f->returns)->b_name;
                   8748:                                while ( nn->tp->base == TYPE ) 
                   8749:                                        nn = Pbase(nn->tp)->b_name;
                   8750:                                if (nn->n_key == NESTED) {
                   8751:                                        Ptype tt;
                   8752:                                        if ( nn->tp->base != EOBJ && 
                   8753:                                                nn->tp->base != COBJ )
                   8754:                                                        tt = nn->tpdef;
                   8755:                                        else  tt = Pbase(nn->tp)->b_name->tp; 
                   8756:                                        if ( tt && tt->nested_sig )
                   8757:                                                error('w',"nested %s as returnT for non-inlineMF, use %t::%s %n{} in definition (anachronism)",nn->string,tt->in_class,nn->string,p);
                   8758:                                }
                   8759:                        }
                   8760: 
                   8761:                        if (hito && f->argtype) fix_args(f,this);
                   8762:                        if (p->n_oper == CTOR) f->s_returns = this_type;
                   8763:                        if (f->body) p->n_sto = STATIC;
                   8764:                        break;
                   8765:                case OVERLOAD:
                   8766:                {       Pgen g = Pgen(f);
                   8767:                        for (Plist gl=g->fct_list; gl; gl=gl->l) {
                   8768:                                Pname n = gl->f;
                   8769:                                Pfct f = Pfct(n->tp);
                   8770: 
                   8771:                                if (hito && f->argtype) fix_args(f,this);
                   8772:                                if (n->n_oper == CTOR) f->s_returns = this_type;
                   8773:                                if (f->body) n->n_sto = STATIC;
                   8774:                        }
                   8775:                }
                   8776:                }
                   8777:        }
                   8778: 
                   8779:        // define members defined inline
                   8780:        for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) {
                   8781:                Pfct f = Pfct(p->tp);
                   8782:                if (f==0) continue;     // public declarations
                   8783: 
                   8784:                switch (f->base) {
                   8785:                case FCT:
                   8786:                        if (f->body) {
                   8787:                                f->dcl(p);
                   8788:                                p->simpl();
                   8789:                        }
                   8790:                        break;
                   8791:                case OVERLOAD:
                   8792:                {       Pgen g = Pgen(f);
                   8793:                        for (Plist gl=g->fct_list; gl; gl=gl->l) {
                   8794:                                Pname n = gl->f;
                   8795:                                Pfct f = Pfct(n->tp);
                   8796: 
                   8797:                                if (f->body) {
                   8798:                                        f->dcl(n);
                   8799:                                        n->simpl();
                   8800:                                }
                   8801:                        }
                   8802:                }
                   8803:                }
                   8804:        }
                   8805: 
                   8806:        byte_offset = byte_old;
                   8807:        bit_offset = bit_old;
                   8808:        max_align = max_old;
                   8809: 
                   8810:        cc->unstack();  // friends are not in class scope
                   8811: 
                   8812:        // fix arguments lists for friends defined inline 
                   8813:        for (Plist fl=friend_list; fl; fl=fl->l) {
                   8814:                Pname p = fl->f;
                   8815:                Pfct f = Pfct(p->tp);
                   8816: 
                   8817:                switch (f->base) {
                   8818:                case FCT:
                   8819:                        if (hito && f->argtype) fix_args(f,this);
                   8820:                        if (f->body &&
                   8821:                           (f->defined&(DEFINED|SIMPLIFIED)) == 0) 
                   8822:                                p->n_sto = STATIC;
                   8823:                        else 
                   8824:                        if (p->n_scope == STATIC)
                   8825:                                error(strict_opt?0:'w',"static%n declared friend toC%t",p,this);
                   8826:                        break;
                   8827:                case OVERLOAD:
                   8828:                {       Pgen g = Pgen(f);
                   8829:                        for (Plist gl=g->fct_list; gl; gl=gl->l) {
                   8830:                                Pname n = gl->f;
                   8831:                                Pfct f = Pfct(n->tp);
                   8832: 
                   8833:                                if (hito && f->argtype) fix_args(f,this);
                   8834:                                if (f->body &&
                   8835:                                   (f->defined&(DEFINED|SIMPLIFIED)) == 0) 
                   8836:                                        n->n_sto = STATIC;
                   8837:                                else 
                   8838:                                if (p->n_scope == STATIC)
                   8839:                                        error(strict_opt?0:'w',"static%n declared friend toC%t",p,this);
                   8840:                        }
                   8841:                }
                   8842:                }
                   8843:        }
                   8844: 
                   8845:        // define friends defined inline and modify return types if necessary
                   8846:        for (fl=friend_list; fl; fl=fl->l) {
                   8847:                Pname p = fl->f;
                   8848:                Pfct f = Pfct(p->tp);
                   8849: 
                   8850:                switch (f->base) {
                   8851:                case FCT:
                   8852:                        if (f->body &&
                   8853:                           (f->defined&(DEFINED|SIMPLIFIED)) == 0) {
                   8854:                                f->dcl(p);
                   8855:                                p->simpl();
                   8856:                        }
                   8857:                        break;
                   8858:                case OVERLOAD:
                   8859:                {       Pgen g = Pgen(f);
                   8860:                        for (Plist gl=g->fct_list; gl; gl=gl->l) {
                   8861:                                Pname n = gl->f;
                   8862:                                Pfct f = Pfct(n->tp);
                   8863: 
                   8864:                                if (f->body &&
                   8865:                                   (f->defined&(DEFINED|SIMPLIFIED)) == 0) {
                   8866:                                        f->dcl(n);
                   8867:                                        n->simpl();
                   8868:                                }
                   8869:                        }
                   8870:                }
                   8871:                }
                   8872:        }
                   8873: 
                   8874:        if (tbl != gtbl) this->simpl();
                   8875: 
                   8876:         if ( statStat && strcmp(statStat->string,string)==0) {
                   8877: //error('d', "classdef::dcl: statstat: %n this %s", statStat, string);
                   8878:                 statStat->hide();
                   8879:                 statStat = 0;
                   8880:         }
                   8881: // error('d',"classdef::dcl defined: %d",defined);
                   8882:        // catch refs to this class in body of nested class function
                   8883:        // (i.e., ref to member of this class...)
                   8884:        if ( (defined&REF_SEEN) != 0 ) dcl_print(0);
                   8885: 
                   8886:      if ( debug_opt ) {
                   8887:        for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) {
                   8888:                Pfct f = Pfct(p->tp);
                   8889:                if (f==0) continue;     // public declarations
                   8890: 
                   8891:                switch (f->base) {
                   8892:                        case FCT:
                   8893:                                if (f->body) {
                   8894:                                        if ( c_body == 1 ) dcl_print(0);
                   8895:                                        p->dcl_print(0);
                   8896:                                }
                   8897:                                break;
                   8898:                        case OVERLOAD: 
                   8899:                        {       
                   8900:                                Pgen g = Pgen(f);
                   8901:                                for (Plist gl=g->fct_list; gl; gl=gl->l) {
                   8902:                                        Pname n = gl->f;
                   8903:                                        Pfct f = Pfct(n->tp);
                   8904:                                        if (f->body) {
                   8905:                                                if ( c_body == 1 ) dcl_print(0);
                   8906:                                                p->dcl_print(0);
                   8907:                                        }
                   8908:                                }
                   8909:                        }
                   8910:                }
                   8911:        }
                   8912: 
                   8913:        for (fl=friend_list; fl; fl=fl->l) {
                   8914:                Pname p = fl->f;
                   8915:                Pfct f = Pfct(p->tp);
                   8916: 
                   8917:                switch (f->base) {
                   8918:                        case FCT:
                   8919:                                if (f->body &&
                   8920:                                   (f->defined&(DEFINED|SIMPLIFIED)) == 0) 
                   8921:                                        p->dcl_print(0);
                   8922:                                break;
                   8923:                        case OVERLOAD:
                   8924:                        {       
                   8925:                                Pgen g = Pgen(f);
                   8926:                                for (Plist gl=g->fct_list; gl; gl=gl->l) {
                   8927:                                        Pname n = gl->f;
                   8928:                                        Pfct f = Pfct(n->tp);
                   8929: 
                   8930:                                        if (f->body &&
                   8931:                                           (f->defined&(DEFINED|SIMPLIFIED)) == 0) 
                   8932:                                                p->dcl_print(0);
                   8933:                                }
                   8934:                        }
                   8935:                }
                   8936:        }
                   8937:     } // end, if (debug_opt)
                   8938: }
                   8939: 
                   8940: void enumdef::dcl(Pname n, Ptable tbl)
                   8941: {
                   8942: //     if (this == 0) error('i',"0->enumdef::dcl(%p)",tbl);
                   8943:        Pname px;
                   8944:        Pname p = mem;
                   8945:        DB( if(Ddebug>=1) error('d',&n->where,"enumdef(%n,%d)",n,tbl); );
                   8946:        Pbase b = new basetype(EOBJ,n);
                   8947:        b->b_const = 1;
                   8948: 
                   8949: #define FIRST_ENUM 0
                   8950:        int enum_count = FIRST_ENUM;
                   8951:        no_of_enumerators = mem->no_of_names();
                   8952:        int largest = 0;
                   8953: 
                   8954:        if (p == 0) mem = new name(make_name('e'));
                   8955: 
                   8956:        for (; p; p=px) {
                   8957:                px = p->n_list;
                   8958: // error( 'd', "p %n", p );
                   8959:                if (p->n_initializer) {
                   8960:                        Pexpr i = p->n_initializer->typ(tbl);
                   8961:                        Neval = 0;
                   8962:                        long ii = i->eval();
                   8963:                        if (largest_int<ii) error("long enumerator");
                   8964:                        enum_count = int(ii);
                   8965:                        if (Neval) error("%s",Neval);
                   8966:                        DEL(i);
                   8967:                        p->n_initializer = 0;
                   8968:                }
                   8969:                p->n_evaluated = 1;
                   8970:                largest |= enum_count;
                   8971:                p->n_val = enum_count++;
                   8972:                p->tp = b;
                   8973: 
                   8974:                Pname nn = tbl->insert(p,0);
                   8975:                if (Nold) {
                   8976:                        if (nn->n_stclass == ENUM) {
                   8977:                        //      error( (p->n_val!=nn->n_val)?0:'w',"enumerator%n declared twice",nn);
                   8978:                //      if (p->n_val!=nn->n_val)
                   8979:                        error("enumerator%n declared twice",nn);
                   8980:                        
                   8981:                        }
                   8982:                        else
                   8983:                                error("incompatibleDs of%n",nn);
                   8984:                }
                   8985:                else {
                   8986:                        nn->n_stclass = ENUM; // no store will be allocated
                   8987:                        if (Eppp == PROTECTED)
                   8988:                                nn->n_protect = PROTECTED;
                   8989:                        else if (Eppp == PUBLIC)
                   8990:                                nn->n_scope = PUBLIC;
                   8991:                }
                   8992:                p->string = nn->string;
                   8993: //             delete p;
                   8994:        }
                   8995: 
                   8996: //     mem = 0;
                   8997: 
                   8998: //     chose a shorter representation for the enum?
                   8999: //     if (largest&0133 == largest)
                   9000: //             e_type = char_type;
                   9001: //     else if largest&077777 == largest)
                   9002: //             e_type = short_type;
                   9003: //     else
                   9004:                e_type = int_type;
                   9005: 
                   9006:        defined |= DEFINED;
                   9007: }
                   9008: 
                   9009: 
                   9010: 0707071010112044131004440001630000160000010175600466055377200000600000013077del.c/*ident      "@(#)ctrans:src/del.c   1.3" */
                   9011: /************************************************************
                   9012: 
                   9013:        C++ source for cfront, the C++ compiler front-end
                   9014:        written in the computer science research center of Bell Labs
                   9015: 
                   9016:        Copyright (c) 1984 AT&T, Inc. All rights Reserved
                   9017:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   9018: 
                   9019: del.c:
                   9020: 
                   9021:        walk the trees to reclaim storage
                   9022: 
                   9023: **************************************************************/
                   9024: 
                   9025: #include "cfront.h"
                   9026: 
                   9027: void name::del()
                   9028: {
                   9029:        DB( if(Adebug>=1) {
                   9030:                fprintf(stderr,"\n*** '%s'->del()",string?string:"???");
                   9031:                display_type(tp); putc(' ',stderr);
                   9032:                where.put(stderr); putc('\n',stderr);
                   9033:            }
                   9034:            if ( base!=NAME && base!=TNAME ) error('i',"name::del() of%k -- id==%ld",base,node::id);
                   9035:        );
                   9036:        Pexpr i = n_initializer;
                   9037: 
                   9038: // error('d', "\nname::del: %d %s", this, string?string:"no name" );
                   9039: //     NFn++;
                   9040:        DEL(tp);
                   9041:        if(i && i!=(Pexpr)1) DEL(i);
                   9042:        delete this;
                   9043: }
                   9044: 
                   9045: void type::del()
                   9046: {
                   9047:        DB( if(Adebug>=1) {
                   9048:                fprintf(stderr,"\n*** '");
                   9049:                display_type(this);
                   9050:                fprintf(stderr," '->del()\n");
                   9051:            }
                   9052:        );
                   9053: //fprintf(stderr,"DEL(type=%d %d)\n",this,base);
                   9054:        permanent = 3;  /* do not delete twice */
                   9055:        switch (base) {
                   9056:        case TNAME:
                   9057:        case NAME:
                   9058:                error('i',"%d->T::del():N %s %d",this,Pname(this)->string,base);
                   9059:        case FCT:
                   9060:        {       Pfct f = (Pfct) this;
                   9061:                DEL(f->returns);
                   9062:                delete f;
                   9063:                break;
                   9064:        }
                   9065:        case VEC:
                   9066:        {       Pvec v = (Pvec) this;
                   9067:                DEL(v->dim);
                   9068:                DEL(v->typ);
                   9069:                delete v;
                   9070:                break;
                   9071:        }
                   9072:        case PTR:
                   9073:        case RPTR:
                   9074:        {       Pptr p = (Pptr) this;
                   9075:                DEL(p->typ);
                   9076:                delete p;
                   9077:                break;
                   9078:        }
                   9079:        }
                   9080: }
                   9081: 
                   9082: void expr::del()
                   9083: {
                   9084:        DB( if(Adebug>=1) {
                   9085:                fprintf(stderr,"\n*** expr::del():  ");
                   9086:                display_expr(this,0,1);
                   9087:                if(Adebug>=2) display_expr(this);
                   9088:        });
                   9089: //fprintf(stderr,"DEL(expr=%d: %d %d %d)\n",this,base,e1,e2); fflush(stderr);
                   9090:        permanent = 3;
                   9091:        switch (base) {
                   9092:        case IVAL:
                   9093:                if (this == one) return;
                   9094:        //case FVAL:
                   9095:        case THIS:
                   9096:        case ICON:
                   9097:        case FCON:
                   9098:        case CCON:
                   9099:        case STRING:
                   9100:        case TEXT:
                   9101:                goto dd;
                   9102:        case DUMMY:
                   9103:        case ZERO:
                   9104:        case NAME:
                   9105:                return;
                   9106:        case CAST:
                   9107:        case SIZEOF:
                   9108:        case NEW:
                   9109:        case GNEW:
                   9110:        case VALUE:
                   9111:                DEL(tp2);
                   9112:                break;
                   9113:        case REF:
                   9114:        case DOT:
                   9115:                DEL(e1);
                   9116:                if (e2) DEL(e2);
                   9117:        case MDOT:
                   9118:                if (mem && mem->base!=NAME) DEL(mem);
                   9119:                if ( i1 == 5 ) delete string4;
                   9120:                goto dd;
                   9121:        case QUEST:
                   9122:                DEL(cond);
                   9123:                break;
                   9124:        case ICALL:
                   9125:                delete il->i_args;
                   9126:                delete il;
                   9127:                goto dd;
                   9128:        case ELIST: { // limit recursion
                   9129:                Pexpr tp = e2;
                   9130:                while ( tp && tp->e2 && tp->e2->base == ELIST ) {
                   9131:                        Pexpr x = tp;
                   9132:                        if ( x->permanent ) break;
                   9133:                        x->permanent = 3;
                   9134:                        tp = tp->e2;
                   9135:                        if ( x->e1 ) DEL(x->e1);
                   9136:                        delete x;
                   9137:                }
                   9138:                e2 = tp;
                   9139:                break;
                   9140:                }
                   9141:        }
                   9142: 
                   9143:        DEL(e1);
                   9144:        DEL(e2);
                   9145: dd:
                   9146:        delete this;
                   9147: }
                   9148: 
                   9149: void stmt::del()
                   9150: {
                   9151:        DB( if(Adebug>=1) {
                   9152:                fprintf(stderr,"\n*** stmt::del():  ");
                   9153:                display_stmt(this,0,1);
                   9154:                if(Adebug>=2) display_stmt(this);
                   9155:        });
                   9156: //fprintf(stderr,"DEL(stmt %d %s)\n",this,keys[base]); fflush(stderr);
                   9157:        permanent = 3;
                   9158:        switch (base) {
                   9159:        case SM:
                   9160:        case WHILE:
                   9161:        case DO:
                   9162:        case RETURN:
                   9163:        case CASE:
                   9164:        case SWITCH:
                   9165:                DEL(e);
                   9166:                break;
                   9167:        case PAIR:
                   9168:                DEL(s2);
                   9169:                break;
                   9170:        case BLOCK:
                   9171:                DEL(d);
                   9172:                DEL(s);
                   9173:                if (own_tbl) DEL(memtbl);
                   9174:                DEL(s_list);
                   9175:                goto dd;
                   9176:        case FOR:
                   9177:                DEL(e);
                   9178:                DEL(e2);
                   9179:                DEL(for_init);
                   9180:                break;
                   9181:        case IF:
                   9182:                DEL(e);
                   9183:                DEL(else_stmt);
                   9184:                break;
                   9185:        }
                   9186: 
                   9187:        DEL(s);
                   9188:        DEL(s_list);
                   9189: dd:
                   9190:        delete this;
                   9191: }
                   9192: 
                   9193: void table::del()
                   9194: {
                   9195: // error('d',"\n*** %d::del() -- '%s'\n",this, t_name?t_name->string:"???");
                   9196: 
                   9197:        for (register i=1; i<free_slot; i++) {
                   9198:                Pname n = entries[i];
                   9199:                if (n==0) error('i',"table.del(0)");
                   9200:                DB( if(Adebug>=2) { fprintf(stderr,"  name: '%s'",n->string);
                   9201:                        display_type(n->tp); putc('\n',stderr);
                   9202:                });
                   9203: 
                   9204: // error( 'd',"\ntable::del: %s n_scope: %d, n_stclass: %d", n->string, n->n_scope, n->n_stclass );
                   9205: 
                   9206:                if (n->n_stclass == STATIC) continue;
                   9207:                switch (n->n_scope) {
                   9208:                case ARG:
                   9209:                case ARGT:
                   9210:                        break;
                   9211:                default:
                   9212:                {       char* s = n->string;
                   9213:                        if (s && (s[0]!='_' || s[1]!='_' || s[2]!='X')) delete s;
                   9214:                        /* delete n; */
                   9215:                        n->del();
                   9216:                }
                   9217:                }
                   9218:        }
                   9219:        //delete entries;
                   9220:        //delete hashtbl;
                   9221:        delete this;
                   9222: }
                   9223: 
                   9224: // local class
                   9225: void delete_local() 
                   9226: {
                   9227:        DB( if(Adebug>=1) {
                   9228:                fprintf( stderr, "delete_local: vlist: %d", vlist );
                   9229:        });
                   9230: // error( 'd', "delete_local: vlist: %d", vlist );
                   9231:     do {
                   9232:        for (vl* v = vlist; v; v = v->next) v->cl->really_print(v->vt);
                   9233:        vlist = 0;
                   9234: 
                   9235:        for (Plist l=isf_list; l; l=l->l) {
                   9236:                Pname n = l->f;
                   9237:                Pfct f = Pfct(n->tp);
                   9238: // error('d',"isf %n f %d",n,f);
                   9239:                if ( f == 0 ) { error('d', "delete_local: f == 0" );break;} 
                   9240:                if (f->base == OVERLOAD) {
                   9241:                        n = Pgen(f)->fct_list->f;       // first fct
                   9242:                        f = Pfct(n->tp);
                   9243:                }
                   9244: 
                   9245:                if (debug_opt==0 && n->n_addr_taken) {
                   9246:                        f->f_inline = 0;
                   9247:                        if (n->n_dcl_printed<2) {
                   9248:                                if (warning_opt)
                   9249:                                        error('w',"out-of-line copy of %n created",n);
                   9250:                                n->dcl_print(0);
                   9251:                        }
                   9252:                }
                   9253:        }
                   9254:        //isf_list = 0;
                   9255:     } while (vlist);
                   9256: 
                   9257:     for ( Plist l = local_class; l; l = l->l )
                   9258:     {
                   9259:           Pname n = l->f;
                   9260: // error( 'd' , "delete_local() %d %n %t", n, n, n->tp );
                   9261:     Pname nn = Pbase(n->tp)->b_name;
                   9262:     Pclass cl = Pclass(nn->tp);
                   9263:        for (Pname px, p=cl->mem_list; p; p=px) {
                   9264:                px = p->n_list;
                   9265:                if (p->tp)
                   9266:                switch (p->tp->base) {
                   9267:                        case FCT:
                   9268:                        {       Pfct f = (Pfct)p->tp;
                   9269:                                if (f->body) {
                   9270:                                    if (f->f_inline==0
                   9271:                                    && f->f_imeasure==0) {
                   9272: 
                   9273:                                        if (ansi_opt && f->f_this) {
                   9274:                                                f->f_this->n_table = 0;
                   9275:                                                for (Pname n=f->f_this->n_list; n; n=n->n_list) 
                   9276:                                                        n->n_table = 0; 
                   9277:                                        }
                   9278: 
                   9279:                                        DEL(f->body);
                   9280:                                        f->body = 0;
                   9281:                                        }
                   9282:                                }
                   9283:                        }
                   9284:                        case COBJ:
                   9285:                        case EOBJ:
                   9286:                                DEL(p);
                   9287:                                break;
                   9288:                        case CLASS:
                   9289:                        case ENUM:
                   9290:                                break;
                   9291:                        default:
                   9292:                                delete p;
                   9293:                        } // end switch
                   9294:                else delete p;
                   9295:        } // end for mem
                   9296:         DEL(cl->memtbl);
                   9297:        cl->mem_list = 0;
                   9298:        cl->permanent = 3;
                   9299:         nn->permanent = 0;
                   9300:        DEL(nn);
                   9301:        n->permanent = 0;
                   9302:        extern void table_delete( char*, TOK, int );
                   9303:        table_delete( n->string, LOCAL, n->lex_level );
                   9304:        DEL(n);
                   9305:     }
                   9306: }
                   9307: 0707071010112045761004440001630000160000010210600466055414200001200000013534discrim.c/* ident "@(#)ctrans:src/discrim.c       1.2" */
                   9308: /************ add copyright **********************
                   9309:  * union discriminator functions for nodes in cfront. 
                   9310:  * all return 0 for none,
                   9311:  *   -1 for bad union index, -2 for inconsistent
                   9312:  *  or otherwise messed up nodes 
                   9313:  */
                   9314: #include "cfront.h"
                   9315: #define DEFINE_TOKEN_CLASS_TABLE
                   9316: #include "node_classes.h"
                   9317: 
                   9318: int basetype::discriminator(int which_union)
                   9319: {
                   9320:     switch(which_union)
                   9321:     {
                   9322:       case 0:
                   9323:        switch(base) {
                   9324:          case FIELD: return 1;
                   9325:          case FCT: return 2;
                   9326:          default: return discrim_none_valid;
                   9327:        }
                   9328:       default:
                   9329:        return discrim_bad_index;
                   9330:     }
                   9331: }
                   9332: 
                   9333: int fct::discriminator(int)
                   9334: {
                   9335:     return discrim_bad_index;
                   9336: }
                   9337: 
                   9338: int expr::discriminator(int which_union)
                   9339: {
                   9340:     switch(which_union) {
                   9341:       case 0:
                   9342:        return 1;               /* tp, never syn_class */
                   9343:       case 1:                  /* e1, i1, string */
                   9344:        switch(base) {
                   9345:          case DEREF:
                   9346:          case ICALL:
                   9347:          case REF:
                   9348:          case DOT:
                   9349:          case VALUE:
                   9350:          case SIZEOF:
                   9351:          case NEW:
                   9352:          case GNEW:
                   9353:          case DELETE:
                   9354:          case CAST:
                   9355:          case CALL:
                   9356:          case G_CALL:
                   9357:          case ASSIGN:
                   9358:          case EQ:
                   9359:          case NE:
                   9360:          case GT:
                   9361:          case GE:
                   9362:          case LE:
                   9363:          case LT:
                   9364:          case ELIST:
                   9365:          case ILIST:
                   9366:          case QUEST:
                   9367:          case CM:
                   9368:          case G_CM:
                   9369:          case PLUS:
                   9370:          case MINUS:
                   9371:          case MUL:
                   9372:          case DIV:
                   9373:          case MOD:
                   9374:          case LS:
                   9375:          case RS:
                   9376:          case AND:
                   9377:          case OR:
                   9378:          case ER:
                   9379:          case ANDAND:
                   9380:          case OROR:
                   9381:          case ASOR: 
                   9382:          case ASER: 
                   9383:          case ASAND:
                   9384:          case ASPLUS:
                   9385:          case ASMINUS:
                   9386:          case ASMUL:
                   9387:          case ASMOD:
                   9388:          case ASDIV:
                   9389:          case ASLS:
                   9390:          case ASRS:
                   9391:          case DECR:
                   9392:          case INCR:
                   9393:            return 1;
                   9394:          case MDOT:
                   9395:          case IVAL:
                   9396:            return 2;
                   9397:          case TNAME:
                   9398:          case NAME:
                   9399:          case ICON:
                   9400:          case FCON:
                   9401:          case CCON:
                   9402:          case ID:
                   9403:          case STRING:
                   9404:          case TEXT:
                   9405:            return 3;
                   9406:          default: return discrim_none_valid;
                   9407:        }
                   9408:       case 2:                  /* e2, i2, string2, n_initializer */
                   9409:        /* i2 is a complete mystery. It is set to 1,
                   9410:           and never referenced. But I'm not sure that
                   9411:           someone somewhere doesn't test one of the other
                   9412:           union elements for equal to 1, so therefore this test. */
                   9413:        if(i2 == 1)return 2;
                   9414:        switch(base) {
                   9415:          case DELETE:
                   9416:          case VALUE:
                   9417:          case ICALL:
                   9418:          case CALL:
                   9419:          case G_CALL:
                   9420:          case ASSIGN:
                   9421:          case EQ:
                   9422:          case NE:
                   9423:          case GT:
                   9424:          case GE:
                   9425:          case LE:
                   9426:          case LT:
                   9427:          case DEREF:
                   9428:          case ELIST:
                   9429:          case QUEST:
                   9430:          case CM:
                   9431:          case G_CM:
                   9432:          case UMINUS:
                   9433:          case NOT:
                   9434:          case COMPL:
                   9435:          case ADDROF:
                   9436:          case G_ADDROF:
                   9437:          case PLUS:
                   9438:          case MINUS:
                   9439:          case MUL:
                   9440:          case DIV:
                   9441:          case MOD:
                   9442:          case LS:
                   9443:          case RS:
                   9444:          case AND:
                   9445:          case OR:
                   9446:          case ER:
                   9447:          case ANDAND:
                   9448:          case OROR:
                   9449:          case ASOR: 
                   9450:          case ASER: 
                   9451:          case ASAND:
                   9452:          case ASPLUS:
                   9453:          case ASMINUS:
                   9454:          case ASMUL:
                   9455:          case ASMOD:
                   9456:          case ASDIV:
                   9457:          case ASLS:
                   9458:          case ASRS:
                   9459:          case DECR:
                   9460:          case INCR:
                   9461:          case NEW:     /*- the placement expression list hangs off e2 -*/
                   9462:            return 1;
                   9463:          case TEXT:
                   9464:            return 3;
                   9465:          case NAME:
                   9466:          case TNAME:
                   9467:            /* The n_initializer field is used for TNAMEs when describing base */
                   9468:            /* class initializations. The TNAME refers to the base class, and */
                   9469:            /* the actuals arguments are hung off the n_initializer list */
                   9470:            return 4;
                   9471:          default: return discrim_none_valid;
                   9472:        }
                   9473:       case 3:                  /* tp2, fct_name, cond, mem, as_type, n_table, il, query_this */
                   9474:        switch(base) {
                   9475:          case VALUE:
                   9476:          case SIZEOF:
                   9477:          case NEW:
                   9478:          case GNEW:    
                   9479:          case CAST:
                   9480:            return 1;
                   9481:          case CALL:
                   9482:          case G_CALL:
                   9483:            return 2;
                   9484:          case QUEST:
                   9485:            return 3;
                   9486:          case REF:
                   9487:          case DOT:
                   9488:          case MDOT: 
                   9489:            return 4;
                   9490:          case ASOR: 
                   9491:          case ASER: 
                   9492:          case ASAND:
                   9493:          case ASPLUS:
                   9494:          case ASMINUS:
                   9495:          case ASMUL:
                   9496:          case ASMOD:
                   9497:          case ASDIV:
                   9498:          case ASLS:
                   9499:          case ASRS:
                   9500:          case DECR:
                   9501:          case INCR:
                   9502:          case ASSIGN:
                   9503:            return 5;
                   9504: 
                   9505:          case NAME:
                   9506:          case TNAME:
                   9507: if (Pname(this)->n_oper==TYPE &&
                   9508: (strcmp(Pname(this)->string, "_type")==0)) {
                   9509: // error('d',"string %s n_oper: %k", string, Pname(this)->n_oper);
                   9510: return 3;
                   9511: }
                   9512:            return 6;
                   9513: 
                   9514:          case ICALL:
                   9515:          case ANAME: 
                   9516:            return 7;
                   9517: 
                   9518:          default: return discrim_none_valid;
                   9519:        }
                   9520:            
                   9521:       default:
                   9522:        return discrim_bad_index;
                   9523:     }
                   9524: }
                   9525: 
                   9526: int name::discriminator (int which_union)
                   9527: {
                   9528:     switch(which_union) {
                   9529:       case 0:                  /* n_qualifier, n_realscope */
                   9530:        if(base == LABEL) return 2;
                   9531:        else return 1;
                   9532:       default:
                   9533:        return discrim_bad_index;
                   9534:     }
                   9535: }
                   9536: 
                   9537: int stmt::discriminator (int which_union)
                   9538: {
                   9539:     switch(which_union) {
                   9540:       case 0:                  /* d, e2, has_default, case_value, ret_tp */
                   9541:        switch(base) {
                   9542:          case BLOCK:
                   9543:          case GOTO:
                   9544:          case LABEL:
                   9545:          case DCL:
                   9546:            return 1;
                   9547:          case FOR:
                   9548:            return 2;
                   9549:          case SWITCH:
                   9550:            return 3;
                   9551:          case PAIR:
                   9552:          case RETURN:
                   9553:            return 4;
                   9554:          default: return discrim_none_valid;
                   9555:        }
                   9556:       case 1:                  /* e, own_tbl, s2 */
                   9557:        switch(base) {
                   9558:          case FOR:
                   9559:          case IF:
                   9560:          case WHILE:
                   9561:          case DO:
                   9562:          case RETURN:
                   9563:          case SWITCH:
                   9564:          case SM:
                   9565:          case SM_PARAM:
                   9566:          case CASE:
                   9567:            return 1;
                   9568:          case BLOCK:
                   9569:            return 2;
                   9570:          case PAIR:
                   9571:            return 3;
                   9572:          default:
                   9573:            return discrim_none_valid;
                   9574:        }
                   9575:       case 2:                  /* for_init, else_stmt, case_list */
                   9576:        switch(base) {
                   9577:          case FOR:
                   9578:            return 1;
                   9579:          case IF:
                   9580:            return 2;
                   9581:          case SWITCH:
                   9582:          case CASE:
                   9583:            return 3;
                   9584:          default:
                   9585:            return discrim_none_valid;
                   9586:        }
                   9587:       default:
                   9588:        return discrim_bad_index;
                   9589:     }
                   9590: }
                   9591: 
                   9592: static node_class token_to_class_map[DUMMY_LAST_NODE];
                   9593: static char map_initialized;
                   9594: 
                   9595: node_class classify_node (Pnode node, int& error)
                   9596: {
                   9597:     int ncx;
                   9598:     node_class nclass;
                   9599: 
                   9600:     error = 0;
                   9601: 
                   9602:     if (! map_initialized) {
                   9603:        map_initialized = 1 ;
                   9604:        for(ncx = 0; ncx < sizeof (token_classes) / sizeof (token_class);
                   9605:            ncx ++)
                   9606:            token_to_class_map[token_classes[ncx].token]
                   9607:                = token_classes[ncx].nclass;
                   9608:     }
                   9609: 
                   9610:     if (!((node->base > 0) && (node->base < DUMMY_LAST_NODE))) {
                   9611:        error = 1;
                   9612:        return nc_unused;
                   9613:     }
                   9614: 
                   9615:     nclass = token_to_class_map[node->base];
                   9616: 
                   9617:     switch(nclass) {
                   9618:       case nc_fct:
                   9619:       case nc_name:
                   9620:        if(node->baseclass) nclass = nc_baseclass;
                   9621:     }
                   9622: 
                   9623:     return nclass;
                   9624: }
                   9625: 
                   9626: node_class classify_node (Pnode node)
                   9627: {
                   9628:     int err;
                   9629:     node_class nclass = classify_node (node, err);
                   9630:     if(err) error ('i', "failed to classify node.");
                   9631:     return nclass;
                   9632: }
                   9633: 0707071010112045771004440001630000160000010210700466055414600001200000041601doprint.c/* ident "@(#)ctrans:src/doprint.c       1.2" */
                   9634: /*
                   9635:  ************* obviously, have to do something here!!!
                   9636: 
                   9637:  * Copyright (c) 1988 Regents of the University of California.
                   9638:  * All rights reserved.
                   9639:  *
                   9640:  * Redistribution and use in source and binary forms are permitted
                   9641:  * provided that the above copyright notice and this paragraph are
                   9642:  * duplicated in all such forms and that any documentation,
                   9643:  * advertising materials, and other materials related to such
                   9644:  * distribution and use acknowledge that the software was developed
                   9645:  * by the University of California, Berkeley.  The name of the
                   9646:  * University may not be used to endorse or promote products derived
                   9647:  * from this software without specific prior written permission.
                   9648:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                   9649:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                   9650:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                   9651:  */
                   9652: 
                   9653: /*
                   9654:     $Header: /usr2/odi/lib.src/RCS/doprint.C,v 1.3 89/09/19 12:00:34 benson Exp $
                   9655: 
                   9656:     Copyright (c) 1989 by Object Design, Inc., Burlington, Mass.
                   9657:     All rights reserved.
                   9658: 
                   9659: */
                   9660: 
                   9661: #include <sys/types.h>
                   9662: #include <stdarg.h>
                   9663: #include <ctype.h>
                   9664: #include <iostream.h>
                   9665: #include <strstream.h>
                   9666: #include <memory.h>
                   9667: #include <math.h>
                   9668: #include <string.h>
                   9669: #include "print_self.h"
                   9670: 
                   9671: /* 11-bit exponent (VAX G floating point) is 308 decimal digits */
                   9672: #define        MAXEXP          308
                   9673: /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
                   9674: #define        MAXFRACT        39
                   9675: 
                   9676: #define        DEFPREC         6
                   9677: 
                   9678: #define        BUF             (MAXEXP+MAXFRACT+1)     /* + decimal point */
                   9679: 
                   9680: #define        PUTC(ch)        (void) fp.put(ch)
                   9681: 
                   9682: #define        ARG() \
                   9683:        _ulong = flags&LONGINT ? va_arg(argp, long) : \
                   9684:            flags&SHORTINT ? va_arg(argp, short) : va_arg(argp, int);
                   9685: 
                   9686: #define        todigit(c)      ((c) - '0')
                   9687: #define        tochar(n)       ((n) + '0')
                   9688: 
                   9689: #define        LONGINT         0x01            /* long integer */
                   9690: #define        LONGDBL         0x02            /* long double; unimplemented */
                   9691: #define        SHORTINT        0x04            /* short integer */
                   9692: #define        ALT             0x08            /* alternate form */
                   9693: #define        LADJUST         0x10            /* left adjustment */
                   9694: #define        ZEROPAD         0x20            /* zero (as opposed to blank) pad */
                   9695: #define        HEXPREFIX       0x40            /* add 0x or 0X prefix */
                   9696: 
                   9697: 
                   9698: static char * exponent(char * p, int exp, u_char fmtch);
                   9699: static char * round(double fract,
                   9700:                    int * exp,
                   9701:                    char * start,
                   9702:                    char * end,
                   9703:                    char ch,
                   9704:                    char * signp);
                   9705: 
                   9706: 
                   9707: 
                   9708: static
                   9709: cvt(double number,
                   9710:     register int prec,
                   9711:     int flags,
                   9712:     char * signp,
                   9713:     u_char fmtch,
                   9714:     char * startp,
                   9715:     char * endp)
                   9716: {
                   9717:     register char *p, *t;
                   9718:     register double fract;
                   9719:     int dotrim, expcnt, gformat;
                   9720:     double integer, tmp;
                   9721: 
                   9722:     dotrim = expcnt = gformat = 0;
                   9723:     fract = modf(number, &integer);
                   9724: 
                   9725:     /* get an extra slot for rounding. */
                   9726:     t = ++startp;
                   9727: 
                   9728:     /*
                   9729:        * get integer portion of number; put into the end of the buffer; the
                   9730:            * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
                   9731:                */
                   9732:     for (p = endp - 1; integer; ++expcnt) {
                   9733:        tmp = modf(integer / 10, &integer);
                   9734:        *p-- = tochar((int)((tmp + .01) * 10));
                   9735:     }
                   9736:     switch(fmtch) {
                   9737:     case 'f':
                   9738:        /* reverse integer into beginning of buffer */
                   9739:        if (expcnt)
                   9740:            for (; ++p < endp; *t++ = *p);
                   9741:        else
                   9742:            *t++ = '0';
                   9743:        /*
                   9744:            * if precision required or alternate flag set, add in a
                   9745:                * decimal point.
                   9746:                    */
                   9747:        if (prec || flags&ALT)
                   9748:            *t++ = '.';
                   9749:        /* if requires more precision and some fraction left */
                   9750:        if (fract) {
                   9751:            if (prec)
                   9752:                do {
                   9753:                    fract = modf(fract * 10, &tmp);
                   9754:                    *t++ = tochar((int)tmp);
                   9755:                } while (--prec && fract);
                   9756:            if (fract)
                   9757:                startp = round(fract, (int *)NULL, startp,
                   9758:                               t - 1, (char)0, signp);
                   9759:        }
                   9760:        for (; prec--; *t++ = '0');
                   9761:        break;
                   9762:     case 'e':
                   9763:     case 'E':
                   9764:       eformat: if (expcnt) {
                   9765:          *t++ = *++p;
                   9766:          if (prec || flags&ALT)
                   9767:              *t++ = '.';
                   9768:          /* if requires more precision and some integer left */
                   9769:          for (; prec && ++p < endp; --prec)
                   9770:              *t++ = *p;
                   9771:          /*
                   9772:              * if done precision and more of the integer component,
                   9773:          * round using it; adjust fract so we don't re-round
                   9774:              * later.
                   9775:                  */
                   9776:          if (!prec && ++p < endp) {
                   9777:              fract = 0;
                   9778:              startp = round((double)0, &expcnt, startp,
                   9779:                             t - 1, *p, signp);
                   9780:          }
                   9781:          /* adjust expcnt for digit in front of decimal */
                   9782:          --expcnt;
                   9783:       }
                   9784:        /* until first fractional digit, decrement exponent */
                   9785:       else if (fract) {
                   9786:          /* adjust expcnt for digit in front of decimal */
                   9787:          for (expcnt = -1;; --expcnt) {
                   9788:              fract = modf(fract * 10, &tmp);
                   9789:              if (tmp)
                   9790:                  break;
                   9791:          }
                   9792:          *t++ = tochar((int)tmp);
                   9793:          if (prec || flags&ALT)
                   9794:              *t++ = '.';
                   9795:       }
                   9796:       else {
                   9797:          *t++ = '0';
                   9798:          if (prec || flags&ALT)
                   9799:              *t++ = '.';
                   9800:       }
                   9801:        /* if requires more precision and some fraction left */
                   9802:        if (fract) {
                   9803:            if (prec)
                   9804:                do {
                   9805:                    fract = modf(fract * 10, &tmp);
                   9806:                    *t++ = tochar((int)tmp);
                   9807:                } while (--prec && fract);
                   9808:            if (fract)
                   9809:                startp = round(fract, &expcnt, startp,
                   9810:                               t - 1, (char)0, signp);
                   9811:        }
                   9812:        /* if requires more precision */
                   9813:        for (; prec--; *t++ = '0');
                   9814: 
                   9815:        /* unless alternate flag, trim any g/G format trailing 0's */
                   9816:        if (gformat && !(flags&ALT)) {
                   9817:            while (t > startp && *--t == '0');
                   9818:            if (*t == '.')
                   9819:                --t;
                   9820:            ++t;
                   9821:        }
                   9822:        t = exponent(t, expcnt, fmtch);
                   9823:        break;
                   9824:     case 'g':
                   9825:     case 'G':
                   9826:        /* a precision of 0 is treated as a precision of 1. */
                   9827:        if (!prec)
                   9828:            ++prec;
                   9829:        /*
                   9830:            * ``The style used depends on the value converted; style e
                   9831:                * will be used only if the exponent resulting from the
                   9832:                    * conversion is less than -4 or greater than the precision.''
                   9833:                        *       -- ANSI X3J11
                   9834:                            */
                   9835:        if (expcnt > prec || !expcnt && fract && fract < .0001) {
                   9836:            /*
                   9837:                * g/G format counts "significant digits, not digits of
                   9838:                         * precision; for the e/E format, this just causes an
                   9839:                         * off-by-one problem, i.e. g/G considers the digit
                   9840:                         * before the decimal point significant and e/E doesn't
                   9841:                         * count it as precision."
                   9842:                             */
                   9843:            --prec;
                   9844:            fmtch -= 2;         /* G->E, g->e */
                   9845:            gformat = 1;
                   9846:            goto eformat;
                   9847:        }
                   9848:        /*
                   9849:            * reverse integer into beginning of buffer,
                   9850:        * note, decrement precision
                   9851:            */
                   9852:        if (expcnt)
                   9853:            for (; ++p < endp; *t++ = *p, --prec);
                   9854:        else
                   9855:            *t++ = '0';
                   9856:        /*
                   9857:            * if precision required or alternate flag set, add in a
                   9858:                * decimal point.  If no digits yet, add in leading 0.
                   9859:                    */
                   9860:        if (prec || flags&ALT) {
                   9861:            dotrim = 1;
                   9862:            *t++ = '.';
                   9863:        }
                   9864:        else
                   9865:            dotrim = 0;
                   9866:        /* if requires more precision and some fraction left */
                   9867:        if (fract) {
                   9868:            if (prec) {
                   9869:                do {
                   9870:                    fract = modf(fract * 10, &tmp);
                   9871:                    *t++ = tochar((int)tmp);
                   9872:                } while(!tmp);
                   9873:                while (--prec && fract) {
                   9874:                    fract = modf(fract * 10, &tmp);
                   9875:                    *t++ = tochar((int)tmp);
                   9876:                }
                   9877:            }
                   9878:            if (fract)
                   9879:                startp = round(fract, (int *)NULL, startp,
                   9880:                               t - 1, (char)0, signp);
                   9881:        }
                   9882:        /* alternate format, adds 0's for precision, else trim 0's */
                   9883:        if (flags&ALT)
                   9884:            for (; prec--; *t++ = '0');
                   9885:        else if (dotrim) {
                   9886:            while (t > startp && *--t == '0');
                   9887:            if (*t != '.')
                   9888:                ++t;
                   9889:        }
                   9890:     }
                   9891:     return(t - startp);
                   9892: }
                   9893: 
                   9894: static char * round(double fract,
                   9895:                    int * exp,
                   9896:                    char * start,
                   9897:                    char * end,
                   9898:                    char ch,
                   9899:                    char * signp)
                   9900: {
                   9901:     double tmp;
                   9902: 
                   9903:     if (fract)
                   9904:        (void)modf(fract * 10, &tmp);
                   9905:     else
                   9906:        tmp = todigit(ch);
                   9907:     if (tmp > 4)
                   9908:        for (;; --end) {
                   9909:            if (*end == '.')
                   9910:                --end;
                   9911:            if (++*end <= '9')
                   9912:                break;
                   9913:            *end = '0';
                   9914:            if (end == start) {
                   9915:                if (exp) {      /* e/E; increment exponent */
                   9916:                    *end = '1';
                   9917:                    ++*exp;
                   9918:                }
                   9919:                else {          /* f; add extra digit */
                   9920:                    *--end = '1';
                   9921:                    --start;
                   9922:                }
                   9923:                break;
                   9924:            }
                   9925:        }
                   9926:     /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
                   9927:     else if (*signp == '-')
                   9928:        for (;; --end) {
                   9929:            if (*end == '.')
                   9930:                --end;
                   9931:            if (*end != '0')
                   9932:                break;
                   9933:            if (end == start)
                   9934:                *signp = 0;
                   9935:        }
                   9936:     return(start);
                   9937: }
                   9938: 
                   9939: static char * exponent(char * p, int exp, u_char fmtch)
                   9940: {
                   9941:     register char *t;
                   9942:     char expbuf[MAXEXP];
                   9943: 
                   9944:     *p++ = fmtch;
                   9945:     if (exp < 0) {
                   9946:        exp = -exp;
                   9947:        *p++ = '-';
                   9948:     }
                   9949:     else
                   9950:        *p++ = '+';
                   9951:     t = expbuf + MAXEXP;
                   9952:     if (exp > 9) {
                   9953:        do {
                   9954:            *--t = tochar(exp % 10);
                   9955:        } while ((exp /= 10) > 9);
                   9956:        *--t = tochar(exp);
                   9957:        for (; t < expbuf + MAXEXP; *p++ = *t++);
                   9958:     }
                   9959:     else {
                   9960:        *p++ = '0';
                   9961:        *p++ = tochar(exp);
                   9962:     }
                   9963:     return(p);
                   9964: }
                   9965: 
                   9966: int vostream_printf(const char *fmt0, va_list argp, ostream& fp)
                   9967: {
                   9968:     register const u_char *fmt;        /* format string */
                   9969:     register int ch;           /* character from fmt */
                   9970:     register int cnt;          /* return value accumulator */
                   9971:     register int n;            /* random handy integer */
                   9972:     register char *t;          /* buffer pointer */
                   9973:     double _double;            /* double precision arguments %[eEfgG] */
                   9974:     u_long _ulong;             /* integer arguments %[diouxX] */
                   9975:     int base;                  /* base for [diouxX] conversion */
                   9976:     int dprec;                 /* decimal precision in [diouxX] */
                   9977:     int fieldsz;               /* field size expanded by sign, etc */
                   9978:     int flags;                 /* flags as above */
                   9979:     int fpprec;                        /* `extra' floating precision in [eEfgG] */
                   9980:     int prec;                  /* precision from format (%.3d), or -1 */
                   9981:     int realsz;                        /* field size expanded by decimal precision */
                   9982:     int size;                  /* size of converted field or string */
                   9983:     int width;                 /* width from format (%8d), or 0 */
                   9984:     char sign;                 /* sign prefix (' ', '+', '-', or \0) */
                   9985:     char softsign;             /* temporary negative sign for floats */
                   9986:     char *digs;                        /* digits for [diouxX] conversion */
                   9987:     char buf[BUF];             /* space for %c, %[diouxX], %[eEfgG] */
                   9988: 
                   9989:     fmt = (const u_char *)fmt0;
                   9990:     digs = "0123456789abcdef";
                   9991:     for (cnt = 0;; ++fmt) {
                   9992:        for (;(ch = *fmt) && ch != '%'; ++cnt, ++fmt)
                   9993:            PUTC(ch);
                   9994:        if (!ch)return (cnt);
                   9995: 
                   9996:        flags = 0; dprec = 0; fpprec = 0; width = 0;
                   9997:        prec = -1;
                   9998:        sign = '\0';
                   9999: 
                   10000:       rflag:           switch (*++fmt) {
                   10001:        case ' ':
                   10002:          /*
                   10003:           * ``If the space and + flags both appear, the space
                   10004:           * flag will be ignored.''
                   10005:           *    -- ANSI X3J11
                   10006:           */
                   10007:          if (!sign)
                   10008:              sign = ' ';
                   10009:          goto rflag;
                   10010:        case '#':
                   10011:          flags |= ALT;
                   10012:          goto rflag;
                   10013:        case '*':
                   10014:          /*
                   10015:           * ``A negative field width argument is taken as a
                   10016:           * - flag followed by a  positive field width.''
                   10017:           *    -- ANSI X3J11
                   10018:           * They don't exclude field widths read from args.
                   10019:           */
                   10020:          if ((width = va_arg(argp, int)) >= 0)
                   10021:              goto rflag;
                   10022:          width = -width;
                   10023:          /* FALLTHROUGH */
                   10024:        case '-':
                   10025:          flags |= LADJUST;
                   10026:          goto rflag;
                   10027:        case '+':
                   10028:          sign = '+';
                   10029:          goto rflag;
                   10030:        case '.':
                   10031:          if (*++fmt == '*')
                   10032:              n = va_arg(argp, int);
                   10033:          else {
                   10034:              n = 0;
                   10035:              while (isascii(*fmt) && isdigit(*fmt))
                   10036:                  n = 10 * n + todigit(*fmt++);
                   10037:              --fmt;
                   10038:          }
                   10039:          prec = n < 0 ? -1 : n;
                   10040:          goto rflag;
                   10041:        case '0':
                   10042:          /*
                   10043:           * ``Note that 0 is taken as a flag, not as the
                   10044:           * beginning of a field width.''
                   10045:           *    -- ANSI X3J11
                   10046:           */
                   10047:          flags |= ZEROPAD;
                   10048:          goto rflag;
                   10049:        case '1': case '2': case '3': case '4':
                   10050:        case '5': case '6': case '7': case '8': case '9':
                   10051:          n = 0;
                   10052:          do {
                   10053:              n = 10 * n + todigit(*fmt);
                   10054:          } while (isascii(*++fmt) && isdigit(*fmt));
                   10055:          width = n;
                   10056:          --fmt;
                   10057:          goto rflag;
                   10058:        case 'L':
                   10059:          flags |= LONGDBL;
                   10060:          goto rflag;
                   10061:        case 'h':
                   10062:          flags |= SHORTINT;
                   10063:          goto rflag;
                   10064:        case 'l':
                   10065:          flags |= LONGINT;
                   10066:          goto rflag;
                   10067:        case 'c':
                   10068:          *(t = buf) = va_arg(argp, int);
                   10069:          size = 1;
                   10070:          sign = '\0';
                   10071:          goto pforw;
                   10072:        case 'D':
                   10073:          flags |= LONGINT;
                   10074:          /*FALLTHROUGH*/
                   10075:        case 'd':
                   10076:        case 'i':
                   10077:          ARG();
                   10078:          if ((long)_ulong < 0) {
                   10079:              _ulong = -_ulong;
                   10080:              sign = '-';
                   10081:          }
                   10082:          base = 10;
                   10083:          goto number;
                   10084:        case 'e':
                   10085:        case 'E':
                   10086:        case 'f':
                   10087:        case 'g':
                   10088:        case 'G':
                   10089:          _double = va_arg(argp, double);
                   10090:          /*
                   10091:           * don't do unrealistic precision; just pad it with
                   10092:           * zeroes later, so buffer size stays rational.
                   10093:           */
                   10094:          if (prec > MAXFRACT) {
                   10095:              if (*fmt != 'g' && *fmt != 'G' || (flags&ALT))
                   10096:                  fpprec = prec - MAXFRACT;
                   10097:              prec = MAXFRACT;
                   10098:          }
                   10099:          else if (prec == -1)
                   10100:              prec = DEFPREC;
                   10101:          /*
                   10102:           * softsign avoids negative 0 if _double is < 0 and
                   10103:           * no significant digits will be shown
                   10104:           */
                   10105:          if (_double < 0) {
                   10106:              softsign = '-';
                   10107:              _double = -_double;
                   10108:          }
                   10109:          else
                   10110:              softsign = 0;
                   10111:          /*
                   10112:           * cvt may have to round up past the "start" of the
                   10113:           * buffer, i.e. ``intf("%.2f", (double)9.999);'';
                   10114:           * if the first char isn't NULL, it did.
                   10115:           */
                   10116:          *buf = NULL;
                   10117:          size = cvt(_double, prec, flags, &softsign, *fmt, buf,
                   10118:                     buf + sizeof(buf));
                   10119:          if (softsign)
                   10120:              sign = '-';
                   10121:          t = *buf ? buf : buf + 1;
                   10122:          goto pforw;
                   10123:        case 'n':
                   10124:          if (flags & LONGINT)
                   10125:              *va_arg(argp, long *) = cnt;
                   10126:          else if (flags & SHORTINT)
                   10127:              *va_arg(argp, short *) = cnt;
                   10128:          else
                   10129:              *va_arg(argp, int *) = cnt;
                   10130:          break;
                   10131:        case 'O':
                   10132:          flags |= LONGINT;
                   10133:          /*FALLTHROUGH*/
                   10134:        case 'o':
                   10135:          ARG();
                   10136:          base = 8;
                   10137:          goto nosign;
                   10138:        case 'T':               // Type
                   10139:          {
                   10140:              streampos cur_pos;
                   10141:              streampos new_pos;
                   10142: 
                   10143:              cur_pos = fp.tellp();
                   10144: 
                   10145:              _Print_self * obj = va_arg (argp, _Print_self *);
                   10146:              obj->print_self (fp);
                   10147: 
                   10148:              new_pos = fp.tellp();
                   10149:                
                   10150:              cnt += int (new_pos - cur_pos);
                   10151:          }
                   10152:          break;
                   10153: 
                   10154:        case 'p':
                   10155:          /*
                   10156:           * ``The argument shall be a pointer to void.  The
                   10157:           * value of the pointer is converted to a sequence
                   10158:           * of printable characters, in an implementation-
                   10159:           * defined manner.''
                   10160:           *    -- ANSI X3J11
                   10161:           */
                   10162:          /* NOSTRICT */
                   10163:          _ulong = (u_long)va_arg(argp, void *);
                   10164:          base = 16;
                   10165:          goto nosign;
                   10166:        case 's':
                   10167:          if (!(t = va_arg(argp, char *)))
                   10168:              t = "(null)";
                   10169:          if (prec >= 0) {
                   10170:              /*
                   10171:               * can't use strlen; can only look for the
                   10172:               * NUL in the first `prec' characters, and
                   10173:               * strlen() will go further.
                   10174:               */
                   10175:              char *p;
                   10176: 
                   10177:              if (p = (char *) memchr(t, 0, prec)) {
                   10178:                  size = p - t;
                   10179:                  if (size > prec)
                   10180:                      size = prec;
                   10181:              } else
                   10182:                  size = prec;
                   10183:          } else
                   10184:              size = strlen(t);
                   10185:          sign = '\0';
                   10186:          goto pforw;
                   10187:        case 'U':
                   10188:          flags |= LONGINT;
                   10189:          /*FALLTHROUGH*/
                   10190:        case 'u':
                   10191:          ARG();
                   10192:          base = 10;
                   10193:          goto nosign;
                   10194:        case 'X':
                   10195:          digs = "0123456789ABCDEF";
                   10196:          /* FALLTHROUGH */
                   10197:        case 'x':
                   10198:          ARG();
                   10199:          base = 16;
                   10200:          /* leading 0x/X only if non-zero */
                   10201:          if (flags & ALT && _ulong != 0)
                   10202:              flags |= HEXPREFIX;
                   10203: 
                   10204:          /* unsigned conversions */
                   10205:        nosign:                 sign = '\0';
                   10206:          /*
                   10207:           * ``... diouXx conversions ... if a precision is
                   10208:           * specified, the 0 flag will be ignored.''
                   10209:           *    -- ANSI X3J11
                   10210:           */
                   10211:        number:                 if ((dprec = prec) >= 0)
                   10212:            flags &= ~ZEROPAD;
                   10213: 
                   10214:          /*
                   10215:           * ``The result of converting a zero value with an
                   10216:           * explicit precision of zero is no characters.''
                   10217:           *    -- ANSI X3J11
                   10218:           */
                   10219:          t = buf + BUF;
                   10220:          if (_ulong != 0 || prec != 0) {
                   10221:              do {
                   10222:                  *--t = digs[_ulong % base];
                   10223:                  _ulong /= base;
                   10224:              } while (_ulong);
                   10225:              digs = "0123456789abcdef";
                   10226:              if (flags & ALT && base == 8 && *t != '0')
                   10227:                  *--t = '0';   /* octal leading 0 */
                   10228:          }
                   10229:          size = buf + BUF - t;
                   10230: 
                   10231:        pforw:
                   10232:          /*
                   10233:           * All reasonable formats wind up here.  At this point,
                   10234:           * `t' points to a string which (if not flags&LADJUST)
                   10235:           * should be padded out to `width' places.  If
                   10236:           * flags&ZEROPAD, it should first be prefixed by any
                   10237:           * sign or other prefix; otherwise, it should be blank
                   10238:           * padded before the prefix is emitted.  After any
                   10239:           * left-hand padding and prefixing, emit zeroes
                   10240:           * required by a decimal [diouxX] precision, then print
                   10241:           * the string proper, then emit zeroes required by any
                   10242:           * leftover floating precision; finally, if LADJUST,
                   10243:           * pad with blanks.
                   10244:           */
                   10245: 
                   10246:          /*
                   10247:           * compute actual size, so we know how much to pad
                   10248:           * fieldsz excludes decimal prec; realsz includes it
                   10249:           */
                   10250:          fieldsz = size + fpprec;
                   10251:          if (sign)
                   10252:              fieldsz++;
                   10253:          if (flags & HEXPREFIX)
                   10254:              fieldsz += 2;
                   10255:          realsz = dprec > fieldsz ? dprec : fieldsz;
                   10256: 
                   10257:          /* right-adjusting blank padding */
                   10258:          if ((flags & (LADJUST|ZEROPAD)) == 0 && width)
                   10259:              for (n = realsz; n < width; n++)
                   10260:                  PUTC(' ');
                   10261:          /* prefix */
                   10262:          if (sign)
                   10263:              PUTC(sign);
                   10264:          if (flags & HEXPREFIX) {
                   10265:              PUTC('0');
                   10266:              PUTC((char)*fmt);
                   10267:          }
                   10268:          /* right-adjusting zero padding */
                   10269:          if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
                   10270:              for (n = realsz; n < width; n++)
                   10271:                  PUTC('0');
                   10272:          /* leading zeroes from decimal precision */
                   10273:          for (n = fieldsz; n < dprec; n++)
                   10274:              PUTC('0');
                   10275: 
                   10276:          /* the string or number proper */
                   10277: 
                   10278:          fp.write(t, size);
                   10279: 
                   10280:          /* trailing f.p. zeroes */
                   10281:          while (--fpprec >= 0)
                   10282:              PUTC('0');
                   10283:          /* left-adjusting padding (always blank) */
                   10284:          if (flags & LADJUST)
                   10285:              for (n = realsz; n < width; n++)
                   10286:                  PUTC(' ');
                   10287:          /* finally, adjust cnt */
                   10288:          cnt += width > realsz ? width : realsz;
                   10289:          break;
                   10290:        case '\0':              /* "%?" prints ?, unless ? is NULL */
                   10291:          return (cnt);
                   10292:        default:
                   10293:          PUTC(*fmt);
                   10294:          cnt++;
                   10295:       }
                   10296:     }
                   10297:     /* NOTREACHED */
                   10298: }
                   10299: 
                   10300: int ostream_printf(ostream& stream, const char * format ...)
                   10301: {
                   10302:     int ret;
                   10303: 
                   10304:     va_list args;
                   10305:     va_start(args, format);
                   10306:     ret = vostream_printf(format, args, stream);
                   10307:     va_end(args);
                   10308:     return ret;
                   10309: }
                   10310: 
                   10311: // There are intended to be more convienient that stirring up
                   10312: // an strstream by hand.
                   10313: 
                   10314: int printf_to_string (char * string, int length, const char * format ...)
                   10315: {
                   10316:     ostrstream& stream = ostrstream (string, length, (ios::open_mode)ios::app);
                   10317: 
                   10318:     va_list args;
                   10319:     va_start(args, format);
                   10320: 
                   10321:     vostream_printf (format, args, stream);
                   10322: 
                   10323:     va_end(args);
                   10324:     stream.str();
                   10325:     return stream.pcount();
                   10326: }
                   10327: 
                   10328: // caller of this must free() the string that comes back. 
                   10329: 
                   10330: char * printf_to_alloc_string (const char * format ...)
                   10331: {
                   10332:     ostrstream& stream = ostrstream ();
                   10333: 
                   10334:     va_list args;
                   10335:     va_start(args, format);
                   10336: 
                   10337:     vostream_printf (format, args, stream);
                   10338: 
                   10339:     va_end(args);
                   10340:     return stream.str();
                   10341: }
                   10342: 0707071010112044141004440001630000160000010176000466055377500001000000031505error.c/*ident    "@(#)ctrans:src/error.c 1.4" */
                   10343: /**************************************************************************
                   10344: 
                   10345:        C++ source for cfront, the C++ compiler front-end
                   10346:        written in the computer science research center of Bell Labs
                   10347: 
                   10348:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   10349:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   10350: 
                   10351:  error.c :
                   10352: 
                   10353:        write error messages
                   10354: 
                   10355:        Until scan_started != 0 no context can be assumed
                   10356: 
                   10357: ***************************************************************************/
                   10358: 
                   10359: #ifdef __cplusplus
                   10360: #include <stdlib.h>
                   10361: #endif
                   10362: 
                   10363: #include "cfront.h"
                   10364: #include "size.h"
                   10365: #include "template.h"
                   10366: 
                   10367: int error_count;
                   10368: static int no_of_warnings;
                   10369: char scan_started;
                   10370: 
                   10371: #define ERRTRACE    20
                   10372: 
                   10373: static char* abbrev_tbl[] = {
                   10374:        " argument",
                   10375:        " base",
                   10376:        " class",
                   10377:        " declaration",
                   10378:        " expression",
                   10379:        " function",
                   10380:        " global",
                   10381:        "H",
                   10382:        " initialize",
                   10383:        "J",
                   10384:        " constructor", // 'K' !
                   10385:        " list",
                   10386:        " member",
                   10387:        " name",
                   10388:        " object",
                   10389:        " pointer",
                   10390:        " qualifie",
                   10391:        " reference",
                   10392:        " statement",
                   10393:        " type",
                   10394:        " undefined",
                   10395:        " variable",
                   10396:        " with",
                   10397:        " expected", // 'X'
                   10398:        " template", // 'Y'???
                   10399:        " parameter", // 'Z'???
                   10400: };
                   10401: 
                   10402: ea* ea0;
                   10403: 
                   10404: void error_init()
                   10405: {
                   10406:        static char errbuf[BUFSIZ];
                   10407:        setbuf(stderr,errbuf);
                   10408:        ea0 = new ea;
                   10409: }
                   10410: 
                   10411: #define INTERNAL 127
                   10412: 
                   10413: void ext(int n)
                   10414: {
                   10415:        int useit=n; // to avoid n not used warning during build
                   10416: // for testing only
                   10417: //     if (n == INTERNAL)
                   10418: //     abort();
                   10419:        exit(error_count?error_count:1);
                   10420: }
                   10421: 
                   10422: /* static */ 
                   10423: void print_loc()
                   10424: {
                   10425:        loc* sl = (Cstmt) ? &Cstmt->where : 0;
                   10426:        loc* dl = (Cdcl && (Cdcl->base==NAME || Cdcl->base==TNAME)) ? &Cdcl->where : 0;
                   10427:        if (sl && dl && sl->file==dl->file) {   // Cstmt and Cdcl in same file
                   10428:                if (sl->line<=dl->line) {
                   10429:                        if (curloc.file==dl->file && curloc.line<dl->line)
                   10430:                                // hack to compensate for YACC's
                   10431:                                // bad manners in the use of line numbers
                   10432:                                sl->put(out_file);
                   10433:                        else
                   10434:                                dl->put(out_file);
                   10435:                }
                   10436:                else
                   10437:                        sl->put(out_file);
                   10438:        }
                   10439:        else if (sl && sl->file==curr_file)     // Cstmt in current file
                   10440:                sl->put(out_file);
                   10441:        else if (dl && dl->file==curr_file)     // Cdcl in current file
                   10442:                dl->put(out_file);
                   10443:        else
                   10444:                curloc.put(out_file);
                   10445: }
                   10446: 
                   10447: static void print_context()
                   10448: {
                   10449:        putc('\n',out_file);
                   10450: }
                   10451: 
                   10452: static char in_error = 0;
                   10453: static loc dummy_loc;
                   10454: 
                   10455: void yyerror(char* s)
                   10456: {
                   10457:        error(s);
                   10458: }
                   10459: 
                   10460: int error(const char* s)
                   10461: {
                   10462:        return error(0,s);
                   10463: }
                   10464: 
                   10465: int error(int t, const char* s)
                   10466: {
                   10467:        return error(t,&dummy_loc,s,*ea0,*ea0,*ea0,*ea0);
                   10468: }
                   10469: 
                   10470: int error(const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3)
                   10471: {
                   10472:        return error(0,&dummy_loc,s,a0,a1,a2,a3);
                   10473: }
                   10474: 
                   10475: int error(loc* lc, const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3)
                   10476: {
                   10477:        return error(0,lc,s,a0,a1,a2,a3);
                   10478: }
                   10479: 
                   10480: int error(int t, const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3)
                   10481: {
                   10482:        return error(t,&dummy_loc,s,a0,a1,a2,a3);
                   10483: }
                   10484: 
                   10485: int suppress_error;
                   10486: 
                   10487: int error(int t, loc* lc, const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3)
                   10488: /*
                   10489:        "int" not "void" because of "pch" in lex.c
                   10490: 
                   10491:        legal error types are:
                   10492:                'w'             warning  (not counted in error count)
                   10493:                'd'             debug
                   10494:                'D'             debug -- no prefix
                   10495:                's'             "not implemented" message
                   10496:                'l'             "compiler limit exceeded" message
                   10497:                0               error 
                   10498:                'i'             internal error (causes abort)
                   10499:                't'             error while printing error message
                   10500: */
                   10501: {
                   10502:        if (suppress_error) return 0;
                   10503: 
                   10504:        if (in_error++)
                   10505:                if (t == 't')
                   10506:                        t = 'i';
                   10507:                else if (4 < in_error) {
                   10508:                        fprintf(stderr,"\nOops!, error while handling error\n");
                   10509:                        ext(13);
                   10510:                }
                   10511: 
                   10512:        FILE * of = out_file;
                   10513:        out_file = stderr;
                   10514: 
                   10515:        if (!scan_started || t=='t')
                   10516:                putch('\n');
                   10517:        else if (lc != &dummy_loc) {
                   10518:                if(t != 'D') lc->put(out_file);
                   10519:        } else {
                   10520:                if(t != 'D') print_loc();
                   10521:        }
                   10522: 
                   10523:        switch (t) {
                   10524:        case 0:
                   10525:                putstring("error: ");
                   10526:                break;
                   10527:         case 'd':
                   10528:                putstring("DEBUG: ");
                   10529:         case 'D':
                   10530:                break;
                   10531:         case 'w':
                   10532:                no_of_warnings++;
                   10533:                putstring("warning: ");
                   10534:                break;
                   10535:         case 'l':
                   10536:                putstring("compiler limit exceeded: ");
                   10537:                break;
                   10538:         case 's':
                   10539:                putstring("sorry, not implemented: ");
                   10540:                break;
                   10541:         case 'i':
                   10542:                if (error_count++) {
                   10543:                        fprintf(out_file,"sorry, %s cannot recover from earlier errors\n",prog_name);
                   10544:                        ext(INTERNAL);
                   10545:                }
                   10546:                else
                   10547:                        fprintf(out_file,"internal %s error: ",prog_name);
                   10548:         }
                   10549: 
                   10550:        ea argv[4];
                   10551:        ea* a = argv;
                   10552:        argv[0] = a0;
                   10553:        argv[1] = a1;
                   10554:        argv[2] = a2;
                   10555:        argv[3] = a3;
                   10556: 
                   10557:        int c;
                   10558: 
                   10559:        while (c = *s++) {
                   10560:                if ('A'<=c && c<='Z')
                   10561:                        putstring(abbrev_tbl[c-'A']);
                   10562:                else if (c == '%') {
                   10563:                        switch (c = *s++) {
                   10564:                        case 'k':       // TOK assumed passed as an int
                   10565:                        {       TOK x = TOK(a->i);
                   10566:                                if (0<x && x<=MAXTOK && keys[x])
                   10567:                                        fprintf(out_file," %s",keys[x]);
                   10568:                                else
                   10569:                                        fprintf(out_file," token(%d)",x);
                   10570:                                break;
                   10571:                        }
                   10572:                        case 't':       // Ptype 
                   10573:                        {       Ptype tt = Ptype(a->p);
                   10574:                                if (tt == 0) break;
                   10575: 
                   10576:                                putch(' ');
                   10577:                        
                   10578:                                int nt = ntok;
                   10579:                                emode = 1;
                   10580:                                tt->dcl_print(0);
                   10581:                                emode = 0;
                   10582:                                ntok = nt;
                   10583:                                break;
                   10584:                        }
                   10585:                        case 'n':       // Pname
                   10586:                        {       Pname nn = Pname(a->p);
                   10587:                                if (nn && nn->string) {
                   10588:                                        // suppress generated class names:
                   10589:                                        if (nn->string[0]=='_'
                   10590:                                        && nn->string[1]=='_'
                   10591:                                        && nn->string[2]=='C') break;
                   10592:                                        emode = 1;
                   10593:                                        putch(' ');
                   10594:                                        nn->print();
                   10595:                                        emode = 0;
                   10596:                                }
                   10597:                                else
                   10598:                                        putstring(" ?");
                   10599:                                break;
                   10600:                        }
                   10601:                        case 'p':       // pointer
                   10602:                        {       char* f = sizeof(char*)==sizeof(int)?" %d":" %ld";
                   10603:                                fprintf(out_file,f,a->p);
                   10604:                                break;
                   10605:                        }
                   10606:                        case 'c':       // char assumed passed as an int
                   10607:                                putch(a->i);
                   10608:                                break;
                   10609: 
                   10610:                        case 'd':       // int
                   10611:                                fprintf(out_file," %d",a->i);
                   10612:                                break;
                   10613: 
                   10614:                        case 'o':       // int
                   10615:                                fprintf(out_file," %o",a->i);
                   10616:                                break;
                   10617: 
                   10618:                        case 's':       // char*
                   10619:                                char *s = ((char *)a->p);
                   10620:                                if ( s ) putst((char*)a->p);
                   10621:                                break;
                   10622:                        }
                   10623:                        a++;
                   10624:                }
                   10625:                else
                   10626:                        putch(c);
                   10627:        }
                   10628: 
                   10629: /*
                   10630:        switch (t) {
                   10631:        case 'd':
                   10632:        case 't':
                   10633:        case 'w':
                   10634:                putch('\n');
                   10635:                break;
                   10636:        default:
                   10637: */
                   10638:                print_context();
                   10639: /*
                   10640:        }
                   10641: */
                   10642: 
                   10643:         templ_inst::head->print_error_loc();
                   10644:        fflush(stderr);
                   10645:        if (!scan_started && t!='d' && t!='w') ext(4);
                   10646: 
                   10647:         // now we may want to carry on 
                   10648:        out_file = of;
                   10649:        switch (t) {
                   10650:        case 't':
                   10651:                if (--in_error) return 0;
                   10652:        case 'i': 
                   10653:                ext(INTERNAL);
                   10654:        case 0:
                   10655:        case 'l':
                   10656:        case 's':
                   10657:                if (MAXERR<++error_count) {
                   10658:                        fprintf(stderr,"Sorry, too many errors\n");
                   10659:                        ext(7);
                   10660:                }
                   10661:        }
                   10662: 
                   10663:        in_error = 0;
                   10664:        return 0;
                   10665: }
                   10666: 
                   10667: 
                   10668: 
                   10669: #ifdef DBG
                   10670: #define OPEREP(v) ((v)>MAXTOK || (v)<=0 ? 0 : keys[v])
                   10671: void
                   10672: display_type( Ptype t )
                   10673: {
                   10674:        if ( t ) { putc(' ',stderr);
                   10675:                FILE * of = out_file;
                   10676:                out_file = stderr;
                   10677:                extern int ntok; int nt = ntok;
                   10678:                emode=1; (t)->dcl_print(0); emode=0;
                   10679:                //fprintf(stderr," <node %d",t->node::id);
                   10680:                if(!t->allocated)fprintf(stderr," UNALLOCATED!");
                   10681:                //putc('>',stderr);
                   10682:                ntok = nt;
                   10683:                out_file = of;
                   10684:        } else fprintf(stderr," <null type>");
                   10685: }
                   10686: #define INDENT(in) { for ( int i = in;  i > 0;  --i ) fprintf(stderr,"  "); }
                   10687: static indent = 0;
                   10688: 
                   10689: void
                   10690: display_expr( Pexpr ptr, char* label, int oneline )
                   10691: {
                   10692:        INDENT(indent);
                   10693:        if ( label ) fprintf(stderr, "%s:", label);
                   10694:        if ( ptr == 0 ) {
                   10695:                fprintf(stderr, "NULL EXPR\n" );
                   10696:                return;
                   10697:        }
                   10698:        fprintf(stderr,"%d",ptr->node::id);
                   10699:        if(!ptr->allocated)fprintf(stderr," UNALLOCATED!");
                   10700:        putc(':',stderr);
                   10701:        char* s = OPEREP(ptr->base);
                   10702:        if ( s == 0 )
                   10703:                fprintf(stderr, "token(%d)", ptr->base );
                   10704:        else
                   10705:                fprintf(stderr,"%s",s);
                   10706:        if ( ptr->displayed ) { // recursion!!!
                   10707:                if ( ptr->base == NAME )
                   10708:                        fprintf(stderr," '%s'",Pname(ptr)->string);
                   10709:                fprintf(stderr,"   RECURSION!!!\n");
                   10710:                ptr->displayed = 0;
                   10711:                return;
                   10712:        }
                   10713:        ptr->displayed = 1;
                   10714:        switch ( ptr->base ) {
                   10715:        case QUEST:
                   10716:                display_type(ptr->tp);
                   10717:                putc('\n',stderr);
                   10718:                if ( !oneline ) {
                   10719:                        ++indent;
                   10720:                        display_expr( ptr->cond, "cond" ); 
                   10721:                        display_expr( ptr->e1, "e1" ); 
                   10722:                        display_expr( ptr->e2, "e2" ); 
                   10723:                        --indent;
                   10724:                }
                   10725:                break;
                   10726:        case REF: case DOT:
                   10727:                display_type(ptr->tp);
                   10728:                putc('\n',stderr);
                   10729:                if ( !oneline ) {
                   10730:                        ++indent;
                   10731:                        display_expr( ptr->e1, "e1" );
                   10732:                        display_expr( ptr->mem, "mem" );
                   10733:                        --indent;
                   10734:                }
                   10735:                break;
                   10736:        case MDOT:
                   10737:                display_type(ptr->tp);
                   10738:                fprintf(stderr," string2:'%s'\n",ptr->string2?ptr->string2:"");
                   10739:                if ( !oneline ) {
                   10740:                        ++indent;
                   10741:                        display_expr( ptr->mem, "mem" );
                   10742:                        --indent;
                   10743:                }
                   10744:                break;
                   10745:        case ICALL:
                   10746:                fprintf(stderr," fn=='%s'",ptr->il->fct_name->string);
                   10747:                display_type(ptr->tp);
                   10748:                putc('\n',stderr);
                   10749:                if ( !oneline ) {
                   10750:                        ++indent;
                   10751:                        for ( int i = 0;  i < ptr->il->i_slots;  ++i ) {
                   10752:                                ia *aa = &ptr->il->i_args[i];
                   10753:                                INDENT(indent);
                   10754:                                fprintf(stderr,"arg:'%s'",aa->local&&aa->local->string?aa->local->string:"");
                   10755:                                display_type(aa->tp);
                   10756:                                putc('\n',stderr);
                   10757:                                ++indent;
                   10758:                                display_expr( aa->arg, "actual" );
                   10759:                                --indent;
                   10760:                        }
                   10761:                        display_expr( ptr->e1, "e1" );
                   10762:                        display_expr( ptr->e2, "e2" );
                   10763:                        --indent;
                   10764:                }
                   10765:                break;
                   10766:        case SIZEOF:
                   10767:                if ( ptr->tp2 ) {
                   10768:                        putc('(',stderr);
                   10769:                        display_type(ptr->tp2);
                   10770:                        putc(')',stderr);
                   10771:                }
                   10772:                display_type(ptr->tp);
                   10773:                putc('\n',stderr);
                   10774:                if ( !oneline ) {
                   10775:                    if ( ptr->e1 ) {
                   10776:                        ++indent;
                   10777:                        display_expr(ptr->e1,"e1");
                   10778:                        --indent;
                   10779:                    }
                   10780:                    if ( ptr->e2 ) {
                   10781:                        ++indent;
                   10782:                        display_expr(ptr->e2,"e2");
                   10783:                        --indent;
                   10784:                    }
                   10785:                }
                   10786:                break;
                   10787:        case ZERO:
                   10788:                display_type(ptr->tp);
                   10789:                putc('\n',stderr);
                   10790:                break;
                   10791:        case NAME: case TNAME: case STRING:
                   10792:        case ICON: case ID:
                   10793:        case FCON: case CCON:
                   10794:        case IVAL:
                   10795:                fprintf(stderr," '%s'",(ptr->string)?ptr->string:"<0>");
                   10796:                display_type(ptr->tp);
                   10797:                if(ptr->string2)fprintf(stderr," string2=='%s'",ptr->string2);
                   10798:                if ( ptr->permanent ) fprintf(stderr, " (permanent)");
                   10799:                if ( ptr->base == IVAL ) fprintf(stderr, " i1==%d", ptr->i1);
                   10800:                putc('\n',stderr);
                   10801:                if ( !oneline && (ptr->base == NAME || ptr->base == TNAME) ) {
                   10802:                        Pname n = Pname(ptr);
                   10803:                        ++indent;
                   10804:                        INDENT(indent);
                   10805:                        fprintf(stderr, "n_sto==%d", n->n_sto );
                   10806:                        fprintf(stderr, " n_stclass==%d",n->n_stclass);
                   10807:                        fprintf(stderr, " n_scope==%d",n->n_scope);
                   10808:                        fprintf(stderr, " n_protected==%d\n", n->n_protect );
                   10809:                        INDENT(indent);
                   10810:                        fprintf(stderr, "n_oper=='%s'", (s=OPEREP(n->base))?s:"0");
                   10811:                        fprintf(stderr, " n_val==%d", n->n_val );
                   10812:                        fprintf(stderr, " n_xref==%d",n->n_xref);
                   10813:                        fprintf(stderr, " lex_level==%d\n", n->lex_level );
                   10814:                        INDENT(indent);
                   10815:                        fprintf(stderr, "n_used==%d",n->n_used);
                   10816:                        fprintf(stderr, " n_assigned_to==%d",n->n_assigned_to);
                   10817:                        fprintf(stderr, " n_addr_taken==%d\n",n->n_addr_taken );
                   10818:                        INDENT(indent);
                   10819:                        fprintf(stderr, "n_union==%d", n->n_union);
                   10820:                        fprintf(stderr, " n_list=='%s'", n->n_list?n->n_list->string:"<0>" );
                   10821:                        fprintf(stderr, " n_qualifier=='%s'", n->n_qualifier?n->n_qualifier->string:"<0>" ); 
                   10822:                        if ( n->n_initializer ) {
                   10823:                                fprintf(stderr, " n_initializer:\n" );
                   10824:                                ++indent;
                   10825:                                display_expr( n->n_initializer );
                   10826:                                --indent;
                   10827:                        } else fprintf(stderr, " n_initializer==<0>\n");
                   10828:                        --indent;
                   10829:                }
                   10830:                break;
                   10831:        case BLOCK:
                   10832:                ((Pstmt)ptr)->where.put(stderr); putc(' ',stderr);
                   10833:                putc('\n',stderr);
                   10834:                break;
                   10835:        default:
                   10836:                display_type(ptr->tp);
                   10837:                putc('\n',stderr);
                   10838:                if ( !oneline && ptr->base > 0
                   10839:                &&   (ptr->base<165 || ptr->base==MEMPTR) ) {
                   10840:                        ++indent;
                   10841:                        display_expr( ptr->e1, "e1" ); 
                   10842:                        display_expr( ptr->e2, "e2" );
                   10843:                        --indent;
                   10844:                }
                   10845:                break;
                   10846:        }
                   10847:        ptr->displayed = 0;
                   10848:        return;
                   10849: }
                   10850: void
                   10851: display_stmt( Pstmt ptr, char* label, int oneline )
                   10852: {
                   10853:        INDENT(indent);
                   10854:        if ( label ) fprintf(stderr, "%s:", label);
                   10855:        if ( ptr == 0 ) {
                   10856:                fprintf(stderr, "NULL STMT\n" );
                   10857:                return;
                   10858:        }
                   10859:        fprintf(stderr,"%d",ptr->node::id);
                   10860:        if(!ptr->allocated)fprintf(stderr," UNALLOCATED!");
                   10861:        putc(':',stderr);
                   10862:        char* s = OPEREP(ptr->base);
                   10863:        if ( s == 0 )
                   10864:                fprintf(stderr, "token(%d)", ptr->base );
                   10865:        else
                   10866:                fprintf(stderr,"%s",s);
                   10867:        if ( ptr->displayed ) { // recursion!!!
                   10868:                if ( ptr->base == NAME )
                   10869:                        fprintf(stderr," '%s'",Pname(ptr)->string);
                   10870:                fprintf(stderr,"   RECURSION!!!\n");
                   10871:                ptr->displayed = 0;
                   10872:                return;
                   10873:        }
                   10874:        putc(' ',stderr);
                   10875:        ptr->where.put(stderr);
                   10876:        if ( oneline ) { putc('\n',stderr); return; }
                   10877:        ptr->displayed = 1;
                   10878:        switch ( ptr->base ) {
                   10879:        case BLOCK:
                   10880:                fprintf(stderr," .. ");
                   10881:                ptr->where2.put(stderr);
                   10882:                putc('\n',stderr);
                   10883:                ++indent;
                   10884:                { for( Pstmt st = ptr->s;  st;  st = st->s_list )
                   10885:                        display_stmt( ptr->s, "s" ); 
                   10886:                }
                   10887:                --indent;
                   10888:                break;
                   10889:        case IF:
                   10890:                putc('\n',stderr);
                   10891:                ++indent;
                   10892:                display_expr(ptr->e,"cond");
                   10893:                display_stmt(ptr->s,"if-clause");
                   10894:                --indent;
                   10895:                if ( ptr->else_stmt ) {
                   10896:                        INDENT(indent);
                   10897:                        fprintf(stderr,"else\n");
                   10898:                        ++indent;
                   10899:                        display_stmt(ptr->else_stmt,"else-clause");
                   10900:                        --indent;
                   10901:                }
                   10902:                break;
                   10903:        case DO:
                   10904:                putc('\n',stderr);
                   10905:                ++indent;
                   10906:                display_stmt(ptr->s,"do-stmt");
                   10907:                display_expr(ptr->e,"cond");
                   10908:                --indent;
                   10909:                break;
                   10910:        case WHILE:
                   10911:                putc('\n',stderr);
                   10912:                ++indent;
                   10913:                display_expr(ptr->e,"cond");
                   10914:                display_stmt(ptr->s,"while-stmt");
                   10915:                --indent;
                   10916:                break;
                   10917:        case FOR:
                   10918:                putc('\n',stderr);
                   10919:                ++indent;
                   10920:                display_stmt(ptr->for_init,"init");
                   10921:                display_expr(ptr->e,"cond");
                   10922:                display_expr(ptr->e2,"incr");
                   10923:                display_stmt(ptr->s,"stmt");
                   10924:                --indent;
                   10925:                break;
                   10926:        case RETURN:
                   10927:                putc('\n',stderr);
                   10928:                ++indent;
                   10929:                display_expr(ptr->e,"e");
                   10930:                --indent;
                   10931:                break;
                   10932:        case SM:
                   10933:                putc('\n',stderr);
                   10934:                ++indent;
                   10935:                display_expr(ptr->e,"e");
                   10936:                --indent;
                   10937:                break;
                   10938:        default:
                   10939:                putc('\n',stderr);
                   10940:                break;
                   10941:        }
                   10942:        ptr->displayed = 0;
                   10943:        return;
                   10944: }
                   10945: 
                   10946: void
                   10947: display_namelist( Plist nl, char* s, int verbose )
                   10948: {
                   10949:        error('d',"namelist:    %s",s?s:"");
                   10950:        ++indent;
                   10951:        for ( Plist l = nl;  l;  l = l->l ) {
                   10952:                Pname n = l->f;
                   10953:                INDENT(indent);
                   10954:                fprintf(stderr,"        %d",n);
                   10955:                error('D'," %n %k n_key %d",n,n?n->tp->base:0,n?n->n_key:0);
                   10956:                if ( verbose ) {
                   10957:                        ++indent;
                   10958:                        display_expr(n);
                   10959:                        --indent;
                   10960:                }
                   10961:        }
                   10962:        --indent;
                   10963: }
                   10964: #endif
                   10965: 0707071010112044151004440001630000160000010176300466055400100001100000053752expand.c/*ident   "@(#)ctrans:src/expand.c        1.3" */
                   10966: /*****************************************************************
                   10967: 
                   10968:        C++ source for cfront, the C++ compiler front-end
                   10969:        written in the computer science research center of Bell Labs
                   10970: 
                   10971:        Copyright (c) 1984 AT&T, Inc. All rights Reserved
                   10972:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   10973: 
                   10974: expand.c:
                   10975: 
                   10976:        expand inline functions
                   10977: 
                   10978: ******************************************************************/
                   10979: 
                   10980: #include "cfront.h"
                   10981: static Ptable Scope;
                   10982: // extern void display_expr(Pexpr);
                   10983: 
                   10984: static char* temp(char* vn, Pname fn)
                   10985: //
                   10986: //     make the name of the temporary: __Xvn00xxxxxx
                   10987: //     xxxxxx is a representation of fn's address -
                   10988: //     anything unique will do.  we use radix 32 here
                   10989: //     add two bytes to make the name sensitive to the scope
                   10990: //     to avoid re-using temps when an inline is expanded in
                   10991: //     more than one other inline that is then called in the
                   10992: //     same expression
                   10993: //
                   10994: {
                   10995:        if (vn[0]!='_' || vn[1]!='_' || vn[2]!='X') {
                   10996:                unsigned long a = (unsigned long) fn->tp;
                   10997: 
                   10998:                // al = the number of radix-32 chars in a
                   10999:                unsigned long aa = a;
                   11000:                int al = 0;
                   11001:                while (aa) {
                   11002:                        al++;
                   11003:                        aa >>= 5;
                   11004:                }
                   11005: 
                   11006:                // allocate memory for the result
                   11007:                int ll = strlen(vn);
                   11008:                char* s = new char[ll+al+8];
                   11009:                register char* p = s;
                   11010: 
                   11011:                // append _ _ X vn
                   11012:                *p++ = '_';
                   11013:                *p++ = '_';
                   11014:                *p++ = 'X';
                   11015:                strcpy(p,vn);
                   11016:                p += ll;
                   11017:                *p++ = '0';
                   11018:                *p++ = '0';
                   11019: 
                   11020:                // append representation of `a'
                   11021:                while (a) {
                   11022:                        *p++ = "abcdefghijklmnopqrstuvwxyz012345"[a&037];
                   11023:                        a >>= 5;
                   11024:                }
                   11025: 
                   11026:                // append scope representation and trailing null
                   11027:                *p++ = 'a' + ((int(Scope)>>4)&15);
                   11028:                *p++ = 'a' + ((int(Scope)>>8)&15);
                   11029:                *p = '\0';
                   11030: //tmp error('d',"temp(%s,%n) -- scope %d -- returning %s",vn,fn,scope,s);
                   11031:                return s;
                   11032:        }
                   11033:        else {
                   11034: //tmp error('d',"temp(%s,%n) -- scope %d -- returning %s",vn,fn,scope,vn);
                   11035:                return vn;
                   11036:        }
                   11037: 
                   11038: }
                   11039: 
                   11040: Pname dcl_local(Ptable scope, Pname an, Pname fn)
                   11041: {
                   11042:        if (scope == 0 || scope->base == 0) {
                   11043:                if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0);
                   11044:                scope = sti_tbl;
                   11045:        //      error('s',"cannot expand inlineF needing temporaryV in nonF context");
                   11046:        //      return an;
                   11047:        }
                   11048: 
                   11049:        if (an->n_stclass == STATIC) {
                   11050:                if (an->tp->base!=FCT) error('s',&fn->where,"cannot expand inlineF with static%n",an);
                   11051:                return an;
                   11052:        }
                   11053: 
                   11054:        Pname cn = fn->n_table->t_name;
                   11055:        char* s = temp(an->string,fn);
                   11056:        Pname nx = new name(s);
                   11057:        Ptype atp = an->tp;
                   11058: //error('d',"dcl_local(%d,%n,%n) -> %s",scope,an,fn,s);
                   11059:        while (atp->base == TYPE) atp = Pbase(atp)->b_name->tp;
                   11060:        if (atp->base == VEC) {
                   11061:                if (an->n_scope == ARG) {
                   11062:                        Pptr t = new ptr(PTR,Pvec(atp)->typ);
                   11063:                        nx->tp = t;
                   11064:                }
                   11065:                else {
                   11066:                        error('s',&fn->where,"cannot expand inlineF needing temporaryV of vectorT");
                   11067:                        return an;
                   11068:                }
                   11069:        }
                   11070:        else
                   11071:                nx->tp = atp;
                   11072:        PERM(nx->tp);
                   11073: 
                   11074:        nx->n_used = an->n_used;
                   11075:        nx->n_assigned_to = an->n_assigned_to;
                   11076:        nx->n_addr_taken = an->n_addr_taken;
                   11077:        nx->n_xref = an->n_xref;
                   11078: //error('d',"nx %n %t,",nx,nx->tp);
                   11079:        Pname r = scope->look(nx->string,0);
                   11080:        if (r) {
                   11081: //error('d',"ll %n %t",ll,ll->tp);
                   11082:                if (r->tp->check(nx->tp,0))
                   11083:                        error('s',&fn->where,"cannot expand inlineF %n with two local variables with the sameN (%s)",fn,an->string);
                   11084:                else
                   11085:                        r = 0;
                   11086:        }
                   11087:        if (r==0) {
                   11088:                r = scope->insert(nx,0);
                   11089: //error('d',"%d %d %d %d",r->n_stclass,an->n_stclass,r->lex_level,an->lex_level);
                   11090:                r->n_stclass = an->n_stclass;
                   11091:                r->lex_level = an->lex_level;
                   11092:                delete nx;
                   11093:                r->where.line = 0;
                   11094:        }
                   11095:        return r;
                   11096: }
                   11097: 
                   11098: int ck_cast(Ptype t1, Ptype t2)
                   11099: /*
                   11100:        return a value of type t2 from a function returning a t1
                   11101:        return 1 if cast is needed
                   11102: */
                   11103: {
                   11104: st:
                   11105:        while (t1->base == TYPE) t1 = Pbase(t1)->b_name->tp;
                   11106:        while (t2->base == TYPE) t2 = Pbase(t2)->b_name->tp;
                   11107: 
                   11108:        if (t1 == t2) return 0;
                   11109: 
                   11110:        if (t1->base != t2->base) return 1;
                   11111: 
                   11112:        switch (t1->base) {
                   11113:        case RPTR:
                   11114:        case PTR:
                   11115:        {       t1 = Pptr(t1)->typ;
                   11116:                if (t1->base == VOID) return 1;
                   11117:                t2 = Pptr(t2)->typ;
                   11118:                goto st;
                   11119:        }
                   11120:        case CHAR:
                   11121:        case SHORT:
                   11122:        case INT:
                   11123:        case LONG:
                   11124:                if (Pbase(t1)->b_unsigned != Pbase(t2)->b_unsigned) return 1;
                   11125:                break;
                   11126:        case COBJ:
                   11127:        {
                   11128:                Pname nn = Pbase(t1)->b_name;
                   11129: 
                   11130:                if (Pclass(nn->tp)->csu==UNION ) return 0; 
                   11131: 
                   11132:                if (t2->base==COBJ && nn->tp==Pbase(t2)->b_name->tp) return 0;
                   11133: 
                   11134:                return 1;
                   11135:        }
                   11136:        }
                   11137: 
                   11138:        return 0;
                   11139: }
                   11140: 
                   11141: int makeCM( Ptype t )
                   11142: /* return 1 if the type is not a primitive type
                   11143:  * this will cause the generation of (t,0) 
                   11144:  * note: ``t'' is guaranteed not to be 0
                   11145:  */
                   11146: {
                   11147:     while ( t->base == TYPE )
                   11148:        t = Pbase(t)->b_name->tp;
                   11149: 
                   11150:     switch (t->base) {
                   11151:        case FLOAT:
                   11152:        case DOUBLE:
                   11153:        case LDOUBLE:
                   11154:        case CHAR:
                   11155:        case SHORT:
                   11156:        case INT:
                   11157:        case LONG:
                   11158:        case EOBJ:
                   11159:                return 0;
                   11160:        default: 
                   11161:                return 1;
                   11162:        }
                   11163: }
                   11164: 
                   11165: static ret_seen = 0;
                   11166: 
                   11167: Pstmt stmt::expand()
                   11168: /*
                   11169:        copy the statements with the formal arguments replaced by ANAMES 
                   11170: 
                   11171:        called once only per inline function
                   11172:        expand_tbl!=0 if the function should be transformed into an expression
                   11173:        and expand_tbl is the table for local variables
                   11174: */
                   11175: {
                   11176:        if (this == 0) error('i',"0->S::expand() for%n",expand_fn);
                   11177:        Pstmt ostmt = Cstmt;
                   11178:        if ( where.line ) Cstmt = this;
                   11179: 
                   11180:        if (memtbl) {   /* check for static variables */
                   11181:                register Ptable t = memtbl;
                   11182:                register int i;
                   11183:                for (register Pname n = t->get_mem(i=1); n; n=t->get_mem(++i)) {
                   11184:                        if (n->n_stclass == STATIC) {
                   11185:                                if (n->tp->base == FCT) continue;
                   11186:                                error('s',"cannot expand inlineF with static%n",n);
                   11187:                                n->n_stclass = AUTO;
                   11188:                        }
                   11189:                        n->where.line = 0;
                   11190:                }
                   11191:        }
                   11192: 
                   11193:        if (expand_tbl) {       /* make expression */
                   11194:                Pexpr ee;
                   11195: 
                   11196:                if (memtbl) { // temporaries
                   11197:                        int i;
                   11198:                        for (Pname n=memtbl->get_mem(i=1); n; n=memtbl->get_mem(++i)) {
                   11199: //error('d',"block %n %k %d %d",n,base,memtbl->real_block == this,n->lex_level);
                   11200:                                if (n->base!=NAME || n->tp==any_type) continue;
                   11201: 
                   11202:                                if (base==BLOCK 
                   11203:                                && memtbl->real_block == this 
                   11204:                                && n->lex_level < 2
                   11205:                                && (n->string[0]!='_'   // promoted from called
                   11206:                                                        // inlines
                   11207:                                        || n->string[1]!='_'
                   11208:                                        || (  n->string[2]!='X'
                   11209:                                           && n->string[2]!='K'))
                   11210:                                ) {
                   11211: //error('d',"not promoting%n",n);
                   11212:                                        continue;
                   11213:                                }
                   11214: 
                   11215:                                if (memtbl != scope)
                   11216:                                {
                   11217:                                        Pname nn = dcl_local(scope,n,expand_fn);
                   11218:                                        nn->base = NAME;
                   11219:                                        n->string = nn->string;
                   11220:                                }
                   11221:                                else if (n->tp->base!=FCT && n->tp->base!=OVERLOAD){
                   11222:                                        n->string = temp(n->string, expand_fn);
                   11223:                                        n->where.line = 0;
                   11224:                                }
                   11225:                        }
                   11226:                }
                   11227: 
                   11228:                switch (base) {
                   11229:                default:
                   11230:                        error('s',"cannot expand inlineF%n with %kS in inline",expand_fn,base);
                   11231:                        Cstmt = ostmt;
                   11232:                        return Pstmt(dummy);
                   11233: 
                   11234:                case BLOCK:
                   11235: DB(if(Edebug>=2){error('d',"stmt::expand() -- block");display_stmt(this);});
                   11236:                        if (s_list) {
                   11237:                                ee = Pexpr(s_list->expand());
                   11238:                                if (s) {
                   11239:                                        ee = new expr(CM, Pexpr(s->expand()), ee);
                   11240:                                        ee->tp = ee->e2->tp;
                   11241:                                        PERM(ee);
                   11242:                                }
                   11243:                                Cstmt = ostmt;
                   11244:                                return Pstmt(ee);
                   11245:                        }
                   11246: 
                   11247:                        if (s) {
                   11248:                                Pstmt st = s->expand();
                   11249:                                Cstmt = ostmt;
                   11250:                                return st;
                   11251:                        }
                   11252: 
                   11253:                        Cstmt = ostmt;
                   11254:                        return Pstmt(zero);
                   11255: 
                   11256:                case PAIR:
                   11257:                        ee = s2 ? Pexpr(s2->expand()) : 0;
                   11258:                        ee = new expr(CM, s?Pexpr(s->expand()):0, ee);
                   11259:                        ee->tp = ee->e2->tp;
                   11260:                        if (s_list) {
                   11261:                                ee = new expr(CM, ee, Pexpr(s_list->expand()));
                   11262:                                ee->tp = ee->e2->tp;
                   11263:                        }
                   11264:                        PERM(ee);
                   11265:                        Cstmt = ostmt;
                   11266:                        return Pstmt(ee);
                   11267: 
                   11268:                case RETURN:
                   11269:                        ret_seen = 1;
                   11270:                        s_list = 0;
                   11271: 
                   11272:                        if (e == 0) 
                   11273:                                ee = zero;
                   11274:                        else {
                   11275:                                ee = e->expand();
                   11276:                                Ptype tt = Pfct(expand_fn->tp)->returns;
                   11277:                                if (tt == 0) tt = Pfct(expand_fn->tp)->returns;
                   11278: //error('d',"return::expand() -- ee==%k  tt==%t",ee?ee->base:0,tt);
                   11279: //display_expr(ee);
                   11280:                                if (tt!=ee->tp && ck_cast(tt,ee->tp)) ee = new cast(tt,ee);
                   11281:                        }
                   11282:        
                   11283:                        Cstmt = ostmt;
                   11284:                        return Pstmt(ee);
                   11285: 
                   11286:                case SM:
                   11287:                        if (e== 0 || e==dummy)
                   11288:                                ee = zero;
                   11289:                        else {
                   11290:                                if (e->base == DEREF) e = e->e1;
                   11291:                                ee = e->expand();
                   11292:                        }
                   11293:                        // no break;
                   11294: 
                   11295:                case ASM:
                   11296:                        if (s_list) {
                   11297:                                ee = new expr(CM, ee, (Pexpr)s_list->expand());
                   11298:                                ee->tp = ee->e2->tp;
                   11299:                                PERM(ee);
                   11300:                        }
                   11301:                        Cstmt = ostmt;
                   11302:                        return (Pstmt)ee;
                   11303: 
                   11304:                case IF:
                   11305:                {
                   11306:                        int ors = ret_seen;
                   11307:                        ret_seen = 0;
                   11308:                        ee = Pexpr(s->expand());
                   11309:                        if(ee->base==ASSIGN && ee->e1->tp &&
                   11310:                            ee->e1->tp->base != PTR)
                   11311:                                ee = new expr(G_CM,ee,zero);
                   11312:                        Pexpr qq = new expr(QUEST,ee,zero);
                   11313:                        int ret1 = ret_seen;
                   11314:                        ret_seen = 0;
                   11315: 
                   11316:                        qq->cond = e->expand();
                   11317:                        qq->e2 = else_stmt ? Pexpr(else_stmt->expand()) : zero;
                   11318:                        int ret2 = ret_seen; 
                   11319:                        if (ret1+ret2 && s_list) {
                   11320:                                error('s',"cannot expand inlineF%n with S after \"return\"",expand_fn);
                   11321:                                ret_seen = 0;
                   11322:                        }
                   11323:                        ret_seen += ret1;
                   11324:                        ret_seen += ret2;
                   11325:                        ret_seen += ors;
                   11326: 
                   11327:                        // handle ``if (x) class_object_valued_expression;''
                   11328: 
                   11329:                        Ptype t1 = qq->e1->tp;
                   11330:                        Ptype t2 = qq->e2->tp;
                   11331: 
                   11332:        if (t1 && t1->base==FCT)
                   11333:                t1 = Pfct(t1)->s_returns ? Pfct(t1)->s_returns : Pfct(t1)->returns;
                   11334: 
                   11335:        if (t2 && t2->base==FCT)
                   11336:                t2 = Pfct(t2)->s_returns ? Pfct(t2)->s_returns : Pfct(t2)->returns;
                   11337: 
                   11338:                        Pname c1 = t1?t1->is_cl_obj():0;
                   11339:                        Pname c2 = t2?t2->is_cl_obj():0;
                   11340: 
                   11341:                        int z1 = c1 && c1!=c2;
                   11342:                        int z2 = c2 && c1!=c2;
                   11343: 
                   11344: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
                   11345: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
                   11346: //display_expr(qq);
                   11347:                        if (c1==0
                   11348:                        && c2==0
                   11349:                        && t1
                   11350:                        && t2
                   11351:                        && t2->check(t1,ASSIGN)
                   11352:                        && t1->check(t2,ASSIGN)) {
                   11353:                                z1 = makeCM( t1 );
                   11354:                                z2 = makeCM( t2 );
                   11355:                                if ((z1 && ret1) || (z2 && ret2))
                   11356:                                        error('s',"cannot expand inlineF with return in ifS");
                   11357:                        }
                   11358: 
                   11359: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
                   11360: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
                   11361: //display_expr(qq);
                   11362:                        if (t1 && z1==0) {
                   11363:                                // since zero is acceptable to all pointer types
                   11364:                                // we need only ``fix'' z1 and z2 will take care
                   11365:                                // of itself
                   11366:                                z1 = t1->is_ptr_or_ref()
                   11367:                                        && t2
                   11368:                                        && t2->is_ptr_or_ref()
                   11369:                                        && t1->check(t2,0)
                   11370:                                        && !const_problem;
                   11371:                        }
                   11372: 
                   11373: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
                   11374: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
                   11375: //display_expr(qq);
                   11376:                        if (z1) {
                   11377:                                Pexpr v = (z2==0 && (t2->is_ptr_or_ref())) ? new cast(t2,zero) : zero;
                   11378:                                qq->e1 = new expr(CM,qq->e1,v);
                   11379:                                qq->e1->tp = qq->e1->e1->tp;
                   11380:                        }
                   11381: 
                   11382: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
                   11383: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
                   11384: //display_expr(qq);
                   11385:                        if (z2) {
                   11386:                                Pexpr v = (z1==0 && (t1->is_ptr_or_ref())) ? new cast(t1,zero) : zero;
                   11387:                                qq->e2 = new expr(CM,qq->e2,v);
                   11388:                                qq->e2->tp = qq->e2->e1->tp;
                   11389:                        }
                   11390: 
                   11391: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2);
                   11392: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2);
                   11393: //display_expr(qq);
                   11394:                        if (s_list) {
                   11395:                                qq = new expr(CM,qq,Pexpr(s_list->expand()));
                   11396:                                qq->tp = qq->e2->tp;
                   11397:                        }
                   11398:                        else
                   11399:                                qq->tp = qq->e1->tp;
                   11400:                        PERM(qq);
                   11401:                        Cstmt = ostmt;
                   11402:                        return Pstmt(qq);
                   11403:                }
                   11404:                }
                   11405:        }
                   11406: 
                   11407:        where.line = 0;
                   11408: 
                   11409:        switch (base) {
                   11410:        default:
                   11411:                if (e) e = e->expand();
                   11412:                break;
                   11413:        case PAIR:
                   11414:                if (s2) s2 = s2->expand();
                   11415:                break;
                   11416:        case BLOCK:
                   11417:                break;
                   11418:        case FOR:
                   11419:                if (for_init) for_init = for_init->expand();
                   11420:                if (e2) e2 = e2->expand();
                   11421:        case ASM:
                   11422:                break;
                   11423: //     case LABEL:
                   11424: //     case GOTO:
                   11425:        case RETURN:
                   11426: //     case BREAK:
                   11427: //     case CONTINUE:
                   11428:                error('s',"cannot expand inlineF%n with %kS",expand_fn,base);
                   11429:        }
                   11430: 
                   11431:        if (s) s = s->expand();
                   11432:        if (s_list) s_list = s_list->expand();
                   11433:        PERM(this);
                   11434:        Cstmt = ostmt;
                   11435:        return this;
                   11436: }
                   11437: 
                   11438: Pexpr expr::expand()
                   11439: {
                   11440:        if (this == 0) error('i',"E::expand(0)");
                   11441: 
                   11442:        switch (base) {
                   11443:        case NAME:
                   11444:                if (expand_tbl && Pname(this)->n_scope==FCT) {
                   11445:                        Pname n = Pname(this);
                   11446:                        char* s = n->string;
                   11447:                        if (s[0]=='_' && s[1]=='_' && s[2]=='X') break;
                   11448:                        Pname cn = expand_fn->n_table->t_name;
                   11449:                //      n->string = temp(s,expand_fn->string,(cn)?cn->string:0);
                   11450:                        n->string = temp(s,expand_fn);
                   11451:                }
                   11452:        case DUMMY:
                   11453:        case ICON:
                   11454:        case FCON:
                   11455:        case CCON:
                   11456:        case IVAL:
                   11457:        //case FVAL:
                   11458:        //case LVAL:
                   11459:        case STRING:
                   11460:        case ZERO:
                   11461:        case TEXT:
                   11462:        case ANAME:
                   11463:        case MDOT:
                   11464:                break;
                   11465:        case ICALL:
                   11466:                if (expand_tbl && e1==0) {
                   11467:                        int ors = ret_seen;
                   11468:                        ret_seen = 0;
                   11469:                        Pname fn = il->fct_name;
                   11470:                        Pfct f = Pfct(fn->tp);
                   11471:                        if (f->f_expr==0
                   11472:                // f->returns==void_type
                   11473:                //      && f->s_returns!=int_type
                   11474:                //      && fn->n_oper!=CTOR
                   11475:                        )
                   11476:                                error('s',&fn->where,"cannot expand value-returning inline%n with call of non-value-returning inline%n",expand_fn,fn);
                   11477:                //      else
                   11478:                //              error("inline%n called before defined",fn);
                   11479: ret_seen = ors;
                   11480:                }
                   11481:                break;
                   11482:        case SIZEOF:
                   11483:        case CAST:
                   11484:                if (tp2) PERM(tp2);
                   11485:                goto rrr;
                   11486:        case QUEST:
                   11487:                cond = cond->expand();
                   11488:        default:
                   11489:                if (e2) e2 = e2->expand();
                   11490:        case REF:
                   11491:        case DOT:
                   11492:        rrr:
                   11493:                if (e1) e1 = e1->expand();
                   11494:                break;
                   11495:        }
                   11496: 
                   11497:        switch (base) {
                   11498:        case CM:
                   11499:        case G_CM:
                   11500:                if (tp==0) tp=e2->tp;
                   11501:        }
                   11502: 
                   11503:        PERM(this);
                   11504:        return this;
                   11505: }
                   11506: 
                   11507: int nin;
                   11508: 
                   11509: static int watch_out;
                   11510: bit expr::not_simple()
                   11511: /*
                   11512:        is a temporary variable needed to hold the value of this expression
                   11513:        as an argument for an inline expansion?
                   11514:        return 1; if side effect
                   11515:        return 2; if modifies expression
                   11516: */
                   11517: {
                   11518:        int s;
                   11519: //error('d',"not_simple%k",base);
                   11520:        switch (base) {
                   11521:        default:
                   11522:                return 2;
                   11523:        case NAME:
                   11524:                if (nin==0 && Pname(this)->n_table==gtbl) return 2;     // unsafe: aliasing
                   11525:        case ZERO:
                   11526:        case IVAL:
                   11527:        //case FVAL:
                   11528:        case ICON:
                   11529:        case CCON:
                   11530:        case FCON:
                   11531:                return 0;
                   11532:        case STRING:
                   11533:                ::watch_out = 1;
                   11534:                return 0;
                   11535:        case MDOT:
                   11536:                return mem->not_simple();
                   11537:        case SIZEOF:
                   11538:                return (e1==0 || e1==dummy) ? 0 : e1->not_simple();
                   11539:        case G_ADDROF:
                   11540:        case ADDROF:
                   11541:                return e2->not_simple();
                   11542:        case CAST:
                   11543:                return e1->not_simple();
                   11544:        case DOT:
                   11545:                ::watch_out = 1;
                   11546:                return e1->not_simple();
                   11547:        case REF:
                   11548:                ::watch_out = 1;
                   11549:                return e1->not_simple();
                   11550:        case UMINUS:
                   11551:        case NOT:
                   11552:        case COMPL:
                   11553:                return e2->not_simple();
                   11554:        case DEREF:
                   11555:                s = e1->not_simple();
                   11556:                if (1<s) return 2;
                   11557:                if (e2==0) return s;
                   11558:                return s |= e2->not_simple();
                   11559:        case MUL:
                   11560:        case DIV:
                   11561:        case MOD:
                   11562:        case PLUS:
                   11563:        case MINUS:
                   11564:        case LS:
                   11565:        case RS:
                   11566:        case AND:
                   11567:        case OR:
                   11568:        case ER:
                   11569:        case LT:
                   11570:        case LE:
                   11571:        case GT:
                   11572:        case GE:
                   11573:        case EQ:
                   11574:        case NE:
                   11575:        case ANDAND:
                   11576:        case OROR:
                   11577:        case CM:
                   11578:                s = e1->not_simple();
                   11579:                if (1<s) return 2;
                   11580:                return s |= e2->not_simple();
                   11581:        case QUEST:
                   11582:                s = cond->not_simple();
                   11583:                if (1<s) return 2;
                   11584:                s |= e1->not_simple();
                   11585:                if (1<s) return 2;
                   11586:                return s |= e2->not_simple();
                   11587:        case ANAME:
                   11588:                if (curr_icall) {
                   11589:                        Pname n = (Pname)this;
                   11590:                        int argno = int(n->n_val);
                   11591:                        for (Pin il=curr_icall; il; il=il->i_next)
                   11592:                                if (n->n_table == il->i_table) goto aok;
                   11593:                        goto bok;
                   11594:                aok:
                   11595:                        return (il->i_args[argno].local) ? 0 : il->i_args[argno].arg->not_simple();
                   11596:                }
                   11597:        bok:    error('i',"expand aname%n",this);
                   11598:        case G_CM:
                   11599:        case VALUE:
                   11600:        case NEW:
                   11601:        case GNEW:
                   11602:        case CALL:
                   11603:        case G_CALL:
                   11604:        case ICALL:
                   11605:        case ASSIGN:
                   11606:        case INCR:
                   11607:        case DECR:
                   11608:        case ASPLUS:
                   11609:        case ASMINUS:
                   11610:        case ASMUL:
                   11611:        case ASDIV:
                   11612:        case ASMOD:
                   11613:        case ASAND:
                   11614:        case ASOR:
                   11615:        case ASER:
                   11616:        case ASLS:
                   11617:        case ASRS:
                   11618:                return 2;
                   11619:        }
                   11620: }
                   11621: 
                   11622: extern void uninline(Pname fn);
                   11623: //extern Pname new_fct;        
                   11624: //extern Pname del_fct;
                   11625: extern Pstmt del_list;
                   11626: extern Pstmt break_del_list;
                   11627: extern Pstmt continue_del_list;
                   11628: extern Pname curr_fct;
                   11629: extern Pexpr init_list;
                   11630: 
                   11631: extern Pname make_default_ctor(Pclass cl);
                   11632: void expand_itor(Pclass cl)
                   11633: {
                   11634: //error('d',"expand_itor(%t)",cl);
                   11635:        Pexpr s2 = curr_expr;
                   11636:        Pstmt s5 = del_list;
                   11637:        Pstmt s6 = break_del_list;
                   11638:        Pstmt s7 = continue_del_list;
                   11639:        Pname s8 = curr_fct;
                   11640:        Pexpr s9 = init_list;
                   11641:        (void) cl->make_itor(1);
                   11642:        curr_expr = s2;
                   11643:        del_list = s5;
                   11644:        break_del_list = s6;
                   11645:        continue_del_list = s7;
                   11646:        curr_fct = s8;
                   11647:        init_list = s9;
                   11648: }
                   11649: /*
                   11650: extern Pname make_default_dtor(Pclass cl);
                   11651: void expand_dtor(Pclass cl)
                   11652: {
                   11653: //error('d',"expand_itor(%t)",cl);
                   11654:        Pexpr s2 = curr_expr;
                   11655:        Pstmt s5 = del_list;
                   11656:        Pstmt s6 = break_del_list;
                   11657:        Pstmt s7 = continue_del_list;
                   11658:        Pname s8 = curr_fct;
                   11659:        Pexpr s9 = init_list;
                   11660:        (void) make_default_dtor(cl);
                   11661:        curr_expr = s2;
                   11662:        del_list = s5;
                   11663:        break_del_list = s6;
                   11664:        continue_del_list = s7;
                   11665:        curr_fct = s8;
                   11666:        init_list = s9;
                   11667: }
                   11668: 
                   11669: 
                   11670: void expand_ictor(Pclass cl)
                   11671: {
                   11672: //error('d',"expand_itor(%t)",cl);
                   11673:        Pexpr s2 = curr_expr;
                   11674:        Pstmt s5 = del_list;
                   11675:        Pstmt s6 = break_del_list;
                   11676:        Pstmt s7 = continue_del_list;
                   11677:        Pname s8 = curr_fct;
                   11678:        Pexpr s9 = init_list;
                   11679:        (void) make_default_ctor(cl);
                   11680:        curr_expr = s2;
                   11681:        del_list = s5;
                   11682:        break_del_list = s6;
                   11683:        continue_del_list = s7;
                   11684:        curr_fct = s8;
                   11685:        init_list = s9;
                   11686: }
                   11687: */
                   11688: Pexpr fct::expand(Pname fn, Ptable scope, Pexpr ll)
                   11689: /*
                   11690:        expand call to (previously defined) inline function in "scope"
                   11691:        with the argument list "ll"
                   11692:        (1) declare variables in "scope"
                   11693:        (2) initialize argument variables
                   11694:        (3) link to body
                   11695: */
                   11696: {
                   11697:        Scope = scope;
                   11698: //error('d',"expand%s() body %d f_expr %d inline %d",fn->string,body,f_expr,f_inline);
                   11699:        if (f_inline == ITOR) {
                   11700:                Pexpr s1 = last_expanded;
                   11701:                expand_itor(memof);
                   11702:                last_expanded = s1;
                   11703:                last_stmt = stmtno;
                   11704:                this = Pfct(fn->tp);
                   11705:                if (f_inline==0 && f_imeasure) {
                   11706:                        uninline(fn);
                   11707:                        return 0;
                   11708:                }
                   11709:        }
                   11710: 
                   11711: //error('d',"expand %n body %d f_expr %d defined %d",fn,body,f_expr,defined);
                   11712: //error('d',"inline %d memtbl %d scope %d",f_inline,Pfct(fn->tp)->body->memtbl,scope);
                   11713: //display_stmt(body);
                   11714:        if ((body==0 && f_expr==0)                      // before defined
                   11715:        ||  ((defined&SIMPLIFIED)==0)                   // before simplified
                   11716:        ||  (Pfct(fn->tp)->body->memtbl==scope)         // while defining
                   11717:        ||  (f_inline>1)                                // recursive call
                   11718:        ) {                                             // so don't expand
                   11719:                if (warning_opt) error('w',"cannot inline%n in thisE",fn);
                   11720:                if (fn->n_addr_taken++==0) fn->dcl_print(0);
                   11721:                return 0;
                   11722:        }
                   11723: 
                   11724:        if (fn->n_oper==CTOR) {
                   11725:                Pclass cl = Pclass(fn->n_table->t_name->tp);
                   11726:                if (cl->c_body == 3) cl->print_all_vtbls(cl);
                   11727:        }
                   11728: 
                   11729:        Pin il = new iline;
                   11730:        Pexpr ic = new texpr(ICALL,0,0);
                   11731:        int ns = 0;
                   11732:        for (Pname an = f_args; an; an=an->n_list) ns++;
                   11733:        il->fct_name = fn;
                   11734:        il->i_args = new ia[il->i_slots = ns];
                   11735:        ic->il = il;
                   11736:        ic->tp = s_returns ? s_returns : returns;
                   11737: //     Pname at = (f_this) ? f_this : (f_result) ? f_result : argtype;
                   11738:        Pname at = f_args;
                   11739: 
                   11740:        f_inline++;
                   11741: 
                   11742:        if (at) il->i_table = at->n_table;
                   11743:        int i = 0;
                   11744:        int not_simple = 0;     /* is a temporary argument needed? */
                   11745: 
                   11746:        for (Pname n=at; n; n=n->n_list, i++) {
                   11747:                /*      check formal/actual argument pairs
                   11748:                        and generate temporaries as necessary
                   11749:                */
                   11750: 
                   11751:                if (ll == 0) error('i',"F::expand(%n):AX",fn);
                   11752:                Pexpr ee;
                   11753: 
                   11754:                if (ll->base == ELIST) {
                   11755:                        ee = ll->e1;
                   11756:                        ll = ll->e2;
                   11757:                }
                   11758:                else {
                   11759:                        ee = ll;
                   11760:                        ll = 0;
                   11761:                }
                   11762: 
                   11763:                /* could be avoided when expanding into a block */
                   11764:                il->i_args[i].local = 0;
                   11765:                int s ;
                   11766: 
                   11767:        // try to protect agains aliasing through pointers and references
                   11768:        for (Pname m=at; m; m=m->n_list) {
                   11769:                Pptr p;
                   11770:                if (n!=m) {
                   11771:                //      if ((p=m->tp->is_ptr()) || (p=m->tp->is_ref()))
                   11772:                        if (p=m->tp->is_ptr_or_ref())
                   11773:                                if (p->check(n->tp,0)==0 || p->typ->check(n->tp,0)==0) goto zxc;
                   11774: 
                   11775:                }
                   11776:        }
                   11777: 
                   11778:                ::watch_out = 0;
                   11779:                int notsimple; notsimple = ee->not_simple();
                   11780:                if ( notsimple==0 && ::watch_out && n->n_used > 1 ) goto zxc;
                   11781:                if (n->n_assigned_to==FUDGE111
                   11782:                && ee!=zero
                   11783:                && notsimple==0) {
                   11784:                        if (ee && ee->e1 && (ee->e1->base == NAME) &&
                   11785:                               (! strcmp (ee->e1->string,"this"))) goto zxc;
                   11786:                }
                   11787:                else if (n->n_addr_taken || n->n_assigned_to) 
                   11788:                        goto zxc;
                   11789:                else if (s=notsimple) {
                   11790:                        if (/*n->n_used==0      // n_used not set for ``this''
                   11791:                        || */1<s
                   11792:                        || 1<n->n_used ) {      // not safe
                   11793:                zxc:
                   11794:                        if (last_expanded && last_expanded==curr_expr && last_stmt==stmtno) {
                   11795:                                if (warning_opt)
                   11796:                                        error('w',"%n not inlined, called twice in an expression",fn);
                   11797:                                f_inline--;
                   11798:                                delete il->i_args;
                   11799:                                delete il;
                   11800:                                if (fn->n_addr_taken++==0) fn->dcl_print(0);
                   11801:                                return 0;
                   11802:                        }
                   11803: //error('d',"zxc %n %t ee %d %t",n,n->tp,ee->base,ee->tp);
                   11804:                        if (ee && ee->tp && (ee->tp->base==EOBJ) && ansi_opt) 
                   11805:                                ; // do nothing
                   11806:                        else {
                   11807:                                Pname nn = dcl_local(scope,n,fn);
                   11808:                                nn->base = NAME;
                   11809:                                il->i_args[i].local = nn;
                   11810:                                ++not_simple;
                   11811:                        //      if (nn->tp->is_ref()
                   11812:                        //      && ee->tp
                   11813:                        //      && ee->tp->is_ptr_or_ref()==0) ee = ee->address();
                   11814:                        }
                   11815:                        }
                   11816:                }
                   11817: 
                   11818:                il->i_args[i].arg = ee;
                   11819:                il->i_args[i].tp = n->tp;
                   11820:        }
                   11821:        
                   11822:        Ptable tbl = body->memtbl;
                   11823:        if (f_expr) {           // generate comma expression
                   11824:                
                   11825:                char loc_var = 0;
                   11826: 
                   11827:                /* look for local variables needing declaration: */
                   11828:                for (n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i) ) {
                   11829: //error('d',"n %n %d",n,n->base);
                   11830: //error('d',"loc %n %d %d %d",n,n->n_used,n->n_assigned_to,n->n_addr_taken);
                   11831:                        if (n->base==NAME       // don't re-declare the args
                   11832:                        && (n->tp->base!=FCT && n->tp->base!=OVERLOAD)
                   11833:                        && (n->n_used || n->n_assigned_to || n->n_addr_taken)) {
                   11834: if (last_expanded && last_expanded==curr_expr && last_stmt == stmtno) {
                   11835:        if (warning_opt) error('w',"cannot inline%n in thisE",fn);
                   11836:        f_inline--;
                   11837:        delete il->i_args;
                   11838:        delete il;
                   11839:        if (fn->n_addr_taken++==0) fn->dcl_print(0);
                   11840:        return 0;
                   11841: }
                   11842:                                Pname nn = dcl_local(scope,n,fn);
                   11843:                                nn->base = NAME;
                   11844:                                n->string = nn->string;
                   11845: 
                   11846:                                loc_var++;
                   11847:                        }
                   11848:                }
                   11849: 
                   11850:                if (i /*not_simple*/ || loc_var) {
                   11851:                        if(!curr_expr) curr_expr = dummy;
                   11852:                        last_expanded = curr_expr;
                   11853:                        last_stmt = stmtno;
                   11854:                }
                   11855: 
                   11856:                Pexpr ex;
                   11857:                if (not_simple) {
                   11858:                        Pexpr etail = ex = new expr(CM,0,0);
                   11859:                        for (i=0; i<il->i_slots; i++) {
                   11860:                                Pname n = il->i_args[i].local;
                   11861:                                if (n == 0) continue;
                   11862:                                Pexpr e = il->i_args[i].arg;
                   11863:                                        // if used assign
                   11864:                                        // otherwise (e.g. unused argument)
                   11865:                                        // simply evaluate for sideeffects
                   11866:                                if (n->n_used
                   11867:                                || n->n_assigned_to
                   11868:                                || n->n_addr_taken) {
                   11869: Pexpr mptr_assign(Pexpr n, Pexpr in);
                   11870:                                Pptr p1 = n->tp->is_ptr();
                   11871:                                 Pptr p2 = e->tp ? e->tp->is_ptr() : 0;
                   11872:                                if (p1 && p1->memof && p1!=p2) {
                   11873:                                        switch (e->base) {
                   11874:                                        case CM:
                   11875:                                        case G_CM:
                   11876:                                                e->e2 = mptr_assign(n,e->e2);
                   11877:                                                break;
                   11878:                                        case ICALL:
                   11879:                                                break;
                   11880:                                        default:
                   11881:                                                e = mptr_assign(n,e);
                   11882:                                        }
                   11883:                                        etail->e1 = e;
                   11884:                                }
                   11885:                                else
                   11886:                                        etail->e1 = new expr(ASSIGN,n,e);
                   11887:                                }
                   11888:                                else
                   11889:                                        etail->e1 = e;
                   11890:                                if (--not_simple)
                   11891:                                        etail = etail->e2 = new expr(CM,0,0);
                   11892:                                else
                   11893:                                        break;
                   11894:                        }
                   11895:                        etail->e2 = f_expr;
                   11896:                }
                   11897:                else
                   11898:                        ex = f_expr;
                   11899:                ic->e1 = ex;
                   11900:        }
                   11901:        else {          // generate block:
                   11902:                for (n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i) ) {
                   11903:                        // mangle local names
                   11904:                        if (n->base==NAME
                   11905:                        && (n->n_used || n->n_assigned_to || n->n_addr_taken)) {
                   11906:                        //      Pname cn = fn->n_table->t_name;
                   11907:                        //      n->string = temp(n->string,fn->string,(cn)?cn->string:0);
                   11908:                                n->string = temp(n->string,fn);
                   11909:                        }
                   11910:                }
                   11911:                Pstmt ss;
                   11912:                if (not_simple) {
                   11913:                        if(!curr_expr) curr_expr = dummy;
                   11914:                        last_expanded = curr_expr;
                   11915:                        last_stmt = stmtno;
                   11916:                        Pstmt st = new estmt(SM,curloc,0,0);
                   11917:                        st->where.line = 0;
                   11918:                        Pstmt stail = st;
                   11919:                        for (i=0; i<il->i_slots; i++) {
                   11920:                                Pname n = il->i_args[i].local;
                   11921:                                if (n == 0) continue;
                   11922:                                Pexpr e = il->i_args[i].arg;
                   11923:                                Pptr p1 = n->tp->is_ptr();
                   11924:                                Pptr p2 = e->tp->is_ptr();
                   11925:                                Pexpr mptr_assign(Pexpr n, Pexpr in);
                   11926:                                if (p1 && p1->memof && p1!=p2) {
                   11927:                                        switch (e->base) {
                   11928:                                        case CM:
                   11929:                                        case G_CM:
                   11930:                                                e->e2 = mptr_assign(n,e->e2);
                   11931:                                                break;
                   11932:                                        default:
                   11933:                                                e = mptr_assign(n,e);
                   11934:                                        }
                   11935:                                        stail->e = e;
                   11936:                                }
                   11937:                                else
                   11938:                                        stail->e = new expr(ASSIGN,n,e);
                   11939:                                if (--not_simple) {
                   11940:                                        stail = stail->s_list = new estmt(SM,curloc,0,0);
                   11941:                                        stail->where.line = 0;
                   11942:                                }
                   11943:                                else
                   11944:                                        break;
                   11945:                        }
                   11946:                        stail->s_list = body;
                   11947:                        ss = new block(curloc,0,st);
                   11948:                        ss->where.line = 0;
                   11949:                }
                   11950:                else
                   11951:                        ss = body;
                   11952:                ic->e2 = Pexpr(ss);
                   11953:        }
                   11954: 
                   11955:        f_inline--;
                   11956: //error('d',"expand%n -- returning%k", fn, ic?ic->base:0);
                   11957: //display_expr(ic);
                   11958:        return ic;
                   11959: }
                   11960: 0707071010112044261004440001630000160000010177000466055400600000700000116316expr.c/*ident     "@(#)ctrans:src/expr.c  1.8" */
                   11961: /***************************************************************************
                   11962: 
                   11963:        C++ source for cfront, the C++ compiler front-end
                   11964:        written in the computer science research center of Bell Labs
                   11965: 
                   11966:        Copyright (c) 1984 AT&T, Inc. All rights Reserved
                   11967:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   11968: 
                   11969: expr.c:
                   11970: 
                   11971:        type check expressions
                   11972: 
                   11973: ************************************************************************/
                   11974: 
                   11975: #include "cfront.h"
                   11976: #include "size.h"
                   11977: 
                   11978: int const_save;
                   11979: int const_ptr;
                   11980: extern Ptype Pfct_type;
                   11981: 
                   11982: Pexpr expr::address()
                   11983: {
                   11984: // error('d',"address %k %d %s",base,base,base==NAME||base==ANAME?string:"?");
                   11985: // error('d',"address e1 %d %k e2 %d %k", e1, e1?e1->base:0, e2, e2?e2->base:0); 
                   11986:        switch (base) {
                   11987:        case DEREF:
                   11988:                if (e2 == 0) return e1;                 // &*e  => e
                   11989:                break;
                   11990:        case QUEST:                                     // &(a?b:c) => a?&b:&c
                   11991:                e1 = e1->address();
                   11992:                // no break;
                   11993:        case G_CM:
                   11994:                if ( e1 && e1->base == G_CALL &&
                   11995:                        e2 && e2->base == G_ADDROF)
                   11996:                        return this;
                   11997:        case CM:
                   11998:                e2 = e2->address();                     // &(e1,e2) => (e1,&e2)
                   11999:                tp = e2->tp;    //LLL
                   12000:                return this;
                   12001:        case INCR:
                   12002:        case DECR:                                      // &(++a) => (++a,&a)
                   12003:                if (e1) break;
                   12004:                nin++;
                   12005:                if (e2->not_simple()) error('s',"& of%k",base);
                   12006:                nin--;
                   12007:                e1 = new expr(base,0,e2);
                   12008:                e2 = e2->address();
                   12009:                base = G_CM;
                   12010:                tp = e2->tp;
                   12011:                return this;
                   12012:        case ASSIGN:                                    // &(a=b) => ((a=b),&a)
                   12013:        case ASPLUS:
                   12014:        case ASMINUS:
                   12015:        case ASMUL:
                   12016:        case ASDIV:
                   12017:        case ASMOD:
                   12018:        case ASAND:
                   12019:        case ASOR:
                   12020:        case ASER:
                   12021:        case ASLS:
                   12022:        case ASRS:
                   12023:                nin++;
                   12024:                if (e1->not_simple()) error('s',"& of%k",base);
                   12025:                nin--;
                   12026:                Pexpr a = new expr(base,e1,e2);
                   12027:                a->tp = a->e1->tp;
                   12028:                base = G_CM;
                   12029:                e1 = a;
                   12030:                e2 = a->e1->address();
                   12031:                tp = e2->tp;
                   12032:                return this;
                   12033: 
                   12034:        case NAME:
                   12035:                if (Pname(this)->n_stclass == REGISTER) error("& register%n",Pname(this));
                   12036:                Pname(this)->take_addr();
                   12037:                break;
                   12038:        case CALL:
                   12039:        case CAST:
                   12040:        case NEW:
                   12041:        case GNEW:
                   12042:                if (tp && tp->is_ptr_or_ref()) {        // hack?
                   12043:                        return this;
                   12044:                }
                   12045:                break;
                   12046:        }
                   12047: 
                   12048:        register Pexpr ee = new expr(G_ADDROF,0,this);
                   12049:        if (tp) {                                       // tp==0 ???
                   12050:                ee->tp = tp->addrof();
                   12051: 
                   12052:                switch (tp->base) {
                   12053:                case PTR:
                   12054:                        Pptr(ee->tp)->memof = Pptr(tp)->memof;
                   12055:                        break;
                   12056:                case FCT:
                   12057:                        if (Pfct(tp)->f_static==0)
                   12058:                        Pptr(ee->tp)->memof = Pfct(tp)->memof;
                   12059:                        break;
                   12060:                case OVERLOAD:
                   12061:                        if (Pfct(Pgen(tp)->fct_list->f->tp)->f_static==0)
                   12062:                        Pptr(ee->tp)->memof = Pfct(Pgen(tp)->fct_list->f->tp)->memof;
                   12063:                }
                   12064:        }
                   12065: 
                   12066:        return ee;
                   12067: }
                   12068: 
                   12069: Pexpr expr::contents()
                   12070: {
                   12071: //error('d',"deref %k %d %t",base,base,tp);
                   12072: //     if (base==ADDROF || base==G_ADDROF) return e2;          // *&
                   12073:        switch (base) {
                   12074:        case ADDROF:
                   12075:        case G_ADDROF:
                   12076:                return e2;              // *&
                   12077:        case ELIST:
                   12078: //error('d',"contents of  elist");
                   12079:                e1 = e1->contents();
                   12080:                tp = e1->tp;
                   12081:                return this;
                   12082:        };
                   12083: 
                   12084:        register Pexpr ee = new expr(DEREF,this,0);
                   12085:        if (tp) {                       // tp==0 ???
                   12086:                Ptype tt = tp;
                   12087:                while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp;
                   12088:                ee->tp = Pptr(tt)->typ;
                   12089:                Pname cn = ee->tp->is_cl_obj();
                   12090:                if (cn) {
                   12091:                        Pclass cl = Pclass(cn->tp);
                   12092:                        if (cl->c_body==1) cl->dcl_print(0);    // look for first use of cl
                   12093:                }
                   12094:        }
                   12095:        return ee;
                   12096: }
                   12097: 
                   12098: static Pexpr 
                   12099: make_postfix( Pexpr op ) 
                   12100: { // apply the postfix form of increment/decrement operator
                   12101:        Pexpr e = op->e1->base==NAME?op->e1:op->e1->mem;
                   12102:        for (Plist fl=Pgen(e->tp)->fct_list;fl; fl=fl->l) {
                   12103:                Pname n = fl->f;
                   12104:                Pfct f = Pfct(n->tp);
                   12105:                if ((f->nargs==1 && f->f_this) ||
                   12106:                    (f->nargs==2 && f->f_this==0)) {
                   12107: 
                   12108:                        if (op->e1->base == NAME) {
                   12109:                                op->e1 = n;     
                   12110:                                op->e2->e2 = new expr(ELIST,zero,0);
                   12111:                        } else {
                   12112:                                op->e1->mem = n;  
                   12113:                                op->e2 = new expr(ELIST,zero,0); 
                   12114:                        }
                   12115: 
                   12116:                        op->fct_name = n; 
                   12117:                        n->dcl_print(0); 
                   12118:                        return op;
                   12119:                }
                   12120:        }
                   12121:        error('w',"no postfix instance of%n, although overloaded",Pname(e));
                   12122:        return op; // as it were
                   12123: }
                   12124: 
                   12125: int bound;
                   12126: int chars_in_largest;  // no of characters in largest int
                   12127: static Pclass mpglob;
                   12128: 
                   12129: Pexpr expr::typ(Ptable tbl)
                   12130: /*
                   12131:        find the type of "this" and place it in tp;
                   12132:        return the typechecked version of the expression:
                   12133:        "tbl" provides the scope for the names in "this"
                   12134: */
                   12135: {
                   12136:        //if (this == 0) error('i',"0->expr::typ");
                   12137:        Pname n;
                   12138:        Ptype t = 0;
                   12139:        Ptype t1, t2;
                   12140:        TOK b = base;
                   12141:        TOK r1, r2;
                   12142: #define nppromote(b)   t=np_promote(b,r1,r2,t1,t2,1)
                   12143: #define npcheck(b)     (void)np_promote(b,r1,r2,t1,t2,0)
                   12144:        if (tbl->base != TABLE) error('i',"expr::typ(%d)",tbl->base);
                   12145: 
                   12146:        DB( if(Tdebug>=1) {
                   12147:                error('d',"%d->expr::typ(%d) %k %t",this,tbl,b,tp);
                   12148:                display_expr(this);
                   12149:        });
                   12150: // error('d',"%k->typ %n tp: %t", b,b==NAME?this:0,tp);
                   12151: // error('d',"     e1 %d %k e1 %d %k",e1,e1?e1->base:0,e2,e2?e2->base:0);
                   12152: 
                   12153:        if (tp) {
                   12154:                switch (b) {
                   12155:                case NAME:
                   12156: //??                   Pname(this)->use();
                   12157:                        break;
                   12158:                case MDOT:
                   12159:                        mem = mem->typ(tbl);
                   12160:                }       ;
                   12161:        //      if (b == NAME) Pname(this)->use();
                   12162:                return this;
                   12163:        }
                   12164: 
                   12165: extern Pname Ntmp;
                   12166: 
                   12167:        switch (b) {            // is it a basic type
                   12168:        case MDOT:
                   12169:                error('i',"mdot %s",string2);
                   12170:        case DUMMY:
                   12171:                error("emptyE");
                   12172:                tp = any_type;
                   12173:                return this;
                   12174: 
                   12175:        case ZERO:
                   12176:                tp = zero_type;
                   12177:                return this;
                   12178: 
                   12179:        case IVAL:
                   12180:                tp = int_type;
                   12181:                return this;
                   12182: 
                   12183:        //case FVAL:
                   12184:        //      tp = float_type;
                   12185:        //      return this;
                   12186: 
                   12187:        case ICON:
                   12188:                /*      is it long?
                   12189:                        explicit long?
                   12190:                        decimal larger than largest signed int
                   12191:                        octal or hexadecimal larger than largest unsigned int
                   12192:                 */
                   12193:        {       int ll = strlen(string);
                   12194:                switch (string[ll-1]) {
                   12195:                case 'l':
                   12196:                case 'L':
                   12197:                        switch (string[ll-2]) {
                   12198:                        case 'u':
                   12199:                        case 'U':
                   12200:                                string[ll-2] = 0;
                   12201:                                tp = ulong_type;
                   12202:                                goto cast_n_save;
                   12203:                        }
                   12204:                lng:
                   12205:                        tp = long_type;
                   12206:                        goto save;
                   12207:                case 'u':
                   12208:                case 'U':                       // 1u => unsigned(1)
                   12209:                        switch (string[ll-2]) {
                   12210:                        case 'l':
                   12211:                        case 'L':
                   12212:                                string[ll-2] = 0;
                   12213:                ulng:
                   12214:                                tp = ulong_type;
                   12215:                                goto cast_n_save;
                   12216:                        default:
                   12217:                                string[ll-1] = 0;
                   12218:                uint:
                   12219:                                tp = uint_type;
                   12220:                                goto cast_n_save;
                   12221:                        }
                   12222:                }
                   12223: 
                   12224:                // no suffix - see if we can figure it out
                   12225:                if  (string[0] == '0') {        // assume 8 bits in byte
                   12226:                        register index = 1;
                   12227:                        switch (string[1]) {
                   12228:                        case 'x':
                   12229:                        case 'X':
                   12230:                                while(string[++index]=='0') ;
                   12231:                                ll -= index;
                   12232:                                int HSZ = SZ_INT+SZ_INT;
                   12233:                                if(ll < HSZ) goto nrm;
                   12234:                                if(ll == HSZ)
                   12235:                                        if(string[2]>='8') goto uint;
                   12236:                                        else goto nrm;
                   12237:                                if(SZ_INT==SZ_LONG) break;
                   12238:                                HSZ = SZ_LONG+SZ_LONG;
                   12239:                                if(ll < HSZ) goto lng;
                   12240:                                if(ll == HSZ)
                   12241:                                        if(string[2]>='8') goto ulng;
                   12242:                                        else goto lng;
                   12243:                                break;
                   12244:                        default:   // OCTAL
                   12245:                                register IBITS = BI_IN_BYTE*SZ_INT;
                   12246:                                while(string[index]=='0') index++;
                   12247:                                register char x = string[index];
                   12248:                                int lbt = x=='1' ? 1 :
                   12249:                                        ( x=='2' || x=='3' ? 2 : 3 );
                   12250:                                int nbits = (ll-index-1)*3 + lbt;
                   12251:                                if(nbits < IBITS) goto nrm;
                   12252:                                if(nbits == IBITS) goto uint;
                   12253:                                if(nbits < BI_IN_BYTE*SZ_LONG) goto lng;
                   12254:                        }
                   12255:                        goto ulng;
                   12256:                }
                   12257:                else {  // DECIMAL
                   12258:                        if (ll<chars_in_largest) {
                   12259:                nrm:
                   12260:                                tp = int_type;
                   12261:                                goto save;
                   12262:                        }
                   12263:                        if (ll>chars_in_largest) {
                   12264:                                if(SZ_INT==SZ_LONG || ll>2*chars_in_largest)
                   12265:                                        goto ulng;
                   12266:                                goto lng;
                   12267:                        }
                   12268:                        // ll == chars_in_largest
                   12269:                        char* p = string;
                   12270:                        char* q = LARGEST_INT;
                   12271:                        do if (*p>*q) {
                   12272:                                if(SZ_INT==SZ_LONG) goto ulng;
                   12273:                                goto lng; 
                   12274:                        } while (*p++==*q++ && *p);
                   12275:                }
                   12276: 
                   12277:                goto nrm;
                   12278:        }
                   12279:        case CCON:
                   12280:                tp = c_strlen(string)<5 ? char_type : int_type; // stored as 'a'
                   12281:                goto save;
                   12282: 
                   12283:        case FCON:
                   12284:        {       int ll = strlen(string);
                   12285:                int last = string[ll-1];
                   12286:                tp = double_type;
                   12287:                if (last=='F' || last=='f') {
                   12288:                        tp = float_type;
                   12289:                        if (!ansi_opt) {
                   12290:                                string[ll-1] = 0;
                   12291:                                goto cast_n_save;
                   12292:                        }
                   12293:                }
                   12294:                else if (last=='L' || last=='l') {
                   12295:                        if (ansi_opt == 0) string[ll-1] = 0;
                   12296:                        tp = ldouble_type;
                   12297:                }
                   12298:                goto save;
                   12299:        }
                   12300:        case STRING:                    // type of "as\tdf" is char[6]
                   12301:                                        // c_strlen counts the terminating '\0'
                   12302:        {       Pvec v = new vec(char_type,0);
                   12303:                v->size = c_strlen(string);
                   12304:                tp = v;
                   12305:        }
                   12306:        save:
                   12307:                if (const_save) {       // "as\tdf" needs 7 chars for storage
                   12308:                        char* p = new char[strlen(string)+1];
                   12309:                        strcpy(p,string);
                   12310:                        string = p;
                   12311:                }
                   12312: 
                   12313:                return this;
                   12314: 
                   12315:        cast_n_save:
                   12316:                if (const_save) {       // "as\tdf" needs 7 chars for storage
                   12317:                        char* p = new char[strlen(string)+1];
                   12318:                        strcpy(p,string);
                   12319:                        string = p;
                   12320:                }
                   12321:                
                   12322:                return new cast(tp,this);
                   12323: 
                   12324:        case THIS:
                   12325:                delete this;
                   12326:                if (cc->c_this) {
                   12327:                        cc->c_this->use();
                   12328:                        return cc->c_this;
                   12329:                }
                   12330:                error("``this'' used in nonC context");
                   12331:                n = new name("this");
                   12332:                n->tp = any_type;
                   12333:                return tbl->insert(n,0); 
                   12334: 
                   12335:        case NAME:
                   12336:        {       
                   12337:                Pname q = Pname(this)->n_qualifier; // suppress virtual iff x::
                   12338:                Pexpr ee = find_name(Pname(this),cc->cot,tbl,0,cc->nof);
                   12339:                if (q && (ee->base==REF || ee->base==DOT))
                   12340:                        ee->n_initializer = Pexpr(q);
                   12341: //error('d',"ee %k %t %n",ee->base,ee->tp,ee->base==NAME?ee:ee->base==REF?ee->mem:0);
                   12342:        //      if (ee->tp->base == RPTR) return ee->contents();
                   12343:                if (ee->tp->is_ref()) return ee->contents();
                   12344: 
                   12345:                if (ee->base==NAME && Pname(ee)->n_xref) {
                   12346:                // fudge to handle X(X&) args
                   12347:                        ee = new expr(DEREF,ee,0);
                   12348:                        ee->tp = ee->e1->tp;    // !!
                   12349:                }
                   12350: 
                   12351:                return ee;
                   12352:        }
                   12353: 
                   12354:        case ADDROF:
                   12355:        case G_ADDROF:  // handle lookup for &s::i
                   12356:                mpglob = 0;
                   12357:                if (e2->base == NAME) e2 = find_name(Pname(e2),cc->cot,tbl,ADDROF,cc->nof);
                   12358:                if (e2->base==NAME && Pname(e2)->n_xref) {
                   12359:                        // fudge to handle X(X&) args
                   12360:                        e2 = new expr(DEREF,e2,0);
                   12361:                        e2->tp = e2->e1->tp;    // !!
                   12362:                }
                   12363:                if (e2->base==DOT) {    // &f().x  = > &(tmp=f(),&tmp)->x
                   12364:                        switch (e2->e1->base) {
                   12365:                        case CALL:
                   12366:                        case G_CALL:
                   12367:                        case VALUE:
                   12368:                                error("& non-lvalue");
                   12369:                        }
                   12370:                }
                   12371:                break;
                   12372: 
                   12373:        case SIZEOF:
                   12374:                if (tp2) {      
                   12375:                        tp2->dcl(tbl);
                   12376:                        switch (tp2->base) {
                   12377:                        case VOID:
                   12378:                                error("sizeof(void)");
                   12379:                                break;
                   12380:                        case CLASS:
                   12381:                        {
                   12382:                                Pclass cl = Pclass(tp2);
                   12383:                                if (cl->c_body==1
                   12384:                                && (cl->defined&(DEFINED|SIMPLIFIED)) == 0) 
                   12385:                                        error('s',"class defined within sizeof");
                   12386:                        }
                   12387:                        }
                   12388:        
                   12389:                        if (e1 && e1!=dummy) {
                   12390:                                e1 = e1->typ(tbl);
                   12391:                                DEL(e1);
                   12392:                                e1 = dummy;
                   12393:                        }
                   12394:                        Pptr r = tp2->is_ref();
                   12395:                        if (r) tp2 = r->typ;    // sizeof(T&)==sizeof(T)
                   12396:                }
                   12397:                else if (e1 == dummy) {
                   12398:                        error("sizeof emptyE");
                   12399:                        tp = any_type;
                   12400:                        return this;
                   12401:                }
                   12402:                else {
                   12403:                        e1 = e1->typ(tbl);
                   12404:                        tp2 = e1->tp;
                   12405:                        if(tp2->base == VEC) tp2->permanent = 1;
                   12406:                        if (e1->base==ILIST)    // PtoM
                   12407:                                e1 = dummy;
                   12408:                        else if (tp2 == char_type)      // sizeof ('a')
                   12409:                                e1 = dummy;
                   12410:                }
                   12411:                (void) tp2->tsizeof();
                   12412:                tp = size_t_type;
                   12413:                return this;
                   12414: 
                   12415:        case CAST:
                   12416: //             return docast(tbl);
                   12417: 
                   12418:        {       Pexpr ee = docast(tbl);
                   12419:                return ee->tp->is_ref() ? ee->contents() : ee;
                   12420:        }
                   12421: 
                   12422: 
                   12423:        case VALUE:
                   12424:                 if ( tp2->base == COBJ || tp2->base == EOBJ) {
                   12425:                         char *s = Pbase(tp2)->b_name->string;
                   12426:                         //Pname tn = gtbl->look( s, 0 );
                   12427:                        //??? non type name apparently takes precedence
                   12428:                        //    Don't use global ftn if it hides local
                   12429:                        //    class ctor.  (Note: More info is needed
                   12430:                        //    to detect all cases.)
                   12431:                         Pname tn = tbl->look( s, 0 );
                   12432: //error( 'd', "tn: %n %t lex_levels: %d %d", tn, tn?tn->tp:0, tn?tn->lex_level:0, Pbase(tp2)->b_name->lex_level );
                   12433:                        if ( tn && tn->n_qualifier == 0
                   12434:                        &&   tn->lex_level == Pbase(tp2)->b_name->lex_level
                   12435:                        &&   (tn->tp->base==FCT || tn->tp->base==OVERLOAD)) 
                   12436:                        {
                   12437:                                 Pexpr et = new expr( CALL, tn, e1 );
                   12438:                                 *this = *et;
                   12439:                                 b = CALL;
                   12440:                                 break;
                   12441:                        }
                   12442:                }
                   12443:                return dovalue(tbl);
                   12444: 
                   12445:        case NEW:
                   12446:        case GNEW:
                   12447:                return donew(tbl);
                   12448: 
                   12449:        case DELETE:    // delete e1 OR delete[e2] e1
                   12450:        case GDELETE:
                   12451:        {       int i;
                   12452:                if (e1->base == ADDROF) error('w',"delete &E");
                   12453:                e1 = e1->typ(tbl);
                   12454:                i = e1->tp->num_ptr(DELETE);
                   12455:                if (i != 'P') error("nonP deleted");
                   12456:                if (e2) {
                   12457:                        e2 = e2->typ(tbl);
                   12458:                        e2->tp->integral(DELETE);
                   12459:                }
                   12460:                tp = void_type;
                   12461:                return this;
                   12462:        }
                   12463: 
                   12464:        case ILIST:     /* an ILIST is pointer to an ELIST */
                   12465:                e1 = e1->typ(tbl);
                   12466:                tp = any_type;
                   12467:                return this;
                   12468: 
                   12469:        case ELIST:
                   12470:        {       Pexpr e;
                   12471:                Pexpr ex;
                   12472: 
                   12473:                if (e1 == dummy && e2==0) {
                   12474:                        error("emptyIrL");
                   12475:                        tp = any_type;
                   12476:                        return this;
                   12477:                }
                   12478:                                
                   12479:                for (e=this; e; e=ex) {
                   12480:                        Pexpr ee = e->e1;
                   12481: //error('d',"e %d %d ee %d %d",e,e?e->base:0,ee,ee?ee->base:0);
                   12482:                        if (e->base != ELIST) error('i',"elist%k",e->base);
                   12483:                        if (ex = e->e2) {       /* look ahead for end of list */
                   12484:                                if (ee == dummy) error("EX in EL");
                   12485:                                if (ex->e1 == dummy && ex->e2 == 0) {
                   12486:                                        /* { ... , } */
                   12487:                                        DEL(ex);
                   12488:                                        e->e2 = ex = 0;
                   12489:                                }
                   12490:                        }
                   12491:                        e->e1 = ee->typ(tbl);
                   12492:                        t = e->e1->tp;
                   12493:                        if (t->base == FCT) {   // yuk!
                   12494:                                ee = new expr(G_ADDROF,0,e->e1);
                   12495:                                e->e1 = ee->typ(tbl);
                   12496:                                t = e->e1->tp;
                   12497:                        }
                   12498:                }
                   12499:                tp = t;
                   12500:                return this;
                   12501:        }
                   12502: 
                   12503:        case DOT:
                   12504:        case REF:
                   12505:        {       if (e2) { // *. or ->*
                   12506:                        if (b == REF) b = base = REFMUL;
                   12507:                        break;
                   12508:                }
                   12509: 
                   12510:                Pbase b;
                   12511: 
                   12512:                e1 = e1->typ(tbl);
                   12513:                t = e1->tp;
                   12514: 
                   12515:                // check that . (->) is applied to class object (pointer)
                   12516:                if (base == REF) {
                   12517:                xxx:
                   12518:                        switch (t->base) {
                   12519:                        case TYPE:
                   12520:                                t = Pbase(t)->b_name->tp;
                   12521:                                goto xxx;
                   12522:                        case COBJ:
                   12523:                        {       Pname n = Pclass(Pbase(t)->b_name->tp)->has_oper(REF);
                   12524:                                if (n) {
                   12525:                                        n->n_used += 2;
                   12526:                                        e1 = new call(new ref(DOT,e1,n),0);
                   12527:                                        return typ(tbl);
                   12528:                                }
                   12529:                                // no break;
                   12530:                        }
                   12531:                        default:
                   12532:                                error("nonP ->%n",mem);
                   12533:                                t = any_type;
                   12534:                                // no break;
                   12535:                        case ANY:
                   12536:                                goto qqq;
                   12537:                        case PTR:
                   12538:                        case VEC:
                   12539:                                b = Pbase(Pptr(t)->typ);
                   12540:                        }
                   12541:                }
                   12542:                 else {  // base == DOT
                   12543:                qqq:
                   12544:                        switch (t->base) {
                   12545:                        case TYPE:      t = Pbase(t)->b_name->tp;       goto qqq;
                   12546:                        default:        error("nonO .%n",mem); t = any_type;
                   12547:                        case ANY:
                   12548:                        case COBJ:      break;
                   12549:                        }
                   12550: //error('d',"dot %k",e1->base);
                   12551:                        switch (e1->base) { 
                   12552:                        case QUEST:
                   12553:                        case ASSIGN:
                   12554:                        case INCR:
                   12555:                        case DECR:
                   12556:                        case ASPLUS:
                   12557:                        case ASMINUS:
                   12558:                        case ASMUL:
                   12559:                        case ASDIV:
                   12560:                        case ASMOD:
                   12561:                        case ASAND:
                   12562:                        case ASOR:
                   12563:                        case ASER:
                   12564:                        case ASLS:
                   12565:                        case ASRS:
                   12566:                        case CM:
                   12567:                        case G_CM:
                   12568:                                base = REF;
                   12569:                                e1 = e1->address();
                   12570:                                break;
                   12571:                         case CALL:
                   12572:                         case G_CALL:
                   12573: //error('d'," f().  %n mem->tp %t",e1->fct_name,mem->tp);
                   12574: #ifdef FDOTRIGHT
                   12575: // this rewrite is only necessary on machines with broken C compilers
                   12576: // there seems to be a lot of those
                   12577: // and for inlines (a,b).c
                   12578:                         if (e1->fct_name && Pfct(e1->fct_name->tp)->f_inline)
                   12579: #endif
                   12580:                         {       // f(). => (tmp=f(),&tmp)->
                   12581:                                 Pname tmp = make_tmp('Q',e1->tp,tbl);
                   12582: //error('d',"fdot2 %k",e1->base);
                   12583:                                 e1 = init_tmp(tmp,e1,tbl);
                   12584:                                 Pexpr aa = tmp->address();
                   12585:                                 e1 = new expr(G_CM,e1,aa);
                   12586:                                 e1->tp = aa->tp;
                   12587:                                 base = REF;
                   12588:                                 break;
                   12589:                         }
                   12590:                         }
                   12591:                        b = Pbase(t);
                   12592:                }
                   12593: 
                   12594:        xxxx:
                   12595:                switch (b->base) {
                   12596:                case TYPE:
                   12597:                        b = Pbase(b->b_name->tp);
                   12598:                        goto xxxx;
                   12599:                default:
                   12600:                        error("(%t) before %k%n (%n not aM)",e1->tp,base,mem,mem);
                   12601:                case ANY:
                   12602:                        tp = any_type;
                   12603:                        return this;
                   12604:                case COBJ:
                   12605:                {       Pclass cl = Pclass(Pbase(b)->b_name->tp);
                   12606:                        if (cl->c_body == 1) cl->dcl_print(0);
                   12607:                        break;
                   12608:                }
                   12609:                }       
                   12610: 
                   12611: /*
                   12612:        x.m is not a const even if x is a const object, this case is handled
                   12613:        by lval() rejecting it
                   12614: */
                   12615: 
                   12616:                if (mem->tp) {
                   12617:                        tp = mem->tp;
                   12618:                        for (Pexpr ee = mem; ee->base==REF; ee = ee->e1) {
                   12619:                                if (ee->e1 == cc->c_this) { // this-> => p->
                   12620:                                        ee->e1 = e1;
                   12621:                                        ee->base = base;
                   12622:                                        return mem->tp->is_ref() ? mem->contents() : mem;
                   12623:                                }
                   12624:                        }
                   12625: 
                   12626:                //      return tp->base==RPTR ? contents() : this;
                   12627:                        return tp->is_ref() ? contents() : this;
                   12628:                }
                   12629: 
                   12630:                
                   12631:                Pname q = Pname(mem)->n_qualifier;
                   12632:                Pexpr e = find_name(Pname(mem),Pclass(b->b_name->tp),0,base,cc->nof);           
                   12633:                if (q && (e->base==REF || e->base==DOT))
                   12634:                        Pname(e)->n_initializer = Pexpr(q);
                   12635: //error('d',"e %k %t %n",e->base,e->tp,e->base==NAME?e:e->base==REF?e->mem:0); 
                   12636: 
                   12637:                for (Pexpr ee = e; ee->base==REF; ee = ee->e1) {
                   12638:                        if (ee->e1 == cc->c_this) { // this-> => p->
                   12639:                                ee->e1 = e1;
                   12640:                                ee->base = base;
                   12641:                                break;
                   12642:                        }
                   12643:                }
                   12644: 
                   12645:                if (e->base == NAME) {
                   12646:                        switch (e->tp->base) {
                   12647:                        case FCT:
                   12648:                        case OVERLOAD:
                   12649:                                mem = e;
                   12650:                                tp = e->tp;
                   12651:                                e = this;
                   12652:                        }
                   12653:                }
                   12654:                        
                   12655:                        // function or static member
                   12656:                return e->tp->is_ref() ? e->contents() : e;
                   12657:        }
                   12658: 
                   12659: //??   case G_CALL:
                   12660:        case CALL:      /* handle undefined function names */
                   12661: //error('d',"call %k %t %k",e1->base,e1->tp,e2?e2->base:0);
                   12662:                if (e1->base==NAME && e1->tp==0) {
                   12663:                        Pname q = Pname(e1)->n_qualifier;
                   12664:                        e1 = find_name(Pname(e1),cc->cot,tbl,CALL,cc->nof);
                   12665: //error('d',"e1 %k %t %n",e1->base,e1->tp,e1->base==NAME?e1:e1->base==REF?e1->mem:0);
                   12666:                        if (q && (e1->base==REF ||e1->base==DOT)) // suppress virtual call
                   12667:                                e1->n_initializer = Pexpr(q);
                   12668:                }
                   12669: 
                   12670:                if (e1->base==NAME && Pname(e1)->n_xref) {
                   12671:                        // fudge to handle X(X&) args
                   12672:                        e1 = new expr(DEREF,e1,0);
                   12673:                        e1->tp = e1->e1->tp;    // !!
                   12674:                }
                   12675: 
                   12676:                switch (e1->base) {
                   12677:                case DOT:
                   12678: /*
                   12679: #ifdef FDOTRIGHT
                   12680:                {
                   12681: //error('d',"fdot1 %k",e1->e1->base);
                   12682:                        switch (e1->e1->base) {
                   12683:                        case CALL:
                   12684:                        case G_CALL:    // f().g() => (tmp=f(),tmp.g())
                   12685:                        {       Pexpr ee = e1->e1;
                   12686:                                Pexpr ex = ee->typ(tbl);
                   12687:                                Pname tmp = make_tmp('Q',ex->tp,tbl);
                   12688:                                ex = init_tmp(tmp,ex,tbl);
                   12689: 
                   12690:                                Pexpr ee2 = new expr(base,e1,e2);
                   12691:                                e1->base = DOT;
                   12692:                                e1->e1 = tmp;
                   12693: 
                   12694:                                base = G_CM;
                   12695:                                e1 = ex;
                   12696:                                e2 = ee2;
                   12697: 
                   12698:                                return typ(tbl);
                   12699:                        }
                   12700:                        }
                   12701:                        break;
                   12702:                }
                   12703: #endif
                   12704: */
                   12705:                case REF:                       // becomes ob.x::~x(0) or
                   12706:                        if (e2==0               // becomes p->x::~x(0)
                   12707:                        && Pref(e1)->mem 
                   12708:                        && Pref(e1)->mem->base==NAME
                   12709:                        && Pname(Pref(e1)->mem)->n_oper==DTOR) {
                   12710:                                e1 = e1->typ(tbl);
                   12711:                                Pexpr ee = call_dtor(e1->e1,Pref(e1)->mem,0,e1->base,one);
                   12712:                                ee->tp = void_type;
                   12713:                                return ee;
                   12714:                        }
                   12715:                }
                   12716:                break;
                   12717: 
                   12718:        case QUEST:
                   12719:                cond = cond->typ(tbl);
                   12720:        case ANDAND:
                   12721:        case OROR:
                   12722:                Ntmp = 0;
                   12723:        }
                   12724: 
                   12725:        if (e1) {
                   12726:                e1 = e1->typ(tbl);
                   12727:                if (e1->tp->is_ref()) e1 = e1->contents();
                   12728:                t1 = e1->tp;
                   12729:        //      if (t1->is_cl_obj()) t1->tsizeof();
                   12730:        }
                   12731:        else
                   12732:                t1 = 0;
                   12733: 
                   12734:        if (e2) {
                   12735:                e2 = e2->typ(tbl);
                   12736:                if (e2->tp->is_ref()) e2 = e2->contents();
                   12737:                t2 = e2->tp;
                   12738:        //      if (t2->is_cl_obj()) t2->tsizeof();
                   12739:        }
                   12740:        else 
                   12741:                t2 = 0;
                   12742: 
                   12743: // error('d',"b %k t1 %t t2 %t",b,t1,t2);
                   12744:        switch (b) {    // filter out non-overloadable operators
                   12745:        default:
                   12746:        {       
                   12747:                Pexpr x = try_to_overload(tbl);
                   12748:                if (x) {
                   12749:                        if (b==INCR || b==DECR) {
                   12750:                                Pexpr fe = x->e1->base==NAME?x->e1:x->e1->mem;
                   12751:                                // by default, prefix version of operator is chosen
                   12752:                                // t2 set ==> ++n, t1 set ==> n++
                   12753:                                if (fe->tp->base==OVERLOAD && t2==0 && t1) 
                   12754:                                        x=make_postfix(x);
                   12755:                        }       
                   12756:                        return x;
                   12757:                }
                   12758: //             if (x) return x;
                   12759: // error('d',"e2: %t t2: %t", e2->tp, t2);
                   12760:                if (t2 && t1==0 && t2!=e2->tp) t2 = e2->tp;
                   12761:        }
                   12762:        case DOT:
                   12763:        case G_CM:
                   12764:        case G_ADDROF:
                   12765:        case G_CALL:
                   12766:        case QUEST:
                   12767:                break;
                   12768:        }
                   12769: 
                   12770:        switch (b) {
                   12771:        case QUEST:
                   12772:        case ANDAND:
                   12773:        case OROR:
                   12774:                if (Ntmp) error('s',"temporary ofC%n with destructor needed in%kE",Ntmp,b);
                   12775:        }
                   12776: 
                   12777:        t = (t1==0) ? t2 : (t2==0) ? t1 : 0;
                   12778: // error('d', "expr::typ t %t", t );
                   12779: // error('d',"b2 %d %k",b,b);
                   12780:        switch (b) {            /* are the operands of legal types */
                   12781:        case REFMUL:
                   12782:                base = REF;
                   12783:                // no break;
                   12784:        case DOT:
                   12785:        {       // a .* p => &a MEMPTR p => appropriate indirection
                   12786:                        // to be considered: what happens if a .* expression
                   12787:                        // is used except in a call/=?
                   12788:                Pexpr a = e1->typ(tbl);
                   12789:                Ptype at = a->tp;
                   12790:                if (base == DOT) {
                   12791:                        a = a->address();
                   12792:                        at = at->addrof();      // beware of n_xref
                   12793:                }
                   12794: 
                   12795:                while (at->base == TYPE) at = Pbase(at)->b_name->tp;
                   12796:                Pname cn = Pptr(at)->typ->is_cl_obj();
                   12797:                Pclass mm = cn ? Pclass(cn->tp) : 0;
                   12798: 
                   12799:                Pexpr p = e2->typ(tbl);
                   12800:                Ptype pt = p->tp;
                   12801:                Pname pcn = pt->is_cl_obj();
                   12802: 
                   12803: //error('d',"mm %t pt %t",mm,pt);
                   12804:                if (pcn) {
                   12805:                        Pclass cl = Pclass(pcn->tp);
                   12806:                        Pname found = 0;
                   12807:                        for (Pname on=cl->conv; on; on=on->n_list) {
                   12808:                                Pfct f = Pfct(on->tp);
                   12809:                                Pptr frt = Pptr(f->returns);
                   12810:                                while (frt->base == TYPE) frt = Pptr(Pbase(frt)->b_name->tp);
                   12811:                                if (frt->base!=PTR || Pptr(frt)->memof==0) break;
                   12812:                                if (Pptr(frt)->memof==mm || mm->has_base(Pptr(frt)->memof)) {
                   12813:                                        if (found)
                   12814:                                                error("two possible conversions forP toM: %n and %n",found,on);
                   12815:                                        else
                   12816:                                                found = on;
                   12817:                                }
                   12818:                        }
                   12819: //error('d',"found %n",found);
                   12820:                        if (found) {
                   12821:                                p = new ref(DOT,p,found);
                   12822:                                p = new call(p,0);
                   12823:                                p = p->typ(tbl);
                   12824:                                pt = p->tp;
                   12825:                        }
                   12826:        
                   12827:                }
                   12828:                while (pt->base == TYPE) pt = Pbase(pt)->b_name->tp;
                   12829:                if (pt->base!=PTR || Pptr(pt)->memof==0) {
                   12830:                        error("P toMX in .*E: %t",pt);
                   12831:                        tp = any_type;
                   12832:                        base = DUMMY;
                   12833:                        return this;
                   12834:                }
                   12835:                Pclass pm = Pptr(pt)->memof;
                   12836: 
                   12837:        //      while (at->base == TYPE) at = Pbase(at)->b_name->tp;
                   12838:        //      Pname cn = Pptr(at)->typ->is_cl_obj();
                   12839:        //      Pclass mm = cn ? Pclass(cn->tp) : 0;
                   12840: //error('d',"mm %t %t %d %d",mm,pm,pm->baseof(mm),mm->has_base(pm));
                   12841: 
                   12842:        //      if (mm!=pm && pm->baseof(mm)==0 && mm->has_base(pm)==0) {
                   12843:                if (mm != pm) {
                   12844:                        if (mm->has_base(pm) == 0) {
                   12845:                                error("badOT in .*E: %t (%s*X)",a->tp,pm->string);
                   12846:                                tp = any_type;
                   12847:                                //return this;
                   12848:                        }
                   12849:                        a = new texpr(CAST,pm->this_type,a);
                   12850:                        e1 = a = a->typ(tbl);
                   12851:                }
                   12852: 
                   12853:                Ptype tpx = Pptr(pt)->typ;
                   12854:                while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp;
                   12855: 
                   12856:                if (tpx->base == FCT) { // a.*p => (&a MEMPTR p)
                   12857:                        base = MEMPTR;
                   12858:                        tp2 = mm;       // keep the class for simpl.c
                   12859:                        e1 = a;
                   12860:                        e2 = p;
                   12861:                }
                   12862:                else {  // a .* p => *(typeof(p))((char*)&a + (int)p-1)
                   12863:                        a = new cast(Pchar_type,a);
                   12864:                        p = new cast(int_type,p);
                   12865:                        p = new expr(MINUS,p,one);
                   12866:                        p->tp = int_type;
                   12867:                        Pexpr pl = new expr(PLUS,a,p);
                   12868:                        pl->tp = Pchar_type;
                   12869:                        base = DEREF;
                   12870:                        pt = new ptr(PTR,tpx);  // need a T* not a T C::*
                   12871:                        Pptr(pt)->rdo = Pptr(tpx)->rdo;
                   12872:                        mpglob = pm;
                   12873:                //      PERM(pt);
                   12874:                        e1 = new cast(pt,pl);
                   12875:                        e2 = 0;
                   12876:                }
                   12877:                tp = tpx;
                   12878:                return tp->is_ref() ? contents() : this;
                   12879:        }
                   12880: 
                   12881:        case G_CALL:
                   12882:        case CALL:
                   12883:                tp = call_fct(tbl);     /* two calls of use() for e1's names */
                   12884:                if (tp->is_ref()) return contents();
                   12885:                return this;
                   12886: 
                   12887:        case DEREF:
                   12888:                if (e1 == dummy) error("O missing before []\n");
                   12889:                if (e2 == dummy) error("subscriptE missing");
                   12890: 
                   12891:                if (t) {        /*      *t      */
                   12892:                        while (t->base == TYPE) t = Pbase(t)->b_name->tp;
                   12893:                //      t->vec_type();
                   12894:                        if (t->base==PTR && Pptr(t)->memof) error("P toM dereferenced");
                   12895:                        tp = t->deref();
                   12896:                }
                   12897:                else {                                  // e1[e2] that is *(e1+e2)
                   12898: //error('d',"deref %t[%t]",t1,t2);
                   12899:                        if (t1->vec_type()) {           // e1[e2]
                   12900:                                switch (t2->base) {
                   12901:                                case CHAR:
                   12902:                                case SHORT:
                   12903:                                case INT:
                   12904:                                case LONG:
                   12905:                                case EOBJ:
                   12906:                                        break;
                   12907:                                default:
                   12908:                                {       Pname cn = t2->is_cl_obj();
                   12909:                                        if (cn) // conversion to integral?
                   12910:                                                e2 = check_cond(e2,DEREF,tbl);
                   12911:                                        else
                   12912:                                                t2->integral(DEREF);
                   12913:                                }
                   12914:                                }
                   12915:                                while (t1->base == TYPE) t1 = Pbase(t1)->b_name->tp;
                   12916:                                if (t1->base==PTR && Pptr(t1)->memof) error("P toM dereferenced");
                   12917:                                tp = t1->deref();
                   12918:                                (void) tp->tsizeof();
                   12919:                        }
                   12920:                        else if (t2->vec_type()) {      // really e2[e1]
                   12921:                                t1->integral(DEREF);
                   12922:                                while (t2->base == TYPE) t2 = Pbase(t2)->b_name->tp;
                   12923:                                if (t2->base==PTR && Pptr(t2)->memof) error("P toM dereferenced");
                   12924:                                tp = t2->deref();
                   12925:                                (void) tp->tsizeof();
                   12926:                        }
                   12927:                        else {
                   12928:                                error("[] applied to nonPT:%t[%t]",t1,t2);
                   12929:                                tp = any_type;
                   12930:                        }
                   12931:                }
                   12932: 
                   12933:                if (tp->is_ref()) return contents();
                   12934: 
                   12935:                return this;
                   12936: 
                   12937:        case G_ADDROF:
                   12938:        case ADDROF:
                   12939: //error('d',"addrof(%d) %k %d",base,e2->base,e2->base);
                   12940:                switch (e2->base) {     // potential lvalues
                   12941:                case G_CM:
                   12942:                        if (base==ADDROF && e2->e2->base==NAME) {
                   12943:                                // check for cfront generated result variable
                   12944:                                char* s = e2->e2->string;
                   12945:                                if (s[0]=='_' && s[1] && s[1]=='_') {
                   12946:                                        if (s[2] && (s[2]=='R' || s[2]=='V')) {
                   12947:                                                error("address of non-lvalue");
                   12948:                                                break;
                   12949:                                        }
                   12950:                                }
                   12951:                        }
                   12952:                case CM:        // &(a,b) => (a,&b)
                   12953:                {
                   12954:                        Pexpr ee = e2;
                   12955:                        ee->tp = 0;
                   12956:                        ee->e2 = new expr(base,0,ee->e2);
                   12957:                        delete this;
                   12958:                        return ee->typ(tbl);
                   12959:                }
                   12960:                case QUEST:     // & (a?b:c) => (a?&b:&c)
                   12961:                {
                   12962:                        Pexpr ee = e2;
                   12963:                        ee->tp = 0;
                   12964:                        ee->e1 = new expr(base,0,ee->e1);
                   12965:                        ee->e2 = new expr(base,0,ee->e2);
                   12966:                        delete this;
                   12967:                        return ee->typ(tbl);
                   12968:                }
                   12969:                case INCR:
                   12970:                case DECR:
                   12971:                        if (e2->e1) break;
                   12972:                case ASSIGN:
                   12973:                case ASPLUS:
                   12974:                case ASMINUS:
                   12975:                case ASMUL:
                   12976:                case ASDIV:
                   12977:                case ASMOD:
                   12978:                case ASAND:
                   12979:                case ASOR:
                   12980:                case ASER:
                   12981:                case ASLS:
                   12982:                case ASRS:
                   12983:                        return e2->address();
                   12984:                }
                   12985: 
                   12986:                if (e2->lval(ADDROF) == 0) {
                   12987:                        if (error_count) {      // error_count == 0 possible
                   12988:                                                // in case of & const
                   12989:                                tp = any_type;
                   12990:                                return this;
                   12991:                        }
                   12992:                }
                   12993: 
                   12994:                tp = t->addrof();
                   12995: 
                   12996:                if( base==ADDROF && mpglob)
                   12997:                        Pptr(tp)->memof = mpglob;
                   12998: 
                   12999:                if (e2->tp->base == VEC) {
                   13000:                        if(e2->base != NAME) {
                   13001:                                base = CAST;
                   13002:                                tp2 = tp;
                   13003:                                e1 = e2;
                   13004:                                e2 = 0;
                   13005:                                return this;
                   13006:                        }
                   13007:                }
                   13008: 
                   13009:        //      tp = t->addrof();
                   13010: 
                   13011:                if (t->base==FCT) 
                   13012:                        Pptr(tp)->memof = Pfct(t)->memof;
                   13013: 
                   13014: //             if (t->tconst() && vec_const==0 && fct_const==0) Pptr(tp)->rdo = 1;
                   13015: // ??? & (const T) is NOT T*const but const T*
                   13016: 
                   13017:                switch (e2->base) {
                   13018:                case NAME:
                   13019:                mname:                                  // check for &s::i
                   13020:                {       Pname n2 = Pname(e2);
                   13021:                        Pname cn = (n2->n_table && n2->n_table!=gtbl) ? n2->n_table->t_name : 0;
                   13022: // error('d',"n2 %k cn %n t %t",n2->base,cn,t);
                   13023:                        if (cn == 0) break;
                   13024:                //      Pptr(tp)->memof = Pclass(cn->tp);
                   13025: 
                   13026:                        if (t->base==FCT && Pfct(t)->f_this==0) {
                   13027:                                Pptr(tp)->memof = 0;
                   13028:                                break;
                   13029:                        }
                   13030: 
                   13031:                        switch (t->base) {
                   13032:                        case OVERLOAD:
                   13033:                                return e2;
                   13034:                        case FCT:
                   13035: // error('d', "cn->tp: %d, %k", cn->tp, cn->tp->base);
                   13036:                                Pptr(tp)->memof = Pclass(cn->tp); //SSS
                   13037:                                
                   13038:                                if (Pfct(t)->f_virtual) {
                   13039:                                        // { 0,vtbl index,0 }
                   13040:                                        e1 = new ival(Pfct(t)->f_virtual);
                   13041:                                        e1 = new expr(ELIST,zero,e1);
                   13042:                                        e2 = zero;
                   13043:                                        base = ILIST;
                   13044:                                //      tp = int_type;
                   13045:                                        return this;
                   13046:                                }               // use the pointer
                   13047:                                
                   13048:                                // { 0,-1,(int(*)())ptr }
                   13049:                                e1 = new ival(-1);
                   13050:                                e1 = new expr(ELIST,zero,e1);
                   13051:                                // e2 is the name
                   13052:                                e2 = new cast(Pfct_type,e2);
                   13053:                                base = ILIST;
                   13054:                        //      tp = int_type;
                   13055:                                return this;
                   13056: 
                   13057:                        //      return e2;
                   13058: 
                   13059:                        default:
                   13060:                                if (n2->n_stclass != STATIC) {  // offset + 1
                   13061: //error('d',"n2 %n %d",n2,n2->n_offset);
                   13062: //error('d',"q %n cn %n",n2->n_qualifier,cn);
                   13063:                                        e1 = new ival(n2->n_offset+1);
                   13064:                                        Pptr(tp)->memof = Pclass(cn->tp);
                   13065: //error('d',"cl %d %s i %d",Pclass(cn->tp),Pclass(cn->tp)?Pclass(cn->tp)->string:"0",n2->n_offset);
                   13066:                                }
                   13067:                                else
                   13068:                                        return this;
                   13069:                        }
                   13070: //error('d',"int_type");
                   13071:                        e1->tp = int_type;
                   13072:                        e2 = 0;
                   13073:                        tp2 = tp;
                   13074:                        base = CAST;
                   13075:                        return this;
                   13076:                }
                   13077:                case DOT:
                   13078:                 case REF:
                   13079:                 {       
                   13080:                         Pname m = Pname(e2->mem);
                   13081: // error( 'd', "e2->mem->base: %k", e2->mem->base );
                   13082: //                      Pname m = (e2->mem->base == MDOT) ? Pname(e2->mem->mem) : Pname(e2->mem);
                   13083:                        while ( m->base == MDOT ) m = Pname(Pexpr(m)->mem);
                   13084: 
                   13085:                        Pfct f = Pfct(m->tp);
                   13086: 
                   13087:                        if (f->base == FCT || f->base == OVERLOAD) {  // &p->f
                   13088:                                Pexpr q = Pname(e2)->n_initializer;  // &p->x::f
                   13089: 
                   13090:                                if (q && bound==0 && e2->e1==cc->c_this) {      
                   13091:                                        // FUDGE: &this->x::f => &x::f
                   13092:                                        DEL(e2);
                   13093:                                        e2 = m;
                   13094:                                        goto mname;
                   13095:                                }
                   13096: 
                   13097:                                bound = 1;
                   13098:                                if(!f->f_static) {
                   13099:                                        error(strict_opt?0:'w',
                   13100:                                            "address of boundF (try using ``%s::*'' forPT and ``&%s::%s'' for address) (anachronism)",
                   13101:                                            m->n_table->t_name->string,
                   13102:                                            m->n_table->t_name->string,
                   13103:                                            m->string
                   13104:                                        );
                   13105:                                }
                   13106: 
                   13107:                                if (q || f->f_virtual==0) {
                   13108:                                        // & x.f  =>  & f
                   13109:                                        DEL(e2);
                   13110:                                        e2 = m;
                   13111:                                }
                   13112:                        }
                   13113:                        break;
                   13114: 
                   13115:                }
                   13116:                case MEMPTR:
                   13117:                        // &(p->*q)
                   13118:                        error("& .* E");
                   13119:                }
                   13120: 
                   13121:                return this;
                   13122: 
                   13123:        case UMINUS:
                   13124:                t->numeric(UMINUS);
                   13125:                tp = t;
                   13126:                return this;
                   13127: 
                   13128:        case UPLUS:
                   13129:                t->num_ptr(UPLUS);
                   13130:                tp = t;
                   13131:                if (ansi_opt==0) {
                   13132:                        base = PLUS;
                   13133:                        e1 = zero;
                   13134:                }
                   13135:                return this;
                   13136: 
                   13137:        case NOT:
                   13138:                e2 = check_cond(e2,NOT,tbl);
                   13139:                tp = int_type;
                   13140:                return this;
                   13141: 
                   13142:        case COMPL:
                   13143:                t->integral(COMPL);
                   13144:                tp = t;
                   13145:                return this;
                   13146: 
                   13147:        case INCR:
                   13148:        case DECR:
                   13149:                {
                   13150: // error('d',"incr-decr: e1: %k e2: %k", e1?e1->base:0, e2?e2->base:0);
                   13151:                Pexpr e = e1?e1:e2;     // e1!=0 ==> e++ or e--
                   13152:                                        // e1==0 ==> ++e or --e
                   13153: 
                   13154:                e->lval(b);
                   13155: 
                   13156:                switch(e->base) {
                   13157:                case QUEST:
                   13158:                        e->tp=0;
                   13159:                        e->e1 = e1 ? new expr(base,e->e1,0) : new expr(base,0,e->e1);
                   13160:                        e->e2 = e1 ? new expr(base,e->e2,0) : new expr(base,0,e->e2);
                   13161:                        delete this;
                   13162:                        return e->typ(tbl);
                   13163:                case CM:
                   13164:                case G_CM:
                   13165:                        e->tp=0;
                   13166:                        e->e2 = e1 ? new expr(base,e->e2,0) : new expr(base,0,e->e2);
                   13167:                        delete this;
                   13168:                        return e->typ(tbl);
                   13169:                case INCR:
                   13170:                case DECR:
                   13171:                        if(e->e1)
                   13172:                                break;
                   13173:                        nin++;
                   13174:                        if(e->e2->not_simple())
                   13175:                                error('s',"overly complex %k of %k",b,e->base);
                   13176:                        nin--;
                   13177:                        e = new expr(G_CM,e,e->e2->typ(tbl));
                   13178:                        if (e1) e1=e; else e2=e;
                   13179:                        // e1?e1:e2 = e;
                   13180:                        return typ(tbl);
                   13181:                case ASSIGN:
                   13182:                case ASPLUS:
                   13183:                case ASMINUS:
                   13184:                case ASMUL:
                   13185:                case ASDIV:
                   13186:                case ASMOD:
                   13187:                case ASAND:
                   13188:                case ASOR:
                   13189:                case ASER:
                   13190:                case ASLS:
                   13191:                case ASRS:
                   13192:                        nin++;
                   13193:                        if(e->e1->not_simple())
                   13194:                                error('s',"overly complex %k of %k",b,e->base);
                   13195:                        nin--;
                   13196:                        e = new expr(G_CM,e,e->e1->typ(tbl));
                   13197:                        if (e1) e1=e; else e2=e;
                   13198:                        // e1?e1:e2 = e;
                   13199:                        return typ(tbl);
                   13200:                }
                   13201:                }
                   13202: 
                   13203:                r1 = t->num_ptr(b);
                   13204:                if (r1='P' && t->check(Pvoid_type,0)==0) error("%k of void*",b);
                   13205:                tp = t;
                   13206:                return this;
                   13207:        
                   13208:        }
                   13209: 
                   13210:        if (e1==dummy || e2==dummy || e1==0 || e2==0) error("operand missing for%k",b);
                   13211:        switch (b) {
                   13212:        case MUL:
                   13213:        case DIV:
                   13214:                r1 = t1->numeric(b);
                   13215:                r2 = t2->numeric(b);
                   13216:                nppromote(b);
                   13217:                break;
                   13218: 
                   13219:        case PLUS:
                   13220:                r2 = t2->num_ptr(PLUS);
                   13221:                r1 = t1->num_ptr(PLUS);
                   13222:                nppromote(PLUS);
                   13223:                goto void_check;
                   13224: 
                   13225:        case MINUS:
                   13226:                r2 = t2->num_ptr(MINUS);
                   13227:                r1 = t1->num_ptr(MINUS);
                   13228:                if (r2=='P' && r1!='P' && r1!='A') error("nonP - P");
                   13229:                nppromote(MINUS);
                   13230:        void_check:
                   13231:                if ((r1='P' && t1->check(Pvoid_type,0)==0) 
                   13232:                ||  (r2='P' && t2->check(Pvoid_type,0)==0))
                   13233:                        error("%k of void*",b);
                   13234:                tp = t;
                   13235:                break;
                   13236: 
                   13237:        case LS:
                   13238:        case RS:
                   13239:        case AND:
                   13240:        case OR:
                   13241:        case ER:
                   13242:                switch (e1->base) {
                   13243:                case LT:
                   13244:                case LE:
                   13245:                case GT:
                   13246:                case GE:
                   13247:                case EQ:
                   13248:                case NE:
                   13249:                        error('w',"%kE as operand for%k",e1->base,b);
                   13250:                }
                   13251:                switch (e2->base) {
                   13252:                case LT:
                   13253:                case LE:
                   13254:                case GT:
                   13255:                case GE:
                   13256:                case EQ:
                   13257:                case NE:
                   13258:                        error('w',"%kE as operand for%k",e2->base,b);
                   13259:                }
                   13260:        case MOD:
                   13261:                r1 = t1->integral(b);
                   13262:                r2 = t2->integral(b);
                   13263:                nppromote(b);
                   13264:                break;
                   13265: 
                   13266:        case LT:
                   13267:        case LE:
                   13268:        case GT:
                   13269:        case GE:
                   13270:        case EQ:
                   13271:        case NE:
                   13272:                r1 = t1->num_ptr(b);
                   13273:                r2 = t2->num_ptr(b);
                   13274:                if (r1=='P' && r2=='I') {       // allow things like:
                   13275:                                                // if (p==2-2)
                   13276:                                                // YUCK!
                   13277:                        Neval = 0;
                   13278:                        long i = e2->eval();
                   13279:                        if (Neval==0 && i==0) {
                   13280:                                DEL(e2);
                   13281:                                e2 = zero;
                   13282:                                r2 = 'Z';
                   13283:                        }
                   13284:                }
                   13285:                else if (r2=='P' && r1=='I') {
                   13286:                        Neval = 0;
                   13287:                        long i = e1->eval();
                   13288:                        if (Neval==0 && i==0) {
                   13289:                                DEL(e1);
                   13290:                                e1 = zero;
                   13291:                                r1 = 'Z';
                   13292:                        }
                   13293:                }
                   13294: 
                   13295:                if (b!=EQ && b!=NE) {
                   13296:                        if (r1=='P' && r2=='Z') error("P%k 0",b);
                   13297:                        if (r2=='P' && r1=='Z') error("P%k 0",b);
                   13298:                }
                   13299: 
                   13300:                // make sure functions are properly converted to pointers to
                   13301:                // functions and make sure overloaded functions are rejected
                   13302:                Pexpr ptof(Pfct ef, Pexpr e, Ptable tbl);
                   13303:                if (r1 == FCT) e1 = ptof(0,e1,tbl);
                   13304:                if (r2 == FCT) e2 = ptof(0,e2,tbl);
                   13305: 
                   13306:                npcheck(b);
                   13307: 
                   13308:                if (r1=='P') { // need cast for pointers to virtual and second bases
                   13309:                        Pptr p1 = t1->is_ptr();
                   13310:                        Pptr p2 = t2->is_ptr();
                   13311:                        Pname cn = p1?p1->typ->is_cl_obj():0;
                   13312:                        Pname cn2 = p2?p2->typ->is_cl_obj():0;
                   13313: 
                   13314:                        if (cn && cn2) {
                   13315:                                Pclass cl = Pclass(cn->tp);
                   13316:                                Pclass cl2 = Pclass(cn2->tp);
                   13317: 
                   13318:                                if (cl->has_base(cl2)) {
                   13319:                                        e1 = cast_cptr(cl2,e1,tbl,0);
                   13320:                                        e1 = new cast(p2,e1);
                   13321:                                }
                   13322:                                else if (cl2->has_base(cl)) {
                   13323:                                        e2 = cast_cptr(cl,e2,tbl,0);
                   13324:                                        e2 = new cast(p1,e2);
                   13325:                                }
                   13326:                        }
                   13327:                }
                   13328: 
                   13329:                if (r1=='P' && t1->memptr()) {
                   13330:                mpmp:
                   13331:                        if (r2=='Z') {
                   13332:                                e2 = zero;
                   13333:                                e1 = new mdot("i",e1);
                   13334:                                e1->i1 = 9;
                   13335:                        }
                   13336:                        else if (r2=='P' && t2->memptr()) {
                   13337:                                // ERROR: no check for sideeffects
                   13338:                                Pexpr i1 = new mdot("i",e1);
                   13339:                                Pexpr i2;
                   13340:                                i1->i1 = 9;
                   13341: 
                   13342:                                i2 = e2;
                   13343:                                while ( i2->base == CAST )
                   13344:                                    i2 = i2->e1;
                   13345:                                if ( i2->base == ILIST )
                   13346:                                    e2 = i2;
                   13347: 
                   13348:                                if (e2->base==ILIST)
                   13349:                                        i2 = e2->e1->e2;
                   13350:                                else {
                   13351:                                        i2 = new mdot("i",e2);
                   13352:                                        i2->i1 = 9;
                   13353:                                }
                   13354: 
                   13355:                                Pexpr f1 = new mdot("f",e1);
                   13356:                                Pexpr f2;
                   13357:                                f1->i1 = 9;
                   13358:                                if (e2->base == ILIST)
                   13359:                                //      f2 = new cast(Pfct_type,e2->e2);
                   13360:                                        f2 = e2->e2;
                   13361:                                else {
                   13362:                                        f2 = new mdot("f",e2);
                   13363:                                        f2->i1 = 9;
                   13364:                                }
                   13365: 
                   13366:                                Pexpr ei = new expr(base,i1,i2);
                   13367:                                Pexpr fi = new expr(base,f1,f2);
                   13368: 
                   13369:                                base = ANDAND;
                   13370:                                e1 = ei;
                   13371:                                e2 = fi;
                   13372:                        } else if (r2=='P') {
                   13373:                                error('s',"%t %k %t",t1,base,t2);
                   13374:                        }
                   13375:                }
                   13376:                else if (r2=='P' && t2->memptr()) {
                   13377:                        Pexpr ee = e1;  // swap
                   13378:                        e1 = e2;
                   13379:                        e2 = ee;
                   13380:                        int rr = r1;
                   13381:                        r1 = r2;
                   13382:                        r2 = rr;
                   13383:                        Ptype tt = t1;
                   13384:                        t1 = t2;
                   13385:                        t2 = tt;
                   13386:                        goto mpmp;
                   13387:                }
                   13388:                t = int_type;
                   13389:                break;
                   13390: 
                   13391:        case ANDAND:
                   13392:        case OROR:
                   13393:                e1 = check_cond(e1,b,tbl);
                   13394:                e2 = check_cond(e2,b,tbl);
                   13395:                t = int_type;
                   13396:                break;
                   13397: 
                   13398:        case QUEST:
                   13399:                {
                   13400:                Pname c1, c2;
                   13401:                cond = check_cond(cond,b,tbl);
                   13402: //error('d',"cond %k %t",cond->base,cond->tp);
                   13403: //error('d',"t1 %t t2 %t",t1,t2);
                   13404: 
                   13405:                // still doesn't do complete checking for possible conversions...
                   13406: 
                   13407:                bit MPTR = 0; // local hack
                   13408: 
                   13409:                extern int suppress_error;                      // global hack
                   13410:                suppress_error++;
                   13411:                r1 = t1->num_ptr(b);
                   13412:                r2 = t2->num_ptr(b);
                   13413:                suppress_error--;
                   13414: if (r1=='P' && r2=='P' && t1->memptr() && t2->memptr()) {
                   13415: 
                   13416:                ++MPTR; // prevent later sorry
                   13417: 
                   13418:                // watch for casts
                   13419:                Pexpr tt = e1;
                   13420:                while ( tt->base == CAST ) tt = tt->e1;
                   13421:                if ( tt->base == ILIST ) e1 = tt; 
                   13422: 
                   13423:                tt = e2;
                   13424:                while ( tt->base == CAST ) tt = tt->e1;
                   13425:                if ( tt->base == ILIST ) e2 = tt; 
                   13426: 
                   13427:                // cannot have sides return (expr?{}:{})
                   13428:                // reuse same temp for both sides ?:
                   13429:                Pname temp = make_tmp( 'A', mptr_type, tbl );
                   13430: 
                   13431:                e1 = mptr_assign( temp, e1 );
                   13432:                e1 = new expr( G_CM, e1, temp );
                   13433:                e1->tp = temp->tp;
                   13434: 
                   13435:                e2 = mptr_assign( temp, e2 );
                   13436:                e2 = new expr( G_CM, e2, temp );
                   13437:                e2->tp = temp->tp;
                   13438: }
                   13439: 
                   13440:                if (t1==t2
                   13441:                || (    (c1=t1->is_cl_obj())
                   13442:                        && (c2=t2->is_cl_obj())
                   13443:                        && (c1->tp==c2->tp)
                   13444:                ))
                   13445:                        t = t1;
                   13446:                else {
                   13447:                        r1 = t1->num_ptr(b);
                   13448:                        r2 = t2->num_ptr(b);
                   13449: 
                   13450:                        if (r1=='P' && r2=='P') {
                   13451:                                Pptr p1 = t1->is_ptr();
                   13452:                                Pptr p2 = t2->is_ptr();
                   13453: //error('d',"p1 %t p2 %t",p1,p2);
                   13454:                                if ((c1 = p1->typ->is_cl_obj())
                   13455:                                && (c2 = p2->typ->is_cl_obj())) {
                   13456:                                        Pclass cl1 = Pclass(c1->tp);
                   13457:                                        Pclass cl2 = Pclass(c2->tp);
                   13458:                                        if (cl1==cl2 || cl2->has_base(cl1)) {
                   13459:                                                t = t1;
                   13460:                                                goto caca;
                   13461:                                        }
                   13462:                                        else if (cl1->has_base(cl2)) {
                   13463:                                                t = t2;
                   13464:                                                goto caca;
                   13465:                                        }
                   13466:                                }
                   13467:                        }
                   13468: 
                   13469:                        if (r1==FCT && r2==FCT) {       // fudge
                   13470:                                if (t1->check(t2,ASSIGN))
                   13471:                                        error("badTs in ?:E: %t and %t",t1,t2);
                   13472:                                else if (Pfct(t1)->memof) error('s',"conditionalE with%t",t1);
                   13473:                                t = t1;
                   13474:                        }
                   13475:                        else 
                   13476:                                nppromote(b);
                   13477:                caca:
                   13478: //error('d',"?: t %t t1 %t t2 %t",t,t1,t2);
                   13479:                        if (t!=t1 && t->check(t1,0)) {
                   13480:                                PERM(t);
                   13481:                                e1 = new cast(t,e1);
                   13482:                        }
                   13483: 
                   13484:                        if (t!=t2 && t->check(t2,0)) {
                   13485:                                PERM(t);
                   13486:                                e2 = new cast(t,e2);
                   13487:                        }
                   13488: 
                   13489:                        Pptr pt = t->is_ptr();
                   13490:                        //if (pt && pt->base==PTR && pt->memof) error('s',"conditionalE with%t",t);
                   13491:                        if (pt && pt->base==PTR && pt->memof && MPTR == 0) error('s',"conditionalE with%t",t);
                   13492:                }
                   13493:                }
                   13494:                break;
                   13495: 
                   13496:        case ASPLUS:
                   13497:                r1 = t1->num_ptr(ASPLUS);
                   13498:                r2 = t2->num_ptr(ASPLUS);
                   13499:                nppromote(ASPLUS);
                   13500:                goto ass;
                   13501: 
                   13502:        case ASMINUS:
                   13503:                r1 = t1->num_ptr(ASMINUS);
                   13504:                r2 = t2->num_ptr(ASMINUS);
                   13505:                if (r2=='P' && r1!='P' && r1!='A') error("P -= nonP");
                   13506:                nppromote(ASMINUS);
                   13507:                goto ass;
                   13508: 
                   13509:        case ASMUL:
                   13510:        case ASDIV:
                   13511:                r1 = t1->numeric(b);
                   13512:                r2 = t1->numeric(b);
                   13513:                nppromote(b);
                   13514:                goto ass;
                   13515: 
                   13516:        case ASMOD:
                   13517:                r1 = t1->integral(ASMOD);
                   13518:                r2 = t2->integral(ASMOD);
                   13519:                nppromote(ASMOD);
                   13520:                goto ass;
                   13521: 
                   13522:        case ASAND:
                   13523:        case ASOR:
                   13524:        case ASER:
                   13525:        case ASLS:
                   13526:        case ASRS:
                   13527:                r1 = t1->integral(b);
                   13528:                r2 = t2->integral(b);
                   13529:                npcheck(b);
                   13530:                t = int_type;
                   13531:                goto ass;
                   13532:        ass:
                   13533:                if (r1='P' && t1->check(Pvoid_type,0)==0) error("%k of void*",b);
                   13534:                tp = t;
                   13535:                as_type = t;    /* the type of the rhs */
                   13536:                t2 = t;
                   13537: 
                   13538:        case ASSIGN:
                   13539: //error('d',"assign %k: %t %t %s",b,t1,t2,ignore_const?"ignore const":"");
                   13540: //error('d',"    e1 %d %k e1 %d %k",e1,e1->base,e2,e2->base);
                   13541:                if (ignore_const) {     // handle static initializers
                   13542:                                        // represented as assignments
                   13543:                                        // ignore consts.
                   13544:                        tp = e1->tp;
                   13545:                        return this;
                   13546:                }
                   13547: 
                   13548:                switch (e1->base) {
                   13549:                case G_CM:
                   13550:                case CM:        // (a,b)=c => *(a,&b)=c
                   13551:                {
                   13552:                        e1->e2 = new expr(G_ADDROF,0,e1->e2);
                   13553:                        e1->tp = 0;
                   13554:                        e1 = new expr(DEREF,e1,0);
                   13555:                        return typ(tbl);
                   13556:                }
                   13557:                case QUEST:     // (a?b:c)=d => *(a?&b:&c)=c
                   13558:                {
                   13559:                        e1->e1 = new expr(G_ADDROF,0,e1->e1);
                   13560:                        e1->e2 = new expr(G_ADDROF,0,e1->e2);
                   13561:                        e1->tp = 0;
                   13562:                        e1 = new expr(DEREF,e1,0);
                   13563:                        return typ(tbl);
                   13564:                }
                   13565:                case ASSIGN:    // (a*=b)=c => a*=b,a=c
                   13566:                case ASPLUS:
                   13567:                case ASMINUS:
                   13568:                case ASMUL:
                   13569:                case ASDIV:
                   13570:                case ASMOD:
                   13571:                case ASAND:
                   13572:                case ASOR:
                   13573:                case ASER:
                   13574:                case ASLS:
                   13575:                case ASRS:
                   13576:                {
                   13577:                        base = G_CM;
                   13578:                        nin++;
                   13579:                        if (e1->e1->not_simple()) error('s',"lvalue %k too complicated",b);
                   13580:                        nin--;
                   13581:                        Pexpr aa = new expr(e1->base,e1->e1,e1->e2);
                   13582:                        Pexpr bb = new expr(b,e1->e1,e2);
                   13583:                        e1 = aa;
                   13584:                        e2 = bb;
                   13585:                        return typ(tbl);
                   13586:                }
                   13587:                case INCR:
                   13588:                case DECR:      // ++a=b => ++a,a=b
                   13589:                {
                   13590:                        if(!e1->e2) break ;
                   13591:                        base = G_CM;
                   13592:                        nin++;
                   13593:                        if (e1->e2->not_simple()) error('s',"lvalue %k too complicated",b);
                   13594:                        nin--;
                   13595:                        Pexpr aa = new expr(e1->base,0,e1->e2);
                   13596:                        Pexpr bb = new expr(b,e1->e2,e2);
                   13597:                        e1 = aa;
                   13598:                        e2 = bb;
                   13599:                        return typ(tbl);
                   13600:                }
                   13601:                case REF:
                   13602:                {
                   13603:                        Pexpr r = e1;
                   13604:                        // hack to prevent
                   13605:                        //      f().i = j
                   13606:                        // transformed into
                   13607:                        //      ((t=f()),&t)->i = j
                   13608:                        if (r->e1->base==G_CM
                   13609:                        && r->e1->e2->base==G_ADDROF
                   13610:                        && r->e1->e2->e2->base==NAME) {
                   13611:                                char* s = r->e1->e2->e2->string;
                   13612:                                if (s[0]=='_' && s[1]=='_')
                   13613:                                        error("left hand side not lvalue");
                   13614:                        }
                   13615:                }
                   13616:                }
                   13617: 
                   13618:                if (e1->lval(b) == 0) {
                   13619:                        tp = any_type;
                   13620:                        return this;
                   13621:                }
                   13622:        lkj:
                   13623:                switch (t1->base) {
                   13624:                case TYPE:
                   13625:                        t1 = Pbase(t1)->b_name->tp;
                   13626:                        goto lkj;
                   13627:                case INT:
                   13628:                case CHAR:
                   13629:                case SHORT:
                   13630:                //      if (e2->base==ICON && e2->tp==long_type)
                   13631:                //              error('w',"long constant assigned to%k",t1->base);
                   13632:                {       Ptype t = e2->tp;
                   13633:                csi:
                   13634:                        switch (t->base) {
                   13635:                        case TYPE:
                   13636:                                t = Pbase(t)->b_name->tp; goto csi;
                   13637:                        case LONG:
                   13638:                        case FLOAT:
                   13639:                        case DOUBLE:
                   13640:                        case LDOUBLE:
                   13641:                                error('w',"%t assigned to %t",e2->tp,t1);
                   13642:                        }
                   13643:                }
                   13644:                        // no break
                   13645:                case LONG:
                   13646:                        if (b==ASSIGN
                   13647:                        && Pbase(t1)->b_unsigned
                   13648:                        && e2->base==UMINUS
                   13649:                        && e2->e2->base==ICON)
                   13650:                                error('w',"negative assigned to unsigned");
                   13651:                        break;
                   13652:                case PTR:
                   13653:                        if (b == ASSIGN) {
                   13654: //error('d',"ptr t1 %t %d %t",t1,t1->memptr(),t2);
                   13655:                        //??    if (t1->memptr() && t2->base!=OVERLOAD) break;
                   13656:                                e2 = ptr_init(Pptr(t1),e2,tbl);
                   13657:                                t2 = e2->tp;
                   13658: //error('d',"pchecked %d",Pchecked);
                   13659:                                if (Pchecked) {
                   13660:                                        tp = e1->tp;
                   13661:                                        return this;
                   13662:                                }
                   13663:                        }
                   13664:                        break;
                   13665:                case COBJ:
                   13666:                {       Pname c1 = t1->is_cl_obj();
                   13667:                                // test of c1->tp necessary for ``fake classes''
                   13668:                                // _Sdd generated for vector assignemnts
                   13669:                        if (c1
                   13670:                        && c1->tp
                   13671:                /*      && Pclass(c1->tp)->memtbl->look("__as",0)==0*/) {
                   13672:                        //&& Pclass(c1->tp)->has_oper(ASSIGN)==0) {
                   13673:                                Pname c2 = t2->is_cl_obj();
                   13674: // error('d', "expr::typ: c1: %n c2: %n", c1, c2 );
                   13675:                                if (c1 != c2) {
                   13676: /*
                   13677:        consider:
                   13678: 
                   13679:        struct A { A(B&); };
                   13680:        struct B : A {};
                   13681: 
                   13682:        A aa;
                   13683:        B bb;
                   13684: 
                   13685:        aa = bb;        // aa.operator=(A(bb));
                   13686:                        // optimize to aa.A(bb) when possible
                   13687:                        // avoid temporary where aa = *(A*)&bb is legal
                   13688: */
                   13689: // error('d',"expr::typ c1 %n %d c2 %n %d",c1,c1?c1->tp:0,c2,c2?c2->tp:0);
                   13690:                                        if (c2
                   13691:                                        && c2->tp
                   13692:                                        && can_coerce(t1,t2)==0
                   13693:                                        //&& Pclass(c2->tp)->has_base(Pclass(c1->tp))
                   13694:                                        //&& (1<is_unique_base(Pclass(c2->tp),c1->string,0))
                   13695:                                        && (vcllist->clear(),vcllist=0,1<is_unique_base(Pclass(c2->tp),c1->string,0))
                   13696:                                        && Pclass(c1->tp)->c_xref&(C_VBASE|C_VPTR|C_ASS)) {
                   13697: // error('d',"aaa");
                   13698:                                                if (make_assignment(c1)) return try_to_overload(tbl);
                   13699:                                        }
                   13700:                                // optimize
                   13701:                                        else {
                   13702:                                                e2 = new expr(ELIST,e2,0);
                   13703:                                                e2 = new texpr(VALUE,t1,e2);
                   13704:                                                if (Pclass(c1->tp)->has_dtor()==0 &&
                   13705:                                                        Pclass(c1->tp)->has_oper(ASSIGN)==0) {
                   13706:                                // optimize
                   13707: // error('d',"bbb");
                   13708:                                                        e2->e2 = e1;
                   13709:                                                        e2 = e2->typ(tbl);
                   13710:                                                        if (e2->base==DEREF && e2->e1->base==G_CALL ||
                   13711:                                                        e2->base==ASSIGN && e2->e1==e1) {
                   13712: // error('d',"ccc");
                   13713:                                                                *this = *e2;
                   13714:                                                        }
                   13715:                                                        tp = t1;
                   13716:                                                        return this;
                   13717:                                                }
                   13718:                                                return typ(tbl);
                   13719:                                        }
                   13720:                                }
                   13721:                                        // test of c1->tp necessary for ``fake classes''
                   13722:                                        // _Sdd generated for vector assignemnts
                   13723:                                else if (c1->tp && Pclass(c1->tp)->c_xref&(C_VBASE|C_VPTR|C_ASS)) {
                   13724:                                        if (make_assignment(c1)) return try_to_overload(tbl);
                   13725:                                }
                   13726:                        }
                   13727:                        (void) t1->tsizeof();
                   13728:                        break;
                   13729:                }
                   13730:                }
                   13731: 
                   13732: //error('d',"check(%t,%t) -> %d",e1->tp,t2,try_to_coerce(t1,e2,"assignment",tbl));
                   13733:                {       Pexpr x = try_to_coerce(t1,e2,"assignment",tbl);
                   13734:                        if (x)
                   13735:                                e2 = x;
                   13736:                        else if (e1->tp->check(t2,ASSIGN))
                   13737:                                error("bad assignmentT:%t =%t",e1->tp,t2);
                   13738:                        else if ((t1 = t1->is_ptr()) && t1->memptr()) {
                   13739:                                if (t2 == zero_type) {
                   13740:                                        Pexpr ee = new expr(ELIST,zero,zero);
                   13741:                                        e2 = new expr(ILIST,ee,zero);
                   13742:                                }
                   13743:                                else if (t2->base==PTR && t2->memptr()) {
                   13744:                                        // do nothing: structure assignment
                   13745:                                }
                   13746:                                else {
                   13747:                                        Pexpr x = ptr_init(Pptr(t1),e2,tbl);
                   13748:                                        if (x != e2) e2 = x;
                   13749:                                }
                   13750:                        }
                   13751:                }               
                   13752:                t = e1->tp;     // the type of the lhs
                   13753:                break;
                   13754:        case CM:
                   13755:        case G_CM:
                   13756:                t = t2;
                   13757:                break;
                   13758:        default:
                   13759:                error('i',"unknown operator%k",b);
                   13760:        }
                   13761: 
                   13762:        tp = t;
                   13763:        return this;
                   13764: }
                   13765: 0707071010112044271004440001630000160000010200100466055401400001000000130600expr2.c/*ident    "@(#)ctrans:src/expr2.c 1.5" */
                   13766: /***************************************************************************
                   13767: 
                   13768:        C++ source for cfront, the C++ compiler front-end
                   13769:        written in the computer science research center of Bell Labs
                   13770: 
                   13771:        Copyright (c) 1984 AT&T, Inc. All rights Reserved
                   13772:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   13773: 
                   13774: expr2.c:
                   13775: 
                   13776:        type check expressions
                   13777: 
                   13778: ************************************************************************/
                   13779: 
                   13780: #include "cfront.h"
                   13781: #include "size.h"
                   13782: 
                   13783: extern Pname conv_dominates(Pname,Pname);
                   13784: static int const_obj1,const_obj2;
                   13785: 
                   13786: Pname really_dominate(Pname on1, Pname on2, bit tc)
                   13787: {
                   13788:        Pfct f1 = on1->tp->base==FCT ? Pfct(on1->tp) :
                   13789:                Pfct(Pgen(on1->tp)->fct_list->f->tp);
                   13790:        Pfct f2 = on2->tp->base==FCT ? Pfct(on2->tp) :
                   13791:                Pfct(Pgen(on2->tp)->fct_list->f->tp);
                   13792: 
                   13793:        // const check
                   13794:        int c1 = f1->f_const;
                   13795:        int c2 = f2->f_const;
                   13796: 
                   13797:        if(c1 == c2) ;
                   13798:        else if(c1 && !c2) return tc ? on1 : on2;
                   13799:        else if(c2 && !c1) return tc ? on2 : on1;
                   13800: 
                   13801:        // hierarchy check
                   13802:        Pname on = conv_dominates(on1,on2);
                   13803:        if(on) return on;
                   13804:        else return 0;
                   13805: }
                   13806: 
                   13807: void name::assign()
                   13808: {
                   13809:        if (n_assigned_to++ == 0) {
                   13810:                switch (n_scope) {
                   13811:                case FCT:
                   13812:                        if (n_used && n_addr_taken==0)  {
                   13813:                                Ptype t = tp;
                   13814:                        ll:
                   13815:                                switch (t->base) {
                   13816:                                case TYPE:
                   13817:                                        t=Pbase(t)->b_name->tp; goto ll;
                   13818:                                case VEC:
                   13819:                                        break;
                   13820:                                default:
                   13821:                                        if (curr_loop)
                   13822:                                                error('w',&where,"%n may have been used before set",this);
                   13823:                                        else
                   13824:                                                error('w',&where,"%n used before set",this);
                   13825:                                }
                   13826:                        }
                   13827:                }
                   13828:        }
                   13829: }
                   13830: 
                   13831: void name::take_addr()
                   13832: {
                   13833: // error('d', "%n->take_addr tp: %t", this, tp?tp:0 );
                   13834: // error('d', "%n->take_addr tp: %d %d", this, tp?tp:0, tp?tp->base:0 );
                   13835:        if ( (warning_opt) && (! n_addr_taken) && (tp) && (tp->base==FCT) && Pfct (tp)->f_inline)
                   13836:                error('w',"can't take address of inline function %n, %n not inlined", this, this);  
                   13837:        n_addr_taken++; 
                   13838:        if ( n_sto == EXTERN && tp ) {
                   13839:                Ptype t = tp;
                   13840:                while ( t->base == TYPE )  
                   13841:                        t = Pbase(t)->b_name->tp;
                   13842:                switch ( t->base ) {
                   13843:                        case COBJ:
                   13844:                                t = Pbase(t)->b_name->tp; // no break
                   13845:                        case CLASS: {
                   13846:                                Pclass cl = Pclass(t);
                   13847:                                if ( cl->c_body == 1 )
                   13848:                                        cl->dcl_print(0);
                   13849:                        }
                   13850:                }
                   13851:        }
                   13852: }
                   13853: 
                   13854: int ignore_const;      // for use by ref_init
                   13855: static is_dataMemPtr(Pexpr);
                   13856: 
                   13857: int expr::lval(TOK oper)
                   13858: {
                   13859:        register Pexpr ee = this;
                   13860:        register Pname n;
                   13861:        int deref = 0;
                   13862:        char* es;
                   13863: 
                   13864: //error('d',"%k expr::lval %k",base,oper);
                   13865: 
                   13866:        switch (oper) {
                   13867:        case ADDROF:
                   13868:        case G_ADDROF:  es = "address of";      break;
                   13869:        case DEREF:     es = "dereference of";  break;
                   13870:        case INCR:      es = "increment of";    goto def;
                   13871:        case DECR:      es = "decrement of";    goto def;
                   13872:        default:        es = "assignment to";
                   13873:        def:
                   13874:                if (ignore_const==0 && tp->tconst()) {
                   13875:                        if (oper) {
                   13876:                                if (base == NAME) {
                   13877:                                        if (vec_const && Pname(this)->n_scope==ARG) break;
                   13878:                                        error("%s constant%n",es,this);
                   13879:                                }
                   13880:                                else
                   13881:                                        error("%s constant",es);
                   13882:                        }
                   13883:                        return 0;
                   13884:                }
                   13885:        }
                   13886: 
                   13887:        for(;;) {
                   13888: //error('d',"loop %k",ee->base);
                   13889:                switch (ee->base) {
                   13890:        //      case G_CALL:
                   13891:        //      case CALL:
                   13892:                default:
                   13893:                defa:
                   13894:                        if (deref == 0) {
                   13895:                                if (oper) error("%s%k (not an lvalue)",es,ee->base);
                   13896:                                return 0;
                   13897:                        }
                   13898:                        return 1;
                   13899:                case ZERO:
                   13900:                case CCON:
                   13901:                case ICON:
                   13902:                case FCON:
                   13903:                        if (oper) error("%s numeric constant",es);
                   13904:                        return 0;
                   13905:                case STRING:
                   13906:                        if (oper) error('w',"%s string constant",es);
                   13907:                        return 1;
                   13908:                case CAST:
                   13909:                switch( oper ) {
                   13910:                case 0:
                   13911:                case ADDROF:
                   13912:                case G_ADDROF:
                   13913:                case DEREF:
                   13914:                        goto defa;
                   13915:                default:
                   13916:                        if ( ee->tp->base == PTR 
                   13917:                             && is_dataMemPtr(ee) ) 
                   13918:                        { // check for const class object
                   13919:                                Pexpr te;
                   13920:                                te = ee->e1->e1->e1;     
                   13921:                                        if ( te->base == G_ADDROF )
                   13922:                                        te = te->e2;
                   13923:                                        if ( te->base == NAME ) {
                   13924:                                        Ptype pt = te->tp;
                   13925:                                        if ( pt->base == PTR )
                   13926:                                                pt = Pptr(pt)->typ;
                   13927:                                        if ( pt->tconst() ) 
                   13928:                                                error("%sCMP of const%n",es,te);
                   13929:                                        return 0;
                   13930:                                }
                   13931:                        }
                   13932:                        goto defa;
                   13933:                }
                   13934: 
                   13935:                case DEREF:
                   13936:                {       
                   13937:                        Pexpr ee1 = ee->e1;
                   13938: // error( 'd', "ee1: %k", ee1->base );
                   13939:                        switch (ee1->base) {    // *& vanishes
                   13940:                        case ADDROF:    // *&
                   13941:                                return 1;
                   13942:                        case G_CM:
                   13943:                        case CM:        // look for *(a,&b)
                   13944:                                if (ee1->e2->base==G_ADDROF
                   13945:                                || ee1->e2->base==ADDROF)
                   13946:                                        return 1;
                   13947:                                goto defaa;
                   13948:                        case QUEST:     // look for *(q?&a:&b)
                   13949:                                if ((ee1->e1->base==G_ADDROF
                   13950:                                        || ee1->e1->base==ADDROF)
                   13951:                                && (ee1->e2->base==G_ADDROF
                   13952:                                        || ee1->e2->base==ADDROF))
                   13953:                                        return 1;
                   13954:                                // no break
                   13955:                        default:
                   13956:                        defaa:
                   13957:                                ee = ee1;
                   13958:                                deref = 1;
                   13959:                        }
                   13960:                        break;
                   13961:                }
                   13962: 
                   13963:                case QUEST:
                   13964:                {       int x1 = ee->e1->lval(deref?0:oper);
                   13965:                        int x2 = ee->e2->lval(deref?0:oper);
                   13966:                        if (ee->e1->tp->check(ee->e2->tp,0)) return 0;
                   13967:                        if (deref) return 1;
                   13968:                        return x1 && x2;
                   13969:                }
                   13970: 
                   13971:                case INCR:
                   13972:                case DECR:
                   13973:                        if (e1) goto defa;      // postfix does not preserve lval
                   13974:                case ASSIGN:
                   13975:                case ASPLUS:
                   13976:                case ASMINUS:
                   13977:                case ASMUL:
                   13978:                case ASDIV:
                   13979:                case ASMOD:
                   13980:                case ASAND:
                   13981:                case ASOR:
                   13982:                case ASER:
                   13983:                case ASLS:
                   13984:                case ASRS:
                   13985:                        return 1;
                   13986: 
                   13987:                case CM:
                   13988:                case G_CM:
                   13989:                        if (ee->e2->lval(deref?0:oper)==0) return deref;
                   13990:                        return 1;
                   13991: 
                   13992:                case MEMPTR:
                   13993:                        ee = ee->e2;
                   13994:                        break;
                   13995: 
                   13996:                case MDOT:
                   13997:                        ee = ee->mem;
                   13998:                        break;
                   13999: 
                   14000:                case DOT:
                   14001:                {
                   14002: // error('d',"dot %k oper %k",ee->e1->base,oper);
                   14003:                        Pexpr e = 0;
                   14004:                        int e_const = 0; // to catch x.y.val = 1, where x is const
                   14005: 
                   14006:                        switch (ee->e1->base) {         // update use counts, etc.
                   14007:                        case NAME:
                   14008:                                switch (oper) {
                   14009:                                case ADDROF:
                   14010:                                case G_ADDROF:  Pname(ee->e1)->take_addr();
                   14011:                                case 0:         break;
                   14012:                                case ASSIGN:    Pname(ee->e1)->n_used--;
                   14013:                                default:        Pname(ee->e1)->assign(); // asop
                   14014:                                }
                   14015:                                break;
                   14016:                        case DOT:
                   14017:                                e = ee->e1;
                   14018:                                do e=e->e1; while (e->base==DOT);
                   14019:                                if (e->base == NAME) {
                   14020:                                        e_const = e->tp->tconst();
                   14021:                                        switch (oper) {
                   14022:                                        case ADDROF:
                   14023:                                        case G_ADDROF:  Pname(e)->take_addr();
                   14024:                                        case 0:         break;
                   14025:                                        case ASSIGN:    Pname(e)->n_used--;
                   14026:                                        default:        Pname(e)->assign(); // asop
                   14027:                                        }
                   14028:                                }
                   14029:                        }
                   14030: 
                   14031:                        n = Pname(ee->mem);
                   14032:                        while (n->base == MDOT) n = Pname(Pref(n)->mem);
                   14033: 
                   14034:                        if (deref==0 && 
                   14035:                                (ee->e1->tp->tconst() || e_const)) {
                   14036: 
                   14037:                                switch (oper) {
                   14038:                                case 0:
                   14039:                                case ADDROF:
                   14040:                                case G_ADDROF:
                   14041:                                case DEREF:
                   14042:                                        break;
                   14043:                                default:
                   14044:                                        error("%sM%n of%t",es,n,e_const?e->tp:ee->e1->tp);
                   14045:                                }
                   14046:                                return 0;
                   14047:                        }
                   14048:                }
                   14049:                goto xx;
                   14050: 
                   14051:                case REF:
                   14052:                        n = Pname(ee->mem);
                   14053:                        while (n->base == MDOT) n = Pname(Pref(n)->mem);
                   14054: 
                   14055:                        if (deref==0 && ee->e1) {  //BR
                   14056:                                Ptype p = ee->e1->tp;
                   14057:                        zxc:
                   14058:                                switch (p->base) {
                   14059:                                case TYPE:      p = Pbase(p)->b_name->tp; goto zxc;
                   14060:                                case PTR:
                   14061:                                case VEC:       break;
                   14062:                                default:        error('i',"expr::lval %t->%n",p,n);
                   14063:                                }
                   14064:                                if (Pptr(p)->typ->tconst()) {
                   14065:                                        switch (oper) {
                   14066:                                        case 0:
                   14067:                                        case G_ADDROF:
                   14068:                                        case DEREF:
                   14069:                                                break;
                   14070:                                        case ADDROF:
                   14071:                                                if ( cm_const_save == 0 && const_ptr == 0 ) 
                   14072:                                                        error(strict_opt?0:'w',"%sM%n of%t",es,n,Pptr(p)->typ);
                   14073:                                                break;
                   14074:                                        default:
                   14075:                                                error("%sM%n of%t",es,n,Pptr(p)->typ);
                   14076:                                        }
                   14077:                                        return 0;
                   14078:                                }
                   14079:                        }
                   14080:                        goto xx;
                   14081: 
                   14082:                case NAME:
                   14083:                        n = Pname(ee);
                   14084:                xx:
                   14085: // error('d',"name xx: %n oper %d lex_level: %d",n,oper,n->lex_level);
                   14086:                        if (deref) return 1;
                   14087:                        if (oper==0) return n->n_stclass != ENUM ;
                   14088: 
                   14089:                        if (n->tp->base==FIELD && Pbase(n->tp)->b_bits==0) {
                   14090:                                error("%s 0-length field%n",es,n);
                   14091:                                return 0;
                   14092:                        }
                   14093: 
                   14094:                        switch (oper) {
                   14095:                        case ADDROF:
                   14096:                        case G_ADDROF:
                   14097:                        {       Pfct f = (Pfct)n->tp;
                   14098: 
                   14099:                                if (n->n_sto == REGISTER) {
                   14100:                                        if (warning_opt) error('w',"& register%n",n);
                   14101:                                //      return 0;
                   14102:                                        n->n_sto = 0;
                   14103:                                        n->n_stclass = AUTO;
                   14104:                                }
                   14105: 
                   14106:                                if (f == 0) {
                   14107:                                        error("& label%n",n);
                   14108:                                        return 0;
                   14109:                                }
                   14110: 
                   14111:                                if (n->n_stclass == ENUM) {
                   14112:                                        error("& enumerator%n",n);
                   14113:                                        return 0;
                   14114:                                }
                   14115: 
                   14116:                                if (n->tp->base == FIELD) {
                   14117:                                        error("& field%n",n);
                   14118:                                        return 0;
                   14119:                                }
                   14120: 
                   14121:                                n->n_used--;
                   14122:                                if (n->n_qualifier) { // oops, not the real one
                   14123:                                        Pname tn = Pclass(n->n_table->t_name->tp)->memtbl->look(n->string,0);
                   14124:                                        n = tn ? tn : n;
                   14125:                                }
                   14126:                                n->take_addr();
                   14127: 
                   14128:                                // suppress hoisting of local consts
                   14129:                                int statmem = n->n_scope==0 || n->n_scope==PUBLIC || n->n_scope == FCT;
                   14130:                                if (n->n_evaluated && n->n_scope!=ARG) { // &const
                   14131:                                        if (statmem == 0 && n->n_dcl_printed==0) {
                   14132:                                                n->n_initializer = new ival(n->n_val);
                   14133:                                                n->dcl_print(0);
                   14134:                                        }
                   14135:                                }
                   14136:                                else if (f->base==FCT && n->n_dcl_printed==0)
                   14137:                                        n->dcl_print(0);
                   14138:                                break;
                   14139:                        }
                   14140: 
                   14141:                        case ASSIGN:
                   14142: //error('d',"ass %n %d",n,n->n_used);
                   14143:                                n->n_used--;
                   14144:                                n->assign();
                   14145:                                break;
                   14146:                        //      goto check_void;
                   14147:                        default:        /* incr ops, and asops */
                   14148:                                if (cc->tot && n==cc->c_this) {
                   14149:                                        error("%n%k",n,oper);
                   14150:                                        return 0;
                   14151:                                }
                   14152:                //      check_void:
                   14153:                //              {       Ptype t = n->tp;
                   14154:                //                      while (t->base==TYPE) t = Pbase(t)->b_name->tp;
                   14155:                //                      if (t==Pvoid_type) {
                   14156:                //                              error("%s%t",es,n->tp);
                   14157:                //                              return 0;
                   14158:                //                      }
                   14159:                //              }
                   14160:                                n->assign();
                   14161:                        }
                   14162:                        return 1;
                   14163:                }
                   14164:        }
                   14165: }
                   14166: 
                   14167: int char_to_int(char* s)
                   14168: /*     assume s points to a string:
                   14169:                'c'
                   14170:        or      '\c'
                   14171:        or      '\0'
                   14172:        or      '\ddd'
                   14173:        or multi-character versions of the above
                   14174:        (hex constants have been converted to octal by the parser)
                   14175: */
                   14176: {
                   14177:        register int i = 0;
                   14178:        register char c, d, e;
                   14179: 
                   14180:        switch (*s) {
                   14181:        default:
                   14182:                error('i',"char constant store corrupted");
                   14183:        case '`':
                   14184:                error("bcd constant");
                   14185:                return 0;
                   14186:        case '\'':
                   14187:                break;
                   14188:        }
                   14189: 
                   14190:        for(;;)                 /* also handle multi-character constants */
                   14191:        switch (c = *++s) {
                   14192:        case '\'':
                   14193:                return i;
                   14194:        case '\\':                      /* special character */
                   14195:                switch (c = *++s) {
                   14196:                case '0': case '1': case '2': case '3': case '4':
                   14197:                case '5': case '6': case '7':   /* octal representation */
                   14198:                        c -= '0';
                   14199:                        switch (d = *++s) {             /* try for 2 */
                   14200:                                
                   14201:                        case '0': case '1': case '2': case '3': case '4':
                   14202:                        case '5': case '6': case '7':
                   14203:                                d -= '0';
                   14204:                                switch (e = *++s) {     /* try for 3 */
                   14205:                                        
                   14206:                                case '0': case '1': case '2': case '3': case '4':
                   14207:                                case '5': case '6': case '7':
                   14208:                                        c = c*64+d*8+e-'0';
                   14209:                                        break;
                   14210:                                default:
                   14211:                                        c = c*8+d;
                   14212:                                        s--;
                   14213:                                }
                   14214:                                break;
                   14215:                        default:
                   14216:                                s--;
                   14217:                        }
                   14218:                        break;
                   14219:                case 'a':
                   14220:                        c = '\a';
                   14221:                        break;
                   14222:                case 'b':
                   14223:                        c = '\b';
                   14224:                        break;
                   14225:                case 'f':
                   14226:                        c = '\f';
                   14227:                        break;
                   14228:                case 'n':
                   14229:                        c = '\n';
                   14230:                        break;
                   14231:                case 'r':
                   14232:                        c = '\r';
                   14233:                        break;
                   14234:                case 't':
                   14235:                        c = '\t';
                   14236:                        break;
                   14237:                case 'v':
                   14238:                        c = '\v';
                   14239:                        break;
                   14240:                case '\\':
                   14241:                        c = '\\';
                   14242:                        break;
                   14243:                case '\'':
                   14244:                        c = '\'';
                   14245:                        break;
                   14246:                }
                   14247:                /* no break */
                   14248:        default:
                   14249:                if (i) i <<= BI_IN_BYTE;
                   14250:                i += c;
                   14251:        }
                   14252: }
                   14253: 
                   14254: const A10 = 'A'-10;
                   14255: const a10 = 'a'-10;
                   14256: 
                   14257: long str_to_long(register const char* p)
                   14258: {
                   14259:        register c;
                   14260:        register unsigned long i= 0;
                   14261:        const char* pp = p;
                   14262: 
                   14263: // error( 'd', "str_to_long: %s", p );
                   14264: 
                   14265:        if ((c=*p++) == '0') {
                   14266:                switch (c = *p++) {
                   14267:                case 0:
                   14268:                        return 0;
                   14269: 
                   14270:                case 'l':
                   14271:                case 'L':       /* long zero */
                   14272:                        return 0;
                   14273: 
                   14274:                case 'x':
                   14275:                case 'X':       /* hexadecimal */
                   14276:                        while (c=*p++) {
                   14277:                                switch (c) {
                   14278:                                case 'l':
                   14279:                                case 'L':
                   14280:                                case 'U':
                   14281:                                case 'u':
                   14282:                                        return i;
                   14283:                                case 'A':
                   14284:                                case 'B':
                   14285:                                case 'C':
                   14286:                                case 'D':
                   14287:                                case 'E':
                   14288:                                case 'F':
                   14289:                                        i = i*16 + c-A10;
                   14290:                                        break;
                   14291:                                case 'a':
                   14292:                                case 'b':
                   14293:                                case 'c':
                   14294:                                case 'd':
                   14295:                                case 'e':
                   14296:                                case 'f':
                   14297:                                        i = i*16 + c-a10;
                   14298:                                        break;
                   14299:                                default:
                   14300:                                        i = i*16 + c-'0';
                   14301:                                }
                   14302:                        }
                   14303:                        return i;
                   14304: 
                   14305:                default:        /* octal */
                   14306:                        do 
                   14307:                                switch (c) {
                   14308:                                case 'l':
                   14309:                                case 'L':
                   14310:                                case 'U':
                   14311:                                case 'u':
                   14312:                                        return i;
                   14313:                                default:
                   14314:                                        i = i*8 + c-'0';
                   14315:                                }
                   14316:                        while (c=*p++);
                   14317:                        return i;
                   14318:                }
                   14319:        }       
                   14320:                                /* decimal */
                   14321:        i = c-'0';
                   14322:        while (c=*p++)
                   14323:                switch (c) {
                   14324:                case 'l':
                   14325:                case 'L':
                   14326:                case 'U':
                   14327:                case 'u':
                   14328:                        return i;
                   14329:                default:
                   14330:                {       unsigned long ii = i;
                   14331:                        i = i*10 + c-'0';
                   14332:                        if (i<ii) goto bad;
                   14333:                }
                   14334:                }
                   14335:        return i;
                   14336: bad:
                   14337:        error("integer constant %s larger than the largest long",pp);
                   14338:        return i;
                   14339:        
                   14340:                
                   14341: }
                   14342: 
                   14343: bit type::is_unsigned()
                   14344: {
                   14345:        Ptype t = this;
                   14346:        while (t->base==TYPE) t = Pbase(t)->b_name->tp;
                   14347:        if (t->base == PTR) return 0;
                   14348:        return Pbase(t)->b_unsigned;
                   14349: }
                   14350: 
                   14351: char* Neval;
                   14352: bit binary_val;
                   14353: 
                   14354: unsigned long expr::ueval(long x1, long x2)
                   14355: {
                   14356:        unsigned long i1 = (unsigned long) x1;  
                   14357:        unsigned long i2 = (unsigned long) x2;
                   14358: //error('d',"ueval %k %ld %ld",base,x1,x2);
                   14359:        switch (base) {
                   14360:        case UMINUS:    return -i2;
                   14361:        case UPLUS:     return i2;
                   14362:        case NOT:       return !i2;
                   14363:        case COMPL:     return ~i2;
                   14364:        case CAST:      return i1;
                   14365:        case PLUS:      return i1+i2;
                   14366:        case MINUS:     return i1-i2;
                   14367:        case MUL:       return i1*i2;
                   14368:        case LS:        return i1<<i2;
                   14369:        case RS:        return i1>>i2;
                   14370:        case NE:        return i1!=i2;
                   14371:        case EQ:        return i1==i2;
                   14372:        case LT:        return i1<i2;
                   14373:        case LE:        return i1<=i2;
                   14374:        case GT:        return i1>i2;
                   14375:        case GE:        return i1>=i2;
                   14376:        case AND:       return i1&i2;
                   14377:        case ANDAND:    return i1&&i2;
                   14378:        case OR:        return i1|i2;
                   14379:        case OROR:      return i1||i2;
                   14380:        case ER:        return i1^i2;
                   14381:        case MOD:       if (i2 == 0) {
                   14382:                                if (Neval == 0) { 
                   14383:                                        Neval = "mod zero";
                   14384:                                        error("mod zero");
                   14385:                                }
                   14386:                                return 1;
                   14387:                        }
                   14388:                        return i1%i2;
                   14389:        case QUEST:     return (cond->eval()) ? i1 : i2;
                   14390:        case DIV:       if (i2 == 0) {
                   14391:                                if (Neval == 0) { 
                   14392:                                        Neval = "divide by zero";
                   14393:                                        error("divide by zero");
                   14394:                                }
                   14395:                                return 1;
                   14396:                        }
                   14397:                        return i1/i2;
                   14398:        case CM:
                   14399:        case G_CM:
                   14400:                return i2;
                   14401:        }
                   14402: 
                   14403:        Neval = "unsigned expression";
                   14404:        return 0;
                   14405: }
                   14406: 
                   14407: long expr::eval()
                   14408: {
                   14409:        if (Neval) return 1;
                   14410: // error('d',"eval %k",base);
                   14411: 
                   14412:        static int targno=0;
                   14413:        static int icallflag=0;
                   14414: 
                   14415:        switch (base) {
                   14416:        case ZERO:      return 0;
                   14417:        case IVAL:      return i1;
                   14418:        case ICON:      return str_to_long(string);
                   14419:        case CCON:      return char_to_int(string);
                   14420:        case FCON:      Neval = "float in constant expression"; return 1;
                   14421:        case STRING:    Neval = "string in constant expression"; return 1;
                   14422:        case EOBJ:      return Pname(this)->n_val;
                   14423:        case SIZEOF:
                   14424:                extern no_sizeof;
                   14425:                if (no_sizeof) Neval = "sizeof";
                   14426:                return tp2->tsizeof();
                   14427:                
                   14428:        case NAME:
                   14429:        {       Pname n = Pname(this);
                   14430: // error('d',"eval %n eval %d %d",n,n->n_evaluated,n->n_val);
                   14431: // error('d',"eval tp->tconst() %d, n->n_initializer: %k", n->tp->tconst(), n->n_initializer?n->n_initializer->base:0 );
                   14432:                if (n->n_evaluated && n->n_scope!=ARG) return n->n_val;
                   14433:                if (binary_val && strcmp(string,"_result")==0) return 8888;
                   14434:                Neval = "cannot evaluate constant";
                   14435:                return 1;
                   14436:        }
                   14437:        case ICALL:
                   14438:                if (e1) {
                   14439:                        icallflag=1;
                   14440:                        targno=0;
                   14441:                        il->i_next = curr_icall;
                   14442:                        curr_icall = il;
                   14443:                        long i = e1->eval();
                   14444:                        curr_icall = il->i_next;
                   14445:                        icallflag=0;
                   14446:                        return i;
                   14447:                }
                   14448:                Neval = "void inlineF";
                   14449:                return 1;
                   14450:        case ANAME:
                   14451:        {       Pname n = (Pname)this;
                   14452: 
                   14453: /*
                   14454:                int argno;
                   14455:                if (icallflag) {
                   14456:                argno=targno;
                   14457:                targno++;
                   14458:                }
                   14459: */
                   14460:                int argno = (int) n->n_val;
                   14461:        
                   14462:                Pin il;
                   14463:                for (il=curr_icall; il; il=il->i_next)
                   14464:                        if (il->i_table == n->n_table) goto aok;
                   14465:                goto bok;
                   14466:        aok:
                   14467:                if (il->i_args[argno].local) {
                   14468:        bok:
                   14469:                        Neval = "inlineF call too complicated for constant expression";
                   14470:                        return 1;
                   14471:                }
                   14472:                Pexpr aa = il->i_args[argno].arg;
                   14473:                return aa->eval();
                   14474:        }
                   14475:        case CAST:
                   14476:        {       if (e1->base==FCON && tp2->base!=FLOAT && tp2->base!=DOUBLE) {
                   14477:                        char* p = e1->string;
                   14478:                        while (*p!='.') p++;
                   14479:                        if (p==e1->string) *p++ = '0';
                   14480:                        *p = 0;
                   14481:                        e1->base = ICON;
                   14482:                }               
                   14483:                long i = e1->eval();
                   14484:                Ptype tt = tp2;
                   14485:        strip:
                   14486:                switch (tt->base) {
                   14487:                default:
                   14488:                        Neval = "cast to non-integral type in constant expression";
                   14489:                        break;
                   14490:                case TYPE:
                   14491:                        tt = Pbase(tt)->b_name->tp;
                   14492:                        goto strip;
                   14493:                case EOBJ:
                   14494:                case LONG:
                   14495:                case INT:
                   14496:                case CHAR:
                   14497:                case SHORT:
                   14498:                        i &= ~(((~(unsigned long)0)<<(BI_IN_BYTE*(tp2->tsizeof()-1)))<<BI_IN_BYTE);
                   14499:                        break;
                   14500:                }
                   14501:                return i;
                   14502:        }
                   14503:        case UMINUS:
                   14504:        case UPLUS:
                   14505:        case NOT:
                   14506:        case COMPL:
                   14507:        case PLUS:
                   14508:        case MINUS:
                   14509:        case MUL:
                   14510:        case LS:
                   14511:        case RS:
                   14512:        case NE:
                   14513:        case LT:
                   14514:        case LE:
                   14515:        case GT:
                   14516:        case GE:
                   14517:        case AND:
                   14518:        case OR:
                   14519:        case ER:
                   14520:        case DIV:
                   14521:        case MOD:
                   14522:        case QUEST:
                   14523:        case EQ:
                   14524:        case ANDAND:
                   14525:                break;
                   14526:        case OROR:
                   14527:                if (binary_val) {       // a||b, don't evaluate b if a!=0
                   14528:                        long i1 = (e1) ? e1->eval() : 0;
                   14529:                        if (Neval==0 && i1 && e1->tp->is_unsigned()==0) return i1;
                   14530:                }
                   14531:                break;
                   14532:        case CM:
                   14533:        case G_CM:
                   14534:                break;
                   14535:        case G_ADDROF:
                   14536:        case ADDROF:
                   14537:                if (binary_val) {       // beware of &*(T*)0
                   14538:                        switch (e2->base) {
                   14539:                        case NAME:
                   14540:                        case DOT:
                   14541:                        case REF:       return 9999;
                   14542:                        }
                   14543:                }
                   14544:        default:
                   14545:                Neval = "bad operator in constant expression";
                   14546:                return 1;
                   14547:        }
                   14548: 
                   14549:        long i1 = (e1) ? e1->eval() : 0;
                   14550:        long i2 = (e2) ? e2->eval() : 0;
                   14551: 
                   14552:        if (binary_val && i1==9999 && i2==9999) {
                   14553:                Neval = "";
                   14554:                return 1;
                   14555:        }
                   14556:        
                   14557:        if (Neval==0
                   14558:        && ((e1&&e1->tp->is_unsigned()) || (e2&&e2->tp->is_unsigned())))
                   14559:                return (long) ueval(i1,i2);
                   14560:        
                   14561:        switch (base) {
                   14562:        case UMINUS:    return -i2;
                   14563:        case UPLUS:     return i2;
                   14564:        case NOT:       return !i2;
                   14565:        case COMPL:     return ~i2;
                   14566:        case CAST:      return i1;
                   14567:        case PLUS:      return i1+i2;
                   14568:        case MINUS:     return i1-i2;
                   14569:        case MUL:       return i1*i2;
                   14570:        case LS:        return i1<<i2;
                   14571:        case RS:        return i1>>i2;
                   14572:        case NE:        return i1!=i2;
                   14573:        case EQ:        return i1==i2;
                   14574:        case LT:        return i1<i2;
                   14575:        case LE:        return i1<=i2;
                   14576:        case GT:        return i1>i2;
                   14577:        case GE:        return i1>=i2;
                   14578:        case AND:       return i1&i2;
                   14579:        case ANDAND:    return i1&&i2;
                   14580:        case OR:        return i1|i2;
                   14581:        case OROR:      return i1||i2;
                   14582:        case ER:        return i1^i2;
                   14583:        case MOD:       if (i2 == 0) {
                   14584:                                if (Neval == 0) { 
                   14585:                                        Neval = "mod zero";
                   14586:                                        error("mod zero");
                   14587:                                }
                   14588:                                return 1;
                   14589:                        }
                   14590:                        return i1%i2;
                   14591:        case QUEST:     return (cond->eval()) ? i1 : i2;
                   14592:        case DIV:       if (i2 == 0) {
                   14593:                                if (Neval == 0) { 
                   14594:                                        Neval = "divide by zero";
                   14595:                                        error("divide by zero");
                   14596:                                }
                   14597:                                return 1;
                   14598:                        }
                   14599:                        return i1/i2;
                   14600:        case CM:
                   14601:        case G_CM:
                   14602:                return i2;
                   14603:        }
                   14604: }
                   14605: bit classdef::baseof(Pname f)
                   14606: /*
                   14607:        is ``this'' class a public base class of "f"'s class
                   14608:        or its immediate base class
                   14609: */
                   14610: {
                   14611:        Ptable ctbl = f->n_table;
                   14612:        Pname b = ctbl->t_name;
                   14613: 
                   14614:        if (b == 0) return 0;
                   14615:        Pclass cl = Pclass(b->tp);
                   14616:        if (cl == 0) return 0;
                   14617:        if (cl == this) return 1;
                   14618:        ppbase = PUBLIC;
                   14619:        Pclass bcl = is_base(cl->string);
                   14620:        return (bcl && ppbase==PUBLIC);
                   14621: }
                   14622: 
                   14623: bit classdef::baseof(Pclass cl)
                   14624: /*
                   14625:        is ``this'' class a public base class of "cl"
                   14626: */
                   14627: {
                   14628:        if (cl == 0) return 0;
                   14629:        if (cl == this) return 1;
                   14630:        ppbase = PUBLIC;
                   14631:        Pclass bcl = is_base(cl->string);
                   14632:        return (bcl && ppbase==PUBLIC);
                   14633: }
                   14634: 
                   14635: static int mem_match(Pfct f1, Pfct f2)
                   14636: /*
                   14637:        check class membership.
                   14638: 
                   14639:        For some reason checking f_this==0 works and f_static doesn't
                   14640: */
                   14641: {
                   14642: //     if (f1->memof) return f2->f_this ?f2->memof==f1->memof : 0;
                   14643: //     if (f1 && f1->memof) return f2->f_this?f2->memof==f1->memof : 0;
                   14644: //     return f2->f_this==0;
                   14645:        if (f1==0 || f2==0) return 0;
                   14646:        if (f1->memof && f2->f_this && f2->memof!=f1->memof) return 0;
                   14647:        if (f2->f_this) return 0;
                   14648:        if (f1->memof && f2->f_static) return 0;
                   14649:        if (f1->check(f2,ASSIGN)) return 0;
                   14650:        return 1;
                   14651: }
                   14652: 
                   14653: int Pchecked;
                   14654: 
                   14655: Pexpr ptof(Pfct ef, Pexpr e, Ptable tbl)
                   14656: /*
                   14657:        a kludge: initialize/assign-to pointer to function
                   14658: */
                   14659: {
                   14660:        Pfct f;
                   14661:        Pname n = 0;
                   14662: eee:
                   14663: //error('d',"ptof %t %t %k",ef,e->tp,e->base);
                   14664:        switch (e->base) {
                   14665:        case QUEST:
                   14666:                e->e1 = ptof(ef,e->e1,tbl);
                   14667:                e->e2 = ptof(ef,e->e2,tbl);
                   14668:                return e;
                   14669:        case CM:
                   14670:        case G_CM:
                   14671:                e->e2 = ptof(ef,e->e2,tbl);
                   14672:                return e;
                   14673:        case NAME:
                   14674:                f = Pfct(e->tp);
                   14675:                Pname nn = Pname(e);
                   14676: 
                   14677:                switch (f->base) {
                   14678:                case OVERLOAD:
                   14679:                        e = Pgen(f)->find(ef,0);
                   14680:                        if (e == 0) {
                   14681:                                error("cannot deduceT for &overloaded%n",nn);
                   14682:                                return e;
                   14683:                        }
                   14684:                //      e = n;
                   14685:                        // no break
                   14686:                case FCT:
                   14687:                        Pchecked = mem_match(ef,Pfct(e->tp));
                   14688:                        e = new expr(G_ADDROF,0,e);
                   14689:                        return e->typ(tbl);     // handle &B::f
                   14690:                        //e->tp = f;
                   14691:                }
                   14692:                goto ad;
                   14693: 
                   14694:        case ZERO:
                   14695:                if (ef->memof) {
                   14696:                        e = new expr(ELIST,zero,zero);
                   14697:                        e = new expr(ILIST,e,zero);
                   14698:                        e->tp = zero_type;
                   14699:                        return e; 
                   14700:                }
                   14701:                break;
                   14702: 
                   14703:        case MDOT:
                   14704:                // ?? error('s',"P toM of not firstB");
                   14705:                do e = e->mem; while (e->base == MDOT);
                   14706:                goto eee;
                   14707: 
                   14708:        case DOT:
                   14709:        case REF:
                   14710:                f = Pfct(e->mem->tp);
                   14711: 
                   14712:                switch (f->base) {
                   14713:                case OVERLOAD:
                   14714:                        n = Pgen(f)->find(ef,0);
                   14715:                        if (n == 0) error("cannot deduceT for &overloaded%n",e->mem);
                   14716:                        else e = n;
                   14717:                        // no break
                   14718:                case FCT:
                   14719:                        Pchecked = mem_match(ef,Pfct(e->tp));
                   14720:                        e = new expr(G_ADDROF,0,e);
                   14721:                        return e->typ(tbl);     // handle &B::f
                   14722:                //      n = Pname(e->mem);
                   14723:                //      e = n->address();
                   14724:                }
                   14725:                goto ad;
                   14726: 
                   14727:        case ADDROF:
                   14728:        case G_ADDROF:
                   14729:                f = Pfct(e->e2->tp);
                   14730:        ad:
                   14731:                if (f->base == OVERLOAD) {
                   14732:                        n = Pgen(f)->find(ef,0);
                   14733:                        if (n == 0) error("cannot deduceT for &overloaded %s()",Pgen(f)->fct_list->f->string);
                   14734:                        Pchecked = mem_match(ef,Pfct(n->tp));
                   14735:                        e->e2 = n;
                   14736:                        e->tp = n->tp;
                   14737:                }
                   14738:                if (n) n->lval(ADDROF);
                   14739:                break;
                   14740: 
                   14741:        case CAST:
                   14742:        {
                   14743:                Pexpr te = e->e1;
                   14744:                if (e->e1->base == G_ADDROF) te = e->e1->e2;
                   14745:                (void) ptof(ef,te,tbl);
                   14746:        }
                   14747:        }
                   14748:        return e;
                   14749: }
                   14750: 
                   14751: Pexpr ptr_init(Pptr p, Pexpr init, Ptable tbl)
                   14752: /*
                   14753:        check for silly initializers
                   14754: 
                   14755:        char* p = 0L;    ??     fudge to allow redundant and incorrect `L'
                   14756:        char* p = 2 - 2; ??     worse
                   14757: */
                   14758: {
                   14759: // error('d',"ptr_init: p=%t init->tp=%t init->base %k",p,init->tp,init->base);
                   14760: 
                   14761:        Pchecked = 0;
                   14762: 
                   14763:        Ptype it = init->tp;
                   14764: itl:
                   14765:        switch (it->base) {
                   14766:        case TYPE:
                   14767:                it = Pbase(it)->b_name->tp; goto itl;
                   14768:        case ZTYPE:
                   14769: //             if (init == zero) break;
                   14770:                break;
                   14771:        case EOBJ:
                   14772:        case INT:
                   14773:        case CHAR:
                   14774:        case SHORT:
                   14775:        case LONG:
                   14776:        {       Neval = 0;
                   14777:                long i = init->eval();
                   14778:                if (Neval)
                   14779:                        error("badPIr: %s",Neval);
                   14780:                else
                   14781:                if (i)
                   14782:                        error("badPIr value %d",i);
                   14783:                else {
                   14784:                        DEL(init);
                   14785:                        init = zero;
                   14786:                }
                   14787:                break;
                   14788:        }               
                   14789:        }
                   14790: 
                   14791:        Pclass c1 = p->memof;
                   14792: 
                   14793:        if (c1) {
                   14794:                if (init==zero)
                   14795:                        ;
                   14796:                else {
                   14797:                        Pclass c2;
                   14798: // error('d',"it %t %d",it,it->base);
                   14799:                        switch (it->base) {
                   14800:                        case FCT:
                   14801:                                c2 = Pfct(it)->memof;
                   14802:                                break;
                   14803:                        case OVERLOAD:
                   14804:                                c2 = Pfct(Pgen(it)->fct_list->f->tp)->memof;
                   14805:                                break;
                   14806:                        case PTR:
                   14807:                        case RPTR:
                   14808:                                c2 = Pptr(it)->memof;
                   14809:                                break;
                   14810:                        default:
                   14811:                                c2 = 0;
                   14812:                        }
                   14813: 
                   14814:                        if (c2 == 0) {
                   14815:                                // initialization by &A::f
                   14816: //error('d',"curious");
                   14817:                        }
                   14818:                        else if (c1 != c2) {
                   14819:                                 Nptr = 0;
                   14820:                                Noffset = 0;
                   14821:                                vcllist->clear();
                   14822:                                vcllist=0;
                   14823:                                int u1 = is_unique_base(c1,c2->string,0);
                   14824: //error('d',"c1 %t c2 %t u1 %d off %d",c1,c2,u1,Noffset);
                   14825:                                 if (u1 && (Nptr || Noffset)) {
                   14826:                                        // requires offset manipulation
                   14827:                                        int bad = 0;
                   14828:                                        if (u1 == 1 && !Nptr) {
                   14829:                                                if (init->base==ILIST) {
                   14830:                                                        // d = d+Noffset;
                   14831:                                                        switch (init->e1->e1->base) {
                   14832:                                                                case IVAL:
                   14833:                                                                        init->e1->e1->i1 += Noffset;
                   14834:                                                                        break;
                   14835:                                                                case ZERO:
                   14836:                                                                        init->e1->e1 = new ival(Noffset);
                   14837:                                                                        break;
                   14838:                                                                default:
                   14839:                                                                        bad = 1;
                   14840:                                                                }
                   14841: 
                   14842:                                                        // if (i<0) f = vptroffset
                   14843:                                                        switch (init->e1->e2->base) {
                   14844:                                                                case IVAL:
                   14845:                                                                        if (0<init->e1->e2->i1) {
                   14846:                                                                        // extern Ptype Pfct_type;
                   14847:                                                                        // store vptr offset
                   14848:                                                                        //  init->e2=new cast(Pfct_type,zero);
                   14849:                                                                        }
                   14850:                                                                        else
                   14851:                                                                                break;
                   14852:                                                                default:
                   14853:                                                                        bad = 1;
                   14854:                                                                }       
                   14855:                                                } // end if (init->base==ILIST)
                   14856:                                                else
                   14857:                                                        bad = 1;
                   14858:                                        } // end if (u1 == 1 ...
                   14859:                                        else
                   14860:                                                bad = 1;
                   14861: 
                   14862:                                if (bad) error('s',"%t assigned to %t (too complicated)",init->tp,p);
                   14863:                                } // end if (u1 && ...
                   14864: 
                   14865:                                 Nptr = 0;
                   14866:                                Noffset = 0;
                   14867:                                vcllist->clear();
                   14868:                                vcllist=0;
                   14869:                                int u2 = is_unique_base(c2,c1->string,0);
                   14870: //error('d',"c1 %t c2 %t u2 %d off %d",c1,c2,u2,Noffset);
                   14871:                                 if (u2 && (Nptr || Noffset)) {
                   14872:                                        // requires offset manipulation
                   14873:                                        error('s',"%t assigned to %t",init->tp,p);
                   14874:                                }
                   14875:                        } // end if (c1 != c2
                   14876:                } // end else
                   14877:        } // end if (c1)
                   14878: 
                   14879:        Ptype pit = p->typ;
                   14880: lll:
                   14881: // error('d',"p %t pit %t",p,pit);
                   14882:        switch (pit->base) {
                   14883:        case TYPE:
                   14884:                pit = Pbase(pit)->b_name->tp;
                   14885:                goto lll;
                   14886:        case FCT:
                   14887:                return ptof(Pfct(pit),init,tbl);
                   14888:        case COBJ:
                   14889:        {       Pptr r;
                   14890: // error('d',"cobj: ptr %t, ref %t",it->is_ptr(),it->is_ref());
                   14891:                if (r=it->is_ptr_or_ref()) {
                   14892:                        Pchecked = 1;
                   14893:                        TOK b = p->base;                // could be REF
                   14894:                        TOK bb = r->base;
                   14895:                        if (b==RPTR) p->base = PTR;
                   14896:                        if (bb==RPTR) r->base = PTR;
                   14897:                        if (p->check(r,ASSIGN)) {
                   14898:                                if ( cc && cc->nof && 
                   14899:                                        Pfct(cc->nof->tp)->f_const &&
                   14900:                                        cc->c_this == init )
                   14901:                                                error("%n const: assignment of%n (%t) to%t",cc->nof,init,init->tp,p);
                   14902:                                else
                   14903:                                        error("no standard conversion of %t to %t",init->tp,p);
                   14904:                        }
                   14905:                        p->base = b;
                   14906:                        r->base = bb;
                   14907:                        Pexpr cp = cast_cptr(Pclass(Pbase(pit)->b_name->tp),init,tbl,0);
                   14908:                        if (cp != init) {
                   14909:                                PERM(p);        // or else it will be deleted twice!
                   14910:                                return new cast(p,cp);
                   14911:                        }
                   14912:                }
                   14913:                // no break
                   14914:        }
                   14915:        default:
                   14916:                return init;
                   14917:        }
                   14918: }
                   14919: 
                   14920: static Pname Lcoerce, Rcoerce;
                   14921: extern int suppress_error;
                   14922: 
                   14923: int try_to_demote(TOK oper, Ptype t1, Ptype t2)
                   14924: /*
                   14925:        look at t1 and t2 and see if there are ``demotions'' of t1 and/or t2
                   14926:        so that ``t1 oper t2'' can be made legal
                   14927: 
                   14928:        return  0 is not
                   14929:                1 if there is exactly one way
                   14930:                >1 if there is more than one way (if in doubt return 2)
                   14931: */
                   14932: {
                   14933: //error('d',"try_to_demote(%k : %t : %t)",oper,t1,t2);
                   14934: 
                   14935:        Pname n1 = t1 ? t1->is_cl_obj() : 0;
                   14936:        Pclass c1 = n1 ? Pclass(n1->tp) : 0;
                   14937:        Pname n2 = t2 ? t2->is_cl_obj() : 0;
                   14938:        Pclass c2 = n2 ? Pclass(n2->tp) : 0;
                   14939: 
                   14940:        Ptype lt = t1;
                   14941:        Ptype rt = t2;
                   14942: 
                   14943:        Lcoerce = Rcoerce = 0;
                   14944: 
                   14945: //     if (oper == DOT) return 0;
                   14946: 
                   14947:        if (c1)
                   14948:                switch (oper) {
                   14949:                case ASSIGN:
                   14950:                case ASPLUS:
                   14951:                case ASMINUS:
                   14952:                case ASMUL:
                   14953:                case ASDIV:
                   14954:                case ASMOD:
                   14955:                case ASAND:
                   14956:                case ASOR:
                   14957:                case ASER:
                   14958:                case ASLS:
                   14959:                case ASRS:      // don't coerce left hand side of assignment
                   14960:                //      c1 = 0;
                   14961:                        if (c1->memtbl->look("__as",0)) return 0;
                   14962:                }
                   14963:        else
                   14964:                switch (oper) {
                   14965:                case ADDROF:
                   14966:                case INCR:
                   14967:                case DECR:      // don't coerce unary requiring an lval
                   14968:                        return 0;
                   14969:                }
                   14970: 
                   14971:        if (c1) {
                   14972: //error('d',"c1 %t",c1);
                   14973:                for (Pname on1 = c1->conv; on1; on1=on1->n_list) {
                   14974: // error( 'd', "on1: %s tp: %k", on1->string, on1->tp->base );
                   14975:                        Pfct f = Pfct(on1->tp);
                   14976:                        lt = f->base==FCT ? f->returns :
                   14977:                                Pfct(Pgen(on1->tp)->fct_list->f->tp)->returns;
                   14978:                        Pname cn = lt->is_cl_obj();
                   14979: 
                   14980:                        if (cn && (Lcoerce==0 || Lcoerce->tp->check(f,0))) {
                   14981:                                Pclass cl = Pclass(cn->tp);
                   14982:                                Pname n = cl->has_oper(oper);
                   14983:                                if (n == 0) continue;
                   14984:                //              while (n->base==REF || n->base==MDOT) n=Pname(n->mem) ;
                   14985:                                Pfct nf = Pfct(n->tp);
                   14986: // error( 'd', "nf: %d %k", nf->base, nf->base );
                   14987:                                if (nf->base == FCT) {
                   14988:                                        if (nf->nargs==1
                   14989:                                        && t2
                   14990:                                        && (nf->argtype->tp->check(t2,ARG)==0
                   14991:                                                || can_coerce(nf->argtype->tp,t2)==1)
                   14992:                                        ) {
                   14993:                                                if (Lcoerce) return 2;
                   14994:                                                Lcoerce = on1;
                   14995:                                        }
                   14996:                                }
                   14997:                                else {
                   14998:                                        for (Plist gl=Pgen(nf)->fct_list; gl; gl=gl->l) {
                   14999:                                                Pfct nf = Pfct(gl->f->tp);
                   15000:                                                if (nf->nargs==1
                   15001:                                                && t2
                   15002:                                                && (nf->argtype->tp->check(t2,ARG)==0
                   15003:                                                        || can_coerce(nf->argtype->tp,t2)==1)
                   15004:                                                ) {
                   15005:                                                        if (Lcoerce) return 2;
                   15006:                                                        Lcoerce = on1;
                   15007:                                                }
                   15008:                                        }
                   15009:                                }
                   15010:                                continue;
                   15011:                        }
                   15012:                        //if (lt->is_cl_obj()) continue;
                   15013:                        if (c2) {
                   15014: //error('d',"c2 %t",c2);
                   15015:                                for (Pname on2 = c2->conv; on2; on2=on2->n_list) {
                   15016:                                        Pfct f = Pfct(on2->tp);
                   15017:                                        rt = f->base==FCT ? f->returns :
                   15018:                                                Pfct(Pgen(on2->tp)->fct_list->f->tp)->returns;
                   15019:                                        if (rt->is_cl_obj()) continue;
                   15020: 
                   15021:                                        suppress_error = 1;
                   15022:                                        int r1 = lt->kind(oper,0);
                   15023:                                        int r2 = rt->kind(oper,0);
                   15024:                                        if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) {
                   15025:                                                Pname sn = on1;
                   15026:                                                if (Lcoerce) {
                   15027:                                                    Pname tn = really_dominate(
                   15028:                                                        Lcoerce, 
                   15029:                                                        on1, 
                   15030:                                                        const_obj1
                   15031:                                                    );
                   15032:                                                    if(!tn) {
                   15033:                                                        suppress_error = 0;
                   15034:                                                        return 2;
                   15035:                                                    }
                   15036:                                                    else sn = tn;
                   15037:                                                }
                   15038:                                                Lcoerce = sn;
                   15039:                                                Rcoerce = on2;
                   15040:                                        
                   15041:                                        }
                   15042:                                        suppress_error = 0;
                   15043:                                }
                   15044:                                        
                   15045:                        }
                   15046:                        else if (rt) {
                   15047:                                suppress_error = 1;
                   15048:                                int r1 = lt->kind(oper,0);
                   15049:                                int r2 = rt->kind(oper,0);
                   15050:                                if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) {
                   15051:                                        Pname sn = on1;
                   15052:                                        if (Lcoerce) {
                   15053:                                                Pname tn = really_dominate(
                   15054:                                                        Lcoerce, 
                   15055:                                                        on1, 
                   15056:                                                        const_obj1
                   15057:                                                );
                   15058:                                                if(!tn) {
                   15059:                                                        suppress_error = 0;
                   15060:                                                        return 2;
                   15061:                                                }
                   15062:                                                else sn = tn;
                   15063:                                        }
                   15064:                                        Lcoerce = sn;
                   15065:                                }
                   15066:                                suppress_error = 0;
                   15067:                        }
                   15068:                        else {
                   15069:                                Pname sn = on1;
                   15070:                                if (Lcoerce) {
                   15071:                                        Pname tn = really_dominate(
                   15072:                                                Lcoerce, 
                   15073:                                                on1, 
                   15074:                                                const_obj1
                   15075:                                        );
                   15076:                                        if(!tn) return 2;
                   15077:                                        else sn = tn;
                   15078:                                }
                   15079:                                Lcoerce = sn;
                   15080:                        }
                   15081:                }
                   15082:        }
                   15083:        else if (c2) {
                   15084: //error('d',"c2 %n",c2);
                   15085:                for (Pname on = c2->conv; on; on=on->n_list) {
                   15086:                        Pfct f = Pfct(on->tp);
                   15087:                        rt = f->base==FCT ? f->returns :
                   15088:                                Pfct(Pgen(on->tp)->fct_list->f->tp)->returns;
                   15089:                        Pname cn = rt->is_cl_obj();
                   15090: //error('d',"cn %n",cn);
                   15091:                        if (cn && (Rcoerce==0 || Rcoerce->tp->check(f,0))) {
                   15092:                                Pclass cl = Pclass(cn->tp);
                   15093:                                Pname n = cl->has_oper(oper);
                   15094:                                if (n == 0) continue;
                   15095: 
                   15096:                //              while (n->base==REF || n->base==MDOT) n=Pname(n->mem);
                   15097:                                Pfct nf = Pfct(n->tp);
                   15098:                                if (nf->base == FCT) {
                   15099:                                        if (nf->nargs == 0) {
                   15100:                                                if (Lcoerce || Rcoerce) return 2;
                   15101:                                                Rcoerce = on;
                   15102:                                        }
                   15103:                                }
                   15104:                                else {
                   15105:                                        for (Plist gl=Pgen(nf)->fct_list; gl; gl=gl->l) 
                   15106:                                                if (Pfct(gl->f->tp)->nargs == 0) {
                   15107:                                                        if (Lcoerce || Rcoerce) return 2;
                   15108:                                                        Rcoerce = on;
                   15109:                                                }
                   15110:                                }
                   15111:                                continue;
                   15112:                        }
                   15113:                        //if (rt->is_cl_obj()) continue;
                   15114:                        if( lt ) {
                   15115:                                suppress_error = 1;
                   15116:                                int r1 = lt->kind(oper,0);
                   15117:                                int r2 = rt->kind(oper,0);
                   15118: 
                   15119:                                if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) {
                   15120:                                        Pname sn = on;
                   15121:                                        if (Lcoerce || Rcoerce) {
                   15122:                                                Pname tn = really_dominate(
                   15123:                                                        Rcoerce, 
                   15124:                                                        on, 
                   15125:                                                        const_obj2
                   15126:                                                );
                   15127:                                                if(!tn) {
                   15128:                                                        suppress_error = 0;
                   15129:                                                        return 2;
                   15130:                                                }
                   15131:                                                else sn = tn;
                   15132:                                        }
                   15133:                                        Rcoerce = sn;
                   15134:                                }
                   15135:                                suppress_error = 0;
                   15136:                        }
                   15137:                }
                   15138:        }
                   15139: 
                   15140: //error('d',"->%d || %d",Lcoerce,Rcoerce);
                   15141:        return (Lcoerce || Rcoerce);
                   15142: }
                   15143: 
                   15144: Pexpr expr::try_to_overload(Ptable tbl)
                   15145: {
                   15146: //     TOK bb = (base==DEREF && e2==0) ? MUL : base;
                   15147: // error('d',"try_to_overload %k %d",base,base);
                   15148: 
                   15149:        Pname n1 = 0;
                   15150:        Ptype t1 = 0;
                   15151:        const_obj1 = 0;
                   15152:        const_obj2 = 0;
                   15153: 
                   15154:        if (e1) {
                   15155:                t1 = e1->tp;
                   15156:                Ptype tpx = t1;
                   15157:                while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp;
                   15158:                n1 = tpx->is_cl_obj();
                   15159:                const_obj1 = t1->tconst();
                   15160: 
                   15161:                Pexpr ee = e1;
                   15162:                 while (ee && (ee->base==DOT || ee->base==REF)) {
                   15163:                                Pexpr m = ee->mem;
                   15164:                                if ( ee->base==REF && m->tp &&  m->tp->is_ptr())
                   15165:                                        break;
                   15166:                                ee = ee->e1;
                   15167:                 }
                   15168:                 if (ee) {
                   15169:                        int tc;
                   15170:                                Ptype ttt = ee->tp;
                   15171:                                switch (e1->base) {
                   15172:                                case REF:
                   15173:                                        Pptr p = ttt?ttt->is_ptr():0;
                   15174:                                        if (p && p->typ->tconst())
                   15175:                                                const_obj1 = 1;
                   15176:                                        break;
                   15177:                                case DOT:
                   15178:                                tc = ttt ? ttt->tconst() : 0;
                   15179:                                        if (ttt && tc && (!strict_opt || tc!=2))
                   15180:                                                const_obj1 = 1;
                   15181:                                }
                   15182:                 }
                   15183:        }
                   15184: 
                   15185:        TOK bb = base;
                   15186:        switch (bb) {
                   15187:        case DEREF:
                   15188:                if (e2 == 0) bb = MUL;
                   15189:                // no break;
                   15190:        case CALL:
                   15191:        case G_CALL:
                   15192:                if (n1 == 0) return 0;  // ignore type of argument list
                   15193:        }
                   15194: 
                   15195:        Pname n2 = 0;
                   15196:        Ptype t2 = 0;
                   15197: 
                   15198:        if (e2 && e2->base!=ELIST) {
                   15199:                t2 = e2->tp;
                   15200:                Ptype tpx = t2;
                   15201:                while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp;
                   15202:                n2 = tpx->is_cl_obj();
                   15203:                const_obj2 = t2->tconst();
                   15204:                Pexpr ee = e2;
                   15205:                 while (ee && (ee->base==DOT || ee->base==REF)) {
                   15206:                                Pexpr m = ee->mem;
                   15207:                                if ( ee->base==REF && m->tp &&  m->tp->is_ptr())
                   15208:                                        break;
                   15209:                                ee = ee->e1;
                   15210:                 }
                   15211:                 if (ee) {
                   15212:                        int tc;
                   15213:                                Ptype ttt = ee->tp;
                   15214:                                switch (e2->base) {
                   15215:                                case REF:
                   15216:                                        Pptr p = ttt?ttt->is_ptr():0;
                   15217:                                        if (p && p->typ->tconst())
                   15218:                                                const_obj2 = 1;
                   15219:                                        break;
                   15220:                                case DOT:
                   15221:                                tc = ttt ? ttt->tconst() : 0;
                   15222:                                        if (ttt && tc && (!strict_opt || tc!=2))
                   15223:                                                const_obj2 = 1;
                   15224:                                }
                   15225:                 }
                   15226:        }
                   15227: 
                   15228:        if (n1==0 && n2==0) return 0;
                   15229:        if (n1 && n1->tp == 0) return 0;        // make_assign() fudge
                   15230: // error('d',"e1: %k e2: %k", e1?e1->base:0, e2?e2->base:0 );
                   15231: // error('d',"t1 %t t2 %t",t1,t2);
                   15232: // error('d',"n1 %n n2 %n",n1,n2);
                   15233:        /* first try for non-member function:   op(e1,e2) or op(e2) or op(e1) */
                   15234:        Pexpr oe2 = e2;
                   15235:        Pexpr ee2 = (e2 && e2->base!=ELIST) ? e2 = new expr(ELIST,e2,0) : 0;
                   15236:        Pexpr ee1 = e1 ? new expr(ELIST,e1,e2) : ee2;
                   15237:        char* obb = oper_name(bb);
                   15238:        Pname gname = tbl->look(obb,0);
                   15239:        // if necessary check for ambiguities
                   15240:        int go = gname ? over_call(gname,ee1) : 0;
                   15241: //error('d',"go %d",go);
                   15242:        if (go) gname = Nover;
                   15243: 
                   15244:        if (n1) {
                   15245:                if (bb == ASSIGN) {
                   15246:                        Pclass c1 = Pclass(n1->tp);
                   15247: //error('d',"look %k %d",bb,c1->memtbl->look(obb,0));
                   15248:                        if (c1->memtbl->look(obb,0)==0) {
                   15249:                                Pclass bcl = c1->baselist?c1->baselist->bclass:0;
                   15250:                                if (n2==0
                   15251:                                || (Pclass(n2->tp)!=c1
                   15252:                                        && Pclass(n2->tp)->has_base(c1)==0)) {
                   15253:                                        // if legal, a=1 can be optimized to a.ctor(1)
                   15254:                                                if (2 < go) goto glob;
                   15255:                                                return 0;
                   15256:                                        }
                   15257: 
                   15258:                                if (bcl
                   15259:                                && c1->obj_size!=bcl->obj_size
                   15260:                                && bcl->memtbl->look(obb,0)) {
                   15261:                                        // cannot inherit from smaller base class
                   15262:                                //      make_assignment(n1);
                   15263:                                //      return try_to_overload(tbl);
                   15264:                                        goto mkas;
                   15265:                                }
                   15266: 
                   15267:                                if (c1->c_xref&(C_VBASE|C_VPTR|C_ASS)) {
                   15268:                                        // make operator=() if
                   15269:                                        //      no base (shouldn't happen
                   15270:                                        //      different (smaller) sized base
                   15271:                                        //      two bases
                   15272:                                mkas:
                   15273:                                        if (2 < go) goto glob;
                   15274:                                //      make_assignment(n1);
                   15275:                                //      return try_to_overload(tbl);
                   15276:                                        return make_assignment(n1) ? try_to_overload(tbl) : 0;
                   15277:                                }
                   15278: // error('d',"n2 %n",n2);
                   15279:                        //      if (n2 && Pclass(n2->tp)==c1)
                   15280:                                return 0;
                   15281:                        }
                   15282:                        // now take care of other assignments, 
                   15283:                }
                   15284: 
                   15285:                int dbconv = 0;
                   15286:                Pclass ccl = Pclass(n1->tp);
                   15287:                // Pexpr mn = Pclass(n1->tp)->memtbl->look(obb,0);
                   15288:                Pexpr mn = ccl->memtbl->look(obb,0);
                   15289: // error('d', "tcl %d %t cl %d %t", tcl, tcl, ccl, ccl);
                   15290:                if(strcmp(obb,"__as")) {
                   15291:                        tcl = ccl; // ugh!!! 
                   15292:                        if(!mn) dbconv = 2;
                   15293:                }
                   15294: //             tcl = ccl; // ugh!!! 
                   15295:                mn = ccl->find_name(obb,0);
                   15296: 
                   15297:                Pname mname = Pname(mn);
                   15298: // error('d',"mn %n %d %k %s",mname,mn,mn?mn->base:0,obb);
                   15299:                if (mname == 0) goto glob;
                   15300: 
                   15301:        zaq:
                   15302:                switch (mname->base) {
                   15303:                case REF:
                   15304:                case MDOT:
                   15305:                        mname = Pname(Pexpr(mname)->mem);
                   15306:                        goto zaq;
                   15307:                }
                   15308: 
                   15309:                int mo = over_call(mname,e2);
                   15310:                int smo = mo;
                   15311:                if(mo && dbconv && mo >= dbconv) mo = dbconv;
                   15312: //error('d',"mo %d (go %d)",mo,go);
                   15313:                if (mo==0 || mo<go)
                   15314:                        goto glob;
                   15315:                else if (mo && mo==go) {
                   15316: //error('d',"t1 %t t2 %t",t1,t2);
                   15317:                        if (gname->tp->base == OVERLOAD) { // find right version
                   15318:                                for (Plist l = Pgen(gname->tp)->fct_list; l; l=l->l) {
                   15319:                                        Pname n = l->f;
                   15320:                                        int x = over_call(n,ee1);
                   15321:                                        if (x == go) {
                   15322:                                                gname = n;
                   15323:                                                break;
                   15324:                                        }
                   15325:                                }
                   15326:                        }
                   15327: //error('d',"gname %n: %t",gname,gname->tp);
                   15328:                        Pname aa = Pfct(gname->tp)->argtype;
                   15329:                        Pptr p;
                   15330:                        Ptype gt1 = aa->tp;
                   15331:                        if (p = gt1->is_ref()) gt1 = p->typ;
                   15332:                        Ptype gt2 = aa->n_list->tp;
                   15333: //error('d',"gt1 %t gt2 %t",gt1,gt2);
                   15334:                        if (mname->tp->base == OVERLOAD) { // find right version
                   15335:                                for (Plist l = Pgen(mname->tp)->fct_list; l; l=l->l) {
                   15336:                                        Pname n = l->f;
                   15337:                                        int x = over_call(n,e2);
                   15338:                                        if (x == smo) {
                   15339:                                                mname = n;
                   15340:                                                break;
                   15341:                                        }
                   15342:                                }
                   15343:                        }
                   15344: //error('d',"mname %n: %t",mname,mname->tp);
                   15345:                        Ptype mt1 = Pfct(mname->tp)->f_this->tp;
                   15346:                        mt1 = Pptr(mt1)->typ;
                   15347:                        Ptype mt2 = Pfct(mname->tp)->argtype->tp;
                   15348: //error('d',"mt1 %t mt2 %t",mt1,mt2);
                   15349:                        Pname mm = new name;
                   15350:                        Pname a1 = new name;
                   15351:                        a1->tp = mt1;
                   15352:                        Pname a2 = new name;
                   15353:                        a2->tp = mt2;
                   15354:                        a1->n_list = a2;
                   15355:                        mm->tp = new fct(void_type,a1,2);
                   15356:                        Pname gg = new name;
                   15357:                        Pname a3 = new name;
                   15358:                        a3->tp = gt1;
                   15359:                        Pname a4 = new name;
                   15360:                        a4->tp = gt2;
                   15361:                        a3->n_list = a4;
                   15362:                        gg->tp = new fct(void_type,a3,1);
                   15363: extern Pname dominate(Pname,Pname,Pexpr,int,int);
                   15364:                        aa = dominate(gg,mm,ee1,0,1);
                   15365:                        delete a1;
                   15366:                        delete a2;
                   15367:                        delete a3;
                   15368:                        delete a4;
                   15369:                        DEL( gg->tp );
                   15370:                        DEL( mm->tp );
                   15371:                        //delete gg->tp;
                   15372:                        //delete mm->tp;
                   15373:                        if (aa == 0) {
                   15374:                                delete gg;
                   15375:                                delete mm;
                   15376:                                error("ambiguous operandTs%n and%t for%k",n1,t2,bb);
                   15377:                                tp = any_type;
                   15378:                                return this;
                   15379:                        }
                   15380:                        else if (aa == gg) {
                   15381:                                delete gg;
                   15382:                                delete mm;
                   15383:                                goto glob;
                   15384:                        }
                   15385:                        delete gg;
                   15386:                        delete mm;
                   15387:                }
                   15388:                else if (mo < 2) {      // user-defined conversion user
                   15389: 
                   15390:                        if (try_to_demote(bb,t1,t2))
                   15391:                                error("ambiguous use of overloaded%k",bb);
                   15392:                }
                   15393: 
                   15394:                base = G_CALL;                          // e1.op(e2) or e1.op()
                   15395:                Pname xx = new name(mname->string);     // do another lookup
                   15396:                                                        // . suppresses virtual
                   15397:                e1 = new ref(DOT,e1,xx);
                   15398:                if (ee1) delete ee1;
                   15399:                return typ(tbl);
                   15400:        }
                   15401:        
                   15402:        if (n2 && e1==0) {                      /* look for unary operator */
                   15403:                suppress_error++;
                   15404:                Pexpr mn = Pclass(n2->tp)->find_name(obb,0);
                   15405:                suppress_error--;
                   15406:                Pname mname = Pname(mn);
                   15407:                if (mname == 0) goto glob;
                   15408:        zaqq:
                   15409:                switch (mname->base) {
                   15410:                case REF:
                   15411:                case MDOT:
                   15412:                        mname = Pname(Pexpr(mname)->mem);
                   15413:                        goto zaqq;
                   15414:                }       
                   15415: 
                   15416:                switch (mname->n_scope) {
                   15417:                default:        goto glob;
                   15418:                case 0:
                   15419:                case PUBLIC:    break;          // try e2.op()
                   15420:                }
                   15421:                
                   15422:                int mo = over_call(mname,0);
                   15423: //error('d',"e2 mo %d (go %d)",mo,go);
                   15424:                if (mo==0 || mo<go)
                   15425:                        goto glob;
                   15426:                else if (mo==go) {
                   15427:                        error("ambiguous operandT%n for%k",n2,bb);
                   15428:                        tp = any_type;
                   15429:                        return this;
                   15430:                }
                   15431:                else if (mo < 2) {      // user-defined conversion user
                   15432:                        if (try_to_demote(bb,t1,t2))
                   15433:                                error("ambiguous use of overloaded%k",bb);
                   15434:                }
                   15435:                base = G_CALL;                          // e2.op()
                   15436:                Pname xx = new name(Nover->string);     // do another lookup
                   15437:                                                        // . suppresses virtual
                   15438:                e1 = new ref(DOT,oe2,xx);
                   15439:                e2 = 0;
                   15440:                if (ee2) delete ee2;
                   15441:                if (ee1 && ee1!=ee2) delete ee1;
                   15442:                return typ(tbl);
                   15443:        }
                   15444:        
                   15445: glob:
                   15446: // error('d',"glob %d",go);
                   15447: 
                   15448:        if (go) {
                   15449:                if (go < 2) {   // user-defined conversion necessary => binary
                   15450:                        if (try_to_demote(bb,t1,t2))
                   15451:                                error("ambiguous use of overloaded%k: %t and %t",bb,t1,t2);
                   15452:                }
                   15453: 
                   15454:                base = gname->n_table == gtbl ? G_CALL : CALL;
                   15455: //error('d',"gname %n %t",gname,gname->tp);
                   15456:                e1 = new name(gname->string);
                   15457:                // if global scope, look only for globals
                   15458:                if(gname->n_table == gtbl) Pname(e1)->n_qualifier = sta_name;
                   15459:                e2 = ee1;
                   15460:                return typ(tbl);
                   15461:        }
                   15462: 
                   15463:        if (ee2) delete ee2;
                   15464:        if (ee1 && ee1!=ee2) delete ee1;
                   15465:        e2 = oe2;
                   15466: 
                   15467: // error('d',"bb %d %k",bb,bb);
                   15468:        switch (bb) {
                   15469:        case CM:
                   15470:        case G_CM:
                   15471:        case G_ADDROF:
                   15472:                return 0;
                   15473:        case ASSIGN:
                   15474:                if (n1
                   15475:                && n2
                   15476:                && (n1->tp==n2->tp || Pclass(n2->tp)->has_base(Pclass(n1->tp)))) {
                   15477:                        if (make_assignment(n1))
                   15478:                                return try_to_overload(tbl);
                   15479:                        else
                   15480:                                return 0;
                   15481:                }
                   15482:        case DEREF:
                   15483:        case CALL:
                   15484:                if (n1 == 0) break;
                   15485: 
                   15486:        default:        /* look for conversions to basic types */
                   15487:                if (n1
                   15488:                && Pclass(n1->tp)->conv
                   15489:                && (bb==ANDAND || bb==OROR)) {
                   15490:                        e1 = check_cond(e1,bb,tbl);
                   15491:                        return 0;
                   15492:                }
                   15493: 
                   15494:                if (n2
                   15495:                && Pclass(n2->tp)->conv
                   15496:                && (bb==ANDAND || bb==OROR || bb==NOT || 
                   15497:                        bb==UMINUS || bb==UPLUS || bb==COMPL)) {
                   15498:                                e2 = check_cond(e2,bb,tbl);
                   15499:                                return 0;
                   15500:                }
                   15501: 
                   15502: // error( 'd', "bb: %k t1: %k t2: %k", bb, t1?t1->base:0, t2?t2->base:0 );
                   15503:                switch (try_to_demote(bb,t1,t2)) {
                   15504:                default:
                   15505:                        if (Lcoerce) error("ambiguous conversion of%n",n1);
                   15506:                        if (Rcoerce) error("ambiguous conversion of%n",n2);
                   15507:                case 0:
                   15508:                        break;
                   15509:                case 1:
                   15510:                        if (Lcoerce) {
                   15511:                                Pname xx = new name(Lcoerce->string);
                   15512:                                Pref r = new ref(DOT,e1,xx);
                   15513:                                e1 = new expr(G_CALL,r,0);
                   15514:                        }
                   15515: 
                   15516:                        if (Rcoerce) {
                   15517:                                Pname xx = new name(Rcoerce->string);
                   15518:                                Pref r = new ref(DOT,e2,xx);
                   15519:                                e2 = new expr(G_CALL,r,0);
                   15520:                        }
                   15521:                        return typ(tbl);
                   15522:                }
                   15523: 
                   15524:                switch (bb) {
                   15525:                case CM:
                   15526:                case ADDROF:    // has legal built-in meaning
                   15527:                        return 0;
                   15528:                }
                   15529: 
                   15530:                if (t1 && t2)
                   15531:                        error("bad operandTs%t%t for%k",t1,t2,bb);
                   15532:                else
                   15533:                        error("bad operandT%t for%k",t1?t1:t2,bb);
                   15534: 
                   15535:                tp = any_type;
                   15536:                return this;
                   15537:        }
                   15538: 
                   15539:        return 0;
                   15540: }
                   15541: 
                   15542: Pexpr cast_cptr(Pclass ccl, Pexpr ee, Ptable tbl, int real_cast)
                   15543: /*
                   15544:        "ee" is being cast to pointer object of class "ccl"
                   15545:        if necessary modify "ee"
                   15546: */
                   15547: {
                   15548: 
                   15549: //     Ptype etp = ee->tp;
                   15550: // error('d',"cast_cptr %k ccl %t ee->tp %t",ee->tp->base,ccl,ee->tp);
                   15551: //     if (etp->base!=PTR && etp->base!=RPTR) return ee;
                   15552:        Ptype etp = ee->tp->is_ptr_or_ref();
                   15553:        if (etp == 0) return ee;
                   15554: 
                   15555:        Pname on = Pptr(etp)->typ->is_cl_obj();
                   15556:        if (on == 0) return ee;
                   15557: 
                   15558:        Pclass ocl = Pclass(on->tp);
                   15559:        if (ocl==ccl || ccl==0 || ocl==0) return ee;
                   15560: 
                   15561: // error('d',"cast_cptr %t(%t) real %d",ccl,ocl,real_cast);
                   15562:        int oo = 0;
                   15563:        Pexpr r = 0;
                   15564: 
                   15565:        if (ocl->baselist
                   15566:        && (ocl->baselist->bclass!=ccl || ocl->baselist->base!=NAME)) {
                   15567:                // casting derived to second or virtual base?
                   15568:                Nptr = 0;
                   15569:                Nvis = 0; 
                   15570:                Nalloc_base = 0;
                   15571:                vcllist->clear();
                   15572:                vcllist=0;
                   15573:                int x = is_unique_base(ocl,ccl->string,0);
                   15574:                if (Nvis) {
                   15575:                        if (real_cast==0)
                   15576:                                error("cast:%n* ->B%t*; privateBC",on,ccl);
                   15577:                        else if (warning_opt)
                   15578:                                error('w',"cast:%n* ->B%t*; privateBC",on,ccl);
                   15579:                        real_cast = 1;  // suppress further error mesages
                   15580:                        Nvis = 0;
                   15581:                }
                   15582: 
                   15583:                switch (x) {
                   15584:                default:
                   15585:                        error("cast:%n* ->B%t*;%t isB more than once",on,ccl,ccl);
                   15586:                case 0:         // unrelated;
                   15587:                        break;
                   15588:                case 1:
                   15589:                        oo = Noffset;
                   15590:                        break;
                   15591:                }
                   15592: 
                   15593:                if (Nptr) {     // => ee?Nptr:0
                   15594:                         if (ocl->c_body==1) ocl->dcl_print(0);
                   15595:                         Nptr->mem = ee; // ee->Pbase_class
                   15596:                        if ( Nalloc_base ) {
                   15597: // error('d', "cast_cptr: nalloc_base: %s", Nalloc_base);
                   15598:                                Nptr->i1 = 5;
                   15599:                                Nptr->string4 = new char[strlen(Nalloc_base)];
                   15600:                                strcpy(Nptr->string4,Nalloc_base);
                   15601:                                Nalloc_base = 0;
                   15602:                        }
                   15603:                        else Nptr->i1 = 3;
                   15604: 
                   15605:                         if (ee->base==ADDROF || ee->base==G_ADDROF)   
                   15606:                                 ee = Nptr;
                   15607:                         else {
                   15608:                                Pexpr p = new expr(QUEST,Nptr,zero);
                   15609:                                nin = 1;
                   15610:                                if (ee->not_simple()) { // need temp
                   15611:                                        Ptype t = ee->tp;
                   15612:                                        Pname pp = make_tmp('N',t,tbl);
                   15613:                                        Pname(pp)->n_assigned_to = 1;
                   15614:                                        ee = new expr(ASSIGN,pp,ee);
                   15615:                                        ee->tp = t;
                   15616:                                        Nptr->mem = pp;
                   15617:                                }
                   15618:                                nin = 0;
                   15619:                                p->cond = ee;
                   15620:                                p->tp = ee->tp;
                   15621:                                 ee = p;
                   15622:                        }
                   15623:                }                       
                   15624:        }
                   15625: 
                   15626:        if (ccl->baselist
                   15627:        && (ccl->baselist->bclass!=ocl || ccl->baselist->base!=NAME)) {
                   15628:                // casting second or virtual base to derived?
                   15629:                Nptr = 0;
                   15630:                vcllist->clear();
                   15631:                vcllist=0;
                   15632:                int x = is_unique_base(ccl,ocl->string,0);
                   15633:                switch (x) {
                   15634:                default:
                   15635:                        error("cast:%n* ->derived%t*;%n isB more than once",on,ccl,on);
                   15636:                case 0:         // unrelated;
                   15637:                        break;
                   15638:                case 1:
                   15639:                        oo = -Noffset;
                   15640:                         if (Nptr)
                   15641:                                 error("cast:%n* ->derived%t*;%n is virtualB",on,ccl,on);
                   15642:                         break;
                   15643:                }
                   15644:                Nvis = 0;       // visibility no concern when converting from base to derived
                   15645:        }
                   15646: // error('d',"oo %d ee %k",oo,ee->base);
                   15647:        if (oo) {       // => ee?ee+offset:0
                   15648:                 if (ee->base==ADDROF || ee->base==G_ADDROF)
                   15649:                         ee = rptr(ee->tp,ee,oo);
                   15650:                 else {
                   15651:                        Pexpr p;
                   15652:                        nin = 1;
                   15653:                        if (ee->not_simple()) { // need temp
                   15654:                                Ptype t = ee->base==MDOT?ee->mem->tp:ee->tp;
                   15655:                                Pname pp = make_tmp('M',t,tbl);
                   15656:                                Pname(pp)->n_assigned_to = 1;
                   15657:                                ee = new expr(ASSIGN,pp,ee);
                   15658:                                ee->tp = t;
                   15659:                                p = rptr(t,pp,oo);
                   15660:                        }
                   15661:                        else
                   15662:                                p = rptr(ee->base==MDOT?ee->mem->tp:ee->tp,ee,oo);
                   15663:                        nin = 0;
                   15664:                        Pexpr pp = new expr(QUEST,p,zero);
                   15665:                        pp->tp = ee->tp;
                   15666:                        pp->cond = ee;
                   15667:                         ee = pp;
                   15668:                }
                   15669:        }
                   15670: 
                   15671:        Nvis = 0; // Nvis set by has_base()
                   15672:        if (ocl->has_base(ccl) && Nvis) {
                   15673:                if (real_cast==0)
                   15674:                        error("cast:%n* ->B%t*; privateBC",on,ccl);
                   15675:                else if (warning_opt)
                   15676:                        error('w',"cast:%n* ->B%t*; privateBC",on,ccl);
                   15677:                Nvis = 0;
                   15678:        }
                   15679: 
                   15680: // error('d',"return %d %k %t",ee,ee->base,ee->tp);
                   15681:        return ee;
                   15682: }
                   15683: 
                   15684: Pexpr expr::donew(Ptable tbl)
                   15685: {
                   15686:        Ptype tt = tp2;
                   15687:        Ptype tpx = tt;
                   15688:        bit v = 0;
                   15689:        bit old = new_type;
                   15690:        int init = 0;   // non-constructor initialization
                   15691:        new_type = 1;
                   15692: 
                   15693:        tt->dcl(tbl);
                   15694:        new_type = old;
                   15695: // error('d',"donew %d %d (%k) tt %t",e1,e2,e2?e2->base:0,tt);
                   15696:        if (e1) e1 = e1->typ(tbl);
                   15697:        if (e2) e2 = e2->typ(tbl);
                   15698: ll:
                   15699: //error('d',"ll %d",tt->base);
                   15700:        switch (tt->base) {
                   15701:        default:
                   15702:                if ( e1) {
                   15703:                        if (v) {
                   15704:                                error("Ir for array created using \"new\"");
                   15705:                                break;
                   15706:                        }
                   15707:                        init = 1;
                   15708:                } 
                   15709:        //      if (e1) {
                   15710:        //              error("Ir for nonCO created using \"new\"");
                   15711:        //              e1 = 0;
                   15712:        //      }
                   15713:                break;
                   15714:        case VEC:
                   15715:                if (v && Pvec(tt)->dim) error("only 1st array dimension can be non-constant");
                   15716:                if (Pvec(tt)->size==0 && Pvec(tt)->dim==0) error("array dimension missing in `new'");
                   15717:        //      if (Pvec(tt)->dim==zero) {
                   15718:        //              Pvec(tt)->size = 0;
                   15719:        //              Pvec(tt)->dim = 0;
                   15720:        //      }
                   15721:                v++;
                   15722:                tt = Pvec(tt)->typ;
                   15723:                goto ll;
                   15724:        case TYPE:
                   15725:                tt = Pbase(tt)->b_name->tp;
                   15726:                goto ll;
                   15727:        case VOID:
                   15728:                error("badT for `new': void");
                   15729:                break;
                   15730:        case COBJ:
                   15731:        {       Pname cn = Pbase(tt)->b_name;
                   15732:                Pclass cl = Pclass(cn->tp);
                   15733:                Pname icn = 0;
                   15734: 
                   15735:                if ( e1 ) { // arguments
                   15736:                        if ( e1->e2 == 0 && e1->base == ELIST ) {
                   15737:                                e1 = e1->e1;
                   15738:                                e1 = e1->typ(tbl);
                   15739:                        }
                   15740:                        icn = (e1->base!=ELIST)?e1->tp->is_cl_obj():0;
                   15741:                }
                   15742:                //Pname icn = (e1 && e1->base!=ELIST)?e1->tp->is_cl_obj() : 0;
                   15743: 
                   15744:                Pclass icl = icn ? Pclass(icn->tp) : 0;
                   15745: 
                   15746:                if (cl->c_abstract) {
                   15747:                        error("`new' of abstractC%t",cl);
                   15748:                        break;
                   15749:                }
                   15750: 
                   15751:                if (v && e1) {
                   15752:                        error("Ir for array ofCO created using \"new\"");
                   15753:                        break;
                   15754:                }
                   15755: 
                   15756:                if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) {
                   15757:                        error("new%n;%n isU",cn,cn);
                   15758:                        break;
                   15759:                }
                   15760: 
                   15761:                Pname ctor = cl->has_ctor();
                   15762: 
                   15763:                if (ctor) {
                   15764:                        if (v) {
                   15765:                                Pname ic;
                   15766:                                if ((ic = cl->has_ictor())==0) {
                   15767:                                        error("array ofC%n that does not have aK taking noAs",cn);
                   15768:                                        break;
                   15769:                                }
                   15770:                                        
                   15771:                                if (Pfct(ic->tp)->nargs) {
                   15772:                                        error("defaultAs forK for array ofC%n",cn);
                   15773:                                        break;
                   15774:                                }
                   15775:                        }
                   15776: 
                   15777:                        if (icl
                   15778:                        && cl->has_itor()==0    // incomplete:
                   15779:                                                // what if X(Y&) exists
                   15780:                                                // for class Y : X ?
                   15781:                        && (icl==cl || icl->has_base(cl))) {
                   15782:                                init = 1;
                   15783:                                break;
                   15784:                        }
                   15785:                        e1 = call_ctor(tbl,0,ctor,e1);
                   15786:                }
                   15787:                else if (e1) {
                   15788:                        if (icl==cl || icl->has_base(cl)) 
                   15789:                                init = 1;
                   15790:                        else
                   15791:                                error("new%n(As ); %n does not have aK",cn,cn);
                   15792:                }
                   15793:        }
                   15794:        }
                   15795: 
                   15796:        if (init) {
                   15797:                Pname tmp = make_tmp('N',tt->addrof(),tbl);
                   15798:                e1 = e1->typ(tbl);
                   15799:                if (tt->check(e1->tp,ASSIGN))
                   15800:                        error("badIrT %t for new operator (%t X)",e1->tp,tt);
                   15801:                e1 = new expr(0,tmp,e1);
                   15802:                tmp->assign();
                   15803:        }
                   15804: 
                   15805: //     tp = (v) ? tpx : tpx->addrof();
                   15806:        switch (v) {
                   15807:                case 0:
                   15808:                        tp = tpx->addrof();
                   15809:                        break;
                   15810:                case 1:
                   15811:                        tp = tpx;
                   15812:                        break;
                   15813:                default:
                   15814:                        tp = tpx;
                   15815:        }
                   15816: //error('d',"donew(%d) -> %t",v,tp);
                   15817:        return this;
                   15818: }
                   15819: 
                   15820: static is_dataMemPtr( Pexpr ee ) 
                   15821: /* this is utterly implementation dependent 
                   15822:  * called by expr::lval to determine 
                   15823:  * const objects bounds to pointers to data members 
                   15824:  */
                   15825: {
                   15826:        Pexpr te = ee->e1;
                   15827:        if ( te == 0 ) return 0;
                   15828:        if ( te->base != PLUS ) return 0;
                   15829:        if ( (te = te->e2) == 0 ) return 0;
                   15830:        if ( te->base != MINUS ) return 0;
                   15831:        if ( (te = te->e1) == 0 ) return 0;
                   15832:        if ( te->base != CAST ) return 0;
                   15833:        if ( (te = te->e1) == 0 ) return 0;
                   15834:        if ( te->tp->base != PTR ) return 0;
                   15835:         if ( Pptr(te->tp)->memof == 0 ) return 0;
                   15836:        return 1;
                   15837: }
                   15838: 0707071010112044301004440001630000160000010200700466055402100001000000162346expr3.c/*ident    "@(#)ctrans:src/expr3.c 1.6" */
                   15839: /***************************************************************************
                   15840: 
                   15841:        C++ source for cfront, the C++ compiler front-end
                   15842:        written in the computer science research center of Bell Labs
                   15843: 
                   15844:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   15845:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   15846: 
                   15847: expr3.c:
                   15848: 
                   15849:        type check function calls, casts, and explicit coercions
                   15850: 
                   15851: ************************************************************************/
                   15852: 
                   15853: #include "cfront.h"
                   15854: #include "size.h"
                   15855: 
                   15856: int pr_dominate(Ptype t1, Ptype t2)
                   15857: /*
                   15858: */
                   15859: {
                   15860:        Pname cn1 = t1->is_cl_obj();
                   15861:        Pname cn2 = t2->is_cl_obj();
                   15862: //error('d',"pr_dominate(%t,%t)",t1,t2);
                   15863: 
                   15864:        if (cn1==0 || cn2==0) {
                   15865:                Ptype p1 = t1->is_ptr();
                   15866:                Ptype p2 = t2->is_ptr();
                   15867:                if (p1 && p2) {                 // pointers
                   15868:                        cn1 = Pptr(p1)->typ->is_cl_obj();
                   15869:                        cn2 = Pptr(p2)->typ->is_cl_obj();
                   15870:                        if (cn1==0 || cn2==0) return 0;
                   15871:                }
                   15872:                else {
                   15873:                        p1 = t1->is_ref();
                   15874:                        p2 = t2->is_ref();
                   15875:                        if (p1 && p2) {         // references
                   15876:                                cn1 = Pptr(p1)->typ->is_cl_obj();
                   15877:                                cn2 = Pptr(p2)->typ->is_cl_obj();
                   15878:                                if (cn1==0 || cn2==0) return 0;
                   15879:                        }
                   15880:                //      else if (p1 && cn2) {
                   15881:                //              cn1 = Pptr(p1)->typ->is_cl_obj();
                   15882:                //      }
                   15883:                        else
                   15884:                                return 0;       // not the same and not classes
                   15885:                }
                   15886:        }
                   15887:        Pclass c1 = Pclass(cn1->tp);
                   15888:        Pclass c2 = Pclass(cn2->tp);
                   15889: //error('d'," c1 : c2 %d; c2 : c1 %d",c1->has_base(c2),c2->has_base(c1));
                   15890:        if (c1->has_base(c2)) return 1;
                   15891:        if (c2->has_base(c1)) return 2;
                   15892:        return 0;
                   15893: }
                   15894: 
                   15895: int exact1(Pname,Ptype);
                   15896: static exact2(Pname,Ptype);
                   15897: static exact3(Pname,Ptype);
                   15898: 
                   15899: static Pname user_dominate(Pname n1, Pname n2, Pexpr arg)
                   15900: {
                   15901:        Pfct f1 = Pfct(n1->tp);
                   15902:        Pfct f2 = Pfct(n2->tp);
                   15903: 
                   15904:        Pname a1 = f1->argtype;
                   15905:        Pname a2 = f2->argtype;
                   15906: //error('d',"user_dominate: %n %t %t",n1,f1,f2);
                   15907: 
                   15908:        for(; a1 && a2; a1 = a1->n_list, a2 = a2->n_list) {
                   15909:                Ptype t1 = a1->tp;
                   15910:                Ptype t2 = a2->tp;
                   15911:        }
                   15912: 
                   15913:        if (a1 && !a1->n_evaluated) return n1;
                   15914:        if (a2 && !a2->n_evaluated) return n2;
                   15915: 
                   15916:        a1 = f1->argtype;
                   15917:        a2 = f2->argtype;
                   15918: 
                   15919:        Pname prev = 0;
                   15920:        Pexpr e = arg;
                   15921: 
                   15922:        for(; a1 && a2 && e; a1 = a1->n_list, a2 = a2->n_list, e = e->e2) {
                   15923:                Ptype t1 = a1->tp;
                   15924:                Ptype t2 = a2->tp;
                   15925:                Ptype at = e->e1->tp;
                   15926: 
                   15927:                int j = can_coerce(t1,at);
                   15928:                Ptype tt1 = Ncoerce ? Pfct(Ncoerce->tp)->returns : 0;
                   15929:                j = can_coerce(t2,at);
                   15930:                Ptype tt2 = Ncoerce ? Pfct(Ncoerce->tp)->returns : 0;
                   15931:                if(!tt1 || !tt2 || tt1->check(tt2,OVERLOAD)) 
                   15932:                        return 0;
                   15933: 
                   15934:                int one = 0, two = 0;
                   15935:                if(exact1(a1,tt1)) one = 4;
                   15936:                else if(exact2(a1,tt1)) one = 3;
                   15937:                else if(exact3(a1,tt1)) one = 2;
                   15938:                else one = 1;
                   15939:                if(exact1(a2,tt1)) two = 4;
                   15940:                else if(exact2(a2,tt1)) two = 3;
                   15941:                else if(exact3(a2,tt1)) two = 2;
                   15942:                else two = 1;
                   15943: 
                   15944:                if(one > two && (!prev || prev==n1)) prev = n1;
                   15945:                else if(two > one && (!prev || prev==n2)) prev = n2;
                   15946:                else if(one == two && one) ;
                   15947:                else return 0;
                   15948:        }
                   15949:        if(prev) return prev;
                   15950:        
                   15951:        return 0;
                   15952: }
                   15953: 
                   15954: Pname dominate(Pname n1, Pname n2, Pexpr arg, int const_obj, int level)
                   15955: /*
                   15956:        the two functions n1 and n2 can each respond to a call using
                   15957:        standard conversions. Does the one dominate the other in the
                   15958:        sense that all its arguments are identical to the other or
                   15959:        classes defived from the class of the corresponding argument
                   15960:        of the other.
                   15961: 
                   15962:        If so return it, otherwise return 0;
                   15963: */
                   15964: {
                   15965:        Pname res = 0;
                   15966: 
                   15967:        Pfct f1 = Pfct(n1->tp);
                   15968:        Pfct f2 = Pfct(n2->tp);
                   15969: 
                   15970:        Pname a1 = f1->argtype;
                   15971:        Pname a2 = f2->argtype;
                   15972:        Pexpr e = arg;
                   15973: //error('d',"dominate: %n %t %t e %d",n1,f1,f2,e);
                   15974: 
                   15975:        if (e == 0) {
                   15976:                if (const_obj) {
                   15977:                        if (f1->f_const && f2->f_const==0) return n1;
                   15978:                        if (f2->f_const && f1->f_const==0) return n2;
                   15979:                }
                   15980:                else {
                   15981:                        if (f1->f_const==0 && f2->f_const) return n1;
                   15982:                        if (f2->f_const==0 && f1->f_const) return n2;
                   15983:                }
                   15984:                return 0;
                   15985:        }
                   15986: 
                   15987:        for(; a1 && a2 && e; a1 = a1->n_list, a2 = a2->n_list, e = e->e2) {
                   15988:                Ptype t1 = a1->tp;
                   15989:                Ptype t2 = a2->tp;
                   15990:                Ptype at = e->e1->tp;
                   15991: //error('d',"t1 %t t2 %t at %t",t1,t2,at);
                   15992:                if (t1==t2 || t1->check(t2,0)==0 )
                   15993:                        continue;
                   15994:                Pptr r1 = t1->is_ref();
                   15995:                Pptr r2 = t2->is_ref();
                   15996: //error('d',"const_problem %t %t %t %d",t1,t2,at,const_problem);
                   15997:                if (const_problem) {    // t1 and t1 differs only in const
                   15998:                        Pname rr;
                   15999:                        if (at->check(t1,0)==0 && const_problem==0) {
                   16000:                                if (t1->is_ptr())
                   16001:                                        rr = n1;
                   16002:                                else
                   16003:                                        goto nc;
                   16004:                        }
                   16005:                        else if (at->check(t2,0)==0 && const_problem==0) {
                   16006:                                if (t2->is_ptr())
                   16007:                                        rr = n2;
                   16008:                                else
                   16009:                                        goto nc;
                   16010:                        }
                   16011:                        else if (r1 && r1->typ->check(at,0)==0 && const_problem==0)
                   16012:                                rr = n1;
                   16013:                        else if (r2 && r2->typ->check(at,0)==0 && const_problem==0)
                   16014:                                rr = n2;
                   16015:                        else
                   16016:                                goto nc;
                   16017:                
                   16018:                        if (res && res!=rr) return 0;   // mutual dominace
                   16019:                        res = rr;
                   16020:                        continue;       // identical
                   16021:                }
                   16022:        nc:
                   16023:                if (r2 && (t1==r2 || t1->check(r2->typ,0)==0)) continue;
                   16024:                if (r1 && (t2==r1 || t2->check(r1->typ,0)==0)) continue;
                   16025: 
                   16026:                Pname rr = 0;
                   16027:                if (t1==at || exact1(a1,at))
                   16028:                        rr = n1;
                   16029:                else if (t2==at || exact1(a2,at))
                   16030:                        rr = n2;
                   16031:                else if (1<level) {     // try integral promotion
                   16032:                        if (exact2(a1,at))
                   16033:                                rr = n1;
                   16034:                        if (exact2(a2,at)) {
                   16035:                                if (rr) rr = 0;
                   16036:                                else rr = n2;
                   16037:                        }
                   16038:                }
                   16039:                if (!rr && 2<level) {   // try standard conversions
                   16040:                        if (exact3(a1,at))
                   16041:                                rr = n1;
                   16042:                        if (exact3(a2,at)) {
                   16043:                                if (rr) rr = 0;
                   16044:                                else rr = n2;
                   16045:                        }
                   16046:                }
                   16047:                if (rr) {
                   16048:                        if  (res && res!=rr) return 0;  // mutual dominance
                   16049:                        res = rr;
                   16050:                        continue;
                   16051:                }
                   16052: 
                   16053:                int r = pr_dominate(t1,t2);
                   16054: //error('d',"pr1 %d",r);
                   16055:                if (r) {
                   16056:                        Pname rr = r==1?n1:n2;
                   16057:                        if (res && res!=rr) return 0;   // mutual dominace
                   16058:                        res = rr;
                   16059:                        continue;
                   16060:                }
                   16061: 
                   16062:                r = pr_dominate(t1,at);
                   16063: //error('d',"pr2 %d",r);
                   16064:                if (r==2) {
                   16065:                        if (res && res!=n1) return 0;   // mutual dominace
                   16066:                        res = n1;
                   16067:                        r = pr_dominate(t2,at);
                   16068:                        if (r==2) return 0;     // mutual dominace
                   16069:                        continue;
                   16070:                }
                   16071: 
                   16072:                r = pr_dominate(t2,at);
                   16073: //error('d',"pr3 %d",r);
                   16074:                if (r==2) {
                   16075:                        if (res && res!=n2) return 0;   // mutual dominace
                   16076:                        res = n2;
                   16077:                        continue;
                   16078:                }
                   16079: 
                   16080:        }
                   16081:        //if (a1==0 && a2 && a2->n_initializer==0) return 0;    // wrong number of arguments
                   16082:        //if (a2==0 && a1 && a1->n_initializer==0) return 0;    // wrong number of arguments
                   16083: 
                   16084:        if (e) {
                   16085: //error('d',"more args %t a1 %t a2 %t",e->e1->tp,a1?a1->tp:0,a2?a2->tp:0);
                   16086:                int k1 = f1->nargs_known!=ELLIPSIS;
                   16087:                int k2 = f2->nargs_known!=ELLIPSIS;
                   16088:                if (a1 && a1->tp->check(e->e1->tp,ASSIGN)==0) return n1;
                   16089:                if (a2 && a2->tp->check(e->e1->tp,ASSIGN)==0) return n2;
                   16090:                if (k1 && k2) return 0;
                   16091:        }
                   16092: 
                   16093:        if (a1==0 && a2 && a2->n_initializer==0) return 0;
                   16094:        if (a2==0 && a1 && a1->n_initializer==0) return 0;
                   16095:        if (res==0)
                   16096:                if (const_obj) {
                   16097:                        if (f1->f_const && f2->f_const==0) return n1;
                   16098:                        if (f2->f_const && f1->f_const==0) return n2;
                   16099:                }
                   16100:                else {
                   16101:                        if (f1->f_const==0 && f2->f_const) return n1;
                   16102:                        if (f2->f_const==0 && f1->f_const) return n2;
                   16103:                }
                   16104: //error('d'," -> %n %t",res,res?res->tp:0);
                   16105:        return res;
                   16106: }
                   16107: 
                   16108: Pname Ntmp;
                   16109: 
                   16110: static refd;   // initialization routine called by ref_init, do not apply itor
                   16111: static no_sti;
                   16112: extern int stat_init;
                   16113: 
                   16114: Pname make_tmp(char c, Ptype t, Ptable tbl)
                   16115: {
                   16116:        int dt = 0; 
                   16117:        Pname tn = tbl->t_name;
                   16118:        Pname cn = t->is_cl_obj();
                   16119: 
                   16120:        if (tn && tn->tp) error('s',"defaultA too complicated");
                   16121:        if (cn && Pclass(cn->tp)->has_dtor()) dt = 1;
                   16122:        if (Ntmp == 0 && dt ) Ntmp = cn;
                   16123: 
                   16124: //error('d',"tbl %d cstmt %d %d sti %d",tbl,Cstmt,Cstmt?Cstmt->memtbl:0,sti_tbl);
                   16125:        if (Cstmt) {    //      make Cstmt into a block
                   16126:                if (Cstmt->memtbl == 0) Cstmt->memtbl = new table(4,tbl,0);
                   16127:                tbl = Cstmt->memtbl;
                   16128:        }
                   16129:        else if (tbl == gtbl && no_sti == 0) {
                   16130:                if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0);
                   16131:                tbl = sti_tbl;
                   16132:        }
                   16133: 
                   16134:        Pname tmpx = new name(make_name(c));
                   16135:        tmpx->where = no_where;
                   16136:        tmpx->tp = t;
                   16137:        (void) t->tsizeof();
                   16138:        if ( t->base == COBJ ) {
                   16139:                Pclass cl = Pclass(Pbase(t)->b_name->tp);
                   16140:                if ( cl->lex_level ) tmpx->lex_level = cl->lex_level;
                   16141:        }
                   16142: 
                   16143:        TOK scop = ARG;
                   16144:        if (stat_init && dt) { 
                   16145:                tmpx->n_sto = STATIC; scop = ARGS; 
                   16146:        }
                   16147: 
                   16148:        // ARG[S]: no init; ARGS: static dtor
                   16149:        Pname tmp = tmpx->dcl(tbl,scop); 
                   16150:        delete tmpx;
                   16151: 
                   16152:        // n_scope == ARGS sets static dtor in simpl2.c
                   16153:        tmp->n_scope = (scop==ARG) ? FCT : ARGS;
                   16154:        return tmp;
                   16155: }
                   16156: 
                   16157: Pexpr init_tmp(Pname tmp, Pexpr init, Ptable tbl)
                   16158: {
                   16159:        Pname cn = tmp->tp->is_cl_obj();
                   16160:        Pname ct = cn ? Pclass(cn->tp)->has_itor() : 0;
                   16161: 
                   16162:        tmp->n_assigned_to = 1;
                   16163: //error('d',"init_tmp %n ct %n refd %d",tmp,ct,refd);
                   16164:        if (ct) {       // must initialize
                   16165:                if (refd) {
                   16166: //error('d',"'orrible %k",init->e1->base);
                   16167:                        switch (init->e1->base) {       // 'orrible 'ack
                   16168:                        case NAME:
                   16169:                        case REF:
                   16170:                        case DEREF:
                   16171:                                if (init->e1->tp->is_ptr())
                   16172:                                        init = init->e1;
                   16173:                                else
                   16174:                                        init = new expr(G_CM,init,init->e1->address());
                   16175:                                        
                   16176:                        }
                   16177:                        if (ct->tp->base == OVERLOAD) ct = Pgen(ct->tp)->fct_list->f;   // first fct
                   16178:                        tbl = 0;
                   16179:                }
                   16180:                return call_ctor(tbl,tmp,ct,init,DOT);
                   16181:        }
                   16182:        Pexpr ass = new expr(ASSIGN,tmp,init); // no ctor: can assign
                   16183:        ass->tp = tmp->tp;
                   16184:        return ass;
                   16185: }
                   16186: /*
                   16187: int exact0(Pname nn, Ptype at)
                   16188: //     return 1 if
                   16189: //     exact match
                   16190: 
                   16191: {
                   16192:        if (nn == 0) return 0; //known==ELLIPSIS;
                   16193:        Ptype nt = nn->tp;
                   16194:        if (at == nt) return 1;
                   16195: //error('d',"exact0 %d",nt->check(at,0));
                   16196:        return nt->check(at,0)==0;
                   16197: }
                   16198: */
                   16199: 
                   16200: int exact3(Pname nn, Ptype at)
                   16201: /*
                   16202:        return 1 if
                   16203:        match with standard conversions
                   16204: */
                   16205: {
                   16206:        if (nn == 0) return 0; //known==ELLIPSIS;
                   16207:        Ptype nt = nn->tp;
                   16208: 
                   16209:        while(nt->base == TYPE)
                   16210:                nt = Pbase(nt)->b_name->tp;
                   16211: 
                   16212:        if (at == nt) return 1;
                   16213: 
                   16214:        switch (nt->base) {
                   16215:        case RPTR:
                   16216:                if (at==zero_type && Pptr(nt)->typ->is_ptr()==0) return 0; //break;
                   16217:                if (nt->check(at,COERCE)) {
                   16218:                        Pptr pt = at->addrof();
                   16219:                        nt->base = PTR;         // handle derived classes
                   16220:                        if (nt->check(pt,COERCE)) {
                   16221:                                nt->base = RPTR;
                   16222:                                delete pt;
                   16223:                                return 0;
                   16224:                        }
                   16225:                        nt->base = RPTR;
                   16226:                        delete pt;
                   16227:                }
                   16228:                break;
                   16229:        default:
                   16230:                switch (at->base) {
                   16231:                default: 
                   16232:                        if (nt->check(at,COERCE)) return 0;
                   16233:                        break;
                   16234:                case OVERLOAD:
                   16235:                        // the actual argument is an overloaded function
                   16236:                        // we'll try each instance until one matches
                   16237:                        register Plist gl;
                   16238:                        int no_match = 1;
                   16239: 
                   16240:                        for (gl = Pgen(at)->fct_list; gl; gl=gl->l) {
                   16241:                                if (nt->check(gl->f->tp,COERCE)==0) {
                   16242:                                        no_match = 0;
                   16243:                                        break;
                   16244:                                }
                   16245:                        }
                   16246: 
                   16247:                        if ( no_match ) return 0;
                   16248:                } 
                   16249:        }
                   16250:        return 1;
                   16251: }
                   16252: 
                   16253: int exact1(Pname nn, Ptype at)
                   16254: /*
                   16255:        return 1 if
                   16256:        exact match with
                   16257:                T <-> const T
                   16258:                X -> X&
                   16259:                T* -> const T*
                   16260:                T* -> T*const
                   16261:        taken into account
                   16262: */
                   16263: {
                   16264:        if (nn == 0) return 0;//known==ELLIPSIS;
                   16265:        Ptype nt = nn->tp;
                   16266:        if (at == nt) return 1;
                   16267: 
                   16268: //error('d',"exact1 nt %t at %t",nt,at);
                   16269:        if (nt->check(at,0)) {
                   16270: //error('d',"nt %t at %t cp %d",nt,at,const_problem);
                   16271:                if (const_problem)  return 1;   // handle T <-> const T
                   16272: 
                   16273:                Pptr rt = nt->is_ref(); //handle X -> X&
                   16274:                if (rt && (at->check(Pptr(rt)->typ,0)==0 || const_problem))  return 1;
                   16275: 
                   16276:                Pptr art = at->is_ptr();
                   16277:                if (rt && art) return 0; // ptrs do not match refs
                   16278: 
                   16279:                // handle T* -> const T* and
                   16280:                // T* -> T*const
                   16281:                if (rt || (rt = nt->is_ptr())) {
                   16282:                        if (art == 0) art = at->is_ref();
                   16283:                        if (art) {
                   16284: //error('d',"art %t %t",art->typ,rt->typ);
                   16285:                                if (art->typ->check(rt->typ,0)) {
                   16286:                                        if (const_problem)  return 1;
                   16287:                                }
                   16288:                                else    // T* -> T*const
                   16289:                                         return 1;
                   16290:                        }
                   16291:                }
                   16292:                return 0;
                   16293:        }
                   16294:        return 1;
                   16295: }
                   16296: 
                   16297: Pexpr Ninit;   // default argument used;
                   16298: int Nstd;      // standard coercion used (derived* =>base* or int=>long or ...)
                   16299: 
                   16300: bit exact_match(Pname n, Pexpr arg)
                   16301: /*
                   16302:        look for an exact match between "n" and the argument list "arg"
                   16303:        This function goes through three stages:
                   16304:        (1) exact match (no coercions at all)
                   16305:        (2) do integral promotions and float->double and re-try exact match
                   16306:        (3) try for unique standard conversions
                   16307: 
                   16308: */
                   16309: {
                   16310:        Pfct f = Pfct(n->tp);
                   16311:        register Pexpr e;
                   16312:        register Pname nn;
                   16313: 
                   16314: // error('d',"exact_match(%n) %t",n,n->tp);
                   16315: 
                   16316:        for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
                   16317:                Pexpr a = e->e1;
                   16318:                Ptype at = a->tp;
                   16319:                if (at->base == ANY) return 0;
                   16320:                if (at->base == ZTYPE) at = int_type;
                   16321:                if (exact1(nn,at)==0) return 0;
                   16322:        }
                   16323: 
                   16324: //error('d',"exact %d -> %d",nn,nn?nn->n_initializer!=0:1);
                   16325:        if (nn) {
                   16326:                Ninit = nn->n_initializer;
                   16327:                return Ninit!=0;
                   16328:        }
                   16329: 
                   16330: //error('d',"return 1");
                   16331:        return 1;       // exact match without any promotions
                   16332: }
                   16333: 
                   16334: int exact2(Pname nn, Ptype at)
                   16335: /*
                   16336:        return 1 if
                   16337:        do integral promotion and float->double on at, then match
                   16338: */
                   16339: {
                   16340: //error('d',"exact2 nt %t at %t",nn?nn->tp:0,at);
                   16341:        while(at->base == TYPE)
                   16342:                at = Pbase(at)->b_name->tp;
                   16343: 
                   16344:        switch (at->base) {
                   16345:        case EOBJ:
                   16346:                at = Penum(Pbase(at)->b_name->tp)->e_type;
                   16347:                break;
                   16348:        case ZTYPE:
                   16349:                at = int_type;
                   16350:                break;
                   16351:        case CHAR:
                   16352:        case SHORT:
                   16353:                at = (Pbase(at)->b_unsigned && at->tsizeof()==SZ_INT) ? uint_type : int_type;
                   16354:                break;
                   16355:        case FLOAT:
                   16356:                at = double_type;
                   16357:        }
                   16358: 
                   16359:        if (nn == 0) return 0;//known==ELLIPSIS;
                   16360:        Ptype nt = nn->tp;
                   16361: //error('d',"  exact2 nt %t at %t",nt,at);
                   16362:        if (at == nt) return 1;
                   16363:        if (nt->check(at,0)) {
                   16364:                if (const_problem) return 1;
                   16365: 
                   16366:                Pptr rt = nt->is_ref(); // handle X -> X&
                   16367:                if (rt && (at->check(Pptr(rt)->typ,0)==0 || const_problem)) return 1;
                   16368: 
                   16369:                Pptr art = at->is_ptr();
                   16370:                if (rt && art) return 0; // ptrs do not match refs
                   16371: 
                   16372:                // handle T* -> const T* and
                   16373:                // T* -> T*const
                   16374:                if (rt || (rt = nt->is_ptr())) {
                   16375:                        if (art == 0) art = at->is_ref();
                   16376:                        if (art) {
                   16377:                                if (art->typ->check(rt->typ,0)) {
                   16378:                                        if (const_problem) return 1;
                   16379:                                }
                   16380:                                else    // T* -> T*const
                   16381:                                        return 1;
                   16382:                        }
                   16383:                }
                   16384:                return 0;
                   16385:        }
                   16386:        return 1;
                   16387: }
                   16388: 
                   16389: bit prom_match(Pname n, Pexpr arg)
                   16390: /*
                   16391:        look for an exact match between "n" and the argument list "arg"
                   16392:        using integral promotions and float->double
                   16393: 
                   16394: */
                   16395: {
                   16396:        Pfct f = Pfct(n->tp);
                   16397:        register Pexpr e;
                   16398:        register Pname nn;
                   16399: 
                   16400: // error('d',"prom_match(%n) %t",n,n->tp);
                   16401: 
                   16402:        for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
                   16403:                Pexpr a = e->e1;
                   16404:                Ptype at = a->tp;
                   16405:                if (at->base == ANY) return 0;
                   16406: 
                   16407:                if (exact2(nn,at)==0) return 0;
                   16408:        }
                   16409:        
                   16410:        if (nn) {
                   16411:                Ninit = nn->n_initializer;
                   16412:                return Ninit!=0;
                   16413:        }
                   16414: 
                   16415:        return 1;       // exact match with promotions
                   16416: }
                   16417: 
                   16418: bit std_match(Pname n, Pexpr arg)
                   16419: /*
                   16420:        look for an exact match between "n" and the argument list "arg"
                   16421:        using standard conversions
                   16422: 
                   16423: */
                   16424: {
                   16425:        Pfct f = Pfct(n->tp);
                   16426:        register Pexpr e;
                   16427:        register Pname nn;
                   16428: 
                   16429: // error('d',"std_match(%n) %t",n,n->tp);
                   16430: 
                   16431:        for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
                   16432:                Pexpr a = e->e1;
                   16433:                Ptype at = a->tp;
                   16434: 
                   16435:                if (at->base == ANY) return 0;
                   16436:                if ( exact3(nn,at) == 0) return 0;
                   16437:        }
                   16438: 
                   16439:        if (nn) {
                   16440:                Ninit = nn->n_initializer;
                   16441:                return Ninit!=0;
                   16442:        }
                   16443: 
                   16444:        return 1;
                   16445: }
                   16446: 
                   16447: Pname Ncoerce;
                   16448: int ref_cast;
                   16449: 
                   16450: bit can_coerce(Ptype t1, Ptype t2)
                   16451: /*     return number of possible coercions of t2 into t1,
                   16452:        Ncoerce holds a coercion function (not constructor), if found
                   16453: */
                   16454: {
                   16455:        int zz = 0;
                   16456:        Ncoerce = 0;
                   16457:        if (t2->base == ANY) return 0;
                   16458: // error('d',"can_coerce t1 %t t2 %t",t1, t2);
                   16459: 
                   16460:        while(t1->base == TYPE)
                   16461:                t1 = Pbase(t1)->b_name->tp;
                   16462: 
                   16463:        switch (t1->base) {
                   16464:        case RPTR:
                   16465:                while(t2->base == TYPE)
                   16466:                        t2 = Pbase(t2)->b_name->tp;
                   16467: 
                   16468:                switch (t2->base) {
                   16469:        //      case VEC:
                   16470:        //      case PTR:
                   16471:        //      case RPTR:
                   16472:        //              if (t1->check(t2,COERCE) == 0) return 1;
                   16473:                default:        
                   16474:                {       Ptype tt2 = t2->addrof();
                   16475:                        if (t1->check(tt2,COERCE) == 0) return 1;
                   16476:                        if (ref_cast) break;//return 0; // (T&): no coercions
                   16477:                                                        // except operator T&()
                   16478:                        Ptype tt1 = Pptr(t1)->typ;
                   16479:                        while (tt1->base==TYPE) tt1 = Pbase(tt1)->b_name->tp;
                   16480:                        int bc;
                   16481:                        if ( tt1->base != PTR && tt1->base != RPTR ) {
                   16482:                                bc = Pbase(tt1)->b_const;
                   16483:                                Pbase(tt1)->b_const = 0; 
                   16484:                        }
                   16485:                        int i = can_coerce(tt1,t2);
                   16486:                        if ( tt1->base != PTR && tt1->base != RPTR ) 
                   16487:                                Pbase(tt1)->b_const = bc;
                   16488:                        if (i) return i;
                   16489:                        zz = 1;
                   16490:                }
                   16491:                }
                   16492:        }
                   16493: 
                   16494:        Pname c1 = t1->is_cl_obj();
                   16495:        Pname c2 = t2->is_cl_obj();
                   16496:        int val = 0;
                   16497:        if (ref_cast || zz) goto oper_coerce;
                   16498:        if (c1) {
                   16499:                Pclass cl = Pclass(c1->tp);
                   16500:                if (c2 && c2->tp==cl) return 1;
                   16501: 
                   16502:                 // A more comprehensive test for template classes
                   16503:                 if (c2 && (Pclass(c1->tp)->same_class(Pclass(c2->tp))))
                   16504:                         return 1 ;
                   16505: 
                   16506:                /*      look for constructor
                   16507:                                with one argument
                   16508:                                or with default for second argument
                   16509:                        of acceptable type
                   16510:                */
                   16511:                Pname ctor = cl->has_ctor();
                   16512:                if (ctor == 0) goto oper_coerce;
                   16513:                register Pfct f = Pfct(ctor->tp);
                   16514: //error('d',"ctor %n f %t",ctor,f);
                   16515:                switch (f->base) {
                   16516:                case FCT:
                   16517:                        switch (f->nargs) {
                   16518:                        case 1:
                   16519:                        one:
                   16520:                        {       Ptype tt = f->argtype->tp;
                   16521:                                        if (tt->check(t2,COERCE)==0)
                   16522:                                                val = 1;
                   16523:                                        else if (const_problem) {
                   16524:                                                Pptr p1 = tt->is_ptr_or_ref();
                   16525:                                                if (p1==0 || p1->typ->tconst()) val = 1;
                   16526:                                        }
                   16527:                                if (tt = tt->is_ref()) {
                   16528:                                        Pptr pt = t2->addrof(); // handle derived classed
                   16529:                                        tt->base = PTR;
                   16530:                                        if (tt->check(pt,COERCE) == 0) val = 1;
                   16531:                                        tt->base = RPTR;
                   16532:                                        delete pt;
                   16533:                                }
                   16534:                                goto oper_coerce;
                   16535:                        }
                   16536:                        default:
                   16537:                                if (f->argtype->n_list->n_initializer) goto one;
                   16538:                        case 0:
                   16539:                                goto oper_coerce;
                   16540:                        }
                   16541:                case OVERLOAD:
                   16542:                {       register Plist gl;
                   16543: 
                   16544:                        for (gl=Pgen(f)->fct_list; gl; gl=gl->l) { // look for match
                   16545:                                Pname nn = gl->f;
                   16546:                                Pfct ff = Pfct(nn->tp);
                   16547: 
                   16548:                                switch (ff->nargs) {
                   16549:                                case 0:
                   16550:                                        break;
                   16551:                                case 1:
                   16552:                                over_one:
                   16553:                                {       Ptype tt = ff->argtype->tp;
                   16554: //error('d',"over one %t %t -> %d %d",tt,t2,tt->check(t2,COERCE),const_problem);
                   16555:                                        if (tt->check(t2,COERCE)==0)
                   16556:                                                val = 1;
                   16557:                                        else if (const_problem) {
                   16558:                                                Pptr p1 = tt->is_ptr_or_ref();
                   16559:                                                if (p1==0 || p1->typ->tconst()) val = 1;
                   16560:                                        }
                   16561:                                        if (tt=tt->is_ref()) {
                   16562:                                                Pptr pt = t2->addrof(); // handle derived classed
                   16563:                                                tt->base = PTR;
                   16564:                                                if (tt->check(pt,COERCE) == 0) {
                   16565:                                                        tt->base = RPTR;
                   16566:                                                        delete pt;
                   16567:                                                        val = 1;
                   16568:                                                        goto oper_coerce;
                   16569:                                                }
                   16570:                                                tt->base = RPTR;
                   16571:                                                delete pt;
                   16572:                                        }
                   16573:                                        break;
                   16574:                                }
                   16575:                                default:
                   16576:                                        if (ff->argtype->n_list->n_initializer) goto over_one;
                   16577:                                }
                   16578:                        }
                   16579:                        goto oper_coerce;
                   16580:                }
                   16581:                default:
                   16582:                        error('i',"cannot_coerce(%k)\n",f->base);
                   16583:                }
                   16584:        }
                   16585: 
                   16586: oper_coerce:
                   16587: //error('d',"oper_coerce %d",val);
                   16588:        if (c2) {       
                   16589:                Pclass cl = Pclass(c2->tp);
                   16590:                int std = 0;
                   16591:                int oval = val;
                   16592:                extern Pname conv_dominates(Pname,Pname);
                   16593:                for (Pname ox, on=cl->conv; on; on=ox) {
                   16594:                        ox = on->n_list;
                   16595: // error( 'd', "can_coerce: ox: %s on: %s tp: %k", ox?ox->string:"", on->string, on->tp->base );
                   16596:                        Plist gl = 0;
                   16597:                        if ( on->tp->base == OVERLOAD ) {
                   16598:                                gl = Pgen(on->tp)->fct_list;
                   16599:                                on = gl->f;
                   16600:                                gl = gl->l;
                   16601:                        }
                   16602: 
                   16603: overlist: 
                   16604: // error( 'd', "can coerce: on: %n tp: %t gl: %d", on, on->tp, gl );
                   16605: 
                   16606:                        Pfct f = Pfct(on->tp);
                   16607:                        Nstd = 0;
                   16608:                        if (t1->check(f->returns,COERCE) == 0) {
                   16609:                                if (Nstd==0) {  // forget solutions involving standard conversions
                   16610:                                        Pname old = Ncoerce;
                   16611:                                        if (std) {      // forget
                   16612:                                                val = oval+1;
                   16613:                                                std = 0;
                   16614:                                                Ncoerce = on;
                   16615:                                        }
                   16616:                                        else if (Ncoerce == 0) {
                   16617:                                        //      val = 1;
                   16618:                                                val++;
                   16619:                                                Ncoerce = on;
                   16620:                                        }
                   16621:                                        else if ((Ncoerce = conv_dominates(Ncoerce,on))==0) {
                   16622:                                                if (val == 1) {
                   16623: //error('d',"val==1 on %n old %n",on,old);
                   16624:                                                        Ptype ton = Pfct(on->tp)->returns;
                   16625:                                                        Ptype tco = Pfct(old->tp)->returns;
                   16626:                                                        if (t1->check(ton,0)==0)
                   16627:                                                                ;
                   16628:                                                        else if (t1->check(tco,0)==0)
                   16629:                                                                on = old;
                   16630:                                                        else
                   16631:                                                                val++;
                   16632:                                                }
                   16633:                                                else
                   16634:                                                        val++;
                   16635:                                                Ncoerce = on;
                   16636:                                        }
                   16637:                                }
                   16638:                                else {  // take note only if no exact match seen
                   16639:                                        if (Ncoerce==0 || on->tp->check(Ncoerce->tp,0)) {
                   16640:                                                if (val==0 || std) {
                   16641: 
                   16642:                                                        if (Ncoerce) Ncoerce = conv_dominates(Ncoerce,on);
                   16643:                                                        if (Ncoerce == 0) {
                   16644:                                                                Ncoerce = on;
                   16645:                                                                val++;
                   16646:                                                                std = 1;
                   16647:                                                        }       
                   16648:                                                }
                   16649:                                        }
                   16650:                                }
                   16651:                        }
                   16652: // error( 'd', "can_coerce: gl: %d", gl );
                   16653:                        if ( gl ) {
                   16654:                                on = gl->f;
                   16655:                                gl = gl->l;
                   16656:                                goto overlist; // must walk list of overloaded instances
                   16657:                        }
                   16658:                }
                   16659:        }
                   16660: //error('d',"val %d",val);
                   16661:        if (val) return val;
                   16662:        if (c1 && Pclass(c1->tp)->has_itor()) return 0;
                   16663: //error('d',"%t->check(%t) -> %d",t1,t2,t1->check(t2,COERCE));
                   16664:        if (t1->check(t2,COERCE)) return 0;
                   16665:        return 1;
                   16666: }
                   16667: 
                   16668: int gen_coerce(Pname n, Pexpr arg)
                   16669: /*
                   16670:        look to see if the argument list "arg" can be coerced into a call of "n"
                   16671:        1: it can
                   16672:        0: it cannot or it can be done in more than one way
                   16673: */
                   16674: {
                   16675:        Pfct f = (Pfct) n->tp;
                   16676:        register Pexpr e;
                   16677:        register Pname nn;
                   16678: 
                   16679: //error('d',"gen_coerce(%n,%d) %t",n,arg,n->tp);
                   16680:        for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) {
                   16681:                if (nn == 0) return f->nargs_known==ELLIPSIS;
                   16682:                Pexpr a = e->e1;
                   16683:                Ptype at = a->tp;
                   16684:                int i = can_coerce(nn->tp,at);
                   16685:                if (i != 1) return 0;
                   16686:        }
                   16687:        if (nn && nn->n_initializer==0) return 0;
                   16688:        return 1;
                   16689: }
                   16690: 
                   16691: 
                   16692: Pname Nover;
                   16693: // int Nover_coerce;
                   16694: 
                   16695: int over_call(Pname n, Pexpr arg)
                   16696: /*     
                   16697:        return 4 if n(arg) can be performed without coercion of arg
                   16698:        return 3 if n(arg) can be performed only with promotion coercion of arg
                   16699:        return 2 if n(arg) can be performed only with standard coercion of arg
                   16700:        return 1 if n(arg) can be performed only with user defined coercion of arg
                   16701:        return 0 if n(arg) is an error
                   16702:        Nover is the function found, if any
                   16703:        Nstd is the number of standard coercions used
                   16704: */
                   16705: {      
                   16706:        register Plist gl;
                   16707:        Pgen g = Pgen(n->tp);
                   16708:        if (arg && arg->base!= ELIST) error('i',"ALX");
                   16709: 
                   16710: //error('d',"over_call(%n) %k",n,n->tp->base);
                   16711:        extern suppress_error;
                   16712:        suppress_error = 1;
                   16713: //     Nover_coerce = 0;
                   16714:        Nstd = 0;
                   16715:        switch (g->base) {
                   16716:        default:        error('i',"over_call(%t)\n",g);
                   16717:        case OVERLOAD:  break;
                   16718:        case FCT:
                   16719:                Nover = n;
                   16720:                Ninit = 0;
                   16721:                if (exact_match(n,arg)) {suppress_error = 0; return 4;}
                   16722:                if (prom_match(n,arg)) {suppress_error = 0; return 3;}
                   16723:                if (std_match(n,arg) && Ninit==0) {suppress_error = 0; return 2;}
                   16724:                Nstd = 0;
                   16725:                suppress_error = 0;
                   16726:                return gen_coerce(n,arg);
                   16727:        }
                   16728: 
                   16729:        Pname exact = 0;
                   16730:        int no_exact = 0;
                   16731:        int ret = 0;
                   16732:        Pname nret;
                   16733:        for (gl=g->fct_list; gl; gl=gl->l) {            /* look for match */
                   16734:                Nover = gl->f;
                   16735:                Ninit = 0;
                   16736:                Nstd = 0;
                   16737:                if (exact_match(Nover,arg)) {suppress_error = 0; return 4;}     // no coercion
                   16738:        //      if (prom_match(Nover,arg)) return 3;    // only promotion
                   16739:        //      if (std_match(Nover,arg) && Ninit==0) return 2; // only built-in conversion
                   16740:                if (ret<3 && prom_match(Nover,arg)) {
                   16741:                        nret = Nover;
                   16742:                        ret = 3;
                   16743:                }
                   16744:                if (ret<2 && std_match(Nover,arg) && Ninit==0) {
                   16745:                        nret = Nover;
                   16746:                        ret = 2;
                   16747:                }
                   16748:        }
                   16749: 
                   16750: suppress_error = 0;
                   16751:        if (ret) {
                   16752:                Nover = nret;
                   16753:                return ret;
                   16754:        }
                   16755: 
                   16756:        Nover = 0;
                   16757:        for (gl=g->fct_list; gl; gl=gl->l) {            /* look for coercion */
                   16758:                Pname nn = gl->f;
                   16759:                if (gen_coerce(nn,arg)) {
                   16760:                        Nover = nn;
                   16761:                        return 1;
                   16762:                }
                   16763:        }
                   16764:        return 0;
                   16765: 
                   16766: }
                   16767: 
                   16768: Ptype expr::call_fct(Ptable tbl)
                   16769: /*
                   16770:        check "this" call:
                   16771:                 e1(e2)
                   16772:        e1->typ() and e2->typ() has been done
                   16773: */
                   16774: {
                   16775:        Pfct f;
                   16776:        Pname fn;
                   16777:        int x;
                   16778:        int k;
                   16779:        Pname nn;
                   16780:        Pexpr e;
                   16781:        Ptype t;
                   16782:        Pexpr arg = e2;
                   16783:        Ptype t1 = e1?e1->tp:0;
                   16784:        int argno;
                   16785:        Pexpr etail = 0;
                   16786:        bit no_change = 0;
                   16787:        Pname no_virt = 0;      // set if explicit qualifier was used: c::f()
                   16788:        Pname chk = 0;          // set if visibility check is needed
                   16789:                                // that is if function name might have been
                   16790:                                // found without use of find_name()
                   16791:        int const_obj = 0;
                   16792: 
                   16793:        if (t1 == any_type) return any_type;
                   16794: 
                   16795:        switch (base) {
                   16796:        case CALL:
                   16797:        case G_CALL:    break;
                   16798:        default:        error('i',"call_fct(%k)",base);
                   16799:        }
                   16800: 
                   16801: // error('d',"call %d %k %n arg %d",this,e1->base,e1->base==NAME?e1:0,arg);
                   16802:        if (t1 == 0) error('i',"call_fct(e1=%d,e1->tp=%t)",e1,t1);
                   16803:        if (arg && arg->base!=ELIST) error('i',"badAL%d%k",arg,arg->base);
                   16804: 
                   16805:        switch (e1->base) {
                   16806:        case NAME:
                   16807:                fn = Pname(e1);
                   16808: //error('d',"name %n %k",fn,fn->n_oper);
                   16809:                switch (fn->n_oper) {
                   16810:                case 0:
                   16811:                case CTOR:
                   16812:                case DTOR:
                   16813:                case TYPE:
                   16814:                case NEW:
                   16815:                case DELETE:
                   16816:                        break;
                   16817:                default:        // real operator: check for operator+(1,2);
                   16818:                        if (arg == 0) break;
                   16819:                        Pexpr a = arg->e1;      // first operand
                   16820: 
                   16821:                        if (Pfct(fn->tp)->memof // obj.operator(1) is OK
                   16822:                        || a->tp->is_cl_obj()
                   16823:                        || a->tp->is_ref()) break;
                   16824:                        a = arg->e2;
                   16825:                        if (a == 0)             // unary
                   16826:                                error("%k of basicT",fn->n_oper);
                   16827:                        else {                  // binary
                   16828:                                a = a->e1;      // second operand
                   16829:                                if (a->tp->is_cl_obj() || a->tp->is_ref()) break;
                   16830:                                error("%k of basicTs",fn->n_oper);
                   16831:                        }
                   16832:                        break;
                   16833:                }
                   16834:                break;
                   16835:        case REF:
                   16836:        case DOT:
                   16837:                no_virt = Pname(e1->n_initializer);
                   16838:                e1->n_initializer = 0;
                   16839:                if (e1 && e1->e1) {
                   16840:                        Ptype t = e1->e1->tp;
                   16841:                        Pptr tt = t->is_ptr_or_ref();
                   16842:                        Ptype ft = tt ? tt->typ : t;
                   16843:                        Pexpr ee = e1->e1;
                   16844:                        const_obj = ft->tconst();
                   16845:                        while (ee && (ee->base==DOT || ee->base==REF)) {
                   16846:                                Pexpr m = ee->mem;
                   16847:                                if ( ee->base==REF && m->tp &&  m->tp->is_ptr())
                   16848:                                        break;
                   16849:                                ee = ee->e1;
                   16850:                        }
                   16851:                        if (ee) {
                   16852:                                Ptype ttt = ee->tp;
                   16853:                                int tc;
                   16854:                                switch (e1->base) {
                   16855:                                case REF:
                   16856:                                        Pptr p = ttt?ttt->is_ptr():0;
                   16857:                                        if (p && p->typ->tconst())
                   16858:                                                const_obj = 1;
                   16859:                                        break;
                   16860:                                case DOT:
                   16861:                                        tc = ttt ? ttt->tconst() : 0;
                   16862:                                        if(ttt && tc && (!strict_opt || tc!=2))
                   16863:                                                const_obj = 1;
                   16864:                                }
                   16865:                        }
                   16866:                }
                   16867:        case MDOT:
                   16868:        {       Pexpr n = e1->mem;
                   16869:        lxlx:
                   16870:                switch (n->base) {
                   16871:                case MDOT:
                   16872:                        // reverse mdot (see expr::print())
                   16873:                        //      p->a.b()  => (&p->a)->b() => b(&p->a)
                   16874:                        // or   p->a->b() => (p->a)->b()  => b(p->a)
                   16875:                        // or   oo.a.b()  => (&oo.a)->b() => b(&oo.a)
                   16876:                        // or   oo.a->b() => (oo.a)->b()  => b(oo.a)
                   16877:                {       
                   16878:                        Pexpr r = e1;
                   16879:                        Pexpr p = r->e1;
                   16880:                        for (Pexpr m = r->mem; m->base==MDOT; m = r->mem) {
                   16881:                                p = new mdot(m->string2,p);
                   16882:                                p->i1 = m->i1+2;
                   16883:                                p->tp = p->mem->tp;
                   16884:                                r->mem = m->mem;
                   16885:                                r->e1 = p;
                   16886:                        }
                   16887:                }
                   16888:                case REF:
                   16889:                case DOT:
                   16890:                        n = n->mem;
                   16891:                        goto lxlx;
                   16892:                case NAME:
                   16893:                        break;
                   16894:                default:
                   16895:                        error('i',"ref %k",n->base);
                   16896:                }
                   16897:                fn = Pname(n);
                   16898: //error('d',"mem %n",fn);
                   16899:                break;
                   16900:        }
                   16901:        case MEMPTR:
                   16902:        default:
                   16903:                fn = 0;
                   16904:        };
                   16905: 
                   16906: lll:
                   16907: //error('d',"lll: %t %k",t1,t1->base);
                   16908:        switch (t1->base) {
                   16909:        case TYPE:
                   16910:                t1 = Pbase(t1)->b_name->tp;
                   16911:                goto lll;
                   16912: 
                   16913:        case PTR:       // pf() allowed as shorthand for (*pf)()
                   16914:                switch (Pptr(t1)->typ->base) {
                   16915:                case FCT:
                   16916:                case OVERLOAD:
                   16917:                        if (Pptr(t1)->memof) error("O missing in call throughP toMF");
                   16918:                        t1 = Pptr(t1)->typ;
                   16919:                        fn = 0;
                   16920:                        goto lll;
                   16921:                }
                   16922: 
                   16923:        default:
                   16924:                if (fn)
                   16925:                        error("call of%n;%n is a%t",fn,fn,e1->tp);
                   16926:                else
                   16927:                        error("call of%kE ofT%t",e1->base,e1->tp);
                   16928: 
                   16929:        case ANY:
                   16930:                return any_type;
                   16931:        
                   16932:        case OVERLOAD:
                   16933:        {       register Plist gl;
                   16934:                Pgen g = Pgen(t1);
                   16935:                Pname found = 0;
                   16936:                Pname exact = 0;
                   16937:                int no_exact = 0;
                   16938:                int no_gen = 0;
                   16939: 
                   16940:                for (gl=g->fct_list; gl; gl=gl->l) {    // look for exact match
                   16941:                        register Pname nn = gl->f;
                   16942:                        if (exact_match(nn,arg)) {
                   16943: //error('d',"found exact %n %t",nn,nn->tp);
                   16944:                                if (found) {
                   16945:                                        // check if one fct dominates the other
                   16946:                                        Pname d = dominate(found,nn,arg,const_obj,0);
                   16947:                                        if (d)
                   16948:                                                nn = d;
                   16949:                                        else
                   16950:                                                error("two exact matches for%n:%t and%t",nn,nn->tp,found->tp);
                   16951:                                }
                   16952:                                found = nn;
                   16953:                        }
                   16954:                }
                   16955: //error('d',"found exact2 %n",found);
                   16956:                if (found) goto fnd;
                   16957: 
                   16958: Pname mvec[20];
                   16959: 
                   16960: /****************************************************************************
                   16961:    the next 2 loops have been commented out to eliminate the rule that calls
                   16962:    requiring only promotions and standard conversions are preferred over
                   16963:    calls requiring user-defined conversions.
                   16964: 
                   16965:                for (gl=g->fct_list; gl; gl=gl->l) {    // look for exact match
                   16966:                        register Pname nn = gl->f;
                   16967: 
                   16968:                        if (prom_match(nn,arg)) {
                   16969:                                if (found) {
                   16970:                                        // check if one fct dominates the other
                   16971:                                        Pname d = dominate(found,nn,arg,const_obj,1);
                   16972:                                        if (d)
                   16973:                                                nn = d;
                   16974:                                        else
                   16975:                                                error("two exact matches (after integral promotions) for%n:%t and%t",nn,nn->tp,found->tp);
                   16976:                                }
                   16977:                                found = nn;
                   16978:                        }
                   16979:                }
                   16980: //error('d',"found exact2 %n",found);
                   16981:                if (found) goto fnd;
                   16982: 
                   16983:        //      for (gl=g->fct_list; gl; gl=gl->l) {    // look for exact match
                   16984:        //              register Pname nn = gl->f;
                   16985:        //
                   16986:        //              if (exact_match(nn,arg) || prom_match(nn,arg)) {
                   16987:        //                      found = nn;
                   16988:        //                      goto fnd;
                   16989:        //              }
                   16990:        //      }
                   16991: 
                   16992:                for (gl=g->fct_list; gl; gl=gl->l) {    // look for match
                   16993:                                                        // with standard conversion
                   16994:                        register Pname nn = gl->f;
                   16995:                        Ninit = 0;
                   16996:                        Nstd = 0;
                   16997:                        if (std_match(nn,arg)) {
                   16998:                        //      if (Nstd == 0)  {
                   16999:                        //              found = nn;
                   17000:                        //              goto fnd;
                   17001:                        //      }
                   17002:                                if (exact) {
                   17003:                                        // check if one fct dominates the other
                   17004:                                        Pname d = dominate(exact,nn,arg,const_obj,2);
                   17005:                                        if (d == 0) {
                   17006:                                                mvec[no_exact++] = nn;
                   17007:                                        //      no_exact++;
                   17008:                                        //      error("two standard conversions possible for%n: %t and %t",fn,exact->tp,nn->tp);
                   17009:                                        }
                   17010:                                        else
                   17011:                                                exact = d;
                   17012:                                }
                   17013:                                else
                   17014:                                        exact = nn;
                   17015:                        }
                   17016:                        
                   17017:                }
                   17018: 
                   17019: //error('d',"excact %n",exact);
                   17020:                if (exact) {
                   17021:                        if (no_exact) {
                   17022:                                while (no_exact) {
                   17023:                                        Pname d = dominate(exact,mvec[--no_exact],arg,const_obj,2);
                   17024:                                        if (d)
                   17025:                                                exact = d;
                   17026:                                        else
                   17027:                                                error("two standard conversions possible for%n: %t and %t",fn,exact->tp,mvec[no_exact]->tp);
                   17028:                                }
                   17029:                                
                   17030:                        }
                   17031: //error('d',"found exact3 %n",found);
                   17032:                        found = exact;
                   17033:                        goto fnd;
                   17034:                }
                   17035: 
                   17036:     this is the end of the commented out section.
                   17037: ************************************************************************/
                   17038: 
                   17039:                for (gl=g->fct_list; gl; gl=gl->l) {    /* look for coercion */
                   17040:                        register Pname nn = gl->f;
                   17041:                        if (prom_match(nn,arg) ||
                   17042:                            std_match(nn,arg)  ||
                   17043:                            gen_coerce(nn,arg)) {
                   17044: //error('d',"user2 %n %t",nn,nn->tp);
                   17045:                                if (found) {
                   17046:                                        // check if one fct dominates the other
                   17047:                                        Pname d = dominate(found,nn,arg,const_obj,3);
                   17048: //error('d',"dom d %d",d);
                   17049:                                        if (d == 0) d = user_dominate(found,nn,arg);
                   17050:                                        if (d == 0) {
                   17051:                                                mvec[no_gen++] = nn;
                   17052:                                        }
                   17053:                                        else
                   17054:                                                found = d;
                   17055:                                }
                   17056:                                else
                   17057:                                        found = nn;
                   17058:                        }
                   17059:                }
                   17060:                if(found) {
                   17061:                        while(no_gen) {
                   17062:                                Pname d = dominate(found,mvec[--no_gen],arg,const_obj,3);
                   17063:                                if(d==0) d = user_dominate(found,mvec[no_gen],arg);
                   17064:                                if(d)
                   17065:                                        found = d;
                   17066:                                else {
                   17067:                                        //error("ambiguousA for%n: %t and %t",fn,found->tp,mvec[no_gen]->tp);
                   17068:                                        error("ambiguous call of%n: %t and %t",fn,found->tp,mvec[no_gen]->tp);
                   17069:                                }
                   17070:                        }
                   17071:                }
                   17072:        fnd:
                   17073: //error('d',"fnd %t",found?found->tp:0);
                   17074:                if (found) {
                   17075:                        overFound = chk = fn = found;
                   17076:                        f = Pfct(fn->tp);
                   17077:                }
                   17078:                else {
                   17079:                        error("badAL for%n (no match against any %n)",fn,fn);
                   17080:                        return any_type;
                   17081:                }
                   17082:                break;
                   17083:        }
                   17084:        case FCT:
                   17085:                f = Pfct(t1);
                   17086:                if (fn) {
                   17087:                        switch (fn->n_oper) {
                   17088:                        case CTOR:
                   17089:                        case TYPE:
                   17090:                                chk = fn;
                   17091:                        }
                   17092:                }
                   17093:        }
                   17094: 
                   17095: //error('d',"chk %n",chk);
                   17096:        if (chk) {
                   17097:                Ptype t = 0;
                   17098:                Pexpr ee = e1->e1;
                   17099: 
                   17100:                switch (e1->base) {
                   17101:                case REF:       // ptr->chk()
                   17102:                        if (ee == 0) {  // 0->x() fudge handling new x()
                   17103:                                check_visibility(chk,no_virt,Pclass(chk->n_table->t_name->tp),tbl,cc->nof);
                   17104:                                break;
                   17105:                        };
                   17106:                        t = ee->tp;
                   17107:                        while(t->base==TYPE) t = Pbase(t)->b_name->tp;
                   17108:                        t = Pptr(t)->typ;
                   17109:                        break;
                   17110:                case DOT:       // obj.chk()
                   17111:                        t = ee->tp;
                   17112:                }
                   17113: 
                   17114:                Pname cn = t?t->is_cl_obj():0;
                   17115:                Pclass cl = cn?Pclass(cn->tp):0; // class of ``this'' for chk
                   17116: 
                   17117:                if (cl) {
                   17118:                        if (chk->n_oper==CTOR
                   17119:                                && chk->n_protect
                   17120:                                && cc->nof
                   17121:                                && cc->nof->n_oper==CTOR)
                   17122:                                        // BUG: cannot handle protected base
                   17123:                                        // class constructor
                   17124:                                ;
                   17125:                        else {
                   17126:                                check_visibility(chk,no_virt,cl,tbl,cc->nof);
                   17127:                        }
                   17128:                }
                   17129:        }
                   17130: 
                   17131:        if (fn && f->returns->is_cl_obj() && f->f_result==0) {
                   17132:                // protect against class cn; cn f(); ... class cn { cn(cn&); ... };
                   17133:                make_res(f);
                   17134: //error('d',"returns %t",f->returns);
                   17135:                f->returns->tsizeof();  // make sure it is declared
                   17136:        }
                   17137: 
                   17138: //error('d',"fn %n %t printed %d",fn,fn?fn->tp:0,fn?fn->n_dcl_printed:0);
                   17139:        if (fn && fn->n_dcl_printed==0) {
                   17140:                if (f->f_inline==0 && f->f_imeasure) {
                   17141:                        extern void uninline(Pname fn);
                   17142:                        uninline(fn);
                   17143:                }
                   17144: 
                   17145:                // ensure printout of class declaration:
                   17146:                for (Pname nn=f->argtype; nn; nn=nn->n_list)
                   17147:                        if (nn->tp->is_cl_obj()) (void) nn->tp->tsizeof();
                   17148: 
                   17149:                fn->dcl_print(0);
                   17150:        }
                   17151: 
                   17152:        if (no_virt && f->f_static==0) {
                   17153:                if (e1->base==REF || e1->base==DOT) e1->n_initializer = fn;
                   17154:        }
                   17155:        else
                   17156:                fct_name = fn;
                   17157: //error('d',"fn %n %t %d %d",fn,f,f->f_this,f->f_static);
                   17158:        if (f->f_this) {        //SSS call of non-static memberfunction
                   17159:                switch (e1->base) {
                   17160:                case MEMPTR:
                   17161:                case REF:
                   17162:                case DOT:
                   17163:                        break;
                   17164:                default:
                   17165:                        error("O orP missing for%n ofT %t",fct_name,f);
                   17166:                }
                   17167:        }
                   17168:        else if (fn) {  //SSS call of static function
                   17169:        sss:
                   17170:                switch (e1->base) {
                   17171:                case REF:
                   17172:                case DOT:
                   17173:                        e1 = e1->mem;
                   17174:                        goto sss;
                   17175:                }
                   17176:        }
                   17177: 
                   17178:        if (fn) fn->use();      // a patch: ctors are sometimes not use()d
                   17179: 
                   17180:        if (f->f_const==0
                   17181:        && (fn==0 || (fn->n_oper!=CTOR && fn->n_oper!=DTOR))) { //CCC
                   17182:                Pexpr ee = e1->e1;
                   17183:                 // while (ee && (ee->base==DOT || ee->base==REF)) ee = ee->e1;
                   17184:                 while (ee && (ee->base==DOT || ee->base==REF)) {
                   17185:                        Pexpr m = ee->mem;
                   17186: // error('d', "m: %k tp %t", m?m->base:0, m?m->tp:0 ); 
                   17187:                        if ( ee->base==REF && m->tp &&  m->tp->is_ptr())
                   17188:                                break;
                   17189:                        ee = ee->e1;
                   17190:                }
                   17191: // error('d', "ee: %k tp %k", ee?ee->base:0, ee?ee->tp->base:0);
                   17192: 
                   17193:                if (ee) {
                   17194:                        Ptype tt = ee->tp;
                   17195:                        switch (e1->base) {
                   17196:                        case REF:
                   17197:                        {       Pptr p = tt?tt->is_ptr():0;
                   17198:                                if (p && p->typ->tconst())
                   17199:                                        error(strict_opt?0:'w',"non-constMF%n called for constO (anachronism)",fn);
                   17200:                                // is really an error, but only warn to help transition
                   17201:                                break;
                   17202:                        }
                   17203:                        case DOT:
                   17204:                                int tc = tt ? tt->tconst() : 0;
                   17205:                                if (tt && tc && (!strict_opt || tc!=2))
                   17206:                                        error(strict_opt?0:'w',"non-constMF%n called for constO (anachronism)",fn);
                   17207:                                // is really an error, but only warn to help transition
                   17208:                        }
                   17209:                }
                   17210:        }
                   17211: 
                   17212:        t = f->returns;
                   17213:        x = f->nargs;
                   17214:        k = f->nargs_known;
                   17215: 
                   17216:        e = arg;
                   17217:        if (k == 0) goto rlab;
                   17218: 
                   17219:        for (nn=f->argtype, argno=1; e||nn; nn=nn->n_list, e=etail->e2, argno++) {
                   17220:                Pexpr a;
                   17221:                int save_base = 0;
                   17222:                char* save_name = 0;
                   17223: 
                   17224:                if (e) {
                   17225:                        a = e->e1;
                   17226:                        etail = e;
                   17227: 
                   17228:                        if (nn) {       /* type check */
                   17229:                                Ptype t1 = nn->tp;
                   17230: //error('d',"argtp %t etp %t a %k",t1,a->tp,a->base);
                   17231: 
                   17232:                                while(t1->base == TYPE)
                   17233:                                        t1 = Pbase(t1)->b_name->tp;
                   17234: 
                   17235:                                switch (t1->base) {
                   17236:                                case RPTR:
                   17237:                                {       Ptype pt = Pptr(t1)->typ;
                   17238:                                        if (pt->base != FCT ||
                   17239:                                                ( pt->base == FCT && 
                   17240:                                                  pt->check(a->tp,0)))
                   17241:                                                        a = ref_init(Pptr(nn->tp),a,tbl);
                   17242:                                        goto cbcb;
                   17243:                                }
                   17244:                                case COBJ:
                   17245:                                        if (a->base!=G_CM
                   17246:                                        || nn->tp->check(a->tp,ASSIGN))
                   17247:                                                a = class_init(0,t1,a,tbl);
                   17248:                                        else
                   17249:                                                a->e2=class_init(0,t1,a->e2,tbl);
                   17250:                                        if (nn->n_xref) {
                   17251:                                                // (temp.ctor(arg),&arg)
                   17252:                                                a = a->address();
                   17253:                                        }
                   17254:                                        else {
                   17255:                                                // defend against:
                   17256:                                                //      int f(X); ... X(X&);
                   17257:                                                Pname cln = Pbase(t1)->b_name;  
                   17258:                                                if (cln && Pclass(cln->tp)->has_itor()) {
                   17259:                                                        // mark X(X&) arguments
                   17260:                                                        nn->n_xref = 1;
                   17261:                                                        a = a->address();
                   17262:                                                }
                   17263:                                        }
                   17264:        cbcb:
                   17265: //error('d',"cbcb: a %d %k %t",a->base,a->base,a->tp);
                   17266:                if (a->base==G_CM) {
                   17267:                        if (a->e1->base==DEREF) a->e1 = a->e1->e2; // (*e1,e2) => (e1,e2)
                   17268: //error('d',"      a %d %k",a->e1->base,a->e1->base);
                   17269:                        if (a->e1->base==G_CALL
                   17270:                        && Pname(a->e1->fct_name)
                   17271:                        && Pname(a->e1->fct_name)->n_oper==CTOR
                   17272:                        && (a->e2->base==G_ADDROF || a->e2->base==ADDROF)) {
                   17273:                                a = a->e1;      // (ctor(&tmp),&tmp) => ctor(&tmp)
                   17274: //error('d',"tmp %k %n",a->e2->base,a->e2->e2);
                   17275:                                goto cccc;
                   17276:                        }
                   17277:                        else if (a->e2->base==G_ADDROF
                   17278:                        && a->e2->e2->base==NAME)  {
                   17279:                        cccc:
                   17280: //error('d',"cccc: a %d %k %t",a->base,a->base,a->tp);
                   17281:        if (t1->base==RPTR
                   17282:        && Pptr(t1)->typ->tconst()==0) {        // temporary used
                   17283:                if (warning_opt)
                   17284:                        error('w',"temporary used for non-const%tA",nn->tp);
                   17285:                else {
                   17286:                        Ptype atp = a->tp;
                   17287:                        if (atp==void_type
                   17288:                        && a->base==G_CALL
                   17289:                        && a->e1->tp->base==FCT)
                   17290:                                atp = Pfct(a->e1->tp)->s_returns;
                   17291: 
                   17292:                        Ptype tt = t1->is_ref();
                   17293: //error('d',"tt %t atp %t",tt,atp);
                   17294:                        if (tt) {
                   17295:                                if (Pptr(tt)->typ->tsizeof()!=atp->tsizeof()) { // sliced
                   17296:                                        Ptype aat = atp->is_ptr_or_ref();
                   17297:                                        if (aat==0
                   17298:                                        || Pptr(tt)->typ->tsizeof()!=Pptr(aat)->typ->tsizeof())
                   17299:                                                error('w',"temporary used for non-const%tA",nn->tp);
                   17300:                                }
                   17301:                        }
                   17302:                        else if (t1->tsizeof()!=atp->tsizeof()) // sliced
                   17303:                                error('w',"temporary used for non-const%tA",nn->tp);
                   17304:                }
                   17305:                
                   17306:        //      if (warning_opt                         // blabber
                   17307:        //      ||  t1->tsizeof()!=a->tp->tsizeof()))   // sliced
                   17308:        //              error('w',"temporary used for non-const%tA",nn->tp);
                   17309: 
                   17310:        }
                   17311:                        }
                   17312:                }
                   17313:                                        e->e1 = a;
                   17314:                                        break;
                   17315:                                case ANY:
                   17316:                                        goto rlab;
                   17317:                                case PTR:
                   17318:                                {
                   17319:                                        save_base = e->e1->base;
                   17320:                                        if(a->tp->base==OVERLOAD)
                   17321:                                                save_name = Pgen(a->tp)->fct_list->f->string;
                   17322:                                        Pexpr te_a = a;
                   17323:                                        e->e1 = a = ptr_init(Pptr(t1),a,tbl);
                   17324:                                        no_change = (te_a == a);
                   17325:                                //      if (x==a || x==a->e2) goto def; // needs checking
                   17326:                                        if (Pchecked == 0) goto def;
                   17327:                                        break;
                   17328:                                }
                   17329:                                //      e->e1 = a = ptr_init(Pptr(t1),a,tbl);
                   17330:                                //      goto def;
                   17331:                                case CHAR:
                   17332:                                case SHORT:
                   17333:                                case INT:
                   17334:                                //      if (a->base==ICON && a->tp==long_type)
                   17335:                                //              error('w',"long constantA for%n,%kX",fn,t1->base);
                   17336:                                {       Ptype t = a->tp;
                   17337:                                        while(t->base == TYPE)
                   17338:                                                t = Pbase(t)->b_name->tp;
                   17339: 
                   17340:                                        switch (t->base) {
                   17341:                                        case LONG:
                   17342:                                        case FLOAT:
                   17343:                                        case DOUBLE:
                   17344:                                        case LDOUBLE:
                   17345:                                                error('w',"A%d: %t passed as %t",argno,a->tp,t1);
                   17346:                                        }
                   17347:                                }
                   17348:                                        // no break
                   17349:                                case LONG:
                   17350:                                        if (Pbase(t1)->b_unsigned
                   17351:                                        && a->base==UMINUS
                   17352:                                        && a->e2->base==ICON)
                   17353:                                                error('w',"negativeA for%n, unsignedX",fn);
                   17354:                                default:
                   17355:                                def:
                   17356:                                {       Pexpr x = try_to_coerce(t1,a,"argument",tbl);
                   17357: //error('d',"x %d t1 %t nn %t a1 %t",x,t1,nn->tp,a->tp);
                   17358:                                        if (x) {
                   17359:                                                if (Pchecked == 0 && no_change) { 
                   17360:                                                        Pexpr te_x = ptr_init(Pptr(t1), x, tbl);
                   17361: 
                   17362:                                                        if ( te_x != x ) e->e1 = a = te_x; else e->e1=x;
                   17363:                                                }
                   17364:                                                else
                   17365:                                                        e->e1 = x;
                   17366:                                        }
                   17367:                                        else if (nn->tp->check(a->tp,ARG)) {
                   17368:                                                error("badA %dT for%n:%t (%tX)",argno,fn,a->tp,nn->tp);
                   17369:                                                return any_type;
                   17370:                                        }
                   17371:                                }
                   17372:                                }
                   17373: 
                   17374:                                 Pexpr tt = e->e1;
                   17375:                                 while ( tt->base == CAST )
                   17376:                                         tt = tt->e1;
                   17377:                                 if ( tt->base == ILIST )
                   17378:                                         e->e1 = tt;
                   17379: 
                   17380:                                 if (e->e1->base == ILIST) {
                   17381:                                         // memptr constant
                   17382:                                         // f({1,2,f}) ==> memptr t; f((t={1,2,f},t))
                   17383:                                        if(save_base == REF) {
                   17384:                                                Pptr m = Pptr(a->tp);
                   17385:                                                error(strict_opt?0:'w',
                   17386:                                                "address of boundF (try using ``%s::*'' forPT and ``&%s::%s'' for address) (anachronism)",
                   17387:                                                m->memof->string,
                   17388:                                                m->memof->string,
                   17389:                                                save_name
                   17390:                                                );
                   17391:                                        }
                   17392:                                         Pname temp = make_tmp('A',mptr_type,tbl);
                   17393:                                         e->e1 = mptr_assign(temp,e->e1);
                   17394:                                         e->e1 = a = new expr(G_CM,e->e1,temp);
                   17395:                                         a->tp = temp->tp;
                   17396:                                 }
                   17397: 
                   17398:                        }
                   17399:                        else {
                   17400:                                if (k != ELLIPSIS) {
                   17401:                                        error("unexpected %dA for%n",argno,fn);
                   17402:                                        return any_type;
                   17403:                                }
                   17404:                                Pexpr te=e;
                   17405:                                while(e) {
                   17406:                                        if (e->e1->base == ILIST) {
                   17407:                                                // memptr constant
                   17408:                                                // f({1,2,f}) ==> memptr t; f((t={1,2,f},t))
                   17409:                                                Pname temp = make_tmp('A',mptr_type,tbl);
                   17410:                                                e->e1 = mptr_assign(temp,e->e1);
                   17411:                                                e->e1 = a = new expr(G_CM,e->e1,temp);
                   17412:                                                a->tp = temp->tp;
                   17413:                                        }
                   17414:                                        e = e->e2;
                   17415:                                }
                   17416:                                e = te;
                   17417:                                goto rlab;
                   17418:                        }
                   17419:                }
                   17420:                else {  /* default argument? */
                   17421:                        a = nn->n_initializer;
                   17422:                        if (a == 0) {
                   17423:                                error("A %d ofT%tX for%n",argno,nn->tp,fn);
                   17424:                                return any_type;
                   17425:                        }
                   17426:                                 if (a->base == ILIST) {
                   17427:                                         // memptr constant
                   17428:                                         // f({1,2,f}) ==> memptr t; f((t={1,2,f},t))
                   17429:                                         Pname temp = make_tmp('A',mptr_type,tbl);
                   17430:                                         a = mptr_assign(temp,a);
                   17431:                                         a = new expr(G_CM,a,temp);
                   17432:                                         a->tp = temp->tp;
                   17433:                                 }
                   17434:                        a->permanent = 2;       // ought not be necessary, but it is
                   17435:                        e = new expr(ELIST,a,0);
                   17436:                        if (etail)
                   17437:                                etail->e2 = e;
                   17438:                        else
                   17439:                                e2 = e;
                   17440:                        etail = e;
                   17441:                }
                   17442:        }
                   17443: 
                   17444: rlab:
                   17445: //error('d',"rlab fct_name %n %t",fct_name,fct_name?fct_name->tp:0);
                   17446:        for (; e; e = e->e2) {  // unchecked arguments
                   17447:                Pexpr a = e->e1;
                   17448:                Pname cn;
                   17449: 
                   17450:                if (a->base==NAME && a->tp->base==FCT) {
                   17451:                        // function name that escaped the type system:
                   17452:                        // update use count
                   17453:                        a->lval(ADDROF);
                   17454:                }
                   17455:                else if (warning_opt && (cn = a->tp->is_cl_obj())) {
                   17456:                        Pclass cl = Pclass(cn->tp);
                   17457:                        if (cl->has_ctor() || cl->memtbl->look("__as",0))//cl->has_oper(ASSIGN)
                   17458:                        {
                   17459:                                if (fct_name)
                   17460:                                error('w',"O ofC%t withK or = copied asA to%n (%t)",cl,fct_name,fct_name->tp);
                   17461:                                else
                   17462:                                error('w',"O ofC%t withK or = copied asA to `...'",cl);
                   17463:                        }
                   17464:                }
                   17465:                else if (a->tp->is_ref())
                   17466:                        e->e1 = a->contents();
                   17467:        }
                   17468: 
                   17469:        if (f->f_result) {              // f(args) => (f(&temp,args),temp)
                   17470:                Pname tn = make_tmp('R',f->returns,tbl);
                   17471:                e2 = new expr(ELIST,tn->address(),e2);
                   17472: // error('d',"result %n refd: %d",fn, refd);
                   17473:                Pexpr ee = new expr(0,0,0);
                   17474:                *ee = *this;
                   17475:                base = G_CM;            // (f(&temp,args),temp)
                   17476:                e1 = ee;
                   17477:                if (refd == 2)
                   17478:                        e2 = tn->address();
                   17479:                else e2 = tn;
                   17480:                tp = tn->tp;
                   17481:        }
                   17482: 
                   17483:        return t;
                   17484: }
                   17485: 
                   17486: int cm_const_save; 
                   17487: 
                   17488: Pexpr ref_init(Pptr p, Pexpr init, Ptable tbl)
                   17489: /*
                   17490:        initialize the "p" with the "init"
                   17491:        remember to call ptr_init to ensure that pointers to second bases
                   17492:        are handled correctly.
                   17493: */
                   17494: {
                   17495:        register Ptype it = init->tp;
                   17496:        Pptr px = p;
                   17497:        while (px->base == TYPE) px = Pptr(Pbase(px)->b_name->tp);
                   17498:        Ptype p1 = px->typ;
                   17499:        Pname c1 = p1->is_cl_obj();
                   17500: // error('d',"ref_init: p %t, p1 %t, px %t, init->tp %t",p,p1,px,it);
                   17501: // error('d', "ref_init: nof: %n f_const: %d", cc?cc->nof:0, cc?(cc->nof?Pfct(cc->nof->tp)->f_const:0):0);
                   17502: 
                   17503:        if (init->base == ILIST) error("IrL as RIr");
                   17504: 
                   17505:        if (init->base==NAME
                   17506:        && Pname(init)->n_scope==ARG
                   17507:        && init->tp->base==FLOAT)
                   17508:                error('w',"initializing a float& with floatA is non-portable");
                   17509: 
                   17510:        while(it->base == TYPE)
                   17511:                it = Pbase(it)->b_name->tp; 
                   17512: 
                   17513:        switch (it->base) {
                   17514:        default:
                   17515:                {       Ptype tt = it->addrof();
                   17516:                        px->base = PTR; // allow &x for y& when y : public x
                   17517:                                        // but not &char for int&
                   17518:                        int x = px->check(tt,COERCE);
                   17519: 
                   17520:                        if (x == 0) {   //CCC type is fine check for constness:
                   17521:                                if (init->tp->tconst()
                   17522:                                && vec_const==0
                   17523:                                && fct_const==0) {
                   17524:                                        // not ``it''
                   17525:                                        if (init->base == ELIST) init = init->e1;
                   17526:                                        if (px->typ->tconst() == 0) error("R to constO");
                   17527:                                        px->base = RPTR;
                   17528:                                        // if we have a const lvalue we can still pass its address
                   17529:                                        ignore_const++;
                   17530:                                        if (init->lval(0)) {
                   17531:                                                init->lval(ADDROF); // force output
                   17532:                                                ignore_const--;
                   17533: //error('d',"in1 %t",init->tp);
                   17534:                                                return ptr_init(px,init->address(),tbl);//return init->address();
                   17535:                                        }
                   17536:                                        ignore_const--;
                   17537:                                        goto xxx;
                   17538:                                }
                   17539:                                px->base = RPTR;
                   17540:                                 if (init->lval(0)) {   // can pass the address                                                 // no temporary needed 
                   17541:                                        init->lval(ADDROF); // force output
                   17542: //error('d',"px %t init %t init %t",px,init->tp,init->tp);
                   17543:                                        return ptr_init(px,init->address(),tbl);
                   17544:                                }
                   17545:                                goto xxx;
                   17546:                        }
                   17547: 
                   17548:                        px->base = RPTR;
                   17549:                }
                   17550:        }
                   17551: 
                   17552: //error('d',"c1 %n",c1);
                   17553:        if (c1) {       // assigning to a const X & is fine
                   17554:                ref_cast++;
                   17555:                Pexpr x = try_to_coerce(p,init,"reference initialization",tbl);
                   17556:                ref_cast--;
                   17557:                if (x) {
                   17558:                        init = x;
                   17559:                        goto xxx;
                   17560:                }
                   17561:                while (p1->base==TYPE) p1 = Pbase(p1)->b_name->tp;
                   17562:                int bc = Pbase(p1)->b_const;
                   17563:                Pbase(p1)->b_const = 0;
                   17564: //             refd = 1;       
                   17565:                switch ( init->base ) {
                   17566:                        case STRING: case ZERO: case CCON:
                   17567:                        case ICON: case FCON: case IVAL:
                   17568:                        case NAME:
                   17569:                                refd = 1; 
                   17570:                                break;
                   17571:                        default:
                   17572:                                refd = (init->e1 && init->e1->base == NAME && 
                   17573:                                        init->e1->tp->base != RPTR &&
                   17574:                                        Pname(init->e1)->n_xref == 0) ? 2: 1;
                   17575:                                break;
                   17576:                }
                   17577: // error('d', "***** refd: %d", refd );
                   17578:                Pexpr a = class_init(0,p1,init,tbl);
                   17579:                Pbase(p1)->b_const = bc;
                   17580:                refd = 0;
                   17581:                if (a==init && init->tp!=any_type) goto xxx;
                   17582: // error('d',"ri a %d %k",a->base,a->base);
                   17583:                switch (a->base) {
                   17584:                case G_CALL:
                   17585:        //      case CM:
                   17586:        //      case G_CM:
                   17587:                        init = a;
                   17588:                        goto xxx;
                   17589:                }
                   17590:                a = a->address();
                   17591:                a =  ptr_init(px,a,tbl);
                   17592:                return a;
                   17593: //             return ptr_init(px,a->address(),tbl);//a->address();
                   17594:        }
                   17595: 
                   17596: //error('d',"p1 %t it %t",p1,it);
                   17597:        if (p1->check(it,0)) {
                   17598: 
                   17599:                if (p1->check(it,ASSIGN) == 0) {
                   17600:                //      if (p1->is_ptr())  // check for base* = derived*
                   17601:                //              goto xxx;
                   17602: 
                   17603:                        // things like ``double& rr = 1;'' temporary needed
                   17604:                        // warn in case of ``slightly wrong lvalue'', e.g.
                   17605:                        //      int i; double& r = i;
                   17606:                        if (init->lval(0) && p1->tconst()==0)
                   17607:                                error('w',"temporary used toIR; no changes will be propagated to actualA");
                   17608:                        goto def;
                   17609:                }
                   17610: 
                   17611:                Pexpr x = try_to_coerce(p1,init,"reference",tbl);       // x==init
                   17612:                if (x==0) x = try_to_coerce(px,init,"reference",tbl);   // x&=init
                   17613:                if (x) {
                   17614:                        init = x;
                   17615:                        goto def;
                   17616:                }
                   17617: 
                   17618:                error("badIrT:%t (%tX)",it,p);
                   17619:                if (init->base != NAME) init->tp = any_type;
                   17620:                return init;
                   17621:        }
                   17622:        
                   17623: xxx:   /*
                   17624:                here comes the test of a ``fundamental theorem'':
                   17625:                a structure valued expression is
                   17626:                        (1) an lvalue of type T (possibly const)
                   17627:                or      (2) the result of a function (a _result if X(X&) is defined)
                   17628:                or      (3) a * or [] or ? or , expression
                   17629:        */
                   17630: //error('d',"xxx %k %d %t",init->base,init->base,init->tp);
                   17631: 
                   17632:        switch (init->base) {
                   17633:        case NAME:
                   17634:        case DEREF:
                   17635:        case REF:
                   17636:        case DOT:                       // init => &init
                   17637:                if (it->tconst() && vec_const==0 && fct_const==0) goto def;
                   17638:                if ( cc && cc->nof && 
                   17639:                        Pfct(cc->nof->tp)->f_const ) 
                   17640:                                cm_const_save = Pbase(p->typ)->b_const;
                   17641:                init->lval(ADDROF);
                   17642:                cm_const_save = 0;
                   17643: 
                   17644:                if (vec_const) return init;
                   17645:                if (fct_const && p1->is_ptr()) goto def;        // fptr& = fct
                   17646:                // no break
                   17647:        case CM:
                   17648:        case G_CM:                      // & (f(&temp), temp)
                   17649:                return ptr_init(px,init->address(),tbl);//init->address();
                   17650:        default:
                   17651:        def:
                   17652:        {
                   17653: // error('d',"def: init->tp %t p1 %t ",init->tp,p1);   
                   17654: // error('d',"p1: %t const_ptr: %d", p1, const_ptr);
                   17655:                if (const_ptr == 0) {
                   17656:                        if (tbl == gtbl || strict_opt) 
                   17657:                                error("Ir for%snon-constR not an lvalue", strict_opt?"":" global ");
                   17658:                        else
                   17659:                        if (warning_opt) 
                   17660:                                error('w', "Ir for non-constR not an lvalue (anachronism)");
                   17661:                }
                   17662: 
                   17663:                 Pname tcl = p1->is_cl_obj ();
                   17664:                 if(tcl && Pclass(tcl->tp)->c_abstract)
                   17665:                        error("a temporary is needed for a parameter, but the argument type is abstract class %t.", tcl->tp);
                   17666: 
                   17667:                Pname n = make_tmp('I',p1,tbl);
                   17668:                Pexpr a;
                   17669:                Pname ic = init->tp->is_cl_obj();
                   17670: 
                   17671:                if (p1->tconst()==0
                   17672:                && (init->tp->tconst() && vec_const==0 && fct_const==0)
                   17673:                && p1->check(it,ASSIGN)==0)
                   17674:                        error('w',"constIr: temporary used toI reference");
                   17675: 
                   17676:                switch (p1->base) {
                   17677:                case INT:
                   17678:                case CHAR:
                   17679:                case SHORT:
                   17680:                        switch (it->base) {
                   17681:                        case LONG:
                   17682:                        case FLOAT:
                   17683:                        case DOUBLE:
                   17684:                        case LDOUBLE:
                   17685:                                error('w',"%t assigned to %t inRIr",it,p1);
                   17686:                        }
                   17687:                }
                   17688: 
                   17689:                if (ic!=c1 && Pclass(ic->tp) != Pclass(c1->tp)) {
                   17690:                        // derived class1 => must cast: ``it Ix; (Ix=init,(p)&Ix);''
                   17691:                        n->tp = init->tp;
                   17692:                        a = ptr_init(px,n->address(),tbl);//n->address();
                   17693:                        PERM(p);
                   17694:                        a = new texpr(CAST,p,a);
                   17695:                        a->tp = p;
                   17696:                }
                   17697:                else
                   17698:                        a = n->address();
                   17699: 
                   17700:                refd = 1;
                   17701:                Pexpr as = init_tmp(n,init,tbl);
                   17702:                refd = 0;
                   17703:                a = new expr(G_CM,as,a);
                   17704:                a->tp = a->e2->tp;
                   17705:                return a;
                   17706:        }
                   17707:        }
                   17708: }
                   17709: 
                   17710: Pexpr class_init(Pexpr nn, Ptype tt, Pexpr init, Ptable tbl)
                   17711: /*
                   17712:        initialize "nn" of type "tt" with "init"
                   17713:        if nn==0 make a temporary,
                   17714:        nn may not be a name
                   17715: */
                   17716: {      
                   17717:        if (init == dummy) return 0;
                   17718: //error('d',"class_init %t with %t init %k refd %d",tt,init->tp,init->base,refd);
                   17719:        Pname c1 = tt->is_cl_obj();
                   17720: 
                   17721:         if (init == 0) {
                   17722:                 error("emptyIr");
                   17723:                 return dummy;
                   17724:         }
                   17725: 
                   17726:        if (c1) {
                   17727:                Pclass cl = Pclass(c1->tp);
                   17728:                Pname c2 = init->tp->is_cl_obj();
                   17729: 
                   17730:                if (c1!=c2 || (refd==0 && cl->has_itor())) {
                   17731:                        /*      really ought to make a temp if refd,
                   17732:                                but ref_init can do that
                   17733:                        */
                   17734:                        int i = can_coerce(tt,init->tp);
                   17735: //error('d',"i %d nn %n",i,nn);
                   17736:                        switch (i) {
                   17737:                        default:
                   17738:                                error("%d ways of making a%n from a%t",i,c1,init->tp);
                   17739:                                init->tp = any_type;
                   17740:                                return init;
                   17741:                        case 0:
                   17742:                                if (c2 && Pclass(c2->tp)->has_base(cl)) {
                   17743:                                        init = init->address();
                   17744:                                        Pexpr x = cast_cptr(cl,init,tbl,0);
                   17745: 
                   17746:                                        if (x == init) {
                   17747:                                                Ptype pt = tt->addrof();
                   17748:                                                PERM(pt);
                   17749:                                                x = new cast(pt,init);
                   17750:                                        }
                   17751: 
                   17752:                                        return x->contents();
                   17753:                                }
                   17754:                                error("cannot make a%n from a%t",c1,init->tp);
                   17755:                                init->tp = any_type;
                   17756:                                return init;
                   17757:                        case 1:
                   17758: //error('d',"ncoerce %n %k %d",Ncoerce,init->base,init->base);
                   17759:                                if (Ncoerce == 0) {
                   17760:                                        Pexpr a = new expr(ELIST,init,0);
                   17761:                                        a = new texpr(VALUE,tt,a);
                   17762:                                        a->e2 = nn;
                   17763:                                //      return a->typ(tbl);
                   17764:                                        a = a->typ(tbl);
                   17765: //error('d',"ci a %k %d %t",a->base,a->base,a->tp);
                   17766:                                        return a;
                   17767:                                }
                   17768: 
                   17769:                                switch (init->base) {
                   17770:                                case CM:
                   17771:                                case G_CM:      //ddd
                   17772:                                case NAME:      /* init.coerce() */
                   17773:        /* *ref */              case DEREF:
                   17774:                                {       Pref r = new ref(DOT,init,Ncoerce);
                   17775:                                        Pexpr rr = r->typ(tbl);
                   17776:                                        init = new expr(G_CALL,rr,0);
                   17777:                                        init->fct_name = Ncoerce;
                   17778:                                        break;
                   17779:                                }
                   17780:                                default:        // (temp=init,temp.coerce())
                   17781:                                {       Pname tmp = make_tmp('U',init->tp,tbl); 
                   17782:                                        int x = refd;   
                   17783:                                        refd = 0;       // ??
                   17784:                                        Pexpr ass = init_tmp(tmp,init,tbl);
                   17785:                                        refd = x;
                   17786:                                        Pref r = new ref(DOT,tmp,Ncoerce);
                   17787:                                        Pexpr rr = r->typ(tbl);
                   17788:                                        Pexpr c = new expr(G_CALL,rr,0);
                   17789:                                        c->fct_name = Ncoerce;
                   17790:                                        c = c->typ(tbl);
                   17791:                                        init = new expr(CM,ass,c);
                   17792:                                        init->tp = c->tp;
                   17793:                                        if (refd) {     // &f() => (t=f(), &t)
                   17794:                                                Pname tmp2 = make_tmp('L',c->tp,tbl); 
                   17795:                                                ass = init_tmp(tmp2,init,tbl);
                   17796:                                                init = new expr(G_CM,ass,tmp2);
                   17797:                                        }
                   17798:                                }
                   17799:                                }
                   17800: //error('d',"nn %n",nn);
                   17801:                                if (nn) {
                   17802:                                        Pexpr a = new expr(ELIST,init,0);
                   17803:                                        a = new texpr(VALUE,tt,a);
                   17804:                                        a->e2 = nn;
                   17805:                                        return a->typ(tbl);
                   17806:                                }
                   17807:                        }
                   17808: //error('d',"c1 %n c2 %n",c1,c2);
                   17809:                        return init->typ(tbl);
                   17810:                }
                   17811:                return init;
                   17812:        }
                   17813: //error('d',"ci check tt %t init->tp %t",tt,init->tp);
                   17814:        if (tt->check(init->tp,ASSIGN) && refd==0) {
                   17815:                error("badIrT:%t (%tX)",init->tp,tt);
                   17816:                init->tp = any_type;
                   17817:        }
                   17818: 
                   17819:        return init;
                   17820: }
                   17821: 
                   17822: extern int bound;      // fudge for bound pointers to functions
                   17823: 
                   17824: Pexpr expr::docast(Ptable tbl)
                   17825: {      
                   17826:        // check cast against value, INCOMPLETE
                   17827: 
                   17828: //error('d',"docast %d %t %k",this,tp2,e1->base);
                   17829:        if (e1 == dummy) {
                   17830:                error("E missing for cast");
                   17831:                tp = any_type;
                   17832:                return this;
                   17833:        }
                   17834: 
                   17835:        int pmf = 0;
                   17836:        int ptom_cast = 0;
                   17837:        Pexpr ee = e1;
                   17838: 
                   17839: //error('d',"ee %k %d",ee->base,ee->base);
                   17840:        switch (ee->base) {
                   17841:        case ADDROF:
                   17842:                ee = ee->e2;
                   17843:                switch (ee->base) {
                   17844:                case NAME:      goto nm;
                   17845:                case REF:       goto rf;
                   17846:                }
                   17847:                break;
                   17848: 
                   17849:        case NAME:
                   17850:        nm:
                   17851:                if (Pname(ee)->n_qualifier) pmf = 1;
                   17852:                break;
                   17853:                
                   17854:        case REF:
                   17855:        rf:
                   17856:                if (ee->e1->base == THIS) bound = 1;
                   17857:                break;
                   17858:        }
                   17859: 
                   17860:        e1 = e1->typ(tbl);
                   17861: 
                   17862:        int b = bound;  // distinguish between explicit and implicit THIS
                   17863:        bound = 0;
                   17864:        pmf = pmf && e1->base==CAST;
                   17865: 
                   17866:        Ptype etp = e1->tp;
                   17867:        Ptype tt = tp2;
                   17868:        Ptype t = tt;
                   17869:        tt->dcl(tbl);
                   17870: 
                   17871:        while (etp->base == TYPE) etp = Pbase(etp)->b_name->tp;
                   17872:        while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp;
                   17873:        
                   17874: //error('d',"e1 %k etp %t tt %t",e1->base,etp,tt);
                   17875: 
                   17876:        switch (etp->base) {
                   17877:        case PTR:
                   17878:        case RPTR:
                   17879:                if (Pptr(etp)->typ->base == OVERLOAD) goto over;
                   17880: 
                   17881:                if (warning_opt && i2==0 && Pptr(etp)->typ->tconst()) {
                   17882:                        switch (tt->base) {
                   17883:                        case FCT:
                   17884:                                break;
                   17885:                        case PTR:
                   17886:                        case RPTR:
                   17887:                                if (Pptr(tt)->typ->tconst()) break;
                   17888:                        default:
                   17889:                                // casting away const
                   17890:                                // should be an error
                   17891:                                // but ANSI says OK so I chicken out
                   17892:                                // to be able to compile strtok(), etc.
                   17893:                                error('w',"const cast away:%t->%t",e1->tp,tp2);
                   17894:                        }
                   17895:                }
                   17896:                else
                   17897:                        i2 = 0; // to allow cfront to escape its own checking
                   17898:                break;
                   17899:        case COBJ:
                   17900:        {       ref_cast = 1;
                   17901:                Pexpr x = try_to_coerce(tt,e1,"cast",tbl);
                   17902:                ref_cast = 0;
                   17903: //error('d',"x %k %t tt %d %t",x?x->base:0,x?x->tp:0,tt,tt);
                   17904:                if (x) {
                   17905:                        if (x!=e1 && x->base==DEREF && tt->is_ref()) x = x->e1;
                   17906:                        if (tt==x->tp || tt->check(x->tp,0)==0 || const_problem)
                   17907:                                return x;
                   17908:                        else
                   17909:                                return new cast(tt,x);
                   17910:                }
                   17911:        //      else if (e1->base==DEREF && tt->is_ref()) return e1;
                   17912:                break;
                   17913:        }
                   17914:        case VOID:
                   17915:                if (tt->base == VOID) {
                   17916:                        tp = t;
                   17917:                        return this;
                   17918:                }
                   17919:                error("cast of void value");
                   17920:                // no break;
                   17921:        case ANY:
                   17922:        any:
                   17923:                tp = any_type;
                   17924:                return this;
                   17925:        case FCT:
                   17926:                if (tt->base == PTR && Pptr(tt)->typ->base != FCT)
                   17927:                        error('w',"P toF cast toP to nonF");
                   17928:                break;
                   17929:        case OVERLOAD:
                   17930:        over:
                   17931:                error("cast of overloaded");
                   17932:                goto any;
                   17933:        }
                   17934: 
                   17935: //error('d',"tt %t",tt);
                   17936:        switch (tt->base) {
                   17937:        case PTR:
                   17938:                if (Pptr(tt)->typ->base==FCT && Pptr(tt)->memof) {
                   17939:                        if (etp->base!=PTR
                   17940:                        || Pptr(etp)->typ->base!=FCT
                   17941:                        || Pptr(etp)->memof==0)
                   17942:                                error("cast toP toM %t",tt);
                   17943:                        else {  // adjust delta in MI case
                   17944:                                // for the moment just suppress the cast
                   17945:                                // all pmfs are the same to cc
                   17946: /*
                   17947:                                Pclass c1 = Pptr(tt)->memof;
                   17948:                                Pclass c2 = Pptr(etp)->memof;
                   17949: */
                   17950:                                ptom_cast = 1;
                   17951:                                tp2 = void_type;
                   17952:                        }
                   17953:                }
                   17954: 
                   17955:                switch (etp->base) {
                   17956:                case COBJ:
                   17957:                        error("cannot castCO toP");
                   17958:                        break;
                   17959:                case FCT:
                   17960:                        e1 = new expr(G_ADDROF,0,e1);
                   17961:                        bound = b;
                   17962:                        e1 = e1->typ(tbl);
                   17963:                        bound = 0;
                   17964:                        if (e1->base == CAST)
                   17965:                                pmf = 1;
                   17966:                        else
                   17967:                                break;
                   17968:                        // no break;
                   17969: 
                   17970:                case PTR:
                   17971:                {       Pname cn = Pptr(tt)->typ->is_cl_obj();
                   17972:                        if (cn) {
                   17973:                                Pexpr x = cast_cptr(Pclass(cn->tp),e1,tbl,1);
                   17974: 
                   17975:                                if (x == e1) {
                   17976:                                        PERM(tt);
                   17977:                                        e1 = new cast(tt,e1);
                   17978:                                        e1->i2 = i2;
                   17979:                                }
                   17980:                                else
                   17981:                                        e1 = x;
                   17982:                        }
                   17983:                        if (pmf) {
                   17984:                                while(tt->base == TYPE)
                   17985:                                        tt = Pbase(tt)->b_name->tp;
                   17986: 
                   17987:                                switch (tt->base) {
                   17988:                                case PTR:
                   17989:                                        if (Pptr(tt)->memof) break;
                   17990:                                default:
                   17991:                                        error("%t cast to%t (%t is not aP toM)",e1->tp,tp2,tp2);
                   17992:                                }
                   17993:                        }
                   17994:                }
                   17995:                }
                   17996:                break;
                   17997: 
                   17998:        case RPTR:              // (x&)e: pretend e is an x
                   17999:        {       Ptype er = etp;
                   18000:                Ptype cr = tt;
                   18001:                do {
                   18002:                        if (er = er->is_ptr_or_ref()) er = Pptr(er)->typ;
                   18003:                        if (cr = cr->is_ptr_or_ref()) cr = Pptr(cr)->typ;
                   18004:                } while (er && cr);
                   18005:                int pp = er!=0; //      if `e' is a suitable pointer cast it:
                   18006:                                //      (x&)e => (x*)e, otherwise
                   18007:                                //      (x&)e => *(x*)&e
                   18008: // error('d',"rptr tt %t e1->base %k e1->tp %t",tt,e1->base,e1->tp);
                   18009:        //      if (Pptr(tt)->typ->tsizeof()>etp->tsizeof()) goto zse;
                   18010:        // we need to be able to ``raise the type'' from base to derived
                   18011:        //      if (etp->is_cl_obj() && Pptr(tt)->typ->is_cl_obj()==0) goto zse;
                   18012: 
                   18013:                if (e1->base==G_CM
                   18014:                || e1->base==CALL
                   18015:                || e1->base==G_CALL
                   18016:                || e1->lval(0))
                   18017:                        ;
                   18018:                else if (e1->tp->tconst()) {
                   18019:                                // casting away const
                   18020:                                // should be an error
                   18021:                                // but ANSI says OK so I chicken out
                   18022:                                // to be able to compile strtok(), etc.
                   18023:                        if (warning_opt && Pptr(tt)->typ->tconst()==0)
                   18024:                                error('w',"const cast away:%t->%t",e1->tp,tp2);
                   18025: 
                   18026:                }
                   18027:                else
                   18028:                        error("cannot cast%t to%t",etp,t);
                   18029: //error('d',"e1 %k %t %d",e1->base,e1->tp,pp);
                   18030:                if (pp == 0) e1 = e1->address();        // *(x*)&e
                   18031:                tp = t;
                   18032: 
                   18033:                // do proper pointer manipulation for multiple inheritance
                   18034:                Pname cn = Pptr(tt)->typ->is_cl_obj();
                   18035:                if (cn) {
                   18036:                        Pexpr x = cast_cptr(Pclass(cn->tp),e1,tbl,1);
                   18037: 
                   18038:                        if (x == e1) {
                   18039:                                PERM(tt);
                   18040:                                e1 = new cast(tt,e1);
                   18041:                                e1->i2 = i2;
                   18042:                        }
                   18043:                        else
                   18044:                                e1 = x;
                   18045:                }
                   18046: 
                   18047:                return pp ? this : contents();
                   18048: //     zse:
                   18049: //             error("cannot cast%t to%t",etp,t);
                   18050: //             tp2 = tt = any_type;
                   18051: //             break;
                   18052:        }
                   18053:        case COBJ:
                   18054:                base = VALUE;   // (x)e => x(e): construct an x from e
                   18055:                e1 = new expr(ELIST,e1,0);
                   18056:                return typ(tbl);
                   18057: 
                   18058:        case CHAR:
                   18059:        case INT:
                   18060:        case SHORT:
                   18061:        case LONG:
                   18062:                switch (etp->base) {
                   18063:                case FCT:
                   18064:                        e1 = new expr(ADDROF,0,e1);
                   18065:                        e1 = e1->typ(tbl);
                   18066:                        //etp = e1->tp;
                   18067:                case PTR:
                   18068:                        if(!e1->tp->memptr() && e1->tp->tsizeof()>tt->tsizeof())
                   18069:                                error("type ``%t'' not large enough for values of ``%t ''",tt,etp);
                   18070:                        break;
                   18071:                case COBJ:
                   18072:                        error("cannot castCO to%k",tt->base);
                   18073:                        break;
                   18074:                }       
                   18075:                break;
                   18076: 
                   18077:        case FLOAT:
                   18078:        case DOUBLE:
                   18079:        case LDOUBLE:
                   18080:                switch (etp->base) {
                   18081:                case FLOAT:
                   18082:                case DOUBLE:
                   18083:                case LDOUBLE:
                   18084:                case CHAR:
                   18085:                case INT:
                   18086:                case SHORT:
                   18087:                case LONG:
                   18088:                case EOBJ:
                   18089:                case ZTYPE:
                   18090:                        break;
                   18091:                default:
                   18092:                        error("cannot cast ``%t '' to ``%t''",etp,tt);
                   18093:                        break;
                   18094:                }       
                   18095:                break;
                   18096: 
                   18097:        case FCT:
                   18098:                error("cannot cast toFT");
                   18099:                break;
                   18100:        }
                   18101: 
                   18102:        tp = t;
                   18103: 
                   18104:        if (e1->base==ILIST && ptom_cast==0) { // pointer to member constant
                   18105:                Pexpr ee = e1->e1;      // ELIST
                   18106:                int i;
                   18107:                switch (ee->e2->base) {
                   18108:                case IVAL:
                   18109:                        i = int(ee->e2->i1);
                   18110:                        break;
                   18111:                case ZERO:
                   18112:                        i = 0;
                   18113:                }
                   18114: 
                   18115:                if (i<0)
                   18116:                        e1 = e1->e2;    // just the function
                   18117:                else
                   18118:                        e1 = ee->e2;    // just the index
                   18119:                return this;
                   18120:        }
                   18121: 
                   18122:        if (etp->base==PTR && Pptr(etp)->memof && Pptr(etp)->typ->base==FCT) {
                   18123:                Pclass cl = Pptr(etp)->memof;
                   18124: 
                   18125:                if (Pptr(tt)->memof==0 && b == 0 ) {
                   18126:                        Pexpr y = new mdot("f",e1);
                   18127:                        y->i1 = 9;
                   18128:                        y = new cast(tt,y);
                   18129:                        if (cl->virt_count && b==0) {
                   18130:                                // ERROR: no check for side effects
                   18131:                                Pexpr z = new mdot("i",e1);
                   18132:                                Pexpr x = new mdot("i",e1);
                   18133:                                x->i1 = 9;
                   18134:                                x = new cast(tt,x);
                   18135:                                z->i1 = 9;
                   18136:                                Pexpr q = new expr (QUEST,x,y);
                   18137:                                q->cond = new expr(LE,zero,z);
                   18138:                                q->tp = tt;
                   18139:                                delete this;
                   18140:                                return q;
                   18141:                        }
                   18142:                        delete this;
                   18143:                        return y;
                   18144:                }
                   18145:        }
                   18146: 
                   18147:        return this;
                   18148: }
                   18149: 
                   18150: Pexpr expr::dovalue(Ptable tbl)
                   18151: {
                   18152:        Ptype tt = tp2;
                   18153:        Pclass cl;
                   18154:        Pname cn;
                   18155: 
                   18156: //error('d',"value %d %t e1 %d e2 %d",tt,tt,e1,e2);
                   18157:        
                   18158:        tt->dcl(tbl);
                   18159: 
                   18160:        while(tt->base == TYPE)
                   18161:                tt = Pbase(tt)->b_name->tp;
                   18162: 
                   18163:        switch (tt->base) {
                   18164:        case EOBJ:
                   18165:        default:
                   18166:                if (e1 == 0) {
                   18167:                        error("value missing in conversion to%t",tt);
                   18168:                        return dummy;
                   18169:                }
                   18170:                base = CAST;
                   18171:                e1 = e1->e1;    // strip ELIST
                   18172:                return typ(tbl);
                   18173: 
                   18174:        case CLASS:
                   18175:                cl = Pclass(tt);
                   18176:                tp2 = Pptr(cl->this_type)->typ;
                   18177:                break;
                   18178: 
                   18179:        case COBJ:
                   18180:                cn = Pbase(tt)->b_name;
                   18181:                cl = Pclass(cn->tp);
                   18182:        }
                   18183: 
                   18184: //error('d',"e1 %k e1->e2 %k",e1->base,e1?e1->e2->base:0);
                   18185:        if (e1 && e1->e2==0) {          // single argument
                   18186:                if (e1->e1->base==ELIST) e1->e1 = e1->e1->e1;   // spurious elist
                   18187:                e1->e1 = e1->e1->typ(tbl);
                   18188:                if (tt->base==COBJ) {
                   18189:                        Pexpr x = try_to_coerce(tt,e1->e1,"type conversion",tbl);
                   18190:                        if (x) return x;
                   18191:                }
                   18192: 
                   18193:                Pname acn = e1->e1->tp->is_cl_obj();
                   18194: //error('d',"acn %n %d",acn,cl->has_itor());
                   18195:                if (acn && cl->has_itor()==0) {
                   18196:                        Pclass acl = Pclass(acn->tp);
                   18197:                        int hb = acl->has_base(cl);
                   18198: 
                   18199:                        if (acl==cl || hb) {
                   18200:                                vcllist->clear();
                   18201:                                vcllist=0;
                   18202:                                if (1<is_unique_base(acl,cl->string,0)) error("ambiguous assignment to base %t",cl);
                   18203:                                Pexpr ee = e1->e1;
                   18204:                                if (ee->base == ELIST) ee = ee->e1;     // ???
                   18205:                                if (hb) {       // ee => *(tp2*)&ee
                   18206:                                                // remember = may be overloaded
                   18207: //error('d',"hb %k %t %d",ee->base,ee->tp,ee->lval(0));
                   18208:                                        ignore_const++;
                   18209:                                        if (ee->lval(0)==0) {
                   18210:                                                Pname tmp = make_tmp('T',ee->tp,tbl);
                   18211:                                                ee = init_tmp(tmp,ee,tbl);
                   18212:                                                ee = new expr(G_CM,ee,tmp->address());
                   18213:                                        }
                   18214:                                        else
                   18215:                                                ee = ee->address();
                   18216:                                        ignore_const--;
                   18217:                                        ee = new texpr(CAST,new ptr(PTR,tp2),ee); //new cast(new ptr(PTR,tp2),ee);
                   18218:                                        ee = ee->contents();
                   18219:                                        ee->typ(tbl);
                   18220:                                }
                   18221: 
                   18222:                                if (e2) {       // x(x_obj) => e2=x_obj
                   18223:                                        base = ASSIGN;
                   18224:                                        e1 = e2;
                   18225:                                        e2 = ee;
                   18226:                                        tp = tp2;
                   18227:                                        return this;
                   18228:                                }
                   18229:                                return ee;      // strip ELIST: x(x_obj) => x_obj
                   18230:                        }
                   18231:                }
                   18232:        }
                   18233: 
                   18234: 
                   18235:        /* x(a) => obj.ctor(a); where e1==obj */
                   18236:        Pname ctor = cl->has_ctor();
                   18237:        if (ctor == 0) {
                   18238:                error("cannot make a%t",cl);
                   18239:                return dummy;
                   18240:        }
                   18241: 
                   18242: // error('d',"e2 %k",e2?e2->base:0);
                   18243: // error('d',"refd: %d const_ptr: %d", refd, const_ptr);
                   18244:        if (e2 == 0) {          // x(a) => x temp; (temp.x(a),temp)
                   18245: /* incomplete condition
                   18246:                if ( refd && const_ptr == 0) {
                   18247:                        if ( tbl == gtbl ) {
                   18248:                                error("Ir forG non-constCR not an lvalue");
                   18249:                        }
                   18250:                        else    
                   18251:                        if (strict_opt) 
                   18252:                                error("Ir for non-constCR not an lvalue");
                   18253:                        else
                   18254:                        if (warning_opt) 
                   18255:                                error('w', "Ir for non-constR not an lvalue (anachronism)");
                   18256:                        }
                   18257: */
                   18258:        
                   18259:                no_sti = 1;
                   18260:                Pname n = make_tmp('V',tp2,tbl);
                   18261:                no_sti = 0;
                   18262:                n->assign();
                   18263:                if (tbl == gtbl) n->dcl_print(0);       // a hack
                   18264:                Pexpr c = call_ctor(tbl,n,ctor,e1,DOT);
                   18265:                c = new expr(G_CM,c,n);
                   18266:                c->tp = n->tp;
                   18267: //error('d',"tp1 %t",c->tp);
                   18268:                return c;
                   18269:        }
                   18270:        else {
                   18271:                Pexpr c = call_ctor(tbl,e2,ctor,e1,DOT);
                   18272:                c = new expr(DEREF,c,0); // deref value returned by constructor
                   18273:                c->tp = c->e1->tp;
                   18274: //error('d',"tp2 %t",c->tp);
                   18275:                return c;
                   18276:        }
                   18277: }
                   18278: 
                   18279: 0707071010112044311004440001630000160000010201300466055402500000700000074341find.c/*ident     "@(#)ctrans:src/find.c  1.5" */
                   18280: /******************************************************************
                   18281: 
                   18282:        C++ source for cfront, the C++ compiler front-end
                   18283:        written in the computer science research center of Bell Labs
                   18284: 
                   18285:        Copyright (c) 1986 AT&T, Inc. All Rights Reserved
                   18286:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   18287: 
                   18288: find.c:
                   18289: 
                   18290:        name lookup and visibility checks
                   18291: 
                   18292: *******************************************************************/
                   18293: 
                   18294: #include "cfront.h"
                   18295: 
                   18296: Pname undef(Pname n, Ptable tbl, TOK f)
                   18297: {
                   18298:        switch (f) {
                   18299:        case CCON:
                   18300:                error("illegalF call: explicit call ofK %s()",n->string);
                   18301:                break;
                   18302:        case 0:         error("%nU",n);                 break;
                   18303:        case CALL:      error("UF%n called",n);         break;
                   18304:        case REF:
                   18305:        case DOT:       error("M%nU",n);                break;
                   18306:        case ADDROF:    error("address ofU%n",n);       break;
                   18307:        }
                   18308: 
                   18309:        if (tbl == gtbl) {
                   18310:                Pname nn = tbl->insert(n,0);
                   18311:                if (f == CALL) {
                   18312:                        nn->tp = new fct(defa_type,0,0);
                   18313:                        nn->n_sto = nn->n_scope = EXTERN;
                   18314:                }
                   18315:                else
                   18316:                        nn->tp = any_type;
                   18317:                delete n;
                   18318:                return nn;
                   18319:        }
                   18320:        
                   18321:        n->n_table = tbl;
                   18322:        n->tp = any_type;
                   18323:        return n;
                   18324: }
                   18325: 
                   18326: 
                   18327: 
                   18328: static int mptr;       // &C::m
                   18329: static Pname me;       // name of fct requesting access to name using find_name()
                   18330: static Pfct mef;       // fct requesting access to name using find_name()
                   18331: Pclass tcl;            // class of original ``this''
                   18332: Pclass mec;            // class requesting access to name using find_name()
                   18333: int mex;
                   18334: 
                   18335: Ptable lcl_tbl = 0;    // handle local function reference of local const for dimen size
                   18336: 
                   18337: 
                   18338: Pexpr find_name(Pname n, Pclass cl, Ptable tbl, int f, Pname m)
                   18339: /*
                   18340:        in function ``m'' find the true name for "n",
                   18341:        implicitly define if undefined
                   18342: 
                   18343:        f==CALL:        n()             cl == cc->cot
                   18344:        f==REF:         p->n            cl == class of *p
                   18345:        f==DOT:         obj.n           cl == class of obj
                   18346:        f==ADDROF:      &n              cl == cc->cot
                   18347:        f==0            n               (none of the above)
                   18348: 
                   18349:        "tbl" defines local scope (block or global)
                   18350: 
                   18351: */
                   18352: {
                   18353:        if ( n == 0 ) error('i',"find_name(n==0,cl==%t,tbl==%d,f==%k,m==%n)",cl,tbl,f,m);
                   18354:        Pname q = n->n_qualifier;
                   18355:        char* s = n->string;
                   18356:        Pexpr ee;
                   18357:        DB( if(Ddebug>=3) {
                   18358:                error('d',"find_name %s::%s cl %t",q?q->string:"",s,cl);
                   18359:                error('d',"     f %d m %n",f,m);
                   18360:                if(q&&q->tp&&q->tp->base==COBJ)
                   18361:                        fprintf(stderr," -- cb==%d\n",Pclass(q->tp)->c_body);
                   18362:        });
                   18363: 
                   18364:        tcl = cl;
                   18365: 
                   18366:        //if (n) {
                   18367:                mex = 1;
                   18368:                if (me = m) {
                   18369:                        mef = Pfct(me->tp);
                   18370:                         if (mef->base!=FCT) 
                   18371:                                 error('i',"mef %d %k",mef,mef->base);
                   18372:                        mec = mef->memof;
                   18373:                }
                   18374:                else {
                   18375:                        mef = 0;
                   18376:                        mec = cl;
                   18377:                }
                   18378:        //}
                   18379:        //else
                   18380:        //      mex = 0;
                   18381: 
                   18382:        if (n->base == MDOT) error('i',"find (mdot %n)",n);
                   18383: 
                   18384:        if (n->n_table) { me = 0; return n; }
                   18385: 
                   18386: //error('d',"q %n %t f %k",q,q?q->tp:0,f);
                   18387:        if (q) {                        // qualified name:      q::s
                   18388: 
                   18389:                if (q == sta_name) {    // explicitly global:   ::s
                   18390:                        Pname nn = gtbl->look(s,0);
                   18391:                        if (nn == 0) { me = 0; return undef(n,gtbl,f); }
                   18392:                        nn->use();
                   18393:                        delete n;
                   18394:                        me = 0;
                   18395:                        return nn;
                   18396:                }
                   18397: 
                   18398:                {
                   18399:                  Pname aq = q; // actual q
                   18400:                  while ( aq->tp->base == TYPE ) aq = Pbase(aq->tp)->b_name;
                   18401:                  if (aq->tp->base != COBJ) {
                   18402:                    error("Qr%nnot aCN",q);
                   18403:                    me = 0;
                   18404:                    return undef(n,gtbl,f);
                   18405:                  }
                   18406:                  q = aq;
                   18407:                }
                   18408:                Pclass qcl = Pclass(Pbase(q->tp)->b_name->tp);
                   18409: 
                   18410:                Pclass bcl = cl;
                   18411: 
                   18412:                if (cl==0 || f==ADDROF)
                   18413:                        bcl = cl = qcl; // Pclass(Pbase(q->tp)->b_name->tp);
                   18414:                else {
                   18415:                //      if (strcmp(q->string,cl->string)) {     // really a base?
                   18416:                //              bcl = cl->is_base(q->string);
                   18417:                        if (strcmp(qcl->string,cl->string)) {   // really a base?
                   18418:                                bcl = cl->is_base(qcl->string);
                   18419:                                if (bcl == 0) {
                   18420:                                        if (f==REF || f==DOT) {
                   18421:                                                error("%s is not aBC of %t",q->string,cl);
                   18422:                                                me = 0;
                   18423:                                                return undef(n,cl->memtbl,7);
                   18424:                                        }
                   18425:                                        goto sss;
                   18426:                                }
                   18427:                                // else try in base or for static
                   18428:                        }
                   18429:                }
                   18430: 
                   18431:                if (f == ADDROF) mptr = 1;              // &C::m
                   18432:                ee = cl->find_name(s,bcl==cl?0:bcl);    // really a member?
                   18433:                mptr = 0;
                   18434: 
                   18435:                if (ee == 0) {
                   18436:                sss:
                   18437: //error('d',"sss %k",f);
                   18438:                        if (f!=REF && f!=DOT) {
                   18439:                                // try for static member of other class:
                   18440:                                Pclass qcl = Pclass(Pbase(q->tp)->b_name->tp);
                   18441:                                mptr = 1;
                   18442:                                if ( cl && cl->csu == ANON ) {
                   18443:                                        mec = (cc-1)->cot;
                   18444:                                        ee = qcl->find_name(s,qcl);
                   18445:                                } else
                   18446:                                        ee = qcl->find_name(s,qcl);
                   18447:                                mptr = 0;
                   18448:                                if (ee && ee->base==NAME) {
                   18449:                                //      switch (ee->tp->base) {
                   18450:                                //      case FCT:
                   18451:                                //      case OVERLOAD:
                   18452:                                //              break;
                   18453:                                //      default:
                   18454:                                                delete n;
                   18455:                                                me = 0;
                   18456:                                                return ee;
                   18457:                                //      }
                   18458:                                }
                   18459:                        }
                   18460:                        error("QdN%n::%n not found in %t",q,n,cl);
                   18461:                        me = 0;
                   18462:                        return undef(n,bcl?bcl->memtbl:cl->memtbl,7);
                   18463:                }
                   18464: 
                   18465:                if (ee->base==REF && ee->e1==0) {       // &C::f, no ``this''
                   18466: //error('d',"ee %k %d f %k",ee->base,ee->e1,f);
                   18467:                        switch (f) {
                   18468:                        case 0:
                   18469:                        case CALL:      //SSS
                   18470:                                {       Pexpr mm = ee->mem;
                   18471:                                        while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
                   18472:                                        if (mm->base==NAME)
                   18473:                                                switch (mm->tp->base) {
                   18474:                                                case FCT:
                   18475:                                                case OVERLOAD:
                   18476:                                                        goto addrof;
                   18477:                                                default:
                   18478:                                                        if (Pname(mm)->n_stclass == STATIC) goto addrof;
                   18479:                                                }
                   18480:                                }
                   18481:                                error("O orOP missing forM%n",n);
                   18482:                                        
                   18483:                        case ADDROF:
                   18484:                        addrof:
                   18485:                                Pexpr x = ee;
                   18486:                                ee = ee->mem;
                   18487:                                delete x;
                   18488:                        case REF:
                   18489:                        case DOT:
                   18490:                                break;
                   18491:                        default:
                   18492:                                error("QdN%n::%n used in nonC context",q,n);
                   18493:                        }
                   18494:                }
                   18495: 
                   18496:                delete n;
                   18497:                me = 0;
                   18498:                return ee;
                   18499:        }
                   18500: 
                   18501:        if (f!=DOT && f!=REF) { // not .s or ->s: look for local, global, and member
                   18502: 
                   18503:                Pname nn = tbl->look(s,0);
                   18504:                if (nn) {       // local, global, or member
                   18505:                        if (nn->n_table->t_name) {      // global or member
                   18506:                                if (cl) {               // might be member
                   18507:                                        if ((ee = cl->find_name(s,0))==0 &&
                   18508:                                                cl->in_class) 
                   18509:                                        { // nested class
                   18510:                                                Pclass nstd_cl = cl->in_class;
                   18511:                                                for (; nstd_cl; nstd_cl=nstd_cl->in_class) 
                   18512:                                                {
                   18513: // error( 'd', "find_name( %s ): nested class %t",s,nstd_cl ); 
                   18514:                                                        if (ee=nstd_cl->find_name(s,0)) 
                   18515:                                                        {
                   18516:                                                                if ( cl->nested_sig == 0 ) {
                   18517:                                                                        error('w',"%s, accessed within nestedC%t, is visible bothGly and within enclosingC%t -- using %n (anachronism)", s, cl, nstd_cl, nn );
                   18518:                                                                        ee = 0;
                   18519:                                                                }
                   18520:                                                                break;
                   18521:                                                        }
                   18522:                                                }       
                   18523:                                        } // nested class
                   18524:                                
                   18525:                                        if ( ee ) 
                   18526:                                        {  // class member name
                   18527:                                                if (ee->base==REF && ee->e1==0 )
                   18528:                                                {
                   18529:                                                        Pexpr mm = ee->mem;
                   18530:                                                        while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
                   18531:                                                        if (mm->base==NAME)
                   18532:                                                                switch (mm->tp->base) {
                   18533:                                                                default:
                   18534:                                                                        if (Pname(mm)->n_stclass != STATIC)
                   18535:                                                                                break;
                   18536:                                                                case FCT:
                   18537:                                                                case OVERLOAD:
                   18538:                                                                        delete n;
                   18539:                                                                        me = 0;
                   18540:                                                                        return mm;
                   18541:                                                                }
                   18542:                                                        error("O orOP missing for%n",Pref(ee)->mem);
                   18543:                                                }
                   18544:                                                delete n;
                   18545:                                                me = 0;
                   18546:                                                return ee;
                   18547:                                          }  // if ee
                   18548:                                }  // if cl
                   18549:                        } // else local, global, or member
                   18550: 
                   18551:                        nn->use();
                   18552:                        delete n;
                   18553:                        me = 0;
                   18554:                        return nn;
                   18555:                }
                   18556: 
                   18557:                if (cl) {
                   18558:                        if ( cl->csu == ANON ) {
                   18559:                                mec = (cc-1)->cot;
                   18560:                                ee = (cc-1)->cot->find_name(s,0);
                   18561:                        } else
                   18562:                                ee = cl->find_name(s,0);
                   18563:                        if (ee) {
                   18564:                        if (ee->base==REF && ee->e1==0) {
                   18565:                                Pexpr mm = ee->mem;
                   18566:                                while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
                   18567:                                if (mm->base==NAME)
                   18568:                                        switch (mm->tp->base) {
                   18569:                                        default:
                   18570:                                                if (Pname(mm)->n_stclass != STATIC)
                   18571:                                                        break;
                   18572:                                        case FCT:
                   18573:                                        case OVERLOAD:
                   18574:                                                delete n;
                   18575:                                                me = 0;
                   18576:                                                return mm;
                   18577:                                        
                   18578:                                        }
                   18579:                                error("O orOP missing for%n",Pref(ee)->mem);
                   18580:                        }
                   18581:                                delete n;
                   18582:                                me = 0;
                   18583:                                return ee;
                   18584:                        }
                   18585:                }
                   18586: 
                   18587:                if ( lcl_tbl && (nn=lcl_tbl->look(s,0)) ) {
                   18588:                        nn->use();
                   18589:                        delete n;
                   18590:                        me = 0;
                   18591:                        return nn;
                   18592:                }
                   18593: 
                   18594:                if (nn = gtbl->look(s,0)) {     // global
                   18595:                        nn->use();
                   18596:                        delete n;
                   18597:                        me = 0;
                   18598:                        return nn;
                   18599:                }
                   18600: 
                   18601:                me = 0;
                   18602:                return undef(n,gtbl,f);
                   18603:        }
                   18604: 
                   18605:        if (ee = cl->find_name(s,cl)) { // .s or ->s
                   18606:                delete n;
                   18607:                me = 0;
                   18608:                return ee;
                   18609:        }
                   18610: 
                   18611:        if(!strcmp(s,cl->string)) {
                   18612:                me = 0;
                   18613:                return undef(n,gtbl,CCON);
                   18614:        }
                   18615: 
                   18616:        me = 0;
                   18617:        return undef(n,gtbl,f);
                   18618: }
                   18619: 
                   18620: int classdef::check_dup(Pclass cl, TOK bb)
                   18621: /*
                   18622:         see if cl is a base of this; return 0 if no clash
                   18623: */
                   18624: {
                   18625:        for (Pbcl b = baselist; b; b=b->next) {
                   18626:                if (cl == b->bclass) {
                   18627:                        if (bb!=VIRTUAL) {
                   18628:                                if (b->base==VIRTUAL)
                   18629:                                        error('w',"%t inaccessible because of virtual%t in%t",cl,cl,this);
                   18630:                                else
                   18631:                                        error('w',"%t inaccessible because of%t in%t",cl,cl,this);
                   18632:                                return 1;
                   18633:                        }
                   18634:                        else if (b->base!=VIRTUAL) {
                   18635:                                error('w',"virtual %t inaccessible because of%t in%t",cl,cl,this);
                   18636:                                return 1;
                   18637:                        }
                   18638:                }
                   18639:                if (b->bclass->check_dup(cl,bb)) return 1;
                   18640:        }
                   18641:        return 0;
                   18642: }
                   18643: 
                   18644: 
                   18645: int Nvis;
                   18646: TOK Nvirt;
                   18647: TOK ppbase;
                   18648: 
                   18649: Pclass classdef::is_base(char* s)
                   18650: /*
                   18651:        is "s" a public base class of this?
                   18652: */
                   18653: {
                   18654: //error('d',"%s->is_base(%s) %k",string,s,ppbase);
                   18655:        TOK pp = ppbase;
                   18656:        for (Pbcl b = baselist; b; b=b->next) {
                   18657: /*
                   18658:                if (b->ppp!=PUBLIC
                   18659:                && cc->cot!=this
                   18660:                && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
                   18661:                        ppbase = b->ppp<pp?pp:b->ppp;   // PUBLIC<PROTECTED<PRIVATE
                   18662: */
                   18663:                if (strcmp(s,b->bclass->string) == 0) {
                   18664:                if (b->ppp!=PUBLIC
                   18665:                && cc->cot!=this
                   18666:                && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
                   18667:                        ppbase = b->ppp<pp?pp:b->ppp;   // PUBLIC<PROTECTED<PRIVATE
                   18668:                        Nvirt = b->base;
                   18669:                        return b->bclass;
                   18670:                }
                   18671:                else {
                   18672:                        Pclass bc = b->bclass->is_base(s);
                   18673:                        if (bc) {
                   18674:                if (b->ppp!=PUBLIC
                   18675:                && cc->cot!=this
                   18676:                && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
                   18677:                        ppbase = b->ppp<pp?pp:b->ppp;   // PUBLIC<PROTECTED<PRIVATE
                   18678:                                return bc;
                   18679:                        }
                   18680:                }
                   18681:        }
                   18682:        ppbase = pp;
                   18683:        return 0;
                   18684: }
                   18685: 
                   18686: bit classdef::has_base(Pclass cl)
                   18687: /*
                   18688:        is "cl" a base of this?
                   18689: */
                   18690: {
                   18691: // error('d', "%t->has_base( %t ) cc->cot: %t", this, cl, cc->cot?cc->cot:0 );
                   18692: 
                   18693:        if (this == 0) return 0;
                   18694:        for (Pbcl b = baselist; b; b=b->next) {
                   18695: // error('d', "b: %t ppp: %k", b->bclass, b->ppp );
                   18696:                if (b->bclass==cl) {
                   18697:                        if (b->ppp!=PUBLIC
                   18698:                        && cc->cot!=this
                   18699:                        && (cc->nof==0 ||
                   18700:                                this->has_friend(Pfct(cc->nof->tp))==0) 
                   18701:                        && this->has_friend(cc->cot)==0)
                   18702:                                Nvis = 1;       // no standard coercion
                   18703:                        Nvirt = b->base;
                   18704:                        return 1;
                   18705:                }
                   18706:                if (b->bclass->has_base(cl)) return 1;
                   18707:        }
                   18708:        return 0;
                   18709: }
                   18710: 
                   18711: int Noffset;
                   18712: Pexpr Nptr;
                   18713: char *Nalloc_base;
                   18714: clist* vcllist;
                   18715: 
                   18716: int clist::onlist(Pclass c)
                   18717: {
                   18718:        for (clist* p = this; p; p = p->next)
                   18719:                if (p->cl == c) return 1;
                   18720:        return 0;
                   18721: }
                   18722: 
                   18723: void clist::clear()
                   18724: {
                   18725:        if (this == 0) return;
                   18726:        clist* p = next;
                   18727:        while (p) {
                   18728:                clist* q = p->next;
                   18729:                delete p;
                   18730:                p = q;
                   18731:        };
                   18732:        delete this;
                   18733: }
                   18734: 
                   18735: Pbcl Nvbc_alloc;
                   18736: int is_unique_base(Pclass cl, char* s, int offset, int in_base )
                   18737: /*
                   18738:        is "s" a unique base class of this?
                   18739: */
                   18740: {
                   18741:        int i = 0;
                   18742:        static Pclass priSeen = 0;
                   18743: // error('d',"is_unique_base(cl: %t, s: %s,%d,%d)",cl,s,offset,in_base);
                   18744:        for (Pbcl b = cl->baselist; b; b=b->next) {
                   18745:                int no = 0;
                   18746:                if (b->base!=VIRTUAL)
                   18747:                        no = offset + b->obj_offset;
                   18748:                else if (in_base)
                   18749:                        continue;
                   18750:                if (strcmp(s,b->bclass->string) == 0) {
                   18751:                        Noffset = no;
                   18752:                        i++;
                   18753:                        if ((b->ppp!=PUBLIC || priSeen )
                   18754:                                && (cc->cot!=cl || cc->cot != priSeen )
                   18755:                                && (cc->nof==0 || cl->has_friend(Pfct(cc->nof->tp))==0)
                   18756:                                        || (priSeen && priSeen->has_friend(Pfct(cc->nof->tp))==0))
                   18757:                                                Nvis = 1;       // no standard coercion
                   18758: 
                   18759:                        if (b->base==VIRTUAL) {
                   18760:                                Nptr = new mdot(s,0);
                   18761:                                if (b->allocated == 0) {
                   18762:                                        Nvbc_alloc = 0;
                   18763:                                        Nalloc_base = cl->has_allocated_base(s);
                   18764:                                }
                   18765:                        }
                   18766:                }
                   18767:                else {
                   18768:                        if (b->base==VIRTUAL) {
                   18769:                                if (vcllist->onlist(b->bclass) )continue;
                   18770:                                vcllist = new clist(b->bclass,vcllist);
                   18771:                        }
                   18772: 
                   18773:                        Pclass clscope = 0;
                   18774:                        if ( cc && cc->c_this ) {
                   18775:                                Ptype t = Pptr(cc->c_this->tp)->typ;
                   18776:                                clscope = Pclass(Pbase(t)->b_name->tp);
                   18777:                        }
                   18778: // error('d', "cl: %t %d clscope: %t %d", cl, cl, clscope, clscope);
                   18779:                        if (b->ppp != PUBLIC && 
                   18780:                                cl != clscope && priSeen == 0 ) priSeen = cl;
                   18781: 
                   18782:                        int ii = is_unique_base(b->bclass,s,no,1);
                   18783:                        if (in_base == 0) priSeen = 0;
                   18784: // error('d',"base %t i %d ii %d",b->bclass,i,ii);
                   18785: // error('d',"base %t %k allocated: %d", b->bclass, b->base, b->allocated);
                   18786:                        i += ii;
                   18787:                        if (ii==1 && b->base==VIRTUAL) {
                   18788:                                Nptr = new mdot(b->bclass->string,0);
                   18789:                                if (b->allocated == 0) {
                   18790:                                        Nvbc_alloc = 0;
                   18791:                                        Nalloc_base = cl->has_allocated_base(b->bclass->string);
                   18792:                                }
                   18793:                        }
                   18794:                }
                   18795:        }
                   18796: 
                   18797:        return i;
                   18798: }
                   18799: 
                   18800: /*
                   18801: int classdef::has_allocated_base(Pclass bcl)
                   18802: 
                   18803:        search the list of !first base classes for this virtual base
                   18804:        space will have been allocated in !first bases for virtual bases
                   18805:        declared in !first classes
                   18806: 
                   18807:        in addition bcl may bave been specified explicitly as a base
                   18808: 
                   18809: {
                   18810:        int off;
                   18811:        for (Pbcl l = baselist; l; l=l->next) {
                   18812:                if (l->base == VIRTUAL) continue; // another non-allocated virtual base
                   18813:                if (l==baselist) continue;      // first base
                   18814: 
                   18815:                Pclass bc = l->bclass;
                   18816:                off = l->obj_offset;
                   18817: 
                   18818:                for (Pbcl ll = bc->baselist; ll; ll=ll->next) {
                   18819:                        // cannot share non-virtual base
                   18820:                        if (ll->base != VIRTUAL) continue;
                   18821:                        if (ll->bclass==bcl) return off + ll->obj_offset;
                   18822:                }
                   18823:        }
                   18824:        return 0;
                   18825: }
                   18826: */
                   18827: 
                   18828: int classdef::has_allocated_base(Pclass bcl)
                   18829: /*
                   18830:        search the list of base classes for this virtual base
                   18831:        space will be allocated in first virtual version found.
                   18832:        return offset.
                   18833: 
                   18834:        A virtual base cannot have offset 0 (its pointer at least is ahead)
                   18835: */
                   18836: {
                   18837: //error('d',"%t->has_allocated_base(%t) ",this,bcl);
                   18838:        for (Pbcl l = baselist; l; l=l->next) {
                   18839:                if (l->base==VIRTUAL
                   18840:                && l->bclass==bcl
                   18841:                && l->obj_offset)
                   18842:                        return l->obj_offset;
                   18843: 
                   18844:                if (l->base==VIRTUAL || l!=baselist) {
                   18845:                        // allocated as an object,
                   18846:                        // not unravelled as a set of members
                   18847:                        int i = l->bclass->has_allocated_base(bcl);
                   18848:                        if (i) return l->obj_offset + i;
                   18849:                }
                   18850:        }
                   18851:        return 0;
                   18852: }
                   18853: 
                   18854: char *classdef::has_allocated_base(char *str) 
                   18855: /*
                   18856:  *     str is an unallocated virtual base class of this
                   18857:  *     return the name of the second or subsequent base class 
                   18858:  *             containing the member ``struct str *P<str>''
                   18859:  */
                   18860: {
                   18861: // error('d',"%t::has_allocated_base(%s) baselist: %t",this,str,baselist->bclass);
                   18862:        for (Pbcl l = baselist; l; l=l->next) {
                   18863:                if (l->base == VIRTUAL) {
                   18864:                        if ( l->allocated ) Nvbc_alloc = l; 
                   18865:                        continue; 
                   18866:                }
                   18867: 
                   18868:                Pclass bc = l->bclass;
                   18869:                for (Pbcl ll = bc->baselist; ll; ll=ll->next) {
                   18870:                        if (ll->base != VIRTUAL) continue;
                   18871:                        if (ll->allocated && 
                   18872:                            strcmp( str, ll->bclass->string) == 0 )
                   18873:                                { 
                   18874:                                        if (bc == baselist->bclass) {
                   18875:                                                // NfirstBase=1; 
                   18876:                                                return 0;
                   18877:                                        }
                   18878:                                        return bc->string;
                   18879:                                }
                   18880:                }
                   18881:        }
                   18882:        return 0;
                   18883: }
                   18884: 
                   18885: /*
                   18886: int allocated_base(Pclass cl,Pclass bcl)
                   18887: {
                   18888: static second;
                   18889: int s2 = second;
                   18890:        for (Pbcl l = cl->baselist; l; l=l->next) {
                   18891:                if (l->base==VIRTUAL
                   18892:                && l->bclass==bcl
                   18893:                && l->obj_offset
                   18894:                && (second || l!=cl->baselist)) return (second=s2,1);
                   18895:                int i = allocated_base(l->bclass,bcl);
                   18896:                if (i) return (second=s2,1);
                   18897:                second = 1;
                   18898:        }
                   18899:        second = s2;
                   18900:        return 0;
                   18901: }
                   18902: */
                   18903: Pname vfct(Pclass cl, char* s)
                   18904: /*
                   18905:        Called for each name "s" in a vtbl for "cl"
                   18906:        Find the "s" to go in the vtbl.
                   18907:        The "s" that caused the vtbl entry to be created
                   18908:                is found if nothing else is
                   18909: */
                   18910: {
                   18911:        Pname n = cl->memtbl->look(s,0);
                   18912:        if (n) return n;
                   18913: 
                   18914:        for (Pbcl b = cl->baselist; b; b=b->next) {
                   18915:                Pname nn = vfct(b->bclass,s);
                   18916:                if (nn) {
                   18917: //error('d',"nn %nn",nn);
                   18918:                        if (n && n!=nn) {
                   18919:                                Pclass ncl = Pclass(n->n_table->t_name->tp);
                   18920:                                Pclass nncl = Pclass(nn->n_table->t_name->tp);
                   18921: //error('d',"ncl %t nncl %t",ncl,nncl);
                   18922:                                if (nncl->is_base(ncl->string))
                   18923:                                        n = nn;         // use nn
                   18924:                        }
                   18925:                        else
                   18926:                                n = nn;
                   18927:                }
                   18928:        }
                   18929: 
                   18930:        return n;
                   18931: }
                   18932: 
                   18933: Pexpr rptr(Ptype t, Pexpr p, int offset)
                   18934: /*
                   18935:        return rvalue of offset off pointer:
                   18936:        (t)((char*)p+offset)
                   18937: */
                   18938: {
                   18939:        if ( t == 0 ) error( 'i', "rptr(), t==0 (type passed for cast)" );
                   18940:        Pexpr pp = p;
                   18941: //error('d',"rptr %t %d",t,offset);
                   18942:        if (offset) {
                   18943:                Pexpr i = new ival(offset);
                   18944:        //      pp = new texpr(CAST,Pchar_type,pp);
                   18945:                pp = new cast(Pchar_type,pp);
                   18946:                pp = new expr(PLUS,pp,i);
                   18947:        }
                   18948:        pp = new cast(t,pp);
                   18949:        return pp;
                   18950: }
                   18951: /*
                   18952: Pexpr lptr(Ptype t, Pexpr p, int offset)
                   18953: 
                   18954:        return lvalue of offset off pointer:
                   18955:        *(t*)((char*)p+offset)
                   18956: 
                   18957: {
                   18958:        Pexpr pp = p;
                   18959:        if (offset) {
                   18960:                Pexpr i = new ival(offset);
                   18961:        //      pp = new texpr(CAST,Pchar_type,pp);
                   18962:                pp = new cast(Pchar_type,pp);
                   18963:                pp = new expr(PLUS,pp,i);
                   18964:        }
                   18965:        pp = new cast(t->addrof(),pp);
                   18966:        pp = new expr(DEREF,pp,0);
                   18967:        pp->tp = t;
                   18968:        return pp;
                   18969: }
                   18970: */
                   18971: int friend_check(Pclass start,Pclass stop, Pfct f)
                   18972: /*
                   18973:        is `f' a friend of a class between `start' and `stop'
                   18974:        in a class DAG?
                   18975: */
                   18976: {
                   18977: //error('d',"friend_check(%t,%t)",start,stop);
                   18978:        
                   18979:        if (start->has_friend(f)) return 1;
                   18980:        if (stop == start) return 0;
                   18981:        for (Pbcl b = start->baselist; b; b = b->next) {
                   18982:                if (b->bclass->has_friend(f)) return 1;
                   18983:                if (friend_check(b->bclass,stop,f)) return 1;
                   18984:        }
                   18985:        return 0;
                   18986: }
                   18987: 
                   18988: bit classdef::has_friend(Pfct f)
                   18989: /*
                   18990:        does this class have function "f" as its friend?
                   18991: */
                   18992: {
                   18993: // error('d',"%t->has_friend(%t) %d %d ",this,f,f,f->base);
                   18994: 
                   18995:        for (Plist l=friend_list; l; l=l->l) {
                   18996:                Pname fr = l->f;
                   18997:                Ptype frt = fr->tp;
                   18998: //error('d',"frt %t %d %d",frt,frt,frt->base);
                   18999:                switch (frt->base) {
                   19000:                case FCT:
                   19001:                        if (f == frt) return 1;
                   19002:                        break;
                   19003:                case OVERLOAD:
                   19004:                        l->f = fr = Pgen(frt)->fct_list->f;     // first fct
                   19005:                        if (fr->tp == f) return 1;
                   19006:                case CLASS:
                   19007:                        break;
                   19008:                default:
                   19009:                        error('i',"bad friend %k",fr->tp->base);
                   19010:                }
                   19011:        }
                   19012:        return 0;
                   19013: }
                   19014: 
                   19015: bit classdef::has_friend(Pclass cl)
                   19016: /*
                   19017:        does this class have class "cl" as its friend?
                   19018: */
                   19019: {
                   19020: // error('d',"%t->has_friend(%t) ",this,cl);
                   19021: 
                   19022:        for (Plist l=friend_list; l; l=l->l) {
                   19023:                Pname fr = l->f;
                   19024:                Ptype frt = fr->tp;
                   19025:                switch (frt->base) {
                   19026:                case CLASS:
                   19027: // error('d',"class friend: %t", frt);
                   19028:                        if ((frt == cl) || cl->same_class(Pclass(frt))) 
                   19029:                                return 1;
                   19030:                case FCT:
                   19031:                case OVERLOAD:
                   19032:                        break;
                   19033:                default:
                   19034:                        {error('i',"bad friend %k",frt->base);}
                   19035:                }
                   19036:        }
                   19037:        return 0;
                   19038: }
                   19039: 
                   19040: Pname find_virtual(Pclass cl, Pname s)
                   19041: /*
                   19042:        does ``cl'' have a virtual function ``s'' in some base class
                   19043: */
                   19044: {
                   19045:        for (Pbcl b = cl->baselist; b; b = b->next) {
                   19046:                Pclass bcl = b->bclass;
                   19047:                Pname n;
                   19048:                if (n = bcl->memtbl->look(s->string,0)) {
                   19049: // error('d', "find_virtual: n: %d base: %k", n, n->base );
                   19050:                        if ( n->base == PUBLIC ) // x::foo;
                   19051:                                continue;
                   19052:                        Pfct f = Pfct(n->tp);
                   19053:                        if (f->base == OVERLOAD) {
                   19054:                                for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) {
                   19055:                                        n = gl->f;
                   19056:                                        // if (f != s->tp) continue;
                   19057:                                        // Replaced by:
                   19058:                                        if (n->tp->check(s->tp,VIRTUAL)) continue;
                   19059:                                        if (Pfct(n->tp)->f_virtual) return n;
                   19060:                                }
                   19061:                        }
                   19062:                        // else if (f->f_virtual)
                   19063:                        else if (f->f_virtual && n->tp->check(s->tp,VIRTUAL)==0)
                   19064:                                return n;
                   19065:                }
                   19066:                else if (n = find_virtual(bcl,s))
                   19067:                        return n;
                   19068:        }
                   19069:        return 0;
                   19070: }
                   19071: 
                   19072: Pname dummy_fct;
                   19073: 
                   19074: static int 
                   19075: is_accessible(Pname n, Pclass this_class, bit noCdcl = 0)
                   19076: // 0 means n is not accessible to this_class
                   19077: {
                   19078: // error('d',"is_accessible(%n,%t)", n, this_class
                   19079: // error('d',"%n: %k mef %t",n,n->n_protect,mef);
                   19080: // error('d',"         this_class %d %t",this_class,this_class);
                   19081: // error('d',"         mec  %d %t",mec,mec);
                   19082: // error('d',"         tcl  %d %t",tcl,tcl);
                   19083: // error('d',"mec->has_base(this_class) %d",mec?mec->has_base(this_class):0);
                   19084: // error('d',"tcl->has_base(mec) %d",tcl?tcl->has_base(mec):0);
                   19085: // error('d',"tcl->has_base(this_class) %d",tcl?tcl->has_base(this_class):0);
                   19086: // error('d',"tcl->has_friend(mef) %d",tcl?tcl->has_friend(mef):0);
                   19087: 
                   19088:        if (this_class==mec || 
                   19089:                (mec && this_class->has_friend(mec)) || 
                   19090:                (mef && this_class->has_friend(mef)))
                   19091:                        return 1;
                   19092:        
                   19093:        if ( n->n_protect && tcl ) {
                   19094:                if ( mec ) 
                   19095:                {
                   19096:                        if ( tcl->has_friend(mec) ||
                   19097:                                ( mec->has_base(this_class) && 
                   19098:                                        (tcl==mec || tcl->has_base(mec))))
                   19099:                                                return 1;
                   19100:                }       
                   19101: 
                   19102:                if ( mef ) 
                   19103:                {
                   19104:                        if ( tcl->has_base(this_class) &&
                   19105:                                // && tcl->has_friend(mef))
                   19106:                                friend_check(tcl,this_class,mef))
                   19107:                                        return 1;
                   19108:                }
                   19109:        }
                   19110: 
                   19111:        // call from check_visibility
                   19112:        if ( noCdcl ) return 0; 
                   19113:        
                   19114:        if ( Cdcl && Cdcl->base == NAME && 
                   19115:                Cdcl->n_stclass == STATIC && 
                   19116:                Cdcl->n_initializer && 
                   19117:                Cdcl->n_qualifier ) 
                   19118:        {
                   19119:                Pbase bn = Pbase(Cdcl->n_qualifier->tp);
                   19120:                Pclass cl = Pclass(bn->b_name->tp);
                   19121: 
                   19122:                if ( cl == this_class ||
                   19123:                        (n->n_protect && cl->has_base(this_class)) || 
                   19124:                        cl->has_friend(this_class))
                   19125:                                return 1;
                   19126:        }
                   19127: 
                   19128:        return 0;
                   19129: }
                   19130: 
                   19131: Pexpr classdef::find_name(char* s, Pclass cl, int access_only)
                   19132: /*
                   19133:        look for "s" in "this" class and its base classes
                   19134:        if (cl)
                   19135:                accept only a member of "cl" or "cl"'s base classes
                   19136:                (that is cl::s was seen)
                   19137: 
                   19138:        complicated by hiding rules: private, protected, friend
                   19139:        
                   19140: */
                   19141: {
                   19142: // error('d',"%s->find_name(%s,%s) memtbl %d",string,s,cl?cl->string:"",memtbl);
                   19143:        Pname n = memtbl->look(s,0);
                   19144: 
                   19145:        if (n) {
                   19146:                if (n->tp) {
                   19147:                        switch (n->tp->base) {
                   19148:                        case OVERLOAD:
                   19149:                                break;
                   19150:                        case FCT:
                   19151:                                if (Pfct(n->tp)->f_virtual==0) {
                   19152:                                        if (n->n_dcl_printed==0) n->dcl_print(0);
                   19153:                                        break;
                   19154:                                }
                   19155:                        default:
                   19156:                                  if (c_body==1) dcl_print(0);
                   19157:                        }
                   19158:                }
                   19159: 
                   19160:                if (n->base == PUBLIC) {
                   19161:                        if (mex && n->n_scope==0) {
                   19162:                                if ( is_accessible(n,this) == 0 ) 
                   19163:                                {
                   19164:                                        if ( me == dummy_fct )
                   19165:                                                error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private");
                   19166:                                        else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
                   19167:                                        mex = 0;        // suppress further error messages
                   19168:                                }
                   19169:                        }
                   19170:                        mex = 0; // don't have find_in_base complain about n
                   19171:                        return find_in_base(s, cl);
                   19172:                }
                   19173: 
                   19174:                if (cl==0 || cl==this) {
                   19175:                        if (mptr==0
                   19176:                        && n->n_stclass!=STATIC
                   19177:                        && n->n_stclass!=ENUM) {
                   19178:                                Ptype t = n->tp;
                   19179: 
                   19180: // error('d',"cl %d this %d",cl,this);
                   19181: 
                   19182:                                if (mex && n->n_scope==0 && n->tp->base!=OVERLOAD) {
                   19183:                                        if ( is_accessible(n,this)==0 )
                   19184:                                        {
                   19185:                                                if ( me == dummy_fct )
                   19186:                                                        error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private");
                   19187:                                                else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
                   19188:                                                mex = 0;        // suppress further error messages
                   19189:                                        }
                   19190:                                }
                   19191: 
                   19192:                                Pname th = cc->c_this;
                   19193:                                Pexpr r = new ref(REF,th,n);
                   19194: 
                   19195:                                if ( access_only == 0 ) {
                   19196:                                        if (th) th->use();
                   19197:                                        n->use();
                   19198:                                }
                   19199:                                r->tp = t;
                   19200:                                return r;
                   19201:                        }
                   19202: 
                   19203:                        if (mex && n->n_scope==0 && n->tp->base!=OVERLOAD) {
                   19204:                                if ( is_accessible(n,this)==0 )
                   19205:                                {
                   19206:                                        if ( me == dummy_fct )
                   19207:                                                error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private");
                   19208:                                        else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
                   19209:                                        mex = 0;        // suppress further error messages
                   19210:                                }
                   19211:                        }
                   19212:                        n->use();
                   19213:                        return n;
                   19214:                }
                   19215:        }
                   19216: 
                   19217:        if ((cl==0 || cl==this) // not qualified to a base class
                   19218:        && csu!=UNION
                   19219:        && csu!=ANON
                   19220:        && strcmp(s,"__as")==0) { // assignment is special: you cannot inherit it
                   19221:                if (baselist==0
                   19222:                || (baselist && baselist->bclass->obj_size!=obj_size)) {
                   19223:                        Pname cn = ktbl->look(string,0);
                   19224:                        if (cn->tp->base == COBJ) cn = Pbase(cn->tp)->b_name;
                   19225:                        Pname x = gtbl->look("__as",0);
                   19226:                        if (x) {        // what if there is an (illegal) global assignment operation?
                   19227:                                        // hack hack don't declare global assignment operations!
                   19228:                                Pfct f = Pfct(x->tp);
                   19229:                                if (f->base == FCT) {
                   19230:                                        Pptr r = f->argtype->tp->is_ref();
                   19231:                                        if (r) {
                   19232:                                                Pname cnn = r->typ->is_cl_obj();
                   19233:                                                if (cnn && cn==cnn) return 0;
                   19234:                                        }
                   19235:                                } else {
                   19236:                                        for (Plist gl = Pgen(f)->fct_list; gl; gl=gl->l) {
                   19237:                                                Pptr r = Pfct(gl->f)->argtype->tp->is_ref();
                   19238:                                                if (r) {
                   19239:                                                        Pname cnn = r->typ->is_cl_obj();
                   19240:                                                        if (cnn &&cn==cnn) return 0;
                   19241:                                                }
                   19242:                                        }
                   19243:                                }
                   19244:                        }
                   19245:                        return make_assignment(cn) ? find_name(s,cl) : 0;
                   19246:                }
                   19247:        }
                   19248: 
                   19249:        return find_in_base(s, cl);
                   19250: }
                   19251: 
                   19252: static Pclass rootClass;
                   19253: static Pbcl pubVClass;
                   19254: static struct PendingMessage { 
                   19255:     Pbcl bc;
                   19256:     Pname mf;
                   19257:     char *nm;
                   19258: } *pM;
                   19259: 
                   19260: Pexpr classdef::find_in_base(char* s, Pclass cl)
                   19261: {
                   19262:        Pbcl bc = 0;
                   19263:        Pexpr e = 0;
                   19264: 
                   19265: // error('d',"%s->find_in_base(%s %s)",string,s,cl?cl->string:"");
                   19266: 
                   19267:        if ( me == 0 ) mef = 0;
                   19268:        if (rootClass == 0) rootClass = this;
                   19269:        for (Pbcl b=baselist; b; b=b->next) {
                   19270:                Pclass ccl = cl==this?0:cl;
                   19271: // error('d',"try %t %s %k",b->bclass,b->bclass?b->bclass->string:"?", b->base);
                   19272:                Pexpr ee = b->bclass->find_name(s,ccl);
                   19273: 
                   19274:                if (ee) {
                   19275:                        if (c_body == 1) {      // look for first use (through this)
                   19276:                                if (b!=baselist || b->base==VIRTUAL)
                   19277:                                        dcl_print(0);
                   19278:                                else {
                   19279:                                        Pexpr ex = ee;
                   19280:                                        while ((ex->base==MDOT && ex->i1==1)
                   19281:                                        || (ex->base==REF && ex->e1==cc->c_this)) ex = ex->mem;
                   19282:                                        switch (ex->tp->base) {
                   19283:                                        case OVERLOAD:
                   19284:                                                break;
                   19285:                                        case FCT:
                   19286:                                                if (Pfct(ex->tp)->f_virtual==0) break;
                   19287:                                        default:
                   19288:                                                dcl_print(0);
                   19289:                                        }
                   19290:                                }
                   19291:                        }
                   19292: 
                   19293:                        if (e) {
                   19294: // error( 'd', "find_in_base: b( %s ): %k %k ",b->bclass->string,b->base,b->ppp);
                   19295:                                Pexpr ex = e;
                   19296:                                int evb = 0;    // number of vbase indirections
                   19297:                                int eb = 0;
                   19298: 
                   19299: // note that this does not catch enum members
                   19300:                                while (ex->base == MDOT
                   19301:                                || (ex->base==REF && ex->e1==cc->c_this)) {
                   19302:                                        if (ex->base==MDOT) evb += int(ex->i1);
                   19303:                                        ex = ex->mem;
                   19304:                                }
                   19305: 
                   19306:                                Pexpr eex = ee;
                   19307:                                int eevb = b->base==VIRTUAL;    // number of vbase indirections (incl. possibly this one)
                   19308:                                int eeb = b->base!=VIRTUAL;
                   19309: 
                   19310:                                while (eex->base == MDOT
                   19311:                                || (eex->base==REF && eex->e1==cc->c_this)) {
                   19312:                                        if (eex->base==MDOT) eevb += int(eex->i1);
                   19313:                                        eex = eex->mem;
                   19314:                                }
                   19315: 
                   19316: // error('d', "find_in_base: ex: %k eex: %k, eevb: %d evb: %d", ex->base, eex->base, eevb, evb );
                   19317: // relying on simple counts for sub-object identification isn't good enough
                   19318: 
                   19319:                                if (ex != eex)  {
                   19320: // error('d',"ex %k tp %k eex %k tp %k", ex->base, ex->tp->base, eex->base, eex->tp->base );
                   19321:                                //      if (!mqua) {
                   19322:                                                Pclass ocl, ncl;
                   19323:                                                if ( ex->tp->base == FCT ) 
                   19324:                                                        ocl = Pfct(ex->tp)->memof;
                   19325:                                                else 
                   19326:                                                if ( ex->tp->base == OVERLOAD )
                   19327:                                                        ocl = Pfct(Pgen(ex->tp)->fct_list->f->tp)->memof;
                   19328:                                                else ocl = Pclass(ex->n_table->t_name->tp);
                   19329: //                                             else ocl = 0;
                   19330: 
                   19331:                                                if ( eex->tp->base == FCT ) 
                   19332:                                                        ncl = Pfct(eex->tp)->memof;
                   19333:                                                else 
                   19334:                                                if ( eex->tp->base == OVERLOAD )
                   19335:                                                        ncl = Pfct(Pgen(eex->tp)->fct_list->f->tp)->memof;
                   19336:                                                 else ncl = Pclass(eex->n_table->t_name->tp);
                   19337: //                                             else ncl = 0;
                   19338: 
                   19339: //                                             Pclass ocl = Pfct(ex->tp)->memof;
                   19340: //                                             Pclass ncl = Pfct(eex->tp)->memof;
                   19341:                                                int eb = ocl?ocl->has_base(ncl):0;
                   19342:                                                int eeb = ncl?ncl->has_base(ocl):0;
                   19343: 
                   19344: //error('d',"eb %d eeb %d evb %d eevb %d",eb,eeb,evb,eevb);
                   19345:                                                if (eb==0 && eeb==0) {
                   19346:                                                        // different
                   19347:                                                        error("ambiguous%n and%n",ex,eex);
                   19348:                                                        break;
                   19349:                                                }
                   19350:                                                else if (eb) {  // ex dominates
                   19351:                                                        if (eevb<evb) error("ambiguous%n and%n (different sub-objects)",ex,eex);
                   19352:                                                }
                   19353:                                                else {  // eex dominates
                   19354:                                                        e = ee;
                   19355:                                                        bc = b;
                   19356:                                                        if (evb<eevb) error("ambiguous%n and%n (different sub-objects)",ex,eex);
                   19357:                                                }
                   19358:                                                if (evb==0 && eevb==0) {
                   19359:                                                        error("ambiguous%n and%n (different sub-objects)",ex,eex);
                   19360:                                                }
                   19361:                                //      }
                   19362:                                //      else {
                   19363:                                //              // different
                   19364:                                //              error("ambiguous%n and%n",ex,eex);
                   19365:                                //              break;
                   19366:                                //      }
                   19367:                                }
                   19368:                                else if (ex->base==NAME
                   19369:                                && (Pname(ex)->n_evaluated || Pname(ex)->n_sto==EXTERN)) {
                   19370: //error('d',"enum");
                   19371:                                }
                   19372:                                else if (evb==0 && eevb==0) {
                   19373: //error('d',"e %k",e->base);
                   19374:                                        // no virtual base => different
                   19375:                                        error("ambiguous%n and%n (no virtualB)",ex,eex);
                   19376:                                        break;
                   19377:                                }
                   19378:                                else if ((evb && eevb==0) || (eevb && evb==0)) {
                   19379:                                        // only one virtual base => different
                   19380:                                        error("ambiguous%n and%n (one not in virtualB)",ex,eex);
                   19381:                                        break;
                   19382:                                }
                   19383:                        }
                   19384:                        else {
                   19385:                                e = ee;
                   19386:                                bc = b;
                   19387:                        }
                   19388:                }
                   19389:        }
                   19390: 
                   19391:        if (rootClass == this ) {
                   19392:                if ( pM ) {
                   19393:                        // deferred until all base classes of ``this'' examined
                   19394:                        error("%n cannot access %s: %s is a privateBC",pM->mf,pM->nm,pM->bc->bclass->string);
                   19395:                        delete pM; pM=0;
                   19396:                }
                   19397:                rootClass = 0;
                   19398:                pubVClass = 0;
                   19399:        }
                   19400: 
                   19401:        if (e == 0) return 0;
                   19402: 
                   19403:        if (mex) {
                   19404:                if ( bc->ppp==PRIVATE ) {       // private base
                   19405:                        if (this==mec || 
                   19406:                            (mec && has_friend(mec)) || 
                   19407:                           (mef && has_friend(mef)))
                   19408:                                ;
                   19409:                        else 
                   19410:                        if ( bc->base == VIRTUAL &&
                   19411:                             rootClass != this ) { 
                   19412:                                // if one instance is public, it dominates
                   19413:                                if ( pubVClass == 0 ||
                   19414:                                      strcmp(pubVClass->bclass->string,bc->bclass->string)) {
                   19415:                                        pM = (PendingMessage *) new char[sizeof(*pM)];
                   19416:                                        pM->bc = bc; pM->mf = me; pM->nm = s;
                   19417:                                }
                   19418:                        }
                   19419:                        else {
                   19420:                                if ( me == dummy_fct )
                   19421:                                        error("G scope cannot access %s: %s is a privateBC",s,bc->bclass->string);
                   19422:                                else error("%n cannot access %s: %s is a privateBC",me,s,bc->bclass->string);
                   19423:                                mex = 0;
                   19424:                        }
                   19425:                }
                   19426:                else { // public base class
                   19427:                if ( bc->base == VIRTUAL ) {
                   19428:                        if ( pM && 
                   19429:                             strcmp(bc->bclass->string,pM->bc->bclass->string)==0 ) {
                   19430:                                delete pM;
                   19431:                                pM=0;
                   19432:                                pubVClass = bc; 
                   19433:                                } // previous private member becomes public
                   19434:                        else pubVClass = bc; // ignore subsequent private instances
                   19435:                        }
                   19436:                }
                   19437:        }
                   19438: 
                   19439:        if (e->base==NAME
                   19440:        && Pname(e)->n_stclass==STATIC) {       // static member
                   19441:                Pname(e)->use();
                   19442:                return e;
                   19443:        }
                   19444:        if (e->base != NAME)
                   19445:        if (bc->base == VIRTUAL) {      // this->mem => this->Pbclass->mem
                   19446:                e->mem = new mdot(bc->bclass->string,e->mem);
                   19447:                e->mem->i1 = 1;
                   19448:                e->mem->tp = e->mem->mem->tp;
                   19449:        }
                   19450:        else if (bc!=baselist) {        // not first base
                   19451:                if (e->e1 == cc->c_this) {      // this->mem => this->Obcl.mem
                   19452:                        e->mem = new mdot(bc->bclass->string,e->mem);
                   19453:                        e->mem->tp = e->mem->mem->tp;
                   19454:                }
                   19455:                else {  // this->p->mem => this->Obcl.p->mem
                   19456:                        Pexpr ee = e;
                   19457:                        while (ee->e1->base == REF) ee = ee->e1;
                   19458:                        ee->mem = new mdot(bc->bclass->string,ee->mem);
                   19459:                        ee->mem->tp = ee->mem->mem->tp; 
                   19460:                }
                   19461:        }
                   19462: 
                   19463:        return e;
                   19464: }
                   19465: 
                   19466: int has_virt(Pclass cl)
                   19467: {
                   19468:        if (cl->virt_count) return 1;
                   19469:        for (Pbcl b = cl->baselist; b; b = b->next)
                   19470:                if (b->bclass->virt_count || has_virt(b->bclass)) return 1;
                   19471:        return 0;
                   19472: }
                   19473: 
                   19474: Pname find_vptr(Pclass cl)
                   19475: /*
                   19476:        find virtual function table
                   19477:        in memtbl or memtbl of ``first bases''
                   19478: */
                   19479: {
                   19480: //error('d',"find_vptr %t",cl);
                   19481:        while (cl) {
                   19482:                Pname vp = cl->memtbl->look("__vptr",0);
                   19483:                if (vp) return vp;
                   19484:                Pbcl b = cl->baselist;
                   19485:                cl = 0;
                   19486:                for (; b; b = b->next)
                   19487:                        if (b->base == NAME) {
                   19488:                                cl = b->bclass;
                   19489:                                break;
                   19490:                        }
                   19491:        }
                   19492: //error('d',"return 0");
                   19493:        return 0;
                   19494: }
                   19495: 
                   19496: void make_dummy()
                   19497: /* a function with no special privileges */
                   19498: {
                   19499:         Pname x = new name(".." /*"__static_initializer"*/);
                   19500:         x->tp = new fct(Pvoid_type,0,1);
                   19501:         dummy_fct = x->dcl(gtbl,EXTERN);
                   19502: //     dummy_fct->string = "";
                   19503:         delete x;
                   19504: }
                   19505: 
                   19506: void check_visibility(Pname n, Pname q, Pclass cl, Ptable tbl, Pname fn)
                   19507: /*
                   19508:        "fn" calls "n" a member function of "cl"
                   19509:        fn can be zero (for functions called in arguments to static constructors) 
                   19510: */
                   19511: {
                   19512: // error('d',"check_visibility(%n, %t, %d, %n)",n,cl,tbl,fn);
                   19513:        if (fn==0) {
                   19514:                 if (dummy_fct == 0) make_dummy();
                   19515:                 fn = dummy_fct;
                   19516:        }
                   19517:        Pname nn = new name;
                   19518:         char* s = n->n_gen_fct_name;    // overloaded name
                   19519:        nn->string = s?s:n->string;
                   19520:        nn->n_qualifier = q;
                   19521:        Pname nx = Pname(find_name(nn,cl,tbl,REF,fn)); // nn deleted by find_name
                   19522:        if (nx->tp->base != OVERLOAD) return;
                   19523: 
                   19524:        // can we get here?
                   19525: 
                   19526:        // overloaded not checked by find_name()
                   19527:        // (since it looks for NAMEs not functions)
                   19528: 
                   19529:        for (Plist gl=Pgen(nx->tp)->fct_list; gl; gl=gl->l) {
                   19530:                Pname nn = gl->f;
                   19531:                if (n == nn) {
                   19532:                        if (nn->n_scope) return;        // public member
                   19533: 
                   19534:                        Pfct omef = mef;
                   19535:                        Pclass omec = mec;
                   19536:                        Pclass otcl = tcl;
                   19537: 
                   19538:                        Pclass ncl = Pclass(nn->n_table->t_name->tp);
                   19539:                        Pname fncn = fn->n_table->t_name;
                   19540: 
                   19541:                        mec = fncn?Pclass(fncn->tp):0; 
                   19542:                        Pfct f = mef = Pfct(fn->tp);
                   19543:                        tcl = cl;
                   19544: 
                   19545:                        int ok = is_accessible( n, ncl, 1 );
                   19546: 
                   19547:                        // restore global values
                   19548:                        mef = omef; mec = omec; tcl = otcl;
                   19549: 
                   19550:                        if ( ok ) return;
                   19551: 
                   19552:                        if ( Cdcl && Cdcl->base == NAME && 
                   19553:                                Cdcl->n_stclass == STATIC && 
                   19554:                                Cdcl->n_initializer && 
                   19555:                                Cdcl->n_qualifier )
                   19556:                        {
                   19557:                                Pbase bn = Pbase(Cdcl->n_qualifier->tp);
                   19558:                                Pclass ccl = Pclass(bn->b_name->tp);
                   19559: 
                   19560:                                if ( ccl == cl || ccl->has_friend(f) ||
                   19561:                                        (n->n_protect && ccl->has_base(ncl)))
                   19562:                                                return;
                   19563:                        }
                   19564: 
                   19565:                        if ( fn == dummy_fct )
                   19566:                                error("G scope cannot access%n: %sM",nn,nn->n_protect?"protected":"private");
                   19567:                        else error("%n cannot access%n: %sM",fn,nn,nn->n_protect?"protected":"private");
                   19568:                        return;
                   19569:                }
                   19570:        }
                   19571:        error('i',"visibility check failed");
                   19572: }
                   19573: 0707071010112044321004440001630000160000010202000466055403200000700000150132gram.y/*ident     "@(#)ctrans:src/gram.y  1.11" */
                   19574: /*************************************************************************
                   19575: 
                   19576:        C++ source for cfront, the C++ compiler front-end
                   19577:        written in the computer science research center of Bell Labs
                   19578: 
                   19579:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   19580:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   19581: 
                   19582: gram.y:
                   19583:        
                   19584:        This is the C++ syntax analyser.
                   19585: 
                   19586:        Syntax extensions for error handling:
                   19587:                nested functions
                   19588:                any expression can be empty
                   19589:                any expression can be a constant_expression
                   19590: 
                   19591:        A call to error() does not change the parser's state
                   19592: 
                   19593: ***************************************************************************/
                   19594: 
                   19595: %{
                   19596: #include "cfront.h"
                   19597: #include "size.h"
                   19598: #include "template.h"
                   19599: #include <string.h>
                   19600: // include tqueue.h after YYSTYPE is defined ...
                   19601: 
                   19602: 
                   19603: struct parstate {
                   19604:        Ptype intypedef;
                   19605:        int   defercheck;
                   19606:        Pname intag;
                   19607: } pstate[BLMAX];
                   19608: static int px;
                   19609: static void
                   19610: SAVE_STATE()
                   19611: {
                   19612:        if ( px++ >= BLMAX ) error('i',"maximum scope depth exceeded");
                   19613:        pstate[px].intypedef = in_typedef;
                   19614:        in_typedef = 0;
                   19615:        pstate[px].defercheck = defer_check;
                   19616:        defer_check = 0;
                   19617:        pstate[px].intag = in_tag;
                   19618:        in_tag = 0;
                   19619: }
                   19620: static void
                   19621: RESTORE_STATE()
                   19622: {
                   19623:        if ( --px < 0 ) error('i',"scope stack underflow");
                   19624:        in_typedef = pstate[px].intypedef;
                   19625:        defer_check = pstate[px].defercheck;
                   19626:        in_tag = pstate[px].intag;
                   19627: }
                   19628: 
                   19629: #define copy_if_need_be(s)  ((templp->in_progress || templp->parameters_in_progress) ? strdup(s) : s) 
                   19630: #define YYMAXDEPTH 600
                   19631: 
                   19632: #ifdef DBG
                   19633: #ifndef YYDEBUG
                   19634: #define YYDEBUG 1
                   19635: #endif
                   19636: #endif
                   19637: 
                   19638: static init_seen = 0;
                   19639: static cdi = 0;
                   19640: static Pnlist cd = 0, cd_vec[BLMAX];
                   19641: static char stmt_seen = 0, stmt_vec[BLMAX];
                   19642: 
                   19643: //local class
                   19644: static Plist tn_vec[BLMAX], lcl_tn_vec[BLMAX], lcl_blk_vec[BLMAX];
                   19645: extern void local_restore();
                   19646: extern void local_name();
                   19647: 
                   19648: //nested class
                   19649: static Plist nested_tn_vec[BLMAX], nested_type_vec[BLMAX];
                   19650: extern void nested_restore();
                   19651: 
                   19652: static Pname err_name = 0;
                   19653: 
                   19654: // fcts put into norm2.c just to get them out of gram.y
                   19655: void sig_name(Pname);  
                   19656: Ptype tok_to_type(TOK);
                   19657: void memptrdcl(Pname, Pname, Ptype, Pname);
                   19658: 
                   19659: static Pptr doptr(TOK p, TOK t)
                   19660: {
                   19661:        Pptr r = new ptr(p,0);
                   19662:        switch (t) {
                   19663:        case CONST:
                   19664:                r->rdo = 1;
                   19665:                // if (p == RPTR) error('w',"redundant `const' after &");
                   19666:                break;
                   19667:        case VOLATILE:
                   19668:                error('w',"\"volatile\" not implemented (ignored)");
                   19669:                break;
                   19670:        default:
                   19671:                error("syntax error: *%k",t);
                   19672:        }
                   19673:        return r;
                   19674: }
                   19675: 
                   19676: static Pbcl dobase(TOK pr, Pname n, TOK v = 0)
                   19677: {
                   19678:        Pbcl b = new basecl(0,0);
                   19679: 
                   19680:        if (pr == PROTECTED) {
                   19681:                pr = PUBLIC;
                   19682:                error("protectedBC");
                   19683:        }
                   19684:        b->ppp = pr;    // save protection indicator
                   19685: 
                   19686:        if (n) {
                   19687:                if (n->base != TNAME) {
                   19688:                        error("BN%n not aTN",n);
                   19689:                        return 0;
                   19690:                }
                   19691: 
                   19692:                Pbase bt = Pbase(n->tp);
                   19693:                while (bt->base == TYPE) bt = Pbase(bt->b_name->tp);
                   19694: 
                   19695:                if (bt->base != COBJ) {
                   19696:                        error("BN%n not aCN",n);
                   19697:                        return 0;
                   19698:                }
                   19699: 
                   19700:                if (v) {
                   19701:                        if (v != VIRTUAL) error("syntax error:%k inBCD",v);
                   19702:                        b->base = VIRTUAL;
                   19703:                }
                   19704:                else
                   19705:                        b->base = NAME;
                   19706: 
                   19707:                b->bclass = Pclass(bt->b_name->tp);
                   19708:        }
                   19709: 
                   19710:        return b;
                   19711: }
                   19712: 
                   19713: 
                   19714: #define Ndata(a,b)     b->normalize(Pbase(a),0,0)
                   19715: #define Ncast(a,b)     b->normalize(Pbase(a),0,1)
                   19716: #define Nfct(a,b,c)    b->normalize(Pbase(a),Pblock(c),0)
                   19717: #define Ncopy(n)       (n->base==TNAME)?new name(n->string):n
                   19718: 
                   19719: #define Finit(p)       Pfct(p)->f_init
                   19720: #define Fargdcl(p,q,r) Pfct(p)->argdcl(q,r)
                   19721: #define Freturns(p)    Pfct(p)->returns
                   19722: #define Vtype(v)       Pvec(v)->typ
                   19723: #define Ptyp(p)                Pptr(p)->typ
                   19724: 
                   19725:                /* avoid redefinitions */
                   19726: #undef EOFTOK
                   19727: #undef ASM
                   19728: #undef BREAK
                   19729: #undef CASE
                   19730: #undef CONTINUE
                   19731: #undef DEFAULT
                   19732: #undef DELETE
                   19733: #undef DO
                   19734: #undef ELSE
                   19735: #undef ENUM
                   19736: #undef FOR
                   19737: #undef FORTRAN
                   19738: #undef FRIEND
                   19739: #undef GOTO
                   19740: #undef IF
                   19741: #undef NEW
                   19742: #undef OPERATOR
                   19743: #undef RETURN
                   19744: #undef SIZEOF
                   19745: #undef SWITCH
                   19746: #undef THIS
                   19747: #undef WHILE
                   19748: #undef LP
                   19749: #undef RP
                   19750: #undef LB
                   19751: #undef RB
                   19752: #undef REF
                   19753: #undef DOT
                   19754: #undef NOT
                   19755: #undef COMPL
                   19756: #undef MUL
                   19757: #undef AND
                   19758: #undef PLUS
                   19759: #undef MINUS
                   19760: #undef ER
                   19761: #undef OR
                   19762: #undef ANDAND
                   19763: #undef OROR
                   19764: #undef QUEST
                   19765: #undef COLON
                   19766: #undef ASSIGN
                   19767: #undef CM
                   19768: #undef SM
                   19769: #undef LC
                   19770: #undef RC
                   19771: #undef ID
                   19772: #undef STRING
                   19773: #undef ICON
                   19774: #undef FCON
                   19775: #undef CCON
                   19776: #undef ZERO
                   19777: #undef ASOP
                   19778: #undef RELOP
                   19779: #undef EQUOP
                   19780: #undef DIVOP
                   19781: #undef SHIFTOP
                   19782: #undef ICOP
                   19783: #undef TYPE
                   19784: #undef TNAME
                   19785: #undef EMPTY
                   19786: #undef NO_ID
                   19787: #undef NO_EXPR
                   19788: #undef FDEF
                   19789: #undef ELLIPSIS
                   19790: #undef AGGR
                   19791: #undef MEM
                   19792: #undef MEMPTR
                   19793: #undef PR
                   19794: #undef TSCOPE
                   19795: #undef DECL_MARKER
                   19796: #undef REFMUL
                   19797: #undef LDOUBLE
                   19798: #undef LINKAGE
                   19799: #undef LOCAL
                   19800: #undef TEMPLATE
                   19801: 
                   19802: #undef XVIRT
                   19803: #undef XNLIST
                   19804: #undef XILINE
                   19805: #undef XIA
                   19806: #undef STATEMENT
                   19807: #undef EXPRESSION
                   19808: #undef SM_PARAM
                   19809: #undef TEMPLATE_TEST
                   19810: #undef PTNAME
                   19811: #undef NEW_INIT_KLUDGE
                   19812: %}
                   19813: 
                   19814: %union {
                   19815:        char*   s;
                   19816:        TOK     t;
                   19817:        int     i;
                   19818:        loc     l;
                   19819:        Pname   pn;
                   19820:        Ptype   pt;
                   19821:        Pexpr   pe;
                   19822:        Pstmt   ps;
                   19823:        Pbase   pb;
                   19824:        Pnlist  nl;
                   19825:        Pslist  sl;
                   19826:        Pelist  el;
                   19827:        Pbcl    pbc;
                   19828:        Pptr    pp;
                   19829:        PP      p;      // fudge: pointer to all class node objects
                   19830:        Plist   pl;
                   19831:        toknode* q;     // token queue
                   19832: }
                   19833: %{
                   19834: #include "tqueue.h"
                   19835: extern YYSTYPE yylval, yyval;
                   19836: extern int yyparse();
                   19837: 
                   19838: // in_typedef should allow for nested in_typedef
                   19839: extern int     declTag;         // !1: inline, virtual mod permitted
                   19840: int            in_sizeof = 0;
                   19841: Ptype          in_typedef = 0;  // catch redefinition of TNAME
                   19842: Pname          in_tag = 0;      // handle complex typedefs: int (*)()
                   19843: extern int     defer_check;     // redefinition typedef check delay
                   19844: Pname          curr_scope;
                   19845: 
                   19846: extern int     must_be_id;      // !0, TNAME => ID, i.e., int X
                   19847: int    DECL_TYPE = 0;   // lalex() wants this set for global x(*fp)()
                   19848: int    in_arg_list=0;   // !0 when parsing argument list
                   19849: static int in_binit_list=0;
                   19850: int    in_class_decl=0; // !0 when processing class definition
                   19851: int    parsing_class_members=0; // !0 when parsing class def but not member function body
                   19852: int    in_mem_fct=0;    // !0 when parsing member function definition
                   19853: 
                   19854: #define yylex lalex
                   19855: #define NEXTTOK() ( (yychar==-1) ? (yychar=yylex(),yychar) : yychar )
                   19856: #define EXPECT_ID() must_be_id = 1
                   19857: #define NOT_EXPECT_ID() must_be_id = 0
                   19858: 
                   19859: Pname syn()
                   19860: {
                   19861: ll:
                   19862:        switch (yyparse()) {
                   19863:        case 0:         return 0;       // EOF
                   19864:        case 1:         goto ll;        // no action needed
                   19865:        default:        return yyval.pn;
                   19866:        }
                   19867: }
                   19868: 
                   19869: %}
                   19870: /*
                   19871:        the token definitions are copied from token.h,
                   19872:        and all %token replaced by %token
                   19873: */
                   19874:                        /* keywords in alphabetical order */
                   19875: %token EOFTOK          0
                   19876: %token ASM             1
                   19877: %token AUTO            2
                   19878: %token BREAK           3
                   19879: %token CASE            4
                   19880: %token CONTINUE                7
                   19881: %token DEFAULT         8
                   19882: %token DELETE          9
                   19883: %token DO              10
                   19884: %token ELSE            12
                   19885: %token ENUM            13
                   19886: %token FOR             16
                   19887: %token FORTRAN         17 
                   19888: %token FRIEND          18 
                   19889: %token GOTO            19
                   19890: %token IF              20
                   19891: %token NEW             23
                   19892: %token OPERATOR                24
                   19893: %token RETURN          28
                   19894: %token SIZEOF          30
                   19895: %token SWITCH          33
                   19896: %token THIS            34
                   19897: %token WHILE           39
                   19898: 
                   19899:                        /* operators in priority order (sort of) */
                   19900: %token LP              40
                   19901: %token RP              41
                   19902: %token LB              42
                   19903: %token RB              43
                   19904: %token REF             44
                   19905: %token DOT             45
                   19906: %token NOT             46
                   19907: %token COMPL           47
                   19908: %token MUL             50
                   19909: %token AND             52
                   19910: %token PLUS            54
                   19911: %token MINUS           55
                   19912: %token LT              58
                   19913: %token GT              60
                   19914: %token ER              64
                   19915: %token OR              65
                   19916: %token ANDAND          66
                   19917: %token OROR            67
                   19918: %token QUEST           68
                   19919: %token COLON           69
                   19920: %token ASSIGN          70
                   19921: %token CM              71
                   19922: %token SM              72
                   19923: %token LC              73
                   19924: %token RC              74
                   19925: 
                   19926:     /* = constants etc. */
                   19927: %token ID         80
                   19928: %token STRING     81
                   19929: %token ICON       82
                   19930: %token FCON       83
                   19931: %token CCON       84
                   19932: %token NAME       85
                   19933: %token ZERO       86
                   19934:     /* groups of tokens */
                   19935: %token ASOP   90       /* op= */
                   19936: %token RELOP  91       /* LE GE LT GT */
                   19937: %token EQUOP  92       /* EQ NE */
                   19938: %token DIVOP  93       /* DIV MOD */
                   19939: %token SHIFTOP         94      /* LS RS */
                   19940: %token ICOP            95      /* INCR DECR */
                   19941: %token TYPE            97
                   19942:     /* TYPE =  INT FLOAT CHAR DOUBLE REGISTER STATIC EXTERN AUTO
                   19943:        LONG SHORT UNSIGNED INLINE FRIEND VIRTUAL */
                   19944: 
                   19945: %token TNAME     123
                   19946: %token EMPTY     124
                   19947: %token NO_ID     125
                   19948: %token NO_EXPR   126
                   19949: %token FDEF      127
                   19950: 
                   19951: %token ELLIPSIS        155
                   19952: %token AGGR    156
                   19953: %token MEM     160
                   19954: %token MEMPTR  173
                   19955: %token PR              175     /* PUBLIC PRIVATE PROTECTED */
                   19956: %token TSCOPE          178     /* TNAME :: */
                   19957: %token DECL_MARKER     179
                   19958: %token REFMUL          180     /* ->*, .* */
                   19959: %token LDOUBLE         181
                   19960: %token LINKAGE         182     /* extern "asdf" */
                   19961: %token LOCAL           183     /* local class */
                   19962: %token TEMPLATE                185     /* local class */
                   19963: 
                   19964: /* "tokens" for aux data structures */
                   19965: 
                   19966: %token XVIRT           200 /* class virt */
                   19967: %token XNLIST          201 /* struct name_list */
                   19968: %token XILINE          202
                   19969: %token XIA             203
                   19970: %token STATEMENT        205
                   19971: %token EXPRESSION       206
                   19972: %token SM_PARAM         207 
                   19973: %token TEMPLATE_TEST    208
                   19974: %token PTNAME           209
                   19975: %token NEW_INIT_KLUDGE  210
                   19976: %token XDELETED_NODE    211
                   19977: %token DUMMY_LAST_NODE  212
                   19978: 
                   19979: %type <p>      external_def fct_dcl fct_def att_fct_def arg_dcl_list 
                   19980:                base_init init_list binit
                   19981:                data_dcl ext_def vec ptr
                   19982:                type tp enum_dcl moe_list moe 
                   19983:                tag ttag enumtag class_head class_dcl cl_mem_list 
                   19984:                cl_mem dl decl_list 
                   19985:                fname decl initializer stmt_list
                   19986:                caselab_stmt caselablist
                   19987:                block statement simple ex_list elist e ee term prim
                   19988:                term_elist
                   19989:                cast_decl cast_type c_decl c_type c_tp
                   19990:                arg_decl formal_decl at arg_type arg_list arg_type_list
                   19991:                new_decl new_type
                   19992:                condition
                   19993:                TSCOPE tscope TNAME tn_list MEMPTR
                   19994:                qualified_tname
                   19995:                PTNAME tname ptname template_def
                   19996: %type <l>      LC RC SWITCH CASE DEFAULT FOR IF DO WHILE GOTO RETURN DELETE
                   19997:                BREAK CONTINUE
                   19998: %type <t>      oper ellipsis_opt
                   19999:                EQUOP DIVOP SHIFTOP ICOP RELOP GT LT ASOP
                   20000:                ANDAND OROR PLUS MINUS MUL ASSIGN OR ER AND 
                   20001:                LP LB NOT COMPL AGGR
                   20002:                TYPE PR REFMUL
                   20003:                STATEMENT EXPRESSION stmt_or_expr
                   20004: %type <s>      CCON ZERO ICON FCON STRING LINKAGE
                   20005: %type <pn>     ID FDEF inline_fct_def identifier
                   20006: %type <pbc>    base_list base_unit_list base_unit
                   20007: %type <q>      EMPTY
                   20008: %type <i>      fct_attributes
                   20009: %type <pl>     arg_lp
                   20010: %type <pe>      temp_inst_parm
                   20011: %type <el>      temp_inst_parms
                   20012: 
                   20013: %left  EMPTY
                   20014: %left  NO_ID
                   20015: %left  RC LC ID BREAK CONTINUE RETURN GOTO DELETE DO IF WHILE FOR CASE DEFAULT
                   20016:        AGGR ENUM TYPE TNAME TSCOPE
                   20017: %left  NO_EXPR
                   20018: 
                   20019: %left  CM
                   20020: %right ASOP ASSIGN
                   20021: %right QUEST COLON
                   20022: %left  OROR
                   20023: %left  ANDAND
                   20024: %left  OR
                   20025: %left  ER
                   20026: %left  AND
                   20027: %left  EQUOP
                   20028: %left  RELOP GT LT
                   20029: %left  SHIFTOP
                   20030: %left  PLUS MINUS
                   20031: %left  MUL DIVOP MEMPTR
                   20032: %left   REFMUL
                   20033: %right NOT COMPL NEW
                   20034: %right ICOP SIZEOF
                   20035: %left  LB LP DOT REF MEM
                   20036: 
                   20037: %start ext_def
                   20038: 
                   20039: %%
                   20040: /*
                   20041:        this parser handles declarations one by one,
                   20042:        NOT a complete .c file
                   20043: */
                   20044: 
                   20045: 
                   20046: /************** DECLARATIONS in the outermost scope: returns Pname (in yylval) ***/
                   20047: 
                   20048: ext_def                :  external_def         {       return 2; }
                   20049:                |  SM                   {       return 1; }
                   20050:                |  EOFTOK               {       return 0; }
                   20051:                |  LINKAGE LC
                   20052:                        {
                   20053:                                set_linkage($<s>1);
                   20054:                                bl_level--;
                   20055:                                return 1;
                   20056:                        }
                   20057:                |  RC
                   20058:                        {
                   20059:                                set_linkage(0);
                   20060:                                bl_level++;
                   20061:                                return 1;
                   20062:                        }
                   20063:                |  template              {  return 1; } 
                   20064:                 |  template_test         {  return 1 ;}
                   20065:                ;
                   20066: 
                   20067: 
                   20068: template_test   : TEMPLATE_TEST identifier LT temp_inst_parms GT SM
                   20069:                  { Ptreet t = tree_template::get($<pn>2->string) ;
                   20070:                     Pexpr  e = 0 ;
                   20071:                    if (t)
                   20072:                      e = t->expand(expr_unlist($<el>4)) ;
                   20073:                    else error ("%s wasn't an expression template",
                   20074:                                        $<pn>2->string)  ;
                   20075:                   } ;
                   20076: 
                   20077: template    :    TEMPLATE
                   20078:                  { templp->start() ; }
                   20079:                  LT template_parm_list GT
                   20080:                  {templp->enter_parameters() ; }
                   20081:                  template_def
                   20082:                  {templp->end($<pn>7);
                   20083:                   templp->in_progress = false ;
                   20084:                   goto mod;}
                   20085:                  ;
                   20086: 
                   20087: template_def   : att_fct_def
                   20088:                  { goto mod; }
                   20089:                 | fct_def
                   20090:                   { goto mod; }
                   20091:                 | class_dcl SM
                   20092:                   { Pname pn = $<pb>1->aggr();
                   20093:                     /* basetype:aggr() does not return the name for a forward */
                   20094:                    /* declaration, so extract it directly */
                   20095:                     $$ = (pn ? pn : $<pb>1->b_name) ;
                   20096:                     DECL_TYPE = 0;  }
                   20097:                 /* internal template specification productions*/
                   20098:                 | STATEMENT 
                   20099:                   {templp->curr_tree_template = $1 ; }
                   20100:                    identifier COLON statement
                   20101:                   {$<pn>3->n_initializer = $<pe>5 ; /* actually a stmt */
                   20102:                     $<pn>$ = $<pn>3; }
                   20103:                 | EXPRESSION 
                   20104:                   {templp->curr_tree_template = $1 ; }
                   20105:                   identifier COLON ee SM
                   20106:                   {$<pn>3->n_initializer = $<pe>5 ; /* actually a stmt */
                   20107:                     $<pn>$ = $<pn>3 ; }
                   20108:                  ;
                   20109: 
                   20110: identifier     : ID 
                   20111:                |  qualified_tname
                   20112:                        { $<pn>$ = Ncopy($<pn>1) ;} ;
                   20113:                ;
                   20114: 
                   20115: external_def   :  data_dcl
                   20116:                        {       
                   20117:                        /* if function declartion with arguments
                   20118:                         * need to make sure modified_tn is traversed */
                   20119:                        if ( $<pn>1 != 0 
                   20120:                                && $<pn>1->tp->base == FCT 
                   20121:                                && Pfct($<pn>1->tp)->nargs !=0 ) 
                   20122:                                        goto mod;
                   20123:                        else {
                   20124:                                modified_tn = 0;
                   20125:                                curr_scope = 0;
                   20126:                                if ($<pn>1==0) $<i>$ = 1; 
                   20127:                             }
                   20128:                        }
                   20129:                |  att_fct_def
                   20130:                        {       goto mod; }
                   20131:                |  fct_def
                   20132:                        {       goto mod; }
                   20133:                |  fct_dcl
                   20134:                        { mod:  if (modified_tn) {
                   20135:                                        restore();
                   20136:                                        modified_tn = 0;
                   20137:                                }
                   20138:                                local_blk = 0;
                   20139:                                curr_scope = 0;
                   20140:                                if (local_tn) {
                   20141:                                        local_restore();
                   20142:                                        local_tn = 0;
                   20143:                                }
                   20144:                                
                   20145:                                if (nested_tn) { // x::f(){}
                   20146:                                        nested_restore();
                   20147:                                        nested_tn = 0;
                   20148:                                        nested_type = 0;
                   20149:                                }
                   20150:                        }
                   20151:                |  ASM LP STRING RP SM
                   20152:                        {       Pname n = new name(make_name('A'));
                   20153:                                n->tp = new basetype(ASM,0);
                   20154:                                Pbase(n->tp)->b_name = Pname($<s>3);
                   20155:                                $$ = n;
                   20156:                        }
                   20157:                ;
                   20158: 
                   20159: fct_dcl                : decl ASSIGN initializer SM
                   20160:                        {
                   20161:                                err_name = $<pn>1;
                   20162:                                if(err_name) err_name->n_initializer = $<pe>3;
                   20163:                                goto fix;
                   20164:                        }
                   20165:                | decl SM
                   20166:                        {
                   20167:                                Ptype t;
                   20168:                                err_name = $<pn>1;
                   20169:                        fix:
                   20170:                                if (err_name == 0) {
                   20171:                                        error("syntax error:TX");
                   20172:                                        $$ = Ndata(defa_type,err_name);
                   20173:                                }
                   20174:                                else if ((t=err_name->tp) == 0) {
                   20175:                                        error("TX for%n",err_name);
                   20176:                                        $$ = Ndata(defa_type,err_name);
                   20177:                                }
                   20178:                                else if (t->base==FCT) {
                   20179:                                        if (Pfct(t)->returns==0)
                   20180:                                                $$ = Nfct(defa_type,err_name,0);
                   20181:                                        else
                   20182:                                                $$ = Ndata(0,err_name);
                   20183:                                }
                   20184:                                else {
                   20185:                                        error("syntax error:TX for%k%n",t->base,err_name);
                   20186:                                        $$ = Ndata(defa_type,err_name);
                   20187:                                }
                   20188:                        }
                   20189:                ;
                   20190: 
                   20191: att_fct_def    :  type decl arg_dcl_list check_inline base_init block
                   20192:                        {       Pname n = Nfct($1,$<pn>2,$6);
                   20193:                                Fargdcl(n->tp,name_unlist($<nl>3),n);
                   20194:                                Finit(n->tp) = $<pn>5;
                   20195:                                $$ = n;
                   20196:                                NOT_EXPECT_ID();
                   20197:                         //???POP_SCOPE(); // undef arg names
                   20198:                        }
                   20199:                |  type decl arg_dcl_list check_inline EMPTY
                   20200:                        {
                   20201:                                Pname n = Nfct($1,$<pn>2,dummy);
                   20202:                                Fargdcl(n->tp,name_unlist($<nl>3),n);
                   20203:                                $<q>5->retval.pn = n;
                   20204:                                $$ = n;
                   20205:                                NOT_EXPECT_ID();
                   20206:                        }
                   20207:                |  type decl arg_dcl_list check_inline NO_ID /*syntax error*/
                   20208:                        {
                   20209:                                error(&$<pn>2->where,"syntax error -- did you forget a ';'?");
                   20210:                                Pname n = Nfct($1,$<pn>2,0);
                   20211:                                $$ = n;
                   20212:                                NOT_EXPECT_ID();
                   20213:                        //???POP_SCOPE(); // undef arg names
                   20214:                        }
                   20215:                ;
                   20216: 
                   20217: fct_def                :  decl arg_dcl_list check_inline base_init block
                   20218:                        {       Pname n = Nfct(defa_type,$<pn>1,$5);
                   20219:                                Fargdcl(n->tp,name_unlist($<nl>2),n);
                   20220:                                if ( $<pn>4 && $<pn>4->n_list && 
                   20221:                                        ccl && ccl->csu == UNION )  
                   20222:                                                error( "multiple initializers in unionK %s::%n", $<pn>1->string, $<pn>1 );
                   20223:                                Finit(n->tp) = $<pn>4;
                   20224:                                $$ = n;
                   20225:                                NOT_EXPECT_ID();
                   20226:                         //???POP_SCOPE(); // undef arg names 
                   20227:                        }
                   20228:                |  decl arg_dcl_list check_inline EMPTY
                   20229:                        {
                   20230:                                Pname n = Nfct(defa_type,$<pn>1,dummy);
                   20231:                                Fargdcl(n->tp,name_unlist($<nl>2),n);
                   20232:                                $<q>4->retval.pn = n;
                   20233:                                $$ = n;
                   20234:                                NOT_EXPECT_ID();
                   20235:                        }
                   20236:                |  decl arg_dcl_list check_inline NO_ID /*syntax error*/
                   20237:                        {
                   20238:                                error(&$<pn>1->where,"badD of%n -- did you forget a ';'?",$<pn>1);
                   20239:                                Pname n = Nfct(defa_type,$<pn>1,0);
                   20240:                                $$ = n;
                   20241:                                NOT_EXPECT_ID();
                   20242:                          //???POP_SCOPE(); // undef arg names
                   20243:                        }
                   20244:                ;
                   20245: 
                   20246: inline_fct_def :  FDEF 
                   20247:                        {//PUSH_ARG_SCOPE
                   20248:                                arg_redec($<pn>1);
                   20249:                        }
                   20250:                   base_init block
                   20251:                        {
                   20252:                                Finit($1->tp) = $<pn>3;
                   20253:                                Pfct($1->tp)->body = Pblock($4);
                   20254:                                $$ = $1;
                   20255:                                NOT_EXPECT_ID();
                   20256:                         //???POP_SCOPE(); // undef arg names
                   20257:                        }
                   20258:                ;
                   20259: 
                   20260: 
                   20261: check_inline   :  /* empty */
                   20262:                   {
                   20263:                        // if parsing implicit inline def, save body
                   20264:                        //   of function for parsing after class def
                   20265:                        switch ( NEXTTOK() ) {
                   20266:                        case LC: case COLON:
                   20267:                                if ( in_class_decl ) {
                   20268:                                        // mem or friend inline def
                   20269:                                        // save text of mem_init & ftn
                   20270:                                        la_backup(yychar,yylval);
                   20271:                                        // yylval used as dummy...
                   20272:                                        la_backup(FDEF, yylval);
                   20273:                                        if ( yylval.q = save_text() )
                   20274:                                                yychar = EMPTY;
                   20275:                                        else { // syntax error
                   20276:                                                // just parse in place
                   20277:                                                yylex(); // FDEF
                   20278:                                                yychar = yylex();
                   20279:                                        }
                   20280:                                } // if in_class_decl
                   20281:                                break;
                   20282:                        default:
                   20283:                                la_backup(yychar,yylval);
                   20284:                                yychar = NO_ID; // 'graceful' recovery
                   20285:                                break;
                   20286:                        }
                   20287:                   }
                   20288:                ;
                   20289: 
                   20290: base_init      :  COLON { ++in_binit_list; } init_list
                   20291:                        {       
                   20292:                                $$ = $3; 
                   20293:                                in_arg_list = 0;
                   20294:                                --in_binit_list;
                   20295:                        }
                   20296:                |  %prec EMPTY
                   20297:                        {       $$ = 0; }
                   20298:                ;
                   20299: 
                   20300: init_list      :  binit
                   20301:                        { $$ = $1; }
                   20302:                |  init_list CM binit
                   20303:                        { $<pn>$ = $<pn>3;  $<pn>$->n_list = $<pn>1; }
                   20304:                ;
                   20305: 
                   20306: binit          :  LP elist RP
                   20307:                        {
                   20308:                                $<pn>$ = new name;
                   20309:                                $<pn>$->n_initializer = $<pe>2;
                   20310:                        }
                   20311:                |  ttag LP elist RP
                   20312:                        {
                   20313:                                Pname n = Ncopy($<pn>1);
                   20314:                                n->base = $<pn>1->base;
                   20315:                                n->tp = $<pn>1->tp;
                   20316:                                n->n_initializer = $<pe>3;
                   20317:                                $<pn>$ = n;
                   20318:                        }
                   20319: 
                   20320: /*
                   20321:                |  NEW LP elist RP
                   20322:                        {       Pname n = new name;
                   20323:                                n->base = NEW;
                   20324:                                n->n_initializer = $<pe>3;
                   20325:                                $<pn>$ = n;
                   20326:                        }
                   20327: */
                   20328:                ;
                   20329: 
                   20330: 
                   20331: 
                   20332: 
                   20333: /*************** declarations: returns Pname ********************/
                   20334: 
                   20335: arg_dcl_list   :  arg_dcl_list data_dcl
                   20336:                        {       if ($<pn>2 == 0)
                   20337:                                        error("badAD");
                   20338:                                else if ($<pn>2->tp->base == FCT)
                   20339:                                        error("FD inAL (%n)",$<pn>2);
                   20340:                                else if ($1)
                   20341:                                         $<nl>1->add_list($<pn>2);
                   20342:                                else
                   20343:                                        $<nl>$ = new nlist($<pn>2);
                   20344:                        }
                   20345:                |  %prec EMPTY
                   20346:                        {
                   20347:                                 $$ = 0; 
                   20348:                        }
                   20349:                ;
                   20350: 
                   20351: dl             :  decl
                   20352:                |  ID COLON 
                   20353:                         {
                   20354:                                 if ( in_typedef ) {
                   20355:                                         error("Tdef field");
                   20356:                                         in_typedef = 0;
                   20357:                                 }
                   20358:                         //      ENTER_NAME($<pn>1);
                   20359:                         }
                   20360:                    e           %prec CM
                   20361:                        {       $$ = $<pn>1;
                   20362:                                $<pn>$->tp = new basetype(FIELD,$<pn>4);
                   20363:                        }
                   20364:                |  COLON e              %prec CM
                   20365:                        {       $$ = new name;
                   20366:                                $<pn>$->tp = new basetype(FIELD,$<pn>2);
                   20367:                                 if ( in_typedef ) {
                   20368:                                         error("Tdef field");
                   20369:                                         in_typedef = 0;
                   20370:                                 }
                   20371:                        }
                   20372:                 |  decl ASSIGN
                   20373:                         {
                   20374:                         //      ENTER_NAME($<pn>1);
                   20375:                         }
                   20376:                    initializer
                   20377:                         {       Pexpr e = $<pe>4;
                   20378:                                 if (e == dummy) error("emptyIr");
                   20379:                                 $<pn>1->n_initializer = e;
                   20380:                                 init_seen = 0;
                   20381:                         }
                   20382:                 ;
                   20383: 
                   20384: decl_list      :  dl
                   20385:                        {       
                   20386:                                if ($1) $<nl>$ = new nlist($<pn>1); 
                   20387:                                if ( NEXTTOK() == CM && la_look() == TNAME ) 
                   20388:                                        EXPECT_ID();
                   20389:                        }
                   20390:                |  decl_list CM dl
                   20391:                        {       if ($1)
                   20392:                                        if ($3)
                   20393:                                                $<nl>1->add($<pn>3);
                   20394:                                        else
                   20395:                                                error("DL syntax");
                   20396:                                else {
                   20397:                                        if ($3) $<nl>$ = new nlist($<pn>3);
                   20398:                                        error("DL syntax");
                   20399:                                }
                   20400:                                if ( NEXTTOK() == CM && la_look() == TNAME ) 
                   20401:                                        EXPECT_ID();
                   20402:                        }
                   20403:                ;
                   20404: 
                   20405: data_dcl       :  type decl_list SM    
                   20406:                        { 
                   20407:                                extern int co_hack;
                   20408:                                co_hack = 1;
                   20409:                                /*$$ = Ndata($1,name_unlist($<nl>2));*/
                   20410:                                Pname n = Ndata($1,name_unlist($<nl>2)); 
                   20411:                                if ( in_typedef && in_tag ) { 
                   20412:                                        if ( n->tp->check( in_tag->tp, 0 ))
                   20413:                                                error("%nredefined: previous: %t now: %t", in_tag, in_tag->tp, n->tp );
                   20414:                                }
                   20415:                                in_typedef = 0;
                   20416:                                in_tag = 0;
                   20417:                                co_hack = 0;
                   20418:                                DECL_TYPE = 0; 
                   20419:                                $$ = n;
                   20420:                        }
                   20421:                |  type SM              
                   20422:                        {
                   20423:                                $$ = $<pb>1->aggr(); 
                   20424:                                in_typedef = 0;
                   20425:                                in_tag = 0;
                   20426:                                DECL_TYPE = 0; 
                   20427:                        }
                   20428:                
                   20429:                ;
                   20430: 
                   20431: /* This is where parametrized types, and regular types come together. */
                   20432: 
                   20433: lt             : LT { templp->parameters_in_progress++; };
                   20434: gt             : GT { templp->parameters_in_progress--; };
                   20435: 
                   20436: tname           : qualified_tname { $<pn>$ = templp->check_tname($<pn>1) ; }
                   20437:                 | qualified_tname lt temp_inst_parms gt
                   20438:                   { 
                   20439:                    $<pn>$ = parametrized_typename($<pn>1,
                   20440:                                                  (expr_unlist($<el>3))) ; 
                   20441:                  }
                   20442:                 | NAME LT temp_inst_parms GT
                   20443:                   { extern Pbase any_type;
                   20444:                    error("%n was not a parametrized type.", $<pn>$) ;
                   20445:                     $<pn>$= $<pn>1->tdef() ;
                   20446:                     $<pn>$->tp = any_type ; } ;
                   20447: 
                   20448: 
                   20449: 
                   20450: tp             :  TYPE                 
                   20451:                        { 
                   20452:                                $$ = new basetype($<t>1,0); 
                   20453:                                if ( $<t>1 == TYPEDEF ) in_typedef = $<pt>$;
                   20454:                                if (DECL_TYPE == -1) DECL_TYPE = 0;
                   20455:                        }
                   20456:                |  LINKAGE              
                   20457:                        {       $$ = new basetype(EXTERN,0);
                   20458:                                $<pb>$->b_linkage = $<s>1;
                   20459:                                if (DECL_TYPE == -1) DECL_TYPE = 0;
                   20460:                        }
                   20461:                |  qualified_tname
                   20462:                        { 
                   20463:                                templp->check_tname($<pn>1);
                   20464:                                $$ = new basetype(TYPE,$<pn>1); 
                   20465:                                if (DECL_TYPE == -1) DECL_TYPE = 0;
                   20466:                        }
                   20467:        /*XXX*/ |  tn_list DECL_MARKER
                   20468:                        { // modified tn_list TNAME
                   20469:                                $$ = new basetype(TYPE,$<pn>2);
                   20470:                                //xxx qualifier currently ignored...
                   20471:                                if (DECL_TYPE == -1) DECL_TYPE = 0;
                   20472:                        }
                   20473:                | qualified_tname lt temp_inst_parms gt
                   20474:                        {
                   20475:                                $<pb>$ = parametrized_basetype($<pn>1,(expr_unlist($<el>3)));
                   20476:                        }
                   20477:                |  class_dcl 
                   20478:                |  enum_dcl
                   20479:                |  DECL_MARKER          
                   20480:                        { 
                   20481:                                if (DECL_TYPE == TNAME)
                   20482:                                        $$ = new basetype(TYPE,$<pn>1); 
                   20483:                //      else if (DECL_TYPE == TSCOPE)
                   20484:                //      $$ = 0;
                   20485:                                else
                   20486:                                if (DECL_TYPE == 0 &&
                   20487:                                        $<p>1->base == TNAME)
                   20488:                                                $$ = new basetype(TYPE,$<pn>1); 
                   20489:                                else
                   20490:                                        $$ = new basetype($<t>1,0); 
                   20491:                                DECL_TYPE = -1;
                   20492:                        }
                   20493:                ;
                   20494: 
                   20495: type           :  tp
                   20496:                |  type TYPE            
                   20497:                        { 
                   20498:                                if ( DECL_TYPE != -1 ) {
                   20499:                                        switch ($<pb>1->base) { Pbase bt;
                   20500:                                        case COBJ: case EOBJ:
                   20501:                                                bt = new basetype(0,0);
                   20502:                                                *bt = *$<pb>1;
                   20503:                                                DEL($<pb>1);
                   20504:                                                $<pb>1 = bt;
                   20505:                                        }
                   20506:                                        $$ = $<pb>1->type_adj($<t>2); 
                   20507:                                }
                   20508:                                DECL_TYPE = 0;
                   20509:                        }
                   20510:                |  type tname
                   20511:                        {
                   20512: //error('d',"decl_type: %d  $1: %t  $2: %n",DECL_TYPE,$<pb>1,$<pn>2);
                   20513:                                if ( DECL_TYPE != -1 ) 
                   20514:                                        $$ = $<pb>1->name_adj($<pn>2);
                   20515:                        /*XXX*/ else if($<pb>1==0) $$=new basetype(TYPE,$<pn>2);
                   20516:                                DECL_TYPE = 0;
                   20517:                        }
                   20518:                |  type class_dcl       { $$ = $<pb>1->base_adj($<pb>2); }
                   20519:                |  type enum_dcl        { $$ = $<pb>1->base_adj($<pb>2); }
                   20520:                |  type DECL_MARKER             
                   20521:                        { 
                   20522:                                if (DECL_TYPE == TYPE) {
                   20523:                                        switch ($<pb>1->base) { Pbase bt;
                   20524:                                        case COBJ: case EOBJ:
                   20525:                                                bt = new basetype(0,0);
                   20526:                                                *bt = *$<pb>1;
                   20527:                                                DEL($<pb>1);
                   20528:                                                $<pb>1 = bt;
                   20529:                                        }
                   20530:                                        $$ = $<pb>1->type_adj($<t>2);  
                   20531:                                }
                   20532:                        /*XXX*/ else if (DECL_TYPE == TSCOPE) {
                   20533:                        /*XXX*/         error('i',"type decl_marker(tscope)");
                   20534:                        /*XXX*/ //      $$ = $1;//ignore(?)
                   20535:                        /*XXX*/ }
                   20536:                                else
                   20537:                                        $$ = $<pb>1->name_adj($<pn>2); 
                   20538:                                DECL_TYPE = -1;
                   20539:                        }
                   20540:                ;
                   20541: 
                   20542: temp_inst_parms : temp_inst_parms CM temp_inst_parm
                   20543:                   {$<el>1->add(new expr(ELIST,$<pe>3,NULL)) ; }
                   20544:                 | temp_inst_parm { $<el>$ =
                   20545:                                     new elist(new expr(ELIST,$<pe>1,NULL)); } ;
                   20546: 
                   20547: temp_inst_parm  : new_type
                   20548:                   {$<pn>1->n_template_arg = template_actual_arg_dummy ;
                   20549:                   $<pe>$ = $<pn>1; /* keep yacc happy */ }
                   20550:                 | e %prec GT
                   20551:                   { $<pe>$ = $<pe>1 ; } ; 
                   20552: 
                   20553: /***************** aggregate: returns Pname *****************/
                   20554: 
                   20555: enumtag        :  tag
                   20556:                { enumcheck:
                   20557:                        Ptype tx = $<pn>1->tp;
                   20558:                        $$ = $1;
                   20559:                        if ( tx->base == TYPE ) {
                   20560:                                $$ = Pbase(tx)->b_name;
                   20561:                                tx = $<pn>$->tp;
                   20562:                                if ( tx->base != EOBJ
                   20563:                                ||   strcmp($<pn>$->string,$<pn>1->string)
                   20564:                                )
                   20565:                                        error("%n of type%t redeclared as enum.",$<pn>1,tx);
                   20566:                        } else if ( tx->base != EOBJ )
                   20567:                                error("%n of type%t redeclared as enum",$<pn>1,tx);
                   20568:                }
                   20569:        |  DECL_MARKER { goto enumcheck; }
                   20570:        ;
                   20571: 
                   20572: enum_dcl       :  ENUM LC moe_list RC          { $$ = end_enum(0,$<nl>3); }
                   20573:                |  ENUM enumtag LC moe_list RC { $$ = end_enum($<pn>2,$<nl>4); }
                   20574:                |  ENUM enumtag         { $<pb>$ = (Pbase)$<pn>2->tp; }
                   20575:                ;
                   20576: 
                   20577: moe_list       :  moe
                   20578:                        {       if ($1) $<nl>$ = new nlist($<pn>1); }
                   20579:                |  moe_list CM moe
                   20580:                        {       if( $3)
                   20581:                                        if ($1)
                   20582:                                                $<nl>1->add($<pn>3);
                   20583:                                        else
                   20584:                                                $<nl>$ = new nlist($<pn>3);
                   20585:                        }
                   20586:                ;
                   20587: 
                   20588: template_parm_list : template_parm_list CM template_parm
                   20589:                    | template_parm
                   20590:                    | { $<pn>$ = NULL ;} ;
                   20591: 
                   20592: 
                   20593: stmt_or_expr    : STATEMENT | EXPRESSION ;
                   20594: 
                   20595: template_parm   : AGGR identifier
                   20596:                   /* Build the name for the parameter
                   20597:                  /* Check that AGGR is indeed CLASS */
                   20598:                  { templp->collect($<t>1, $<pn>2) ; }
                   20599:                  | stmt_or_expr identifier
                   20600:                  { templp->collect($<t>1, $<pn>2) ; }  
                   20601:                  |   type formal_decl
                   20602:                        {templp->collect(Ndata($1,$<pn>2)); } ; 
                   20603: 
                   20604: 
                   20605: /* Sam: these productions are a variant of the ones for arg_decl,
                   20606:  verify them against arg_decl for each release. */
                   20607: formal_decl    :  ID
                   20608:                        {       $$ = $<pn>1; }
                   20609:                |  ptr formal_decl              %prec MUL
                   20610:                        {       Ptyp($1) = $<pn>2->tp;
                   20611:                                $<pn>2->tp = (Ptype)$1;
                   20612:                                $$ = $2;
                   20613:                        }
                   20614:                |  formal_decl vec              %prec LB
                   20615:                        {       Vtype($2) = $<pn>1->tp;
                   20616:                                $<pn>1->tp = (Ptype)$2;
                   20617:                        }
                   20618:                |  formal_decl arg_list
                   20619:                        {       Freturns($2) = $<pn>1->tp;
                   20620:                                $<pn>1->tp = (Ptype)$2;
                   20621:                        } ;
                   20622: 
                   20623: 
                   20624: moe            :  ID
                   20625:                        {       $$ = $<pn>1; $<pn>$->tp = moe_type; }
                   20626:                |  ID ASSIGN e
                   20627:                        {       $$ = $<pn>1;
                   20628:                                $<pn>$->tp = moe_type;
                   20629:                                $<pn>$->n_initializer = $<pe>3;
                   20630:                        }
                   20631:                |  /* empty: handle trailing CM: enum e { a,b, }; */
                   20632:                        {       $$ = 0; }
                   20633:                ;
                   20634: 
                   20635: class_dcl      :  class_head cl_mem_list RC
                   20636:                        {       parsing_class_members = 0;
                   20637:                                RESTORE_STATE();
                   20638:                                switch ( NEXTTOK() ) {
                   20639:                                case TYPE: case AGGR: case ENUM: case EOFTOK:
                   20640:                                        error("`;' or declaratorX afterCD");
                   20641:                                        la_backup(yychar,yylval);
                   20642:                                        yychar = SM;
                   20643:                                        break;
                   20644:                                }
                   20645:                                la_backup(yychar,yylval);
                   20646:                                yychar = -1;
                   20647:                                restore_text();
                   20648:                                ++bl_level; // scope weirdness!
                   20649:                                ++in_mem_fct;
                   20650:                        }
                   20651:                        inline_mem_defs
                   20652:                        {
                   20653:                                --in_mem_fct;
                   20654:                                --bl_level; // scope weirdness!
                   20655:                                if ( yychar == ID ) {
                   20656:                                        // (yuk!) adjust lex level
                   20657:                                        --yylval.pn->lex_level;
                   20658:                                }
                   20659:                                ccl->mem_list = name_unlist($<nl>2);
                   20660:                                if ( --in_class_decl )  // nested class
                   20661:                                        // continue to parse enclosing class
                   20662:                                        parsing_class_members = 1;
                   20663:                                ccl->nest_list = nested_type;
                   20664:                                if ( nested_tn ) nested_restore();
                   20665:                                nested_type = nested_type_vec[in_class_decl];
                   20666:                                nested_tn = nested_tn_vec[in_class_decl];
                   20667:                                end_cl();
                   20668:                                declTag = 1;
                   20669:                         //POP_SCOPE();
                   20670:                        }
                   20671:                |  AGGR tag 
                   20672:                        { aggrcheck:
                   20673:                                $<pb>$ = (Pbase)$<pn>2->tp; 
                   20674:                                if ( $$->base == TYPE ) {
                   20675:                                        Pname nx = $<pb>$->b_name;
                   20676:                                        $<pb>$ = (Pbase)nx->tp;
                   20677:                                        if ( $$->base != COBJ
                   20678:                                        ||   strcmp(nx->string,$<pn>2->string)
                   20679:                                        )
                   20680:                                                error("%n of type%t redeclared as%k.",$<pn>2,$<pb>$,$<t>1);
                   20681:                                } else if ( $$->base != COBJ )
                   20682:                                        error("%n of type%t redeclared as%k",$<pn>2,$<pb>$,$<t>1);
                   20683:                                check_tag();
                   20684:                        }
                   20685:                 | AGGR qualified_tname lt temp_inst_parms gt
                   20686:                   { 
                   20687:                    Pname p = parametrized_typename($<pn>2, (expr_unlist($<el>4))) ;
                   20688:                     $<pb>$ = (Pbase)p->tp; 
                   20689:                     check_tag(); 
                   20690:                  }                   
                   20691:                |  AGGR DECL_MARKER 
                   20692:                        {
                   20693:                                goto aggrcheck;
                   20694:                        }
                   20695:                ;
                   20696: 
                   20697: 
                   20698: inline_mem_defs        :  /* empty */
                   20699:                |  inline_mem_defs inline_fct_def
                   20700:                ;
                   20701: 
                   20702: base_list      :  COLON base_unit_list         { $$ = $2; }
                   20703:                |  %prec EMPTY                  { $$ = 0; }
                   20704:                ;
                   20705: 
                   20706: base_unit_list :  base_unit
                   20707:                |  base_unit_list CM base_unit
                   20708:                        {       if ($3) { $$ = $3; $<pbc>$->next = $1; } }
                   20709:                ;
                   20710: 
                   20711: base_unit      :  ttag                 { $$ = dobase(0,$<pn>1); }
                   20712:                |  PR ttag              { $$ = dobase($<t>1,$<pn>2); }
                   20713:                |  TYPE ttag            { $$ = dobase(0,$<pn>2,$<t>1); }
                   20714:                |  PR TYPE ttag         { $$ = dobase($<t>1,$<pn>3,$<t>2); }
                   20715:                |  TYPE PR ttag         { $$ = dobase($<t>2,$<pn>3,$<t>1); }
                   20716:                ;
                   20717: 
                   20718: class_head     :  AGGR LC      
                   20719:                        {//PUSH_CLASS_SCOPE(0);
                   20720:                                parsing_class_members = 1;
                   20721:                                $$ = start_cl($<t>1,0,0); 
                   20722:                                nested_tn_vec[in_class_decl] = nested_tn;
                   20723:                                nested_type_vec[in_class_decl++] = nested_type;
                   20724:                                nested_tn = nested_type = 0;
                   20725:                                SAVE_STATE();
                   20726:                        }
                   20727: 
                   20728:                |  AGGR tag base_list LC
                   20729:                        { //PUSH_CLASS_SCOPE($<pn>2->string);
                   20730:                                parsing_class_members = 1;
                   20731:                                $$ = start_cl($<t>1,$<pn>2,$<pbc>3);
                   20732:                                nested_tn_vec[in_class_decl] = nested_tn;
                   20733:                                nested_type_vec[in_class_decl++] = nested_type;
                   20734:                                nested_tn = nested_type = 0;
                   20735:                                SAVE_STATE();
                   20736:                        }
                   20737:                ;
                   20738: 
                   20739: tag            :  ID   { $$ = $1; }
                   20740:                |  qualified_tname { $$=$1; }
                   20741:                ;
                   20742: 
                   20743: ttag           :  ID   { $$ = $1; }
                   20744:                |  tname { $$=$1; }
                   20745:                ;
                   20746: 
                   20747: cl_mem_list    :  cl_mem_list cl_mem
                   20748:                        {
                   20749:                                if ($2) {
                   20750:                                        if ($1)
                   20751:                                                $<nl>1->add_list($<pn>2);
                   20752:                                        else
                   20753:                                                $<nl>$ = new nlist($<pn>2);
                   20754:                                }
                   20755:                        }
                   20756:                |  %prec EMPTY { $$ = 0; }
                   20757:                |  cl_mem_list TEMPLATE
                   20758:                        {
                   20759:                                error( "ZizedTD must be atG, notC scope" );
                   20760:                                error('i', "cannot recover from previous error" );
                   20761:                        }
                   20762:                ;
                   20763: 
                   20764: cl_mem         :  data_dcl
                   20765:                |  att_fct_def SM
                   20766:                |  fct_def SM
                   20767:                |  fct_def
                   20768:                |  att_fct_def
                   20769:                |  fct_dcl
                   20770:                |  PR COLON
                   20771:                        {       $$ = new name;
                   20772:                                $<pn>$->base = $<t>1;
                   20773:                        }
                   20774:        /*XXX   |  tn_list TNAME SM
                   20775:         *              {       Pname n = Ncopy($<pn>2);
                   20776:         *                      n->n_qualifier = $<pn>1;
                   20777:         *                      n->base = PR;
                   20778:         *                      $$ = n;
                   20779:         *              }
                   20780:         */     |  tn_list fname SM
                   20781:                        {       Pname n = Ncopy($<pn>2);
                   20782:                                if (n->n_oper == TYPE) {
                   20783:                                        error('s',"visibilityD for conversion operator");
                   20784:                                        // n->tp = Ptype(n->n_initializer);
                   20785:                                        n->tp = Ptype(n->cond);
                   20786:                                        n->cond = 0;
                   20787:                                        // n->n_initializer = 0;
                   20788:                                        n->n_oper = 0;
                   20789:                                        sig_name(n);
                   20790:                                }
                   20791:                                n->n_qualifier = $<pn>1;
                   20792:                                n->base = PR;
                   20793:                                $$ = n;
                   20794:                        }
                   20795:                ;
                   20796: 
                   20797: /************* declarators:    returns Pname **********************/
                   20798: /*     a ``decl'' is used for function and data declarations,
                   20799:                and for member declarations
                   20800:                (it has a name)
                   20801:        an ``arg_decl'' is used for argument declarations
                   20802:                (it may or may not have a name)
                   20803:        an ``cast_decl'' is used for casts
                   20804:                (it does not have a name)
                   20805:        a ``new_decl'' is used for type specifiers for the NEW operator
                   20806:                (it does not have a name, and PtoF and PtoV cannot be expressed)
                   20807: */
                   20808: 
                   20809: fname          :  ID
                   20810:                        {       $$ = $<pn>1; }
                   20811:                |  COMPL TNAME  /* qualified_tname? */
                   20812:                        {       $$ = Ncopy($<pn>2);
                   20813:                                $<pn>$->n_oper = DTOR;
                   20814:                        }
                   20815:                |  OPERATOR oper
                   20816:                        {       $$ = new name(oper_name($2));
                   20817:                                $<pn>$->n_oper = $<t>2;
                   20818:                        }
                   20819:                |  OPERATOR c_type
                   20820:                        {       Pname n = $<pn>2;
                   20821:                                n->string = "_type";
                   20822:                                n->n_oper = TYPE;
                   20823:                                n->cond = Pexpr(n->tp);
                   20824:                                // n->n_initializer = Pexpr(n->tp);
                   20825:                                n->tp = 0;
                   20826:                                $$ = n;
                   20827:                        }
                   20828:                ;
                   20829: 
                   20830: oper           :  PLUS
                   20831:                |  MINUS
                   20832:                |  MUL
                   20833:                |  AND
                   20834:                |  OR
                   20835:                |  ER
                   20836:                |  SHIFTOP
                   20837:                |  EQUOP
                   20838:                |  DIVOP
                   20839:                |  RELOP
                   20840:                |  LT
                   20841:                |  GT
                   20842:                |  ANDAND
                   20843:                |  OROR
                   20844:                |  LP RP        {       $$ = CALL; }
                   20845:                |  LB RB        {       $$ = DEREF; }
                   20846:                |  NOT
                   20847:                |  COMPL
                   20848:                |  ICOP
                   20849:                |  ASOP
                   20850:                |  ASSIGN
                   20851:                |  NEW          {       $$ = NEW; }
                   20852:                |  DELETE       {       $$ = DELETE; }
                   20853:                |  REF          {       $$ = REF; }
                   20854:                |  CM           {       $$ = CM; }
                   20855:                |  REFMUL       {       $$ = REFMUL;
                   20856:                                        if ($<t>1 == DOT) error(".* cannot be overloaded");
                   20857:                                }
                   20858:                ;
                   20859: 
                   20860: tn_list                :  tscope
                   20861:                /*XXX*/ {   if ( $<pn>1 != sta_name ) {
                   20862: // error('d',"tn_list: tscope: pn1: %s", $<pn>1->string);
                   20863:                                Ptype t = $<pn>1->tp;
                   20864:                                while ( t->base == TYPE )
                   20865:                                        t = Pbase(t)->b_name->tp;
                   20866:                                Pname n = Pbase(t)->b_name;
                   20867:                                if (NEXTTOK() == TNAME
                   20868:                                && strcmp(n->string,yylval.pn->string)==0){
                   20869:                                        // ctor -- change to ID to avoid
                   20870:                                        //    parsing as type spec
                   20871:                                        yychar = ID;
                   20872:                                        yylval.pn = Ncopy(yylval.pn);
                   20873:                                        yylval.pn->n_oper = TNAME;
                   20874:                                }
                   20875:                            }
                   20876:                            $<pn>$ = $<pn>1;
                   20877:                        }
                   20878: /* YYY         |  tn_list tscope       { $<pn>$ = $<pn>1; } */
                   20879:                |  tn_list tscope       { error('s', "CNs do not nest, use typedef x::y y_in_x"); };
                   20880:        /*XXX   |  tn_list ID DOT       { error("CNs do not nest"); } */
                   20881:                ;
                   20882: 
                   20883: qualified_tname        : tn_list TNAME
                   20884:                        {       $<pn>$ = $<pn>2;
                   20885:                                //xxx qualifier currently ignored...
                   20886:                                // $<pn>$ = Ncopy( $<pn>2 );
                   20887:                                // $<pn>$->n_oper = TNAME;
                   20888:                                // $<pn>$->n_qualifier = $<pn>1;
                   20889:                        }
                   20890:                | TNAME
                   20891:                        {       $<pn>$ = $<pn>1;
                   20892:                        //      $<pn>$ = Ncopy( $<pn>1 );
                   20893:                        //      $<pn>$->n_oper = TNAME;
                   20894:                        }
                   20895:                ;
                   20896: 
                   20897: fct_attributes : /* empty */
                   20898:                        { $$ = 0; }
                   20899:                | fct_attributes TYPE
                   20900:                        { /* const/volatile function */
                   20901:                                switch ( $<t>2 ) {
                   20902:                                case VOLATILE:
                   20903:                                        error('s',"volatile functions");
                   20904:                                        break;
                   20905:                                case CONST:
                   20906:                                        $$ = ($1 | 1);
                   20907:                                        break;
                   20908:                                default:
                   20909:                                        if ( NEXTTOK() != SM
                   20910:                                        &&   yychar != COLON
                   20911:                                        &&   yychar != LC ) {
                   20912:                                                la_backup(yychar,yylval);
                   20913:                                                yylval.t = $<t>2;
                   20914:                                                la_backup(TYPE,yylval);
                   20915:                                                yylval.t = SM;
                   20916:                                                yychar = SM;
                   20917:                                                error("syntax error: unexpected%k (did you forget a `;'?)",$<t>2);
                   20918:                                        } else error("FD syntax: unexpected%k",$<t>2);
                   20919:                                        break;
                   20920:                                }
                   20921:                        }
                   20922:                ;
                   20923: 
                   20924: decl           :  decl arg_list
                   20925:                        {       Freturns($2) = $<pn>1->tp;
                   20926:                                $<pn>1->tp = $<pt>2;
                   20927:                        }
                   20928:                |  decl LP RP fct_attributes
                   20929:                        { /* function with no argument */
                   20930:                                $<pn>1->tp = new fct($<pn>1->tp,0,1);
                   20931:                                Pfct($<pn>1->tp)->f_const = ($<i>4 & 1);
                   20932:                        }
                   20933:                |  tname arg_list
                   20934:                        {       Pname n = $<pn>1;
                   20935:                                $$ = Ncopy(n);
                   20936:                                 //??? what if tname is qualified ???
                   20937:                                if (ccl && strcmp(n->string,ccl->string)) n->hide();
                   20938:                                $<pn>$->n_oper = TNAME;
                   20939:                                Freturns($2) = $<pn>$->tp;
                   20940:                                $<pn>$->tp = $<pt>2;
                   20941:                        }
                   20942:                |  decl arg_lp elist RP
                   20943:                        /*      may be class object initializer,
                   20944:                                class object vector initializer,
                   20945:                                if not elist will be a CM or an ID
                   20946:                        */
                   20947:                        {       
                   20948:                                $<pn>1->tp = new fct($<pn>1->tp,$<pn>3,1); 
                   20949:                                in_arg_list = 0;
                   20950:                                end_al($2,0);
                   20951:                                RESTORE_STATE();
                   20952:                         //POP_SCOPE(); // similar to end_al()
                   20953:                        }
                   20954:                |  tname LP MUL ID RP arg_list
                   20955:                        {
                   20956:                                Pptr p = new ptr( PTR, 0 );
                   20957:                                Ptyp(p) = new basetype(TYPE,$<pn>1);
                   20958:                                Freturns( $6 ) = Ptype(p);
                   20959:                                $<pn>4->tp = $<pt>6;
                   20960:                                $$ = $4;
                   20961:                                if (DECL_TYPE == -1) DECL_TYPE = 0;
                   20962:                        }
                   20963:                |  tname LP elist RP
                   20964:                        {       $$ = Ncopy($<pn>1);
                   20965:                                $<pn>$->n_oper = TNAME;
                   20966:                                $<pn>$->tp = new fct(0,$<pn>3,1);
                   20967:                        } 
                   20968:                |  tname LP RP fct_attributes
                   20969:                        { /* function with no argument */
                   20970:                                $$ = Ncopy($<pn>1);
                   20971:                                $<pn>$->n_oper = TNAME;
                   20972:                                $<pn>$->tp = new fct(0,0,1);
                   20973:                                Pfct($<pn>1->tp)->f_const = ($<i>4 & 1);
                   20974:                        }
                   20975:                |  tname LP MEMPTR decl RP arg_list
                   20976:                        {       memptrdcl($<pn>3,$<pn>1,$<pt>6,$<pn>4);
                   20977:                                $$ = $4;
                   20978:                        }
                   20979:                |  fname
                   20980:                |  ID DOT fname
                   20981:                        {       $$ = Ncopy($<pn>3);
                   20982:                                $<pn>$->n_qualifier = $1;
                   20983:                                error(strict_opt?0:'w',"`.' used for qualification; please use `::' (anachronism)");
                   20984:                        }
                   20985:                |  tn_list fname
                   20986:                        {       $$ = $2;
                   20987:                                if ( $<pn>1 != sta_name ) {
                   20988:                                        set_scope($<pn>1); 
                   20989:                                        $<pn>$->n_qualifier = $<pn>1;
                   20990:                                }
                   20991:                        }
                   20992:        /*XXX*/ |  tn_list ID DOT fname
                   20993:                        {       $$ = Ncopy($<pn>4);
                   20994:                                $<pn>$->n_qualifier = $2;
                   20995:                                error(ansi_opt?0:'w',"anachronism `.' used for qualification; please use `::'");
                   20996:                                if ( $<pn>1 != sta_name ) {
                   20997:                                        set_scope($<pn>1); 
                   20998:                                        $<pn>2->n_qualifier = $<pn>1;
                   20999:                                }
                   21000:                        }
                   21001:        /*XXX   |  tn_list TNAME
                   21002:         *              {
                   21003:         *                      if ( $<pn>1 == sta_name ) 
                   21004:         *                              error( ":: applied to CN%n", $<pn>2 );
                   21005:         *                      $$ = Ncopy($<pn>2);
                   21006:         *                      set_scope($<pn>1);
                   21007:         *                      $<pn>$->n_oper = TNAME;
                   21008:         *                      $<pn>$->n_qualifier = $<pn>1;
                   21009:         *              }
                   21010:         */     |  ptr decl     %prec MUL
                   21011:                        {       Ptyp($1) = $<pn>2->tp;
                   21012:                                $<pn>2->tp = $<pt>1;
                   21013:                                $$ = $2;
                   21014:                        }
                   21015:                |  ptr tname    %prec MUL
                   21016:                        {       $$ = Ncopy($<pn>2);
                   21017:                                $<pn>$->n_oper = TNAME;
                   21018:                                // cannot evaluate at this point: defer until data_dcl
                   21019:                                if ( in_typedef ) {
                   21020:                                        defer_check = 1;
                   21021:                                        in_tag = $<pn>2;
                   21022:                                }
                   21023:                                $<pn>2->hide();
                   21024:                                defer_check = 0;
                   21025:                                $<pn>$->tp = $<pt>1;
                   21026:                        }
                   21027:                |  tname vec    %prec LB
                   21028:                        {       $$ = Ncopy($<pn>1);
                   21029:                                $<pn>$->n_oper = TNAME;
                   21030:                                if ( in_typedef ) {
                   21031:                                        defer_check = 1;
                   21032:                                        in_tag = $<pn>1;
                   21033:                                }
                   21034:                                $<pn>1->hide();
                   21035:                                defer_check = 0;
                   21036:                                $<pn>$->tp = $<pt>2;
                   21037:                        }
                   21038:                |  decl vec     %prec LB        
                   21039:                        {       Vtype($2) = $<pn>1->tp;
                   21040:                                $<pn>1->tp = $<pt>2;
                   21041:                        }
                   21042: /*
                   21043:                |  LP decl RP arg_list
                   21044:                        {
                   21045:                                Freturns($4) = $<pn>2->tp;
                   21046:                                $<pn>2->tp = $<pt>4;
                   21047:                                $$ = $2;
                   21048:                        }
                   21049:                |  LP decl RP vec
                   21050:                        {       Vtype($4) = $<pn>2->tp;
                   21051:                                $<pn>2->tp = $<pt>4;
                   21052:                                $$ = $2;
                   21053:                        }
                   21054: */
                   21055:                |  arg_lp decl RP 
                   21056:                        { 
                   21057:                                $$ = $2; 
                   21058:                                in_arg_list = 0;
                   21059:                                end_al($1,0);
                   21060:                                RESTORE_STATE();
                   21061:                         //POP_SCOPE(); // similar to end_al()
                   21062:                        }
                   21063:                ;
                   21064: 
                   21065: arg_decl       :  ID
                   21066:                        {       $$ = $<pn>1; }
                   21067:                |  ptr qualified_tname  %prec MUL
                   21068:                        {       $$ = Ncopy($<pn>2);
                   21069:                                $<pn>$->n_oper = TNAME;
                   21070:                                $<pn>2->hide();
                   21071:                                $<pn>$->tp = $<pt>1;
                   21072:                        }
                   21073:                |  %prec NO_ID
                   21074:                        {       
                   21075:                                $$ = new name; 
                   21076:                                NOT_EXPECT_ID();
                   21077:                        }
                   21078:                |  ptr arg_decl         %prec MUL
                   21079:                        {       Ptyp($1) = $<pn>2->tp;
                   21080:                                $<pn>2->tp = (Ptype)$1;
                   21081:                                $$ = $2;
                   21082:                        }
                   21083:                |  arg_decl vec         %prec LB
                   21084:                        {       Vtype($2) = $<pn>1->tp;
                   21085:                                $<pn>1->tp = (Ptype)$2;
                   21086:                        }
                   21087:                |  arg_decl arg_list
                   21088:                        {       Freturns($2) = $<pn>1->tp;
                   21089:                                $<pn>1->tp = (Ptype)$2;
                   21090:                        }
                   21091: /*
                   21092:                |  LP arg_decl RP arg_list
                   21093:                        {       Freturns($4) = $<pn>2->tp;
                   21094:                                $<pn>2->tp = (Ptype)$4;
                   21095:                                $$ = $2;
                   21096:                        }
                   21097:                |  LP arg_decl RP vec
                   21098:                        {       Vtype($4) = $<pn>2->tp;
                   21099:                                $<pn>2->tp = (Ptype)$4;
                   21100:                                $$ = $2;
                   21101:                        }
                   21102: */
                   21103:                |  arg_lp arg_decl RP   
                   21104:                        { 
                   21105: // error('d', "arg_lp arg_decl rp in_arg_list: %d", in_arg_list );
                   21106:                                $$ = $2; 
                   21107:                                in_arg_list = 0;
                   21108:                                end_al($1,0);
                   21109:                                RESTORE_STATE();
                   21110:                         //POP_SCOPE(); // similar to end_al()
                   21111:                        }
                   21112:                ;
                   21113: 
                   21114: new_decl       :  %prec NO_ID
                   21115:                        {       $$ = new name; }
                   21116:                |  ptr new_decl         %prec MUL
                   21117:                        {       Ptyp($1) = $<pn>2->tp;
                   21118:                                $<pn>2->tp = (Ptype)$1;
                   21119:                                $$ = $2;
                   21120:                                 NOT_EXPECT_ID();
                   21121:                        }
                   21122:                |  new_decl vec         %prec LB
                   21123:                        {       Vtype($2) = $<pn>1->tp;
                   21124:                                $<pn>1->tp = (Ptype)$2;
                   21125:                        }
                   21126:                ;
                   21127: 
                   21128: cast_decl      :  %prec NO_ID { $$ = new name; }
                   21129:                |  ptr cast_decl                        %prec MUL
                   21130:                        {       Ptyp($1) = $<pn>2->tp;
                   21131:                                $<pn>2->tp = (Ptype)$1;
                   21132:                                $$ = $2;
                   21133:                                NOT_EXPECT_ID();
                   21134:                        }
                   21135:                |  cast_decl vec                        %prec LB
                   21136:                        {       Vtype($2) = $<pn>1->tp;
                   21137:                                $<pn>1->tp = (Ptype)$2;
                   21138:                        }
                   21139:                |  LP cast_decl RP arg_list
                   21140:                        {       Freturns($4) = $<pn>2->tp;
                   21141:                                $<pn>2->tp = $<pt>4;
                   21142:                                $$ = $2;
                   21143:                        }
                   21144:                |  LP cast_decl RP vec
                   21145:                        {       Vtype($4) = $<pn>2->tp;
                   21146:                                $<pn>2->tp = $<pt>4;
                   21147:                                $$ = $2;
                   21148:                        }
                   21149:                ;
                   21150: 
                   21151: c_decl         :  %prec NO_ID
                   21152:                        {       $$ = new name; }
                   21153:                |  ptr c_decl                           %prec MUL
                   21154:                        {       Ptyp($1) = $<pn>2->tp;
                   21155:                                $<pn>2->tp = (Ptype)$1;
                   21156:                                $$ = $2;
                   21157:                        }
                   21158:                ;
                   21159: 
                   21160: 
                   21161: 
                   21162: /***************** statements: returns Pstmt *****************/
                   21163: stmt_list      :  /* empty */
                   21164:                        {
                   21165:                                $$ = 0; 
                   21166:                        }
                   21167:                |  stmt_list TEMPLATE
                   21168:                        {
                   21169:                                error( "ZizedTD must be atG, not local scope" );
                   21170:                                error('i', "cannot recover from previous error" );
                   21171:                        }
                   21172:                |  stmt_list caselab_stmt
                   21173:                        {       
                   21174:                                if ($2)
                   21175:                                        if ($1)
                   21176:                                                $<sl>1->add($<ps>2);
                   21177:                                        else {
                   21178:                                                $<sl>$ =  new slist($<ps>2);
                   21179:                                                stmt_seen = 1;
                   21180:                                        }
                   21181:                        }
                   21182:                ;
                   21183: caselab_stmt   :  caselablist statement
                   21184:                        {
                   21185:                                $$ = $2;
                   21186:                                if ($2) stmt_seen = 1;
                   21187:                        }
                   21188:                ;
                   21189: 
                   21190: caselablist    : /* empty */
                   21191:                        {
                   21192:                                $$ = 0;
                   21193:                                check_decl();
                   21194:                        }
                   21195:                ;
                   21196: 
                   21197: condition      :  LP e RP
                   21198:                        {       $$ = $2;
                   21199:                        /*      if ($<pe>$ == dummy) error("empty condition");*/
                   21200:                                stmt_seen = 1;
                   21201:                        }
                   21202:                ;
                   21203: 
                   21204: block          :  LC
                   21205:                        {//PUSH_BLOCK_SCOPE     
                   21206:                                cd_vec[cdi] = cd;
                   21207:                                stmt_vec[cdi] = stmt_seen;
                   21208:                                tn_vec[cdi] = modified_tn;
                   21209:                                lcl_blk_vec[cdi++] = local_blk;
                   21210:                                lcl_tn_vec[cdi] = local_tn;
                   21211:                                local_blk = 0;
                   21212:                                local_tn = 0;
                   21213:                                cd = 0;
                   21214:                                stmt_seen = 0;
                   21215:                                modified_tn = 0;
                   21216:                        }
                   21217:                        stmt_list RC
                   21218:                        {       Pname n = name_unlist(cd);
                   21219:                                Pstmt ss = stmt_unlist($<sl>3);
                   21220:                                $$ = new block($<l>1,n,ss,$<l>4);
                   21221:                                if ( local_tn ) local_restore();
                   21222:                                if ( local_blk ) local_name();
                   21223:                                if (modified_tn) restore();
                   21224:                                cd = cd_vec[--cdi];
                   21225:                                stmt_seen = stmt_vec[cdi];
                   21226:                                modified_tn = tn_vec[cdi];
                   21227:                                local_tn = lcl_tn_vec[cdi];
                   21228:                                local_blk = lcl_blk_vec[cdi];
                   21229:                                if (cdi < 0) error('i',"block level(%d)",cdi);
                   21230:                                NOT_EXPECT_ID();
                   21231:                         //POP_SCOPE(); // similar to end_al()
                   21232:                        }
                   21233:                |  LC RC
                   21234:                        {       $$ = new block($<l>1,0,0,$<l>2); NOT_EXPECT_ID();}
                   21235:                |  LC error RC
                   21236:                        {       $$ = new block($<l>1,0,0,$<l>3); NOT_EXPECT_ID();}
                   21237:                ;
                   21238: 
                   21239: simple         :  ee
                   21240:                        {       $$ = new estmt(SM,curloc,$<pe>1,0);     }
                   21241:                |  BREAK
                   21242:                        {       $$ = new stmt(BREAK,$<l>1,0); }
                   21243:                |  CONTINUE
                   21244:                        {       $$ = new stmt(CONTINUE,$<l>1,0); }
                   21245:                |  GOTO ID
                   21246:                        {       $$ = new lstmt(GOTO,$<l>1,$<pn>2,0); }
                   21247:                |  DO { stmt_seen=1; } caselab_stmt WHILE condition
                   21248:                        {       $$ = new estmt(DO,$<l>1,$<pe>5,$<ps>3); }
                   21249:                |  ASM LP STRING RP
                   21250:                        {       
                   21251:                                if (stmt_seen)
                   21252:                                        $$ = new estmt(ASM,curloc,(Pexpr)$<s>3,0);
                   21253:                                else {
                   21254:                                        Pname n = new name(make_name('A'));
                   21255:                                        n->tp = new basetype(ASM,(Pname)$<s>3);
                   21256:                                        if (cd)
                   21257:                                                cd->add_list(n);
                   21258:                                        else
                   21259:                                                cd = new nlist(n);
                   21260:                                        $$ = 0;
                   21261:                                }
                   21262:                        }
                   21263:                ;
                   21264: 
                   21265: sm             : {
                   21266:                        if ( NEXTTOK() != SM ) {
                   21267:                                error("`;' missing afterS");
                   21268:                                la_backup(yychar,yylval);
                   21269:                                yychar = SM;
                   21270:                        }
                   21271:                  } SM
                   21272:                ;
                   21273: 
                   21274: statement      :  simple sm
                   21275:                |  SM
                   21276:                        {       $$ = new estmt(SM,$<l>1,dummy,0); }
                   21277:                |  RETURN e SM
                   21278:                        {       $$ = new estmt(RETURN,$<l>1,$<pe>2,0); }
                   21279:                |  TYPE STRING block
                   21280:                        {
                   21281:                                error("local linkage specification");
                   21282:                                $$ = $<pn>3;
                   21283:                        }
                   21284:                |  data_dcl
                   21285:                        {       Pname n = $<pn>1;
                   21286:                                if (n) {
                   21287: //error('d',"adding local dcl of%n%t ll %d in_typedef%t",n,n->tp,n->lex_level,in_typedef);
                   21288:                                        if (stmt_seen) {
                   21289:                                                $$ = new block(n->where,n,0);
                   21290:                                                $<ps>$->base = DCL;
                   21291:                                        }
                   21292:                                        else {
                   21293:                                                if (cd)
                   21294:                                                        cd->add_list(n);
                   21295:                                                else
                   21296:                                                        cd = new nlist(n);
                   21297:                                                $$ = 0;
                   21298:                                        }
                   21299:                                } // if n
                   21300:                        }
                   21301:                |  att_fct_def
                   21302:                        {
                   21303:                                Pname n = $<pn>1;
                   21304:                                error(&n->where,"%n's definition is nested (did you forget a ``}''?)",n);
                   21305:                                if (cd)
                   21306:                                        cd->add_list(n);
                   21307:                                else
                   21308:                                        cd = new nlist(n);
                   21309:                                $$ = 0;
                   21310:                        }
                   21311:                |  block
                   21312:                |  IF condition caselab_stmt
                   21313:                        {       $$ = new ifstmt($<l>1,$<pe>2,$<ps>3,0); }
                   21314:                |  IF condition caselab_stmt ELSE caselab_stmt
                   21315:                        {       $$ = new ifstmt($<l>1,$<pe>2,$<ps>3,$<ps>5); }
                   21316:                |  WHILE condition caselab_stmt
                   21317:                        {       $$ = new estmt(WHILE,$<l>1,$<pe>2,$<ps>3); }
                   21318:                |  FOR LP { stmt_seen=1; } caselab_stmt e SM e RP caselab_stmt
                   21319:                        {       $$ = new forstmt($<l>1,$<ps>4,$<pe>5,$<pe>7,$<ps>9); }
                   21320:                |  SWITCH condition caselab_stmt
                   21321:                        {       $$ = new estmt(SWITCH,$<l>1,$<pe>2,$<ps>3); }
                   21322:                |  ID COLON { $$ = $1; stmt_seen=1; } caselab_stmt
                   21323:                        {       Pname n = $<pn>3;
                   21324:                                $$ = new lstmt(LABEL,n->where,n,$<ps>4);
                   21325:                        }
                   21326:                |  TNAME COLON { $$ = new name($<pn>1->string); stmt_seen=1; } caselab_stmt
                   21327:                        {       Pname n = $<pn>3;
                   21328:                                $$ = new lstmt(LABEL,n->where,n,$<ps>4);
                   21329:                        }
                   21330:                |  CASE { stmt_seen=1; } e COLON caselab_stmt
                   21331:                        {       if ($<pe>3 == dummy) error("empty case label");
                   21332:                                $$ = new estmt(CASE,$<l>1,$<pe>3,$<ps>5);
                   21333:                        }
                   21334:                |  DEFAULT COLON { stmt_seen=1; } caselab_stmt
                   21335:                        {       $$ = new stmt(DEFAULT,$<l>1,$<ps>4); }
                   21336:                ;
                   21337: 
                   21338: 
                   21339: 
                   21340: /********************* expressions: returns Pexpr **************/
                   21341: elist          : ex_list
                   21342:                        {       Pexpr e = expr_unlist($<el>1);
                   21343:                                while (e && e->e1==dummy) {
                   21344:                                        register Pexpr ee2 = e->e2;
                   21345:                                        if (ee2) error("EX inEL");
                   21346:                                        delete e;
                   21347:                                        e = ee2;
                   21348:                                }
                   21349:                                $$ = e;
                   21350:                        }
                   21351:                ;
                   21352: 
                   21353: ex_list                :  initializer          %prec CM
                   21354:                        {       $<el>$ = new elist(new expr(ELIST,$<pe>1,0)); }
                   21355:                |  ex_list CM initializer
                   21356:                        {       $<el>1->add(new expr(ELIST,$<pe>3,0)); }
                   21357:                ;
                   21358: 
                   21359: initializer    :  e                            %prec CM
                   21360:                |  LC elist RC
                   21361:                        {
                   21362:                                if ( in_arg_list ) 
                   21363:                                                error( "syntax error: IrL not permitted in AL" );
                   21364:                                else if ( in_binit_list )
                   21365:                                        error( "syntax error: IrL not permitted inMIr" );
                   21366:                                else 
                   21367:                                        init_seen = 1;
                   21368:                                Pexpr e;
                   21369:                                if ($2)
                   21370:                                        e = $<pe>2;
                   21371:                                else
                   21372:                                        e = new expr(ELIST,dummy,0);
                   21373:                                $$ = new expr(ILIST,e,0);
                   21374:                        }
                   21375:                ;
                   21376: 
                   21377: ee             :  ee ASSIGN ee
                   21378:                        {       bbinop: $$ = new expr($<t>2,$<pe>1,$<pe>3); }
                   21379:                |  ee PLUS ee   {       goto bbinop; }
                   21380:                |  ee MINUS ee  {       goto bbinop; }
                   21381:                |  ee MUL ee    {       goto bbinop; }
                   21382:                |  ee AND ee    {       goto bbinop; }
                   21383:                |  ee OR ee     {       goto bbinop; }
                   21384:                |  ee ER ee     {       goto bbinop; }
                   21385:                |  ee SHIFTOP ee        {       goto bbinop; }
                   21386:                |  ee EQUOP ee  {       goto bbinop; }
                   21387:                |  ee DIVOP ee  {       goto bbinop; }
                   21388:                |  ee RELOP ee  {       goto bbinop; }
                   21389:                |  ee GT ee     {       goto bbinop; }
                   21390:                |  ee LT ee     {       goto bbinop; }
                   21391:                |  ee ANDAND ee {       goto bbinop; }
                   21392:                |  ee OROR ee   {       goto bbinop; }
                   21393:                |  ee ASOP ee   {       goto bbinop; }
                   21394:                |  ee CM ee     {       goto bbinop; }
                   21395:                |  ee QUEST ee COLON ee
                   21396:                        {       $$ = new qexpr($<pe>1,$<pe>3,$<pe>5); }
                   21397:                |  DELETE term 
                   21398:                        { $$ = new expr(DELETE,$<pe>2,0); }
                   21399:                |  DELETE LB e RB term
                   21400:                        {
                   21401:                                if($<pe>3 != dummy) {
                   21402:                                        if ( warning_opt || strict_opt )
                   21403:                                                error(strict_opt?0:'w',"v in `delete[v]' is redundant; use `delete[] instead (anachronism)");
                   21404:                                }
                   21405:                                $$ = new expr(DELETE,$<pe>5,$<pe>3);
                   21406:                        }
                   21407:                |  MEM DELETE term 
                   21408:                        {       $$ = new expr(GDELETE,$<pe>3,0); }
                   21409:                |  MEM DELETE LB e RB term
                   21410:                        {
                   21411:                                if($<pe>4 != dummy) { 
                   21412:                                        if ( warning_opt || strict_opt )
                   21413:                                                error(strict_opt?0:'w',"v in `::delete[v]' is redundant; use `::delete[] instead (anachronism)");
                   21414:                                }
                   21415:                                $$ = new expr(DELETE,$<pe>6,$<pe>4);
                   21416:                        }
                   21417:                |  term
                   21418:                ; 
                   21419: 
                   21420: e              :  e ASSIGN e
                   21421:                        {       binop:  $$ = new expr($<t>2,$<pe>1,$<pe>3); }
                   21422:                |  e PLUS e     {       goto binop; }
                   21423:                |  e MINUS e    {       goto binop; }
                   21424:                |  e MUL e      {       goto binop; }
                   21425:                |  e AND e      {       goto binop; }
                   21426:                |  e OR e       {       goto binop; }
                   21427:                |  e ER e       {       goto binop; }
                   21428:                |  e SHIFTOP e  {       goto binop; }
                   21429:                |  e EQUOP e    {       goto binop; }
                   21430:                |  e DIVOP e    {       goto binop; }
                   21431:                |  e RELOP e    {       goto binop; }
                   21432:                |  e LT e       {       goto binop; }
                   21433:                |  e GT e       {       goto binop; }
                   21434:                |  e ANDAND e   {       goto binop; }
                   21435:                |  e OROR e     {       goto binop; }
                   21436:                |  e ASOP e     {       goto binop; }
                   21437:                |  e CM e       {       goto binop; }
                   21438:                |  e QUEST e COLON e
                   21439:                        {       $$ = new qexpr($<pe>1,$<pe>3,$<pe>5); }
                   21440:                |  DELETE term 
                   21441:                        {       $$ = new expr(DELETE,$<pe>2,0); }
                   21442:                |  DELETE LB e RB term
                   21443:                        {
                   21444:                                if($<pe>3 != dummy) {
                   21445:                                        if ( warning_opt || strict_opt )
                   21446:                                                error(strict_opt?0:'w',"v in `delete[v]' is redundant; use `delete[] instead (anachronism)");
                   21447:                                }
                   21448:                                $$ = new expr(DELETE,$<pe>5,$<pe>3);
                   21449:                        }
                   21450:                |  MEM DELETE term 
                   21451:                        {       $$ = new expr(GDELETE,$<pe>3,0); }
                   21452:                |  MEM DELETE LB e RB term
                   21453:                        {
                   21454:                                if($<pe>4 != dummy) {
                   21455:                                        if ( warning_opt || strict_opt )
                   21456:                                                error(strict_opt?0:'w',"v in `::delete[v]' is redundant; use `::delete[] instead (anachronism)");
                   21457:                                }
                   21458:                                $$ = new expr(DELETE,$<pe>6,$<pe>4);
                   21459:                        }
                   21460:                |  term { 
                   21461:                        init_seen = 0; 
                   21462:                        } 
                   21463:                |  %prec NO_EXPR
                   21464:                        {       $$ = dummy; }
                   21465:                ; 
                   21466: 
                   21467: term           :  NEW cast_type        { goto new1; }
                   21468:                |  NEW new_type
                   21469:                        {       new1:
                   21470:                                Ptype t = $<pn>2->tp;
                   21471:                                $$ = new texpr(NEW,t,0);
                   21472:                        }
                   21473:                |  MEM NEW cast_type    { goto new3; }
                   21474:                |  MEM NEW new_type
                   21475:                        {       new3:
                   21476:                                Ptype t = $<pn>3->tp;
                   21477:                                $$ = new texpr(GNEW,t,0);
                   21478:                        }
                   21479:                |  term ICOP
                   21480:                        {       $$ = new expr($<t>2,$<pe>1,0); }
                   21481:                |  cast_type term %prec ICOP
                   21482:                        {       $$ = new texpr(CAST,$<pn>1->tp,$<pe>2); }
                   21483:                |  MUL term
                   21484:                        {       $$ = new expr(DEREF,$<pe>2,0); }
                   21485:                |  AND term
                   21486:                        {       $$ = new expr(ADDROF,0,$<pe>2); }
                   21487:                |  MINUS term
                   21488:                        {       $$ = new expr(UMINUS,0,$<pe>2); }
                   21489:                |  PLUS term
                   21490:                        {       $$ = new expr(UPLUS,0,$<pe>2); }
                   21491:                |  NOT term
                   21492:                        {       $$ = new expr(NOT,0,$<pe>2); }
                   21493:                |  COMPL term
                   21494:                        {       $$ = new expr(COMPL,0,$<pe>2); }
                   21495:                |  ICOP term
                   21496:                        {       $$ = new expr($<t>1,0,$<pe>2); }
                   21497:                |  SIZEOF term
                   21498:                        {       
                   21499:                                $$ = new texpr(SIZEOF,0,$<pe>2); 
                   21500:                                in_sizeof = 0;
                   21501:                        }
                   21502:                |  SIZEOF cast_type %prec SIZEOF
                   21503:                        {       
                   21504:                                $$ = new texpr(SIZEOF,$<pn>2->tp,0); 
                   21505:                                in_sizeof = 0;
                   21506:                        }
                   21507:                |  term LB e RB
                   21508:                        {       $$ = new expr(DEREF,$<pe>1,$<pe>3); }
                   21509:                |  term REF prim
                   21510:                        {       $$ = new ref(REF,$<pe>1,$<pn>3); }
                   21511:                |  term REFMUL term
                   21512:                        {       $$ = new expr($<t>2,$<pe>1,$<pe>3); }
                   21513:                |  term REF qualified_tname
                   21514:                        {       $$ = new ref(REF,$<pe>1,Ncopy($<pn>3)); }
                   21515:                |  term DOT prim
                   21516:                        {       $$ = new ref(DOT,$<pe>1,$<pn>3); }
                   21517:                |  term DOT qualified_tname
                   21518:                        {       $$ = new ref(DOT,$<pe>1,Ncopy($<pn>3)); }
                   21519:                |  prim
                   21520:                |  term_elist 
                   21521:                        {
                   21522:                        if ( init_seen )
                   21523:                                error( "syntax error:IrL illegal within ()");
                   21524:                        }
                   21525: 
                   21526:                |  term_lp e RP
                   21527:                        {
                   21528:                                if ( $2 == dummy )
                   21529:                                        error("syntax error: nullE");
                   21530:                                $$ = $2;
                   21531:                        }
                   21532:                |  ZERO
                   21533:                        {       $$ = zero; }
                   21534:                |  ICON
                   21535:                        {       $$ = new expr(ICON,0,0);
                   21536:                                $<pe>$->string = copy_if_need_be($<s>1);
                   21537:                        }
                   21538:                |  FCON
                   21539:                        {       $$ = new expr(FCON,0,0);
                   21540:                                $<pe>$->string = copy_if_need_be($<s>1);
                   21541:                        }
                   21542:                |  STRING
                   21543:                        {       $$ = new expr(STRING,0,0);
                   21544:                                $<pe>$->string = copy_if_need_be($<s>1);
                   21545:                        }
                   21546:                |  CCON
                   21547:                        {       $$ = new expr(CCON,0,0);
                   21548:                                $<pe>$->string = copy_if_need_be($<s>1);
                   21549:                        }
                   21550:                |  THIS
                   21551:                        {       $$ = new expr(THIS,0,0); }
                   21552:                ;
                   21553: 
                   21554: term_elist     : TYPE LP elist RP
                   21555:                        {       $$ = new texpr(VALUE,tok_to_type($<t>1),$<pe>3); }
                   21556: /*
                   21557:                |  qualified_tname LP elist RP
                   21558: */
                   21559:                |  tname LP elist RP
                   21560:                        {       $$ = new texpr(VALUE,$<pn>1->tp,$<pe>3); }
                   21561:                 |  NEW term_lp elist RP cast_type    { goto new2; }
                   21562:                 |  NEW term_lp elist RP new_type     /* allow separate allocation */
                   21563:                        {       new2:
                   21564:                                Ptype t = $<pn>5->tp;
                   21565:                                $$=new texpr(NEW,t,0);
                   21566:                                $<pe>$->e2 = $<pe>3;
                   21567:                        }
                   21568:                |  MEM NEW term_lp elist RP cast_type   { goto new4; }
                   21569:                |  MEM NEW term_lp elist RP new_type    /* allow separate allocation */
                   21570:                        {       new4:
                   21571:                                Ptype t = $<pn>6->tp;
                   21572:                                $$ = new texpr(GNEW,t,0);
                   21573:                                $<pe>$->e2 = $<pe>4;
                   21574:                        }
                   21575:                |  term LP elist RP
                   21576:                        {       
                   21577:                                Pexpr ee = $<pe>3;
                   21578:                                Pexpr e = $<pe>1;
                   21579:                                if (e->base==NEW || e->base==GNEW)
                   21580:                                        e->e1 = ee;
                   21581:                                else
                   21582:                                        $$ = new call(e,ee);
                   21583:                        }
                   21584: 
                   21585:                ;
                   21586: 
                   21587: ptname         : PTNAME lt temp_inst_parms  gt
                   21588:                  {
                   21589:                    $<pn>$ =parametrized_typename($<pn>1,(expr_unlist($<el>3))); 
                   21590:                 }
                   21591:                ;
                   21592: 
                   21593: tscope         :  TSCOPE
                   21594:                        {       
                   21595:                                $<pn>$ = $<pn>1; 
                   21596:                                curr_scope = $<pn>1;
                   21597:                        }
                   21598:                        |  MEM { $<pn>$ = sta_name; }
                   21599:                |  ptname TSCOPE { $<pn>$ = $<pn>1; }
                   21600:                ;
                   21601: 
                   21602: 
                   21603: prim           :  ID
                   21604:                        {       $$ = $<pn>1; }
                   21605:        /*XXX*/ |  tn_list ID
                   21606:                        {       $$ = Ncopy($<pn>2);
                   21607:                                $<pn>$->n_qualifier = $<pn>1;
                   21608:                        }
                   21609:                |  OPERATOR oper
                   21610:                        {       $$ = new name(oper_name($2));
                   21611:                                $<pn>$->n_oper = $<t>2;
                   21612:                        }
                   21613:                |  tn_list OPERATOR oper
                   21614:                        {       $$ = new name(oper_name($3));
                   21615:                                $<pn>$->n_oper = $<t>3;
                   21616:                                $<pn>$->n_qualifier = $<pn>1;
                   21617:                        }
                   21618:                |  OPERATOR c_type
                   21619:                        {       $$ = $2;
                   21620:                                sig_name($<pn>$);
                   21621:                        }
                   21622:                |  tn_list OPERATOR c_type
                   21623:                        {       $$ = $3;
                   21624:                                sig_name($<pn>$);
                   21625:                                $<pn>$->n_qualifier = $<pn>1;
                   21626:                        }
                   21627:                |  tn_list COMPL tag    /* allow explicit call of destructor */
                   21628:                        {       
                   21629:                                if (strcmp($<pn>1->string,$<pn>3->string)) error("syntax error: inconsistent destructor notation");
                   21630:                                $$ = new name(oper_name(DTOR));
                   21631:                                $<pn>$->n_oper = DTOR;
                   21632:                                $<pn>$->n_qualifier = $<pn>1;
                   21633:                        }
                   21634:                ;
                   21635: 
                   21636: 
                   21637: 
                   21638: /****************** abstract types (return type Pname) *************/
                   21639: cast_type      :  term_lp type cast_decl RP 
                   21640:                        { $$ = Ncast($2,$<pn>3); }
                   21641:                ;
                   21642: 
                   21643: term_lp                :  LP { check_cast(); }
                   21644:                ;
                   21645: 
                   21646: c_tp           :  TYPE 
                   21647:                        {
                   21648:                                TOK t = $<t>1;
                   21649: 
                   21650:                                switch (t) {
                   21651:                                case FRIEND:
                   21652:                                case OVERLOAD:
                   21653:                                case REGISTER:
                   21654:                                case STATIC:
                   21655:                                case EXTERN:
                   21656:                                case AUTO:
                   21657:                                case VIRTUAL:
                   21658:                                        error("%k in operatorT",t);
                   21659:                                        t = INT;
                   21660:                                        
                   21661:                                }
                   21662: 
                   21663:                                $$ = new basetype(t,0);
                   21664: 
                   21665:                        }
                   21666:                |  tname        { $$ = new basetype(TYPE,$<pn>1); }
                   21667:                |  c_tp TYPE            
                   21668:                        { 
                   21669:                                if ( DECL_TYPE != -1 ) {
                   21670:                                        switch ($<pb>1->base) { Pbase bt;
                   21671:                                        case COBJ: case EOBJ:
                   21672:                                                bt = new basetype(0,0);
                   21673:                                                *bt = *$<pb>1;
                   21674:                                                DEL($<pb>1);
                   21675:                                                $<pb>1 = bt;
                   21676:                                        }
                   21677:                                        $$ = $<pb>1->type_adj($<t>2); 
                   21678:                                }
                   21679:                                DECL_TYPE = 0;
                   21680:                        }
                   21681:                |  c_tp tname
                   21682:                        { 
                   21683:                                if ( DECL_TYPE != -1 ) 
                   21684:                                        $$ = $<pb>1->name_adj($<pn>2);
                   21685:                                DECL_TYPE = 0;
                   21686:                        }
                   21687:                ;
                   21688: 
                   21689: c_type         :  c_tp c_decl  { $$ = Ncast($1,$<pn>2); }
                   21690:                ;
                   21691: 
                   21692: new_type       :  type new_decl        { $$ = Ncast($1,$<pn>2); };
                   21693: 
                   21694: arg_type       :  type arg_decl
                   21695:                        {       
                   21696:                          //      ENTER_NAME($<pn>2);
                   21697:                                $$ = Ndata($1,$<pn>2); 
                   21698:                        }
                   21699:                 |  type arg_decl ASSIGN
                   21700:                         {
                   21701:                         //      ENTER_NAME($<pn>2);
                   21702:                         }
                   21703:                    initializer
                   21704:                         {       $$ = Ndata($1,$<pn>2);
                   21705:                                 $<pn>$->n_initializer = $<pe>5;
                   21706:                         }
                   21707:                 ;
                   21708: 
                   21709: arg_lp         :  LP 
                   21710:                        {//PUSH_ARG_SCOPE 
                   21711:                                SAVE_STATE();
                   21712:                                check_decl(); 
                   21713:                                in_arg_list=1; 
                   21714:                                $$ = modified_tn;
                   21715:                                modified_tn = 0;
                   21716:                        }
                   21717:                ;
                   21718: 
                   21719: arg_list       :  arg_lp arg_type_list ellipsis_opt RP fct_attributes
                   21720:                    {
                   21721:                        $$ = new fct(0,name_unlist($<nl>2),$<t>3); 
                   21722:                        if ( NEXTTOK() != COLON ) in_arg_list=0;
                   21723:                        //in_arg_list=0;
                   21724:                        Pfct($<pt>$)->f_const = ($<i>5 & 1);
                   21725:                        if ( parsing_class_members
                   21726:                        ||   (NEXTTOK()!=LC && yychar!=COLON)) {
                   21727:                                end_al($1,1);
                   21728:                         //POP_SCOPE(); // similar to end_al()
                   21729:                        } else
                   21730:                                end_al($1,0);
                   21731:                        RESTORE_STATE();
                   21732:                    }
                   21733:                ;
                   21734: 
                   21735: arg_type_list  :  arg_type_list CM at
                   21736:                        {
                   21737:                                if ($3)
                   21738:                                        if ($1)
                   21739:                                                $<nl>1->add($<pn>3);
                   21740:                                        else {
                   21741:                                                error("AD syntax");
                   21742:                                                $<nl>$ = new nlist($<pn>3); 
                   21743:                                        }
                   21744:                                else
                   21745:                                        error("AD syntax");
                   21746:                        }
                   21747:                |  at   %prec CM
                   21748:                        {
                   21749:                                if ($1) $<nl>$ = new nlist($<pn>1); 
                   21750:                        }
                   21751:                ;
                   21752: 
                   21753: at             :  arg_type
                   21754:                |  %prec EMPTY  {       $$ = 0; }
                   21755:                ;
                   21756: 
                   21757: ellipsis_opt   :  /* empty */
                   21758:                    {   $$ = 1; }
                   21759:                |  ELLIPSIS
                   21760:                    {   $$ = ELLIPSIS; }
                   21761:                |  CM ELLIPSIS
                   21762:                    {   $$ = ELLIPSIS; }
                   21763:                ;
                   21764: 
                   21765: ptr            :  MUL %prec NO_ID
                   21766:                        {
                   21767:                        $$ = new ptr(PTR,0); 
                   21768:                        EXPECT_ID();
                   21769:                        }
                   21770:                |  AND %prec NO_ID
                   21771:                        {
                   21772:                        $$ = new ptr(RPTR,0); 
                   21773:                        EXPECT_ID();
                   21774:                        }
                   21775:                |  MUL TYPE %prec NO_ID
                   21776:                        {       $$ = doptr(PTR,$<t>2); }
                   21777:                |  ptr TYPE %prec NO_ID
                   21778:                        {       
                   21779:                                switch ( $<t>2 ) {
                   21780:                                case CONST:
                   21781:                                      $<pp>1->rdo = 1; break;
                   21782:                                case VOLATILE:
                   21783:                                     error('w',"\"volatile\" not implemented (ignored)");
                   21784:                                     break;
                   21785:                                default:
                   21786:                                    error( "syntax error: *%k", $<t>2 );
                   21787:                                }
                   21788:                                $$ = $<pp>1; 
                   21789:                        }
                   21790:                |  AND TYPE %prec NO_ID
                   21791:                        {       $$ = doptr(RPTR,$<t>2); }
                   21792:                |  ptname MEMPTR %prec NO_ID
                   21793:                        {       goto memptr1;  }
                   21794:                |  MEMPTR %prec NO_ID
                   21795:                        {
                   21796:                        memptr1:
                   21797:                        $$ = new ptr(PTR,0);
                   21798:                        $<pp>$->memof = Pclass(Pbase($<pn>1->tp)->b_name->tp);
                   21799:                        EXPECT_ID();
                   21800:                        }
                   21801:                |  ptname MEMPTR TYPE %prec NO_ID
                   21802:                        {       
                   21803:                                $<t>2 = $<t>3;
                   21804:                                goto memptr2;  
                   21805:                        }
                   21806:                |  MEMPTR TYPE %prec NO_ID
                   21807:                        {       
                   21808:                                memptr2:
                   21809:                                $$ = doptr(PTR,$<t>2);
                   21810:                                $<pp>$->memof = Pclass(Pbase($<pn>1->tp)->b_name->tp);
                   21811:                        }
                   21812:                ;
                   21813: 
                   21814: vec            :  LB e RB              { $$ = new vec(0,$<pe>2!=dummy?$<pe>2:0 ); }
                   21815:                |  NOT %prec LB         { $$ = new vec(0,0); }
                   21816:                ;
                   21817: 
                   21818: %%
                   21819: 
                   21820: static void
                   21821: check_tag()
                   21822: /*
                   21823:         Allow the case of inline/virtual/overload as 
                   21824:         modifiers of return type of form struct/class/union x foo() 
                   21825:         SM, COLON, LC ==> real class declaration, not return type
                   21826: */
                   21827: {
                   21828:        switch ( NEXTTOK() ) {
                   21829:        case SM: case COLON: case LC:
                   21830:                declTag = 1;
                   21831:                break;
                   21832:        default:
                   21833:                declTag = 0;
                   21834:                break;
                   21835:         }
                   21836: }
                   21837: 
                   21838: static void
                   21839: end_al( Plist mtn, int rst )
                   21840: // unhide type names hidden by arg names
                   21841: // mtn == saved modified_tn
                   21842: {
                   21843:        if ( rst == 0 ) {
                   21844:                // not really an arg list, or we are entering a function def
                   21845:                // merge modified_tn and don't restore
                   21846:                if ( modified_tn == 0 ) modified_tn = mtn;
                   21847:                else {
                   21848:                        for ( Plist l = modified_tn; l->l; l = l->l ) ;
                   21849:                        l->l = mtn;
                   21850:                }
                   21851:        } else {
                   21852:                restore();
                   21853:                modified_tn = mtn;
                   21854:        }
                   21855: }
                   21856: static void
                   21857: arg_redec( Pname fn )
                   21858: {
                   21859:        if ( fn==0 || fn->tp->base != FCT )
                   21860:                error('i',"bad inline rewrite!");
                   21861:        Pname al = Pfct(fn->tp)->argtype;
                   21862:        Pname n = 0;
                   21863:        for ( ;  al;  al = al->n_list ) {
                   21864:                DB( if(Ydebug>=1)error('d',"arg_redec:  %n  %d",al,al->lex_level); );
                   21865:                // nested function args should have lex_level >= 1
                   21866:                if ( al->lex_level==1 && (n=ktbl->look(al->string,0)) )
                   21867:                        n->hide();
                   21868:                else if ( al->lex_level>1 && (n=ktbl->look(al->string,LOCAL)) )
                   21869:                        n->hide();
                   21870:                DB( if(Ydebug>=1)error('d',"   %n",n); );
                   21871:        }
                   21872: }
                   21873: 
                   21874: 
                   21875: 0707071010112046011004440001630000160000010211100466055415400000700000014643hash.c/* ident "@(#)ctrans:src/hash.c     1.2" */
                   21876: /*
                   21877:     $Header: /usr2/odi/libmisc/RCS/hash.C,v 1.11 90/03/22 09:24:07 sam Exp $
                   21878: 
                   21879:     Copyright (c) 1989 by Object Design, Inc., Burlington, Mass.
                   21880:     All rights reserved.
                   21881: 
                   21882: */
                   21883: 
                   21884: #include <stdio.h>
                   21885: #include "hash.h" 
                   21886: #include <osfcn.h>
                   21887: 
                   21888: #define EMPTY   0
                   21889: #define VALID   1
                   21890: #define DELETED 2
                   21891: 
                   21892: void default_Hash_error_handler(const char* msg)
                   21893: {
                   21894:   fprintf(stderr, "Fatal Hash error: %s\n", msg) ;
                   21895:   exit(1) ;
                   21896: }
                   21897: 
                   21898: Error_Proc Hash_error_handler = default_Hash_error_handler ;
                   21899: 
                   21900: Error_Proc set_Hash_error_handler(Error_Proc f)
                   21901: {
                   21902:   Error_Proc old = Hash_error_handler ;
                   21903:   Hash_error_handler = f ;
                   21904:   return old ;
                   21905: }
                   21906: 
                   21907: void Hash::error(const char* msg)
                   21908: {
                   21909:   (*Hash_error_handler)(msg) ;
                   21910: }
                   21911: 
                   21912: Hash::Hash(int sz= DEFAULT_INITIAL_HASH_SIZE)
                   21913: {
                   21914:   tab = new HashTableEntry[size = sz] ;
                   21915:   for (int i = 0; i < size; ++i) tab[i].status = EMPTY ;
                   21916:   entry_count = 0 ;
                   21917: }
                   21918: 
                   21919: Hash::Hash(Hash& a)
                   21920: {
                   21921:   tab = new HashTableEntry[size = a.size] ;
                   21922: 
                   21923:   key_hash_function = a.key_hash_function ;
                   21924:   key_key_equality_function = a.key_key_equality_function ;
                   21925: 
                   21926:   for (int i = 0; i < size; ++i) tab[i].status = EMPTY ;
                   21927:   entry_count = 0 ;
                   21928:   for (HashWalker p(a); p; p.advance())
                   21929:     (*this)[p.key()] = p.get() ;
                   21930: }
                   21931: 
                   21932: Hash& Hash::operator = (Hash& a)
                   21933: {
                   21934:   if (a.tab != tab)
                   21935:   {
                   21936:     clear() ;
                   21937:     delete [size] tab ;
                   21938:     tab = new HashTableEntry[size = a.size] ;
                   21939:     for (int i = 0; i < size; ++i) tab[i].status = EMPTY ;
                   21940:     entry_count = 0 ;
                   21941:     for (HashWalker p(a); p; p.advance())
                   21942:       (*this)[p.key()] = p.get() ;
                   21943:   }
                   21944:   return *this ;
                   21945: }
                   21946: 
                   21947: /* 
                   21948:  * hashing method: double hash based on high bits of hash fct,
                   21949:  * followed by linear probe. Can't do too much better if Assoc
                   21950:  * sizes not constrained to be prime.
                   21951: */
                   21952: 
                   21953: 
                   21954: static inline doublehashinc(unsigned int h, int s)
                   21955: {
                   21956:   return ((h / s) % s) >> 1 ;
                   21957: }
                   21958: 
                   21959: // IWBNI we knew whether we were being called as an lvalue or rvalue.
                   21960: // If the former, then we wouldn't have to scan through the whole
                   21961: // table just to tell if we should rehash or not.  Sigh.
                   21962: int& Hash::operator [](int key)
                   21963: {
                   21964:   unsigned int hashval = key_hash(key) ;
                   21965:   while (1)
                   21966:     {
                   21967:       int bestspot = -1 ;
                   21968:       int h = hashval % size ;
                   21969:       for (int i = 0; i <= size; ++i)
                   21970:        {
                   21971:          if (tab[h].status == EMPTY)
                   21972:            {
                   21973:              // resize if the hash table is more than 87.5% full
                   21974:              if (entry_count > ((size>>1)+(size>>2)+(size>>3)))
                   21975:                // resize and insert again
                   21976:                break ;
                   21977:              if (bestspot < 0) bestspot = h ;
                   21978:              tab[bestspot].key = key ;
                   21979:              tab[bestspot].status = VALID ;
                   21980:              ++entry_count ;
                   21981:              return tab[bestspot].cont ;
                   21982:            }
                   21983:          else if (tab[h].status == DELETED)
                   21984:            {
                   21985:              if (bestspot < 0) bestspot = h ;
                   21986:            }
                   21987:          else if (key_key_eq(tab[h].key, key))
                   21988:            return tab[h].cont ;
                   21989:          if (i == 0)
                   21990:            h = (h + doublehashinc(hashval, size)) % size ;
                   21991:          else if (++h >= size)
                   21992:            h -= size ;
                   21993:        }
                   21994:       resize(size << 1)  ;
                   21995:     }
                   21996: }
                   21997: 
                   21998: /* This seems convoluted, but it does whatever you want without
                   21999:    redundant probing of the hash table. */
                   22000: 
                   22001: void Hash::action (int key, int val, insert_action what,
                   22002:                   int& found, int& old_val)
                   22003: {
                   22004:   unsigned int hashval = key_hash(key) ;
                   22005:   while (1)
                   22006:     {
                   22007:       int bestspot = -1 ;
                   22008:       int h = hashval % size ;
                   22009:       for (int i = 0; i <= size; ++i)
                   22010:        {
                   22011:          if (tab[h].status == EMPTY)
                   22012:            {
                   22013:              // resize if the hash table is more than 87.5% full
                   22014:              if (entry_count > ((size>>1)+(size>>2)+(size>>3)))
                   22015:                // resize and insert again
                   22016:                break ;
                   22017:              if (bestspot < 0) bestspot = h ;
                   22018:              found = 0;
                   22019:              if(what != probe) {
                   22020:                tab[bestspot].key = key ;
                   22021:                tab[bestspot].status = VALID ;
                   22022:                ++entry_count ;
                   22023:                tab[bestspot].cont = val;
                   22024:              } 
                   22025:              return;
                   22026:            }
                   22027:          else if (tab[h].status == DELETED)
                   22028:            {
                   22029:              if (bestspot < 0) bestspot = h ;
                   22030:            }
                   22031:          else if (key_key_eq(tab[h].key, key)) {
                   22032:            found = 1;
                   22033:            old_val = tab[h].cont;
                   22034:            if(what == replace) 
                   22035:              tab[h].cont = val;
                   22036:            return;
                   22037:          }
                   22038:          if (i == 0)
                   22039:            h = (h + doublehashinc(hashval, size)) % size ;
                   22040:          else if (++h >= size)
                   22041:            h -= size ;
                   22042:        }
                   22043:       resize(size << 1)  ;
                   22044:     }
                   22045: }
                   22046: 
                   22047: int Hash::contains(int key)
                   22048: {
                   22049:   unsigned int hashval = key_hash(key) ;
                   22050:   int h = hashval % size ;
                   22051:   for (int i = 0; i <= size; ++i)
                   22052:   {
                   22053:     if (tab[h].status == EMPTY)
                   22054:       return 0 ;
                   22055:     else if (tab[h].status == VALID && key_key_eq(tab[h].key, key))
                   22056:       return 1 ;
                   22057:     if (i == 0)
                   22058:       h = (h + doublehashinc(hashval, size)) % size ;
                   22059:     else if (++h >= size)
                   22060:       h -= size ;
                   22061:   }
                   22062:   return 0 ;
                   22063: }
                   22064: 
                   22065: int Hash::del(int key)
                   22066: {
                   22067:   unsigned int hashval = key_hash(key) ;
                   22068:   int h = hashval % size ;
                   22069:   for (int i = 0; i <= size; ++i)
                   22070:   {
                   22071:     if (tab[h].status == EMPTY)
                   22072:       return 0 ;
                   22073:     else if (tab[h].status == VALID && key_key_eq(tab[h].key, key))
                   22074:     {
                   22075:       tab[h].status = DELETED ;
                   22076:       --entry_count ;
                   22077:       return 1 ;
                   22078:     }
                   22079:     if (i == 0)
                   22080:       h = (h + doublehashinc(hashval, size)) % size ;
                   22081:     else if (++h >= size)
                   22082:       h -= size ;
                   22083:   }
                   22084:   return 0 ;
                   22085: }
                   22086: 
                   22087: void Hash::apply(intProc f)
                   22088: {
                   22089:   for (int i = 0; i < size; ++i)
                   22090:     if (tab[i].status == VALID)
                   22091:       (*f)(tab[i].cont) ;
                   22092: }
                   22093: 
                   22094: void Hash::clear()
                   22095: {
                   22096:   for (int i = 0; i < size; ++i)
                   22097:     tab[i].status = EMPTY ;
                   22098:   entry_count = 0 ;
                   22099: }
                   22100: 
                   22101: void Hash::resize(int newsize)
                   22102: {
                   22103:   if (newsize < entry_count)
                   22104:     error("requested resize too small") ;
                   22105:   HashTableEntry* oldtab = tab ;
                   22106:   int oldsize = size ;
                   22107:   tab = new HashTableEntry[size = newsize] ;
                   22108:   for (int i = 0; i < size; ++i) 
                   22109:     tab[i].status = EMPTY ;
                   22110:   entry_count = 0 ;
                   22111:   for (i = 0; i < oldsize; ++i)
                   22112:     if (oldtab[i].status == VALID)
                   22113:       (*this)[oldtab[i].key] = oldtab[i].cont ;
                   22114:   delete [oldsize] oldtab ;
                   22115: }
                   22116: 
                   22117: void HashWalker::reset()
                   22118: {
                   22119:   for (pos = 0; pos < h->size; ++pos)
                   22120:     if (h->tab[pos].status == VALID)
                   22121:       return ;
                   22122:   pos = -1 ;
                   22123: }
                   22124: 
                   22125: void HashWalker::advance()
                   22126: {
                   22127:   if (pos < 0)
                   22128:     return ;
                   22129:   for (pos++; pos < h->size; ++pos)
                   22130:     if (h->tab[pos].status == VALID)
                   22131:       return ;
                   22132:   pos = -1 ;
                   22133: }
                   22134: 
                   22135: /*
                   22136: unsigned int foo(int bar) {return bar;}
                   22137: int baz(int a, int b) {return a == b;}
                   22138: 
                   22139: main()
                   22140: {
                   22141:   Hash vh(10)  ;
                   22142:   HashWalker vt(vh)  ;
                   22143:   int i  ;
                   22144: 
                   22145:   vh.key_hash_function = &foo  ;
                   22146:   vh.key_key_equality_function = baz  ;
                   22147:   printf("Capacity=%d \n", vh.capacity()) ;
                   22148:   for (i=0; i<500; i+= 5)
                   22149:     {
                   22150:       vh[i] = i * i  ;
                   22151:     }
                   22152:   vt.reset() ;
                   22153:   while (vt.valid())
                   22154:     {
                   22155:       printf("key=%d, data=%d\t", vt.key(), vt.get());
                   22156:       vt.advance()  ;
                   22157:     }
                   22158:   for (i=0; i<500; i+= 10)
                   22159:     {
                   22160:       vh.del (i) ;
                   22161:       printf("After delete: %d\n", vh[i]);
                   22162:     }
                   22163:   printf("\n-----------------\n") ;
                   22164:   vt.reset() ;
                   22165:   while (vt.valid())
                   22166:     {
                   22167:       printf("key=%d, data=%d\t", vt.key(), vt.get());
                   22168:       vt.advance()  ;
                   22169:     }
                   22170: }
                   22171: 
                   22172: */
                   22173: 0707071010112046061004440001630000160000010212400466055420200000700000011465hash.h/* ident "@(#)ctrans:src/hash.h     1.2" */
                   22174: /* Compiler interface to hash tables from odi library. 
                   22175:        $Source: /usr3/lang/benson/work/stripped_cfront/RCS/hash.h,v $ $RCSfile: hash.h,v $
                   22176:        $Revision: 1.1 $                $Date: 89/11/20 08:50:36 $
                   22177:        $Author: benson $               $Locker:  $
                   22178:        $State: Exp $
                   22179: 
                   22180:     $Header: /usr2/odi/objectstore.src/libos/RCS/hash.H,v 1.4 89/09/26 09:37:31 benson Exp $
                   22181: 
                   22182:     Copyright (c) 1989 by Object Design, Inc., Burlington, Mass.
                   22183:     All rights reserved.
                   22184: 
                   22185: */
                   22186: 
                   22187: #ifndef _HASH_H
                   22188: #define _HASH_H
                   22189: 
                   22190: #include <string.h>
                   22191: 
                   22192: typedef void (*Error_Proc) (const char*) ;
                   22193: 
                   22194: extern void default_Hash_error_handler (const char*) ;
                   22195: extern Error_Proc Hash_error_handler ;
                   22196: extern Error_Proc set_Hash_error_handler (Error_Proc f) ;
                   22197: 
                   22198: #ifndef _hash_typedefs
                   22199: #define _hash_typedefs 1
                   22200: typedef void (*intProc)(int) ;
                   22201: #endif
                   22202: 
                   22203: #define DEFAULT_INITIAL_HASH_SIZE 100
                   22204: 
                   22205: struct HashTableEntry
                   22206: {
                   22207:   int                   key ;
                   22208:   int                   cont ;
                   22209:   char                  status ;
                   22210: } ;
                   22211: 
                   22212: class HashWalker ;
                   22213: 
                   22214: class Hash
                   22215: {
                   22216:   friend class          HashWalker ;
                   22217: 
                   22218:   HashTableEntry*       tab ;
                   22219:   int                   size ;
                   22220:   int                   entry_count ;
                   22221: 
                   22222: public:
                   22223:   unsigned int         (*key_hash_function)(int)  ;
                   22224:    int                 (*key_key_equality_function) (int, int) ;
                   22225: 
                   22226:   unsigned int          key_hash(int  a) ;
                   22227:   int                   key_key_eq(int a, int  b);    
                   22228: 
                   22229:                         Hash(int sz) ;
                   22230:                         Hash(Hash& a) ;
                   22231:                         ~Hash() ;
                   22232: 
                   22233:   Hash&                 operator= (Hash& a) ;
                   22234: 
                   22235:   int                   count() ;
                   22236:   int                   empty() ;
                   22237:   int                   full() ;
                   22238:   int                   capacity() ;
                   22239: 
                   22240:   void                  clear() ;
                   22241:   void                  resize(int newsize) ;
                   22242: 
                   22243:   enum insert_action   { probe, insert, replace };
                   22244:   void                 action (int key, int val, insert_action what,
                   22245:                                int& found, int& old_val);
                   22246:   int&                  operator [] (int  k) ;
                   22247:   int                   contains(int  key) ;
                   22248:   int                   del(int  key) ;
                   22249: 
                   22250:   void                  apply (intProc f) ;
                   22251:   void                  error(const char* msg) ;
                   22252: } ;
                   22253: 
                   22254: class HashWalker
                   22255: {
                   22256:   Hash*     h ;
                   22257:   int                   pos ;
                   22258: 
                   22259: public:
                   22260:                         HashWalker(Hash& l) ;
                   22261:                         ~HashWalker() ;
                   22262: 
                   22263:   int                   null() ;
                   22264:   int                   valid() ;
                   22265:                         operator void* () ;
                   22266:   int                   operator ! () ;
                   22267:   void                  advance() ;
                   22268:   void                  reset() ;
                   22269:   void                  reset(Hash& l) ;
                   22270:   const int&            key() ;
                   22271:   int&                  get() ;
                   22272: } ;
                   22273: 
                   22274: inline unsigned int Hash::key_hash(int a)
                   22275: {
                   22276: #ifdef HASHFUNCTION
                   22277:   return HASHFUNCTION(a) ;
                   22278: #else
                   22279:   return (*key_hash_function)(a) ;
                   22280: #endif
                   22281: }
                   22282: 
                   22283: inline int Hash::key_key_eq(int a, int b)
                   22284: {
                   22285: #ifdef EQUALITYFUNCTION
                   22286:   return EQUALITYFUNCTION(a, b) ;
                   22287: #else
                   22288:   return (*key_key_equality_function)(a, b) ;
                   22289: #endif
                   22290: }
                   22291: 
                   22292: 
                   22293: inline Hash::~Hash()
                   22294: {
                   22295:   delete [size] tab ;
                   22296: }
                   22297: 
                   22298: inline int Hash::count()
                   22299: {
                   22300:   return entry_count ;
                   22301: }
                   22302: 
                   22303: inline int Hash::empty()
                   22304: {
                   22305:   return entry_count == 0 ;
                   22306: }
                   22307: 
                   22308: inline int Hash::full()
                   22309: {
                   22310:   return entry_count == size ;
                   22311: }
                   22312: 
                   22313: inline int Hash::capacity()
                   22314: {
                   22315:   return size ;
                   22316: }
                   22317: inline HashWalker::HashWalker(Hash& a)
                   22318: {
                   22319:   h = &a ;
                   22320:   reset() ;
                   22321: }
                   22322: 
                   22323: inline void HashWalker::reset(Hash& a)
                   22324: {
                   22325:   h = &a ;
                   22326:   reset() ;
                   22327: }
                   22328: 
                   22329: 
                   22330: inline HashWalker::~HashWalker() {}
                   22331: 
                   22332: inline int HashWalker::null()
                   22333: {
                   22334:   return pos < 0 ;
                   22335: }
                   22336: 
                   22337: inline int HashWalker::valid()
                   22338: {
                   22339:   return pos >= 0 ;
                   22340: }
                   22341: 
                   22342: inline HashWalker::operator void* ()
                   22343: {
                   22344:   return (pos < 0)? 0 : this ;
                   22345: }
                   22346: 
                   22347: inline int HashWalker::operator ! ()
                   22348: {
                   22349:   return (pos < 0) ;
                   22350: }
                   22351: 
                   22352: 
                   22353: inline const int& HashWalker::key()
                   22354: {
                   22355:   if (pos < 0)
                   22356:     h->error("operation on null Walker") ;
                   22357:   return h->tab[pos].key ;
                   22358: }
                   22359: 
                   22360: inline int& HashWalker::get()
                   22361: {
                   22362:   if (pos < 0)
                   22363:     h->error("operation on null Walker") ;
                   22364:   return h->tab[pos].cont ;
                   22365: }
                   22366: 
                   22367: inline int pointer_hasheq (int a, int b)
                   22368: {
                   22369:     return a == b;
                   22370: };
                   22371: 
                   22372: inline unsigned int pointer_hash_fcn (int x)
                   22373: {
                   22374:     unsigned X = (unsigned) x;
                   22375:     return ((X << 16) | (X >> 16)) ^ x;
                   22376: }
                   22377: 
                   22378: class pointer_hash : public Hash {
                   22379:   public:
                   22380:     pointer_hash (int sz = 0) : Hash (sz) {
                   22381:        key_hash_function = pointer_hash_fcn;
                   22382:        key_key_equality_function = pointer_hasheq;
                   22383:     }
                   22384: 
                   22385:     pointer_hash (pointer_hash& h) : Hash (h) {};
                   22386: };
                   22387: 
                   22388: inline int string_hasheq (int a, int b)
                   22389: {
                   22390:     return !strcmp((char *)a, (char *) b);
                   22391: };
                   22392: 
                   22393: static unsigned int string_hash_fcn (int x)
                   22394: {
                   22395:     char * str = (char *)x;
                   22396:     int l = strlen(str);
                   22397:        
                   22398:     if(x <= 4) return str[0];
                   22399:     else {
                   22400:        unsigned int * f4 = (unsigned int *) str;
                   22401:        if (l < 8) return ((*f4 << 16) | (*f4 >> 16)) ^ *f4;
                   22402:        else {
                   22403:            unsigned int * s4 = f4 ++;
                   22404:            return ((*f4 << 16) | (*f4 >> 16)) ^ *s4;
                   22405:        }
                   22406:     }
                   22407: };
                   22408: 
                   22409: 
                   22410: class string_hash : public Hash {
                   22411:     public:
                   22412: 
                   22413:     string_hash (int sz = 0) : Hash (sz) {
                   22414:        key_hash_function = string_hash_fcn;
                   22415:        key_key_equality_function = string_hasheq;
                   22416:     };
                   22417: 
                   22418:     string_hash (string_hash& h) : Hash (h) {};
                   22419: };
                   22420: 
                   22421: #endif
                   22422: 0707071010112046071004440001630000160000010210470466055420500001500000001056ios_printf.h/* ident "@(#)ctrans:src/ios_printf.h 1.2" */
                   22423: /* Begin iostream_printf.H -- printf functions that work on ostreams.
                   22424:    someday, perhaps, scanf functions for istreams. */
                   22425: 
                   22426: #include <stdarg.h>
                   22427: #include <iostream.h>
                   22428: 
                   22429: int vostream_printf(const char *format, va_list argp, ostream& fp);
                   22430: int ostream_printf(ostream& stream, const char * format ...);
                   22431: 
                   22432: // returns count of characters added.
                   22433: int printf_to_string (char * string, int length, const char * format ...);
                   22434: 
                   22435: // returns string which came from malloc.
                   22436: char * printf_to_alloc_string (const char * format ...);
                   22437: 0707071010112044331004440001630000160000010202700466055403600001000000134002lalex.c/*ident    "@(#)ctrans:src/lalex.c 1.15" */
                   22438: /**************************************************************************
                   22439: 
                   22440:        C++ source for cfront, the C++ compiler front-end
                   22441:        written in the computer science research center of Bell Labs
                   22442: 
                   22443:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   22444:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   22445: 
                   22446: lalex.c:
                   22447: 
                   22448:        lookahead 
                   22449: 
                   22450: *****************************************************************************/
                   22451: #include <stdio.h>
                   22452: 
                   22453: #ifdef c_plusplus
                   22454: overload is_empty;
                   22455: #endif
                   22456: 
                   22457: #include "cfront.h"
                   22458: #include "yystype.h"
                   22459: #include "tqueue.h"
                   22460: #include "template.h"
                   22461: 
                   22462: #ifdef DBG
                   22463: #define LDB(val,a) { if(Ldebug>=val) {a;} }
                   22464: #else
                   22465: #define LDB(val,a) /**/
                   22466: #endif
                   22467: 
                   22468: #ifdef DBG
                   22469: static char*
                   22470: image( int t )
                   22471: {
                   22472:        if(keys[t]) return keys[t];
                   22473:        else { static char b[20];
                   22474:                sprintf(b,"token(%d)",t);
                   22475:                return b;
                   22476:        }
                   22477: }
                   22478: static void
                   22479: printok( toknode* t )
                   22480: {
                   22481:        switch(t->tok) {
                   22482:        default:
                   22483:                fprintf(stderr,"\t%s",image(t->tok));
                   22484:                break;
                   22485:        case ID: case ICON: case CCON: case FCON: case STRING:
                   22486:                fprintf(stderr,"ID '%s'",t->retval.s);
                   22487:                break;
                   22488:        case TNAME:
                   22489:                fprintf(stderr,"TNAME '%s'",t->retval.pn->string);
                   22490:                break;
                   22491:        case PTNAME:
                   22492:                fprintf(stderr,"PTNAME '%s'",t->retval.pn->string);
                   22493:                break;
                   22494:        case TSCOPE:
                   22495:                fprintf(stderr,"TSCOPE '%s'::",t->retval.pn->string);
                   22496:                break;
                   22497:        case MEMPTR:
                   22498:                fprintf(stderr,"MEMPTR '%s'::*",t->retval.pn->string);
                   22499:                break;
                   22500:        }
                   22501:        putc(' ',stderr);
                   22502:        t->place.put(stderr);
                   22503:        putc('\n',stderr);
                   22504: }
                   22505: static void
                   22506: showQ( char* where )
                   22507: /*
                   22508:        display token Q
                   22509: */
                   22510: {
                   22511:        fprintf(stderr,"TOKEN Q (%s):\n",where);
                   22512:        for (register toknode* t = front; t; t = t->next) printok(t);
                   22513:        putc('\n',stderr);
                   22514: }
                   22515: #endif
                   22516: 
                   22517: int bl_level;
                   22518: 
                   22519: static int  laexpr( TOK );
                   22520: static int  latype( TOK );
                   22521: static int  la_decl();
                   22522: static TOK  lookahead();
                   22523: 
                   22524: /* make this a toknode! */
                   22525: static int lasttk = 0;         // one token history
                   22526: static YYSTYPE lastval;        // yylval lasttk value 
                   22527: 
                   22528: int must_be_expr = 0;          // handle redundant parentheses
                   22529: int must_be_id = 0;            // !0, TNAME => ID, i.e., int X
                   22530: 
                   22531: loc curloc;
                   22532: int curr_file;
                   22533: 
                   22534: toknode* latok;                        // current lookahead token
                   22535: toknode* front = 0;
                   22536: toknode* rear  = 0;
                   22537: 
                   22538: const  TQCHUNK = 16;
                   22539: 
                   22540: void*
                   22541: toknode::operator new(size_t)
                   22542: {
                   22543:        register toknode* p;
                   22544: 
                   22545:        if ((p=free_toks) == 0) {
                   22546:                register toknode* q;
                   22547:                free_toks = q = (toknode*)malloc( TQCHUNK * sizeof(toknode) );
                   22548:                p = free_toks;
                   22549:                for (; q != &p[TQCHUNK-1]; q->next = q+1, ++q);
                   22550:                q->next = 0;
                   22551:        }
                   22552:        free_toks = p->next;
                   22553:        return p;
                   22554: }
                   22555: 
                   22556: toknode::toknode(TOK t, YYSTYPE r, loc tloc)
                   22557: {
                   22558:        tok = t;
                   22559:        used = 0;
                   22560:        retval = r;
                   22561:        place = tloc;
                   22562:        next = last = 0;
                   22563: }
                   22564: 
                   22565: void
                   22566: toknode::operator delete(void* vp,size_t)
                   22567: {
                   22568:        register toknode* p = (toknode*)vp;
                   22569:        p->next = free_toks;
                   22570:        free_toks = p;
                   22571:        vp = 0;
                   22572: }
                   22573: 
                   22574: #define USE_TOKEN(T,W) \
                   22575:        LDB(2,error('d',&(T)->place,"use_token('%k','%s')",(T)->tok,W);); \
                   22576:        if ( !(T)->used ) use_token(T);
                   22577: 
                   22578: Ptype
                   22579: return_nstd_local_type( Pname n, TOK &sw )
                   22580: { 
                   22581:        Ptype tt;
                   22582:        switch ( n->tp->base ) {
                   22583:                case EOBJ:
                   22584:                case COBJ:
                   22585:                        tt = Pbase(n->tp)->b_name->tp;
                   22586:                        sw = n->tp->base;
                   22587:                        break;
                   22588:                default:
                   22589:                        tt = n->tpdef;
                   22590:                        sw = NESTED; // in repr.c, prints ``typedef''
                   22591:                        break;
                   22592:        }
                   22593:        return tt;
                   22594: }
                   22595: 
                   22596: static Pname
                   22597: local_nested_kludge( Pname n, Pname tn )
                   22598: /*
                   22599:  * for backward compatibility with 2.0
                   22600:  * in transitional model of nested class types
                   22601:  * 
                   22602:  * struct T { ... };
                   22603:  * foobar() {
                   22604:  *     class X {
                   22605:  *             typedef int T;
                   22606:  *             // ...
                   22607:  *     };
                   22608:  *     T t;
                   22609:  * }
                   22610:  *
                   22611:  * pure nested classes, choose global struct T{};
                   22612:  * no nested classes, choose typedef int T
                   22613:  * transitional model: choose typedef, and generate warning
                   22614:  * BUG: local typedefs and enums do not have lex_level set
                   22615:  */
                   22616: {
                   22617: // error( 'd', "local_nested_kludge: n: %n", n );
                   22618:        for ( Pname nn = n; nn; nn = nn->n_tbl_list )
                   22619:        {
                   22620:                Pname local_class;
                   22621:                TOK ntd;
                   22622:                if ( nn->n_key != NESTED ) continue;
                   22623:                Ptype tt = return_nstd_local_type(nn,ntd);
                   22624:                Pclass cl = tt->in_class;
                   22625:                while ( cl->in_class ) cl = cl->in_class;
                   22626:                if (cl->lex_level && 
                   22627:                        (local_class = ktbl->look(cl->string,LOCAL)))
                   22628:                {
                   22629:                        // same typedef at nested and non-nested scope
                   22630:                        if (ntd == NESTED && tn && tn->tp == nn->tp )
                   22631:                                ; 
                   22632:                        else
                   22633:                                error('w',"%s occurs at outer and nested localC scope; using %k %t::%s", n->string,ntd,cl,n->string);
                   22634: 
                   22635: /*
                   22636:                        if ( ntd == NESTED && nn->n_dcl_printed != 2 ) {
                   22637:                                nn->dcl_print(0);
                   22638:                                nn->n_dcl_printed = 2;
                   22639:                        }
                   22640: */
                   22641:                        return nn;
                   22642:                }
                   22643:        }
                   22644:        return 0;
                   22645: }
                   22646: 
                   22647: enum { one_back, two_back };
                   22648:        
                   22649: static void
                   22650: use_token( toknode* T )
                   22651: /*
                   22652:        lookup TNAMEs here instead of in tlex()
                   22653:        maintain block level
                   22654: */
                   22655: {
                   22656:        static TOK last_tokens[2];  // TSCOPE not reduced at this point
                   22657:        static Pname last_tname;    // tname :: id, where id is nested class
                   22658:        static Pname tdef_name;     // typedef tname tdef_name
                   22659:        T->used = 1;
                   22660: 
                   22661:        DB(if(Ldebug>=1) {
                   22662:                error('d',&T->place,"\n*** use_token(%k )",T->tok);
                   22663:                printok(T);
                   22664:                error('D',&T->place,"    lasttk%k last_tname%n last tokens%k%k",lasttk,last_tname,last_tokens[one_back],last_tokens[two_back]);
                   22665:        });
                   22666: 
                   22667:        switch ( T->tok ) {
                   22668:        case ID:
                   22669:                Pname n;
                   22670: // error('d', &T->place, "use_token: %s", T->retval.s );
                   22671:                if ( last_tokens[one_back] == MEM &&
                   22672:                        last_tokens[two_back] == TNAME &&
                   22673:                        (n=ktbl->look(T->retval.s,NESTED))) 
                   22674:                { // TYPEDEF :: ID, nested class ctor 
                   22675:                        if (tdef_name && tdef_name->n_key==NESTED &&
                   22676:                                strcmp(tdef_name->string,n->string)==0)
                   22677:                        {
                   22678:                                T->tok = TNAME;
                   22679:                                T->retval.pn = n;
                   22680:                                break;
                   22681:                        }       
                   22682:                        else { // TNAME :: ID, where ID may be nested class
                   22683:                        for ( Pname nn = n; nn; nn = nn->n_tbl_list )
                   22684:                        {
                   22685:                                TOK sw;
                   22686:                                if ( nn->n_key != NESTED ) continue;
                   22687:                                Ptype tt = return_nstd_local_type(nn,sw);
                   22688:                                Pclass cl = tt->in_class;
                   22689:                                if (strcmp(last_tname->string,cl->string)==0)
                   22690:                                {
                   22691:                                        T->tok = TNAME;
                   22692:                                        T->retval.pn = nn;
                   22693:                                        break;
                   22694:                                }       
                   22695:                        }
                   22696:                        }
                   22697:                }
                   22698:                else
                   22699:                if ( bl_level && 
                   22700:                        // TNAME:: and :: cannot refer to ``local'' TNAME
                   22701:                        last_tokens[one_back] != MEM  && 
                   22702:                        (n=ktbl->look(T->retval.s,LOCAL)) ) 
                   22703:                {
                   22704:                        DB( if(Ldebug>=1)error( 'd', &T->place, "use_token: local class instance: %n", n ) );
                   22705:                        T->tok = TNAME;
                   22706:                        T->retval.pn = n;
                   22707:                } 
                   22708:                else if ( n=ktbl->look(T->retval.s,0) ) {
                   22709:                        DB( if(Ldebug>=1)error( 'd', &T->place, "use_token:GC instance: %n", n ) );
                   22710: // error( 'd', &T->place, "use_token:GC instance: %n %t", n, n->tp );
                   22711: 
                   22712:                        // X:: ?, then n cannot be a global TNAME
                   22713:                        //      except in the case of a constructor
                   22714:                        if (last_tokens[one_back] == MEM &&
                   22715:                                last_tokens[two_back] == TNAME &&
                   22716:                                strcmp(T->retval.s,last_tname->string))
                   22717:                                        ; // do nothing; i.e., return ID
                   22718:                        else 
                   22719:                        if ( bl_level && n->tp->base != COBJ &&
                   22720:                                last_tokens[one_back] == MEM &&
                   22721:                                last_tokens[two_back] != TNAME &&
                   22722:                                gtbl->look(T->retval.s,0))
                   22723:                                        ; // do nothing: local typedefs & enums not implemented
                   22724:                        else {
                   22725:                                Pname nn = 0;
                   22726:                                TOK ntd;
                   22727:                                if (bl_level && (nn=ktbl->look(T->retval.s,NESTED)))
                   22728:                                {
                   22729:                                        (void) return_nstd_local_type(n,ntd);
                   22730:                                        nn = local_nested_kludge(nn,ntd==NESTED?n:0);
                   22731:                                }
                   22732:                                T->tok = TNAME;
                   22733:                                T->retval.pn = nn?nn:n;
                   22734:                        }
                   22735:                }
                   22736: #ifdef DBG
                   22737:                else if(Ldebug>=1)
                   22738:                        error('d',&T->place,"use_token: id %s",T->retval.s);
                   22739: #endif
                   22740:                break;
                   22741:        case LC: ++bl_level; break;
                   22742:        case RC: --bl_level; break;
                   22743:        }
                   22744:        
                   22745:        if (T->tok != COMPL || last_tokens[one_back] != MEM) {
                   22746:                last_tokens[two_back] = last_tokens[one_back];
                   22747:                last_tokens[one_back] = T->tok; 
                   22748:                if (T->tok == TNAME) last_tname = T->retval.pn;
                   22749:                if ( last_tname && 
                   22750:                        last_tname->tp->base == TYPE )
                   22751:                {
                   22752:                        tdef_name = last_tname;
                   22753:                        do
                   22754:                                tdef_name = Pbase(tdef_name->tp)->b_name;
                   22755:                        while ( tdef_name->tp->base == TYPE );
                   22756:                }
                   22757:        }
                   22758: }
                   22759: 
                   22760: void
                   22761: addtok(TOK t, YYSTYPE r, loc tloc)
                   22762: {
                   22763:        toknode* T = new toknode(t,r,tloc);
                   22764:        if (front == 0)
                   22765:                front = rear = T;
                   22766:        else {
                   22767:                rear->next = T;
                   22768:                T->last = rear;
                   22769:                rear = T;
                   22770:        }
                   22771: //error('d',&tloc,"addtok: %k '%s'",t,t==ID?r.s:"");
                   22772: //showQ("addtok");
                   22773: }
                   22774: 
                   22775: extern TOK
                   22776: deltok( int noset = 0 )
                   22777: {
                   22778:        register toknode* T = front;
                   22779:        USE_TOKEN(T,"deltok");
                   22780:        register TOK tk = T->tok;
                   22781:        if ( !noset ) { yylval = T->retval; curloc = T->place; }
                   22782:        curr_file = curloc.file;
                   22783:        if (front = front->next)
                   22784:                front->last = 0;
                   22785:        else
                   22786:                latok = rear = 0;
                   22787:        delete T;
                   22788:        return tk;
                   22789: }
                   22790: 
                   22791: static void
                   22792: add_tokens()
                   22793: /*
                   22794:     extend lookahead token queue when depleted
                   22795: */
                   22796: {
                   22797:     TOK tk = tlex();
                   22798:     if ( tk != ID )
                   22799:        return;
                   22800: 
                   22801:     while (tk == ID || tk == MEM || tk == DOT )  
                   22802:        tk = tlex(); 
                   22803: }
                   22804: 
                   22805: extern TOK
                   22806: la_look()
                   22807: /*
                   22808:        peek at head of token queue
                   22809: */
                   22810: {
                   22811:     LDB(1,fprintf(stderr,"\n*** la_look()"));
                   22812:     if ( front == 0 )
                   22813:        add_tokens();
                   22814: 
                   22815:     latok = front;
                   22816:     USE_TOKEN(latok,"la_look");
                   22817:     LDB(1,fprintf(stderr," -- %s\n",image(latok->tok)));
                   22818:     return latok->tok;
                   22819: }
                   22820: 
                   22821: #define NEXTTOK() ( (yychar==-1) ? (yychar=lalex(),yychar) : yychar )
                   22822: void
                   22823: check_decl()
                   22824: /*
                   22825:        Lookahead to direct parsing of local/arg type declarations
                   22826:        la_decl() returns 1 if lookahead sees a declaration.
                   22827: */
                   22828: {
                   22829:        TOK tk2;
                   22830:        switch( NEXTTOK() ) {
                   22831:        default:
                   22832:        break;
                   22833:        case TSCOPE: //XXX
                   22834:                tk2 = la_look();
                   22835:                while ( tk2 == TSCOPE ) tk2 = lookahead();
                   22836:                if ( tk2 == TNAME ) {
                   22837:                    toknode* t = latok;
                   22838:                    if(t->tok!=TNAME)
                   22839:                        error('i',&t->place,"check_decl() token scan");
                   22840:                    tk2 = lookahead();
                   22841:                    if ( tk2 == LP && la_decl() ) {
                   22842:                        t->tok = DECL_MARKER; //TNAME
                   22843:                    }
                   22844:                }
                   22845:                break;
                   22846:        case TYPE: case TNAME:
                   22847:            if ( la_look() == LP && la_decl() ) {
                   22848:                must_be_id = 0;
                   22849:                DECL_TYPE=yychar;
                   22850:                yychar = DECL_MARKER;
                   22851:            }
                   22852:        }
                   22853: }
                   22854: 
                   22855: void
                   22856: check_cast()
                   22857: /*
                   22858:        Lookahead to direct parsing of cast
                   22859:        la_cast() returns 1 if lookahead sees an ambiguous old-style C cast.
                   22860: */
                   22861: {
                   22862:        TOK tk2;
                   22863:        switch( NEXTTOK() ) {
                   22864:        case TSCOPE: //XXX
                   22865:                tk2 = la_look();
                   22866:                while ( tk2 == TSCOPE ) tk2 = lookahead();
                   22867:                if ( tk2 == TNAME ) {
                   22868:                    toknode* t = latok;
                   22869:                    if(t->tok!=TNAME)
                   22870:                          error('i',&t->place,"check_cast() token scan");
                   22871:                    tk2 = lookahead();
                   22872:                    if ( tk2 == LP && la_decl() ) {
                   22873:                        t->tok = DECL_MARKER;//TNAME
                   22874:                    }
                   22875:                }
                   22876:                break;
                   22877:        case TYPE: case TNAME:
                   22878:            if ( la_look() == LP && la_cast() ) {
                   22879:                must_be_id = 0;
                   22880:                DECL_TYPE = yychar;
                   22881:                yychar = DECL_MARKER;
                   22882:            }
                   22883:        }
                   22884: }
                   22885: 
                   22886: 
                   22887: static int
                   22888: latype( TOK t )
                   22889: {
                   22890:        switch ( t ) {
                   22891:        default: // includes friend, typedef, storage classes, etc.
                   22892:                return 0;
                   22893:        case CHAR: case SHORT: case INT: case LONG:
                   22894:        case FLOAT: case DOUBLE:
                   22895:         case UNSIGNED:
                   22896:                return 1;
                   22897:        }
                   22898: }
                   22899: 
                   22900: static int
                   22901: laexpr( TOK t )
                   22902: {
                   22903:        switch ( t ) {
                   22904:        default: 
                   22905:                return 0;
                   22906:        case RETURN: case NEW: case AND: case ANDAND: case OR: case OROR:
                   22907:        case SIZEOF: case NOT: case COMPL: case MUL: case PLUS: case MINUS: 
                   22908:        case ER: case ASSIGN: case ASOP: case RELOP: case EQUOP: case DIVOP: 
                   22909:        case SHIFTOP: case ICOP:
                   22910:                return 1;
                   22911:        }
                   22912: }
                   22913: 
                   22914: static toknode *get_next_token(toknode *t) {
                   22915:   if (! t->next)
                   22916:     add_tokens() ;
                   22917:   
                   22918:   return t->next ;
                   22919: }
                   22920: 
                   22921: 
                   22922: static int template_tscope(Pname tn, toknode *lt) 
                   22923: /* provide the looakhead for determining TSCOPE tokens when the name is a
                   22924:  * parametrized type name; the lookahead here is non-trivial, because it
                   22925:  * involves stepping over the template arguments. 
                   22926:  */
                   22927: {
                   22928:   int nest = 0 ; // the LT has been fetched
                   22929: 
                   22930:   if (lt->tok != LT) error ('i', "a `<' token was expected") ;  
                   22931: 
                   22932:   // assume the worst, ensure that name strings are consed in the heap
                   22933:   templp->parameters_in_progress++ ;
                   22934:   
                   22935:   for (toknode *t = lt;; t = get_next_token(t))    
                   22936:     switch (t->tok) {
                   22937:       
                   22938:     case LT:
                   22939:        ++nest;
                   22940:        continue;
                   22941:     case GT:
                   22942:        // ***************
                   22943:        // need to fold in awareness of x::y::z
                   22944:        if (--nest == 0) {
                   22945:                t = get_next_token(t);
                   22946:                if (t->tok == MEM) {
                   22947:                // determine whether it is a memptr
                   22948:                        if (t->next == 0) add_tokens();
                   22949:                        if (t->next->tok == MUL) {
                   22950:                                t->tok = MEMPTR;
                   22951:                                t->next = t->next->next ;
                   22952:                } else  t->tok = TSCOPE ;
                   22953:                t->retval.pn  = tn ;
                   22954:                --templp->parameters_in_progress;
                   22955:                return 1;
                   22956:        } 
                   22957:        else  return 0 ;
                   22958:       }
                   22959:       continue;
                   22960: 
                   22961:     case SM: case LC: case RC: // a quick exit in case of error
                   22962:     case EOFTOK:
                   22963:        --templp->parameters_in_progress;
                   22964:        return 0 ;
                   22965:       
                   22966:     default:
                   22967:        continue;
                   22968:     }
                   22969: }
                   22970: 
                   22971: static TOK
                   22972: lookahead()
                   22973: /*
                   22974:     advance lookahead pointer, lexing at end of Q
                   22975:     handle occurrences of TNAME and TSCOPE
                   22976:     (should be kept up to date with lalex())
                   22977: */
                   22978: {
                   22979:     TOK tk;
                   22980:     TOK tk2;
                   22981:     TOK prev_tk = 0;
                   22982:     YYSTYPE lastval;
                   22983: 
                   22984:     if ( latok == rear ) {
                   22985:        add_tokens();
                   22986:        if ( latok )
                   22987:            latok = latok->next;
                   22988:        else
                   22989:            latok = front;
                   22990:     }
                   22991:     else
                   22992:        latok = latok->next;
                   22993: 
                   22994:     if ( latok->last ) {
                   22995:        prev_tk = latok->last->tok;
                   22996:        lastval = latok->last->retval;
                   22997:     }
                   22998: 
                   22999: nexttok:
                   23000:     USE_TOKEN(latok,"lookahead1");
                   23001:     tk = latok->tok;
                   23002:     if ( tk == ID || tk == TNAME ) 
                   23003:     {
                   23004:        if (latok->next == 0) add_tokens();
                   23005:        USE_TOKEN(latok->next,"lookahead2");
                   23006:        /* TOK */ tk2 = latok->next->tok;
                   23007:        if ( tk == TNAME ) {
                   23008:           if (tk2 == LT) {
                   23009:              // a parametrized type name -- differentiate from TNAME 
                   23010:              // so that it can be dealt with in the grammar. 
                   23011:              if (template_tscope(latok->retval.pn, latok->next)) tk = PTNAME;
                   23012:           }
                   23013:            else  
                   23014:           if ( tk2 == MEM || tk2 == DOT ) {
                   23015: tscope:        
                   23016:                tk = TSCOPE;
                   23017: // error('d',"lookahead: tk: %k tk2: %k", tk, tk2 );
                   23018: // XXX -- should be modified to loop and do lookup
                   23019:                latok = latok->next;
                   23020:                if (latok->next == 0) add_tokens();
                   23021:                USE_TOKEN(latok->next,"lookahead3");
                   23022:                tk2 = latok->next->tok;
                   23023:                if ( tk2 == MUL ) {
                   23024:                        tk = MEMPTR;
                   23025:                        latok = latok->next;
                   23026:                }
                   23027:            }
                   23028:            else if (( prev_tk == MUL && tk2 != RP )
                   23029:                        || prev_tk == AND )
                   23030:                {
                   23031:                tk = ID;
                   23032:                latok->retval.pn->hide();
                   23033:                latok->tok = ID;
                   23034:                latok->retval.s = latok->retval.pn->string;
                   23035:                }
                   23036:        }
                   23037:        else if ( tk2 == MEM ) {
                   23038:                // ID ::
                   23039:        //XXX   latok = latok->next->next;
                   23040:        //XXX   goto nexttok;
                   23041:                goto tscope; // treat as tscope
                   23042:        }
                   23043: 
                   23044:        if ( tk == ID &&
                   23045:                ( tk2 == ID ||
                   23046:                ( prev_tk == ID && ( tk2 == COLON || tk2 == LC )))) {
                   23047:                        // ID ID
                   23048:                        latok = latok->next;
                   23049:                        goto nexttok;
                   23050:                        }
                   23051:     }
                   23052: 
                   23053:        if ( tk == ID ) {
                   23054:                Pname nstd = ktbl->look(latok->retval.s,NESTED);
                   23055:                if (nstd && (must_be_id == 0 ||
                   23056:                        must_be_id && prev_tk == LP)) {
                   23057: extern Pname check_for_nested(Pname,TOK,YYSTYPE,TOK); // use this in lalex, too
                   23058:                                Pname n = check_for_nested(nstd,prev_tk,lastval,tk2);
                   23059:                                if ( n ) {
                   23060:                                        tk = latok->tok = TNAME;
                   23061:                                        latok->retval.pn = n;
                   23062:                                }
                   23063:                }
                   23064:        }
                   23065: 
                   23066:     return tk;
                   23067: }
                   23068: 
                   23069: static Pname mem_sel = 0;
                   23070: 
                   23071: static Pname
                   23072: do_local_class( Pname n, int lex_level ) 
                   23073: { /*
                   23074:    * modify to ``do_local_type:
                   23075:    *   do local types: enums and typedefs
                   23076:    */
                   23077:        Pname nn = n;
                   23078:        if ( n->tp ) { // already a TNAME
                   23079:                Pclass cl = n->tp->base==COBJ ? Pclass(Pbase(n->tp)->b_name->tp) : 0;
                   23080:                if ( n->lex_level != lex_level || (cl && cl->lcl) ) {
                   23081:                        local_hide( n );
                   23082:                        nn = new name( n->string );
                   23083:                        nn->lex_level = lex_level>=0?lex_level:0;
                   23084:                }
                   23085:                else 
                   23086:                if ( lex_level == n->lex_level && cl->defined ) {
                   23087:                        error( "localC %n redefined", n );
                   23088:                        return n;
                   23089:                }
                   23090:        }
                   23091: 
                   23092:        nn = nn->tname( lastval.t );
                   23093:        modified_tn = modified_tn->l;
                   23094:        nn->n_key = LOCAL;
                   23095:        local_class = new name_list( nn, local_class );
                   23096:        local_blk = new name_list( nn, local_blk );
                   23097: 
                   23098: // error('d', "do_local_class: nn %n tp %t", nn, Pclass(Pbase(nn->tp)->b_name->tp));
                   23099:        return nn;
                   23100: }
                   23101: 
                   23102: static char*
                   23103: make_nested_name( char *s, Pclass cl )
                   23104: { // Q<cnt>_<class_names><space><null>
                   23105:        const nested_depth = 9;
                   23106:        char *str_arr[nested_depth];
                   23107:        int  size_arr[nested_depth];
                   23108:        int cnt = 2;
                   23109:        int size = 4; // Q,<cnt>,<_>,<null>
                   23110: 
                   23111:        str_arr[0] = s; str_arr[1] = cl->string; 
                   23112: 
                   23113:        size += size_arr[0] = strlen(s); 
                   23114:        size += size_arr[1] = cl->strlen?cl->strlen:strlen(cl->string);
                   23115: 
                   23116:        for (Pclass nc = cl->in_class; nc; nc = nc->in_class ) {
                   23117:                if (cnt > nested_depth-1) error('s',"nested depth class beyond %d unsupported",nested_depth);
                   23118:                size += size_arr[cnt] = nc->strlen?nc->strlen:strlen(nc->string);
                   23119:                str_arr[cnt++] = nc->string; 
                   23120:        }
                   23121: 
                   23122:        for ( int i=0; i<cnt; i++ ) // <nnn><string>
                   23123:                size += size_arr[i]>99?3:size_arr[i]<10?1:2;
                   23124: 
                   23125: //error('d', "make_nested_name( %s, %t ) cnt: %d size: %d", s, cl, cnt, size );
                   23126:        char *result = new char[size];
                   23127:        sprintf(result, "Q%d_", cnt );
                   23128:        size = 3;
                   23129:        for ( i=cnt; i; i-- ) {
                   23130:                sprintf(result+size,"%d%s", size_arr[i-1], str_arr[i-1]);
                   23131:                size += size_arr[i-1] + (size_arr[i-1]>99?3:size_arr[i-1]<10?1:2);
                   23132:        }
                   23133: 
                   23134: //error('d', "size: %d ", size );
                   23135:        result[size] = '\0';
                   23136: //error('d', "make_nested_name result: %s", result );
                   23137:        return result;
                   23138: }
                   23139: 
                   23140: int is_empty( Pclass cl, bit const_chk )
                   23141: { /*   for nested class check, empty means *no* members
                   23142:    *    for const object check, means no *data* members
                   23143:    */
                   23144: 
                   23145: // error('d',"%t->is_empty: max: %d real_size: %d", cl, cl->memtbl->max(),cl->real_size );
                   23146: 
                   23147:        int mbr_cnt = cl->memtbl->max();
                   23148:        if ( mbr_cnt == 0 ) return 1;
                   23149: 
                   23150:        if ( cl->baselist == 0 && cl->real_size!=1 )
                   23151:                return 0;
                   23152: 
                   23153:        // empty class to turn on transitional nested class scope
                   23154:        if ( const_chk == 0 && 
                   23155:                ( cl->baselist != 0 || mbr_cnt > 1 )) return 0;
                   23156: 
                   23157:        int i = 1;
                   23158:        for (Pname nn=cl->memtbl->get_mem(i); nn; nn=cl->memtbl->get_mem(++i)) {
                   23159:                if (nn->base==NAME && 
                   23160:                        nn->n_union==0 && 
                   23161:                        nn->tp->base!=FCT && 
                   23162:                        nn->tp->base!=OVERLOAD && 
                   23163:                        nn->tp->base!=CLASS && 
                   23164:                        nn->tp->base!=ENUM && 
                   23165:                        nn->tp->base!=EOBJ && 
                   23166:                        nn->n_stclass != STATIC) 
                   23167:                        {
                   23168:                                if ( nn->string[0]=='_' &&
                   23169:                                        nn->string[1]=='_' &&
                   23170:                                        nn->string[2]=='W' )
                   23171:                                                return 1;
                   23172:                                else return 0;
                   23173:                        }
                   23174:        }
                   23175: 
                   23176:        return 1; // if here, no data members encountered
                   23177: }
                   23178: 
                   23179: static int
                   23180: is_empty( Penum en )
                   23181: { // is this an empty enum ??
                   23182: 
                   23183: // error('d', "%t no_of_enumerators: %d", en, en->no_of_enumerators);
                   23184:        if ( en->no_of_enumerators != 0 )
                   23185:                return 0;
                   23186: 
                   23187:        return 1;
                   23188: }
                   23189: 
                   23190: static Pname
                   23191: check_nested_type( Pname nm )
                   23192: {
                   23193: // error('d', "check nested type: %n ccl: %t", nm, ccl );
                   23194: 
                   23195:        Pname nx, n = ktbl->look(nm->string, NESTED);
                   23196:        if ( n == 0 || n == nm ) return nm;
                   23197: 
                   23198:        int cnt = 1;
                   23199:        for (nx = n; n; n=n->n_tbl_list ) 
                   23200:                if (n->n_key == NESTED) ++cnt;
                   23201: 
                   23202:        if ( cnt > 1 ) {
                   23203:                error( "ambiguous nested type %s (%d instances), use x::y syntax", nm->string, cnt );
                   23204:                error( 'i', "cannot recover from previous errors" );
                   23205:        }
                   23206:        else { 
                   23207:                TOK ntk;
                   23208:                Ptype tt = return_nstd_local_type(nx,ntk);
                   23209:                error('w', "use %t:: to access nested %k %s (anachronism)", tt->in_class, ntk, nx->string);
                   23210:        }
                   23211:        return nx;
                   23212: }
                   23213: 
                   23214: static int
                   23215: in_local_class( Pclass cl )
                   23216: {
                   23217:        if ( cl->lex_level )
                   23218:                return 1;
                   23219:        if ( cl->in_class )
                   23220:                return in_local_class( cl->in_class );
                   23221:        return 0;
                   23222: }
                   23223: 
                   23224: Pname
                   23225: do_nested_type( Pname n ) 
                   23226: {
                   23227:        Pname nn = n;
                   23228:        char *str = 0;
                   23229: 
                   23230: // error('d', "do_nested_type: %s in_typedef: %d ccl: %t", n->string, in_typedef, ccl );
                   23231:        if ( in_typedef && ccl->string[0]=='_'
                   23232:        &&  ccl->string[1]=='_'
                   23233:        &&  ccl->string[2]=='C') return n;
                   23234: 
                   23235:        if ( n->tp ) 
                   23236:         { // already a TNAME :
                   23237:          // hide existing instance, encode new instance
                   23238:          /*
                   23239:           * need handle the anomaly:
                   23240:           * class x;
                   23241:           * x *p;
                   23242:           * class y {
                   23243:           *    class x{ ... }; // oops
                   23244:           * };
                   23245:           */
                   23246:                if (n->tp->base==COBJ) {
                   23247:                        Pclass cl = Pclass(Pbase(n->tp)->b_name->tp);
                   23248:                        if (cl->defined == 0 && lasttk == AGGR) {
                   23249:                                error('w',"forwardD ofC%n resolved to nested%t::%s",n,ccl,n->string);
                   23250:                                cl->lcl = new char[9];
                   23251:                                strcpy(cl->lcl,"FUDGE007"); // license to hack
                   23252:                                n->lex_level=Pbase(n->tp)->b_name->lex_level=0;
                   23253:                                return n;
                   23254:                        }
                   23255:                } 
                   23256:                else if (n->tp->base==EOBJ) { // watch out for enum x;
                   23257:                        Penum en = Penum(Pbase(n->tp)->b_name->tp);
                   23258:                        if (en->defined == 0 && lasttk == ENUM) return n;
                   23259:                }
                   23260: 
                   23261:                nested_hide( n );
                   23262:                nn = new name( n->string );
                   23263:                str = make_nested_name( n->string, ccl );
                   23264:        }
                   23265:        else
                   23266:        // make sure we haven't already seen a nested instance
                   23267:        // if so, for transition, this needs to be an error
                   23268:        if (ktbl->look( n->string, NESTED ))
                   23269:                error("multiple type %s nestings (to do this define an empty class/enum %s {};)",n->string,n->string); 
                   23270:        if ( in_typedef ) {
                   23271:                if (strcmp(ccl->string, nn->string)==0) { // class x { typedef T x;
                   23272:                        error( "nested Tdef %s redefines immediately enclosing class", nn->string );
                   23273:                        error( 'i', "cannot recover from previous errors" );
                   23274:                }
                   23275: 
                   23276:                // make sure there isn't an identifier at global scope being defined
                   23277:                // by a nested typedef -- previously an error; keep it so for transition
                   23278:                Pname tn;
                   23279:                if ( n->tp == 0 && in_local_class(ccl)==0 &&
                   23280:                      (tn=gtbl->look(n->string,0))) {
                   23281:                        error( "nested Tdef %s redefinesG %n", n->string, tn );
                   23282:                        error( 'i', "cannot recover from previous errors" );
                   23283:                }
                   23284: 
                   23285:                nn->tpdef = new type;
                   23286:                nn->tpdef->nested_sig = str;
                   23287:                nn->tpdef->in_class = ccl;
                   23288:                nn->tpdef->lex_level = NESTED;
                   23289:                PERM(nn->tpdef);
                   23290:        }
                   23291:        else {
                   23292:                nn = nn->tname( lastval.t );
                   23293:                Pname tn = Pbase(nn->tp)->b_name;
                   23294:                Ptype tt = tn->tp;
                   23295:                if ( tt->defined && tt->in_class == ccl) {
                   23296:                        error( "nested %t redefines immediately enclosing class", nn->string );
                   23297:                        error( 'i', "cannot recover from previous errors" );
                   23298:                }
                   23299:                tt->nested_sig = str;
                   23300:                modified_tn = modified_tn->l;
                   23301:                nn->lex_level = tn->lex_level = 0;
                   23302:                nested_type = new name_list( nn, nested_type );
                   23303:        }
                   23304:        nn->n_key = NESTED;
                   23305:        return nn;
                   23306: }
                   23307: 
                   23308: static Pname dtor_seen;
                   23309: static int in_expr;
                   23310: extern int in_sizeof;
                   23311: 
                   23312: extern TOK
                   23313: lalex()
                   23314: /*  return next token to grammar  */
                   23315: {
                   23316:     register TOK tk;
                   23317:     if ( front == 0 )
                   23318:        add_tokens();           // extend lookahead queue
                   23319:     LDB(1,fprintf(stderr,"\n*** lalex()\n");showQ("before"));
                   23320: 
                   23321: gettok:
                   23322:     tk = deltok();
                   23323: // error('d',&curloc,"lalex: just got %k '%s' in_typedef: %d",tk,tk==ID?yylval.s:tk==TNAME?yylval.pn->string:"", in_typedef);
                   23324: 
                   23325:     if ( tk == ID || tk == TNAME ) 
                   23326:     {
                   23327:        TOK tk2 = la_look();
                   23328:        int lex_level = bl_level - in_class_decl - (tk2 == LC );
                   23329: 
                   23330:        if ( tk == TNAME )
                   23331:        {
                   23332: //error('d', "lalex tname %n;   lasttk: %k tk2: %k", yylval.pn, lasttk, tk2);
                   23333: //error('d', "    must_be_id: %d must_be_expr %d  decl_type %d",must_be_id,must_be_expr,DECL_TYPE);
                   23334: //error('d', "    bl_level: %d parsing_members %d",bl_level,parsing_class_members);
                   23335:            if ( tk2 == LP 
                   23336:                && (bl_level == 0 || parsing_class_members) 
                   23337:                && ( laexpr(lasttk) == 0 ) 
                   23338:                && must_be_expr == 0
                   23339:                && DECL_TYPE == 0 ) {
                   23340:                        if (la_decl()) {
                   23341:                                must_be_id = 0;
                   23342:                                DECL_TYPE = tk;
                   23343:                                tk = DECL_MARKER;
                   23344:                                goto ret;
                   23345:                        }
                   23346:            }
                   23347: 
                   23348:            // note: *** can handle local typedefs here, too!
                   23349:            if ( in_typedef && 
                   23350:                        in_typedef->base != 0 && 
                   23351:                        ccl && in_mem_fct == 0 &&
                   23352:                        (tk2 == SM || tk2 == RP || tk2 == LB))
                   23353:                                yylval.pn = do_nested_type(yylval.pn);
                   23354:        
                   23355:            if ( lasttk == AGGR || lasttk == ENUM ) {
                   23356:                if ( tk2 == LC || tk2 == COLON ) { // class definition  
                   23357:                        if ( lex_level 
                   23358:                                && (in_class_decl==0 || in_mem_fct)
                   23359:                                && lasttk != ENUM )  // temporary
                   23360:                                        yylval.pn = do_local_class( yylval.pn, lex_level );
                   23361:                        else 
                   23362:                        if ( in_class_decl && ccl )
                   23363:                                yylval.pn = do_nested_type( yylval.pn );
                   23364:                }
                   23365:            } 
                   23366: 
                   23367:           if (tk2 == LT) {
                   23368:              // a parametrized type name
                   23369:              if (template_tscope(yylval.pn,latok)) 
                   23370:                        tk = PTNAME ;
                   23371:           } else  
                   23372:           if ( tk2 == MEM || (tk2 == DOT && mem_sel == 0 )) {  
                   23373:                if (tk2==DOT)
                   23374:                        error(strict_opt?0:'w',"``.'' used for qualification; please use ``::'' (anachronism)");
                   23375: crunch:
                   23376:                tk = TSCOPE;
                   23377:                {//XXX -- should be modified to do lookup and del at each ::
                   23378:                  while ( (tk2 = lookahead()) == TSCOPE ) ;
                   23379:                  if ( tk2 == TNAME ) {
                   23380:                        tk2 = lookahead();
                   23381:                        if ( tk2 == LP 
                   23382:                        && (bl_level == 0 || parsing_class_members) 
                   23383:                        && ( laexpr(lasttk) == 0 ) 
                   23384:                        && must_be_expr == 0
                   23385:                        && DECL_TYPE == 0 ) {
                   23386:                                if (la_decl()) {
                   23387:                                        must_be_id = 0;
                   23388:                                        //DECL_TYPE = tk;//???
                   23389:                                        DECL_TYPE = TNAME;
                   23390:                                        //front should be ::
                   23391:                                        front->tok = TSCOPE;
                   23392:                                        front->retval.pn = yylval.pn;
                   23393:                                        yylval.pn = 0;
                   23394:                                        tk = DECL_MARKER;
                   23395:                                        goto ret;
                   23396:                                }
                   23397:                        }
                   23398:                  }
                   23399:                }
                   23400:                tk2 = deltok(1);
                   23401:                tk2 = la_look();
                   23402:                if ( tk2 == MUL ) {
                   23403:                        tk = MEMPTR;
                   23404:                        tk2 = deltok(1);
                   23405:                }
                   23406:            }
                   23407:            // Have a TNAME.  Check to be sure.
                   23408:            else if ( must_be_id ){
                   23409: //error('d',"lalex: must_be_id: <tname %n> <%k>",yylval.pn,tk2);
                   23410:                if ( in_class_decl 
                   23411:                        && lasttk == TYPE 
                   23412:                        && tk2 == LP
                   23413:                        && strcmp(yylval.pn->string,ccl->string) == 0 )
                   23414:                        error("%nK with returnT", yylval.pn);
                   23415: 
                   23416:                else if ( lasttk == TYPE && lastval.t == OVERLOAD
                   23417:                          && ( tk2 == SM || tk2 == LP ) )
                   23418:                        { 
                   23419:                        tk = ID;
                   23420:                        yylval.pn->hide();
                   23421:                        yylval.pn = new name( yylval.pn->string );
                   23422:                        yylval.pn->n_oper = TNAME;
                   23423:                        }
                   23424:                else if ( lasttk == OPERATOR ||
                   23425:                        in_typedef && yylval.pn->n_key == NESTED)
                   23426:                                must_be_id = 0;
                   23427:                else if ( lasttk != TSCOPE // watch out for X::X
                   23428:                     || lastval.pn != yylval.pn 
                   23429:                     || (in_typedef && 
                   23430:                                in_typedef->check( yylval.pn->tp,0) == 0 )) 
                   23431:                {
                   23432:                        tk = ID;
                   23433:                        if ( in_typedef && (lasttk == MUL || lasttk == REF)) {
                   23434:                                defer_check = 1;
                   23435:                                in_tag = yylval.pn;
                   23436:                        }
                   23437: 
                   23438:                        if ( lasttk == MEM && yylval.pn->lex_level ) {
                   23439:                                Pname nn = gtbl->look( yylval.pn->string, 0 );
                   23440:                                if (nn == 0 )
                   23441:                                        error( "%k%s undeclared", lasttk, yylval.pn->string);
                   23442:                                else
                   23443:                                        yylval.pn = nn;
                   23444:                        }
                   23445:                        else {
                   23446: // error('d',"lalex: else: lasttk: %k", lasttk );
                   23447:                                if (lasttk!=DOT && lasttk!=REF
                   23448:                                &&  lasttk!=TSCOPE && lasttk != GOTO ) {
                   23449:                                    // handle typedefs in basetype::check
                   23450:                                    //    when type is available
                   23451:                                    if (!in_typedef) {
                   23452: // error('d',"\"%s\" line %d: hiding%n",__FILE__,__LINE__,yylval.pn);
                   23453:                                        yylval.pn->hide();
                   23454:                                    }
                   23455:                                    yylval.pn = new name(yylval.pn->string);
                   23456:                                    yylval.pn->n_oper = TNAME;
                   23457:                                }
                   23458:                        }
                   23459:                        if ( defer_check ) defer_check = 0;
                   23460:                }
                   23461:            } // must_be_id
                   23462: 
                   23463:            if ( in_class_decl &&
                   23464:                ccl->lex_level &&
                   23465:                yylval.pn->lex_level != 0 && 
                   23466:                yylval.pn->tp && 
                   23467:                (yylval.pn->tp->base != COBJ && yylval.pn->tp->base != EOBJ)) 
                   23468:            {
                   23469:                Pname n = gtbl->look( yylval.pn->string,0);
                   23470:                if ( in_mem_fct ) {
                   23471:                     if (n && n->base == TNAME ) {
                   23472:                        error('w', "local typedef %n(%t) is not in scope of local class %s members; usingG (%t)", yylval.pn, yylval.pn->tp, ccl->string, n->tp );
                   23473:                        yylval.pn = n;
                   23474:                    } else
                   23475:                        error( "local typedef %sis not in scope of inline member function of local class %s", yylval.pn->string, ccl->string);
                   23476:                }
                   23477:            }
                   23478: 
                   23479:            // if we still have a TNAME, make sure have the right TNAME
                   23480:            // possibility of ananchronistic reference to nested type
                   23481:            Ptype nbt = yylval.pn->tp;
                   23482:            if (tk == TNAME && curr_scope == 0 && nbt && // Y y; not X::Y y;
                   23483:                (nbt->base == EOBJ || nbt->base == COBJ))
                   23484:            {
                   23485:                Ptype t = Pbase(nbt)->b_name->tp;
                   23486:                if ( ccl && t->in_class &&
                   23487:                        strcmp(t->in_class->string, ccl->string)) 
                   23488:                {
                   23489:                        switch( nbt->base ) {
                   23490:                                case COBJ:
                   23491:                                        if (is_empty(Pclass(t)))
                   23492:                                                yylval.pn = check_nested_type( yylval.pn );
                   23493:                                        break;
                   23494:                                case EOBJ:
                   23495:                                        if (is_empty(Penum(t)))
                   23496:                                                yylval.pn = check_nested_type( yylval.pn );
                   23497:                                        break;
                   23498:                        };
                   23499:                }
                   23500:            }
                   23501:         }
                   23502:        else 
                   23503:         { // tk == ID 
                   23504:                char *s = yylval.s;
                   23505:                Pname n = ktbl->look( s, HIDDEN );
                   23506:                Pname nstd = ktbl->look( s, NESTED );
                   23507: 
                   23508:                // inside a class definition, ccl, that is nested 
                   23509:                // s is a nested class name, and is the name of ccl
                   23510:                if (ccl && ccl->in_class && nstd && 
                   23511:                        strcmp(s, ccl->string)==0)
                   23512:                {
                   23513:                        for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
                   23514:                                Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ)
                   23515:                                                ? Pbase(nn->tp)->b_name->tp : nn->tpdef;
                   23516:                                Pclass cl = tt->in_class; 
                   23517:                                if ( nn->n_key != NESTED ) continue;
                   23518:                                if (strcmp(ccl->in_class->string,cl->string) == 0) {
                   23519:                                        tk = TNAME;
                   23520:                                        yylval.pn = nn;
                   23521:                                        n = nstd = nn;
                   23522:                                        }
                   23523:                        }
                   23524:                }
                   23525: 
                   23526:                if (tk2 == MEM) {
                   23527:                    // ID ::
                   23528:                    if (n) {
                   23529:                        yylval.pn = n;
                   23530:                /*XXX*/ goto crunch;
                   23531:                    } 
                   23532:                    else
                   23533:                    if (nstd &&
                   23534:                        nstd->n_tbl_list==0)
                   23535:                    {
                   23536:                        yylval.pn = nstd;
                   23537:                        tk = TSCOPE;
                   23538:                        tk2 = deltok(1);
                   23539:                        tk2 = la_look();
                   23540:                        if (tk2 == MUL ) {
                   23541:                                tk = MEMPTR;
                   23542:                                tk2 = deltok(1);
                   23543:                        }
                   23544:                    }
                   23545:                    else {
                   23546:                        error( "%s:: %sis not aTN", s, s ); 
                   23547:                        tk2 = deltok(1);
                   23548:                        goto gettok;
                   23549:                    }
                   23550:                } 
                   23551:                else  // transitional kludge
                   23552:                if ( n && nstd && n == nstd )  
                   23553:                        ; // null statement
                   23554: 
                   23555:                // Have an ID. Check last token to be sure.
                   23556:                else if (lasttk==ENUM || lasttk==AGGR &&
                   23557:                                // template <class id, class id>
                   23558:                                (tk2 != GT && tk2 != CM)) 
                   23559:                        {
                   23560:                        int fd = tk2!=LC && tk2!=COLON;
                   23561:                        tk = TNAME;
                   23562:                        if ( nstd ) { 
                   23563:                                // in transitional model, need flag this as error
                   23564:                                if ( fd == 0 ) { // real definition
                   23565:                                        if ( ccl == 0 )
                   23566:                                                error("nested andG%k %s(to do this placeG%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS, s); 
                   23567:                                        else
                   23568:                                                error("multiple nested%k %s(to do this placeG%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS,s); 
                   23569:                                        error( 'i', "cannot recover from previous errors" );
                   23570:                                }
                   23571:                        }
                   23572:                        else 
                   23573:                        // new tag, define it
                   23574:                        if (n==0 || 
                   23575:                                (n->n_template_arg == template_type_formal))
                   23576:                        {
                   23577: // error('d', "ccl: %t fd: %d, in_mem_fct: %d, in_class_decl: %d", ccl, fd, in_mem_fct, in_class_decl);
                   23578:                                n = new name( s );
                   23579:                                if ( fd )  // struct X*, etc.
                   23580:                                        n->lex_level=0; 
                   23581:                                else
                   23582:                                        n->lex_level=lex_level>=0?lex_level:0;
                   23583: 
                   23584:                                if ( ccl && fd == 0 && 
                   23585:                                        in_class_decl && 
                   23586:                        (bl_level == ccl->lex_level + in_class_decl + 1))
                   23587:                                                n = do_nested_type( n );
                   23588:                                else
                   23589:                                // note: ***** modify to handle local typedef
                   23590:                                // note: ***** add local enums
                   23591:                                if ( n->lex_level &&
                   23592:                                        lasttk != ENUM ) // temporary
                   23593:                                                n = do_local_class( n, n->lex_level );
                   23594:                                else {
                   23595:                                        n = n->tname( lastval.t );
                   23596:                                        modified_tn = modified_tn->l;
                   23597:                                        if (fd && gtbl->look(n->string,0)) statStat = n;
                   23598:                                }
                   23599:                        }
                   23600:                        else {
                   23601:                                if (n->tp->base!=COBJ && n->tp->base!=EOBJ) {
                   23602:                                        error( 'i', "hidden%n:%t",n,n->tp );
                   23603:                                        goto gettok;
                   23604:                                }
                   23605: 
                   23606:                                if ( tk2 == LC || tk2 == COLON ) { 
                   23607:                                        // class declared and hidden but not yet defined
                   23608:                                        // may have ctor defined which invalidates hiding
                   23609:                                        statStat = n;
                   23610:                                        n->n_key = 0; // inside class definition it cannot be hidden
                   23611:                                }
                   23612:                        }
                   23613:                        yylval.pn = nstd?nstd:n; 
                   23614:                }
                   23615:                else {
                   23616:                        tk = ID;
                   23617:                        yylval.pn = new name( s );
                   23618:                }
                   23619: 
                   23620:                if ( tk == ID ) 
                   23621:                {
                   23622:                    switch ( tk2 ) {
                   23623:                    case ID: case TNAME: case AGGR: case ENUM:
                   23624:                    {
                   23625:                        Pname n = 0; 
                   23626: 
                   23627:                        if ((curr_scope||ccl) && nstd) {
                   23628:                        // within class scope in which nested class is visible
                   23629:                        // curr_scope == set by TSCOPE, X::foo() { ... }
                   23630:                        // ccl == parsing class definition ``ccl''
                   23631: 
                   23632:                                char *str = curr_scope?curr_scope->string:ccl->string;
                   23633:                                for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
                   23634:                                        Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ)
                   23635:                                                        ? Pbase(nn->tp)->b_name->tp : nn->tpdef;
                   23636:                                        Pclass cl = tt->in_class; 
                   23637:                                        if ( nn->n_key != NESTED ) continue;
                   23638:                                        if ( strcmp(str,cl->string) == 0){      
                   23639:                                                tk = TNAME;
                   23640:                                                yylval.pn = nn;
                   23641:                                                if (lasttk == TYPE && 
                   23642:                                                        lastval.t == TYPEDEF )
                   23643:                                                                in_typedef = yylval.pn->tp;
                   23644:                                                break;
                   23645:                                        }
                   23646:                                }
                   23647:                        }
                   23648:                        if (tk == TNAME) break; // found nested class
                   23649: 
                   23650:                        n = ktbl->look( s, HIDDEN ); 
                   23651:                        if ( n ) {
                   23652:                                Pname nn = n;
                   23653:                                switch ( n->tp->base ) {
                   23654:                                        default:
                   23655:                                                error("typedef %sis not visible in this scope", s );
                   23656:                                                break;
                   23657:                                        case COBJ:
                   23658:                                                if (is_empty(Pclass(Pbase(n->tp)->b_name->tp)))
                   23659:                                                        n = check_nested_type( nn );
                   23660:                                                if (nn == n)
                   23661:                                                        error("%sis hidden: use struct %s%s", s,s,front->retval.s);
                   23662:                                                break;
                   23663:                                        case EOBJ:
                   23664:                                                if (is_empty(Penum(Pbase(n->tp)->b_name->tp)))
                   23665:                                                        n = check_nested_type( nn );
                   23666:                                                if (nn == n)
                   23667:                                                        error("%sis hidden: use enum %s%s", s,s,front->retval.s);
                   23668:                                                break;
                   23669:                                };
                   23670:                                tk = TNAME;
                   23671:                                yylval.pn = n;
                   23672:                        }
                   23673:                        else  
                   23674:                        if (n=ktbl->look(s,NESTED)) 
                   23675:                        {
                   23676:                                TOK ntk;
                   23677:                                bit ok = 0;
                   23678:                                Ptype tt = return_nstd_local_type(n,ntk);
                   23679:                                Pclass cl = tt->in_class; 
                   23680:                                if (ccl) {
                   23681:                                        // x::y unncessary with in_class,
                   23682:                                        // a derived class of in_class
                   23683:                                        // or classes enclosing in_class
                   23684:                                        if (ccl==cl || ccl->has_base(cl))
                   23685:                                                ok++;
                   23686:                                        else {
                   23687:                                        for (Pclass eccl=ccl->in_class;eccl; eccl=eccl->in_class)
                   23688:                                                if ( eccl == cl ) { ok++; break; }
                   23689:                                        }
                   23690:                                }
                   23691:                                if (!ok)
                   23692:                                        error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, n->string );
                   23693:                                tk = TNAME;
                   23694:                                yylval.pn = n;
                   23695:                        }
                   23696:                        else { // probably a typo
                   23697:                            if ( tk2 == ID )
                   23698:                                error("%s%s: %sis not aTN", s,front->retval.s,s);
                   23699:                            else if ( tk2 == TNAME )
                   23700:                                error("%s%s: %sis not aTN", s,front->retval.pn->string,s);
                   23701:                            else 
                   23702:                                error("%s%k: %sis not aTN", s,front->retval.t,s);
                   23703:                            goto gettok;
                   23704:                        }
                   23705:                         break;
                   23706:                    }
                   23707:                    case DOT: case REF:
                   23708:                         mem_sel = yylval.pn;
                   23709:                         break;
                   23710:                    default:
                   23711:                        if ( lasttk == TNAME && tk2 == LC )  
                   23712:                        {
                   23713:                                error("T%s %k: %s is unexpected", s, tk2, s );
                   23714:                                goto gettok;
                   23715:                        }
                   23716:                        
                   23717:                        // have an ID.  lets just make sure it should not be a TNAME
                   23718:                        if (curr_scope||ccl||nstd) {
                   23719:                                if (ccl && in_typedef && 
                   23720:                                        in_typedef->base != 0 &&  
                   23721:                                        in_mem_fct == 0 &&
                   23722:                                        (tk2 == SM || tk2 == RP || tk2 == LB)) 
                   23723:                                        {
                   23724:                                                yylval.pn = do_nested_type( yylval.pn );
                   23725:                                                tk = TNAME;
                   23726:                                        }
                   23727:                                else
                   23728:                                if (nstd && must_be_id == 0 && in_expr == 0) {
                   23729: // error('d',"nstd: %n must_be_id 0 have id tk2: %k lasttk: %k",nstd,tk2,lasttk);
                   23730: // error('d',"nstd: in_expr %d lex_level %d",in_expr,lex_level);
                   23731:                                        Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0);
                   23732:                                        for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
                   23733:                                                TOK ntk;
                   23734:                                                bit ok = 0;
                   23735:                                                Ptype tt = return_nstd_local_type(nn,ntk);
                   23736:                                                Pclass cl = tt->in_class; 
                   23737: // error('d',"xcl: %t ccl: %t", xcl, ccl );
                   23738:                                                if ( xcl ) {
                   23739:                                                        if (xcl==cl || xcl->has_base(cl) || ccl == cl)
                   23740:                                                                ok++;
                   23741:                                                        else {
                   23742:                                                        for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class)
                   23743:                                                                if ( eccl == cl ) { ok++; break; }
                   23744:                                                        }
                   23745:                                                }
                   23746:                                                        
                   23747:                                                if (nn == nstd)
                   23748:                                                {
                   23749:                                                if (
                   23750:                                                    // special case: foo(X,
                   23751:                                                    // in_arg_list not set until **after** X is handled
                   23752:                                                    ((in_arg_list || lasttk==LP) &&  // foo(nestedX
                   23753:                                                        (tk2==CM || tk2==ASSIGN || 
                   23754:                                                                (tk2==RP && lasttk!=MUL && lasttk!=REF))) 
                   23755:                                                    || // class x : public nestedX
                   23756:                                                        (tk2==LC && (lasttk==PR || lasttk==VIRTUAL))
                   23757:                                                    || // nestedX [*&]
                   23758:                                                        (tk2 == MUL || tk2==AND)
                   23759:                                                    || (lasttk==LP && tk2==RP)
                   23760:                                                    || (lasttk==TSCOPE && lastval.pn == nn) 
                   23761:                                                    || (lasttk==COMPL && dtor_seen == nn) 
                   23762:                                                    || (lasttk==TYPE && lastval.t == TYPEDEF)
                   23763:                                                     || lasttk == OPERATOR
                   23764:                                                    || lasttk == NEW || in_sizeof )
                   23765:                                                {  // must be type name, and it must be nested: 
                   23766:                                                        if ( nstd->n_tbl_list == 0 ) { // only one: ok
                   23767:                                                                if (lasttk != TSCOPE && !ok )
                   23768:                                                                        error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, nn->string);
                   23769:                                                                break;
                   23770:                                                        }
                   23771:                                                        else {
                   23772:                                                                if (lasttk != TSCOPE && lasttk != TYPE && !ok){
                   23773:                                                                        error("ambiguous nested type %s, use %t::%s",nn->string,xcl,nn->string);
                   23774:                                                                        error( 'i', "cannot recover from previous errors" );
                   23775:                                                                }
                   23776:                                                        }
                   23777:                                                }
                   23778: 
                   23779:                                            }
                   23780:                                                if ( nn->n_key != NESTED ) continue;
                   23781:                                                if (xcl && 
                   23782:                                                        strcmp(xcl->string,cl->string) == 0) break;
                   23783:                                        } // end: for nn = nstd
                   23784: 
                   23785:                                        if (nn) {
                   23786:                                                tk = TNAME;
                   23787:                                                yylval.pn = nn;
                   23788:                                                if (lasttk == TYPE && 
                   23789:                                                        lastval.t == TYPEDEF )
                   23790:                                                                in_typedef = yylval.pn->tp;
                   23791:                                        }
                   23792:                                }  // end: if (nstd)
                   23793:                        } // end: if (curr_scope||ccl)
                   23794:                         break;
                   23795:                    } // end: switch tk2
                   23796:                } // end: if (tk == ID)
                   23797:            }
                   23798: 
                   23799: // error('d',"testing for in_expr: in_expr: %d tk: %k", in_expr, tk );
                   23800: // error('d',"testing for in_expr: tk2: %k lasttk: %k", tk2, lasttk );
                   23801:            if (lex_level && tk==ID && tk2==LP &&
                   23802:                        (lasttk==LC || lasttk==RC || lasttk==RP ||
                   23803:                        lasttk == ASSIGN || lasttk == SM))
                   23804:                                in_expr = 1;
                   23805:            else in_expr = 0;
                   23806:        
                   23807:        }
                   23808:         if ( tk == TNAME || ( tk == TYPE && latype(yylval.t) )
                   23809: // XXX     || tk == TSCOPE || tk == MEM 
                   23810:           || tk == REF || tk == DOT || tk == GOTO 
                   23811:           || tk == MEMPTR )
                   23812:           // TNAME cannot immediately follow a type name,
                   23813:           // scope operator, right curly, selection, or goto
                   23814:                must_be_id = 1;
                   23815:        else
                   23816:                must_be_id = 0;
                   23817: 
                   23818:         switch ( tk ) {
                   23819:            case SM:
                   23820:                mem_sel = 0; // no break
                   23821:                in_expr = 0;
                   23822:            case RP: case RC: must_be_expr = 0; break;
                   23823:            case COLON: 
                   23824:                if  (lasttk == RP || 
                   23825:                    (lasttk == TYPE && lastval.t == CONST)) 
                   23826:                        must_be_expr = 1;
                   23827:                break;
                   23828:            case SIZEOF:
                   23829:                in_sizeof = 1;
                   23830:                break;
                   23831:        };
                   23832: ret:
                   23833:     if ( tk == COMPL && lasttk == TSCOPE )
                   23834:         dtor_seen = lastval.pn;
                   23835:     else dtor_seen = 0;
                   23836:     lasttk = tk;
                   23837:     lastval = yylval;
                   23838:     LDB(1,showQ("after");
                   23839:        fprintf(stderr,"returning '%s'",image(tk));
                   23840:        if ( tk==ID || tk==TNAME ) fprintf(stderr," -- '%s'",yylval.pn->string);
                   23841:        fprintf(stderr,"\n");
                   23842:     );
                   23843: // error('d',"returning tk: %k dtor_seen: %n", tk,dtor_seen );
                   23844:     return tk;
                   23845: }
                   23846: 
                   23847: extern void
                   23848: la_backup( TOK t, YYSTYPE r )
                   23849: /*
                   23850:     called by parser to push token back on front of queue
                   23851: */
                   23852: {
                   23853:     LDB(1,fprintf(stderr,"\n*** la_backup( '%s', ...)\n",image(t)));
                   23854:     if ( t == ID ) { Pname n = r.pn; r.s = n->string; DEL(n); }
                   23855:     register toknode* T = new toknode(t,r,curloc);
                   23856:     if (front) {
                   23857:        front->last = T;
                   23858:        T->next = front;
                   23859:        T->last = 0;
                   23860:        front = T;
                   23861:     } else
                   23862:        front = rear = T;
                   23863:     lasttk = 0;
                   23864: }
                   23865: 
                   23866: extern int
                   23867: la_sctype( TOK t )
                   23868: {
                   23869: //error('d',&latok->place,"la_sctype(%k ) -- latok ==%k",t,latok->tok);
                   23870:        if ( t != latok->tok && t != TSCOPE && t != MEMPTR )
                   23871:                error( 'i', &latok->place, "la_sctype, lalex.c" );
                   23872: 
                   23873:        switch( latok->retval.t ) {
                   23874:                case TYPEDEF:
                   23875:                case EXTERN:
                   23876:                case STATIC:
                   23877:                case AUTO:
                   23878:                case REGISTER:
                   23879:                case OVERLOAD:
                   23880:                case INLINE:
                   23881:                case FRIEND:
                   23882:                case CONST:
                   23883:                case VOLATILE:
                   23884:                        return 1; 
                   23885:                default:
                   23886:                        return 0; 
                   23887:        }
                   23888: }
                   23889: 
                   23890: extern int
                   23891: la_cast()
                   23892: /*
                   23893:        called in reduction of term_lp to check for ambiguous prefix-style cast
                   23894:        if result is 1, caller inserts DECL_MARKER to force reduction of cast
                   23895: */
                   23896: {
                   23897:        // yychar already designates TYPE or TNAME
                   23898:        // LP must start the lookahead queue!
                   23899:        LDB(1,fprintf(stderr,"\n*** la_cast()\n"););
                   23900:        int tk, tk2 = latok->tok;
                   23901: 
                   23902:        for ( ; ; ) {
                   23903:            tk = tk2;
                   23904:            tk2 = lookahead();
                   23905: 
                   23906:            switch( tk ) {
                   23907:            case LP:
                   23908:                if ( tk2 == MUL || tk2 == AND ||
                   23909:                        tk2 == TSCOPE || tk2 == MEMPTR )
                   23910:                    // T ( * ...
                   23911:                    // T ( C ::* ...
                   23912:                    continue;
                   23913:                else
                   23914:                    // T ( exp )
                   23915:                    return 0;
                   23916:            case MUL: case AND:
                   23917:                //if ( tk2 == SCTYPE )
                   23918:                if ( la_sctype( tk2 ) )
                   23919:                    // T ( * const ...
                   23920:                    // T ( * volatile ...
                   23921:                    tk2 = lookahead();
                   23922:                continue;
                   23923:            case MEMPTR:
                   23924:                if ( tk2 == RP ) continue;
                   23925:                break;
                   23926:            case TSCOPE:
                   23927:                if ( tk2 == MUL )
                   23928:                    // T ( C :: * ...
                   23929:                    continue;
                   23930:                else
                   23931:                    // T ( exp )
                   23932:                    return 0;
                   23933:            case RP: case LB:
                   23934:                // T (*)()
                   23935:                // T (*[])()
                   23936:                return 1;
                   23937:            }
                   23938: 
                   23939:            return 0;
                   23940:        }
                   23941: }
                   23942: 
                   23943: static int
                   23944: la_decl()
                   23945: /*
                   23946:        handles ambiguities
                   23947:                type (*x) ()
                   23948:                type (*x) []
                   23949:        at start of arg list / statement
                   23950:        return val == 1 if lookahead finds a declaration
                   23951:                (used for error messages only)
                   23952:        if declaration is "ambiguous" (i.e., can't be recognized with
                   23953:                1-symbol lookahead), insert DECL_MARKER to force reduction
                   23954:                of "type"
                   23955: */
                   23956: {
                   23957:        
                   23958:        // LP must start the lookahead queue!
                   23959:        LDB(1,fprintf(stderr,"\n*** la_decl()\n"););
                   23960:        int tk, tk2 = latok->tok;
                   23961:        int paren = 0;
                   23962:        int ptr = 0;
                   23963: 
                   23964:        for ( ; ; ) {
                   23965: 
                   23966:            tk = tk2;
                   23967:            tk2 = lookahead();
                   23968: 
                   23969: // fprintf(stderr,"\nla_decl:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]);
                   23970:            switch( tk ) {
                   23971:            case LP:
                   23972:                if ( tk2 == MUL || tk2 == AND || tk2 == TSCOPE ) {
                   23973:                    // T ( * ...
                   23974:                    ++paren;
                   23975:                    ptr = 1;
                   23976:                    continue;
                   23977:                } else
                   23978:                if ( tk2 == MEMPTR ) {
                   23979:                // T ( C ::*  ...
                   23980:                        return 1;
                   23981:                } else 
                   23982:                // possible redundant parens
                   23983:                if ( tk2 == ID && lookahead() == RP ) {
                   23984:                        TOK tp = lookahead();
                   23985: // error( 'd', "tp %k tk: %k tk2: %k", tp, tk, tk2 );
                   23986: // error( 'd', "bl_level: %d, in_class_decl: %d", bl_level,in_class_decl );
                   23987:                        if ( tp == SM || tp == CM || tp == ASSIGN )
                   23988:                        {
                   23989:                                // member initialization list
                   23990:                                if ( tp != SM && in_arg_list == 0 ) return 1;
                   23991:                        }
                   23992:                        else 
                   23993:                        if ( tp == RP && (bl_level-in_class_decl==0))
                   23994:                                return 1;
                   23995:                        if ( tp != LP ) 
                   23996:                                return 0;
                   23997:                        latok=latok->last; // restore lookahead
                   23998:                        ++paren;
                   23999:                        continue;
                   24000:                        }
                   24001:                else
                   24002:                    // T ( exp )
                   24003:                    return 0;
                   24004:            case MUL: case AND:
                   24005:                //if ( tk2 == SCTYPE )
                   24006:                if ( la_sctype( tk2 ))
                   24007:                    // T ( * const ...
                   24008:                    // T ( * volatile ...
                   24009:                    return 1;
                   24010:                else {
                   24011:                    ptr = 0;
                   24012:                    continue;
                   24013:                }
                   24014:            case MEMPTR:
                   24015:                // T ( C :: * ...
                   24016:                return 1;
                   24017:            case TSCOPE:
                   24018:                if ( tk2 == MUL ) //??tk SHOULD HAVE TRANSLATED TO MEMPTR!!
                   24019:                    // T ( C :: * ...
                   24020:                    return 1;
                   24021:                else if ( ptr )
                   24022:                    // T ( exp )
                   24023:                    return 0;
                   24024:                else if ( tk2 == ID || tk2 == OPERATOR )
                   24025:                    // T ( * C :: id ...
                   24026:                    continue;
                   24027:                else
                   24028:                    // error
                   24029:                    return 0;
                   24030:            }
                   24031: 
                   24032:            break;
                   24033:        }
                   24034: 
                   24035:        if ( tk == RP || tk == LB )
                   24036:            // T (*)()
                   24037:            // T (*[])()
                   24038:            return 1;
                   24039: 
                   24040:        if ( tk != ID && tk != OPERATOR )
                   24041:            // T ( exp )
                   24042:            return 0;
                   24043: 
                   24044:        if ( tk == OPERATOR )
                   24045:            switch ( tk2 ) {
                   24046:            case PLUS: case MINUS: case MUL: case REFMUL:
                   24047:             case AND: case OR: case ER: case SHIFTOP: case EQUOP: 
                   24048:            case DIVOP: case RELOP: case ANDAND: case OROR: 
                   24049:            case NOT: case COMPL: case ICOP: case ASSIGN: 
                   24050:             case ASOP: case NEW: case GNEW: case DELETE:
                   24051:                // OPERATOR oper
                   24052:                tk2 = lookahead();
                   24053:                break;
                   24054:            case LP:
                   24055:                // OPERATOR ()
                   24056:                tk2 = lookahead();
                   24057:                if ( tk2 == RP ) {
                   24058:                    tk2 = lookahead();
                   24059:                    break;
                   24060:                } else
                   24061:                    return 0;
                   24062:            case LB:
                   24063:                // OPERATOR []
                   24064:                tk2 = lookahead();
                   24065:                if ( tk2 == LB ) {
                   24066:                    tk2 = lookahead();
                   24067:                    break;
                   24068:                } else
                   24069:                    return 0;
                   24070:            default:    // illegal operator
                   24071:                return 0;
                   24072:            }
                   24073: 
                   24074:        int allow_lp = 1;
                   24075:        int allow_rp = 1;
                   24076:        for ( ; ; ) {
                   24077:            tk = tk2;
                   24078:            tk2 = lookahead();
                   24079: 
                   24080: // fprintf(stderr,"\nla_decl2:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]);
                   24081:            switch( tk ) {
                   24082:            case LP:
                   24083:                if ( !allow_lp )
                   24084:                    // T ( * id [ exp ] ( ...
                   24085:                    return 0;
                   24086: 
                   24087:                // Current lookahead will be a decl if
                   24088:                // the next lookahead is an arg decl
                   24089:                if ( tk2 == RP || tk2 == ENUM || tk2==AGGR 
                   24090:                        || tk2==ELLIPSIS || la_sctype( tk2 )) 
                   24091:                    // T ( * id ()
                   24092:                    // T ( * id ) ()
                   24093:                    return 1;
                   24094: 
                   24095:                if ( tk2 == TYPE || tk2 == TNAME ) {
                   24096:                    // T ( * id ) ( T2 ...
                   24097:                    if ( lookahead() == LP && !la_decl() )
                   24098:                        return 0;
                   24099:                    return 1;
                   24100:                }
                   24101: 
                   24102:                return 0;
                   24103:            case LB:
                   24104:                 if ( tk2 == RB || lookahead() == RB )
                   24105:                    // T ( * id [] ...
                   24106:                    return 1;
                   24107:                else {
                   24108:                    // T ( * id [ exp ] ...
                   24109:                    allow_lp = 0;
                   24110:                    allow_rp = 1;
                   24111:                    while ( lookahead() != RB );
                   24112:                    tk2 = lookahead();
                   24113:                    continue;
                   24114:                }
                   24115:            case RP:
                   24116: // error ('d', "rp: allow_rp: %d paren: %d", allow_rp, paren );
                   24117:                if ( !allow_rp || !paren )
                   24118:                    // T ( * id ) )
                   24119:                    return 0;
                   24120: // permit redundant parentheses
                   24121:                else 
                   24122:                if ( tk2 == SM || tk2 == CM || tk2 == ASSIGN )
                   24123:                        return 1;
                   24124:                else
                   24125:                if ( tk2 == RP && (bl_level-in_class_decl == 0))
                   24126:                        return 1;
                   24127:                else
                   24128:                {
                   24129:                    // T ( * id ) ...
                   24130:                    allow_lp = 1;
                   24131:                    allow_rp = 0;
                   24132:                    --paren;
                   24133:                    continue;
                   24134:                }
                   24135:            default:
                   24136:                return 0;
                   24137:            }
                   24138:        }
                   24139: }
                   24140: 
                   24141: 
                   24142: 
                   24143: /*
                   24144: **     PROCESSING OF INLINE MEMBER FUNCTIONS
                   24145: */
                   24146: static int la_snarf();
                   24147: 
                   24148: extern toknode*
                   24149: save_text()
                   24150: /*
                   24151:        save text of inline def on q of class
                   24152: */
                   24153: {
                   24154:        // Q should contain at least the tokens < FDEF, X ... >
                   24155:        // where X is either LC or COLON (start of ftn)
                   24156:        LDB(2,fprintf(stderr,"save_text()"));
                   24157:        LDB(3,fprintf(stderr,"front: %s",image(front->tok)));
                   24158:        LDB(3,fprintf(stderr,"front->next: %s",image(front->next->tok)));
                   24159:        latok = front->next;
                   24160:        if ( la_snarf() ) {
                   24161:                // append this set of tokens to
                   24162:                // inline tokenq for class
                   24163:                toknode* t = front; // FDEF
                   24164:                if ( ccl->c_funqf == 0 )
                   24165:                        ccl->c_funqf = front;
                   24166:                else {
                   24167:                        ccl->c_funqr->next = front;
                   24168:                        front->last = ccl->c_funqr;
                   24169:                }
                   24170:                ccl->c_funqr = latok;
                   24171:                front = latok->next;
                   24172:                latok->next = 0;
                   24173:                if (front)  front->last = 0;
                   24174:                return t;
                   24175:        }
                   24176:        return 0;
                   24177: }
                   24178: 
                   24179: 
                   24180: extern void
                   24181: restore_text()
                   24182: /*
                   24183:        restore tokens for member inlines onto token q
                   24184: */
                   24185: {
                   24186:        LDB(2,fprintf(stderr,"restore_text()"));
                   24187:        if (ccl->c_funqf == 0)  // no inlines on Q
                   24188:                return;
                   24189:        LDB(3,fprintf(stderr,"  Q present: %d,%d",ccl->c_funqf,ccl->c_funqr));
                   24190:        LDB(3,fprintf(stderr,"  front==%s",image(ccl->c_funqf->tok)));
                   24191:        LDB(3,fprintf(stderr,"  rear ==%s",image(ccl->c_funqr->tok)));
                   24192:        ccl->c_funqr->next = front;
                   24193:        if (front)  front->last = ccl->c_funqr;
                   24194:        front = ccl->c_funqf;
                   24195:        ccl->c_funqf = ccl->c_funqr = 0;
                   24196: }
                   24197: 
                   24198: 
                   24199: static void
                   24200: del_tokens( toknode* marker )
                   24201: /*
                   24202:     delete tokens from marker to latok, not inclusive
                   24203: */
                   24204: {
                   24205:     if ( marker == 0 || marker == latok || marker->next == 0 )
                   24206:        error('i', "bad token queue");
                   24207: 
                   24208:     LDB(2,fprintf(stderr,"del_tokens: %s..%s\n",image(marker->tok),image(latok->tok)));
                   24209: 
                   24210:     register toknode* tt = marker->next;
                   24211:     if ( tt == latok ) return;
                   24212:     marker->next = latok;
                   24213:     latok->last->next = 0;
                   24214:     latok->last = marker;
                   24215:     register toknode* tx = tt;
                   24216:     do {
                   24217:        LDB(3,fprintf(stderr,"  deleting %s\n",image(tt->tok)));
                   24218:        tx = tx->next;
                   24219:        delete tt;
                   24220:        tt = tx;
                   24221:     } while ( tx );
                   24222: }
                   24223: 
                   24224: 
                   24225: static int
                   24226: la_snarf()
                   24227: /*
                   24228:        scan function def without processing declarations
                   24229: */
                   24230: {
                   24231:        LDB(2,fprintf(stderr,"la_snarf()"));
                   24232:        loc *L = &latok->place;
                   24233:        //DBPLACE(1,L.l,L.f);
                   24234:        int parens = 0;
                   24235:        int paren_error = 0;
                   24236:        toknode* marker = latok;
                   24237:        switch ( latok->tok ) {
                   24238:        default:
                   24239:                error('i', L, "bad token Q snarfing function: %d", latok->tok);
                   24240:        case COLON:
                   24241:                break;
                   24242:        case LC:
                   24243:                --bl_level;
                   24244:                goto eatf;
                   24245:        }
                   24246:        LDB(2,fprintf(stderr,"\"eat\" member initializers"));
                   24247:        for (;;) {
                   24248:                if (latok->next == 0) add_tokens();
                   24249:                switch ( (latok=latok->next)->tok ) {
                   24250:                case LP:
                   24251:                        ++parens;
                   24252:                default:
                   24253:                        LDB(3,fprintf(stderr,"...%s",image(latok->tok)));
                   24254:                        continue;
                   24255:                case RP:
                   24256:                        if ( (--parens < 0) && (paren_error++ == 0) )
                   24257:                                error(0,&latok->place,"unbalanced ()");
                   24258:                        continue;
                   24259:                case LC:
                   24260:                case RC:
                   24261:                        if ( parens <= 0 )
                   24262:                                goto eatf;
                   24263:                        continue;
                   24264:                case SM:
                   24265:                        if ( parens <= 0 ) {
                   24266:                                error(0, L, "illegal bit field");
                   24267:                                del_tokens( front );
                   24268:                                delete front;
                   24269:                                front = latok;
                   24270:                                front->last = 0;
                   24271:                                return 0;
                   24272:                        }
                   24273:                        continue;
                   24274:                case EOFTOK:
                   24275:                        error('i',&latok->place,"unexpected end of file");
                   24276:                } // switch
                   24277:        } // for
                   24278: 
                   24279:        eatf:
                   24280:        int level = 1;
                   24281:        for (;;) {
                   24282:                if (latok->next == 0) add_tokens();
                   24283:                switch ( (latok=latok->next)->tok ) {
                   24284:                case LC:
                   24285:                        ++level;
                   24286:                default:
                   24287:                        LDB(3,fprintf(stderr,"...%s",image(latok->tok)));
                   24288:                        continue;
                   24289:                case RC:
                   24290:                        LDB(3,fprintf(stderr,"...RC"));
                   24291:                        if (--level <= 0) {
                   24292:                                if (level < 0) {
                   24293:                                        error(0,&latok->place,"unexpected '}'");
                   24294:                                        goto bad;
                   24295:                                }
                   24296:                                return 1;
                   24297:                        }
                   24298:                        break;
                   24299:                case EOFTOK:
                   24300:                        error('e', &latok->place, "unbalanced {}");
                   24301:                        goto bad;
                   24302:                } // switch
                   24303:        } // for
                   24304:        bad:
                   24305:                del_tokens( marker );
                   24306:                marker->tok = SM;
                   24307:                return 0;
                   24308: }
                   24309: 
                   24310: Pname check_for_nested( Pname nstd, TOK lasttk, YYSTYPE lastval, TOK tk2)
                   24311: {
                   24312: // error('d',"nstd: %n must_be_id 0 tk2: %k lasttk: %d",nstd,tk2,lasttk);
                   24313:        TOK tk = ID;
                   24314:        Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0);
                   24315: 
                   24316:        for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
                   24317:                TOK ntk;
                   24318:                bit ok = 0;
                   24319:                Ptype tt = return_nstd_local_type(nn,ntk);
                   24320:                Pclass cl = tt->in_class; 
                   24321:                if ( xcl ) {
                   24322:                        if (xcl==cl || xcl->has_base(cl))
                   24323:                                ok++;
                   24324:                        else {
                   24325:                                for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class)
                   24326:                                if ( eccl == cl ) { ok++; break; }
                   24327:                        }
                   24328:                }
                   24329:                                                        
                   24330:                if (nn == nstd)
                   24331:                {
                   24332:                        if ( ((in_arg_list || lasttk==LP) &&  // foo(nestedX
                   24333:                                (tk2==CM || tk2==ASSIGN || tk2==RP)) 
                   24334:                            || (tk2==LC && (lasttk==PR || lasttk==VIRTUAL))
                   24335:                            || (tk2 == MUL || tk2==AND)
                   24336:                            || (lasttk==LP && tk2==RP)
                   24337:                            || (lasttk==TSCOPE && lastval.pn == nn) 
                   24338:                            || (lasttk==COMPL && dtor_seen == nn) 
                   24339:                            || (lasttk==TYPE && lastval.t == TYPEDEF)
                   24340:                            || lasttk == NEW || in_sizeof )
                   24341:                        {  
                   24342:                                if ( nstd->n_tbl_list == 0 ) { // only one: ok
                   24343:                                        break;
                   24344:                                } else {
                   24345:                                        if (lasttk != TSCOPE && !ok){
                   24346:                                                error("ambiguous nested type %s, use X::%s",nn->string,nn->string);
                   24347:                                                error( 'i', "cannot recover from previous errors" );
                   24348:                                        }
                   24349:                                }
                   24350:                        }
                   24351:                }
                   24352:                if ( nn->n_key != NESTED ) continue;
                   24353:                if (xcl && strcmp(xcl->string,cl->string) == 0) break;
                   24354:        } // end: for nn = nstd
                   24355:        return nn;
                   24356: }
                   24357: 
                   24358: 0707071010112044341004440001630000160000010203200466055404200000600000066146lex.c/*ident      "@(#)ctrans:src/lex.c   1.4" */
                   24359: /***************************************************************************
                   24360: 
                   24361:        C++ source for cfront, the C++ compiler front-end
                   24362:        written in the computer science research center of Bell Labs
                   24363: 
                   24364:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   24365:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   24366: 
                   24367: lex.c:
                   24368:        lexical analyser based on pcc's and cpre's scanners
                   24369:        modified to handle classes:
                   24370:        new keywords:   class
                   24371:                        public
                   24372:                        call
                   24373:                        etc.
                   24374:        names are not entered in the symbol table by lex()
                   24375:        names can be of arbitrary length
                   24376:        error() is used to report errors
                   24377:        {} and () must match
                   24378:        numeric constants are not converted into internal representation
                   24379:        but stored as strings
                   24380: 
                   24381: ****************************************************************************/
                   24382: 
                   24383: #include "cfront.h"
                   24384: #include "yystype.h"
                   24385: #include "size.h"
                   24386: #include "tqueue.h"
                   24387: #include "template.h"
                   24388: 
                   24389: # define  CCTRANS(x) x
                   24390: #define copy_if_need_be(s)  ((templp->in_progress || templp->parameters_in_progress) ? strdup(s) : (s))
                   24391: 
                   24392:        /* lexical actions */
                   24393: 
                   24394: #define A_ERR  0               /* illegal character */
                   24395: #define A_LET  1               /* saw a letter */
                   24396: #define A_DIG  2               /* saw a digit */
                   24397: #define A_1C   3               /* return a single character */
                   24398: #define A_STR  4               /* string */
                   24399: #define A_CC   5               /* character constant */
                   24400: #define A_BCD  6               /* GCOS BCD constant */
                   24401: #define A_SL   7               /* saw a / */
                   24402: #define A_DOT  8               /* saw a . */
                   24403: #define A_2C   9               /* possible two character symbol */
                   24404: #define A_WS   10              /* whitespace (not \n) */
                   24405: #define A_NL   11              /* \n */
                   24406: #define A_LC   12              /* { */
                   24407: #define A_RC   13              /* } */
                   24408: #define A_L    14              /* ( */
                   24409: #define A_R    15              /* ) */
                   24410: #define A_EOF  16
                   24411: #define A_ASS  17
                   24412: #define A_LT   18
                   24413: #define A_GT   19              /* > */
                   24414: #define A_ER   20
                   24415: #define A_OR   21
                   24416: #define A_AND  22
                   24417: #define A_MOD  23
                   24418: #define A_NOT  24
                   24419: #define A_MIN  25
                   24420: #define A_MUL  26
                   24421: #define A_PL   27
                   24422: #define A_COL  28              /* : */
                   24423: #define A_SHARP        29              /* # */
                   24424: #define A_DOLL  30              /* $ */
                   24425: 
                   24426:        /* character classes */
                   24427: 
                   24428: # define LEXLET 01
                   24429: # define LEXDIG 02
                   24430: /* no LEXOCT because 8 and 9 used to be octal digits */
                   24431: # define LEXHEX 010
                   24432: # define LEXWS 020
                   24433: # define LEXDOT 040
                   24434: 
                   24435: const FIRSTCHUNK = 8*1024-8;
                   24436: const BUFCHUNK = 4*1024-8;
                   24437: 
                   24438:        /* text buffer */
                   24439: static char inbuf[FIRSTCHUNK/*TBUFSZ*/];
                   24440: static char* txtmax = &inbuf[FIRSTCHUNK/*TBUFSZ*/-1];
                   24441: static char* txtstart = 0;
                   24442: static char* txtfree = 0;
                   24443: 
                   24444: static struct buf* bufhead;
                   24445: static buf* freebuf;
                   24446: //static bufs;
                   24447: 
                   24448: struct buf {
                   24449:        buf* next;
                   24450:        char chars[BUFCHUNK];
                   24451: //     buf() { next=bufhead; bufhead=this; }
                   24452: };
                   24453: 
                   24454: new_buf(char c)
                   24455: {
                   24456: //fprintf(stderr,"new_buf %d\n",bufs++);
                   24457:        buf* pbuf;
                   24458:        if (freebuf) {
                   24459:                pbuf = freebuf;
                   24460:                freebuf = freebuf->next;
                   24461:        }
                   24462:        else
                   24463:                pbuf = new buf; // allocate and register new chunk
                   24464:        pbuf->next = bufhead;
                   24465:        bufhead = pbuf;
                   24466: 
                   24467:        if (BUFCHUNK < txtmax-txtstart) error('l',"lexical token too long");
                   24468: 
                   24469:        // copy current token:
                   24470:        char* p = txtstart;
                   24471:        txtstart = txtfree = &pbuf->chars[0];
                   24472:        while (p<txtmax) *txtfree++ = *p++;
                   24473:        *txtfree++=c;
                   24474:        txtmax = &pbuf->chars[BUFCHUNK-1];
                   24475:        return 0;
                   24476: }
                   24477: 
                   24478: 
                   24479: #define pch(c) ((txtmax<=txtfree)?new_buf(c):(*txtfree++=c))
                   24480: #define start_txt()    txtstart = txtfree
                   24481: #define del_txt()      txtfree = txtstart
                   24482: 
                   24483: static int Nfile;// = 1;
                   24484: static char* file_name[MAXFILE*4];     // source file names
                   24485:                                        // file_name[0] == src_file_name
                   24486:                                        // file_name[0] == 0 means stdin
                   24487: static short file_stack[MAXFILE];      // stack of file name indices
                   24488: static int tcurr_file;                 // current index in file_stack
                   24489:                                        // that is current #include nest level
                   24490: 
                   24491: Linkage linkage = linkage_default; // linkage is default C++   
                   24492: const LINKMAX = 10;
                   24493: static Linkage lvec[LINKMAX] = { linkage_default };
                   24494: static int lcount = 0;
                   24495: 
                   24496: void set_linkage(char* p)
                   24497: {
                   24498:        if (p==0 || *p == 0) {  // resume previous linkage
                   24499:                if (lcount>0) linkage = lvec[--lcount];
                   24500:        }
                   24501:        else {
                   24502:                if (LINKMAX<=++lcount) {
                   24503:                        error('l',"linkage directive nested too deep");
                   24504:                        --lcount;
                   24505:                } else if (strcmp(p,"C")==0)
                   24506:                        lvec[lcount] = linkage = linkage_C;
                   24507:                else if (strcmp(p,"C++")==0)
                   24508:                        lvec[lcount] = linkage = linkage_Cplusplus;
                   24509:                else {
                   24510:                        error("%s linkage",p);
                   24511:                        --lcount;
                   24512:                }
                   24513:        }
                   24514: }
                   24515: 
                   24516: static struct loc tloc;
                   24517: FILE * out_file = stdout;
                   24518: FILE * in_file = stdin;
                   24519: Ptable ktbl;
                   24520: Ptable keyword_table;
                   24521: 
                   24522: static int p_level = 0;                /* number of unmatched ``(''s */
                   24523: static int b_level = 0;                /* number of unmatched ``{''s */
                   24524: 
                   24525: # ifdef ibm
                   24526: 
                   24527: # define CSMASK 0377
                   24528: # define CSSZ 256
                   24529: 
                   24530: # else
                   24531: 
                   24532: # define CSMASK 0177
                   24533: # define CSSZ 128
                   24534: 
                   24535: # endif
                   24536: 
                   24537: static short lxmask[CSSZ+1];
                   24538: 
                   24539: int saved = 0; /* putback character, avoid ungetchar */
                   24540: static int lxtitle();
                   24541: 
                   24542: // overload rt;
                   24543: inline YYSTYPE rt(char* x) { YYSTYPE y; y.s  = x;        return y; }
                   24544: inline YYSTYPE rt(int   x) { YYSTYPE y; y.t  = x;        return y; }
                   24545: inline YYSTYPE rt(loc   x) { YYSTYPE y; y.l  = x;        return y; }
                   24546: inline YYSTYPE rt(void* x) { YYSTYPE y; y.pn = Pname(x); return y; }
                   24547: 
                   24548: #define get(c)         (c=getc(in_file))
                   24549: #define unget(c)       ungetc(c,in_file)
                   24550: 
                   24551: #define reti(a,b)      { addtok(a, rt(b), tloc);          return a; }
                   24552: #define retn(a,b)      { addtok(a, rt((Pnode)b), tloc);   return a; }
                   24553: #define rets(a,b)      { addtok(a, rt(b), tloc);          return a; }
                   24554: #define retl(a)                { addtok(a, rt(tloc), tloc);       return a; }
                   24555: 
                   24556: // keys[] holds the external form for tokens with fixed representation 
                   24557: // illegal tokens and those with variable representation have 0 entries
                   24558: char* keys[MAXTOK+1];
                   24559: 
                   24560: static void 
                   24561: new_key(char* s, TOK toknum, TOK yyclass)
                   24562: /*
                   24563:   make "s" a new keyword with the representation (token) "toknum"
                   24564:   "yyclass" is the yacc token (for example new_key("int",INT,TYPE); )
                   24565:   "yyclass==0" means yyclass=toknum;
                   24566: */
                   24567: {
                   24568:        Pname n = new name(s);
                   24569: 
                   24570:        keys[(toknum==LOC)?yyclass:toknum] = s;
                   24571:        n = new name(s);
                   24572:        Pname nn = keyword_table->insert(n,0);
                   24573:        // if (Nold) error('i',"keyword %sD twice",s);
                   24574:        nn->base = toknum;
                   24575:        nn->syn_class = (yyclass) ? yyclass : toknum;
                   24576:        delete n;
                   24577: }
                   24578: 
                   24579: const int keyword_count = 67;
                   24580: static void 
                   24581: ktbl_init()
                   24582: /*
                   24583:        enter keywords into keyword table for use by lex()
                   24584:        and into keyword representation table used for output
                   24585:  
                   24586:         ktbl is only for types. We put nothing in it. 
                   24587:        keyword_table is for user-defined reserved words 
                   24588: */
                   24589: {
                   24590:        ktbl = new table(KTBLSIZE,0,0);
                   24591:        keyword_table = new table(keyword_count,0,0);
                   24592: 
                   24593:        new_key("asm",ASM,0);
                   24594:        new_key("auto",AUTO,TYPE);
                   24595:        new_key("break",LOC,BREAK);
                   24596:        new_key("case",LOC,CASE);
                   24597:        new_key("continue",LOC,CONTINUE);
                   24598:        new_key("char",CHAR,TYPE);
                   24599:        new_key("do",LOC,DO);
                   24600:        new_key("double",DOUBLE,TYPE);
                   24601:        new_key("default",LOC,DEFAULT);
                   24602:        new_key("enum",ENUM,0);
                   24603:        new_key("else",LOC,ELSE);
                   24604:        new_key("extern",EXTERN,TYPE);
                   24605:        new_key("float",FLOAT,TYPE);
                   24606:        new_key("for",LOC,FOR);
                   24607:        new_key("goto",LOC,GOTO);
                   24608:        new_key("catch",CATCH,CATCH);
                   24609:        new_key("try",TRY,TRY);
                   24610:        new_key("if",LOC,IF);
                   24611:        new_key("int",INT,TYPE);
                   24612:        new_key("long",LONG,TYPE);
                   24613:        new_key("return",LOC,RETURN);
                   24614:        new_key("register",REGISTER,TYPE);
                   24615:        new_key("static",STATIC,TYPE);
                   24616:        new_key("struct",STRUCT,AGGR);
                   24617:        new_key("sizeof",SIZEOF,0);
                   24618:        new_key("short",SHORT,TYPE);
                   24619:        new_key("switch",LOC,SWITCH);
                   24620:        new_key("typedef",TYPEDEF,TYPE);
                   24621:        new_key("unsigned",UNSIGNED,TYPE);
                   24622:        new_key("union",UNION,AGGR);
                   24623:        new_key("void",VOID,TYPE);
                   24624:        new_key("while",LOC,WHILE);
                   24625: 
                   24626:        new_key("class",CLASS,AGGR);
                   24627:        new_key("const",CONST,TYPE);
                   24628:        new_key("delete",LOC,DELETE);
                   24629:        new_key("friend",FRIEND,TYPE);
                   24630:        new_key("inline",INLINE,TYPE);
                   24631:        new_key("new",NEW,0);
                   24632:        new_key("operator",OPERATOR,0);
                   24633:        new_key("overload",OVERLOAD,TYPE);
                   24634:        new_key("private",PRIVATE,PR);
                   24635:        new_key("protected",PROTECTED,PR);
                   24636:        new_key("public",PUBLIC,PR);
                   24637:        new_key("signed",SIGNED,TYPE);
                   24638:        new_key("template",TEMPLATE,0);
                   24639:        new_key("this",THIS,0);
                   24640:        new_key("virtual",VIRTUAL,TYPE);
                   24641:        new_key("volatile",VOLATILE,TYPE);
                   24642: 
                   24643:        new_key("__statement", STATEMENT, 0) ;
                   24644:        new_key("__expression", EXPRESSION, 0) ;
                   24645:        new_key("__template_test", TEMPLATE_TEST, 0) ;
                   24646: }
                   24647: 
                   24648: loc last_line;
                   24649: loc noloc = { 0, 0 };
                   24650: 
                   24651: void loc::putline()
                   24652: {
                   24653:        if (file==0 && line==0) return;
                   24654: //   fix, Nfile, not MAXFILE; Nfile == MAXFILE*4
                   24655: //     if (0<=file && file<MAXFILE) {
                   24656:        if ( 0<=file && file <= Nfile ) {
                   24657:                char* f = file_name[file];
                   24658:                if (f==0) f = src_file_name;
                   24659:                fprintf(out_file,line_format,line,f);
                   24660:                last_line = *this;
                   24661:        }
                   24662: }
                   24663: 
                   24664: void loc::put(FILE* p)
                   24665: {
                   24666: //    fix, Nfile, not MAXFILE; Nfile == MAXFILE*4
                   24667: //     if (0<=file && file<MAXFILE) {
                   24668:        if ( 0<=file && file <= Nfile ) {
                   24669:                char* f = file_name[file];
                   24670:                if (f==0) f = src_file_name;
                   24671:                fprintf(p,"\"%s\", line %d: ",f,line);
                   24672:        }
                   24673: }
                   24674: 
                   24675: void lxenter(register char* s, short m)
                   24676: /* enter a mask into lxmask */
                   24677: {
                   24678:        register c;
                   24679: 
                   24680:        while( c= *s++ ) lxmask[c+1] |= m;
                   24681: 
                   24682: }
                   24683: 
                   24684: 
                   24685: void lxget(register c, register m)
                   24686: /*
                   24687:        put 'c' back then scan for members of character class 'm'
                   24688:        terminate the string read with \0
                   24689:        txtfree points to the character position after that \0
                   24690: */
                   24691: {
                   24692:        pch(c);
                   24693:        while ( (get(c), lxmask[c+1]&m) ) pch(c);
                   24694:        unget(c);
                   24695:        pch('\0');
                   24696: }
                   24697: 
                   24698: struct LXDOPE {
                   24699:        short lxch;     /* the character */
                   24700:        short lxact;    /* the action to be performed */
                   24701:        TOK   lxtok;    /* the token number to be returned */
                   24702: } lxdope[] = {
                   24703: #ifdef apollo
                   24704:        '@',    A_ERR,  0,      /* illegal characters go here... */
                   24705: #else
                   24706:          '$',    A_DOLL, 0,
                   24707: //       '$',    A_ERR,  0,      /* illegal characters go here... */
                   24708: #endif
                   24709:        '_',    A_LET,  0,      /* letters point here */
                   24710:        '0',    A_DIG,  0,      /* digits point here */
                   24711:        ' ',    A_WS,   0,      /* whitespace goes here */
                   24712:        '\n',   A_NL,   0,
                   24713:        '"',    A_STR,  0,      /* character string */
                   24714:        '\'',   A_CC,   0,      /* ASCII character constant */
                   24715:        '`',    A_BCD,  0,      /* 'foreign' character constant, e.g. BCD */
                   24716:        '(',    A_L,    LP,
                   24717:        ')',    A_R,    RP,
                   24718:        '{',    A_LC,   LC,
                   24719:        '}',    A_RC,   RC,
                   24720:        '[',    A_1C,   LB,
                   24721:        ']',    A_1C,   RB,
                   24722:        '*',    A_MUL,  MUL,
                   24723:        '?',    A_1C,   QUEST,
                   24724:        ':',    A_COL,  COLON,
                   24725:        '+',    A_PL,   PLUS,
                   24726:        '-',    A_MIN,  MINUS,
                   24727:        '/',    A_SL,   DIV,
                   24728:        '%',    A_MOD,  MOD,
                   24729:        '&',    A_AND,  AND,
                   24730:        '|',    A_OR,   OR,
                   24731:        '^',    A_ER,   ER,
                   24732:        '!',    A_NOT,  NOT,
                   24733:        '~',    A_1C,   COMPL,
                   24734:        ',',    A_1C,   CM,
                   24735:        ';',    A_1C,   SM,
                   24736:        '.',    A_DOT,  DOT,
                   24737:        '<',    A_LT,   LT,
                   24738:        '>',    A_GT,   GT,
                   24739:        '=',    A_ASS,  ASSIGN,
                   24740:        '#',    A_SHARP, 0,
                   24741:        EOF,    A_EOF,  EOFTOK
                   24742:        };
                   24743: /* note: EOF is used as sentinel, so must be <=0 and last entry in table */
                   24744: 
                   24745: static struct LXDOPE *lxcp[CSSZ+1];
                   24746: 
                   24747: void 
                   24748: lex_init()
                   24749: {
                   24750:        register struct LXDOPE *p;
                   24751:        register i;
                   24752:        register char *cp;
                   24753:        /* set up character classes */
                   24754: 
                   24755:        /* first clear lexmask */
                   24756:        for(i=0; i<=CSSZ; i++) lxmask[i] = 0;
                   24757: 
                   24758: #ifdef apollo
                   24759:        lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$", LEXLET );
                   24760: #else
                   24761:        lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET );
                   24762: #endif
                   24763:        lxenter( "0123456789", LEXDIG );
                   24764:        lxenter( "0123456789abcdefABCDEF", LEXHEX );
                   24765:                /* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */
                   24766:        lxenter( " \t\r\b\f\013", LEXWS );
                   24767:        lxmask['.'+1] |= LEXDOT;
                   24768: 
                   24769:        /* make lxcp point to appropriate lxdope entry for each character */
                   24770: 
                   24771:        /* initialize error entries */
                   24772: 
                   24773:        for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
                   24774: 
                   24775:        /* make unique entries */
                   24776: 
                   24777:        for( p=lxdope; ; ++p ) {
                   24778:                lxcp[p->lxch+1] = p;
                   24779:                if( p->lxch < 0 ) break;
                   24780:        }
                   24781: 
                   24782:        /* handle letters, digits, and whitespace */
                   24783:        /* by convention, first, second, and third places */
                   24784: 
                   24785:        cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
                   24786:        while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
                   24787:        cp = "123456789";
                   24788:        while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
                   24789:        cp = "\t\b\r\f\013";
                   24790:        while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
                   24791: 
                   24792:        file_name[0] = src_file_name;
                   24793:        // set both curloc and tloc so curloc is valid at program startup
                   24794: //     curloc.file = tloc.file = 0;
                   24795:        curloc.line = tloc.line = 1;
                   24796: 
                   24797:        ktbl_init();
                   24798:        lex_clear();
                   24799:        saved = lxtitle();
                   24800: }
                   24801: 
                   24802: void lex_clear()
                   24803: {
                   24804:        // delete extra buffers:
                   24805:        buf* p = bufhead;       
                   24806:        bufhead = 0;
                   24807: //if (p) {
                   24808: //fprintf(stderr,"lex_clear\n");
                   24809: //bufs=0;
                   24810: //}
                   24811:        while (p) {
                   24812:                buf* pp = p;
                   24813:                p = p->next;
                   24814:                pp->next = freebuf;
                   24815:                freebuf = pp;
                   24816:        }
                   24817: 
                   24818:        // re-set to static buffer:
                   24819:        txtstart = txtfree = inbuf;
                   24820:        txtmax = &inbuf[FIRSTCHUNK/*TBUFSZ*/-1];
                   24821: }
                   24822: 
                   24823: int int_val(char hex)
                   24824: {
                   24825:        switch (hex) {
                   24826:        case '0': case '1': case '2': case '3': case '4':
                   24827:        case '5': case '6': case '7': case '8': case '9':
                   24828:                return hex-'0';
                   24829:        case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
                   24830:                return hex-'a'+10;
                   24831:        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
                   24832:                return hex-'A'+10;
                   24833:        }
                   24834: }
                   24835: 
                   24836: void hex_to_oct()
                   24837: /*
                   24838:        \x has been seen on input (in char const or string) and \ printed
                   24839:        read the following hexadecimal integer and replace it with an octal
                   24840: */
                   24841: {
                   24842:        int i = 0;
                   24843:        int c;
                   24844:        get(c);
                   24845:        if (lxmask[c+1] & LEXHEX) {
                   24846:                i = int_val(c);
                   24847:                get(c);                                 // try for two
                   24848:                if (lxmask[c+1] & LEXHEX) {
                   24849:                        i = (i<<4) + int_val(c);
                   24850:                        get(c);                         // try for three
                   24851:                        if (lxmask[c+1] & LEXHEX)
                   24852:                                i = (i<<4) + int_val(c);
                   24853:                        else
                   24854:                                unget(c);
                   24855:                }
                   24856:                else
                   24857:                        unget(c);
                   24858:        }
                   24859:        else {
                   24860:                error("hexadecimal digitE after \\x");
                   24861:                unget(c);
                   24862:        }
                   24863: 
                   24864: //     if (0377 < i) error('l',"hexadecimal constant too large");
                   24865:        i &= 0377;
                   24866: 
                   24867:        pch(('0'+(i>>6)));
                   24868:        pch(('0'+((i&070)>>3)));
                   24869:        pch(('0'+(i&7)));
                   24870: }
                   24871: 
                   24872: 
                   24873: char * chconst()
                   24874: /*
                   24875:        read a character constant into inbuf
                   24876: */
                   24877: {
                   24878:        register c;
                   24879:        int nch = 0;
                   24880: 
                   24881:        pch('\'');
                   24882: 
                   24883:        for(;;) {
                   24884:                char* p;
                   24885:                char cc = 0;
                   24886: 
                   24887:                switch (get(c)) {
                   24888:                case '\'':
                   24889:                        goto ex;
                   24890:                case EOF:
                   24891:                        error("eof in char constant");
                   24892:                        goto ex;
                   24893:                case '\n':
                   24894:                        error("newline in char constant");
                   24895:                        goto ex;
                   24896:                case '\\':
                   24897:                        if (SZ_INT == nch++) error('l',"char constant too long");
                   24898:                        pch(c);
                   24899:                        switch (get(c)){
                   24900:                        case '\n':
                   24901:                                ++tloc.line;
                   24902:                        default:
                   24903:                                pch(c);
                   24904:                                break;
                   24905:                        case '4': case '5': case '6': case '7': // octal
                   24906:                                p = txtfree;
                   24907:                                cc = c-4;
                   24908:                        case '0': case '1': case '2': case '3':
                   24909:                                pch(c);
                   24910:                                get(c);  /* try for 2 */
                   24911:                                if( lxmask[c+1] & LEXDIG && c<'8'){
                   24912:                                        pch(c);
                   24913:                                        get(c);  /* try for 3 */
                   24914:                                        if (lxmask[c+1] & LEXDIG && c<'8') {
                   24915:                                                if (cc) *p = cc; // zap high bit
                   24916:                                                pch(c);
                   24917:                                        }
                   24918:                                        else
                   24919:                                                unget(c);
                   24920:                                }
                   24921:                                else
                   24922:                                        unget(c);
                   24923:                                break;
                   24924:                        case 'x':       // hexadecimal
                   24925:                                hex_to_oct();
                   24926:                                break;
                   24927:                        };
                   24928:                        break;
                   24929:                default:
                   24930:                        if (SZ_INT == nch++) error('l',"char constant too long");
                   24931:                        pch(c);
                   24932:                }
                   24933:        }
                   24934: ex:
                   24935:        if(nch==0)
                   24936:                error("empty char constant");
                   24937:        pch('\'');
                   24938:        pch('\0');
                   24939:        return txtstart;
                   24940: }
                   24941: 
                   24942: void lxcom()
                   24943: /* process a "block comment" */
                   24944: {
                   24945:        register c;
                   24946: 
                   24947:        for(;;)
                   24948:        switch (get(c)) {
                   24949:        case EOF:
                   24950:                error('w',"eof in comment");
                   24951:                return;
                   24952:        case '\n':
                   24953:                tloc.line++;
                   24954: //             Nline++;
                   24955:                break;
                   24956:        case '*':
                   24957:                if (get(c) == '/') return;
                   24958:                unget(c);
                   24959:                break;
                   24960:        case '/':
                   24961:                if (get(c) == '*') error('w',"``/*'' in comment");
                   24962:                unget(c);
                   24963:                break;
                   24964:        }
                   24965: }
                   24966: 
                   24967: 
                   24968: void linecom()
                   24969: // process a "line comment"
                   24970: {
                   24971:        register c;
                   24972: 
                   24973:        get(c);
                   24974: #ifdef DBG
                   24975:        if ( c=='@' && get(c)=='!' ) {
                   24976:                while ( get(c) != '\n' && c != EOF ) pch(c);
                   24977:                pch('\0');
                   24978:                process_debug_flags(txtstart);
                   24979:                del_txt();
                   24980:        }
                   24981: #endif
                   24982:        for(;;get(c))
                   24983:        switch (c) {
                   24984:        case EOF:
                   24985:                error('w',"eof in comment");
                   24986:                return;
                   24987:        case '\n':
                   24988:                tloc.line++;
                   24989: //             Nline++;
                   24990:                saved = lxtitle();
                   24991:                return;
                   24992:        }
                   24993: }
                   24994: 
                   24995: char eat_whitespace()
                   24996: {
                   24997: 
                   24998:        for(;;) {
                   24999:                register c = get(c);
                   25000:        lx:
                   25001: 
                   25002:                switch (c) {
                   25003:                case EOF:
                   25004:                        error('w',"unexpected comment");
                   25005:                        return EOF;
                   25006:                case '/':
                   25007:                        switch (get(c)) {
                   25008:                        case '*':
                   25009:                                lxcom();
                   25010:                                break;
                   25011:                        case '/':
                   25012:                                linecom();
                   25013:                                break;
                   25014:                        default:
                   25015:                                unget(c);
                   25016:                                return '/';
                   25017:                        }
                   25018:                        break;
                   25019:                case '\n':
                   25020:                        ++tloc.line;
                   25021:                        c = lxtitle();
                   25022:                        goto lx;
                   25023:                case ' ':
                   25024:                case '\t':
                   25025:                        break;
                   25026:                default:
                   25027:                        return c;               
                   25028:                }
                   25029:        }       
                   25030: }
                   25031: 
                   25032: void get_string()
                   25033: {
                   25034:        int lxchar;
                   25035: 
                   25036:        for(;;)
                   25037:        switch (get(lxchar)) {
                   25038:        case '\\':
                   25039:                pch('\\');
                   25040:                switch (get(lxchar)){
                   25041:                case '\n':
                   25042:                        ++tloc.line;
                   25043:                default:
                   25044:                        pch(lxchar);
                   25045:                        break;
                   25046:                case 'x':       // hexadecimal
                   25047:                        hex_to_oct();
                   25048:                        break;
                   25049:                };
                   25050:                break;
                   25051:        case '"':
                   25052:         {       char* p = txtstart;     // eat_whitespace() moves txtstart
                   25053:                 if ((lxchar = eat_whitespace()) == '"') {
                   25054:                         // string catenation, break with
                   25055:                         // newline to avoid merging characters
                   25056:                         // (e.g. "\xAB" "C")
                   25057:                         pch('\\');
                   25058:                         pch('\n');
                   25059: 
                   25060:                         continue;       // eat '\"' and carry on
                   25061:                 };
                   25062: 
                   25063:                 txtstart = p;
                   25064:                unget(lxchar);
                   25065:                pch(0);
                   25066:                return;
                   25067:         }
                   25068:        case '\n':
                   25069:                error("newline in string");
                   25070:                pch(0);
                   25071:                return;
                   25072:        case EOF:
                   25073:                error("eof in string");
                   25074:                pch(0);
                   25075:                return;
                   25076:        default:
                   25077:                pch(lxchar);
                   25078:        }
                   25079: }
                   25080: 
                   25081: TOK tlex()
                   25082: {
                   25083:        TOK ret;
                   25084:        Pname n;
                   25085: 
                   25086: //     Ntoken++;
                   25087: 
                   25088:        for(;;) {
                   25089:                register lxchar;
                   25090:                register struct LXDOPE *p;
                   25091: 
                   25092:                start_txt();
                   25093: 
                   25094:                if (saved) {
                   25095:                        lxchar = saved;
                   25096:                        saved = 0;
                   25097:                }
                   25098:                else
                   25099:                        get(lxchar);
                   25100: 
                   25101:                if (lxchar+1 >= CSSZ )
                   25102:                 error( "illegal input character encountered: %d", lxchar );
                   25103: 
                   25104:                switch( (p=lxcp[lxchar+1])->lxact ){
                   25105: 
                   25106:                case A_1C:      // eat up a single character, and return an opcode 
                   25107:                        reti(p->lxtok,p->lxtok);
                   25108: 
                   25109:                case A_EOF:
                   25110:                        if (p_level || b_level+lcount)
                   25111:                                error("'%s' missing at end of input",(b_level+lcount) ? "}" : ")");
                   25112:                
                   25113:                        reti(EOFTOK,0);
                   25114: 
                   25115:                case A_SHARP:
                   25116:                        // cope with header file not ended with '\n'
                   25117:                        unget('#');
                   25118:                        saved = lxtitle();
                   25119:                        continue;
                   25120: 
                   25121:                case A_ERR:
                   25122:                {       if (' '<=lxchar && lxchar<='~') // ASCII printable
                   25123:                                error("illegal character '%c' (ignored)",lxchar);
                   25124:                        else
                   25125:                                error("illegal character '0%o' (ignored)",lxchar);
                   25126:                        continue;
                   25127:                }
                   25128: 
                   25129:                case A_DOLL:
                   25130:                 { // lex a name of the for $id for template tree formals
                   25131:                        Pname fn ;
                   25132:                         lxget( lxchar, LEXLET|LEXDIG ) ;
                   25133: 
                   25134:                         if (!templp->in_progress ||  !txtstart[1]) {
                   25135:                           // no name string immediately follows, treat it                                  
                   25136:                           // like an illegal character
                   25137:                           error("illegal character '0%o' (ignored)",lxchar);                               
                   25138:                           continue;
                   25139:                         }  
                   25140: 
                   25141:                         txtstart++ ;
                   25142:                         if(fn=templ_compilation::tree_parameter(txtstart)) {                              
                   25143:                                switch (fn->n_template_arg) {
                   25144:                                        case template_expr_tree_formal:
                   25145:                                        // retain the $ in the name
                   25146:                                                retn(ID, strdup(--txtstart)) ;
                   25147: 
                   25148:                                        case template_stmt_tree_formal:
                   25149:                                                retn(SM_PARAM, fn) ;
                   25150:                                }  
                   25151:                         }  
                   25152:                         error("%s wasn't a statement or expression formal", txtstart);
                   25153:                         rets(ID, copy_if_need_be(txtstart));
                   25154:                 }
                   25155: 
                   25156:                case A_LET:     // collect an identifier and check for keyword
                   25157:                {
                   25158:                        char ll;
                   25159:                        switch (ll = lxchar) {
                   25160:                //      case 'l':
                   25161:                        case 'L':
                   25162:                                switch (get(lxchar)) {
                   25163:                                case '\'':
                   25164:                                        error('s',"wide character constant");
                   25165:                                        unget(lxchar);
                   25166:                                        continue;
                   25167:                                case '"':
                   25168:                                        error('s',"wide character string");
                   25169:                                        unget(lxchar);
                   25170:                                        continue;
                   25171:                                }
                   25172:                                unget(lxchar);
                   25173:                                lxchar = ll;
                   25174:                        }
                   25175:                }
                   25176: 
                   25177:                        lxget( lxchar, LEXLET|LEXDIG );
                   25178:                         /* look for a keyword or a global type */
                   25179:                        if ((n = keyword_table->look(txtstart,0))  /* keyword */
                   25180:                                || (n = ktbl->look(txtstart, 0)))  /* local type */
                   25181:                        {
                   25182:                                TOK x;
                   25183:                                del_txt();
                   25184:                                switch (x=n->base) {
                   25185:                                case TNAME:
                   25186:                                        rets(ID,n->string);
                   25187:                                case LOC:
                   25188:                                        retl(n->syn_class);
                   25189:                                case EXTERN:
                   25190:                                        if ((lxchar = eat_whitespace()) == '\"') {
                   25191:                                                // linkage directive
                   25192:                                                get_string();
                   25193:                                                rets(LINKAGE,txtstart);
                   25194:                                        }
                   25195:                                        unget(lxchar);
                   25196:                                        reti(TYPE,EXTERN);
                   25197:                                case CATCH:
                   25198:                                // case TEMPLATE:
                   25199:                                        error('s',"%k",n->syn_class);
                   25200:                                        continue;
                   25201:                                case TRY:
                   25202:                                {
                   25203:                                        static int warn_try;
                   25204:                                        if (!warn_try) { 
                   25205:                                                Pname n = keyword_table->look("try",0);
                   25206:                                                n->n_key = DEFAULT;
                   25207:                                                error('w',&tloc,"%k is a future reserved keyword",n->syn_class);
                   25208:                                                warn_try++;
                   25209:                                        }
                   25210:                                        rets(ID,n->string);
                   25211:                                }
                   25212:                                default:
                   25213:                                        reti(n->syn_class,x);
                   25214:                                }
                   25215:                        }
                   25216:                        // rets(ID,txtstart);
                   25217:                         rets(ID, copy_if_need_be(txtstart)) ;
                   25218: 
                   25219:                case A_DIG:
                   25220: 
                   25221:                        ret = ICON;
                   25222: 
                   25223:                        if (lxchar=='0') {
                   25224:                                int pkchar;
                   25225:                                get(pkchar);
                   25226:                                if(pkchar=='x' || pkchar=='X') {        // hex
                   25227:                                        pch(lxchar);
                   25228:                                        lxget(pkchar,LEXHEX);
                   25229:                                        txtfree--;
                   25230:                                        if (txtfree-txtstart<3) // minimum "0Xd\0"
                   25231:                                                error("hex digitX after \"0x\"");
                   25232:                                        get(lxchar);
                   25233:                                        goto getsuffix;
                   25234:                                }
                   25235:                                unget(pkchar);
                   25236:                        }
                   25237: 
                   25238:                        lxget(lxchar,LEXDIG);
                   25239:                        txtfree--;
                   25240: 
                   25241:                        if (get(lxchar) == '.') {
                   25242:                getfp:
                   25243:                                lxget('.', LEXDIG );
                   25244:                                txtfree--;
                   25245:                                ret = FCON;
                   25246:                                get(lxchar);
                   25247:                        };
                   25248:                
                   25249:                        if (lxchar=='e' || lxchar=='E') {
                   25250:                                pch(lxchar);
                   25251:                                get(lxchar);
                   25252:                                if(lxchar=='-' || lxchar=='+') {
                   25253:                                        pch(lxchar);
                   25254:                                        get(lxchar);
                   25255:                                }
                   25256:                                if (lxmask[lxchar+1] & LEXDIG) {
                   25257:                                        lxget( lxchar, LEXDIG );
                   25258:                                        txtfree--;
                   25259:                                        get(lxchar);
                   25260:                                }
                   25261:                                else
                   25262:                                        error("missing exponent digits?");
                   25263:                                ret = FCON;
                   25264:                        };
                   25265: 
                   25266:                        if(*txtstart=='0' && ret==ICON) {
                   25267:                                char *bch = txtstart;
                   25268:                                while (++bch <= txtfree) {
                   25269:                                        if(*bch=='8' || *bch=='9')
                   25270:                                                error("%c used as octal digit",*bch);
                   25271:                                }
                   25272:                        }
                   25273: 
                   25274:                getsuffix:
                   25275:                        switch (lxchar) {
                   25276:                        case 'f':
                   25277:                        case 'F':
                   25278:                                if (ret==ICON)
                   25279:                                        error("%c suffix for integer constant",lxchar);
                   25280:                                else
                   25281:                                        pch(lxchar);
                   25282:                                break;
                   25283:                        case 'u':
                   25284:                        case 'U':
                   25285:                                if (ret==FCON) {
                   25286:                                        error("%c suffix for floating constant",lxchar);
                   25287:                                        break;
                   25288:                                }
                   25289:                                pch(lxchar);
                   25290:                                switch(get(lxchar)) {
                   25291:                                case 'l':
                   25292:                                case 'L':
                   25293:                                        pch(lxchar);
                   25294:                                        break;
                   25295:                                default:
                   25296:                                        saved=lxchar;
                   25297:                                        break;
                   25298:                                }
                   25299:                                break;
                   25300:                        case 'l':
                   25301:                        case 'L':
                   25302:                                pch(lxchar);
                   25303:                                if (ret==FCON) {
                   25304:                                        break;
                   25305:                                }
                   25306:                                switch(get(lxchar)) {
                   25307:                                case 'u':
                   25308:                                case 'U':
                   25309:                                        pch(lxchar);
                   25310:                                        break;
                   25311:                                default:
                   25312:                                        saved=lxchar;
                   25313:                                        break;
                   25314:                                }
                   25315:                                break;
                   25316:                        default:
                   25317:                                saved = lxchar;
                   25318:                                break;
                   25319:                        };
                   25320: 
                   25321:                        if(*txtstart=='0' && txtfree-txtstart==1)
                   25322:                                reti(ZERO,0);   // plain zero
                   25323: 
                   25324:                        pch(0);
                   25325:                        rets(ret,txtstart);
                   25326: 
                   25327: 
                   25328:                case A_DOT:
                   25329:                        switch (get(lxchar)) {
                   25330:                        case '.':       // look for ellipsis
                   25331:                                if (get(lxchar) != '.') {
                   25332:                                        error("token .. ?");
                   25333:                                        saved = lxchar;
                   25334:                                }
                   25335:                                reti(ELLIPSIS,0);
                   25336:                        case '*':
                   25337:                                reti (REFMUL,DOT);
                   25338:                        }
                   25339: 
                   25340:                        if (lxmask[lxchar+1] & LEXDIG){// look for floating constant
                   25341:                                unget(lxchar);
                   25342:                                goto getfp;
                   25343:                        }
                   25344:                        saved = lxchar;
                   25345:                        reti(DOT,0);
                   25346: 
                   25347:                case A_STR:
                   25348:                        /* save string constant in buffer */
                   25349:                        get_string();
                   25350:                        rets(STRING,txtstart);
                   25351: 
                   25352:                case A_CC:
                   25353:                        /* character constant */
                   25354:                        rets(CCON,chconst());
                   25355: 
                   25356:                case A_BCD:
                   25357:                        {
                   25358:                                register i;
                   25359:                                int j;
                   25360:        
                   25361:                                pch('`');
                   25362:        
                   25363:                                for (i=0; i<7; ++i) {
                   25364:                                        pch(get(j));
                   25365:                                        if (j == '`' ) break;
                   25366:                                }
                   25367:                                pch(0);
                   25368:                                if (6<i)
                   25369:                                        error('l',"bcd constant exceeds 6 characters" );
                   25370:                                rets(CCON,txtstart);
                   25371:                        }
                   25372: 
                   25373:                case A_SL:      /* / */
                   25374:                        switch (get(lxchar))  {
                   25375:                        case '*':
                   25376:                                lxcom();
                   25377:                                break;
                   25378:                        case '/':
                   25379:                                linecom();
                   25380:                                break;
                   25381:                        case '=':
                   25382:                                reti(ASOP,ASDIV);
                   25383:                        default:
                   25384:                                saved = lxchar;
                   25385:                                reti(DIVOP,DIV);
                   25386:                        }
                   25387: 
                   25388:                case A_WS:
                   25389:                        continue;
                   25390: 
                   25391:                case A_NL:
                   25392:                        ++tloc.line;
                   25393: //                     Nline++;
                   25394:                        saved = lxtitle();
                   25395:                        continue;
                   25396: 
                   25397:                case A_LC:
                   25398:                        if (BLMAX <= b_level++) {
                   25399:                                error('l',"blocks too deeply nested");
                   25400:                                ext(3);
                   25401:                        }
                   25402:                        retl(LC);
                   25403: 
                   25404:                case A_RC:
                   25405:                        if (lcount+b_level-- <= 0) {
                   25406:                                error("unexpected '}'");
                   25407:                                b_level = 0;
                   25408:                        }
                   25409:                        retl(RC);
                   25410: 
                   25411:                case A_L:
                   25412:                        p_level++;
                   25413:                        reti(LP,0);
                   25414: 
                   25415:                case A_R:
                   25416:                        if (p_level-- <= 0) {
                   25417:                                error("unexpected ')'");
                   25418:                                p_level = 0;
                   25419:                        }
                   25420:                        reti(RP,0);
                   25421: 
                   25422:                case A_ASS:
                   25423:                        switch (get(lxchar)) {
                   25424:                        case '=':
                   25425:                                reti(EQUOP,EQ);
                   25426:                        default:
                   25427:                                saved = lxchar;
                   25428:                                reti(ASSIGN,ASSIGN);
                   25429:                        }
                   25430: 
                   25431:                case A_COL:
                   25432:                        switch (get(lxchar)) {
                   25433:                        case ':':
                   25434:                                reti(MEM,0);
                   25435:                        case '=':
                   25436:                                error("':=' is not a c++ operator");
                   25437:                                reti(ASSIGN,ASSIGN);
                   25438:                        default:
                   25439:                                saved = lxchar;
                   25440:                                reti(COLON,COLON);
                   25441:                        }
                   25442:                case A_NOT:
                   25443:                        switch (get(lxchar)) {
                   25444:                        case '=':
                   25445:                                reti(EQUOP,NE);
                   25446:                        default:
                   25447:                                saved = lxchar;
                   25448:                                reti(NOT,NOT);
                   25449:                        }
                   25450:                case A_GT:
                   25451:                        switch(get(lxchar)) {
                   25452:                        case '>':
                   25453:                                switch (get(lxchar)) {
                   25454:                                case '=':
                   25455:                                        reti(ASOP,ASRS);
                   25456:                                        break;
                   25457:                                default:
                   25458:                                        saved = lxchar;
                   25459:                                        reti(SHIFTOP,RS);
                   25460:                                }
                   25461:                        case '=':
                   25462:                                reti(RELOP,GE);
                   25463:                        default:
                   25464:                                saved = lxchar;
                   25465:                                reti(GT,GT);
                   25466:                        }
                   25467:                case A_LT:
                   25468:                        switch (get(lxchar)) {
                   25469:                        case '<':
                   25470:                                switch (get(lxchar)) {
                   25471:                                case '=':
                   25472:                                        reti(ASOP,ASLS);
                   25473:                                default:
                   25474:                                        saved = lxchar;
                   25475:                                        reti(SHIFTOP,LS);
                   25476:                                }
                   25477:                        case '=':
                   25478:                                reti(RELOP,LE);
                   25479:                        default:
                   25480:                                saved = lxchar;
                   25481:                                reti(LT,LT);
                   25482:                        }
                   25483:                case A_AND:
                   25484:                        switch (get(lxchar)) {
                   25485:                        case '&':
                   25486:                                reti(ANDAND,ANDAND);
                   25487:                        case '=':
                   25488:                                reti(ASOP,ASAND);
                   25489:                        default:
                   25490:                                saved = lxchar;
                   25491:                                reti(AND,AND);
                   25492:                        }
                   25493:                case A_OR:
                   25494:                        switch (get(lxchar)) {
                   25495:                        case '|':
                   25496:                                reti(OROR,OROR);
                   25497:                        case '=':
                   25498:                                reti(ASOP,ASOR);
                   25499:                        default:
                   25500:                                saved = lxchar;
                   25501:                                reti(OR,OR);
                   25502:                        }
                   25503:                case A_ER:
                   25504:                        switch (get(lxchar)) {
                   25505:                        case '=':
                   25506:                                reti(ASOP,ASER);
                   25507:                        default:
                   25508:                                saved = lxchar;
                   25509:                                reti(ER,ER);
                   25510:                        }
                   25511:                case A_PL:
                   25512:                        switch (get(lxchar)) {
                   25513:                        case '=':
                   25514:                                reti(ASOP,ASPLUS);
                   25515:                        case '+':
                   25516:                                reti(ICOP,INCR);
                   25517:                        default:
                   25518:                                saved = lxchar;
                   25519:                                reti(PLUS,PLUS);
                   25520:                        }
                   25521:                case A_MIN:
                   25522:                        switch (get(lxchar)) {
                   25523:                        case '=':
                   25524:                                reti(ASOP,ASMINUS);
                   25525:                        case '-':
                   25526:                                reti(ICOP,DECR);
                   25527:                        case '>':
                   25528:                                if (get(lxchar) == '*')
                   25529:                                        {reti(REFMUL,REF);}
                   25530:                                else
                   25531:                                        saved = lxchar;
                   25532:                                reti(REF,REF);
                   25533:                        default:
                   25534:                                saved = lxchar;
                   25535:                                reti(MINUS,MINUS);
                   25536:                        }
                   25537:                case A_MUL:
                   25538:                        switch (get(lxchar)) {
                   25539:                        case '=':
                   25540:                                reti(ASOP,ASMUL);
                   25541:                        case '/':
                   25542:                                error('w',"*/ not as end of comment");
                   25543:                        default:
                   25544:                                saved = lxchar;
                   25545:                                reti(MUL,MUL);
                   25546:                        }
                   25547:                case A_MOD:
                   25548:                        switch (get(lxchar)) {
                   25549:                        case '=':
                   25550:                                reti(ASOP,ASMOD);
                   25551:                        default:
                   25552:                                saved = lxchar;
                   25553:                                reti(DIVOP,MOD);
                   25554:                        }
                   25555:                default:
                   25556:                        {error('i',"lex act==%d getc()->%d",p,lxchar);}
                   25557: 
                   25558:                }
                   25559: 
                   25560:                error('i',"lex, main switch");
                   25561:        }
                   25562: 
                   25563: }
                   25564: 
                   25565: int lxtitle()
                   25566: /*
                   25567:        called after a newline; set linenumber and file name
                   25568: */
                   25569: {
                   25570:        register c;
                   25571: 
                   25572:        for(;;)
                   25573:        switch ( get(c) ) {
                   25574:        default:                // e.g. not '\n', not '#'
                   25575:                return c;
                   25576:        case '\n':
                   25577:                tloc.line++;
                   25578: //             Nline++;
                   25579:        ll:
                   25580:                break;
                   25581:        case '#':       /* # lineno "filename" */
                   25582:        {       int cl = tloc.line;
                   25583:                tloc.line = 0;
                   25584:                for(;;) 
                   25585:                switch (get(c)) {
                   25586:                case '"':
                   25587:                        start_txt();
                   25588:                        for(;;)
                   25589:                        switch (get(c)) {
                   25590:                        case '"':
                   25591:                                pch('\0');
                   25592: 
                   25593:                                while (get(c) != '\n') ;  // skip to eol.. ignore anything more
                   25594: 
                   25595:                                if (*txtstart) {        // stack file name
                   25596:                                        char* fn;
                   25597:                                        if (tcurr_file == 0){
                   25598:                                                if (( fn = file_name[0]) 
                   25599:                                                        && (strcmp(txtstart,fn)!=0)){  // 1st include
                   25600:                                                        if (MAXFILE*4<++Nfile) error('i',"fileN buffer overflow");
                   25601:                                                        if (MAXFILE<++tcurr_file) error('i',"fileN stack overflow");
                   25602:                                                        file_stack[tcurr_file] = Nfile;
                   25603:                                                
                   25604:                                                        char* p1 = new char[txtfree-txtstart];
                   25605:                                                        (void) strcpy(p1,txtstart);
                   25606:                                                        file_name[Nfile] = p1;
                   25607:        //                                              Nstr++;
                   25608:                                                }
                   25609:                                                else { //&& line is dummy #line "input.c"
                   25610:                                                        // ignore
                   25611:                                                }
                   25612: //&& dead, dead, dead                  goto push;
                   25613:                                        }
                   25614:                                        else if ( (fn=file_name[file_stack[tcurr_file]])
                   25615:                                        && (strcmp(txtstart,fn)==0) ) {
                   25616:                                                //new line, same file: ignore
                   25617:                                        }
                   25618:                                        else if ( (fn=file_name[file_stack[tcurr_file-1]])
                   25619:                                        && (strcmp(txtstart,fn)==0) ) {
                   25620:                                                // previous file: pop
                   25621:                                                tcurr_file--;
                   25622:                                        }
                   25623:                                        else {  // new file name: push
                   25624: //&&                           push:
                   25625:                                                if (MAXFILE*4<Nfile++) error('i',"fileN buffer overflow");
                   25626:                                                if (MAXFILE<tcurr_file++) error('i',"fileN stack overflow");
                   25627:                                                file_stack[tcurr_file] = Nfile;
                   25628:                                                char* p = new char[txtfree-txtstart];
                   25629:                                                (void) strcpy(p,txtstart);
                   25630:                                                file_name[Nfile] = p;
                   25631: //                                             Nstr++;
                   25632:                                        }
                   25633:                                }
                   25634:                                else {  // no name .. back to the original .c file: ""
                   25635:                                        tcurr_file = 0;
                   25636:                                }
                   25637:                                del_txt();
                   25638:                                tloc.file = file_stack[tcurr_file];
                   25639:                                goto ll;
                   25640:                        case '\n':
                   25641:                                error("unexpected end of line on '# line'");
                   25642:                        default:
                   25643:                                pch(c);
                   25644:                        }
                   25645:                case ' ':
                   25646:                        break;
                   25647: 
                   25648:                case '0':
                   25649:                case '1':
                   25650:                case '2':
                   25651:                case '3':
                   25652:                case '4':
                   25653:                case '5':
                   25654:                case '6':
                   25655:                case '7':
                   25656:                case '8':
                   25657:                case '9':
                   25658:                        tloc.line = tloc.line*10+c-'0'; 
                   25659:                        break;
                   25660: 
                   25661:                case 'l':       // look for "#line ..." and then ignore "line"
                   25662:                        if (get(c)=='i' && get(c)=='n' && get(c)=='e') break;
                   25663:                case '\n':
                   25664:                         tloc.putline();
                   25665:                         goto ll;
                   25666: 
                   25667:                default: // pass #rubbish through
                   25668:                        tloc.line = cl;
                   25669:                        pch('#');
                   25670:                        pch(c);
                   25671:                        while (get(c) != '\n') pch(c);
                   25672:                        pch('\0');
                   25673:                        fprintf(out_file,"\n%s\n",txtstart);
                   25674:                        start_txt();
                   25675:                        tloc.line++;
                   25676: //                     Nline++;
                   25677:                        goto ll;
                   25678:                }
                   25679:        }
                   25680:        }
                   25681: }
                   25682: 0707071010112044351004440001630000160000010204200466055404600000700000046311main.c/*ident     "@(#)ctrans:src/main.c  1.9" */
                   25683: /***********************************************************************
                   25684: 
                   25685:        C++ source for cfront, the C++ compiler front-end
                   25686:        written in the computer science research center of Bell Labs
                   25687: 
                   25688:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   25689:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   25690: 
                   25691: main.c:
                   25692: 
                   25693:        Initialize global environment
                   25694:        Read argument line
                   25695:        Start compilation
                   25696:        Clean up and exit
                   25697: 
                   25698: **************************************************************************/
                   25699: 
                   25700: #ifdef __cplusplus
                   25701: #include <stdlib.h>
                   25702: #endif
                   25703: 
                   25704: #include <ctype.h>
                   25705: #include <string.h>
                   25706: #include <libc.h>
                   25707: #include <osfcn.h>
                   25708: #include <fstream.h>
                   25709: #include "size.h"
                   25710: #include "cfront.h"
                   25711: #include "tree_dump.h"
                   25712: #include "template.h"
                   25713: #include "hash.h"
                   25714: 
                   25715: char* prog_name = "<<AT&T C++ Translator <(3.0)(PT)> 08/08/90>>";
                   25716: char* src_file_name = "";
                   25717: char* line_format = "\n# %d \"%s\"\n";
                   25718: 
                   25719: int dump_tree;
                   25720: int tree_dump_brief = 0;
                   25721: dcn_arg dump_tree_arg;
                   25722: 
                   25723: #ifdef unix
                   25724: #include <signal.h>
                   25725: 
                   25726: static void core_dump(int = 0)
                   25727: {
                   25728:        if (error_count)
                   25729:                fprintf(stderr,"sorry, cannot recover from previous error\n");
                   25730:        else 
                   25731:                error('i',"bus error (or something nasty like that)");
                   25732:        ext(99);
                   25733: }
                   25734: #endif
                   25735: 
                   25736: Plist isf_list;
                   25737: Pstmt st_ilist;
                   25738: Pstmt st_dlist;
                   25739: Ptable sti_tbl;
                   25740: Ptable std_tbl;
                   25741: Plist stat_mem_list;
                   25742: 
                   25743: int vtbl_opt = -1;     // how to deal with vtbls:
                   25744:                        // -1 static and defined
                   25745:                        // 0 external and supposed to be defined elsewhere
                   25746:                        // 1 external and defined
                   25747: int debug_opt;
                   25748: int gplus_opt;         // -g to cc, overrides print optimization 
                   25749: int ansi_opt;
                   25750: int strict_opt;                // disallow features from the anachronism section
                   25751:                        // of the manual
                   25752: int warning_opt;       // produce more warnings if set
                   25753: bit stmtno = 0;
                   25754: 
                   25755: extern simpl_init();
                   25756: extern typ_init();
                   25757: extern syn_init();
                   25758: extern lex_init();
                   25759: extern error_init();
                   25760: 
                   25761: char *st_name(char*);  // generates names of static ctor, dtor callers, ptbl_vec
                   25762: Pname def_name;                // first definition in file
                   25763: Pname pdef_name;       // used with ptbl_vec if function is first definition
                   25764: 
                   25765: int syn_count = 0; // to set conditional breakpoints to find particular expressions  
                   25766: Hash *dumper_node_hash_table;
                   25767:   
                   25768: void static
                   25769: clean_dumper_hash_table() {
                   25770:        if(!dumper_node_hash_table) 
                   25771:                return;
                   25772:        else {
                   25773:                HashWalker hi(*dumper_node_hash_table);
                   25774:                while(hi.valid ()) {
                   25775:                        struct node& n = *(struct node*) hi.key();
                   25776:                if(n.permanent == 0 || n.permanent == 3) /* flush deleted nodes */          
                   25777:                        dumper_node_hash_table->del(hi.key());
                   25778:                hi.advance();                              
                   25779:                }                 
                   25780:        }     
                   25781: }     
                   25782:    
                   25783: void run()
                   25784: /*
                   25785:        run the appropriate stages
                   25786: */
                   25787: {
                   25788:        Pname n;
                   25789:        templp = new templ_compilation;  // canonical instance
                   25790:                                         
                   25791: 
                   25792:        if(dump_tree) {
                   25793:                dumper_node_hash_table =
                   25794:                        dump_tree_arg.nodes_seen_hash = new pointer_hash (10000);
                   25795:                dump_tree_arg.verbose = dt_recursive_1;
                   25796:        }    
                   25797: 
                   25798:        while (n=syn()) {
                   25799:                if (n == Pname(1)) continue;
                   25800:                if (n->n_list) PERM(n->tp);
                   25801: 
                   25802:                DB( if(Rdebug>=1) error('d',"run: syn(): '%s'", n->string););
                   25803:                 templp->instantiate_ref_templ();
                   25804: 
                   25805:                for (Pname nx, nn=n; nn; nn=nx) {
                   25806:                        Pname rr;
                   25807:                        ++syn_count;
                   25808:                        nx = nn->n_list;
                   25809:                        nn->n_list = 0;
                   25810: 
                   25811:                        DB( if(Rdebug>=1) error('d',"run: dcl(): %n, base: %k",nn,nn->base););
                   25812: 
                   25813:                        if ((rr=nn->dcl(gtbl,EXTERN))==0
                   25814:                        || nn->base==0
                   25815:                        || error_count) continue;
                   25816: 
                   25817:                        DB( if(Rdebug>=1) error('d',"run: simpl(): %n",nn););
                   25818: 
                   25819:                        nn->simpl();
                   25820: 
                   25821:                        if (error_count) {
                   25822:                                if(dump_tree) {
                   25823:                                        display_cfront_node (dump_tree_arg, nn);
                   25824:                                        *dump_tree_arg.output_stream << "---------------------------\n\n";
                   25825:                                }
                   25826:                                continue;
                   25827:                        }
                   25828: 
                   25829:                        DB( if(Rdebug>=1) error('d',"run:print(): %n (%k) tp %t",nn,nn->base,nn->tp););
                   25830: 
                   25831:                        if (nn->base == TNAME)
                   25832:                                nn->dcl_print(0);
                   25833:                        else {
                   25834:                                Ptype t = nn->tp;
                   25835:                        llxx:
                   25836:                                switch (t->base) {
                   25837:                                case TYPE:
                   25838:                                        t = Pbase(t)->b_name->tp; goto llxx;
                   25839:                                case CLASS:
                   25840:                                        DB( if(Rdebug>=1) fprintf(stderr," -- class\n"););
                   25841:                                        if (vtbl_opt==1 || gplus_opt) n->dcl_print(0);
                   25842:                                        break;
                   25843:                                case ENUM:
                   25844:                                        DB( if(Rdebug>=1) fprintf(stderr," -- enum\n"););
                   25845:                                        Penum(n->tp)->dcl_print(0);
                   25846:                                        break;
                   25847:                                case FCT:
                   25848:                                        DB( if(Rdebug>=1) error('d'," -- fct%n inline %d body %d",nn,Pfct(t)->f_inline,Pfct(t)->body););
                   25849:                                        if (Pfct(t)->body==0
                   25850:                                        || (debug_opt==0 && Pfct(t)->f_inline && ((n->n_table!=gtbl) || strcmp(nn->string,"main")))
                   25851:                                        || Pfct(t)->f_imeasure && Pfct(t)->f_inline==0) break;
                   25852:                                        DB( if(Rdebug>=1) error('d',"rr %n inline %d body %d",rr,Pfct(rr->tp)->f_inline,Pfct(rr->tp)->body););
                   25853:                                        rr->dcl_print(0);
                   25854:                                        break;
                   25855:        
                   25856:                                default:
                   25857:                                        DB( if(Rdebug>=1) error('d'," -- %n tpbase: %k",nn,nn->tp->base););
                   25858:                                        // print class def, if appropriate
                   25859:                                        // can't use tsizeof() since this may
                   25860:                                        // print an error if class isn't defined
                   25861:                                        { for(Ptype tx = t;;) {
                   25862:                                                switch ( tx->base ) {
                   25863:                                                case VEC:
                   25864:                                                    tx=Pvec(tx)->typ;
                   25865:                                                    continue;
                   25866:                                                case TYPE: case COBJ:
                   25867:                                                    tx=Pbase(tx)->b_name->tp;
                   25868:                                                    continue;
                   25869:                                                }
                   25870:                                                Pclass cl = Pclass(tx);
                   25871:                                                if ( cl->base == CLASS
                   25872:                                                &&  (cl->defined&(DEFINED|SIMPLIFIED))
                   25873:                                                &&   cl->c_body==1 )
                   25874:                                                        cl->dcl_print(0);
                   25875:                                                break;
                   25876:                                          }
                   25877:                                        }
                   25878:                                        nn->dcl_print(0);
                   25879:                                }
                   25880:                        }
                   25881: 
                   25882:                        if(dump_tree) {
                   25883:                                display_cfront_node (dump_tree_arg, nn);
                   25884:                                *dump_tree_arg.output_stream << "---------------------------\n\n";
                   25885:                        }
                   25886: 
                   25887:                        if (error_count) continue;
                   25888: 
                   25889:                        DB( if(Rdebug>=1) error('d',"run: cleanup"););
                   25890:                        switch (nn->tp->base) { // clean up
                   25891:                        default:
                   25892:                        {       
                   25893:                                Pexpr i = nn->n_initializer;
                   25894:                                DB( if(Rdebug>=1) error('d',"default nn %n i %d",nn,i););
                   25895:                                if (i && i!=Pexpr(1)) {
                   25896:                                        DEL(i);
                   25897:                                        nn->n_initializer = 0;
                   25898:                                        if (def_name==0 && rr->n_scope != STATIC) { 
                   25899:                                                def_name = rr;
                   25900:                                                if (pdef_name == 0) ptbl_init(0);
                   25901:                                        }
                   25902:                                }
                   25903:                                break;
                   25904:                        }
                   25905: 
                   25906:                        case FCT:
                   25907:                        {       
                   25908:                                Pfct f = Pfct(nn->tp);
                   25909:                                DB( if(Rdebug>=1) error('d', "function nn: %n local_class: %d %d", nn, local_class, f->local_class ););
                   25910:                                if (f->body
                   25911:                                && f->f_inline==0
                   25912:                                && f->f_imeasure==0) {
                   25913:                                         if ( local_class = f->local_class )  { 
                   25914:                                                delete_local();
                   25915:                                                local_class = 0;
                   25916:                                        }
                   25917: 
                   25918:                                         if (ansi_opt && f->f_this) {
                   25919:                                                 f->f_this->n_table = 0;
                   25920:                                                 for (Pname n=f->f_this->n_list; n; n=n->n_list)
                   25921:                                                         n->n_table = 0;
                   25922:                                         }
                   25923: 
                   25924:                                        DEL(f->body);
                   25925:                                        if (def_name==0) { 
                   25926:                                                def_name = rr;
                   25927:                                                if (pdef_name == 0) ptbl_init(0);
                   25928:                                        }
                   25929:                                }
                   25930:                                break;
                   25931:                        }
                   25932: 
                   25933:                        case CLASS:
                   25934:                        {       Pclass cl = Pclass(nn->tp);
                   25935:                                for (Pname px, p=cl->mem_list; p; p=px) {
                   25936:                                    px = p->n_list;
                   25937:                                    if (p->tp) {
                   25938:                                        switch (p->tp->base) {
                   25939:                                        case FCT:
                   25940:                                        {       Pfct f = (Pfct)p->tp;
                   25941:                                                if (f->body) {
                   25942:                                                        if (f->f_inline==0
                   25943:                                                        && f->f_imeasure==0) {
                   25944:                                                                if ( local_class = f->local_class ) {
                   25945:                                                                        delete_local();
                   25946:                                                                        local_class = 0;
                   25947:                                                                }
                   25948:                                                                DEL(f->body);
                   25949:                                                                f->body = 0;
                   25950:                                                        }
                   25951:                                                }
                   25952:                                        }
                   25953:                                        case CLASS:
                   25954:                                        case ENUM:
                   25955:                                                break;
                   25956:                                        case COBJ:
                   25957:                                        case EOBJ:
                   25958:                                                DEL(p);
                   25959:                                                break;
                   25960:                                        default:
                   25961:                                                delete p;
                   25962:                                        }
                   25963:                                    } else {
                   25964:                                        delete p;
                   25965:                                    }
                   25966:                                } // for
                   25967:                                cl->mem_list = 0;
                   25968:                                cl->permanent = 3;
                   25969:                                break;
                   25970:                        }
                   25971:                        }
                   25972:                        DEL(nn);
                   25973:                }
                   25974:                lex_clear();
                   25975:                if (dump_tree) clean_dumper_hash_table();
                   25976:        }
                   25977:        templp->end_of_compilation() ;
                   25978: 
                   25979:        switch (no_of_undcl) {
                   25980:        case 1:         {error('w',"undeclaredF%n called",undcl);}
                   25981:        case 0:         break;
                   25982:        default:        {error('w',"%d undeclaredFs called; for example%n",no_of_undcl,undcl);}
                   25983:        }
                   25984: 
                   25985:        switch (no_of_badcall) {
                   25986:        case 1:         {error('w',"%n declaredWoutAs calledWAs",badcall);}
                   25987:        case 0:         break;
                   25988:        default:        {error('w',"%d Fs declaredWoutAs calledWAs; for example%n",no_of_badcall,badcall);}
                   25989:        }
                   25990: 
                   25991:        if (error_count) return;
                   25992: 
                   25993:        int i = 1;
                   25994:        for (Pname m=gtbl->get_mem(i); m; m=gtbl->get_mem(++i)) {
                   25995:                if (m->base==TNAME
                   25996:                || m->n_sto==EXTERN
                   25997:                || m->n_stclass == ENUM) continue;
                   25998: 
                   25999:                Ptype t = m->tp;
                   26000:                if (t == 0) continue;
                   26001:                switch (t->base) {
                   26002:                case CLASS:
                   26003:                case ENUM:
                   26004:                case OVERLOAD:  continue;
                   26005:                case COBJ:
                   26006:                //case ANON:
                   26007:                case VEC:       break;
                   26008:                case FCT:
                   26009:                                if (Pfct(t)->f_inline || Pfct(t)->body==0) continue;
                   26010:                }
                   26011: 
                   26012: //error('d',&m->where,"%n %d %d %s",m,m->n_addr_taken,m->n_used,m->n_sto==STATIC?"static":"");
                   26013: //xxx doesn't check anon union members as their use bits are set differently
                   26014:                if (m->n_addr_taken==0
                   26015:                && m->n_used==0
                   26016:                && m->n_sto == STATIC) { // (static or anon?)
                   26017:                        for(;;) {
                   26018: //error('d',&m->where,"  %t tconst(): %d",t,t->tconst());
                   26019:                                if(t->base==TYPE) {
                   26020:                                        if(t->tconst()) break;
                   26021:                                        t=Pbase(t)->b_name->tp;
                   26022:                                } else if(t->base==VEC) {
                   26023:                                        t=Pvec(t)->typ;
                   26024:                                } else {
                   26025:                                    if ( t->tconst() == 0 ) {
                   26026: //error('d',"m%n tp%t t%t",m,m->tp,t);
                   26027:                                        if ( t->base != COBJ )
                   26028:                                                error('w',&m->where,"%n defined but not used",m);
                   26029:                                        else { Pclass cl;
                   26030:                                            cl = Pclass(Pbase(t)->b_name->tp);
                   26031:                                            if ( cl->has_ctor()==0 )
                   26032:                                                if ( cl->csu == ANON )
                   26033:                                                 ; //error('w',&m->where,"anonymous union defined but not used");
                   26034:                                                else
                   26035:                                                    error('w',&m->where,"%n defined but not used",m);
                   26036:                                        }
                   26037:                                    } // if const
                   26038:                                    break;
                   26039:                                }
                   26040:                        } // for
                   26041:                } // if static and not used
                   26042:        }
                   26043: 
                   26044:         Pname ctor = 0;
                   26045:        Pname dtor = 0;
                   26046:        --curloc.line;
                   26047: 
                   26048:        if (st_ilist) { //      make an "init" function;
                   26049:                        //      it calls all constructors for static objects
                   26050:                DB( if(Rdebug>=1) error('d',"make sti"); );
                   26051:                Pname n = new name( st_name("__sti__") );
                   26052:                Pfct f = new fct(void_type,0,1);
                   26053:                n->tp = f;
                   26054:                f->body = new block(st_ilist->where,0,st_ilist);
                   26055:        //      f->body->s = st_ilist;
                   26056:                f->body->memtbl = sti_tbl;
                   26057:                n->n_sto = EXTERN;
                   26058:                // assignments here are really initializations:
                   26059:                ignore_const++;
                   26060:                f->f_linkage = linkage_C;
                   26061:                f->sign();
                   26062:                (void) n->dcl(gtbl,EXTERN);
                   26063:                ignore_const--;
                   26064:                n->simpl();
                   26065:                n->dcl_print(0);
                   26066:                ctor = n;
                   26067:        }
                   26068: 
                   26069:        if (st_dlist) { //      make a "done" function;
                   26070:                        //      it calls all destructors for static objects
                   26071:                DB( if(Rdebug>=1) error('d',"make std"); );
                   26072:                Pname n = new name( st_name("__std__") );
                   26073:                Pfct f = new fct(void_type,0,1);
                   26074:                n->tp = f;
                   26075:                f->body = new block(st_dlist->where,0,st_dlist);
                   26076:        //      f->body->s = st_dlist;
                   26077:                f->body->memtbl = std_tbl;
                   26078:                n->n_sto = EXTERN;
                   26079:                f->f_linkage = linkage_C;
                   26080:                f->sign();
                   26081:                (void) n->dcl(gtbl,EXTERN);
                   26082:                n->simpl();
                   26083:                n->dcl_print(0);
                   26084:                dtor = n;
                   26085:        }
                   26086: 
                   26087: #ifdef PATCH
                   26088:                /*For fast load: make a static "__link" */
                   26089:        if (ctor || dtor)
                   26090:        {
                   26091:                printf("static struct __linkl { struct __linkl * next;\n");
                   26092:                if ( ansi_opt )
                   26093:                        printf("void (*ctor)(); void (*dtor)(); } __link = \n");
                   26094:                else
                   26095:                        printf("char (*ctor)(); char (*dtor)(); } __link = \n");
                   26096:        //      printf("{ (struct __linkl *)0, %s, %s };\n",
                   26097:        //              ctor_name ? ctor_name : "0",
                   26098:        //              dtor_name ? dtor_name : "0");
                   26099:                putstring("{ (struct __linkl *)0, ");
                   26100:                if (ctor) ctor->print(); else putch('0');
                   26101:                putch(',');
                   26102:                if (dtor) dtor->print(); else putch('0');
                   26103:                putstring("};\n");
                   26104:        }
                   26105: #endif
                   26106: 
                   26107:         DB( if(Rdebug>=1) error( 'd', "run: vlist: %d", vlist ); );
                   26108:         do {
                   26109:                for (vl* v = vlist; v; v = v->next) v->cl->really_print(v->vt);
                   26110:                vlist = 0;
                   26111: 
                   26112:                for (Plist l=isf_list; l; l=l->l) {
                   26113:                        Pname n = l->f;
                   26114:                        Pfct f = Pfct(n->tp);
                   26115: DB( if(Rdebug>=1)error('d',"isf %n %t f %d addr %d",n,f,f,n->n_addr_taken); );
                   26116:                        if (f->base == OVERLOAD) {
                   26117:                                n = Pgen(f)->fct_list->f;       // first fct
                   26118:                                f = Pfct(n->tp);
                   26119:                        }
                   26120: 
                   26121:                        if (debug_opt==0 && 
                   26122:                                n->n_addr_taken) {
                   26123:                                f->f_inline = 0;
                   26124:                                if (n->n_dcl_printed<2) {
                   26125:                                        if (warning_opt)
                   26126:                                                error('w',"out-of-line copy of %n created",n);
                   26127:                                        n->dcl_print(0);
                   26128:                                }
                   26129:                        }
                   26130:                }
                   26131:        } while (vlist);
                   26132: 
                   26133:        if (strict_opt == 0) { // define static members 
                   26134:                // patch for SysV VAX -g linkage botch
                   26135:                for (Plist l=stat_mem_list; l; l=l->l) {
                   26136:                        Pname n = l->f;
                   26137: // error('d',"stat mem %n %d %d ",n,n->n_initializer,n->n_evaluated);
                   26138:                        if (n->n_initializer==0 && n->n_evaluated==0) {
                   26139:                                Ptype t = n->tp;
                   26140:                                n->n_sto = 0;
                   26141:                                Pname cn = t->is_cl_obj();
                   26142:                                if (cn==0) cn = cl_obj_vec;
                   26143:                                if (cn) (void) t->tsizeof();    // be sure to print class
                   26144:                                if ((cn && Pclass(cn->tp)->has_ctor())
                   26145:                                || t->is_ref())
                   26146:                                        ; // force explicit definition
                   26147:                                else
                   26148:                                        n->dcl_print(0);
                   26149:                        }
                   26150:                }
                   26151:        }
                   26152: 
                   26153:        i = 1;
                   26154:        for (Pname nm=ptbl->get_mem(i); nm; nm=ptbl->get_mem(++i))  {
                   26155:                DB( if(Rdebug>=1) error('d',"ptbl anme %s string2 %s key:%k",nm->string==0?"???":nm->string2,nm->string2==0?"???":nm->string2,nm->n_key); );
                   26156:                if ( nm->n_key == 0 ) { // ptbl used in file, generate definition
                   26157:                        int str1 = (*src_file_name)?strlen(src_file_name)+2:0; // +2 for __
                   26158:                        int str2 = strlen(nm->string2) - str1;
                   26159:                        char *ps = new char[ str2 + 1 ];
                   26160:                        strncpy( ps, nm->string2, str2 ); // grab vtbl name
                   26161:                        ps[str2]='\0';
                   26162:                        ps[2] = 'v';
                   26163:                        fprintf(out_file,"extern struct __mptr %s[];\n",ps);
                   26164:                        // fprintf(out_file,"struct __mptr* %s = %s;\n",nm->string2,ps);
                   26165:                        ptbl_add_pair(nm->string2,ps);
                   26166:                        delete ps;
                   26167:                }
                   26168:        }
                   26169: 
                   26170:        ptbl_init(1);
                   26171:        curloc.putline();
                   26172:        fprintf(out_file,"\n/* the end */\n");
                   26173: }
                   26174: 
                   26175: 
                   26176: #ifdef DBG
                   26177: int Adebug = 0;
                   26178: int Ddebug = 0;
                   26179: int Edebug = 0;
                   26180: int Ldebug = 0;
                   26181: int Mdebug = 0;
                   26182: int Ndebug = 0;
                   26183: int Pdebug = 0;
                   26184: int Rdebug = 0;
                   26185: int Sdebug = 0;
                   26186: int Tdebug = 0;
                   26187: //Ydebug == yydebug initialized in y.tab.c
                   26188: void
                   26189: process_debug_flags( char* p )
                   26190: {
                   26191:        // arg to +Dxxx or debugging comments //@!xxx
                   26192:        // format of xxx == sequence of any combination of
                   26193:        //      +flags  --  increment flags (default)
                   26194:        //      -flags  --  decrement flags
                   26195:        //      0flags  --  unset flags
                   26196:        // where flags are single chars
                   26197:        int incr = 1;
                   26198:        char c;
                   26199:        fprintf(stderr,"\n*** processing debugging flags '%s'\n",p);
                   26200:        while ( c = *p++ ) {
                   26201:                switch ( c ) {
                   26202:                case '+': incr =  1; break;
                   26203:                case '-': incr = -1; break;
                   26204:                case '0': incr =  0; break;
                   26205:                case ' ': break;
                   26206:                // flags...
                   26207:                case 'A': if(incr==0) Adebug=0; else Adebug+=incr; break;
                   26208:                case 'D': if(incr==0) Ddebug=0; else Ddebug+=incr; break;
                   26209:                case 'E': if(incr==0) Edebug=0; else Edebug+=incr; break;
                   26210:                case 'L': if(incr==0) Ldebug=0; else Ldebug+=incr; break;
                   26211:                case 'M': if(incr==0) Mdebug=0; else Mdebug+=incr; break;
                   26212:                case 'N': if(incr==0) Ndebug=0; else Ndebug+=incr; break;
                   26213:                case 'P': if(incr==0) Pdebug=0; else Pdebug+=incr; break;
                   26214:                case 'R': if(incr==0) Rdebug=0; else Rdebug+=incr; break;
                   26215:                case 'S': if(incr==0) Sdebug=0; else Sdebug+=incr; break;
                   26216:                case 'T': if(incr==0) Tdebug=0; else Tdebug+=incr; break;
                   26217:                case 'Y': if(incr==0) Ydebug=0; else Ydebug+=incr; break;
                   26218:                default: error('w',"unknown debugging flag '%c'",c);
                   26219:                }
                   26220:        }
                   26221: }
                   26222: #endif /*DBG*/
                   26223: 
                   26224: int no_of_undcl, no_of_badcall;
                   26225: Pname undcl, badcall;
                   26226: 
                   26227: void pt_option(char * ostr) 
                   26228: { // options +O[BTo] for PT
                   26229:     ostr ++;                   /* skip the O */
                   26230:     switch(*ostr) {
                   26231:       default:
                   26232:        fprintf(stderr, "cfront: argument syntax: invalidZizedTs option (+O[BTo].");
                   26233:        exit(11);
                   26234:     case 'B':
                   26235:        tree_dump_brief = 1;
                   26236:     case 'T':
                   26237:        dump_tree = 1;
                   26238:        if(0 == *(ostr + 1) || strcmp (ostr, "T-") == 0)
                   26239:            dump_tree_arg.output_stream = (ostream*)&cout;
                   26240:        else {
                   26241:            dump_tree_arg.output_stream
                   26242:                = new ofstream (ostr+1, ios::out);
                   26243:            if(dump_tree_arg.output_stream->fail()) {
                   26244:                perror ("cfront");
                   26245:                fprintf (stderr, "Failed to open %s\n", ostr + 1);
                   26246:                exit (11);
                   26247:            }
                   26248:        }
                   26249:        break;
                   26250:       case 'o':
                   26251:        out_file = fopen (ostr+1, "w");
                   26252:        if(out_file == NULL) {
                   26253:            perror ("cfront");
                   26254:            fprintf(stderr, "Failed to open %s\n", ostr+1);
                   26255:            exit(11);
                   26256:        }
                   26257:        break;
                   26258:     }
                   26259: }
                   26260: 
                   26261: main(int argc, char* argv[])
                   26262: /*
                   26263:        read options, initialize, and run
                   26264: */
                   26265: {
                   26266:        register char * cp;
                   26267:        char* afile = "";
                   26268: #ifdef unix
                   26269: 
                   26270: #ifdef COMPLETE_SIG_PF
                   26271:         signal(SIGILL,core_dump);
                   26272:         signal(SIGIOT,core_dump);
                   26273:         signal(SIGEMT,core_dump);
                   26274:         signal(SIGFPE,core_dump);
                   26275:         signal(SIGBUS,core_dump);
                   26276:         signal(SIGSEGV,core_dump);
                   26277: #else
                   26278:        typedef void (*ST)(int ...);    // trick to circumvent problems with old
                   26279:        ST sick = ST(&signal);          // (or C) versions <signal.h>
                   26280:        (*sick)(SIGILL,core_dump);
                   26281:        (*sick)(SIGIOT,core_dump);
                   26282:        (*sick)(SIGEMT,core_dump);
                   26283:        (*sick)(SIGFPE,core_dump);
                   26284:        (*sick)(SIGBUS,core_dump);
                   26285:        (*sick)(SIGSEGV,core_dump);
                   26286: 
                   26287: #endif
                   26288: #endif
                   26289: 
                   26290: // SUM: not needed
                   26291: // #ifdef apollo
                   26292: //     set_sbrk_size(1000000); // resets free store size
                   26293: //#else
                   26294: #ifndef apollo
                   26295:        //(void) malloc(0);     // suppress cashing in V8 malloc
                   26296: #endif
                   26297: 
                   26298:        error_init();
                   26299: 
                   26300:        for (int i=1; i<argc; ++i) {
                   26301:                switch (*(cp=argv[i])) {
                   26302:                case '+':
                   26303:                        while (*++cp) {
                   26304:                                switch(*cp) {
                   26305:                                case 'O':   
                   26306:                                        pt_option(cp);
                   26307:                                        goto xx;
                   26308:                                case 'f':
                   26309:                                        src_file_name = cp+1;
                   26310:                                        goto xx;
                   26311:                                case 'x':       // read cross compilation table
                   26312:                                        if (read_align(afile = cp+1)) {
                   26313:                                                fprintf(stderr,"bad size-table (option +x)\n");
                   26314:                                                exit(11);
                   26315:                                        }
                   26316:                                        goto xx;
                   26317:                                case 'e':
                   26318:                                        switch (*++cp) {
                   26319:                                        case '0':
                   26320:                                        case '1': 
                   26321:                                                vtbl_opt = *cp-'0';
                   26322:                                                break;
                   26323:                                        default:
                   26324:                                                fprintf(stderr,"bad +e option\n");
                   26325:                                                exit(11);
                   26326:                                        }
                   26327:                                        break;
                   26328:                                case 'd':
                   26329:                                        debug_opt = 1;
                   26330:                                        break;
                   26331:                                case 'g':
                   26332:                                        gplus_opt = 1;
                   26333:                                        break;
                   26334:                                case 'D':
                   26335: #ifdef DBG
                   26336:                                        process_debug_flags(++cp);
                   26337: #else
                   26338:                                        error('w',"cfront not compiled for debugging -- +D%s ignored",++cp);
                   26339: #endif
                   26340:                                        goto xx;
                   26341:                                case 'w':
                   26342:                                        warning_opt = 1;
                   26343:                                        break;
                   26344:                                case 'a':
                   26345:                                        switch (*++cp) {
                   26346:                                        case '0':
                   26347:                                        case '1': 
                   26348:                                                ansi_opt = *cp-'0';
                   26349:                                                break;
                   26350:                                        default:
                   26351:                                                fprintf(stderr,"bad +a option\n");
                   26352:                                                exit(11);
                   26353:                                        }
                   26354:                                        break;
                   26355:                                case 'p':
                   26356:                                        strict_opt = 1;
                   26357:                                        break;
                   26358:                                case 'L':
                   26359:                                        line_format = "\n#line %d \"%s\"\n";
                   26360:                                        break;
                   26361:                                default:
                   26362:                                        fprintf(stderr,"%s: unexpected option: +%c ignored\n",prog_name,*cp);
                   26363: 
                   26364:                                }
                   26365:                        }
                   26366:                xx:
                   26367:                        break;
                   26368:                default:
                   26369:                        fprintf(stderr,"%s: bad argument \"%s\"\n",prog_name,cp);
                   26370:                        exit(11);
                   26371:                }
                   26372:        }
                   26373: 
                   26374: 
                   26375:        fprintf(out_file,line_format+1,1,src_file_name); // strips leading \n
                   26376:        fprintf(out_file,"\n/* %s */\n",prog_name);
                   26377:        if (*src_file_name) fprintf(out_file,"/* < %s > */\n",src_file_name);
                   26378: 
                   26379: //     if (Nspy) {
                   26380: //             start_time = time(0);
                   26381: //             print_align(afile);
                   26382: //     }
                   26383:        fflush(stderr);
                   26384:        otbl_init();
                   26385:        lex_init();
                   26386:        syn_init();
                   26387:        typ_init();
                   26388:        simpl_init();
                   26389:        scan_started = 1;
                   26390:        curloc.putline();
                   26391:        if ((BI_IN_BYTE==0) && (SZ_INT==0) && (SZ_WPTR==0))
                   26392:                error("no size/alignment values - use +x of provide #ifdef in size.h");
                   26393:        run();
                   26394:        if(dump_tree) {
                   26395:                ostream_printf(*dump_tree_arg.output_stream, "------------ GTBL ------------\n\n");
                   26396:                display_cfront_node (dump_tree_arg, ktbl);
                   26397:                ostream_printf(*dump_tree_arg.output_stream, "------------ KTBL ------------\n\n");
                   26398:                display_cfront_node (dump_tree_arg, ktbl);
                   26399:        }                                              
                   26400: 
                   26401: //     if (Nspy) {
                   26402: //             stop_time = time(0);
                   26403: //             spy(src_file_name);
                   26404: //     }
                   26405:        exit( (0<=error_count && error_count<127) ? error_count : 127);
                   26406: }
                   26407: 
                   26408: char* st_name(char* pref)
                   26409: /*
                   26410:        make name "pref|source_file_name|_" or "pref|source_file_name|_"
                   26411:        where non alphanumeric characters are replaced with '_'
                   26412:        and add def_name at end to ensure uniqueness
                   26413: */
                   26414: {
                   26415:        int prefl = strlen(pref);
                   26416:        int strl = prefl + 2;   // trailing '_' and 0
                   26417:        if (*src_file_name) strl += strlen(src_file_name);
                   26418:        char* defs;
                   26419:        int defl;
                   26420:        if (def_name) {
                   26421:                defs = def_name->string;
                   26422:                defl = strlen(defs)+1;  // '_'
                   26423:        }
                   26424:        else {
                   26425:                defs = 0;
                   26426:                defl = 0;
                   26427:        }
                   26428:        char* name = new char[strl+defl];
                   26429:        strcpy(name,pref);
                   26430:        if (*src_file_name) strcpy(name+prefl,src_file_name);
                   26431:        name[strl-2] = '_';
                   26432:        name[strl-1] = 0;
                   26433: //     char *p = name;
                   26434: //     while ( *++p ) if (!isalpha(*p) && !isdigit(*p)) *p = '_';
                   26435:        for (char* p = name; *p; p++) if (!isalpha(*p) && !isdigit(*p)) *p = '_';
                   26436:        if (defs) {
                   26437:                strcpy(name+strl-1,defs);       // after the '_'
                   26438:                name[strl+defl-2] = '_';
                   26439:                name[strl+defl-1] = 0;
                   26440:        }
                   26441: #ifdef DENSE
                   26442:        void chop(char*);
                   26443:        chop(name);
                   26444: #endif
                   26445: 
                   26446:        return name;
                   26447: }
                   26448: 0707071010112041141004440001630000160000010112640466055427400001100000007532makefile#ident    "@(#)ctrans:src/makefile        1.3"
                   26449: ###############################################################################
                   26450: #                      Copyright (c) 1984 AT&T
                   26451: #                        All Rights Reserved   
                   26452: #
                   26453: #      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T
                   26454: #      
                   26455: #      The copyright notice above does not evidence any        
                   26456: #      actual or intended publication of such source code.
                   26457: #
                   26458: ###############################################################################
                   26459: CC     =       CC
                   26460: 
                   26461: #The ANSI_OUT option has been replaced by the +a1 and +a0 compilation options
                   26462: 
                   26463: #for systems which only recognize identifiers of up to 31 characters
                   26464: #setting DENSE to -DDENSE causes cfront to generate internal names
                   26465: #of 31 characters or less 
                   26466: DENSE=
                   26467: 
                   26468: # The use of RETBUG is nolonger needed with version 2.0 and has been removed.
                   26469: # RETBUG was used in 1.* Translator versions to circumvent a C compiler bug.
                   26470: 
                   26471: CCFLAGS=-O
                   26472: 
                   26473: # top level makefile modifies the following
                   26474: MPMACRO        = PATCH
                   26475: MPFILE = patch
                   26476: 
                   26477: OFILES =       alloc.o dcl.o dcl2.o dcl3.o dcl4.o del.o \
                   26478:                discrim.o doprint.o error.o expand.o \
                   26479:                expr.o expr2.o expr3.o find.o hash.o lalex.o lex.o main.o \
                   26480:                norm.o norm2.o print.o print2.o print_self.o repr.o simpl.o \
                   26481:                simpl2.o size.o table.o template.o tree_copy.o tree_dump.o \
                   26482:                tree_walk.o typ.o typ2.o y.tab.o 
                   26483: 
                   26484: cfront:        $(OFILES)
                   26485:        $(CC)   -o cfront $(CCFLAGS) $(OFILES)
                   26486: 
                   26487: $(OFILES):     cfront.h token.h typedef.h
                   26488: 
                   26489: y.tab.c:       gram.y 
                   26490:        yacc gram.y
                   26491: 
                   26492: alloc.o:       alloc.c
                   26493:        $(CC) $(CCFLAGS) -c alloc.c 
                   26494: 
                   26495: dcl.o: dcl.c size.h
                   26496:        $(CC) $(CCFLAGS) -c dcl.c 
                   26497: 
                   26498: dcl2.o:        dcl2.c size.h
                   26499:        $(CC) $(CCFLAGS) -c dcl2.c 
                   26500: 
                   26501: dcl3.o:        dcl3.c size.h
                   26502:        $(CC) $(CCFLAGS) -c dcl3.c 
                   26503: 
                   26504: dcl4.o:        dcl4.c size.h
                   26505:        $(CC) $(CCFLAGS) -c dcl4.c 
                   26506: 
                   26507: del.o: del.c
                   26508:        $(CC) $(CCFLAGS) -c del.c 
                   26509: 
                   26510: discrim.o:     discrim.c cfront.h
                   26511:        $(CC) $(CCFLAGS) -c discrim.c
                   26512: 
                   26513: doprint.o:     doprint.c
                   26514:        $(CC) $(CCFLAGS) -c doprint.c
                   26515: 
                   26516: error.o:       error.c size.h
                   26517:        $(CC) $(CCFLAGS) -c error.c 
                   26518: 
                   26519: expand.o:      expand.c
                   26520:        $(CC) $(CCFLAGS) -c expand.c 
                   26521: 
                   26522: expr.o:        expr.c size.h
                   26523:        $(CC) $(CCFLAGS) -c expr.c 
                   26524: 
                   26525: expr2.o:       expr2.c size.h
                   26526:        $(CC) $(CCFLAGS) -c expr2.c 
                   26527: 
                   26528: expr3.o:       expr3.c size.h
                   26529:        $(CC) $(CCFLAGS) -c expr3.c 
                   26530: 
                   26531: find.o:        find.c 
                   26532:        $(CC) $(CCFLAGS) -c find.c 
                   26533: 
                   26534: hash.o: hash.c hash.h
                   26535:        $(CC) $(CCFLAGS) -c hash.c 
                   26536: 
                   26537: lalex.o:lalex.c yystype.h tqueue.h 
                   26538:        $(CC) $(CCFLAGS) -c lalex.c
                   26539: 
                   26540: lex.o: lex.c size.h tqueue.h yystype.h
                   26541:        $(CC) $(CCFLAGS) -c lex.c 
                   26542: 
                   26543: # main depends on this makefile to force recompilation
                   26544: # when going from patch to munch
                   26545: main.o:        main.c makefile
                   26546:        $(CC) -D$(MPMACRO) $(DENSE) $(CCFLAGS) -c main.c 
                   26547: 
                   26548: norm.o:        norm.c size.h
                   26549:        $(CC) $(CCFLAGS) -c norm.c 
                   26550: 
                   26551: norm2.o:       norm2.c size.h
                   26552:        $(CC) $(CCFLAGS) -c norm2.c 
                   26553: 
                   26554: print.o:       print.c
                   26555:        $(CC) $(CCFLAGS) -c print.c 
                   26556: 
                   26557: print2.o:      print2.c
                   26558:        $(CC) $(DENSE) $(CCFLAGS) -c print2.c 
                   26559: 
                   26560: print_self.o:   print_self.c
                   26561:        $(CC) $(CCFLAGS) -c print_self.c 
                   26562: 
                   26563: repr.o:        repr.c
                   26564:        $(CC) $(CCFLAGS) -c repr.c 
                   26565: 
                   26566: simpl.o:       simpl.c size.h
                   26567:        $(CC) $(CCFLAGS) -c simpl.c 
                   26568: 
                   26569: simpl2.o:      simpl2.c size.h
                   26570:        $(CC) $(CCFLAGS) -c simpl2.c 
                   26571: 
                   26572: size.o:        size.c size.h
                   26573:        $(CC) $(CCFLAGS) -c size.c 
                   26574: 
                   26575: table.o:       table.c
                   26576:        $(CC) $(CCFLAGS) -c table.c 
                   26577: 
                   26578: template.o: template.c
                   26579:        $(CC) $(CCFLAGS) -c template.c 
                   26580: 
                   26581: tree_copy.o: tree_copy.c
                   26582:        $(CC) $(CCFLAGS) -c tree_copy.c 
                   26583: 
                   26584: tree_dump.o:    tree_dump.c cfront.h
                   26585:        $(CC) $(CCFLAGS) -c tree_dump.c
                   26586: 
                   26587: tree_walk.o: tree_walk.c
                   26588:        $(CC) $(CCFLAGS) -c tree_walk.c 
                   26589: 
                   26590: typ.o: typ.c size.h
                   26591:        $(CC) $(CCFLAGS) -c typ.c 
                   26592: 
                   26593: typ2.o:        typ2.c size.h
                   26594:        $(CC) $(CCFLAGS) -c typ2.c 
                   26595: 
                   26596: y.tab.o:       y.tab.c size.h 
                   26597:        $(CC) -DGRAM $(CCFLAGS) -c y.tab.c 
                   26598: 
                   26599: cpio:  
                   26600:        ls alloc.c dcl.c dcl2.c dcl3.c dcl4.c del.c discrim.c doprint.c \
                   26601:                error.c expand.c expr.c expr2.c expr3.c find.c hash.c \
                   26602:                lalex.c lex.c main.c norm.c norm2.c print.c print2.c \
                   26603:                print_self.c repr.c simpl.c simpl2.c size.c table.c \
                   26604:                template.c tree_copy.c tree_dump.c tree_walk.c typ.c typ2.c \
                   26605:                gram.y \
                   26606:                cfront.h token.h size.h tqueue.h typedef.h yystype.h \
                   26607:                hash.h ios_printf.h node_classes.h print_self.h \
                   26608:                template.h token_names.h tree_copy.h tree_dump.h tree_walk.h \
                   26609:                makefile | cpio -oc > cfront.cpio
                   26610: 
                   26611: 0707071010112046101004440001630000160000010212500466055421000001700000012215node_classes.h/* ident "@(#)ctrans:src/node_classes.h     1.2" */
                   26612: /* 
                   26613:  * node_classes.h 
                   26614:  */
                   26615: 
                   26616: #ifndef _node_classes
                   26617: #define _node_classes
                   26618: 
                   26619: enum discriminator_error {
                   26620:     discrim_none_valid = 0,
                   26621:     discrim_bad_index = -1,
                   26622:     discrim_inconsistent_node = -2,
                   26623: };
                   26624: 
                   26625: enum node_class {
                   26626:     nc_unused = 0,
                   26627:     nc_eof = 1,
                   26628:     nc_virt = 2,
                   26629:     nc_nlist = 3,
                   26630:     nc_gen = 4,
                   26631:     nc_vec = 5,
                   26632:     nc_ptr = 6,
                   26633:     nc_fct = 7,
                   26634:     nc_table = 8,
                   26635:     nc_basetype = 9,
                   26636:     nc_name = 10,
                   26637:     nc_expr = 11,
                   26638:     nc_stmt = 12,
                   26639:     nc_enumdef = 13,
                   26640:     nc_classdef = 14,
                   26641:     nc_baseclass = 15,
                   26642:     nc_iline = 16,
                   26643:     nc_ia = 17,
                   26644: };
                   26645:     
                   26646: /* 
                   26647:        searching this is slower than a directly indexed array,
                   26648:        but this is more maintainable. We can speed it up later. 
                   26649: */
                   26650: 
                   26651: #ifdef DEFINE_TOKEN_CLASS_TABLE
                   26652: struct token_class {
                   26653:     TOK token;
                   26654:     node_class nclass;
                   26655: } token_classes[] = {
                   26656:     { EOFTOK, nc_eof },
                   26657:     { ASM, nc_stmt },
                   26658:     { AUTO, nc_basetype },
                   26659:     { BREAK, nc_stmt },
                   26660:     { CASE, nc_stmt },
                   26661:     { CHAR, nc_basetype },
                   26662:     { CLASS, nc_classdef },
                   26663:     { CONTINUE, nc_stmt },
                   26664:     { DEFAULT, nc_stmt },
                   26665:     { DELETE, nc_expr },
                   26666:     { DO, nc_stmt },
                   26667:     { DOUBLE, nc_basetype },
                   26668:     { ELSE, nc_stmt },
                   26669:     { ENUM, nc_enumdef },
                   26670:     { EXTERN, nc_basetype },
                   26671:     { FLOAT, nc_basetype },
                   26672:     { FOR, nc_stmt },
                   26673:     { FORTRAN, nc_unused },
                   26674:     { FRIEND, nc_basetype },
                   26675:     { GOTO, nc_stmt },
                   26676:     { IF, nc_stmt },
                   26677:     { INT, nc_basetype },
                   26678:     { LONG, nc_basetype },
                   26679:     { NEW, nc_expr },
                   26680:     { OPERATOR, nc_fct },
                   26681:     { RETURN, nc_stmt },
                   26682:     { PUBLIC, nc_name },
                   26683:     { CONST, nc_basetype },
                   26684:     { REGISTER, nc_basetype },
                   26685:     { RETURN, nc_stmt },
                   26686:     { SHORT, nc_basetype },
                   26687:     { SIZEOF, nc_expr },
                   26688:     { STATIC, nc_basetype },
                   26689:     { STRUCT, nc_unused },
                   26690:     { SWITCH, nc_stmt },
                   26691:     { THIS, nc_expr },
                   26692:     { TYPEDEF, nc_basetype },
                   26693:     { UNION, nc_unused },
                   26694:     { UNSIGNED, nc_basetype },
                   26695:     { VOID, nc_basetype },
                   26696:     { WHILE, nc_stmt },
                   26697:     { LP, nc_unused },
                   26698:     { RP, nc_unused },
                   26699:     { LB, nc_unused },
                   26700:     { RB, nc_unused },
                   26701:     { REF, nc_expr },
                   26702:     { DOT, nc_expr },
                   26703:     { NOT, nc_expr },
                   26704:     { COMPL, nc_expr },
                   26705:     { INCR, nc_expr },
                   26706:     { DECR, nc_expr },
                   26707:     { MUL, nc_expr },
                   26708:     { DIV, nc_expr },
                   26709:     { AND, nc_expr },
                   26710:     { MOD, nc_expr },
                   26711:     { PLUS, nc_expr },
                   26712:     { MINUS, nc_expr },
                   26713:     { LS, nc_expr },
                   26714:     { RS, nc_expr },
                   26715:     { LT, nc_expr },
                   26716:     { LE, nc_expr },
                   26717:     { GT, nc_expr },
                   26718:     { GE, nc_expr },
                   26719:     { EQ, nc_expr },
                   26720:     { NE, nc_expr },
                   26721:     { ER, nc_expr },
                   26722:     { OR, nc_expr },
                   26723:     { ANDAND, nc_expr },
                   26724:     { OROR, nc_expr },
                   26725:     { QUEST, nc_expr },
                   26726:     { COLON, nc_unused },
                   26727:     { ASSIGN, nc_expr },
                   26728:     { CM, nc_expr },
                   26729:     { SM, nc_stmt },
                   26730:     { SM_PARAM, nc_stmt },
                   26731:     { LC, nc_unused },
                   26732:     { RC, nc_unused },
                   26733:     { INLINE, nc_fct },
                   26734:     { OVERLOAD, nc_gen },
                   26735:     { VIRTUAL, nc_fct },       /* but might be a basecl */
                   26736:     { COERCE, nc_unused },
                   26737:     { PROTECTED, nc_name },
                   26738:     { ID, nc_unused },
                   26739:     { STRING, nc_expr },
                   26740:     { ICON, nc_expr },
                   26741:     { FCON, nc_expr },
                   26742:     { CCON, nc_expr },
                   26743:     { NAME, nc_name },         /* but might be basecl */
                   26744:     { ZERO, nc_expr },
                   26745:     { ASOP, nc_expr },
                   26746:     { RELOP, nc_expr },
                   26747:     { EQUOP, nc_expr },
                   26748:     { DIVOP, nc_expr },
                   26749:     { SHIFTOP, nc_expr },
                   26750:     { ICOP, nc_expr },
                   26751:     { UNOP, nc_expr },
                   26752:     { TYPE, nc_basetype },
                   26753:     { UMINUS, nc_expr },
                   26754:     { FCT, nc_fct },
                   26755:     { CALL, nc_expr },
                   26756:     { VEC, nc_vec },
                   26757:     { DEREF, nc_expr },
                   26758:     { ADDROF, nc_expr },
                   26759:     { CAST, nc_expr },
                   26760:     { FIELD, nc_basetype },
                   26761:     { LABEL, nc_stmt },
                   26762:     { BLOCK, nc_stmt },
                   26763:     { DCL, nc_stmt },
                   26764:     { COBJ, nc_basetype },
                   26765:     { EOBJ, nc_basetype },
                   26766:     { TNAME, nc_name },
                   26767:     { ILIST, nc_expr },
                   26768:     { PTR, nc_ptr },
                   26769:     { ASPLUS, nc_expr },
                   26770:     { ASMINUS, nc_expr },
                   26771:     { ASMUL, nc_expr },
                   26772:     { ASDIV, nc_expr },
                   26773:     { ASMOD, nc_expr },
                   26774:     { ASAND, nc_expr },
                   26775:     { ASOR, nc_expr },
                   26776:     { ASER, nc_expr },
                   26777:     { ASLS, nc_expr },
                   26778:     { ASRS, nc_expr },    
                   26779:     { ARG, nc_basetype },
                   26780:     { ZTYPE, nc_basetype },
                   26781:     { ARGT, nc_basetype },
                   26782:     { ELIST, nc_expr },
                   26783:     { ANY, nc_basetype },
                   26784:     { TABLE, nc_table },
                   26785:     { LOC, nc_unused },
                   26786:     { DUMMY, nc_expr },
                   26787:     { G_ADDROF, nc_expr },
                   26788:     { G_CALL, nc_expr },
                   26789:     { G_CM, nc_expr },
                   26790:     { IVAL, nc_expr },
                   26791:     { ELLIPSIS, nc_unused },
                   26792:     { AGGR, nc_unused },
                   26793:     { RPTR, nc_ptr },
                   26794:     { HIDDEN, nc_unused },
                   26795:     { MEM, nc_expr },
                   26796:     { CTOR, nc_unused },
                   26797:     { DTOR, nc_unused },
                   26798:     { CONST_PTR, nc_ptr },
                   26799:     { CONST_RPTR, nc_ptr },
                   26800:     { TEXT, nc_expr },
                   26801:     { PAIR, nc_stmt },
                   26802:     { ANON, nc_unused },
                   26803:     { ICALL, nc_expr },
                   26804:     { ANAME, nc_expr },
                   26805:     { VOLATILE, nc_basetype },
                   26806:     { SIGNED, nc_basetype },
                   26807:     { UPLUS, nc_expr },
                   26808:     { MEMPTR, nc_unused },
                   26809:     { PRIVATE, nc_name },
                   26810:     { PR, nc_unused },
                   26811:     { MDOT, nc_expr },
                   26812:     { TSCOPE, nc_unused },
                   26813:     { DECL_MARKER, nc_unused },
                   26814:     { REFMUL, nc_expr },
                   26815:     { LDOUBLE, nc_basetype },
                   26816:     { LINKAGE, nc_unused },
                   26817:     { LOCAL, nc_basetype },
                   26818:     { GNEW, nc_expr },
                   26819:     { TEMPLATE, nc_unused },
                   26820:     { STAT_INIT, nc_unused },
                   26821:     { CATCH, nc_unused },
                   26822:     { GDELETE, nc_expr },
                   26823:     { XVIRT, nc_virt },
                   26824:     { XNLIST, nc_nlist },
                   26825:     { XILINE, nc_iline },
                   26826:     { XIA, nc_ia },
                   26827:     { VALUE, nc_expr },
                   26828:     { XDELETED_NODE, nc_unused },
                   26829: };
                   26830: #endif
                   26831: 
                   26832: node_class classify_node (Pnode, int&);
                   26833: node_class classify_node (Pnode);
                   26834: 
                   26835: #endif
                   26836: 0707071010112044361004440001630000160000010204500466055405300000700000120447norm.c/*ident     "@(#)ctrans:src/norm.c  1.10" */
                   26837: /************************************************************************
                   26838: 
                   26839:        C++ source for cfront, the C++ compiler front-end
                   26840:        written in the computer science research center of Bell Labs
                   26841: 
                   26842:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   26843:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   26844: 
                   26845: norm.c:
                   26846: 
                   26847:        "normalization" handles problems which could have been handled
                   26848:        by the syntax analyser; but has not been done. The idea is
                   26849:        to simplify the grammar and the actions accociated with it,
                   26850:        and to get a more robust error handling
                   26851: 
                   26852: ****************************************************************************/
                   26853: #ifdef c_plusplus
                   26854: overload nested_hide;
                   26855: #endif
                   26856: 
                   26857: #include "cfront.h"
                   26858: #include "size.h"
                   26859: #include "template.h"
                   26860: 
                   26861: extern Pname do_nested_type(Pname);
                   26862: extern int is_anon(char*);
                   26863: 
                   26864: Pname sta_name = 0;
                   26865: 
                   26866: void syn_init()
                   26867: {
                   26868:        any_type = new basetype(ANY,0);
                   26869:        PERM(any_type); any_type->defined = DEFINED;
                   26870:        dummy = new expr(DUMMY,0,0);
                   26871:        PERM(dummy);
                   26872:        dummy->tp = any_type;
                   26873:        zero = new expr(ZERO,0,0);
                   26874:        PERM(zero);
                   26875:        sta_name = new name;
                   26876:        PERM(sta_name);
                   26877: //     Gtbl = new table(GTBLSIZE,0,0); //SYM
                   26878: //     Ctbl = Gtbl; //SYM
                   26879: }
                   26880: 
                   26881: int stcount;
                   26882: 
                   26883: char* make_name(TOK c)
                   26884: {
                   26885:        char* s = new char[8];  // as it happens: fits in two words
                   26886: 
                   26887:        if (10000 <= ++stcount) error('i',"too many generatedNs");
                   26888: 
                   26889:        sprintf(s,"__%c%d",c,stcount);
                   26890:        return s;
                   26891: }
                   26892: 
                   26893: Pbase basetype::type_adj(TOK t)
                   26894: {
                   26895: DB(if(Ndebug>=1)error('d',"'%k'->type_adj(%k) --%t b_xname%n",base,t,this,b_xname););
                   26896:        if (b_xname) {
                   26897:                if (base)
                   26898:                        error("badBT:%n%k",b_xname,t);
                   26899:                else {
                   26900:                        base = TYPE;
                   26901:                        b_name = b_xname;
                   26902:                }
                   26903:                b_xname = 0;
                   26904:        }
                   26905: 
                   26906:        switch (t) {
                   26907:        case TYPEDEF:   b_typedef = 1;  break;
                   26908:        case INLINE:    b_inline = 1;   break;
                   26909:        case VIRTUAL:   b_virtual = 1;  break;
                   26910:        case CONST:     if (b_const) error('w',"two const declarators");
                   26911:                        b_const = 1;    break;
                   26912:        case UNSIGNED:  b_unsigned = 1; break;
                   26913:        case SHORT:     b_short = 1;    break;
                   26914:        case LONG:      if (b_long) error('w',"two long declarators");
                   26915:                        if (base == DOUBLE)
                   26916:                                base = LDOUBLE;
                   26917:                        else
                   26918:                                b_long = 1;
                   26919:                        break;
                   26920:        case FRIEND:
                   26921:        case OVERLOAD:
                   26922:        case EXTERN:
                   26923:        case STATIC:
                   26924:        case AUTO:
                   26925:        case REGISTER:
                   26926:                if (b_sto)
                   26927:                        error("badBT:%k%k",b_sto,t);
                   26928:                else
                   26929:                        b_sto = t;
                   26930:                break;
                   26931:        case DOUBLE:
                   26932:                if (b_long) {
                   26933:                        t = LDOUBLE;
                   26934:                        b_long = 0;
                   26935:                }
                   26936:                // no break
                   26937:        case VOID:
                   26938:        case CHAR:
                   26939:        case INT:
                   26940:        case FLOAT:
                   26941:                if (base)
                   26942:                        error("badBT:%k%k",base,t);
                   26943:                else
                   26944:                        base = t; 
                   26945:                break;
                   26946:        case SIGNED:
                   26947:        case VOLATILE:
                   26948:                error('w',"\"%k\" not implemented (ignored)",t);
                   26949:                break;
                   26950:        default:
                   26951:                error('i',"BT::type_adj(%k)",t);
                   26952:        }
                   26953:        return this;
                   26954: }
                   26955: 
                   26956: Pbase basetype::name_adj(Pname n)
                   26957: {
                   26958: DB(if(Ndebug>=1)error('d',"'%k'->name_adj(%n) --%t b_xname%n",base,n,this,b_xname));
                   26959:        if (b_xname) {
                   26960:                if (base)
                   26961:                        error("badBT:%n%n",b_xname,n);
                   26962:                else {
                   26963:                        base = TYPE;
                   26964:                        b_name = b_xname;
                   26965:                }
                   26966:                b_xname = 0;
                   26967:        }
                   26968: 
                   26969:        if ( base==0 
                   26970:                && n->base == TNAME 
                   26971:                && ( n->tp->base!=COBJ || in_arg_list )) {
                   26972:                        base = TYPE;
                   26973:                        b_name = n;
                   26974:        }
                   26975:        else
                   26976:                b_xname = n;
                   26977: 
                   26978:        return this;
                   26979: }
                   26980: 
                   26981: static TOK type_set( Pbase b )
                   26982: {
                   26983:        TOK t = 0;
                   26984: 
                   26985:        if ( b->b_long ) t = LONG;
                   26986:        else if ( b->b_short ) t = SHORT;
                   26987:        else if ( b->b_unsigned ) t = UNSIGNED;
                   26988:        else if ( b->b_inline ) t = INLINE;
                   26989:        else if ( b->b_virtual ) t = VIRTUAL;
                   26990:        else if ( b->b_sto == OVERLOAD ) t = OVERLOAD;
                   26991:        return t;
                   26992: }
                   26993: 
                   26994: int declTag = 1;
                   26995: 
                   26996: Pbase basetype::base_adj(Pbase b)
                   26997: {
                   26998: DB(if(Ndebug>=1)error('d',"'%k'->base_adj(%t) --%t b_xname%n",base,b,this,b_xname));
                   26999:        Pname bn = b->b_name;
                   27000: 
                   27001:        switch (base) {
                   27002:        case COBJ:
                   27003:        case EOBJ:
                   27004:                error("NX after%k%n",base,b_name);
                   27005:                return this;
                   27006:        }
                   27007: 
                   27008:        TOK t;
                   27009:        if (base) {
                   27010:                if (b_name)
                   27011:                        error("badBT:%k%n%k%n",base,b_name,b->base,bn);
                   27012:                else
                   27013:                        error("badBT:%k%k%n",base,b->base,bn);
                   27014:        }
                   27015:        else if ( t = type_set(this)) {
                   27016:                if (b_name)
                   27017:                        error("badBT:%k%n%k%n",t,b_name,b->base,bn);
                   27018:                else {
                   27019:                         if ( declTag++ && (t!= INLINE)) error("badBT:%k%k%n",t,b->base,bn);
                   27020:                        base=b->base; b_name = bn;
                   27021: // error('d',"base_adj: t: %k", t );
                   27022:                }
                   27023:        }
                   27024:        else {
                   27025:                base = b->base;
                   27026:                b_name = bn;
                   27027:                b_table = b->b_table;
                   27028:        }
                   27029: 
                   27030:        if ( b->base == COBJ ) {
                   27031:                Pclass cl = Pclass(bn->tp);
                   27032:                if ( cl->in_class && 
                   27033:                        bn->tpdef &&
                   27034:                        bn->tpdef->lex_level == NESTED ) 
                   27035:                { // peculiar case: class x { typedef class bn {} _bn; ... 
                   27036:                  // bn has been half dealt with in do_nested_type ...
                   27037:                        Pname n = new name(bn->string);
                   27038:                        n->tp = b;
                   27039:                        Pname nn = ktbl->insert(n, NESTED); //SYM
                   27040:                        nn->tpdef = bn->tpdef;
                   27041:                        nn->tpdef->lex_level = nn->lex_level = 0;
                   27042:                        bn->tpdef = 0;
                   27043:                }
                   27044:        }
                   27045: 
                   27046:        return this;
                   27047: }
                   27048: 
                   27049: Pbase basetype::check(Pname n)
                   27050: /*
                   27051:        "n" is the first name to be declared using "this"
                   27052:        check the consistency of "this"
                   27053:        and use "b_xname" for "n->string" if possible and needed
                   27054: */
                   27055: {
                   27056:        b_inline = 0;
                   27057:        b_virtual = 0;
                   27058: //error('d',"basetype::check(%n) base %k b_xname %n",n,base,b_xname);
                   27059: 
                   27060:        if (b_xname && (n->tp || n->string)) {
                   27061:                if (base)
                   27062:                        error("badBT:%k%n",base,b_xname);
                   27063:                else {
                   27064:                        base = TYPE;
                   27065:                        b_name = b_xname;
                   27066:                }
                   27067:                b_xname = 0;
                   27068:        }
                   27069: 
                   27070:        if (b_xname) {
                   27071:                if (n->string)
                   27072:                        error("twoNs inD:%n%n",b_xname,n);
                   27073:                else {
                   27074:                        n->string = b_xname->string;
                   27075:                        b_xname->hide();
                   27076:                }
                   27077:                b_xname = 0;
                   27078:        }
                   27079: 
                   27080:        if (ccl==0
                   27081:        && n
                   27082:        && n->n_oper==TNAME
                   27083:        && n->n_qualifier==0
                   27084:        && n->string) { // hide type name
                   27085:                Pname nx = ktbl->look(n->string,0); //SYM
                   27086:                if (nx) nx->hide();
                   27087:        }
                   27088: 
                   27089:        int defa = 0;
                   27090:        switch (base) {
                   27091:        case 0:
                   27092:                defa = 1;
                   27093:                base = INT;
                   27094:                break;
                   27095:        case EOBJ:
                   27096:        case COBJ:
                   27097:                if (b_name->base == TNAME) error('i',"TN%n inCO %p",b_name,this);
                   27098:        }
                   27099: 
                   27100:        if (b_long || b_short) {
                   27101:                TOK sl = (b_short) ? SHORT : LONG;
                   27102:                if (b_long && b_short) error("badBT:long short%k%n",base,n);
                   27103:                if (base != INT)
                   27104:                        error("badBT:%k%k%n",sl,base,n);
                   27105:                else
                   27106:                        base = sl;
                   27107:                b_short = b_long = 0;
                   27108:        }
                   27109: 
                   27110:        if (b_typedef && b_sto) error("badBT:Tdef%k%n",b_sto,n);
                   27111:        b_typedef = b_sto = 0; 
                   27112: 
                   27113:        if (b_linkage) {
                   27114:                if (1 <= bl_level) error("local linkage directive");
                   27115:        }
                   27116: 
                   27117:        if (Pfctvec_type == 0) return this;
                   27118: 
                   27119:        if (b_const) {
                   27120:                if (b_unsigned) {
                   27121:                        switch (base) {
                   27122:                        default:
                   27123:                                error("badBT: unsigned const %k%n",base,n);
                   27124:                                b_unsigned = 0;
                   27125:                        case LONG:
                   27126:                        case SHORT:
                   27127:                        case INT:
                   27128:                        case CHAR:
                   27129:                                return this;
                   27130:                        }
                   27131:                }
                   27132:                return this;
                   27133:        }
                   27134:        else if (b_unsigned) {
                   27135:                switch (base) {
                   27136:                case LONG:
                   27137:                        delete this;
                   27138:                        return ulong_type;
                   27139:                case SHORT:
                   27140:                        delete this;
                   27141:                        return ushort_type;
                   27142:                case INT:
                   27143:                        delete this;
                   27144:                        return uint_type;
                   27145:                case CHAR:
                   27146:                        delete this;
                   27147:                        return uchar_type;
                   27148:                default:
                   27149:                        error("badBT: unsigned%k%n",base,n);
                   27150:                        b_unsigned = 0;
                   27151:                        return this;
                   27152:                }
                   27153:        }
                   27154:        else {
                   27155:                switch (base) {
                   27156:                case LONG:
                   27157:                        delete this;
                   27158:                        return long_type;
                   27159:                case SHORT:
                   27160:                        delete this;
                   27161:                        return short_type;
                   27162:                case INT:
                   27163:                         if (this==int_type || this==defa_type) return this;
                   27164:                 //      if (this != int_type)
                   27165:                                 delete this;
                   27166:                         if (defa) return defa_type;
                   27167:                         return int_type;
                   27168:                case CHAR:
                   27169:                        delete this;
                   27170:                        return char_type;
                   27171:                case VOID:
                   27172:                        delete this;
                   27173:                        return void_type;
                   27174:                case TYPE:
                   27175:                        /* use a single base saved in the keyword */
                   27176:                        if (b_name->n_qualifier) {
                   27177:                                Pbase rv = Pbase(b_name->n_qualifier);
                   27178:                                delete this;
                   27179:                                return rv;
                   27180:                        }
                   27181:                        else {
                   27182:                                PERM(this);
                   27183:                                b_name->n_qualifier = (Pname)this;
                   27184:                                return this;
                   27185:                        }
                   27186:                default:
                   27187:                        return this;
                   27188:                }
                   27189:        }
                   27190: }
                   27191: 
                   27192: Pname basetype::aggr()
                   27193: /*
                   27194:        "type SM" seen e.g.     struct s {};
                   27195:                                class x;
                   27196:                                enum e;
                   27197:                                int tname;
                   27198:                                friend cname;
                   27199:                                friend class x;
                   27200:                                int;
                   27201:                                
                   27202:                                typedef int i; // where i is tname
                   27203: 
                   27204:        convert
                   27205:                union { ... };
                   27206:        into
                   27207:                union name { ... } name ;
                   27208: */
                   27209: {
                   27210: DB(if(Ndebug>=1)error('d',"'%k'->aggr() --%t b_xname%n ccl%t",base,this,b_xname,ccl));
                   27211:        if (b_xname) {
                   27212:                if (base) {
                   27213:                        Pname n = new name(b_xname->string);
                   27214:                /*SYM?*/if (ccl && b_xname->tpdef)
                   27215:                /*SYM?*/        n->tpdef = b_xname->tpdef;
                   27216:                         b_xname->hide();
                   27217:                         b_xname = 0;
                   27218:                        return n->normalize(this,0,0);
                   27219:                }
                   27220:                else {
                   27221:                        base = TYPE;
                   27222:                        b_name = b_xname;
                   27223:                        b_xname = 0;
                   27224:                }
                   27225:        }
                   27226: 
                   27227:        switch (base) {
                   27228:        case COBJ:
                   27229:        {       Pclass cl = Pclass(b_name->tp);
                   27230:                char* s = cl->string;
                   27231:        /*SYM?*/if (b_name->base == TNAME) error('i',"TN%n inCO",b_name);
                   27232:                if (b_const) error("const%k%n",cl->csu,b_name);
                   27233: 
                   27234:                if (cl->c_body == 2) {  /* body seen */
                   27235:                        if (s[0]=='_' && s[1]=='_' && s[2]=='C') {
                   27236:                                char* ss = new char[8]; // max size of generated name is 7 chars, see make_name()
                   27237:                                Pname obj = new name(ss);
                   27238:                                strcpy(ss,s);
                   27239:                                if (cl->csu == UNION) {
                   27240:                                        ss[2] = 'O';
                   27241:                                        cl->csu = ANON;
                   27242:                                        return obj->normalize(this,0,0);
                   27243:                                }
                   27244:                                error('w',"unusable%k ignored",cl->csu);
                   27245:                        }
                   27246:                        if ( b_sto == FRIEND )
                   27247:                                error("friend%k%n{...}",cl->csu,b_name);
                   27248:                        cl->c_body = 1;
                   27249:                        return b_name;
                   27250:                }
                   27251:                else {  /* really a typedef for cfront only: class x; */
                   27252:                        if (b_sto == FRIEND) goto frr;
                   27253:                        if (ansi_opt) printf("struct %s;\n",s);
                   27254:                        return 0;
                   27255:                }
                   27256:        }
                   27257: 
                   27258:        case EOBJ:
                   27259:        {       Penum en = Penum(b_name->tp);
                   27260:        /*SYM?*/if (b_name->base == TNAME) error('i',"TN%n in enumO",b_name);
                   27261:                if (b_const) error("const enum%n",b_name);
                   27262:                if (en->e_body == 2) {
                   27263:                        en->e_body = 1;
                   27264:                        return b_name;
                   27265:                }
                   27266:                else {
                   27267:                        error("forwardD of enum%n", b_name);
                   27268:                        en->e_type = int_type;
                   27269:                }
                   27270:                return 0;
                   27271:        }
                   27272: 
                   27273:        case 0:
                   27274:        {       Pname n = new name(make_name('D'));
                   27275:                n->tp = defa_type;
                   27276:                error("NX inDL");
                   27277:                return n;
                   27278:        }       
                   27279:        default:
                   27280:                if (b_typedef) error('w',"illegalTdef ignored");
                   27281: 
                   27282:                if (b_sto == FRIEND && b_name ) {
                   27283:                frr:
                   27284:                        Pname fr = ktbl->look(b_name->string,0); //SYM
                   27285:                        if (fr == 0) error('i',"cannot find friend%n",b_name);
                   27286:                        Pname n = new name(b_name->string);
                   27287:                        n->n_sto = FRIEND;
                   27288:                        // If it is a parameterized type, use the instantiation 
                   27289:                        // type, not the general type.
                   27290:                        if ((fr->tp->base == COBJ) && 
                   27291:                            (Pclass(Pbase(fr->tp)->b_name->tp)->class_base ==
                   27292:                                template_class))
                   27293:                        {
                   27294:                            if (base == COBJ) 
                   27295:                                n->tp = this;
                   27296:                            else 
                   27297:                            if ((base == TYPE) &&
                   27298:                                (Pbase(this)->b_name->base == TNAME) &&
                   27299:                                (Pbase(this)->b_name->tp->base == COBJ))
                   27300:                                        n->tp = Pbase(this)->b_name->tp;
                   27301:                            else 
                   27302:                                error('i', "basetype wasn't a COBJ");
                   27303:                        }
                   27304:                        else n->tp = fr->tp;
                   27305:                        return n;
                   27306:                }
                   27307:                else {
                   27308:                        Pname n = new name(make_name('D'));
                   27309:                        n->tp = defa_type;
                   27310:                        error('w',"NX inDL");
                   27311:                        return n;
                   27312:                }
                   27313:        }
                   27314: }
                   27315: 
                   27316: void local_name() //SYM -- to be removed
                   27317: { /* need to provide an additional temporary name
                   27318:    * to handle case of
                   27319:    * f() {
                   27320:    *    { class x{...}; }
                   27321:    *    { class x{...}; }
                   27322:    * }
                   27323:    * generate name after closing } of block
                   27324:    * to distinquish between separate blocks at same lexical level 
                   27325:    */
                   27326:        for (Plist l=local_blk; l; l=l->l) {
                   27327:                Pname n = l->f;
                   27328:                if ( n->tp == 0 ) error( 'i', "no tp yet: #0 local_name" );
                   27329:                if ( Pbase(n->tp)->b_name == 0 ) error( 'i', "no tp yet: #1 local_name" );
                   27330:                Pname bn = Pbase(n->tp)->b_name;
                   27331:                if ( bn->tp == 0 ) error( 'i', "no tp yet#2: local_name" );
                   27332:                Pclass cl = Pclass(bn->tp);
                   27333:                 cl->lcl = make_name( 'L' );
                   27334: // error( 'd', "local_name(): %n bn: %n: cl : %s nof: %d", n, bn, cl->string, cc->nof );
                   27335:         }
                   27336: }
                   27337: 
                   27338: void local_restore() //SYM -- to be removed
                   27339: {
                   27340:        for (Plist l=local_tn; l; l=l->l) {
                   27341:                Pname n = l->f;
                   27342: // error('d',"local_restore: n %n %t %d bl_level: %d", n, n->tp, n->lex_level, bl_level );
                   27343:                n->n_key = (n->lex_level==0) ? 0 
                   27344:                        : (n->lex_level && n->lex_level<=bl_level) ? LOCAL : HIDDEN;
                   27345:        }
                   27346: }
                   27347: 
                   27348: void local_hide( Pname n ) //SYM -- to be removed
                   27349: {
                   27350: // error('d',"local_hide(%n )",n);
                   27351: 
                   27352:    if ( n->base != TNAME ) return; 
                   27353:    if ( n->n_key == 0 ) {
                   27354:         local_tn = new name_list( n, local_tn );
                   27355:         n->n_key = HIDDEN;
                   27356: // error( 'd', "local_hide(): %n n_key: %d", n, n->n_key );
                   27357:    }
                   27358: }
                   27359: 
                   27360: void 
                   27361: nested_restore() //SYM -- to be removed
                   27362: {
                   27363:        for (Plist l = nested_type; l; l=l->l)
                   27364:        {
                   27365:                Pname n = l->f;
                   27366:                n->n_key = NESTED;
                   27367:        }
                   27368:                
                   27369:        for (l=nested_tn; l; l=l->l) {
                   27370:                Pname n = l->f;
                   27371:                Ptype tp = n->tp;
                   27372: // error('d',"nested_restore: n %n %t %d bl_level: %d", n, n->tp, n->lex_level, bl_level );
                   27373: // error('d'," --- n_key %k", n->n_key );
                   27374: 
                   27375:                if ( tp->in_class ) 
                   27376:                        n->n_key = NESTED;
                   27377:                else
                   27378:                if ( tp->lex_level )
                   27379:                        n->n_key = LOCAL;
                   27380:                else 
                   27381:                        n->n_key = 0;
                   27382: // error('d'," --- n_key %k", n->n_key );
                   27383:        }
                   27384: }
                   27385: 
                   27386: void 
                   27387: nested_hide( Pname n ) //SYM -- to be removed
                   27388: {
                   27389: // error('d',"nested_hide(%n )",n);
                   27390: 
                   27391:    if ( n->base != TNAME ) return; 
                   27392:    if ( n->n_key == 0 ) {
                   27393:         nested_tn = new name_list( n, nested_tn );
                   27394:         n->n_key = HIDDEN;
                   27395: // error( 'd', "nested_hide(): %n n_key: %d", n, n->n_key );
                   27396:    }
                   27397: }
                   27398: 
                   27399: static void 
                   27400: nested_hide( Plist l ) //SYM -- to be removed
                   27401: {
                   27402: // error('d',"nested_hide( list )");
                   27403: 
                   27404:        for (; l; l=l->l) {
                   27405:                Pname nn = l->f;
                   27406:                Pname n = ktbl->look(nn->string,0);
                   27407: // error('d',"nested_hide %n %t", n, n->tp, n->n_key);
                   27408:                if (n==0) continue;
                   27409: 
                   27410:                if ( n->base != TNAME ) 
                   27411:                        error('i', "nested_hide: %n not a type name (%t)", n, n->tp );
                   27412:                if ( n->n_key == 0 ) {
                   27413:                        nested_tn = new name_list( n, nested_tn );
                   27414:                        n->n_key = HIDDEN;
                   27415: // error( 'd', "nested_hide(list): %n n_key: %d", n, n->n_key );
                   27416: //             nn->n_key = 0;
                   27417:                }
                   27418:        }
                   27419: }
                   27420: 
                   27421: int defer_check = 0;
                   27422: Pname statStat = 0;
                   27423: 
                   27424: void name::hide()
                   27425: /*
                   27426:        hide "this": that is, "this" should not be a keyword in this scope
                   27427: */
                   27428: {
                   27429:        if (base != TNAME) return;
                   27430: // error('d',"'%n '->hide() -- %t lex_level %d bl_level %d",this,tp,lex_level,::bl_level);
                   27431:        if (n_key == 0) {
                   27432:                 if (lex_level == bl_level && in_arg_list == 0) {
                   27433:                        if (tp->base != COBJ) { 
                   27434:                                if ( !in_typedef ) 
                   27435:                                     error("%n redefined: typedef and identifier", this);
                   27436:                                else if ( in_typedef->base 
                   27437:                                                && tp->base != type_set(Pbase(in_typedef)) 
                   27438:                                                && in_typedef->check(tp,0) ) {
                   27439:                                                        if ( defer_check == 0 )
                   27440:                                                                error("%n redefined: previous: %t now: %t", this, tp, in_typedef);
                   27441:                                } 
                   27442:                        } 
                   27443:                        else {
                   27444: //error('d',"in_typedef%t %d tp%t %d",in_typedef,in_typedef,tp,tp);
                   27445: //error('d',"in_typedef%k tp%k",in_typedef->base,tp->base);
                   27446:                                if ( in_typedef && in_typedef->base
                   27447:                                &&   in_typedef->check(tp, 0) ) {
                   27448:                                        if ( defer_check == 0 )
                   27449:                                                error( "%n redefined: previous: %t now: %t", this, tp, in_typedef);
                   27450:                                }
                   27451:                                else {
                   27452:                                        Pname nn = Pbase(tp)->b_name;
                   27453:                                        Pclass cl = Pclass( nn->tp );
                   27454:                                        // check for 'typedef class X X;'
                   27455:                                        //       and 'typedef X X;'
                   27456:                                        if ( in_typedef )
                   27457:                                            while ( in_typedef->base == TYPE )
                   27458:                                                in_typedef = Pbase(in_typedef)->b_name->tp;
                   27459:                                        if ( in_typedef
                   27460:                                        &&   in_typedef->base==COBJ
                   27461:                                        &&   Pbase(in_typedef)->b_name->tp==cl )
                   27462:                                                in_typedef = tp;
                   27463:                                        else if ( cl->has_ctor() )
                   27464:                                                error( "%n redefined: both aCNWK and %s", this, in_typedef?"a type name":"an identifier" );
                   27465:                                }
                   27466:                        }
                   27467: 
                   27468:                 }
                   27469: // error( 'd', "%n::hide", this );
                   27470:                modified_tn = new name_list(this,modified_tn);
                   27471:                n_key = HIDDEN;
                   27472:        }
                   27473: }
                   27474: 
                   27475: static Pname Ntncheck; // ensure TNAMES hidden within class scopes
                   27476: static int notReally = 0;
                   27477: 
                   27478: void set_scope(Pname tn) //SYM -- to be shrunk
                   27479: /* enter the scope of class tn after seeing "tn::f" */
                   27480: {
                   27481: // error( 'd', "set_scope: %n %t %d", tn, tn->tp, tn->tp->base );
                   27482: // error( 'd', "set_scope: %d", notReally );
                   27483: 
                   27484:        Pbase b = Pbase(tn->tp);
                   27485:        while ( b->base == TYPE )  b=Pbase(b->b_name->tp);  // typedef class X T
                   27486:        if (b->base != COBJ) return; // error caught elsewhere
                   27487: 
                   27488:        Pclass cl = Pclass(b->b_name->tp);
                   27489:        char *str = cl->string;
                   27490: 
                   27491:        if ( cl->nest_list && notReally == 0 ) { 
                   27492:                nested_type = cl->nest_list; 
                   27493:                nested_hide(cl->nest_list); 
                   27494:        }
                   27495: 
                   27496:        Pname ntn = Ntncheck;
                   27497:        if( notReally == 0 )
                   27498:            while ( ntn && ntn->tp->base == TYPE ) ntn = Pbase(ntn->tp)->b_name;
                   27499: 
                   27500:        if ( notReally || ntn == 0 || strcmp( str,ntn->string )) {
                   27501:                if ( cl->baselist ) {
                   27502:                    Pname nb = new name, nbc = new name;
                   27503:                    nb->tp = new basetype(COBJ,0);
                   27504:                    Pbase(nb->tp)->b_name = nbc;
                   27505:                    for (Pbcl bx, bb=cl->baselist;  bb;  bb = bb->next) {
                   27506:                        bx = bb->next;
                   27507:                        if ( bb->bclass != 0 ) {
                   27508:                                nbc->tp = bb->bclass;
                   27509:                                notReally++; set_scope(nb); notReally--;
                   27510:                        }
                   27511:                    }
                   27512:                    DEL(nbc); /*DEL(nb->tp);*/ DEL(nb);
                   27513:                }
                   27514: 
                   27515:                int i = 1;
                   27516:                Pname n = 0;
                   27517:                Plist ll = 0;
                   27518:                if (b->parametrized_class()) {
                   27519:                  for (Pname nn = cl->mem_list; nn; nn = nn->n_list)
                   27520:                    switch (nn->base) {
                   27521:                    case PUBLIC: case PRIVATE: case PROTECTED:
                   27522:                        continue;
                   27523:                    default:
                   27524:                        if (nn->tp->base == CLASS) continue;
                   27525:                        if (nn->tp->base == ENUM) continue;
                   27526:                        if ((nn->base == NAME) &&
                   27527:                            ((nn->n_oper == TNAME) && (nn->tp->base == FCT)) ||
                   27528:                            (nn->n_oper == CTOR) ||
                   27529:                            (nn->n_oper == DTOR)) continue ;
                   27530:                        n = ktbl->look( nn->string, 0 );
                   27531:                        if (n) ll = new name_list( n, ll );
                   27532:                    }
                   27533:                } // if b->parametrized_class()
                   27534:                else
                   27535:                for (Pname nn=cl->memtbl->get_mem(i); nn; nn=cl->memtbl->get_mem(++i) ) {
                   27536:                        if (nn->base == TNAME || nn->base == PUBLIC) continue;
                   27537:                        if (nn->tp->base == CLASS) continue;
                   27538:                        if (nn->tp->base == ENUM) continue;
                   27539:                        n = ktbl->look( nn->string, 0 );
                   27540:                        if (n) ll = new name_list( n, ll );
                   27541:                }
                   27542: 
                   27543:                if ( ll ) cl->tn_list = ll;
                   27544:                if (notReally == 0) Ntncheck = tn; 
                   27545:        }
                   27546:        
                   27547:        for (Plist l=cl->tn_list; l; l=l->l) {
                   27548:                Pname n = l->f;
                   27549:                n->n_key = (n->lex_level) ? 0 : HIDDEN;
                   27550:                modified_tn = new name_list(n,modified_tn);
                   27551:        }
                   27552: }
                   27553: 
                   27554: void restore() //SYM -- to be removed
                   27555: {
                   27556:        for (Plist l=modified_tn; l; l=l->l) {
                   27557:                Pname n = l->f;
                   27558: // error('d',"restore: n %n %t %d bl_level: %d", n, n->tp, n->lex_level, bl_level );
                   27559: //fprintf(stderr," -- n_key %d\n",n->n_key);
                   27560:                n->n_key = (n->lex_level==0 || (n->lex_level && n->lex_level<=bl_level)) ? 0 : HIDDEN;
                   27561: //fprintf(stderr," -- n_key %d\n",n->n_key);
                   27562:                if ( n->lex_level == 0 
                   27563:                        && (n->tp->base == COBJ || n->tp->base == EOBJ)) {
                   27564:                        Pname nn = gtbl->look( n->string, 0 );
                   27565:                        if ( nn ) n->n_key = HIDDEN;
                   27566:                }
                   27567: //fprintf(stderr," -- n_key %d\n",n->n_key);
                   27568:        }
                   27569: }
                   27570: 
                   27571: Pbase start_cl(TOK t, Pname c, Pbcl b)
                   27572: {
                   27573:         int mk_local = 0;
                   27574:        DB(if(Ndebug>=1)error('d',"start_cl(%k,%d,%d)",t,c,b););
                   27575:        if (c == 0) {
                   27576:            c = new name(make_name('C'));
                   27577:            c->lex_level -= in_class_decl + 1;
                   27578:            if ( in_typedef && c->lex_level ) 
                   27579:                 mk_local = 1;
                   27580:            else c->lex_level = 0;
                   27581:        }
                   27582: 
                   27583:        for ( Pclass tc = ccl; tc; tc = tc->in_class ) {
                   27584:            if ( tc->lex_level == c->lex_level // c not local to mem ftn of tc
                   27585:            &&   strcmp( tc->string, c->string) == 0) {
                   27586:                error( "C %s redefined", c->string );
                   27587:                error('i', "can't recover from previous errors");
                   27588:             }
                   27589:        }
                   27590: 
                   27591:        Pname n = c->tname(t);                  /* t ignored */
                   27592: 
                   27593:         if (templp->in_progress && (c->lex_level == 0))
                   27594:         // bring the template in scope
                   27595:                templp->introduce_class_templ(n);
                   27596: 
                   27597: // typedef struct {} x;
                   27598:        if ( mk_local ) {
                   27599:            n->n_key  = LOCAL;
                   27600:            extern Plist local_blk, local_class; // place in cfront.h
                   27601:            local_class = new name_list( n, local_class );
                   27602:            local_blk = new name_list( n, local_blk );
                   27603:            modified_tn = modified_tn->l;
                   27604:        }
                   27605: 
                   27606:        n->where = curloc;
                   27607:        Pbase bt = Pbase(n->tp);                /* COBJ */
                   27608:        if (bt->base != COBJ) {
                   27609:                error("twoDs of%n:%t andC",n,bt);
                   27610:                error('i', "can't recover from previous errors");
                   27611:        }
                   27612: 
                   27613:        Pclass occl = ccl;
                   27614:        ccl = Pclass(bt->b_name->tp);           /* CLASS */
                   27615:        if (ccl->defined) ccl->defined |= IN_ERROR;
                   27616:        ccl->defined |= DEF_SEEN;
                   27617: 
                   27618: // error('d', "start_cl: %n ccl->in_class: %t lex_level: %d", n, ccl->in_class, n->lex_level );
                   27619: 
                   27620:        if (ccl->in_class = occl) {
                   27621:                occl->tn_list = modified_tn;    // save  mod-list
                   27622:                modified_tn = 0;
                   27623:        }
                   27624:        
                   27625:        Ntncheck = 0;  // zero it out with each new class declaration
                   27626:        ccl->string = n->string;
                   27627:        ccl->csu = t;
                   27628: 
                   27629:        if (b) {        // list of base classes
                   27630:                for (Pbcl bx, bb=b, l=0; bb; bb = bx) {
                   27631:                        bx = bb->next;
                   27632:                        bb->next = 0;
                   27633: 
                   27634:                        if ( bb->bclass
                   27635:                        &&   strcmp(ccl->string,bb->bclass->string)==0 )
                   27636:                                error(&n->where,"%nderived from itself",n);
                   27637:                        else if (l == 0)
                   27638:                                l = bb;
                   27639:                        else {  // append and check for duplicates
                   27640:                                for (Pbcl ll = l;;) {
                   27641:                                         if (bb->bclass && ll->bclass==bb->bclass) {
                   27642:                                                error("%s has %s asB twice",ccl->string,bb->bclass->string);
                   27643:                                                break;
                   27644:                                        }
                   27645: 
                   27646:                                        if (ll->next)
                   27647:                                                ll = ll->next;
                   27648:                                        else {
                   27649:                                                bb->next = l;
                   27650:                                                l = bb;
                   27651:                                                break;
                   27652:                                        }
                   27653:                                }
                   27654:                        }
                   27655:                }
                   27656: 
                   27657:                ccl->baselist = l;
                   27658:                notReally++; set_scope(n); notReally--;
                   27659:        }
                   27660:        return bt;      
                   27661: }
                   27662: 
                   27663: void end_cl()
                   27664: {
                   27665:        Pclass occl = ccl->in_class;
                   27666:        Plist ol = occl ? occl->tn_list : 0;    // saved modified name list
                   27667:        ccl->c_body = 2;
                   27668: 
                   27669:        if (modified_tn) {      // export nested class names to outer scope:
                   27670:                Plist local = 0;
                   27671:                for (Plist l=modified_tn, nl=0; l; l=nl) {
                   27672:                        nl = l->l;
                   27673:                        Pname n = l->f;
                   27674: 
                   27675:                        // in a pure implementation, no longer do this
                   27676:                        if (ktbl->look(n->string,0)) {
                   27677:                                // add it to enclosing class's modified name list
                   27678:                                l->l = ol;
                   27679:                                ol = l;
                   27680:                        }
                   27681:                        else {  // retain it in this class's modified name list
                   27682:                                l->l = local;
                   27683:                                local = l;
                   27684:                        }
                   27685:                }
                   27686:                if (ccl->tn_list = modified_tn = local) restore();
                   27687:        }
                   27688:        modified_tn = ol;       // restore mod-list (possibly modified)
                   27689: /*
                   27690: if ( occl ) {
                   27691: Pname n = ktbl->look(ccl->string,NESTED);
                   27692: for (;n; n=n->n_tbl_list) {
                   27693: Ptype tt = Pbase(n->tp)->b_name->tp;
                   27694: // error('d',"end_cl: ccl: %t occl: %t in_class: %t", ccl, occl, tt->in_class);
                   27695: if (strcmp(tt->in_class->string, occl->string) == 0) {
                   27696:        n->n_key = 0;
                   27697:        }
                   27698: } 
                   27699: }
                   27700: */
                   27701:        ccl = occl;
                   27702: }
                   27703: 
                   27704: Pbase end_enum(Pname n, nlist* b)
                   27705: {
                   27706: // error( 'd', "end_enum: %n ccl: %t", n , ccl ); 
                   27707:        if (n == 0) n = new name(make_name('E'));
                   27708:        n = n->tname(ENUM);
                   27709:        Pbase bt = (Pbase)n->tp;
                   27710:        if (bt->base != EOBJ) {
                   27711:                error("twoDs of%n:%t and enum",n,bt);
                   27712:                error('i', "can't recover from previous errors");
                   27713:        }
                   27714:        Penum en = (Penum)bt->b_name->tp;
                   27715:        en->e_body = 2;
                   27716:        en->mem = name_unlist(b);
                   27717:        if (en->defined) {
                   27718:                // shouldn't be necessary anymore with nested types
                   27719:                // if ( in_class_decl )
                   27720:                //      error("%n redefined, enum tag not local to class", n);
                   27721:                en->defined |= IN_ERROR;
                   27722:         }
                   27723:        en->defined |= DEF_SEEN;
                   27724:        en->in_class = ccl;
                   27725:        if (ccl && (bl_level==ccl->lex_level + in_class_decl) && is_anon(n->string))
                   27726:                n=do_nested_type(n);
                   27727:        return bt;
                   27728: }
                   27729: 
                   27730: extern Ptype return_nstd_local_type(Pname,TOK&);
                   27731: Pname name::tdef()
                   27732: /*
                   27733:        typedef "this"
                   27734: */
                   27735: {
                   27736:        DB(if(Ndebug>=1) {
                   27737:           error('d',&where,"'%n'->tdef()%t in_typedef %d",this,tp,in_typedef);
                   27738:           error('d',&where,"   lex_level %d tpdef%t",lex_level,tpdef);
                   27739:        });
                   27740:         int anon_cl = 0;
                   27741:         if (n_qualifier) {
                   27742:                 error("QdN in typedef",this);
                   27743:                 n_qualifier = 0;
                   27744:         }
                   27745: 
                   27746:        Pname n;
                   27747:        if ( tpdef && tpdef->in_class ) { // nested typedef
                   27748: // error('d', "*****%s->tdef: %d ccl: %t", string, tpdef, ccl );
                   27749:                n = ktbl->insert(this,NESTED);
                   27750:                n->tpdef = tpdef;
                   27751:                n->tpdef->lex_level = n->lex_level = 0;
                   27752:                nested_type = new name_list( n, nested_type );
                   27753:        }
                   27754:        else {
                   27755:                Pname nn = ktbl->look(string,NESTED);
                   27756:                if ( nn ) {
                   27757:                        TOK ntk = 0; // set by return_nstd...
                   27758:                        Ptype tt = return_nstd_local_type(nn,ntk);
                   27759:                        error("nested%k%t::%s seen beforeGTdef %s (to do this placeG definition first)",ntk, tt->in_class, string, string);
                   27760:                        error( 'i', "cannot recover from previous errors" );
                   27761:                }
                   27762:                lex_level = bl_level - in_class_decl;
                   27763:                n = ktbl->insert(this,0);
                   27764:        }
                   27765: 
                   27766:        if (tp == 0) error('i',"Tdef%n tp==0",this);
                   27767:        n->base = base = TNAME;
                   27768:        PERM(n);
                   27769:        PERM(tp);
                   27770: 
                   27771:        if (tp->base == COBJ || tp->base == EOBJ ) 
                   27772:        {       // typedef struct/enum { } s; => struct/enum s {};
                   27773:                Pname b = Pbase(tp)->b_name;
                   27774:                if (b->string[0] == '_' && b->string[1] == '_' ) 
                   27775:                        switch ( tp->base ) {
                   27776:                                case COBJ: {
                   27777:                                        if (b->string[2] == 'C') {
                   27778:                                                Pclass cl = Pclass(b->tp);
                   27779:                                                b->string = n->string;
                   27780:                                                cl->string = n->string;
                   27781:                                                cl->strlen = strlen(cl->string);
                   27782:                                                if ( lex_level ) {
                   27783:                                                        anon_cl = 1;
                   27784:                                                        n->n_key = LOCAL;
                   27785:                                                }
                   27786:                                        }
                   27787:                                        break;
                   27788:                                }
                   27789:                                case EOBJ: {
                   27790:                                        if (b->string[2] == 'E') {
                   27791:                                                Penum en = Penum(b->tp);
                   27792:                                                b->string = n->string;
                   27793:                                                en->string = n->string;
                   27794:                                                en->strlen = strlen(en->string);
                   27795:                                        }       
                   27796:                                }
                   27797:                        }
                   27798:        }
                   27799: 
                   27800:        if ( anon_cl == 0 )
                   27801:                modified_tn = new name_list(n,modified_tn);
                   27802:        DB(if(Ndebug>=1) {
                   27803:           error('d',&where,">>'%n'->tdef()%t returning",this,tp);
                   27804:           error('d',&where,"   lex_level %d tpdef%t",lex_level,tpdef);
                   27805:        });
                   27806:        return n;
                   27807: }
                   27808: 
                   27809: Pname name::tname(TOK csu)
                   27810: /*
                   27811:        "csu" "this" seen, return typedef'd name for "this"
                   27812:        return  (TNAME,x)
                   27813:        x:      (COBJ,y)
                   27814:        y:      (NAME,z)
                   27815:        z:      (CLASS,ae);
                   27816: */
                   27817: {
                   27818: //error('d',"'%n'::tname(%k)",this,csu);
                   27819:        switch (base) {
                   27820:        case TNAME:
                   27821:                return this;
                   27822:        case NAME:
                   27823:        {       Pname tn = ktbl->insert(this,0);
                   27824:                Pname on = new name;
                   27825:                tn->base = TNAME;
                   27826:                tn->lex_level = lex_level;
                   27827:                modified_tn = new name_list(tn,modified_tn);
                   27828:                tn->n_list = n_list = 0;
                   27829:                string = tn->string;
                   27830:                *on = *this;
                   27831:                switch (csu) {
                   27832:                case ENUM:
                   27833:                        tn->tp = new basetype(EOBJ,on);
                   27834:                        on->tp = new enumdef(0);
                   27835:                        Penum(on->tp)->string = tn->string;
                   27836:                        break;
                   27837:                case CLASS:
                   27838:                case STRUCT:
                   27839:                case UNION:
                   27840:                        on->tp =  new classdef(csu);
                   27841:                        Pclass(on->tp)->string = tn->string;
                   27842:                        Pclass(on->tp)->lex_level = lex_level;
                   27843:                        tn->tp = new basetype(COBJ,on);
                   27844:                        Pbase(tn->tp)->b_table = Pclass(on->tp)->memtbl;
                   27845:                        break;
                   27846:                default:
                   27847:                        error('i',&where,"illegal csu%k for%n in name::tname()",csu,this);
                   27848:                }
                   27849:                PERM(tn);
                   27850:                PERM(tn->tp);
                   27851:                PERM(on);
                   27852:                PERM(on->tp);
                   27853:                return tn;
                   27854:        }
                   27855:        default:
                   27856:                error('i',"tname(%s %d %k)",string,this,base);
                   27857:        } 
                   27858: }
                   27859: 
                   27860: int co_hack;
                   27861: Pname name::normalize(Pbase b, Pblock bl, bit Cast)
                   27862: /*
                   27863:        if (bl) : a function definition (check that it really is a type
                   27864: 
                   27865:        if (Cast) : no name string
                   27866: 
                   27867:        for each name on the name list
                   27868:        invert the declarator list(s) and attatch basetype
                   27869:        watch out for class object initializers
                   27870: 
                   27871:        convert
                   27872:                struct s { int a; } a;
                   27873:        into
                   27874:                struct s { int a; }; struct s a;
                   27875: */
                   27876: {
                   27877:        Pname n;
                   27878:        Pname nn;
                   27879:        TOK stc;
                   27880:        bit tpdf;
                   27881:        bit inli;
                   27882:        bit virt;
                   27883:        char * lnkg;
                   27884:        DB( if(Ndebug>=1) {
                   27885:            error('d',"'%n'::normalize(b%t, bl %d, cast %d)",this,b,bl,Cast);
                   27886:            error('d',"    tp%k - lex_level %d - bl_level %d",tp?tp->base:0,lex_level,bl_level);
                   27887:        });
                   27888:        if (b) {
                   27889:                stc = b->b_sto;
                   27890:                tpdf = b->b_typedef;
                   27891:                inli = b->b_inline;
                   27892:                virt = b->b_virtual;
                   27893:                lnkg = b->b_linkage;
                   27894:        }
                   27895:        else {
                   27896:                stc = 0;
                   27897:                tpdf = 0;
                   27898:                inli = 0;
                   27899:                virt = 0;
                   27900:                lnkg = 0;
                   27901:        }
                   27902: 
                   27903:        if (inli && stc==EXTERN)  {
                   27904:                error("both extern and inline");
                   27905:                inli = 0;
                   27906:        }
                   27907: 
                   27908:        if ( stc==STATIC && tp && 
                   27909:                tp->base == FCT 
                   27910:                && Pfct(tp)->f_const ) 
                   27911:                        error( "%n staticMF cannot be const", this ); 
                   27912: 
                   27913:        if (stc==FRIEND && tp==0) {
                   27914:                /*      friend x;
                   27915:                        must be handled during syntax analysis to cope with
                   27916:                                class x { friend y; y* p; };
                   27917:                        "y" is not local to "x":
                   27918:                                class x { friend y; ... }; y* p;
                   27919:                        is legal
                   27920: 
                   27921:                        examples:
                   27922:                                
                   27923:                                typedef void    SIG_TYP(int);
                   27924:                                class x {
                   27925:                                        friend class y;
                   27926:                                        friend z;
                   27927:                                        friend x;               // dumb
                   27928:                                        friend int i;           // error
                   27929:                                        friend SIG_TYP sigFunc; // subtle
                   27930:                                        friend int f();
                   27931:                                        friend g(int);
                   27932:                                };
                   27933:                */
                   27934:                if (b && (b->base || b->b_name || b->b_xname)) goto ccc;
                   27935: 
                   27936:                if (n_list) {
                   27937:                        error("L of friends");
                   27938:                        n_list = 0;
                   27939:                }
                   27940: 
                   27941:                if (!Cast) {
                   27942:                        Pname nn = gtbl->look( string, 0 );
                   27943:                        if ( nn ) {
                   27944:                                if (nn->tp->base == FCT) 
                   27945:                                        error("friendF must include signature:%n", this ); 
                   27946:                                else
                   27947:                                        error("illegal friendD:%n", this );
                   27948:                        }
                   27949:                }
                   27950: 
                   27951: //error( 'd', "%n ll: %d", ccl, ccl->lex_level );
                   27952:                lex_level = ccl->lex_level;
                   27953:                Pname nx = tname(CLASS);
                   27954:                modified_tn = modified_tn->l;   /* global */
                   27955:                n_sto = FRIEND;
                   27956:                tp = nx->tp;
                   27957:                return this;
                   27958:        }
                   27959: ccc:
                   27960:        if (tp                          // FUDGE: fix the bad grammar
                   27961:        && tp->base==FCT
                   27962:        && (n_oper==TNAME || Pfct(tp)->returns)) {
                   27963:                Pfct f = Pfct(tp);
                   27964:                Pfct f2 = Pfct(f->returns);
                   27965: 
                   27966:                if (f2) {
                   27967:                        Ptype pt;
                   27968:                        Ptype t = f2;
                   27969:                lxlx:
                   27970:                        switch (t->base) {
                   27971:                        case PTR:       // x(* p)(args) ?
                   27972:                        case VEC:       // x(* p[10])(args) ?
                   27973:                                if (pt = Pptr(t)->typ) {
                   27974:                                        if (pt->base == TYPE) {
                   27975:                                                Pptr(t)->typ = 0;
                   27976:                                                b = Pbase(pt);
                   27977:                                        //      stc = b->b_sto;
                   27978:                                        //      tpdf = b->b_typedef;
                   27979:                                        //      inli = b->b_inline;
                   27980:                                        //      virt = b->b_virtual;
                   27981:                                        }
                   27982:                                        else {
                   27983:                                                t = pt;
                   27984:                                                goto lxlx;
                   27985:                                        }
                   27986:                                }
                   27987:                                goto zse1;
                   27988:                        case FCT:
                   27989:                        {//     Pexpr e = f2->argtype;
                   27990:                                Pexpr e = Pfct(f)->argtype;
                   27991:                                if  (e && e->base==ELIST) { // get the real name; fix its type
                   27992:                                        if (e->e2 || e->e1->base!=DEREF) goto zse1;
                   27993:                                        Pexpr ee = e->e1;
                   27994:                                        Ptype t = 0;
                   27995:                                        Ptype tpx;
                   27996:                                ldld:
                   27997:                                        switch (ee->base) {
                   27998:                                        case DEREF:
                   27999:                                        {       Ptype tt = (ee->e2) ? Ptype(new vec(0,ee->e2)) : Ptype (new ptr(PTR,0));
                   28000:                                                if (t)
                   28001:                                                        Pptr(t)->typ = tt;
                   28002:                                                else
                   28003:                                                        tpx = tt;
                   28004:                                                t = tt;
                   28005:                                                ee = ee->e1;
                   28006:                                                goto ldld;
                   28007:                                        }
                   28008:                                        case NAME:
                   28009:                                        {       Pname rn = Pname(ee);
                   28010:                                                b = new basetype(TYPE,ktbl->look(string,0));
                   28011:                                                f->returns = tpx;
                   28012:                                                n_oper = 0;
                   28013:                                                string = rn->string;
                   28014:                                                base = NAME;
                   28015:                                        }
                   28016:                                        }
                   28017:                                }
                   28018:                        }
                   28019:                        }
                   28020:                }
                   28021:        }
                   28022: 
                   28023: zse1:
                   28024:        if (b == 0) {
                   28025:                error("BTX for %s",string);
                   28026:                b = Pbase(defa_type);
                   28027:        }
                   28028:        
                   28029:        if (Cast) string = "";
                   28030:        b = b->check(this);
                   28031: 
                   28032:        switch (b->base) {      //      separate class definitions
                   28033:                                //      from object and function type declarations
                   28034:        case COBJ:
                   28035:                nn = b->b_name;
                   28036:                if (Pclass(nn->tp)->c_body==2) {        /* first occurrence */
                   28037:                        if ( stc == FRIEND ) {
                   28038:                            Pclass cl = Pclass(nn->tp);
                   28039:                            if ( cl->csu == ANON )
                   28040:                                error( &nn->where, "friend anonymous union");
                   28041:                            else
                   28042:                                error( &nn->where, "%k%n defined in friendD",cl->csu,nn);
                   28043:                        }
                   28044:                        if (tp && tp->base==FCT && co_hack == 0) {
                   28045:                                error(&this->where,"%k%n defined as returnT for%n (did you forget a ';' after '}' ?)",Pclass(nn->tp)->csu,nn,this);
                   28046:                                nn = this;
                   28047:                                break;
                   28048:                        }
                   28049:                        nn->n_list = this;
                   28050:                        Pclass(nn->tp)->c_body = 1;     /* other occurences */
                   28051:                }
                   28052:                else
                   28053:                        nn = this;
                   28054:                break;
                   28055:        case EOBJ:
                   28056:                nn = b->b_name;
                   28057:                if (Penum(nn->tp)->e_body==2) {
                   28058:                        if (tp && tp->base==FCT) {
                   28059:                                error(&this->where,"enum%n defined as returnT for%n (did you forget a ';'?)",nn,this);
                   28060:                                nn = this;
                   28061:                                break;
                   28062:                        }
                   28063:                        nn->n_list = this;
                   28064:                        Penum(nn->tp)->e_body = 1;
                   28065:                }
                   28066:                else {
                   28067:                        Penum en = Penum(nn->tp);
                   28068:                        if ( en->defined == 0 ) 
                   28069:                                error( "forwardD of enum%n", nn );
                   28070:                        en->e_type = int_type; 
                   28071:                        nn = this;
                   28072:                }
                   28073:                break;
                   28074:        default:
                   28075:                nn = this;
                   28076:        }
                   28077: 
                   28078: //error('d',&where,"name::normalize: nn%n ll %d   nn %d this %d",nn,nn->lex_level,nn,this);
                   28079:        Pname nx; 
                   28080:        for (n=this; n; n=nx) {
                   28081:                Ptype t = n->tp;
                   28082:                nx = n->n_list;
                   28083:                n->n_sto = stc;
                   28084: 
                   28085:                if (n->base == TNAME) error('i',"redefinition ofTN%n",n);
                   28086: 
                   28087:                if (t == 0) {
                   28088:                        if (bl == 0)
                   28089:                                n->tp = t = b;
                   28090:                        else {
                   28091:                                if ( n->base == NAME && n->n_oper )
                   28092:                                        error(&n->where,"illegalD of %n",n);
                   28093:                                else
                   28094:                                        error(&n->where,"body of nonF%n",n);
                   28095:                                t = new fct(0,0,0);
                   28096:                        }
                   28097:                }
                   28098: 
                   28099:                switch (t->base) {
                   28100:                case PTR:
                   28101:                case RPTR:
                   28102:                        n->tp = Pptr(t)->normalize(b);
                   28103:                        break;
                   28104:                case VEC:
                   28105:                        n->tp = Pvec(t)->normalize(b);
                   28106:                        break;
                   28107:                case FCT:
                   28108:                        n->tp = Pfct(t)->normalize(b);
                   28109:                        break;
                   28110:                case FIELD:
                   28111:                        if (n->string == 0) n->string = make_name('F');
                   28112:                        n->tp = t;
                   28113:                        Pbase tb = b;
                   28114: // error('d', "field t %k tb %k", t->base, tb->base );
                   28115:                flatten:
                   28116:                        switch (tb->base) {
                   28117:                        case TYPE:   /* chase typedefs */
                   28118:                                tb = (Pbase)tb->b_name->tp;
                   28119:                                goto flatten;
                   28120:                        case CHAR:
                   28121:                        case SHORT:
                   28122:                        case EOBJ:
                   28123:                        case INT:
                   28124: //  typedef const unsigned cu_int;
                   28125: //     struct x { x(); cu_int b1: 2; }
                   28126: 
                   28127:                                Pbase(t)->b_fieldtype = (b->b_unsigned||tb->b_unsigned) ? uint_type : int_type;
                   28128:                //              goto iii;
                   28129:                //      case CHAR:
                   28130:                //              Pbase(t)->b_fieldtype = (b->b_unsigned) ? uchar_type : char_type;
                   28131:                //              goto iii;
                   28132:                //      case SHORT:
                   28133:                //              Pbase(t)->b_fieldtype = (b->b_unsigned) ? ushort_type : short_type;
                   28134:                //              goto iii;
                   28135:                //      iii:
                   28136:                                Pbase(t)->b_unsigned = b->b_unsigned?b->b_unsigned:tb->b_unsigned;
                   28137:                                Pbase(t)->b_const = b->b_const?b->b_const:tb->b_const;
                   28138:                                break;
                   28139:                        default:
                   28140:                                error("non-int field");
                   28141:                                n->tp = defa_type;
                   28142:                        }
                   28143:                        break;
                   28144:                }
                   28145: 
                   28146:                Pfct f = Pfct(n->tp);
                   28147: 
                   28148:                if (f->base != FCT) {
                   28149:                        if (bl) {
                   28150:                                error("body for nonF%n",n);
                   28151:                                n->tp = f = new fct(defa_type,0,0);
                   28152:                                continue;
                   28153:                        }
                   28154:                        if (inli) error("inline nonF%n",n);
                   28155:                        if (virt) error("virtual nonF%n",n);
                   28156:                                
                   28157:                        if (tpdf) {
                   28158: // error('d', "%n->normalize: ccl: %t", this, ccl );
                   28159:                                if (ccl && n->tpdef &&
                   28160:                                        (n->tpdef->lex_level == NESTED ||
                   28161:                                                n->tpdef->lex_level == LOCAL))
                   28162:                                        ; // using this field for nested/local type info
                   28163:                                else
                   28164:                                if (n->n_initializer) {
                   28165:                                        error("Ir forTdefN%n",n);
                   28166:                                        n->n_initializer = 0;
                   28167:                                }
                   28168:                                n->tdef();
                   28169:                                // because do_nested_type can't call tdef()
                   28170:                                if ( n->n_key == NESTED )
                   28171:                                        modified_tn = modified_tn->l;
                   28172:                        }
                   28173:                        continue;
                   28174:                }
                   28175: 
                   28176:                if ( lnkg ) set_linkage(lnkg);
                   28177:                f->f_linkage = linkage;
                   28178:                if ( lnkg ) set_linkage(0);
                   28179:                // wait and call f->sign() after args are checked
                   28180: 
                   28181:                f->f_inline = inli;
                   28182:                extern int vcounter;
                   28183:                 f->f_virtual = virt?(vcounter++,VTOK):0;
                   28184: 
                   28185:                if (tpdf) {
                   28186:                        if (f->body = bl) error("Tdef%n { ... }",n);
                   28187:                        if (n->n_qualifier) {
                   28188:                                // typedef T x::f(args);
                   28189:                                // a pointer to member fucntion:
                   28190:                                // equivalent to typedef T x::(f)(args);
                   28191:                                f->memof = Pclass(Pbase(n->n_qualifier->tp)->b_name->tp);
                   28192:                                n->n_qualifier = 0;
                   28193:                        }
                   28194:                        n->tdef();
                   28195:                        // because do_nested_type can't call tdef()
                   28196:                        if ( n->n_key == NESTED )
                   28197:                                modified_tn = modified_tn->l;
                   28198:                        continue;
                   28199:                }
                   28200: 
                   28201:                if (f->body = bl) continue;
                   28202: 
                   28203:                /*
                   28204:                        Check function declarations.
                   28205:                        Look for class object instantiations
                   28206:                        The real ambiguity:             ; class x fo();
                   28207:                                is interpreted as an extern function
                   28208:                                declaration NOT a class object with an
                   28209:                                empty initializer
                   28210:                */
                   28211:                {       Pname cn = f->returns->is_cl_obj();
                   28212:                         Ptype template_formal_type ;
                   28213:                        bit clob = (cn || cl_obj_vec);
                   28214: 
                   28215:                        if (f->argtype) { /* check argument/initializer list */
                   28216:                                Pname nn;
                   28217: 
                   28218:                                for (nn=f->argtype; nn; nn=nn->n_list) {
                   28219:                                        if (nn->base != NAME) {
                   28220:                                                if (!clob) {
                   28221:                                                        if ((f->returns->base == TYPE) &&
                   28222:                                                            (Pbase(f->returns)->b_name->n_template_arg == template_type_formal))                                    
                   28223:                                                 {
                   28224:                                                 // T x(var); wher T is a template formal
                   28225:                                                 // it could be a class when instantiated
                   28226:                                                 // wait until then to issue error message
                   28227:                                                                template_formal_type = f->returns;
                   28228:                                                                Pname nnn = Pbase(f->returns)->b_name;
                   28229:                                                                        nnn->n_template_formal_must_be_class = 1;
                   28230:                                                                goto is_obj;
                   28231:                                                         }
                   28232:                                                        error(&n->where,"ATX for%n",n);
                   28233:                                                        goto zzz;
                   28234:                                                }
                   28235:                                                goto is_obj;
                   28236:                                        }
                   28237:                                        //if (nn->string) {
                   28238:                                        //      error("AN%n inD of%n",nn,n);
                   28239:                                        //      nn->string = 0;
                   28240:                                        //}
                   28241:                                        if (nn->tp) goto ok;
                   28242:                                }
                   28243:                                if (!clob) {
                   28244:                                        error("FALX");
                   28245:                                        goto zzz;
                   28246:                                }
                   28247:                is_obj:
                   28248:                                /* it was an initializer: expand to constructor */
                   28249:                                n->tp = f->returns;
                   28250:                                if (f->argtype->base != ELIST) f->f_args = f->argtype = (Pname)new expr(ELIST,(Pexpr)f->argtype,0);
                   28251:                                if ( n->n_initializer ) {
                   28252:                                        error(&n->where,"twoIrs for%n",n);
                   28253:                                        DEL( ((Pexpr)f->argtype) );
                   28254:                                        f->argtype = 0;
                   28255:                                } else
                   28256:                                        // n->n_initializer = new texpr(VALUE,cn->tp,(Pexpr)f->argtype);
                   28257:                                         n->n_initializer = new texpr(VALUE, cn ? cn->tp : template_formal_type, (Pexpr)f->argtype);
                   28258:                                goto ok;
                   28259:                        zzz:
                   28260:                                if (f->argtype) {
                   28261:                                        DEL(Pexpr(f->argtype));
                   28262:                                        f->argtype = 0;
                   28263:                                        f->nargs = 0;
                   28264:                                        f->nargs_known = 1;
                   28265:                                }
                   28266:                        }
                   28267:                        else {  /* T a(); => function declaration */
                   28268: /*
                   28269:                                if (clob) {
                   28270:                                        DEL(n->tp);
                   28271:                                        n->tp = f->returns;
                   28272:                                }
                   28273: */
                   28274:                        }
                   28275:                ok:
                   28276:                        ;
                   28277:                }
                   28278:        }
                   28279:        return nn;
                   28280: }
                   28281: 
                   28282: Ptype vec::normalize(Ptype vecof)
                   28283: {
                   28284:        Ptype t = typ;
                   28285:        typ = vecof;
                   28286: 
                   28287:        while(vecof->base == TYPE)
                   28288:                vecof = Pbase(vecof)->b_name->tp;
                   28289:                
                   28290:        switch (vecof->base) {
                   28291:        case RPTR:
                   28292:                        error("array ofRs");
                   28293:                        break;
                   28294:        case FCT:
                   28295:                        error("array ofFs");
                   28296:                        break;
                   28297:        default:
                   28298:                        break;
                   28299:        }
                   28300: 
                   28301:        if (t == 0) return this;
                   28302: 
                   28303:        switch (t->base) {
                   28304:        case PTR:
                   28305:        case RPTR:      return Pptr(t)->normalize(this);
                   28306:        case VEC:       return Pvec(t)->normalize(this);
                   28307:        case FCT:       return Pfct(t)->normalize(this);
                   28308:        default:        error('i',"bad arrayT(%d)",t->base);
                   28309:        }
                   28310: 
                   28311: }
                   28312: 
                   28313: Ptype ptr::normalize(Ptype ptrto)
                   28314: {
                   28315: //     if (this == 0) error('i',"0->ptr.normalize()");
                   28316:        Ptype t = typ;
                   28317:        typ = ptrto;
                   28318: 
                   28319:        int bc = 0;
                   28320:        while (ptrto->base == TYPE) {
                   28321:                bc += Pbase(ptrto)->b_const;
                   28322:                ptrto = Pbase(ptrto)->b_name->tp;
                   28323:        }
                   28324: 
                   28325:        switch (ptrto->base) {
                   28326:        case FCT:
                   28327:                if (memof)
                   28328:                        if (Pfct(ptrto)->memof) {
                   28329:                                if (memof != Pfct(ptrto)->memof) error("P toMF mismatch: %s and %s",memof->string, Pfct(ptrto)->memof->string);
                   28330:                        }
                   28331:                        else
                   28332:                                Pfct(ptrto)->memof = memof;
                   28333:                else
                   28334:                        memof = Pfct(ptrto)->memof;
                   28335:                break;
                   28336:        case RPTR:
                   28337:                switch (base) {
                   28338:                case PTR:       error("P toR"); break;
                   28339:                case RPTR:      error("R toR"); break;
                   28340:                }
                   28341:        }
                   28342: 
                   28343:        if (t == 0) {
                   28344:                Pbase b = Pbase(ptrto);
                   28345:                if (Pfctvec_type
                   28346:                && rdo==0
                   28347:                && b->b_unsigned==0
                   28348:                && b->b_const==0
                   28349:                && bc == 0
                   28350:                && memof==0
                   28351:                && base==PTR) {
                   28352:                        switch (b->base) {
                   28353:                        case INT:       delete this;    return Pint_type;
                   28354:                        case CHAR:      delete this;    return Pchar_type;
                   28355:                        case VOID:      delete this;    return Pvoid_type;
                   28356:                        }
                   28357:                }
                   28358:                if (base==RPTR && b->base==VOID) error("void& is not a validT");
                   28359:                return this;
                   28360:        }
                   28361: 
                   28362:        switch (t->base) {
                   28363:        case PTR:
                   28364:        case RPTR:      return Pptr(t)->normalize(this);
                   28365:        case VEC:       return Pvec(t)->normalize(this);
                   28366:        case FCT:       return Pfct(t)->normalize(this);
                   28367:        default:        error('i',"badPT(%k)",t->base);
                   28368:        }
                   28369: }
                   28370: 
                   28371: Ptype fct::normalize(Ptype ret)
                   28372: /*
                   28373:        normalize return type
                   28374: */
                   28375: {
                   28376:        register Ptype t = returns;
                   28377:        returns = ret;
                   28378: 
                   28379:        if (argtype && argtype->base==NAME && argtype->n_qualifier) {
                   28380:                error("syntax: ANX");
                   28381:                argtype = 0;
                   28382:                nargs = 0;
                   28383:                nargs_known = 0;
                   28384:        }
                   28385: 
                   28386:        while(ret->base == TYPE)
                   28387:                ret = Pbase(ret)->b_name->tp;
                   28388: 
                   28389:        switch(ret->base) {
                   28390:        case VEC:
                   28391:                error("F returning array");
                   28392:                break;
                   28393:        case FCT:
                   28394:                error("F returningF");
                   28395:                returns = ret = t?t:int_type;
                   28396:                break;
                   28397:        default:
                   28398:                break;
                   28399:        }
                   28400: 
                   28401:        if (t == 0) return this;
                   28402: 
                   28403:        switch (t->base) {
                   28404:        case PTR:
                   28405:        case RPTR:      return Pptr(t)->normalize(this);
                   28406:        case VEC:       return Pvec(t)->normalize(this);
                   28407:        case FCT:       return Pfct(t)->normalize(this);
                   28408:        default:        error('i',"badFT:%k",t->base);
                   28409:        }
                   28410: }
                   28411: 
                   28412: void fct::argdcl(Pname dcl, Pname fn)
                   28413: /*
                   28414:        sort out the argument types for old syntax:
                   28415:                        f(a,b) int a; char b; { ... }
                   28416:        beware of
                   28417:                        f(a) struct s { int a; }; struct s a;
                   28418: */
                   28419: {
                   28420:        Pname n;
                   28421: /*fprintf(stderr,"%d argtype %d %d dcl %d %d\n",this, argtype, argtype?argtype->base:0, dcl, dcl?dcl->base:0); fflush(stderr);*/
                   28422:        switch (base) {
                   28423:        case FCT:       break;
                   28424:        case ANY:       return;
                   28425:        default:        error('i',"fct::argdcl(%d)",base);
                   28426:        }
                   28427: 
                   28428:        if (argtype) {
                   28429:                switch (argtype->base) {
                   28430:                case NAME:
                   28431:                        if (dcl) error("badF definition syntax");
                   28432:                        for (n=argtype; n; n=n->n_list) {
                   28433:                                if (n->string == 0) n->string = make_name('A');
                   28434:                        }
                   28435:                        return;
                   28436:                case ELIST:     // expression list:     f(a,b,c) int a; ... { ... }
                   28437:                                // scan the elist and build a NAME list
                   28438:                {
                   28439:                        Pname tail = 0;
                   28440:                        n = 0;
                   28441: 
                   28442:                        error(strict_opt?0:'w',&fn->where,"old style definition of%n (anachronism)",fn);
                   28443: 
                   28444:                        for (Pexpr e=Pexpr(argtype); e; e=e->e2) {
                   28445:                                Pexpr id = e->e1;
                   28446:                                if (id->base != NAME) {
                   28447:                                        error("NX inAL");
                   28448:                                        argtype = 0;
                   28449:                                        dcl = 0;
                   28450:                                        break;
                   28451:                                }
                   28452:                                Pname nn = new name(id->string);
                   28453:                                if (n)
                   28454:                                        tail = tail->n_list = nn;
                   28455:                                else
                   28456:                                        tail = n = nn;
                   28457:                        }
                   28458:                        f_args = argtype = n;
                   28459:                        break;
                   28460:                }
                   28461:                default:
                   28462:                        error("ALX(%d)",argtype->base);
                   28463:                        argtype = 0;
                   28464:                        dcl = 0;
                   28465:                }
                   28466:        }
                   28467:        else if(nargs_known == ELLIPSIS) {
                   28468:                return;
                   28469:        }
                   28470:        else {
                   28471:                nargs_known = 1;
                   28472:                nargs = 0;
                   28473:                if (dcl) error("ADL forFWoutAs");
                   28474:                return;
                   28475:        }
                   28476: 
                   28477: //     nargs_known = 0;
                   28478: 
                   28479:        if (dcl) {
                   28480:                Pname d;
                   28481:                Pname dx;
                   28482:                /*      for each  argument name see if its type is specified
                   28483:                        in the declaration list otherwise give it the default type
                   28484:                */
                   28485: 
                   28486:                for (n=argtype; n; n=n->n_list) {
                   28487:                        char* s = n->string;
                   28488:                        if (s == 0) {
                   28489:                                error("AN missing inF definition");
                   28490:                                n->string = s = make_name('A');
                   28491:                        }
                   28492:                        else if (n->tp) error("twoTs forA %s",n->string);
                   28493: 
                   28494:                        for (d=dcl; d; d=d->n_list) {
                   28495:                                if (strcmp(s,d->string) == 0) {
                   28496:                                        if (d->tp->base == VOID) {
                   28497:                                                error("voidA%n",d);
                   28498:                                                d->tp = any_type;
                   28499:                                        }
                   28500:                                        n->tp = d->tp;
                   28501:                                        n->n_sto = d->n_sto;
                   28502:                                        d->tp = 0;      // now merged into argtype
                   28503:                                        goto xx;
                   28504:                                }
                   28505:                        }
                   28506:                        n->tp = defa_type;
                   28507:                xx:;
                   28508:                        if (n->tp == 0) error('i',"noT for %s",n->string);
                   28509:                }
                   28510:        
                   28511:                /*      now scan the declaration list for "unused declarations"
                   28512:                        and delete it
                   28513:                */
                   28514:                for (d=dcl; d; d=dx) {
                   28515:                        dx = d->n_list;
                   28516:                        if (d->tp) {    /* not merged with argtype list */
                   28517:                                /*if (d->base == TNAME)  ??? */
                   28518:                                switch (d->tp->base) {
                   28519:                                case CLASS:
                   28520:                                case ENUM:
                   28521:                                        /* WARNING: this will reverse the order of
                   28522:                                           class and enum declarations
                   28523:                                        */
                   28524:                                        d->n_list = argtype;
                   28525:                                        f_args = argtype = d;
                   28526:                                        break;
                   28527:                                default:
                   28528:                                         error("%n inADL not inAL",d);
                   28529:                                }
                   28530:                        }
                   28531:                }
                   28532:        }
                   28533: 
                   28534:        /* add default argument types if necessary */
                   28535:        for (n=argtype; n; n=n->n_list) {
                   28536:                if (n->tp == 0) n->tp = defa_type;
                   28537:                nargs++;
                   28538:        }
                   28539: }
                   28540: 
                   28541: Pname cl_obj_vec;      /* set if is_cl_obj() found a array of class objects */
                   28542: Pname eobj;            /* set if is_cl_obj() found an enum */
                   28543: 
                   28544: Pname type::is_cl_obj()
                   28545: /*
                   28546:        returns this->b_name if this is a class object
                   28547:        returns 0 and sets cl_obj_vec to this->b_name
                   28548:                if this is a array of class objects
                   28549:        returns 0 and sets eobj to this->b_name
                   28550:                if this is an enum object
                   28551:        else returns 0
                   28552: */
                   28553: {
                   28554:        bit v = 0;
                   28555:        register Ptype t = this;
                   28556: 
                   28557:        if (t == 0) return 0;
                   28558:        eobj = 0;
                   28559:        cl_obj_vec = 0;
                   28560: xx:
                   28561:        switch (t->base) {
                   28562:        case TYPE:
                   28563:                t = Pbase(t)->b_name->tp;
                   28564:                goto xx;
                   28565: 
                   28566:        case COBJ:
                   28567:                if (v) {
                   28568:                        cl_obj_vec = Pbase(t)->b_name;
                   28569:                        return 0;
                   28570:                }
                   28571:                else
                   28572:                        return Pbase(t)->b_name;
                   28573: 
                   28574:        case VEC:
                   28575:                t = Pvec(t)->typ;
                   28576:                v=1;
                   28577:                goto xx;
                   28578: 
                   28579:        case EOBJ:
                   28580:                eobj = Pbase(t)->b_name;
                   28581:        default:        
                   28582:                return 0;
                   28583:        }
                   28584: }
                   28585: 
                   28586: /*
                   28587: static Pname
                   28588: lookup(char* s, Pclass cl)
                   28589: {
                   28590:        Pbcl bc = 0;
                   28591:        Pname n = cl->memtbl->look(s,0);
                   28592:        if ( n ) return n;
                   28593:        Pname n2 = 0;
                   28594:        for (Pbcl b=cl->baselist; b; b=b->next) {
                   28595:                n = b->bclass->lookup(s,cl);
                   28596:                if ( n == 0 ) continue;
                   28597:                if ( n2 ) { // clash?
                   28598:                }
                   28599:                n2 = n;
                   28600:        }
                   28601: }
                   28602: */
                   28603: 0707071010112044371004440001630000160000010205100466055405600001000000011657norm2.c/*ident    "@(#)ctrans:src/norm2.c 1.4" */
                   28604: /************************************************************************
                   28605: 
                   28606:        C++ source for cfront, the C++ compiler front-end
                   28607:        written in the computer science research center of Bell Labs
                   28608: 
                   28609:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   28610:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   28611: 
                   28612: norm2.c:
                   28613: 
                   28614:        "normalization" handles problems which could have been handled
                   28615:        by the syntax analyser; but has not been done. The idea is
                   28616:        to simplify the grammar and the actions associated with it,
                   28617:        and to get a more robust error handling
                   28618: 
                   28619: ****************************************************************************/
                   28620: 
                   28621: #include "cfront.h"
                   28622: #include "size.h"
                   28623: 
                   28624: #ifdef DBG
                   28625: long node_id = 0;
                   28626: #define DBCHECK() if(node::allocated) error('i',"allocated node (id %d, base%k) on free list! (src: \"%s\", %d",node::id,node::base,__FILE__,__LINE__);
                   28627: #else
                   28628: #define DBCHECK() /**/
                   28629: #endif
                   28630: 
                   28631: fct::fct(Ptype t, Pname arg, TOK known)
                   28632: {
                   28633:        base = FCT;
                   28634:        nargs_known = known;
                   28635:        returns = t;
                   28636:        argtype = arg; 
                   28637:        DBID();
                   28638: 
                   28639:        if (arg==0 || arg->base==ELIST) return;
                   28640: //error('d',"fct::fct %d sig %d",this,f_signature);
                   28641:        register Pname n;
                   28642:        Pname pn = 0;
                   28643:        for (n=arg; n; pn=n,n=n->n_list) {
                   28644:                if( n->n_sto==EXTERN ) error("externA");
                   28645:                if( n->n_sto==STATIC ) error("static used forA%n",arg);
                   28646:  
                   28647:                switch (n->tp->base) {
                   28648:                case VOID:
                   28649:                        argtype = 0;
                   28650:                        nargs_known = 1;
                   28651:                        if(n->n_initializer)
                   28652:                                error("voidFA");
                   28653:                        else if (n->string)
                   28654:                                error("voidFA%n",n);
                   28655:                        else if (nargs || n->n_list) {
                   28656:                                error("voidFA");
                   28657:                                nargs_known = 0;
                   28658:                        }
                   28659:                        nargs = 0;
                   28660:                        break;
                   28661:                case CLASS:
                   28662:                case ENUM:
                   28663:                        error("%k defined inAL (will not be in scope at point of call)",n->tp->base);
                   28664:                        if (n == argtype)
                   28665:                                argtype = n->n_list;
                   28666:                        else
                   28667:                                pn->n_list = n->n_list;
                   28668:                        break;
                   28669:                default:
                   28670:                        nargs++;
                   28671:                }
                   28672:        }
                   28673: }
                   28674: 
                   28675: expr::expr(TOK ba, Pexpr a, Pexpr b)
                   28676: {
                   28677:        DBCHECK();
                   28678: 
                   28679:        base = ba;
                   28680:        e1 = a;
                   28681:        e2 = b;
                   28682:        DBID();
                   28683: }
                   28684: 
                   28685: stmt::stmt(TOK ba, loc ll, Pstmt a)
                   28686: {
                   28687:        DBCHECK();
                   28688: 
                   28689:        base = ba;
                   28690:        where = ll;
                   28691:        s=a;
                   28692:        DBID();
                   28693: }
                   28694: 
                   28695: classdef::classdef(TOK b)
                   28696: {
                   28697:        base = CLASS;
                   28698:        csu = b;
                   28699:        memtbl = new table(CTBLSIZE,0,0);
                   28700:        DBID();
                   28701: }
                   28702: 
                   28703: classdef::~classdef()
                   28704: {
                   28705:        delete memtbl;
                   28706: }
                   28707: 
                   28708: basetype::basetype(TOK b, Pname n)
                   28709: {
                   28710:        switch (b) {
                   28711:        case 0:                         break;
                   28712:        case TYPEDEF:   b_typedef = 1;  break;
                   28713:        case INLINE:    b_inline = 1;   break;
                   28714:        case VIRTUAL:   b_virtual = 1;  break;
                   28715:        case CONST:     b_const = 1;    break;
                   28716:        case UNSIGNED:  b_unsigned = 1; break;
                   28717:        case FRIEND:
                   28718:        case OVERLOAD:
                   28719:        case EXTERN:
                   28720:        case STATIC:
                   28721:        case AUTO:
                   28722:        case REGISTER:  b_sto = b;      break;
                   28723:        case SHORT:     b_short = 1;    break;
                   28724:        case LONG:      b_long = 1;     break;
                   28725:        case ANY:
                   28726:        case ZTYPE:
                   28727:        case VOID:
                   28728:        case CHAR:
                   28729:        case INT:
                   28730:        case FLOAT:
                   28731:        case LDOUBLE:
                   28732:        case DOUBLE:    base = b;       break;
                   28733:        case TYPE:
                   28734:        case COBJ:
                   28735:        case EOBJ:
                   28736:        case FIELD:
                   28737:        case ASM:
                   28738:                base = b;
                   28739:                b_name = n;
                   28740:                break;
                   28741:        case SIGNED:
                   28742:        case VOLATILE:
                   28743:                error('w',"\"%k\" not implemented (ignored)",b);
                   28744:                break;
                   28745:        default:
                   28746:                error('i',"badBT:%k",b);
                   28747:        }
                   28748:        DBID();
                   28749: }
                   28750: 
                   28751: name::name(char* s) : expr(NAME,0,0)
                   28752: {
                   28753:        // DBCHECK() called in expr::expr()
                   28754:        string = s;
                   28755:        where = curloc;
                   28756:        lex_level = bl_level;
                   28757: }
                   28758: 
                   28759: nlist::nlist(Pname n)
                   28760: {
                   28761:        head = n;
                   28762:        for (Pname nn=n; nn->n_list; nn=nn->n_list);
                   28763:        tail = nn;
                   28764: }
                   28765: 
                   28766: void nlist::add_list(Pname n)
                   28767: {
                   28768:        if (n->tp && (n->tp->defined & IN_ERROR)) return;
                   28769: 
                   28770:        tail->n_list = n;
                   28771:        for (Pname nn=n; nn->n_list; nn=nn->n_list);
                   28772:        tail = nn;
                   28773: }
                   28774: 
                   28775: Pname name_unlist(Pnlist l)
                   28776: {
                   28777:        if (l == 0) return 0;
                   28778:        Pname n = l->head;
                   28779: 
                   28780:        delete l;
                   28781:        return n;
                   28782: }
                   28783: 
                   28784: Pstmt stmt_unlist(Pslist l)
                   28785: {
                   28786:        if (l == 0) return 0;
                   28787:        Pstmt s = l->head;
                   28788: //     NFl++;
                   28789: 
                   28790:        delete l;
                   28791:        return s;
                   28792: }
                   28793: 
                   28794: Pexpr expr_unlist(Pelist l)
                   28795: {
                   28796:        if (l == 0) return 0;
                   28797:        Pexpr e = l->head;
                   28798: //     NFl++;
                   28799: 
                   28800:        delete l;
                   28801:        return e;
                   28802: }
                   28803: 
                   28804: void sig_name(Pname n)
                   28805: {
                   28806:        static char buf[256];
                   28807:        buf[0] = '_';
                   28808:        buf[1] = '_';
                   28809:        buf[2] = 'o';
                   28810:        buf[3] = 'p';
                   28811:        char* p = n->tp->signature(buf+4);
                   28812:        if (255 < p-buf) error('i',"sig_name():N buffer overflow");
                   28813:        char *s = new char [ p - buf + 1 ];
                   28814:        strcpy(s,buf);
                   28815:        n->string = s;
                   28816:        n->tp = 0;
                   28817: }
                   28818: 
                   28819: Ptype tok_to_type(TOK b)
                   28820: {
                   28821:        Ptype t;
                   28822:        switch (b) {
                   28823:        case CHAR:      t = char_type; break;
                   28824:        case SHORT:     t = short_type; break;
                   28825:        case LONG:      t = long_type; break;
                   28826:        case UNSIGNED:  t = uint_type; break;
                   28827:        case FLOAT:     t = float_type; break;
                   28828:        case DOUBLE:    t = double_type; break;
                   28829:        case LDOUBLE:   t = ldouble_type; break;
                   28830:        case VOID:      t = void_type; break;
                   28831:        default:        error("illegalK:%k",b);
                   28832:        case INT:       t = int_type;
                   28833:        }
                   28834:        return t;
                   28835: }
                   28836: 
                   28837: Pbase defa_type;
                   28838: Pbase moe_type;
                   28839: Pexpr dummy;
                   28840: Pexpr zero;
                   28841: 
                   28842: Pclass ccl;
                   28843: Plist modified_tn = 0;
                   28844: 
                   28845: Plist local_tn = 0;
                   28846: Plist local_blk = 0;
                   28847: Plist local_class = 0;
                   28848: 
                   28849: Plist nested_tn = 0;
                   28850: Plist nested_type = 0;
                   28851: 
                   28852: void memptrdcl(Pname bn, Pname tn, Ptype ft, Pname n)
                   28853: {
                   28854:        Pptr p = new ptr(PTR,0);
                   28855:        p->memof = Pclass(Pbase(bn->tp)->b_name->tp);
                   28856:        Pbase b = new basetype(TYPE,tn);
                   28857:        PERM(p);
                   28858:        Pfct f = Pfct(ft);
                   28859:        Ptype t = n->tp;
                   28860:        if (t) {
                   28861:                p->typ = t;
                   28862:        ltlt:
                   28863:                switch (t->base) {
                   28864:                case PTR:
                   28865:                case RPTR:
                   28866:                case VEC:
                   28867:                        if (Pptr(t)->typ == 0) {
                   28868:                                Pptr(t)->typ = b;
                   28869:                                break;
                   28870:                        }
                   28871:                        t = Pptr(t)->typ;
                   28872:                        goto ltlt;
                   28873:                default:
                   28874:                        error('s',"P toMFT too complicated");
                   28875:                }
                   28876:        }
                   28877:        else
                   28878:        p->typ = b;     
                   28879:        f->returns = p;
                   28880:        n->tp = f;
                   28881: }
                   28882: 0707071010112044401004440001630000160000010205200466055406200001000000061331print.c/*ident    "@(#)ctrans:src/print.c 1.3" */
                   28883: /**************************************************************************
                   28884: 
                   28885:        C++ source for cfront, the C++ compiler front-end
                   28886:        written in the computer science research center of Bell Labs
                   28887: 
                   28888:        Copyright (c) 1984 AT&T, Inc. All rights Reserved
                   28889:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   28890: 
                   28891: print.c:
                   28892: 
                   28893:        print statements and expressions
                   28894: 
                   28895: ****************************************************************************/
                   28896: 
                   28897: #include "cfront.h"
                   28898: 
                   28899: static int addrof_cm ;
                   28900: extern void puttok(TOK);
                   28901: 
                   28902: /*
                   28903: void cprint(Pexpr e)
                   28904: {
                   28905:        if (e == 0) return;
                   28906: //error('d',"%k %n %t",e->base,e->base==NAME?e:0,e->tp);
                   28907: //     if ((e->base==NAME || e->base==ANAME)
                   28908: //     && Pname(e)->n_evaluated==0) {
                   28909:                Ptype t = e->tp;
                   28910:                while (t->base == TYPE) t = Pbase(t)->b_name->tp;
                   28911:                if (t->base == EOBJ) fprintf(out_file,"(int)");
                   28912: //     }
                   28913:         
                   28914:         Eprint(e);
                   28915: }
                   28916: */
                   28917: #define cprint(e) if (e) Eprint(e)
                   28918: #define eprint(e) if (e) Eprint(e)
                   28919: 
                   28920: void Eprint(Pexpr e)
                   28921: {
                   28922:        switch (e->base) {
                   28923:        case REF:
                   28924:                if (Pref(e)->mem && Pref(e)->mem->tp && Pref(e)->mem->tp->base == FCT) {
                   28925:                        //  suppress ``this'' in ``this->f''
                   28926:                        Pref(e)->mem->print();
                   28927:                        break;
                   28928:                }
                   28929:        case NAME:
                   28930:        case MDOT:
                   28931:        case ID:
                   28932:        case ZERO:
                   28933:        case ICON:
                   28934:        case CCON:
                   28935:        case FCON:
                   28936:        case STRING:
                   28937:        case IVAL:
                   28938:        case TEXT:
                   28939:        case CM:
                   28940:        case G_CM:
                   28941:        case ELIST:
                   28942:        case COLON:
                   28943:        case ILIST:
                   28944:        case DOT:
                   28945:        case THIS:
                   28946:        case CALL:
                   28947:        case G_CALL:
                   28948:        case ICALL:
                   28949:        case ANAME:
                   28950:                e->print();
                   28951:        case DUMMY:
                   28952:                break;
                   28953:        default:
                   28954:                putch('(');
                   28955:                e->print();
                   28956:                putch(')');
                   28957:        }
                   28958: }
                   28959: 
                   28960: void expr::print()
                   28961: {
                   28962:        if (this == 0) error('i',"0->E::print()");
                   28963:        if (this==e1 || this==e2) error('i',"(%p%k)->E::print(%p %p)",this,base,e1,e2);
                   28964: // error('d',"(%d %k)->expr::print(%d %d)",this,base,e1,e2);
                   28965: 
                   28966:        switch (base) {
                   28967:        case MDOT:
                   28968:        {
                   28969: // error('d',"mdot %s i1 %d %t",string2,i1,mem->tp);
                   28970:        int not_allocated = 0;
                   28971:                switch (i1) {
                   28972:                case 0:
                   28973:                        putcat('O',string2);
                   28974:                        puttok(DOT);    // use sub-object directly
                   28975:                        mem->print();
                   28976:                        break;
                   28977:                case 1:
                   28978:                        putcat('P',string2);
                   28979:                        puttok(REF);    // use through pointer
                   28980:                        mem->print();
                   28981:                        break;
                   28982:                case 2:
                   28983:                        if (mem->tp->is_ptr_or_ref()==0) {
                   28984:                                mem->print();
                   28985:                                puttok(DOT);
                   28986:                                putcat('O',string2);
                   28987:                        }
                   28988:                        else
                   28989:                        {
                   28990:                        putch('(');     // REF turns pointer into object: add &
                   28991:                        putch('&');     // ``this'' is a pointer
                   28992:                        putch('(');
                   28993:                        eprint(mem);//mem->print();
                   28994:                        puttok(REF);    // call sub-object directly
                   28995:                        putcat('O',string2);
                   28996:                        putch(')');
                   28997:                        putch(')');
                   28998:                        }
                   28999:                        break;
                   29000:                case 5:
                   29001:                        not_allocated = 1;
                   29002:                        // no break;    
                   29003:                case 3:
                   29004:                    if (mem->tp->is_ptr_or_ref()==0) {
                   29005:                        putch('(');     // Px is a pointer (T*) turn it back to a T
                   29006:                        putch('*');     // *Px
                   29007:                        putch('(');
                   29008:                        eprint(mem);//mem->print();
                   29009:                        puttok(DOT);    //  call through pointer
                   29010:                        putcat('P',string2);
                   29011:                        putch(')');
                   29012:                        putch(')');
                   29013:                    }
                   29014:                    else {
                   29015: //                     eprint(mem);    // <<< mem->print()
                   29016:                        if (not_allocated) {
                   29017:                                putch('(');
                   29018:                                mem->print();
                   29019:                                if ( mem->base == NAME ) 
                   29020:                                        puttok(REF);
                   29021:                                else puttok(DOT);
                   29022:                                putcat('O',string4);
                   29023:                                putch(')');
                   29024:                        }
                   29025:                        else eprint(mem);
                   29026:                        if (mem->base == NAME && not_allocated)
                   29027:                                puttok(DOT);
                   29028:                        else puttok(REF);       //  call through pointer
                   29029:                        putcat('P',string2);
                   29030:                    }
                   29031:                    break;
                   29032:                case 9: // vtbl entry:  (p->_vtbl).f, (p->_vtbl).i, (p->_vtbl).d
                   29033:                        // or memptr: mp.f, mp.i, mp.d
                   29034:                        eprint(mem);
                   29035:                        putch('.');
                   29036:                        putstring(string2);
                   29037:                } // end switch(i1)
                   29038:                break;
                   29039:        } // end MDOT
                   29040: 
                   29041:        case NAME:
                   29042:        {       Pname n = Pname(this);
                   29043:                 if (n->n_evaluated
                   29044:         //      && n->tp->base!=EOBJ    // this output enumerators
                   29045:                 && n->n_scope!=ARG) {
                   29046:                         Ptype t = tp;
                   29047:                        while (t->base == TYPE) t = Pbase(t)->b_name->tp;
                   29048:                         if (t->base == EOBJ) t = Penum(Pbase(t)->b_name->tp)->e_type;
                   29049:                         if (t->base!=INT || t->is_unsigned()) {
                   29050:                                putstring("((");
                   29051:                                bit oc = Cast;
                   29052:                                Cast = 1;
                   29053:                                 t->print();
                   29054:                                Cast = oc;
                   29055:                                fprintf(out_file,")%d)",n->n_val);
                   29056:                        }
                   29057:                        else
                   29058:                                fprintf(out_file,"%d",n->n_val);
                   29059:                }
                   29060:                else
                   29061:                        n->print();
                   29062:                break;
                   29063:        }
                   29064:        case ANAME:
                   29065:                if (curr_icall) {       // in expansion: look it up
                   29066:                        Pname n = Pname(this);
                   29067:                        int argno = int(n->n_val);
                   29068: 
                   29069:                        for (Pin il=curr_icall; il; il=il->i_next)
                   29070:                                if (n->n_table == il->i_table) goto aok;
                   29071:                        goto bok;
                   29072:                aok:
                   29073:                        if (n = il->i_args[argno].local) {
                   29074:                                n->print();
                   29075:                        }
                   29076:                        else {
                   29077:                                Pexpr ee = il->i_args[argno].arg;
                   29078:                                Ptype t = il->i_args[argno].tp;
                   29079:                                if (ee==0 || ee==this) error('i',"%p->E::print(A %p)",this,ee);
                   29080:                                if (ee->tp==0
                   29081:                                || (t!=ee->tp
                   29082:                                        && t->check(ee->tp,0)
                   29083:                                        && t->is_cl_obj()==0
                   29084:                                //      && eobj==0)
                   29085:                                        )
                   29086:                                ) {
                   29087:                                        putstring("((");
                   29088:                                        bit oc = Cast;
                   29089:                                        Cast = 1;
                   29090:                                        t->print();
                   29091:                                        Cast = oc;
                   29092:                                        putch(')');
                   29093:                                        // eprint(ee);
                   29094:                                //      if (ee->base == CAST) {
                   29095:                                //              eprint(ee->e1);
                   29096:                                //      }
                   29097:                                //      else
                   29098:                                                eprint(ee);
                   29099:                                        putch(')');
                   29100:                                }
                   29101:                                else
                   29102:                                        eprint(ee);
                   29103:                        }
                   29104:                }
                   29105:                else {
                   29106:                bok:    /* in body: print it: */
                   29107:                        Pname(this)->print();
                   29108:                }
                   29109:                break;
                   29110: 
                   29111:        case ICALL:
                   29112:        {       il->i_next = curr_icall;
                   29113:                curr_icall = il;
                   29114: //error('d',"icall %n",il->fct_name);
                   29115:                if (il == 0) error('i',"E::print: iline missing");
                   29116:                Pexpr a0 = il->i_args[0].arg;
                   29117:                int val = QUEST;
                   29118:                if (il->fct_name->n_oper != CTOR) goto dumb;
                   29119: 
                   29120:                /*
                   29121:                        find the value of "this"
                   29122:                        if the argument is a "this" NOT assigned to
                   29123:                        by the programmer, it was initialized
                   29124:                */
                   29125:                switch (a0->base) {
                   29126:                case ZERO:
                   29127:                        val = 0;
                   29128:                        break;
                   29129:                case ADDROF:
                   29130:                case G_ADDROF:
                   29131:                        val = 1;
                   29132:                        break;
                   29133:                case CAST:
                   29134:                        if (a0->e1->base == ANAME || a0->e1->base == NAME) {
                   29135:                                Pname a = (Pname)a0->e1;
                   29136:                                if (a->n_assigned_to == FUDGE111) val = FUDGE111;
                   29137:                        }
                   29138:                }
                   29139:                if (val==QUEST) goto dumb;
                   29140:                /*
                   29141:                        now find the test:  "(this==0) ? _new(sizeof(X)) : 0"
                   29142: 
                   29143:                        e1 is a comma expression,
                   29144:                        the test is either the first sub-expression
                   29145:                                or the first sub-expression after the assignments
                   29146:                                        initializing temporary variables
                   29147:                 */
                   29148:        dumb:
                   29149:                eprint(e1);
                   29150:                if (e2) Pstmt(e2)->print();
                   29151:                curr_icall = il->i_next;
                   29152:                break;
                   29153:        }
                   29154:        case REF:
                   29155:        case DOT:
                   29156:                eprint(e1);
                   29157:                puttok(base);
                   29158:                if (mem == 0) {
                   29159:                        fprintf(out_file,"MEM0");
                   29160:                        break;
                   29161:                }
                   29162:                if (mem->base == NAME)
                   29163:                        Pname(mem)->print();
                   29164:                else
                   29165:                        mem->print();
                   29166:                break;
                   29167: 
                   29168:        case MEMPTR:
                   29169:                error("P toMF not called");
                   29170:                break;
                   29171: 
                   29172:        case VALUE:
                   29173:                tp2->print();
                   29174:                puttok(LP);
                   29175: 
                   29176: //             if (e2) {
                   29177: //                     putstring(" &");
                   29178: //                     e2->print();
                   29179: //                     putstring(", ");
                   29180: //             }
                   29181:                if (e1) e1->print();
                   29182:                puttok(RP);
                   29183:                break;
                   29184: 
                   29185:        case SIZEOF:
                   29186:                puttok(SIZEOF);
                   29187:                if (e1 && e1!=dummy) {
                   29188:                        eprint(e1);
                   29189:                }
                   29190:                else if (tp2) {
                   29191:                        putch('(');
                   29192:                        if (tp2->base == CLASS) {
                   29193:                                Pclass cl = Pclass(tp2);
                   29194:                                putstring((cl->csu == UNION)?"union ":"struct ");
                   29195:                                char *str = 0;
                   29196:                                // nested local class does not encode name
                   29197:                                if ( cl->lex_level && cl->nested_sig == 0 ) 
                   29198:                                        str = make_local_name( cl );
                   29199:                                putstring(str?str:(cl->nested_sig?cl->nested_sig:cl->string));
                   29200:                                delete str;
                   29201:                        }
                   29202:                        else
                   29203:                                tp2->print();
                   29204:                        putch(')');
                   29205:                }
                   29206:                break;
                   29207: 
                   29208: /*
                   29209: // always turned into function calls:
                   29210:         case NEW:
                   29211:         case GNEW:
                   29212: // error('d',"print new %d tp2 %t e1 %d e2 %d",base,tp2,e1,e2);
                   29213:                puttok(NEW);
                   29214:                tp2->print();
                   29215:                if (e1) {
                   29216:                        putch('(');
                   29217:                        e1->print();
                   29218:                        putch(')');
                   29219:                }
                   29220:                break;
                   29221: 
                   29222:        case DELETE:
                   29223:         case GDELETE:
                   29224: //error('d',"print delete");
                   29225:                puttok(DELETE);
                   29226:                e1->print();
                   29227:                break;
                   29228: */
                   29229:        case CAST:
                   29230:                putch('(');
                   29231: //error('d',"print cast %t",tp2);
                   29232:                if (tp2->base != VOID && tp2->memptr() == 0 ) {
                   29233:                         // when VOID is represented as CHAR not everything
                   29234:                         // can be cast to VOID
                   29235:                        putch('(');
                   29236:                        bit oc = Cast;
                   29237:                        Cast = 1;
                   29238:                        tp2->print();
                   29239:                        Cast = oc;
                   29240:                        putch(')');     
                   29241:                }
                   29242:                eprint(e1);
                   29243:                putch(')');
                   29244:                break;
                   29245: 
                   29246:        case ICON:
                   29247:        case FCON:
                   29248:        case CCON:
                   29249:        case ID:
                   29250:                if (string) putst(string);
                   29251:                break;
                   29252: 
                   29253:        case STRING:
                   29254:                 // avoid printing very long lines
                   29255:                 ntok += 4;
                   29256:                fprintf(out_file,"\"%s\"",string);
                   29257:                break;
                   29258: 
                   29259:        case THIS:
                   29260:        case ZERO:
                   29261:                putstring("0 ");
                   29262:                break;
                   29263: 
                   29264:        case IVAL:
                   29265:                fprintf(out_file,"%d",i1);
                   29266:                break;
                   29267: 
                   29268:        case TEXT:
                   29269:        {
                   29270:                int oo = vtbl_opt;      // make `simulated static' name
                   29271:                vtbl_opt = -1;  
                   29272:                char* s = vtbl_name(string,string2);
                   29273:                vtbl_opt = oo;
                   29274:                s[2] = 'p';     // pointer, not tbl itself
                   29275:                 char* t = ptbl_lookup(s);
                   29276:                 fprintf(out_file, " %s",t);
                   29277:                delete t;
                   29278: 
                   29279:                char *str = 0;
                   29280:                if ( string ) { 
                   29281:                        str = new char[ strlen(string) + strlen(string2) + 1 ];
                   29282:                        strcpy( str, string );
                   29283:                        strcat( str, string2 );
                   29284:                }
                   29285: 
                   29286:                if ( ptbl->look( str?str:string2, 0 ) == 0 &&
                   29287:                     ptbl->look( str?str:string2, HIDDEN ) == 0 ) {
                   29288:                        Pname nn = ptbl->insert(new name(str?str:string2),0);
                   29289:                        nn->string2 = new char[strlen(s)+1];
                   29290:                        strcpy(nn->string2,s);
                   29291:                }
                   29292: 
                   29293:                delete str;
                   29294:                delete s;
                   29295:        }
                   29296:                // no break;
                   29297: 
                   29298:        case DUMMY:
                   29299:                break;
                   29300: 
                   29301:        case G_CALL:
                   29302:        case CALL:
                   29303:        {       Pname fn = fct_name;
                   29304:                Pname at;
                   29305:                int m_ptr = 0;
                   29306: 
                   29307:                if (fn) {
                   29308:                        Pfct f = Pfct(fn->tp);
                   29309: 
                   29310:                        if (f->base==OVERLOAD) {        // overloaded after call
                   29311:                                fct_name = fn = Pgen(f)->fct_list->f;
                   29312:                                f = Pfct(fn->tp);
                   29313:                        }
                   29314: 
                   29315:                        fn->print();
                   29316:                        at = f->f_args;
                   29317:                }
                   29318:                else {
                   29319:                        Pfct f = Pfct(e1->tp);
                   29320: 
                   29321:                        if (f) {        // pointer to fct
                   29322:                                Pexpr exex = e1;
                   29323:                                if ( exex->base == DEREF ) {
                   29324:                                        exex = exex->e1;
                   29325:                                        while ( exex->base == CAST )
                   29326:                                                        exex = exex->e1;
                   29327:                                        if ( exex->base == MDOT )
                   29328:                                                        m_ptr = 1;
                   29329:                                }
                   29330: 
                   29331:                                if (f->base == OVERLOAD) { // overloaded after call
                   29332:                                        fct_name = fn = Pgen(f)->fct_list->f;
                   29333:                                        f = Pfct(fn->tp);
                   29334:                                }
                   29335: 
                   29336:                                while (f->base == TYPE) f = Pfct(Pbase(f)->b_name->tp);
                   29337:                                if (f->base == PTR) {
                   29338:                                        putstring("(*");
                   29339:                                        e1->print();
                   29340:                                        putch(')');
                   29341:                                        f = Pfct(Pptr(f)->typ);
                   29342:                                        while (f->base == TYPE) f = Pfct(Pbase(f)->b_name->tp);
                   29343:                                }
                   29344:                                else
                   29345:                                        eprint(e1);
                   29346: 
                   29347:                        //      at = (f->f_result) ? f->f_result : f->argtype;
                   29348:                                at = f->f_args;
                   29349:                        }
                   29350:                        else {  // virtual: argtype encoded
                   29351:                                // f_this already linked to f_result and/or argtype
                   29352:                                at = (e1->base==QUEST) ? Pname(e1->e1->tp2) : Pname(e1->tp2);
                   29353:                                eprint(e1);
                   29354:                        }
                   29355:                }
                   29356: 
                   29357:                puttok(LP);
                   29358: 
                   29359:                if (e2) {
                   29360:                        if (at) {
                   29361:                                Pexpr e = e2;
                   29362:                                while (at) {
                   29363:                                        Pexpr ex;
                   29364:                                        Ptype t = at->tp;
                   29365: 
                   29366:                                        if (t == 0) error('i',"T ofA missing for%n",fn);
                   29367:                                        if (e == 0) error('i',"%tA missing for%n",t,fn);
                   29368:                                        if (e->base == ELIST) {
                   29369:                                                ex = e->e1;
                   29370:                                                e =  e->e2;
                   29371:                                        }
                   29372:                                        else
                   29373:                                                ex = e;
                   29374: 
                   29375:                                        if (ex == 0) error('i',"A ofT%t missing",t);
                   29376:                                        if (t!=ex->tp
                   29377:                                        && ex->tp
                   29378:                                        && t->check(ex->tp,0)
                   29379:                                        && t->is_cl_obj()==0
                   29380:                                        && eobj==0
                   29381:                                        && m_ptr == 0
                   29382:                                        && (t->is_ptr()==0 || Mptr==0)) {
                   29383:                                                putch('(');
                   29384:                                                bit oc = Cast;
                   29385:                                                Cast = 1;
                   29386:                                                t->print();
                   29387:                                                Cast = oc;
                   29388:                                                putch(')');
                   29389: #ifdef sun
                   29390: if (ex->base == DIV) { // defend against perverse SUN cc bug
                   29391:        putstring("(0+");
                   29392:        eprint(ex);
                   29393:        putch(')');
                   29394: }
                   29395: else
                   29396: #endif
                   29397:                                                // eprint(ex);
                   29398:                                        //      if (ex->base==CAST) {
                   29399:                                        //              eprint(ex->e1);
                   29400:                                        //      }
                   29401:                                        //      else
                   29402:                                                        eprint(ex);
                   29403:                                        }
                   29404:                                        else
                   29405:                                                ex->print();
                   29406: 
                   29407:                                        // if m_ptr is set, then don't advance at
                   29408:                                        // at does not know about generated `this'
                   29409:                                        if ( m_ptr ) {
                   29410:                                                m_ptr = 0;
                   29411:                                                if (at) puttok(CM);
                   29412:                                                continue;
                   29413:                                        }
                   29414: 
                   29415:                                        at = at->n_list;
                   29416:                                        if (at) puttok(CM);
                   29417:                                }
                   29418:                                if (e) {
                   29419:                                        puttok(CM);
                   29420:                                        e->print();
                   29421:                                }                
                   29422:                        }
                   29423:                        else
                   29424:                                e2->print();
                   29425:                }
                   29426:                puttok(RP);
                   29427:                break;
                   29428:        }
                   29429: 
                   29430:        case ASSIGN:
                   29431:                if (e1->base==ANAME && Pname(e1)->n_assigned_to==FUDGE111) {
                   29432:                // suppress assignment to "this" that has been optimized away
                   29433:                        Pname n = Pname(e1);
                   29434:                        int argno = int(n->n_val);
                   29435:                        for (Pin il=curr_icall; il; il=il->i_next)
                   29436:                                if (il->i_table == n->n_table) goto akk;
                   29437:                        goto bkk;
                   29438:                akk:
                   29439:                        if (il->i_args[argno].local == 0) {
                   29440:                                e2->print();
                   29441:                                break;
                   29442:                        }
                   29443:                }
                   29444:                //no break
                   29445:        case EQ:
                   29446:        case NE:
                   29447:        case GT:
                   29448:        case GE:
                   29449:        case LE:
                   29450:        case LT:
                   29451:        bkk:
                   29452:        {       Ptype t1 = e1->tp;
                   29453:                Ptype t2 = e2->tp;
                   29454: 
                   29455:                 if (base!=ASSIGN) {
                   29456:                        cprint(e1);
                   29457:                }
                   29458:                else
                   29459:                        eprint(e1);
                   29460:                puttok(base);
                   29461: 
                   29462:                if (t1 && t1!=t2 && e2->base!=ZERO) {
                   29463:                        // cast, but beware of int!=long etc.
                   29464:                cmp:
                   29465:                        switch (t1->base) {
                   29466:                        case TYPE:
                   29467:                                t1 = Pbase(t1)->b_name->tp;
                   29468:                                goto cmp;
                   29469:                        default:
                   29470:                         //        if (e2->base==NAME
                   29471:                         //        && Pname(e2)->n_evaluated==0
                   29472:                         //        && e2->tp->base==EOBJ)
                   29473:                         //                fprintf(out_file,"(int)");
                   29474:                                 break;
                   29475:                     //    case EOBJ:
                   29476:                     //           if (base==ASSIGN) goto cst;
                   29477:                     //          break;
                   29478:                        case PTR:
                   29479:                        case RPTR:
                   29480:                        case VEC:
                   29481:                                if (t2)
                   29482:                                        while ( t2->base == TYPE ) 
                   29483:                                                t2 = Pbase(t2)->b_name->tp;
                   29484: 
                   29485:                                if (e2->tp==0
                   29486:                                || (Pptr(t1)->typ!=Pptr(t2)->typ && t1->check(t2,0))) {
                   29487:                    //     cst:
                   29488:                                        putch('(');
                   29489:                                        bit oc = Cast;
                   29490:                                        Cast = 1;
                   29491:                                        e1->tp->print();
                   29492:                                        Cast = oc;
                   29493:                                        putch(')');     
                   29494:                                }
                   29495:                        }
                   29496:                }
                   29497: 
                   29498:                eprint(e2);
                   29499:                break;
                   29500:        }
                   29501: 
                   29502:        case DEREF:
                   29503:                if (e2) {
                   29504: 
                   29505:                        eprint(e1);
                   29506:                        putch('[');
                   29507:                        cprint(e2);
                   29508:                        putch(']');
                   29509:                }
                   29510:                else {
                   29511:                         putch('(');
                   29512:                        putch('*');
                   29513:                        eprint(e1);
                   29514:                         putch(')');
                   29515:                }
                   29516:                break;
                   29517: 
                   29518:        case ILIST:
                   29519:                puttok(LC);
                   29520:                if (e1) e1->print();
                   29521:                if (e2) {       // member pointer initiliazers
                   29522:                        puttok(CM);
                   29523:                        e2->print();
                   29524:                }
                   29525:                puttok(RC);
                   29526:                break;
                   29527: 
                   29528:        case ELIST:
                   29529:        {       Pexpr e = this;
                   29530:                for(;;) {
                   29531:                        if (e->base == ELIST) {
                   29532:                                e->e1->print();
                   29533:                                if (e = e->e2) {
                   29534:                                        puttok(CM);
                   29535:                                }
                   29536:                                else
                   29537:                                        return;
                   29538:                        }
                   29539:                        else {
                   29540:                                e->print();
                   29541:                                return;
                   29542:                        }
                   29543:                }
                   29544:        }
                   29545: 
                   29546:        case QUEST:
                   29547:        {       // look for (&a == 0) etc.
                   29548:                Neval = 0;
                   29549:                binary_val = 1;
                   29550:                long i = cond->eval();
                   29551:                binary_val = 0;
                   29552:                if (Neval == 0)
                   29553:                        (i?e1:e2)->print();
                   29554:                else {
                   29555:                        eprint(cond);
                   29556:                        putch('?');
                   29557:                        cprint(e1);
                   29558:                        putch(':');
                   29559:                        cprint(e2);
                   29560:                }
                   29561:                break;
                   29562:        }
                   29563: 
                   29564:        case CM:        // do &(a,b) => (a,&b) for previously checked inlines
                   29565:        case G_CM:
                   29566:                puttok(LP);
                   29567:                switch (e1->base) {
                   29568:                case ZERO:
                   29569:                case IVAL:
                   29570:                case ICON:
                   29571:                case NAME:
                   29572:                case MDOT:
                   29573:                case DOT:
                   29574:                case REF:
                   29575:                case FCON:
                   29576:                // case FVAL:
                   29577:                case STRING:
                   29578:                        goto le2;       // suppress constant a: &(a,b) => (&b)
                   29579:                default:
                   29580:                        {       int oo = addrof_cm;     // &(a,b) does not affect a
                   29581:                                addrof_cm = 0;
                   29582:                                eprint(e1);
                   29583:                                addrof_cm = oo;
                   29584:                        }
                   29585:                        puttok(CM);
                   29586:                le2:
                   29587:                        if (addrof_cm) {
                   29588:                                switch (e2->base) {
                   29589:                                case CAST:
                   29590:                                        if (e2->e2)
                   29591:                                        switch (e2->e2->base) {
                   29592:                                        case CM:
                   29593:                                        case G_CM:
                   29594:                                        case ICALL:     goto ec;
                   29595:                                        }
                   29596:                                case NAME:
                   29597:                                case MDOT:
                   29598:                                case DOT:
                   29599:                                case DEREF:
                   29600:                                case REF:
                   29601:                                case ANAME:
                   29602:                                        puttok(ADDROF);
                   29603:                                        addrof_cm--;
                   29604:                                        eprint(e2);
                   29605:                                        addrof_cm++;
                   29606:                                        break;
                   29607:                                case ICALL:
                   29608:                //              case CALL:
                   29609:                                case CM:
                   29610:                                case G_CM:
                   29611:                                ec:
                   29612:                                        eprint(e2);
                   29613:                                        break;
                   29614:                                case G_CALL:
                   29615:                                        /* & ( e, ctor() ) with temporary optimized away */
                   29616:                                        if (e2->fct_name
                   29617:                                        && e2->fct_name->n_oper==CTOR) {
                   29618:                                                addrof_cm--;
                   29619:                                                eprint(e2);
                   29620:                                                addrof_cm++;
                   29621:                                                break;
                   29622:                                        }
                   29623:                                default:
                   29624:                                        error('i',"& inlineF call (%k)",e2->base);
                   29625:                                }
                   29626:                        }
                   29627:                        else
                   29628:                        //      e2->print();
                   29629:                                eprint(e2);
                   29630:                        puttok(RP);
                   29631:                }
                   29632:                break;
                   29633: 
                   29634:        case UPLUS: // only preserved for ansi_opt==1
                   29635:        case UMINUS:
                   29636:        case NOT:
                   29637:        case COMPL:
                   29638:         //      puttok(base);
                   29639:         //      eprint(e2);
                   29640:         //      break;
                   29641:                 goto op2;
                   29642:        case ADDROF:
                   29643:        case G_ADDROF:
                   29644:                switch (e2->base) {     // & *e1 or &e1[e2]
                   29645:                case DEREF:
                   29646:                        if (e2->e2 == 0) {      // &*e == e
                   29647:                                e2->e1->print();
                   29648:                                return;
                   29649:                        }
                   29650:                        break;
                   29651:                case ICALL:
                   29652:                        addrof_cm++;    // assumes inline expanded into ,-expression
                   29653:                        eprint(e2);
                   29654:                        addrof_cm--;
                   29655:                        return;
                   29656:                case ASSIGN:            // &(a=b)       ??? works on many cc s
                   29657:                        eprint(e2);     // make sure it breaks!
                   29658:                        return;
                   29659:                case NAME: {
                   29660:                        Pname n = Pname(e2);
                   29661:                        if(n->n_evaluated) {
                   29662:                                n->n_evaluated=0;
                   29663:                                puttok(ADDROF);
                   29664:                                eprint(e2);
                   29665:                                n->n_evaluated=1;
                   29666:                                return;
                   29667:                        }
                   29668:                        break;
                   29669:                        }
                   29670:                }
                   29671: 
                   29672:                // suppress cc warning on &fct
                   29673:                if (e2->tp==0 || e2->tp->base!=FCT) puttok(ADDROF);
                   29674: 
                   29675:                eprint(e2);
                   29676:                break;
                   29677: 
                   29678:        case PLUS:
                   29679:        case MINUS:
                   29680:        case MUL:
                   29681:        case DIV:
                   29682:        case MOD:
                   29683:        case LS:
                   29684:        case RS:
                   29685:        case AND:
                   29686:        case OR:
                   29687:        case ER:
                   29688:        case ANDAND:
                   29689:        case OROR:
                   29690:         case DECR:
                   29691:         case INCR:
                   29692:                 cprint(e1);
                   29693:         op2:
                   29694:                puttok(base);
                   29695:                cprint(e2);
                   29696:                 break;
                   29697:        case ASOR:
                   29698:        case ASER:
                   29699:        case ASAND:
                   29700:        case ASPLUS:
                   29701:        case ASMINUS:
                   29702:        case ASMUL:
                   29703:        case ASMOD:
                   29704:        case ASDIV:
                   29705:        case ASLS:
                   29706:        case ASRS:
                   29707:                 eprint(e1);
                   29708:                 goto op2;
                   29709: 
                   29710:        default:
                   29711:                error('i',"%p->E::print%k",this,base);
                   29712:        //      fprintf(out_file," EEE(%d) ",base);
                   29713:        }
                   29714: }
                   29715: 
                   29716: Pexpr aval(Pname a)
                   29717: {
                   29718:        int argno = int(a->n_val);
                   29719:        Pin il;
                   29720:        for (il=curr_icall; il; il=il->i_next)
                   29721:                if (il->i_table == a->n_table) goto aok;
                   29722:        return 0;
                   29723: aok:
                   29724:        Pexpr aa = il->i_args[argno].arg;
                   29725: ll:
                   29726:        switch (aa->base) {
                   29727:        case CAST:      aa = aa->e1; goto ll;
                   29728:        case ANAME:     return aval(Pname(aa));
                   29729:        default:        return aa;
                   29730:        }
                   29731: }
                   29732: 
                   29733: #define putcond()      putch('('); e->print(); putch(')')
                   29734: 
                   29735: static loc csloc = { 0, 0 }; // loc of last stmt with line!=0
                   29736: 
                   29737: void stmt::print()
                   29738: {
                   29739: //error('d',"S::print %d:%k s %d s_list %d",this,base,s,s_list);
                   29740:        if (where.line == 0) {
                   29741:            if (csloc.line) csloc.putline();
                   29742:        } else {
                   29743:            csloc = where;
                   29744:            if (where.line!=last_line.line)
                   29745:                if (last_ll = where.line)
                   29746:                        where.putline();
                   29747:                else
                   29748:                        last_line.putline();
                   29749:        }
                   29750: 
                   29751:        if (memtbl && base!=BLOCK) { /* also print declarations of temporaries */
                   29752:                puttok(LC);
                   29753:                Ptable tbl = memtbl;
                   29754:                memtbl = 0;
                   29755:                int i;
                   29756:                int bl = 1;
                   29757:                for (Pname n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i)){
                   29758:                        if (n->tp == any_type) continue;
                   29759:                        /* avoid double declarartion of temporaries from inlines */
                   29760:                        char* s = n->string;
                   29761:                        if (s[0]!='_' || s[1]!='_' || s[2]!='X') {
                   29762:                                n->dcl_print(0);
                   29763:                                bl = 0;
                   29764:                        }
                   29765:                        Pname cn;
                   29766:                        if (bl
                   29767:                        && (cn=n->tp->is_cl_obj())
                   29768:                        && Pclass(cn->tp)->has_dtor()) bl = 0;
                   29769:                }
                   29770:                if ( last_ll==0 && (last_ll = where.line) )
                   29771:                        where.putline();
                   29772:                if (bl) {
                   29773:                        Pstmt sl = s_list;
                   29774:                        s_list = 0;
                   29775:                        print();
                   29776:                        memtbl = tbl;
                   29777:                        puttok(RC);
                   29778:                        if (sl) {
                   29779:                                s_list = sl;
                   29780:                                sl->print();
                   29781:                        }
                   29782:                }
                   29783:                else {
                   29784:                        print();
                   29785:                        memtbl = tbl;
                   29786:                        puttok(RC);
                   29787:                }
                   29788:                return;
                   29789:        }
                   29790: 
                   29791:        switch (base) {
                   29792:        default:
                   29793:                error('i',"S::print(base=%k)",base);
                   29794: 
                   29795:        case ASM:
                   29796:                fprintf(out_file,"asm(\"%s\");\n",(char*)e);
                   29797:                break;
                   29798: 
                   29799:        case DCL:
                   29800:                d->dcl_print(SM);
                   29801:                break;
                   29802: 
                   29803:        case BREAK:
                   29804:        case CONTINUE:
                   29805:                puttok(base);
                   29806:                puttok(SM);
                   29807:                break;
                   29808: 
                   29809:        case DEFAULT:
                   29810:                puttok(base);
                   29811:                //puttok(COLON);
                   29812:                putch(':');
                   29813:                s->print();
                   29814:                break;
                   29815: 
                   29816:        case SM:
                   29817:                if (e) {
                   29818:                        e->print();
                   29819:                        if (e->base==ICALL && e->e2) break;     /* a block: no SM */
                   29820:                }
                   29821:                puttok(SM);
                   29822:                break;
                   29823: 
                   29824:        case WHILE:
                   29825:                puttok(WHILE);
                   29826:                putcond();
                   29827:                if (s->s_list) {
                   29828:                        puttok(LC);
                   29829:                        s->print();
                   29830:                        puttok(RC);
                   29831:                }
                   29832:                else
                   29833:                        s->print();
                   29834:                break;
                   29835: 
                   29836:        case DO:
                   29837:                puttok(DO);
                   29838:                s->print();
                   29839:                puttok(WHILE);
                   29840:                putcond();
                   29841:                puttok(SM);
                   29842:                break;
                   29843: 
                   29844:        case SWITCH:
                   29845:                puttok(SWITCH);
                   29846:                putcond();
                   29847:                s->print();
                   29848:                break;
                   29849: 
                   29850:        case RETURN:
                   29851:                {
                   29852:                puttok(RETURN);
                   29853:                if (e) {
                   29854: //error('d',"print return rt %t etp %t",ret_tp,e->tp);
                   29855:                        if (ret_tp && ret_tp!=e->tp) {
                   29856:                                Ptype tt = ret_tp;
                   29857:                        gook:
                   29858:                                switch (tt->base) {
                   29859:                                case TYPE:
                   29860:                                        tt = Pbase(tt)->b_name->tp;
                   29861:                                        goto gook;
                   29862:                                case COBJ:
                   29863:                                        break;  // cannot cast to struct
                   29864:                                case RPTR:
                   29865:                                case PTR:
                   29866:                                        if (Pptr(tt)->typ==Pptr(e->tp)->typ) break;
                   29867:                                        if (Pptr(tt)->memof) break;
                   29868:                                default:
                   29869:                                        if (e->tp==0 || ret_tp->check(e->tp,0)) {
                   29870:                                                int oc = Cast;
                   29871:                                                putch('(');
                   29872:                                                Cast = 1;
                   29873:                                                ret_tp->print();
                   29874:                                                Cast = oc;
                   29875:                                                putch(')');
                   29876:                                        }
                   29877:                                }
                   29878:                        }
                   29879:                        eprint(e);
                   29880:                }
                   29881:                puttok(SM);
                   29882:                }
                   29883:                while (s_list && s_list->base==SM) s_list = s_list->s_list; // FUDGE!!
                   29884:                break;
                   29885: 
                   29886:        case CASE:
                   29887:                puttok(CASE);
                   29888:                eprint(e);
                   29889:                putch(':');
                   29890:                s->print();
                   29891:                break;
                   29892: 
                   29893:        case GOTO:
                   29894:                puttok(GOTO);
                   29895:                d->print();
                   29896:                puttok(SM);
                   29897:                break;
                   29898: 
                   29899:        case LABEL:
                   29900:                d->print();
                   29901:                putch(':');
                   29902:                s->print();
                   29903:                break;
                   29904: 
                   29905:        case IF:
                   29906:        {       int val = QUEST;
                   29907:                if (e->base == ANAME) {
                   29908:                        Pname a = Pname(e);
                   29909:                        Pexpr arg = aval(a);
                   29910: //error('d',"arg %d%k %d (%d)",arg,arg?arg->base:0,arg?arg->base:0,arg?arg->e1:0);
                   29911:                        if (arg)
                   29912:                                switch (arg->base) {
                   29913:                                case ZERO:      val = 0; break;
                   29914:                                case ADDROF:
                   29915:                                case G_ADDROF:  val = 1; break;
                   29916:                                case IVAL:      val = arg->i1!=0;
                   29917:                        }
                   29918:                }
                   29919: //error('d',"val %d",val);
                   29920:                switch (val) {
                   29921:                case 1:
                   29922:                        s->print();
                   29923:                        break;
                   29924:                case 0:
                   29925:                        if (else_stmt)
                   29926:                                else_stmt->print();
                   29927:                        else
                   29928:                                puttok(SM);     /* null statement */
                   29929:                        break;
                   29930:                default:
                   29931:                        puttok(IF);
                   29932:                        putcond();
                   29933:                        if (s->s_list) {
                   29934:                                puttok(LC);
                   29935:                                s->print();
                   29936:                                puttok(RC);
                   29937:                        }
                   29938:                        else
                   29939:                                s->print();
                   29940:                        if (else_stmt) {
                   29941:                                if (else_stmt->where.line == 0) {
                   29942:                                    if (csloc.line) csloc.putline();
                   29943:                                } else {
                   29944:                                    csloc = else_stmt->where;
                   29945:                                    if (else_stmt->where.line!=last_line.line)
                   29946:                                        if (last_ll = else_stmt->where.line)
                   29947:                                                else_stmt->where.putline();
                   29948:                                        else
                   29949:                                                last_line.putline();
                   29950:                                }
                   29951:                                puttok(ELSE);
                   29952:                                if (else_stmt->s_list) {
                   29953:                                        puttok(LC);
                   29954:                                        else_stmt->print();
                   29955:                                        puttok(RC);
                   29956:                                }
                   29957:                                else
                   29958:                                        else_stmt->print();
                   29959:                        }
                   29960:                }
                   29961:                break;
                   29962:        }
                   29963: 
                   29964:        case FOR:
                   29965:        {
                   29966:        //      int fi = for_init && ((for_init->base!=SM || for_init->memtbl || for_init->s_list);
                   29967:                int fi = 0;     // is the initializer statement an expression?
                   29968:                if (for_init) {
                   29969:                        fi = 1;
                   29970:                        if (for_init->memtbl==0 && for_init->s_list==0)
                   29971:                                if (for_init->base==SM)
                   29972:                                        if (for_init->e->base!=ICALL || for_init->e->e1)
                   29973:                                                fi = 0;
                   29974:                }
                   29975: //error('d',"for(; %d%k; %d%k)",e,e->base,e2,e2->base);
                   29976:                if (fi) {
                   29977:                        puttok(LC);
                   29978:                        for_init->print();
                   29979:                }
                   29980:                putstring("for(");
                   29981:                if (fi==0 && for_init) for_init->e->print();
                   29982:                putch(';');     // to avoid newline: not puttok(SM)
                   29983:                if (e) e->print();
                   29984:                putch(';');
                   29985:                if (e2) e2->print();
                   29986:                puttok(RP);
                   29987:                s->print();
                   29988:                if (fi) puttok(RC);
                   29989:                break;
                   29990:        }
                   29991: 
                   29992:        case PAIR:
                   29993:                if (s&&s2) {
                   29994:                        puttok(LC);
                   29995:                        s->print();
                   29996:                        s2->print();
                   29997:                        puttok(RC);
                   29998:                }
                   29999:                else {
                   30000:                        if (s) s->print();
                   30001:                        if (s2) s2->print();
                   30002:                }
                   30003:                break;
                   30004: 
                   30005:        case BLOCK:
                   30006:                puttok(LC);
                   30007: //error('d',"block %d d %d memtbl %d own_tbl %d",this,d,memtbl,own_tbl);
                   30008:                if (d) d->dcl_print(SM);
                   30009:                if (memtbl && own_tbl) {
                   30010:                        Pname n;
                   30011:                        int i;
                   30012:                        for (n=memtbl->get_mem(i=1); n; n=memtbl->get_mem(++i)) {
                   30013:                                if (n->tp && n->n_union==0 && n->tp!=any_type)
                   30014:                                        switch (n->n_scope) {
                   30015:                                        case ARGT:
                   30016:                                        case ARG:
                   30017:                                                break;
                   30018:                                        default:
                   30019: // error('d', "n: %s %k n_key: %k", n->string, n->base, n->n_key);
                   30020:                                                if ( n->base == TNAME && n->n_key == NESTED ) 
                   30021:                                                        continue; // printed from nested class
                   30022:                                                n->dcl_print(0);
                   30023:                                        }
                   30024:                        }
                   30025:                        if (last_ll==0 && s && (last_ll=s->where.line))
                   30026:                                s->where.putline();
                   30027:                }
                   30028:                if (s) s->print();
                   30029:                if (where2.line == 0) {
                   30030:                    if (csloc.line) csloc.putline();
                   30031:                } else {
                   30032:                    csloc = where2;
                   30033:                    if (where2.line!=last_line.line)
                   30034:                        if (last_ll = where2.line)
                   30035:                                where2.putline();
                   30036:                        else
                   30037:                                last_line.putline();
                   30038:                }
                   30039:                putstring("}\n");
                   30040:                if (last_ll && where.line) last_line.line++;
                   30041:        }
                   30042: 
                   30043:        if (s_list) s_list->print();
                   30044: }
                   30045: 
                   30046: /*
                   30047: void table::dcl_print(TOK s, TOK pub)
                   30048: 
                   30049: //     print the declarations of the entries in the order they were inserted
                   30050: //     ignore labels (tp==0)
                   30051: 
                   30052: {
                   30053:        register Pname* np;
                   30054:        register int i;
                   30055: 
                   30056:        if (this == 0) return;
                   30057: 
                   30058:        np = entries;
                   30059:        for (i=1; i<free_slot; i++) {
                   30060:                register Pname n = np[i];
                   30061:                switch (s) {
                   30062:                case 0:
                   30063:                        n->dcl_print(0);
                   30064:                        break;
                   30065:                case EQ:
                   30066:                        if (n->tp && n->n_scope == pub) n->dcl_print(0);
                   30067:                        break;
                   30068:                case NE:
                   30069:                        if (n->tp && n->n_scope != pub) n->dcl_print(0);
                   30070:                        break;
                   30071:                }
                   30072:        }
                   30073: }
                   30074: */
                   30075: 
                   30076: struct ptbl_rec {
                   30077:       char* pname;
                   30078:       char* vname;
                   30079:       ptbl_rec* next;
                   30080: };
                   30081: 
                   30082: static char* ptbl_name;
                   30083: static ptbl_rec* ptbl_rec_lookup_head = 0;
                   30084: static ptbl_rec* ptbl_rec_pair_head = 0;
                   30085: 
                   30086: void ptbl_init(int flag)
                   30087: {
                   30088:       if (!flag) {
                   30089:              char *p = st_name( "__ptbl_vec__" );      
                   30090:               ptbl_name = new char[strlen(p)+1];
                   30091:               strcpy(ptbl_name, p);                         
                   30092:               delete p;
                   30093:               fprintf(out_file, "extern struct __mptr* %s[];\n", ptbl_name);
                   30094:                if (last_ll) last_line.line++;
                   30095:       }
                   30096:       else {
                   30097:               ptbl_rec *r, *p = ptbl_rec_lookup_head;
                   30098:              if ( p == 0 ) return; // don't generate an empty object
                   30099:               fprintf(out_file, "struct __mptr* %s[] = {\n", ptbl_name);
                   30100:                if (last_ll) last_line.line++;
                   30101:               int i = 0;
                   30102:               while (p != 0) {
                   30103:                       r = ptbl_rec_pair_head;
                   30104:                       while (r && strcmp(r->pname, p->pname))
                   30105:                               r = r->next;
                   30106:                       fprintf(out_file, "%s,\n", r->vname);
                   30107:                        if (last_ll) last_line.line++;
                   30108:                       p = p->next;
                   30109:               }
                   30110:               // fprintf(out_file, "0\n};\n");
                   30111:               fprintf(out_file, "\n};\n");
                   30112:                if (last_ll) last_line.line += 2;
                   30113:       }
                   30114: }
                   30115: 
                   30116: char* ptbl_lookup(char *name)
                   30117: {
                   30118:       ptbl_rec *r, *s, *p = ptbl_rec_lookup_head;
                   30119:       int i = 0;
                   30120: 
                   30121:       while (p && strcmp(name, p->pname)) {
                   30122:               r = p;
                   30123:               p = p->next;
                   30124:               i++;
                   30125:       }
                   30126: 
                   30127:       if (p == 0) {
                   30128:               s = new ptbl_rec;
                   30129:               s->pname = new char[strlen(name) + 1];
                   30130:               s->vname = 0;
                   30131:               s->next = 0;
                   30132:               strcpy(s->pname, name);
                   30133:               if (ptbl_rec_lookup_head == 0) 
                   30134:                       ptbl_rec_lookup_head = s;
                   30135:               else r->next = s;
                   30136:       }
                   30137: 
                   30138:       char *pp = new char[ strlen(ptbl_name) + 10 ];   
                   30139:       sprintf(pp, "%s[%d]", ptbl_name, i);
                   30140:       return(pp);
                   30141: }
                   30142: 
                   30143: void ptbl_add_pair(char* ptbl, char* vtbl)
                   30144: {
                   30145: // error('d', "ptbl_add_pair: ptbl: %s, vtbl: %s", ptbl, vtbl );
                   30146:       ptbl_rec *p = new ptbl_rec;
                   30147: 
                   30148:       p->pname = new char[strlen(ptbl) + 1];
                   30149:       strcpy(p->pname, ptbl);
                   30150:       p->vname = new char[strlen(vtbl) + 1];
                   30151: 
                   30152:       strcpy(p->vname, vtbl);
                   30153:       p->next = ptbl_rec_pair_head;
                   30154: 
                   30155:       ptbl_rec_pair_head = p;
                   30156: }
                   30157: 0707071010112044411004440001630000160000010205600466055406600001100000140076print2.c/*ident   "@(#)ctrans:src/print2.c        1.4" */
                   30158: /**************************************************************************
                   30159: 
                   30160:        C++ source for cfront, the C++ compiler front-end
                   30161:        written in the computer science research center of Bell Labs
                   30162: 
                   30163:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   30164:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   30165: 
                   30166: print2.c:
                   30167: 
                   30168:        print names and declarations
                   30169: 
                   30170: ****************************************************************************/
                   30171: 
                   30172: #include "cfront.h"
                   30173: #include "template.h"
                   30174: 
                   30175: bit Cast;
                   30176: int last_ll = 1;
                   30177: Pin curr_icall;
                   30178: char emode;
                   30179: int ntok;
                   30180: 
                   30181: static int MAIN;       // fudge to get _main() called by main()
                   30182: 
                   30183: #define eprint(e) if (e) Eprint(e)
                   30184: 
                   30185: #ifdef DENSE
                   30186: void chop(char*);
                   30187: #endif
                   30188: 
                   30189: void puttok(TOK t)
                   30190: /*
                   30191:        print the output representation of "t"
                   30192: */
                   30193: {
                   30194: //     if (t<=0 || MAXTOK<t) error("illegal token %d",t);
                   30195: //     char* s = keys[t];
                   30196: //     if (s == 0) error("V representation token %d",t);
                   30197: 
                   30198:        putstring(keys[t]);
                   30199: 
                   30200:        if (12<ntok++) {
                   30201:                ntok = 0;
                   30202:                last_line.putline();
                   30203:        }
                   30204:        else if (t == SM) {
                   30205:                ntok = 0;
                   30206:                putch('\n');
                   30207:                if (last_ll) last_line.line++;
                   30208:        }
                   30209:        else
                   30210:                putch(' ');
                   30211: }
                   30212: 
                   30213: #define MX     20
                   30214: #define NTBUF  10
                   30215: class dcl_buf {
                   30216:        /*
                   30217:                buffer for assembling declaration (or cast)
                   30218:                left contains CONST_PTR => *CONST
                   30219:                             CONST_RPTR => &CONST
                   30220:                                PTR     => *
                   30221:                                RPTR    => &
                   30222:                                LP      => (
                   30223:                right contains  RP      => )
                   30224:                                VEC     => [ rnode ]
                   30225:                                FCT     => ( rnode )
                   30226:                                FIELD   => : rnode
                   30227:        */
                   30228:        Pbase b;
                   30229:        Pname n;
                   30230:        TOK left[MX], right[MX];
                   30231:        Pnode   rnode[MX];
                   30232:        Pclass  lnode[MX];
                   30233:        int li, ri;
                   30234: public:
                   30235:        void    init(Pname nn)          { b=0; n=nn; li=ri=0; }
                   30236:        void    base(Pbase bb)          { b = bb; }
                   30237:        void    front(TOK t)            { left[++li] = t; }
                   30238:        void    front(Pclass c)         { left[++li] = MEMPTR; lnode[li] = c; }
                   30239:        void    back(TOK t, Pnode nod)  { right[++ri] = t; rnode[ri] = nod; }
                   30240:        void    paran()                 { front(LP); back(RP,0); }
                   30241:        void    put();
                   30242: } *tbufvec[NTBUF] = {0}, *tbuf = 0;
                   30243: 
                   30244: int freetbuf = 0;
                   30245: 
                   30246: void dcl_buf::put()
                   30247: {
                   30248:        int i;
                   30249:        Pfct ff = 0;
                   30250: 
                   30251:        if (MX<=li || MX<=ri) error('i',"T buffer overflow");
                   30252:        if (b == 0) error('i',"noBT%s",Cast?" in cast":"");
                   30253: 
                   30254:        if (n && n->n_sto && n->n_sto!=REGISTER) puttok(n->n_sto);
                   30255: 
                   30256:        b->dcl_print();
                   30257:        
                   30258:        for( ; li; li--) {
                   30259:                switch (left[li]) {
                   30260:                case LP:
                   30261:                        putch('(');
                   30262:                        break;
                   30263:                case PTR:
                   30264:                        putch('*');
                   30265:                        break;
                   30266:                case RPTR:
                   30267:                        if (emode)
                   30268:                                putch('&');
                   30269:                        else
                   30270:                                putch('*');
                   30271:                        break;
                   30272:                case CONST_PTR:
                   30273:                        if (emode)
                   30274:                                putstring("*const ");
                   30275:                        else
                   30276:                                putch('*');
                   30277:                        break;
                   30278:                case CONST_RPTR:
                   30279:                        if (emode)
                   30280:                                putstring("&const ");
                   30281:                        else
                   30282:                                putch('*');
                   30283:                        break;
                   30284:                case MEMPTR:
                   30285:                        if (lnode[li]) fprintf(out_file,"%s::",lnode[li]->string);
                   30286:                }
                   30287:        }
                   30288: 
                   30289:        if (n) n->print();
                   30290: 
                   30291:        for(i=1; i<=ri; i++) {
                   30292:                switch (right[i]) {
                   30293:                case RP:
                   30294:                        putch(')');
                   30295:                        break;
                   30296:                case VEC:
                   30297:                        putch('[');
                   30298:                        {       Pvec v = (Pvec) rnode[i];
                   30299:                                Pexpr d = v->dim;
                   30300:                                int s = v->size;
                   30301:                                if (d) d->print();
                   30302:                                if (s) fprintf(out_file,"%d",s);
                   30303:                        }
                   30304:                        putch(']');
                   30305:                        break;
                   30306:                case FCT:       // beware of function returning pointer to
                   30307:                                // function expressed witout typedef
                   30308:                {       Pfct f = Pfct(rnode[i]);
                   30309:                        if (f->body) ff = f;
                   30310:                        f->dcl_print();
                   30311:                        break;
                   30312:                }
                   30313:                case FIELD:
                   30314:                 {       Pbase f = (Pbase) rnode[i];
                   30315:                         Pexpr d = (Pexpr)f->b_name;
                   30316:                         int s = f->b_bits;
                   30317:                         putch(':');
                   30318:                         if (d)
                   30319:                                 d->print();
                   30320:                         else if (s)
                   30321:                                 fprintf(out_file,"%d",s);
                   30322:                         else
                   30323:                                 puttok(ZERO);
                   30324:                         break;
                   30325:                 }
                   30326:                }
                   30327:        }
                   30328: void print_body(Pfct);
                   30329:        if (ff && emode==0) print_body(ff);
                   30330: }
                   30331: 
                   30332: static Pexpr mk_zero_init( Ptype tt, Pname obname, Pname currname )
                   30333: /*
                   30334:        creates 0 initializer for defined objects
                   30335:        side effect: generates right nesting level for {}
                   30336: */
                   30337: {
                   30338: zaq:
                   30339:        switch (tt->base) {
                   30340:        case TYPE:
                   30341:                tt = Pbase(tt)->b_name->tp; goto zaq;
                   30342:        case VEC: // type a[size]; => type a[size] = {0};
                   30343:        {
                   30344:                if ( obname == currname ) {
                   30345:                //xxx initializing vectors blows up the size of some programs
                   30346:                        return 0;
                   30347:                } else {
                   30348:                        Pexpr i = mk_zero_init(Pvec(tt)->typ,obname,currname);
                   30349:                        if ( i == 0 ) return 0;
                   30350:                        return new expr( ILIST, i, 0 );
                   30351:                }
                   30352:        }
                   30353:        case COBJ: // "X a;" == "X a = {0};"
                   30354:        {
                   30355:                Pclass cl = Pclass(Pbase(tt)->b_name->tp);
                   30356:                if ( !ansi_opt && (cl->csu == ANON || cl->csu == UNION) ) {
                   30357:                    if ( warning_opt ) {
                   30358:                        // ridiculous handstands to avoid printing
                   30359:                        // compiler generated names in warning
                   30360:                        Ptype tn = obname->tp;
                   30361:                        for(;;) if(tn->base==VEC) tn=Pvec(tn)->typ; else break;
                   30362:                        if ( obname == currname && tt == tn ) {
                   30363:                            if ( cl->string[0]=='_' && cl->string[1]=='_' )
                   30364:                                error('w',&obname->where,"cannot generate zeroIr for%n ofT union; toI, compile with +a1 or insert non-union object as first member",obname);
                   30365:                            else
                   30366:                                error('w',&obname->where,"cannot generate zeroIr for%n ofT%t; toI, compile with +a1 or insert non-union object as first member",obname,obname->tp);
                   30367:                        } else { Pclass cx;
                   30368:                            if ( tn->base == COBJ
                   30369:                            &&   (cx=(Pclass)Pbase(tn)->b_name->tp,
                   30370:                                  cx->string[0]=='_' && cx->string[1]=='_') )
                   30371:                                error('w',&obname->where,"cannot generate zeroIr for%n (union or aggregate with union as first element); toI, compile with +a1 or insert non-union object as first member",obname);
                   30372:                            else
                   30373:                                error('w',&obname->where,"cannot generate zeroIr for%n ofT%t (union or aggregate with union as first element); toI, compile with +a1 or insert non-union object as first member",obname,obname->tp);
                   30374:                        }
                   30375:                    } // if warning_opt
                   30376:                    return 0;
                   30377:                }
                   30378:                Pbcl l = cl->baselist;
                   30379:                while ( l ) {
                   30380:                        if ( l->base == NAME ) cl = l->bclass;
                   30381:                        else return new expr(ILIST,zero,0);
                   30382:                        l = cl->baselist;
                   30383:                }
                   30384:                int i = 1;
                   30385:                Pname nn = cl->memtbl->get_mem(i);
                   30386:                for ( ;  nn;  nn = cl->memtbl->get_mem(++i) ) {
                   30387:                        Ptype tx = nn->tp;
                   30388:                        while ( tx->base == TYPE ) tx = Pbase(tx)->b_name->tp;
                   30389:                        if (nn->base==NAME
                   30390:                        && nn->n_union==0
                   30391:                        && tx->base!=FCT
                   30392:                        && tx->base!=OVERLOAD
                   30393:                        && tx->base!=CLASS
                   30394:                        && tx->base!=ENUM
                   30395:                        && nn->n_stclass != STATIC) {
                   30396:                                Pexpr i = mk_zero_init(tx,obname,nn);
                   30397:                                if ( i == 0 ) return 0;
                   30398:                                return new expr(ILIST,i,0);
                   30399:                        }
                   30400:                }
                   30401:                return 0;
                   30402:        }
                   30403:        case PTR:
                   30404:                if (tt->memptr()) {
                   30405:                        Pexpr i = new expr(ELIST,zero,zero);
                   30406:                        return new expr(ILIST,i,zero);
                   30407:                }
                   30408:                // no break
                   30409:        case RPTR:
                   30410:        case CHAR:
                   30411:        case SHORT:
                   30412:        case INT:
                   30413:        case EOBJ:
                   30414:        case LONG:
                   30415:        case FLOAT:
                   30416:        case DOUBLE:
                   30417:        case LDOUBLE:   // "int a;" == "int a = 0;"
                   30418:        case FIELD:
                   30419:        case ANY:
                   30420:                return zero;
                   30421:        }
                   30422:        return 0;
                   30423: }
                   30424: 
                   30425: void name::dcl_print(TOK list)
                   30426: /*
                   30427:        Print the declaration for a name (list==0) or a name list (list!=0):
                   30428:                For each name
                   30429:                (1) print storage class
                   30430:                (2) print base type
                   30431:                (3) print the name with its declarators
                   30432:        Avoid (illegal) repetition of basetypes which are class or enum declarations
                   30433:        (A name list may contain names with different base types)
                   30434:        list == SM :    terminator SM
                   30435:        list == 0:      single declaration with terminator SM
                   30436:        list == CM :    separator CM
                   30437: */
                   30438: {
                   30439:        if (error_count) return;
                   30440: 
                   30441:        for (Pname n=this; n; n=n->n_list) {
                   30442:                Ptype t = n->tp;
                   30443:                int sm = 0;
                   30444: 
                   30445: // error('d',"%s->dcl_print() tp %t sto %k",n->string,t,n->n_sto);
                   30446:                if (t == 0) error('i',"N::dcl_print(%n)T missing",n);
                   30447: 
                   30448:                if (n->n_stclass==ENUM) if (list) continue; else return;
                   30449: 
                   30450:                if (n->where.line!=last_line.line || n->where.file!=last_line.file)
                   30451: //fprintf(stderr,"%s ",n->string?n->string:"<0>"); n->where.put(stderr); fprintf(stderr,"  last "); last_line.put(stderr); putc('\n',stderr);
                   30452:                        if (last_ll = n->where.line)
                   30453:                                n->where.putline();
                   30454:                        else
                   30455:                                last_line.putline();
                   30456:        
                   30457:                int tc = Pbase(t)->b_const;
                   30458:                for (Ptype tt = t; tt->base==TYPE; tt = Pbase(tt)->b_name->tp)
                   30459:                        tc |= Pbase(tt)->b_const;
                   30460:  
                   30461:                switch (t->base) {
                   30462:                case CLASS:
                   30463: //fprintf(stderr,"class %s->dcl_print()\n",n->string);
                   30464:                        if (n->base != TNAME) {
                   30465:                                Pclass(t)->dcl_print(n);
                   30466:                                sm = 1;
                   30467:                        }
                   30468:                        break;
                   30469: 
                   30470:                case ENUM:
                   30471:                         Penum(t)->dcl_print(0);
                   30472:                        sm = 1;
                   30473:                        break;
                   30474: 
                   30475:                case FCT:
                   30476:                {       Pfct f = Pfct(t);
                   30477: 
                   30478:                        if (n->base == TNAME) puttok(TYPEDEF);
                   30479: 
                   30480: // error('d',"fct %n->dcl_print() printed %d body %d defined %d",n,n->n_dcl_printed,f->body,f->defined);
                   30481: // error('d',"n %d tbl %d tp %t inline %d",n,n->n_table,n->tp,f->f_inline);
                   30482:                        if (n->n_dcl_printed==2 // definition already printed
                   30483:                        || (n->n_dcl_printed==1 && f->body==0)
                   30484:                                                // declaration already printed
                   30485:                        ) {
                   30486:                                // don't print again
                   30487:                                sm = 1; // no SM
                   30488:                                break;
                   30489:                        }
                   30490: 
                   30491:                        if (f->f_result == 0) make_res(f);
                   30492: 
                   30493:                        if (f->body && n->n_sto==EXTERN) n->n_sto = 0;
                   30494: 
                   30495:                        if (f->f_inline && ((n->n_table!=gtbl) || strcmp(n->string,"main"))) {
                   30496:                                if (debug_opt)  {
                   30497: //error('d',"f %t defined %d inline %d",f,f->defined,f->f_inline);
                   30498:                                        if (f->defined&DEFINED
                   30499:                                        && f->defined&SIMPLIFIED
                   30500:                                        && f->f_inline!=ITOR)
                   30501:                                                goto prnt_def;
                   30502:                                        else if (n->n_dcl_printed==0)
                   30503:                                                goto prnt_dcl;
                   30504:                                        else {
                   30505:                                                sm = 1;
                   30506:                                                break;
                   30507:                                        }
                   30508:                                }
                   30509:                                if (f->f_virtual || n->n_addr_taken) {
                   30510:                                prnt_dcl:
                   30511: //error('d',"prnt_dcl %d %n %k",n,n,n->n_sto);
                   30512:                                        TOK st = n->n_sto;
                   30513:                                        Pblock b = f->body;
                   30514:                                        f->body = 0;
                   30515:                                        t->dcl_print(n);
                   30516:                                        n->n_dcl_printed = 1;
                   30517:                                        n->n_sto = st;
                   30518:                                        f->body = b;
                   30519:                                        break;
                   30520:                                }
                   30521:                                else
                   30522:                                        sm = 1; // no SM
                   30523:                        }
                   30524:                        else if ((f->defined&DEFINED)==0
                   30525:                                || (f->defined&SIMPLIFIED)==0)
                   30526:                                goto prnt_dcl;
                   30527:                        else if (n->n_table==gtbl && strcmp(n->string,"main")==0) {
                   30528:                                if (f->f_inline) {
                   30529:                                        if (warning_opt) {
                   30530:                                                error('w',"main() cannot be inlined");
                   30531:                                                error('w',"out-of-line copy of main() created");
                   30532:                                        }
                   30533:                                        n->n_sto=0;
                   30534:                                }
                   30535:                                MAIN = 1;
                   30536:                                gtbl->look("main",0)->use();
                   30537:                                f->f_signature = 0;
                   30538:                                t->dcl_print(n);
                   30539:                                n->n_dcl_printed = f->body?2:1;
                   30540:                                MAIN = 0;
                   30541:                        }
                   30542:                        else {
                   30543:                        prnt_def:
                   30544: // error('d',"prnt_def %n %k %d %k",n,n->n_oper,n,n->n_sto);
                   30545:                                if (n->n_oper==CTOR || n->n_oper==DTOR) {
                   30546:                                        Pclass cl = Pclass(n->n_table->t_name->tp);
                   30547:                                        if (cl->c_body == 3) cl->print_all_vtbls(cl);
                   30548:                                }
                   30549: 
                   30550:                                if ( n->n_sto == STATIC && 
                   30551:                                        pdef_name == 0 && def_name == 0 ) {
                   30552: // error('d', "printing ptbl_vec without first definition" );
                   30553:                                                pdef_name = n;
                   30554:                                                ptbl_init(0);
                   30555:                                }
                   30556:                                t->dcl_print(n);
                   30557:                                n->n_dcl_printed = f->body?2:1;
                   30558:                        }
                   30559:                        if (f->body) sm = 1;
                   30560:                        break;
                   30561:                }
                   30562: 
                   30563:                case OVERLOAD:
                   30564:                {
                   30565:                        for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) {
                   30566:                                Pname nn = gl->f;
                   30567:                                nn->dcl_print(0);
                   30568:                                sm = 1;
                   30569:                        }
                   30570:                        break;
                   30571:                }
                   30572: 
                   30573:                case ASM:
                   30574:                        fprintf(out_file,"asm(\"%s\")\n",(char*)Pbase(t)->b_name);
                   30575:                        break;
                   30576: 
                   30577:                case INT:
                   30578:                case EOBJ:
                   30579:                case CHAR:
                   30580:                case LONG:
                   30581:                case SHORT:
                   30582:                tcx:
                   30583:                        // do not allocate space for constants unless necessary
                   30584:                        if (tc
                   30585:                        && n->n_sto!=EXTERN     // extern const one;
                   30586:                                                // const one = 1;
                   30587:                                                // allocates storage
                   30588:                        && (n->n_scope==EXTERN  // FUDGE const one = 1;
                   30589:                                                // is treated as static
                   30590:                                                // need loader support
                   30591:                                || n->n_scope==STATIC
                   30592:                                || n->n_scope==FCT)
                   30593:                        ) {
                   30594:                                if (n->n_evaluated && n->n_addr_taken==0) {
                   30595:                                        sm = 1; /* no ; */
                   30596:                                        break;
                   30597:                                }
                   30598:                        }
                   30599:                        tc = 0;
                   30600:                        // no break;
                   30601: 
                   30602:                default:
                   30603:                {
                   30604: /*     
                   30605: //  don't print local instance of const
                   30606:                        if ( n->n_dcl_printed == 3 ) {
                   30607:                                sm = 1;
                   30608:                                break;
                   30609:                        }
                   30610: */
                   30611:                        Pexpr i = n->n_initializer;
                   30612:                        if (n->base == TNAME && n->n_key == NESTED) i = 0;
                   30613:                        if (tc) {
                   30614:                                switch (tt->base) {
                   30615:                                case CHAR:
                   30616:                                case SHORT:
                   30617:                                case INT:
                   30618:                                case LONG:
                   30619:                                case EOBJ:
                   30620:                                        goto tcx;
                   30621:                                }
                   30622:                        }
                   30623: 
                   30624:                        if (n->base == TNAME) {
                   30625:                                /* Always print template formals, even when they have the same 
                   30626:                         * formal name, since the instantiation name is different. This 
                   30627:                         * fix should not be required when the copy mechanism is in place. */
                   30628:                                if (! n_template_arg)
                   30629:                                        for (Pname tn=ktbl->look(n->string,HIDDEN); tn; tn=tn->n_tbl_list) 
                   30630:                                                if (tn && tn->lex_level && t==tn->tp) return;
                   30631:                                puttok(TYPEDEF);
                   30632:                        }
                   30633: 
                   30634:                        if (n->n_stclass == REGISTER) {
                   30635:                                // (imperfect) check against member functions
                   30636:                                // register s a; a.f() illegal
                   30637:                                Pname cln = n->tp->is_cl_obj();
                   30638:                                if (cln) {
                   30639:                                        Pclass cl = Pclass(cln->tp);
                   30640:                                        if (cl->csu!=CLASS
                   30641:                                        && cl->baselist==0
                   30642:                                        && cl->has_itor()==0
                   30643:                                        && cl->virt_count==0) puttok(REGISTER);
                   30644:                                }
                   30645:                                else
                   30646:                                        puttok(REGISTER);
                   30647:                        }
                   30648: 
                   30649:                        if (i) {
                   30650:                                if (n->n_sto==EXTERN && n->n_stclass==STATIC) {
                   30651:                                        n->n_initializer = 0;
                   30652:                                        t->dcl_print(n);
                   30653:                                        puttok(SM);
                   30654:                                        n->n_initializer = i;
                   30655:                                        n->n_sto = 0;
                   30656:                                        t->dcl_print(n);
                   30657:                                        n->n_sto = EXTERN;
                   30658:                                }
                   30659:                                else
                   30660:                                        t->dcl_print(n);
                   30661:                                if(n->n_table) {
                   30662:                                        Pname nn = n->n_table->look(n->string,0);
                   30663:                                        if(nn)
                   30664:                                                nn->n_dcl_printed = 1;
                   30665:                                        else
                   30666:                                                n->n_dcl_printed = 1;
                   30667:                                }
                   30668:                                else
                   30669:                                        n->n_dcl_printed = 1;
                   30670:                        }
                   30671:                        else if (n->n_evaluated && Pbase(t)->b_const) {
                   30672:                                if (n->n_sto==EXTERN && n->n_stclass==STATIC) {
                   30673:                                        int v = n->n_evaluated;
                   30674:                                        n->n_evaluated = 0;
                   30675:                                        t->dcl_print(n);
                   30676:                                        puttok(SM);
                   30677:                                        if (n->where.line!=last_line.line || n->where.file!=last_line.file)
                   30678:                                                if (last_ll = n->where.line)
                   30679:                                                        n->where.putline();
                   30680:                                                else
                   30681:                                                        last_line.putline();
                   30682:                                        n->n_evaluated = v;
                   30683:                                        n->n_sto = 0;
                   30684:                                        t->dcl_print(n);
                   30685:                                        n->n_sto = EXTERN;
                   30686:                                }
                   30687:                                else
                   30688:                                        t->dcl_print(n);
                   30689:                                if(n->n_table) {
                   30690:                                        Pname nn = n->n_table->look(n->string,0);
                   30691:                                        if(nn)
                   30692:                                                nn->n_dcl_printed = 1;
                   30693:                                        else
                   30694:                                                n->n_dcl_printed = 1;
                   30695:                                }
                   30696:                                else
                   30697:                                        n->n_dcl_printed = 1;
                   30698:                        }
                   30699:                        else {
                   30700: //error('d',"%n sto %k val %d stc %k",n,n->n_sto,n->n_val,n_stclass);
                   30701:                                if ((n->n_sto==0 || (n->n_val && n->n_evaluated==0))
                   30702:                                 && n_stclass==STATIC
                   30703:                                && n->n_sto!=STATIC
                   30704:                                 && n->n_table==gtbl) {
                   30705:                                         if (n->n_val && n->n_evaluated==0) { 
                   30706:                                                 // extern x = f();
                   30707:                                                 // generate int x = 0;       
                   30708:                                                 // plus dynamic initialization
                   30709:                                                 n->n_sto = 0;
                   30710:                                         }
                   30711: 
                   30712:                                        n->n_initializer = i = mk_zero_init(t,n,n);
                   30713:                                }
                   30714:                                t->dcl_print(n);
                   30715:                                if(n->n_table) {
                   30716:                                        Pname nn = n->n_table->look(n->string,0);
                   30717:                                        if(nn)
                   30718:                                                nn->n_dcl_printed = 1;
                   30719:                                        else
                   30720:                                                n->n_dcl_printed = 1;
                   30721:                                }
                   30722:                                else
                   30723:                                        n->n_dcl_printed = 1;
                   30724:                        }
                   30725: 
                   30726:                        if (n->n_scope!=ARG) {
                   30727:                                if (i) {
                   30728:                                        puttok(ASSIGN);
                   30729: 
                   30730:                                        Pexpr i2 = i;
                   30731:                                        while (i2->base == CAST) i2 = i2->e1;
                   30732:                                        if (i2->base == ILIST) i = i2;
                   30733:                                        if (t!=i->tp
                   30734:                                        && i->base!=ZERO
                   30735:                                        && i->base!=ILIST /*&& i->tp!=Pchar_type*/) {
                   30736:                                                Ptype t1 = n->tp;
                   30737:                                        cmp:
                   30738:                                                switch (t1->base) {
                   30739:                                                case TYPE:      
                   30740:                                                        t1 = Pbase(t1)->b_name->tp;
                   30741:                                                        goto cmp;
                   30742:                                                default:
                   30743:                                                        i->print();
                   30744:                                                        break;
                   30745:                                        //      case EOBJ:
                   30746:                                        //              goto cst;
                   30747:                                                case VEC:
                   30748:                                                        if (Pvec(t1)->typ->base==CHAR) {
                   30749:                                                                i->print();
                   30750:                                                                break;
                   30751:                                                        }
                   30752:                                                        // no break
                   30753:                                                case PTR:
                   30754:                                                case RPTR:
                   30755:                                                        if (i->tp==0 || n->tp->check(i->tp,0)) {
                   30756:                                           //      cst:
                   30757:                                                                putch('(');
                   30758:                                                                bit oc = Cast;
                   30759:                                                                Cast = 1;
                   30760:                                                                t->print();
                   30761:                                                                Cast = oc;
                   30762:                                                                putch(')');
                   30763:                                                        }
                   30764:                                                        eprint(i);
                   30765:                                                }
                   30766:                                        }
                   30767:                                        else {
                   30768:                                                if (i==zero) {
                   30769:                                                        while (t->base == TYPE) t = Pbase(t)->b_name->tp;
                   30770:                                        //              if (t->base == EOBJ) {
                   30771:                                        //                      putch('(');
                   30772:                                        //                      bit oc = Cast;
                   30773:                                        //                      Cast = 1;
                   30774:                                        //                      t->print();
                   30775:                                        //                      Cast = oc;
                   30776:                                        //                      putch(')');
                   30777:                                        //              }
                   30778:                                                }
                   30779:                                                eprint(i);
                   30780:                                                
                   30781:                                        //      i->print();
                   30782:                                        }
                   30783:                                }
                   30784:                                else if (n->n_evaluated) {
                   30785:                                        puttok(ASSIGN);
                   30786:                                        if (n->tp->base!=INT || n->tp->is_unsigned()) {
                   30787:                                                putstring("((");
                   30788:                                                bit oc = Cast;
                   30789:                                                Cast = 1;
                   30790:                                                n->tp->print();
                   30791:                                                Cast = oc;
                   30792:                                                fprintf(out_file,")%d)",n->n_val);
                   30793:                                        }
                   30794:                                        else
                   30795:                                                fprintf(out_file,"%d",n->n_val);
                   30796:                                }
                   30797:                        }
                   30798:                }
                   30799:                }
                   30800: 
                   30801:                switch (list) {
                   30802:                case SM:
                   30803:                        if (sm==0) puttok(SM);
                   30804:                        break;
                   30805:                case 0:
                   30806:                        if (sm==0) puttok(SM);
                   30807:                        return;
                   30808:                case CM:
                   30809:                        if (n->n_list) puttok(CM);
                   30810:                        break;
                   30811:                }
                   30812:        }
                   30813: } 
                   30814: 
                   30815: char *local_sign( Ptype pt )
                   30816: { // get function signature for local class
                   30817:        char buf[1024];
                   30818:        char* bb = pt->signature(buf);
                   30819:        int ll = bb-buf;
                   30820:        if (1023 < ll) error('i',"local class N buffer overflow");
                   30821:        char *p = new char[ll+1];
                   30822:        strcpy(p,buf);
                   30823:        return p;
                   30824: }
                   30825: 
                   30826: void enumdef::dcl_print(Pname cln)
                   30827: /*
                   30828: */
                   30829: {
                   30830:        // note: ***** modify to handle local enums 
                   30831: // error('d', "%t::dcl_print(%n) in_class: %t nested_sig: %s", this, cln, in_class, nested_sig );
                   30832:        char* s = nested_sig?nested_sig:(cln ? cln->string:0);
                   30833:        if ( nested_sig )
                   30834:                fprintf(out_file,"enum __%s { ",nested_sig);
                   30835:        else fprintf(out_file,"enum %s { ",string);
                   30836: 
                   30837:        for (Pname px, p=mem; p; p=px) {
                   30838:                px = p->n_list;
                   30839:                if (s) {
                   30840:                        if (p->n_evaluated)
                   30841:                                fprintf(out_file,"%s__%s = %d",p->string,s,p->n_val);
                   30842:                        else
                   30843:                                fprintf(out_file,"%s__%s",p->string,s);
                   30844:                }
                   30845:                else {
                   30846:                        if (p->n_evaluated)
                   30847:                                fprintf(out_file,"%s = %d",p->string,p->n_val);
                   30848:                        else
                   30849:                                fprintf(out_file,"%s",p->string);
                   30850:                }
                   30851:                if (px) puttok(CM);
                   30852:                p->n_initializer = 0;
                   30853:                delete p;
                   30854:        }
                   30855:        mem = 0;
                   30856:        puttok(RC);
                   30857:        puttok(SM);
                   30858: }
                   30859: 
                   30860: void name::print()
                   30861: { // print just the name itself
                   30862:        if (this == 0) error('i',"0->N::print()");
                   30863:        if (string == 0) {
                   30864:                if (emode) putch('?');
                   30865:                return;
                   30866:        }
                   30867: 
                   30868: // error( 'd', "%s->name::print(), base: %k", string, base );
                   30869:        switch (base) {
                   30870:        case TNAME:
                   30871:                if (n_key == NESTED && tpdef &&
                   30872:                        tpdef->nested_sig) {
                   30873:                        if ( emode == 0 ) {
                   30874:                                putstring( " __" );
                   30875:                                putst(tpdef->nested_sig);
                   30876:                        }
                   30877:                        else {
                   30878:                                putst(tpdef->in_class->string);
                   30879:                                putstring( "::" );
                   30880:                                putst(string);
                   30881:                        }
                   30882:                        return;
                   30883:                }
                   30884: 
                   30885:                if (emode && tp) {
                   30886:                        if (n_template_arg_string) {
                   30887:                                tp->dcl_print(0); return;
                   30888:                        } else
                   30889:                        if(tp->base == COBJ) {
                   30890:                                Pclass cl = Pclass(Pbase(tp)->b_name->tp);
                   30891:                                if(cl && cl->base == CLASS && 
                   30892:                                  (cl->class_base == instantiated_template_class)) {
                   30893:                                        Ptclass(cl)->inst->print_pretty_name(); return;
                   30894:                                }
                   30895:                        }
                   30896:                }
                   30897: 
                   30898:                putst(n_template_arg_string ? n_template_arg_string : string);
                   30899:                return;
                   30900: 
                   30901:        case MDOT:
                   30902:                Pexpr(this)->print();
                   30903:                return;
                   30904:        }
                   30905: 
                   30906:        if (emode) {
                   30907:                Ptable tbl;
                   30908:                char* cs = 0;
                   30909:                bit f = 0;
                   30910:                if (tp) {
                   30911:                        switch (tp->base) {
                   30912:                        case OVERLOAD:
                   30913:                        case FCT:
                   30914:                                f = 1;
                   30915:                        default:
                   30916:                                if (tbl=n_table) {
                   30917:                                        if (tbl == gtbl) {
                   30918:                                                if (f == 0) putstring("::");
                   30919:                                        }
                   30920:                                        else {
                   30921:                                                if (tbl->t_name) {
                   30922:                                                        Ptclass pc = Ptclass(tbl->t_name->tp);
                   30923:                                                        cs = tbl->t_name->string;
                   30924:                                                        if ((pc->base == CLASS)  && 
                   30925:                                                                (pc->class_base == instantiated_template_class))
                   30926:                                                                        pc->inst->print_pretty_name();
                   30927:                                                        else fprintf(out_file,"%s",cs);
                   30928:                                                        fprintf (out_file, "::") ;
                   30929:                                                }
                   30930:                                        }
                   30931:                                }
                   30932: 
                   30933:                                if (n_scope==ARG && strcmp(string,"this")==0) {
                   30934:                                        // tell which "this" it is
                   30935:                                        Ptype tt = Pptr(tp)->typ;
                   30936:                                        Pname cn = Pbase(tt)->b_name;
                   30937:                                        fprintf(out_file,"%s::",cn->string);
                   30938:                                }
                   30939: 
                   30940:                        case CLASS:
                   30941:                        case ENUM:
                   30942:                //      case TYPE:
                   30943:                                break;
                   30944:                        }
                   30945:                nop:
                   30946:                        switch (n_oper) {
                   30947:                        case TYPE:
                   30948:                                putstring("operator ");
                   30949:                                if (tp) Pfct(tp)->returns->dcl_print(0);
                   30950:                                break;
                   30951:                        case 0:
                   30952:                                putstring(string);
                   30953:                                break;
                   30954:                        case DTOR:
                   30955:                                putch('~');
                   30956:                        case CTOR:
                   30957:                                if (cs) {
                   30958:                                        if(tbl->t_name) {
                   30959:                                                Ptclass pc = Ptclass(tbl->t_name->tp);
                   30960:                                                if ((pc->base == CLASS) && 
                   30961:                                                        (pc->class_base == instantiated_template_class))
                   30962:                                                                pc->inst->print_pretty_name();
                   30963:                                                else putstring(cs);
                   30964:                                        }
                   30965:                                }
                   30966:                                else {
                   30967:                                        if (string)
                   30968:                                                fprintf(out_file,"%s()", n_template_arg_string 
                   30969:                                                        ? n_template_arg_string : string);
                   30970:                                        else putstring("constructor");
                   30971:                                        f = 0;
                   30972:                                }
                   30973:                                break;
                   30974:                        case TNAME:
                   30975:                                putstring(string);
                   30976:                                break;
                   30977:                        default:
                   30978:                                putstring("operator ");
                   30979:                                putstring(keys[n_oper]);
                   30980:                                break;
                   30981:                        }
                   30982:                        if (f) putstring("()");
                   30983:                }
                   30984:                else {
                   30985:                        if (n_oper) goto nop;
                   30986:                        if (string) 
                   30987:                                putstring(n_template_arg_string 
                   30988:                                        ? n_template_arg_string : string);
                   30989:                }
                   30990:                return;
                   30991:        }
                   30992:        
                   30993:        char* sig = 0;
                   30994:        Pclass cl = 0;
                   30995:        Penum en = 0;
                   30996:        int i = n_union;
                   30997: 
                   30998:        if (tp) {
                   30999:                Ptable tbl;
                   31000: 
                   31001:                switch (tp->base) {
                   31002:                default:
                   31003:                        if (tbl=n_table) {      // global or member
                   31004:                                Pname tn;
                   31005:                                if (tbl == gtbl) {
                   31006:                                        // if (i) fprintf(out_file,"__O%d.",i);
                   31007:                                        if ( i ) {
                   31008:                                                if (n_anon) 
                   31009:                                                fprintf(out_file,"__O%d.%s.", i, n_anon );
                   31010:                                        else fprintf(out_file,"__O%d.",i);
                   31011:                                        }
                   31012:                                        break;
                   31013:                                }
                   31014: 
                   31015:                                if (tn=tbl->t_name) { 
                   31016:                                        cl = Pclass(tn->tp);
                   31017:                                        if (i) { 
                   31018:                                                if (cl->string[0]=='_'  
                   31019:                                                    && cl->string[1]=='_'
                   31020:                                                    && cl->string[2]=='C' ) {
                   31021:                                                        if (n_anon)
                   31022:                                                                fprintf(out_file,"__O%d.%s.", i, n_anon );
                   31023:                                                        else fprintf(out_file,"__O%d.",i);
                   31024:                                                }
                   31025:                                                else
                   31026:                                                if ( cl->nested_sig ) 
                   31027:                                                        fprintf(out_file,"__O%d__%s.",i,cl->nested_sig);
                   31028:                                                else
                   31029:                                                if ( cl->lex_level ) {
                   31030:                                                        char *str = make_local_name(cl,1);
                   31031:                                                        fprintf(out_file,"__O%d%s.",i,str);
                   31032:                                                        delete str;
                   31033:                                                }
                   31034:                                                else fprintf(out_file,"__O%d__%d%s.",i,cl->strlen,cl->string);
                   31035:                                                cl = 0;
                   31036:                                        }
                   31037:                                        else 
                   31038:                                        if (cl->string[0]=='_'
                   31039:                                                && cl->string[1]=='_'
                   31040:                                                && cl->string[2]=='C'
                   31041:                                                && n_stclass != STATIC )
                   31042:                                                        cl = 0;
                   31043:                                        break;
                   31044:                                }
                   31045:                        }
                   31046: 
                   31047:                        switch (n_stclass) {    // local variable
                   31048:                        case STATIC:
                   31049:                        case EXTERN:
                   31050:                                if (i)
                   31051:                                        fprintf(out_file,"__O%d.",i);
                   31052:                                else if (n_sto==STATIC && tp->base!=FCT) {
                   31053:                                        if (lex_level == 0)
                   31054:                                                putstring("__S");
                   31055:                                        else
                   31056:                                                fprintf(out_file,"__%d",lex_level);
                   31057:                                }
                   31058:                                break;
                   31059:                        default:
                   31060:                                // encode with lexical level UNLESS ``special''
                   31061:                                // e.g. __builtin
                   31062:                                if (string[0]!='_' || string[1]!='_' || string[2] != 'C' ) {
                   31063:                                        if (i)
                   31064:                                        {
                   31065:                                                if (n_anon)
                   31066:                                                    fprintf(out_file,"__%d__O%d.%s.",lex_level-1,i,n_anon);
                   31067:                                                else fprintf(out_file,"__%d__O%d.",lex_level-1,i);
                   31068:                                        }
                   31069:                                        else
                   31070:                                                fprintf(out_file,"__%d",lex_level);
                   31071:                                }
                   31072:                        }
                   31073:                        break;
                   31074:                case CLASS:
                   31075:                case ENUM:
                   31076:                        if (tp->in_class && tp->nested_sig) en = Penum(tp);
                   31077:                        break;
                   31078:                }
                   31079: 
                   31080:                if (tp->base==FCT) {
                   31081:                        sig = Pfct(tp)->f_signature;
                   31082:                        if (sig && sig[0]==0) sig = 0;
                   31083:                }
                   31084:        }
                   31085: 
                   31086:        if (string) {
                   31087: #ifdef DENSE
                   31088:                int i = strlen(string);
                   31089:                if (cl) i += cl->strlen+4;      // __dd<class name>
                   31090:                if (sig) {
                   31091:                        if (cl == 0) i += 2;
                   31092:                        i += strlen(sig);
                   31093:                }
                   31094: 
                   31095:                if (31<i) {
                   31096:                        char buf[256];
                   31097:                        if (cl && sig)
                   31098:                                sprintf(buf,"%s__%d%s%s",string,cl->strlen,cl->string,sig);
                   31099:                        else if (cl)
                   31100:                                sprintf(buf,"%s__%d%s",string,cl->strlen,cl->string);
                   31101:                        else if (sig)
                   31102:                                sprintf(buf,"%s__%s",string,sig);
                   31103:                        else 
                   31104:                                sprintf(buf,"%s",string);
                   31105:                        chop(buf);
                   31106:                        fprintf(out_file,"%s ",buf);
                   31107:                        return;
                   31108:                }
                   31109: #endif
                   31110: 
                   31111:                if ( en )
                   31112:                        fprintf(out_file,"__%s", en->nested_sig);
                   31113:                else 
                   31114:                        putstring(n_template_arg_string 
                   31115:                                ? n_template_arg_string : string);
                   31116: 
                   31117:                if ( cl ) {
                   31118:                        if ( cl->nested_sig )
                   31119:                                fprintf(out_file,"__%s",cl->nested_sig);
                   31120:                        else
                   31121:                        if ( cl->lex_level ) {
                   31122:                                char *str = make_local_name( cl, 1 );
                   31123:                                putstring( str );
                   31124:                                delete str;
                   31125:                        }
                   31126:                        else fprintf(out_file,"__%d%s",cl->strlen,cl->string);
                   31127:                }
                   31128: 
                   31129:                if (sig) {
                   31130:                        if (cl == 0) putstring("__");
                   31131:                        putstring(sig);
                   31132:                }
                   31133:                putch(' ');
                   31134:        }
                   31135: }
                   31136: 
                   31137: #ifdef DENSE
                   31138: void chop(char* buf)
                   31139: {
                   31140:        static char alpha[] = "_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
                   31141:        static const asz = sizeof(alpha)-1;
                   31142:        int hash = 0;
                   31143:        char* p = &buf[29];
                   31144:                        
                   31145:        while (*p) {
                   31146:                hash <<= 1;
                   31147:                if (hash & (1<<12)) {
                   31148:                        hash &= ~(1<<12);
                   31149:                        hash++;
                   31150:                }
                   31151:                hash ^= *p++;
                   31152:        }
                   31153: 
                   31154:        buf[29] = alpha[(int)(hash%asz)];
                   31155:        buf[30] = alpha[(int)((hash/asz)%asz)];
                   31156:        buf[31] = 0;
                   31157: }
                   31158: #endif
                   31159: 
                   31160: void type::print()
                   31161: {
                   31162:        switch (base) {
                   31163:        case PTR:
                   31164:        case RPTR:
                   31165:        case VEC:
                   31166:                Pptr(this)->dcl_print(0);
                   31167:                break;
                   31168:        case FCT:
                   31169:                Pfct(this)->dcl_print();
                   31170:                break;
                   31171: //     case VEC:
                   31172: //             Pvec(this)->dcl_print(0);
                   31173: //             break;
                   31174:        case CLASS:
                   31175:        case ENUM:
                   31176:                if (emode)
                   31177:                        fprintf(out_file,"%k",base);
                   31178:                else
                   31179:                //      error('i',"%p->T::print(%k %s)",this,base,Pclass(this)->string);        
                   31180:                        fprintf(out_file,"struct %s *",Pclass(this)->string);
                   31181:                break;
                   31182:        case TYPE:
                   31183:                if (Cast||Pbase(this)->b_name->lex_level) {
                   31184:                        Pbase(this)->b_name->tp->print();
                   31185:                        break;
                   31186:                }
                   31187:                // no break
                   31188:        default:
                   31189:                Pbase(this)->dcl_print();
                   31190:        }
                   31191: }
                   31192: 
                   31193: char* type::signature(register char* p)
                   31194: /*
                   31195:        take a signature suitable for argument types for overloaded
                   31196:        function names
                   31197: */
                   31198: {
                   31199:        Ptype t = this;
                   31200:        int pp = 0;     // pointer to
                   31201: 
                   31202: xx:
                   31203: //error('d',"xx(%d) %d %k",this,t,t->base);
                   31204: 
                   31205:        // first unroll typedefs and handle derived types:
                   31206: 
                   31207:        switch (t->base) {
                   31208:        case TYPE:
                   31209:                if (Pbase(t)->b_const) *p++ = 'C';
                   31210:                t = Pbase(t)->b_name->tp;
                   31211:                goto xx;
                   31212: 
                   31213:        case VEC:
                   31214:                if (pp && Pvec(t)->size) {           // A<size>_
                   31215:                        *p++ = 'A';
                   31216:                        sprintf(p,"%d\0",Pvec(t)->size); // don't trust
                   31217:                                                         // sprintf return value
                   31218:                        while (*++p);
                   31219:                        *p++ = '_';
                   31220:                }
                   31221:                else
                   31222:                        *p++ = 'P';
                   31223:                t = Pvec(t)->typ;
                   31224:                pp = 1;
                   31225:                goto xx;
                   31226: 
                   31227:        case PTR:
                   31228:                if (Pptr(t)->rdo) *p++ = 'C';           // *const
                   31229:                if (Pptr(t)->memof) {                   // M<size><classname>
                   31230:                        Pclass cl = Pptr(t)->memof;
                   31231:                        register char* s = cl->string;
                   31232:                        int d = cl->strlen;
                   31233:                        if (d==0) cl->strlen = d = strlen(s);
                   31234:                        *p++ = 'M';
                   31235:                        if (d/10) *p++ = '0'+d/10;
                   31236:                        *p++ = '0'+ d%10;       // assume <100 char
                   31237:                        while (*p++ = *s++);
                   31238:                        --p;                            // not the '\0'
                   31239:                }
                   31240:                else
                   31241:                        *p++ = 'P';
                   31242:                t = Pptr(t)->typ;
                   31243:                pp = 1;
                   31244:                goto xx;
                   31245: 
                   31246:        case RPTR:
                   31247:                *p++ = 'R';
                   31248:                t = Pptr(t)->typ;
                   31249:                pp = 1;
                   31250:                goto xx;
                   31251: 
                   31252:        case FCT:
                   31253:        {       Pfct f = Pfct(t);
                   31254:                Pname n = f->argtype;
                   31255: 
                   31256:                if (f->f_const) *p++ = 'C';     // constant member function
                   31257:                if (f->f_static) *p++ = 'S';    // static member function
                   31258:        //      if (f->memof && f->f_this==0) *p++ = 'S';       //SSS static member function
                   31259:                *p++ = 'F';
                   31260:                if (n == 0)
                   31261:                        *p++ = 'v';     // VOID, that is f() == f(void)
                   31262:                else
                   31263:        for ( ; n; n=n->n_list) {       // print argument encoding
                   31264:                                        // check if argtype is the same
                   31265:                                        // as previously seen argtype
                   31266:                int i = 0;
                   31267:                for (Pname nn=f->argtype; n!=nn; nn=nn->n_list) {
                   31268:                        i++;
                   31269:                        if (nn->tp==n->tp || nn->tp->check(n->tp,0)==0) {
                   31270:                                // typeof (n) == typeof(arg i)
                   31271:                                int x = 1;      // try for a run after n
                   31272:                                Pname nnn = n;
                   31273:                                while ((nnn=nnn->n_list) && x<9) {
                   31274:                                        if (nnn->tp==n->tp
                   31275:                                        || nnn->tp->check(n->tp,0)==0) {
                   31276:                                                x++;
                   31277:                                                n = nnn;
                   31278:                                        }
                   31279:                                        else
                   31280:                                                break;
                   31281:                                }
                   31282: 
                   31283:                                if (x == 1)             // Ti
                   31284:                                        *p++ = 'T';
                   31285:                                else {                  // Nxi
                   31286:                                        *p++ = 'N';
                   31287:                                        *p++ = '0'+x;
                   31288:                                }
                   31289:        
                   31290:                                // assume <100 arguments
                   31291:                                if (9<i) *p++ = '0'+i/10;
                   31292:                                *p++ = '0'+i%10;
                   31293:                                goto zk;
                   31294:                        }       
                   31295:                }
                   31296: 
                   31297:                // ``normal'' case print argument type signature
                   31298:        //      if (n->n_xref) *p++ = 'R';
                   31299:                p = n->tp->signature(p);
                   31300:                zk:;
                   31301:        }
                   31302: 
                   31303:                if (f->nargs_known == ELLIPSIS) *p++ = 'e';
                   31304: 
                   31305:                if (pp) {               // '_' result type
                   31306:                        *p++ = '_';
                   31307:                        p = f->returns->signature(p);
                   31308:                }
                   31309: 
                   31310:                *p = 0;
                   31311:                return p;
                   31312:        }
                   31313:        }
                   31314: 
                   31315:        // base type modifiers:
                   31316: 
                   31317:        if ( Pbase(t)->b_const )        *p++ = 'C';
                   31318: //     if ( Pbase(t)->b_signed )       *p++ = 'S';
                   31319:        if ( Pbase(t)->b_unsigned )     *p++ = 'U';
                   31320: //     if ( Pbase(t)->b_volatile )     *p++ = 'V';
                   31321: 
                   31322: 
                   31323:        // now base types:
                   31324: 
                   31325:        register char *s, *ns = 0;;
                   31326:        int d;
                   31327:        Pclass cl;
                   31328: //lll:
                   31329:        switch (t->base) {
                   31330: //     case TNAME:     t = Pbase(t)->b_name->tp; goto lll;
                   31331:        case ANY:                       break;
                   31332:        case ZTYPE:                     break;
                   31333:        case VOID:      *p++ = 'v';     break;
                   31334:        case CHAR:      *p++ = 'c';     break;
                   31335:        case SHORT:     *p++ = 's';     break;
                   31336: //     case EOBJ:
                   31337:        case INT:       *p++ = 'i';     break;
                   31338:        case LONG:      *p++ = 'l';     break;
                   31339:        case FLOAT:     *p++ = 'f';     break;
                   31340:        case DOUBLE:    *p++ = 'd';     break;
                   31341:        case LDOUBLE:   *p++ = 'r';     break;
                   31342:        case EOBJ:
                   31343: //             *p++ = 'i';
                   31344: //             break;
                   31345:        {       Penum en = Penum(Pbase(t)->b_name->tp);
                   31346:        //      t = en->e_type;
                   31347:        //      goto lll;
                   31348:                ns = en->nested_sig; 
                   31349:                s = en->string;
                   31350:                d = en->strlen;
                   31351:                if (d==0) en->strlen = d = strlen(s);
                   31352:                goto pppp;
                   31353:        }
                   31354: 
                   31355:        case COBJ:
                   31356:        {       cl = Pclass(Pbase(t)->b_name->tp);
                   31357:                ns = cl->nested_sig;
                   31358:                s = cl->string;
                   31359:                d = cl->strlen;
                   31360:                if (d==0) cl->strlen = d = strlen(s);
                   31361:        pppp:
                   31362:                if ( ns == 0 ) {
                   31363:                        if (d/10) *p++ = '0'+d/10;
                   31364:                        *p++ = '0'+ d%10;       // assume less that 99 characters
                   31365:                }
                   31366:                else s = ns;
                   31367: 
                   31368:                while (*p++ = *s++);
                   31369:                --p;
                   31370:                break;
                   31371:        }
                   31372:        case FIELD:
                   31373:        default:
                   31374:                error('i',"signature of %k",t->base);
                   31375:        }
                   31376: 
                   31377:        *p = 0;
                   31378:        return p;
                   31379: }
                   31380: 
                   31381: void basetype::dcl_print()
                   31382: {
                   31383:        Pname nn;
                   31384:        Pclass cl;
                   31385: 
                   31386:        if (emode) {
                   31387:                if (b_virtual) puttok(VIRTUAL);
                   31388:                if (b_inline) puttok(INLINE);
                   31389:        }
                   31390:        if(ansi_opt || emode)
                   31391:                if (b_const) puttok(CONST);
                   31392:        if (b_unsigned) puttok(UNSIGNED);
                   31393: 
                   31394:        switch (base) {
                   31395:        case ANY:
                   31396:                if (emode)
                   31397:                        putstring("any ");
                   31398:                else
                   31399:                        putstring("int ");
                   31400:                break;
                   31401: 
                   31402:        case ZTYPE:
                   31403:                if (emode)
                   31404:                        putstring("zero ");
                   31405:                else
                   31406:                        putstring("int ");
                   31407:                break;
                   31408: 
                   31409:        case VOID:
                   31410:                 if (emode==0 && ansi_opt==0) {
                   31411:                         // silly trick to bypass BSD C compiler bug
                   31412:                         // void* (*)() dosn't work there
                   31413:                         // note simpl.c knows that VOID -> CHAR grep for VCVC
                   31414:                         puttok(CHAR);
                   31415:                        break;
                   31416:                 } 
                   31417:        case CHAR:
                   31418:        case SHORT:
                   31419:        case INT:
                   31420:        case LONG:
                   31421:        case FLOAT:
                   31422:        case DOUBLE:
                   31423:         case LDOUBLE:
                   31424:                puttok(base);
                   31425:                break;
                   31426: 
                   31427:        case EOBJ:
                   31428:                nn = b_name;
                   31429:        eob:
                   31430:                if (emode == 0)
                   31431:                //      puttok(INT);
                   31432:                        Penum(nn->tp)->e_type->dcl_print();
                   31433:                else {
                   31434:                         puttok(ENUM);
                   31435:                         nn->print();
                   31436:                }
                   31437:                 break;
                   31438: 
                   31439:        case COBJ:
                   31440:                nn = b_name;
                   31441:        cob:
                   31442:                cl = Pclass(nn->tp);
                   31443:                if (emode && (cl->base == CLASS)  &&
                   31444:                        (cl->class_base == instantiated_template_class)) {
                   31445:                                Ptclass(cl)->inst->print_pretty_name();
                   31446:                                break;
                   31447:                } else
                   31448:                if (cl && (cl->csu==UNION || cl->csu==ANON))
                   31449:                        puttok(UNION);
                   31450:                else puttok(STRUCT);
                   31451:                { 
                   31452:                        char* s = 0;
                   31453:                        if ( cl && cl->nested_sig )
                   31454:                                fprintf(out_file," __%s ",cl->nested_sig);
                   31455:                        else {
                   31456:                                if ( cl && cl->lex_level )
                   31457:                                        s = make_local_name( cl );
                   31458:                                putst(s?s:nn->string);
                   31459:                                delete s;
                   31460:                        }
                   31461:                }
                   31462:                break;
                   31463: 
                   31464:        case TYPE:
                   31465:                if (emode == 0) {
                   31466:                        switch (b_name->tp->base) {
                   31467:                        case COBJ:
                   31468:                                nn = Pbase(b_name->tp)->b_name;
                   31469:                                goto cob;
                   31470:                        case EOBJ:
                   31471:                                nn = Pbase(b_name->tp)->b_name;
                   31472:                                goto eob;
                   31473:                        }
                   31474:                }
                   31475:                b_name->print();
                   31476:                break;
                   31477: 
                   31478:        default:
                   31479:                if (emode) {
                   31480:                        if (0<base && base<=MAXTOK && keys[base])
                   31481:                                fprintf(out_file," %s",keys[base]);
                   31482:                        else
                   31483:                                putch('?');
                   31484:                }
                   31485:                else
                   31486:                        error('i',"%p->BT::dcl_print(%d)",this,base);
                   31487:        }
                   31488: }
                   31489: Pbase memptr_type;
                   31490: 
                   31491: void type::dcl_print(Pname n)
                   31492: /*
                   31493:        "this" type is the type of "n". Print the declaration
                   31494: */
                   31495: {
                   31496: //error('d',"%p::dcl_print(%n)",this,n);
                   31497:        Ptype t = this;
                   31498:        Pptr p;
                   31499:        TOK pre = 0;
                   31500: 
                   31501:        if (t == 0) error('i',"0->dcl_print()");
                   31502:        if (n && n->tp!=t) error('i',"not %n'sT (%p)",n,t);
                   31503: 
                   31504:        if (base == OVERLOAD) {
                   31505:                for (Plist gl=Pgen(this)->fct_list; gl; gl=gl->l) {
                   31506:                        Pname nn = gl->f;
                   31507:                        nn->tp->dcl_print(nn);
                   31508:                        if (gl->l) puttok(SM);
                   31509:                }
                   31510:                return;
                   31511:        }
                   31512: 
                   31513:        tbuf = tbufvec[freetbuf];
                   31514:        if (tbuf == 0) {
                   31515:                if (freetbuf == NTBUF-1) error('i',"AT nesting overflow");
                   31516:                tbufvec[freetbuf] = tbuf = new class dcl_buf;
                   31517:        }
                   31518:        freetbuf++;
                   31519:        if ( base==FIELD && Pbase(this)->b_bits == 0 )
                   31520:                tbuf->init(0);// some compilers can't handle mangled names here
                   31521:        else
                   31522:                tbuf->init(n);
                   31523:        if (n && n->n_xref) tbuf->front(PTR);
                   31524: 
                   31525:        while (t) {
                   31526:                TOK k;
                   31527: 
                   31528:                switch (t->base) {
                   31529:                case PTR:
                   31530:                        p = Pptr(t);
                   31531:                        k = (p->rdo) ? CONST_PTR : PTR;
                   31532:                        goto ppp;
                   31533:                case RPTR:
                   31534:                        p = Pptr(t);
                   31535:                        k = (p->rdo) ? CONST_RPTR : RPTR;
                   31536:                ppp:
                   31537:                        if (p->memof) {
                   31538:                                if (emode) {
                   31539:                                        tbuf->front(k);
                   31540:                                        tbuf->front(p->memof);
                   31541:                                }
                   31542:                                else {
                   31543:                                        t = p->typ;
                   31544:                                        while (t->base==TYPE) t = Pbase(t)->b_name->tp;
                   31545:                                        if (t->base == FCT) {
                   31546:                                                tbuf->base(mptr_type);
                   31547:                                                goto zaq;
                   31548:                                        }
                   31549:                                        else
                   31550:                                                tbuf->front(k);
                   31551:                                }
                   31552:                        }
                   31553:                        else
                   31554:                                tbuf->front(k);
                   31555:                        pre = PTR;
                   31556:                        t = p->typ;
                   31557:                        break;
                   31558:                case VEC:
                   31559:                {       Pvec v = Pvec(t);
                   31560:                        if (Cast && pre != PTR && pre != VEC) { // for Macintosh: ptr to array uses [] notation
                   31561:                                tbuf->front(PTR);
                   31562:                                pre = PTR;
                   31563:                        }
                   31564:                        else {
                   31565:                                if (pre == PTR) tbuf->paran();
                   31566:                                tbuf->back(VEC,v);
                   31567:                                pre = VEC;
                   31568:                        }
                   31569:                        t = v->typ;
                   31570:                        break;
                   31571:                }
                   31572: 
                   31573:                case FCT:
                   31574:                {       Pfct f = Pfct(t);
                   31575:                        if (pre == PTR)
                   31576:                                tbuf->paran();
                   31577:                        else if (emode && f->memof && n==0)
                   31578:                                tbuf->front(f->memof);
                   31579:                        tbuf->back(FCT,f);
                   31580:                        pre = FCT;
                   31581:                        t = (f->s_returns) ? f->s_returns : f->returns;
                   31582:                        break;
                   31583:                }
                   31584:                case FIELD:
                   31585:                        tbuf->back(FIELD,t);
                   31586:                        tbuf->base( Pbase(Pbase(t)->b_fieldtype) );
                   31587:                        t = 0;
                   31588:                        break;
                   31589:                case 0:
                   31590:                        if(!emode)error('i',"noBT(B=0)");
                   31591:                        goto dobase;
                   31592:                case TYPE:
                   31593:                        if (Cast||Pbase(t)->b_name->lex_level) { // unravel type in case it contains vectors
                   31594:                                t = Pbase(t)->b_name->tp;
                   31595:                                break;
                   31596:                        }
                   31597:                default: // the base has been reached
                   31598:                dobase:
                   31599:                        if (emode) {
                   31600:                                char* s;
                   31601:                                for (Ptype tt = t; tt->base==TYPE; tt=Pbase(tt)->b_name->tp);
                   31602:                                switch (tt->base) {
                   31603:                                case CLASS:
                   31604:                                        s = Pclass(tt)->string;
                   31605:                                         if (Ptclass(this)->class_base == instantiated_template_class ||
                   31606:                                             Ptclass(this)->class_base == uninstantiated_template_class) {
                   31607:                                                Ptclass(this)->inst->print_pretty_name();
                   31608:                                                --freetbuf;
                   31609:                                                return;
                   31610:                                         }
                   31611:                                        if (s[0]=='_' &&s[1]=='_' && s[2]=='C') s="class";
                   31612:                                        goto fret;
                   31613:                                case ENUM:
                   31614:                                        s = "enum";
                   31615:                                        goto fret;
                   31616:                                case OVERLOAD:
                   31617:                                        s = "overloaded";
                   31618:                                fret:
                   31619:                                        putstring(s);
                   31620:                                        freetbuf--;
                   31621:                                        return;
                   31622:                                }
                   31623:                        }
                   31624: 
                   31625:                        tbuf->base( Pbase(t) );
                   31626:                        goto zaq;
                   31627:                } // switch
                   31628:        } // while
                   31629: zaq:
                   31630:        tbuf->put();
                   31631:        freetbuf--;
                   31632: }
                   31633: 
                   31634: void fct::dcl_print()
                   31635: {
                   31636:        Pname nn;
                   31637: //error('d',"fct::dcl_print()");
                   31638:        if (emode) {
                   31639:                putch('(');
                   31640:                for (nn=argtype; nn;) {
                   31641:                        nn->tp->dcl_print(0);
                   31642:                        if (nn=nn->n_list) puttok(CM); else break;
                   31643:                }
                   31644:                switch (nargs_known) {
                   31645:                case 0:         //      putst("?"); break;
                   31646:                case ELLIPSIS:  puttok(ELLIPSIS); break;
                   31647:                }
                   31648:                putch(')');
                   31649:                if (f_const) puttok(CONST);     
                   31650:                if (f_static) puttok(STATIC);   // wrong place for ``static''
                   31651:                return;
                   31652:        }
                   31653: 
                   31654:        Pname at = f_args;
                   31655:        putch('(');
                   31656: 
                   31657:        if (ansi_opt) {
                   31658:                // print typed arguments:
                   31659:                at = (f_this) ? f_this : (f_result) ? f_result : argtype; 
                   31660:                // WNG -- note:  at = f_args had 0 value with ansi_opt set
                   31661:                //               mystery fix added here
                   31662:                if (at == 0) {
                   31663:                        if (nargs_known == ELLIPSIS) {
                   31664:                                putch(')');
                   31665:                                return;
                   31666:                        }
                   31667:                        puttok(VOID);
                   31668:                }
                   31669:                else if (body && Cast==0)
                   31670:                        at->dcl_print(CM);      // print argument type and name
                   31671:                else {
                   31672:                        for (nn=at; nn;) {
                   31673:                        //      nn->tp->dcl_print(0);   // print argument type
                   31674:                                nn->tp->dcl_print(nn);  // print argument type
                   31675:                                                        // (there may not be a name)
                   31676:                                if (nn=nn->n_list) puttok(CM); else break;
                   31677:                        }
                   31678:                }
                   31679:                if (nargs_known == ELLIPSIS) putstring(",...");
                   31680:                putch(')');
                   31681:        }
                   31682:        else {
                   31683:                // print argument names followed by argument type declarations:
                   31684:                if (body && Cast==0) {
                   31685:                        for (nn=at; nn;) {
                   31686:                                nn->print();
                   31687:                                if (nn=nn->n_list) puttok(CM); else break;
                   31688:                        }
                   31689: #ifdef mips
                   31690:                        if (nargs_known == ELLIPSIS)
                   31691:                                putstring(", va_alist");
                   31692: #endif
                   31693: #ifdef sparc
                   31694:                         if (nargs_known == ELLIPSIS)
                   31695:                                 putstring(", __builtin_va_alist");
                   31696: #endif
                   31697:                        putch(')');
                   31698:                }
                   31699:                else
                   31700:                        putch(')');
                   31701:        }
                   31702: }
                   31703: 
                   31704: void print_body(Pfct f)
                   31705: {
                   31706:        if (Cast==0) {
                   31707:                
                   31708:                if (ansi_opt==0 && f->f_args) {
                   31709:                        f->f_args->dcl_print(SM);
                   31710:                        if ( last_ll==0 && (last_ll = f->body->where.line) )
                   31711:                                f->body->where.putline();
                   31712:                }
                   31713: 
                   31714:                if (MAIN) {
                   31715:                        putstring("{ _main(); ");       // call constructors
                   31716:                        f->body->print();
                   31717:                        puttok(RC);
                   31718:                }
                   31719:                else 
                   31720:                        f->body->print();
                   31721:        }
                   31722: }
                   31723: 
                   31724: Pbcl shared_seen;
                   31725: 
                   31726: void classdef::print_members()
                   31727: {
                   31728:        int i;
                   31729:        
                   31730:        Pbcl l = baselist;
                   31731: // error('d',"%t->print_members()",this);
                   31732:        if (l) {
                   31733:                if (l->base == NAME) {
                   31734:                        l->bclass->print_members();     // first base only
                   31735:                        // pad to ensure alignment:
                   31736:                        int boff = l->bclass->real_size;
                   31737:                        int ba = l->bclass->align();
                   31738:                        int xtra = boff%ba;
                   31739:                        int waste = (xtra) ? ba-xtra : 0;       // padding
                   31740: //error('d',"%s: size % align %d waste %d",string,boff,ba,waste);
                   31741:                        if (waste) {
                   31742:                                // waste it to protect against structure
                   31743:                                // assignments to the base class
                   31744:                                char* s = make_name('W');
                   31745:                                fprintf(out_file,"char %s[%d];\n",s,waste);
                   31746:                                delete s;
                   31747:                        }
                   31748:                        l = l->next;
                   31749:                }
                   31750: 
                   31751:                for (; l; l=l->next)
                   31752:                /*      for second base etc. one must allocate as an object
                   31753:                        (rather than a list of members) to ensure proper alignment
                   31754:                        for shared base allocate a pointer
                   31755:                        size, alignment, & offset handled in cassdef::dcl()
                   31756:                */
                   31757:                        if (l->base == NAME) {
                   31758:                                Pclass bcl = l->bclass;
                   31759:                                char *str =  0;
                   31760:                                char *cs = bcl->nested_sig?bcl->nested_sig:bcl->string;
                   31761:                                if (bcl->lex_level && 
                   31762:                                        bcl->nested_sig==0) 
                   31763:                                                str=make_local_name(bcl);
                   31764:                                puttok(STRUCT);
                   31765:                                putst(str?str:cs);
                   31766:                                putcat('O',bcl->string); // leave as unencoded
                   31767:                                puttok(SM);
                   31768:                                delete str;
                   31769:                        }
                   31770:        }
                   31771: 
                   31772:        // Sam: A class or an enum type declared within a class can hide a
                   31773:        // member with the same name, so make sure that it gets printed by
                   31774:        // traversing the n_tbl_list to get at these names.
                   31775:        for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i)) {
                   31776:          do { if (nn->base==NAME
                   31777:                && nn->n_union==0
                   31778:                && nn->tp->base!=FCT
                   31779:                && nn->tp->base!=OVERLOAD
                   31780:                && nn->tp->base!=CLASS
                   31781:                && nn->tp->base!=ENUM
                   31782:                && nn->n_stclass != STATIC) {
                   31783:                //      if (nn->tp->base==FIELD && Pbase(nn->tp)->b_bits==0) continue;
                   31784:                        Pexpr i = nn->n_initializer;
                   31785:                        nn->n_initializer = 0;
                   31786:                        nn->dcl_print(0);
                   31787:                        nn->n_initializer = i;
                   31788:                }
                   31789:          } while ((nn->base == NAME) &&
                   31790:                 ((nn->tp->base!=CLASS) || (nn->tp->base!=ENUM)) &&
                   31791:                 (nn = nn->n_tbl_list)) ;
                   31792:        }
                   31793: 
                   31794:        for (l=baselist; l; l=l->next)
                   31795:                if (l->base==VIRTUAL && l->ptr_offset) {
                   31796:                        Pclass bcl = l->bclass;
                   31797:                                char* str =  0;
                   31798:                        char *cs = bcl->nested_sig?bcl->nested_sig:bcl->string;
                   31799:                        if (bcl->lex_level && 
                   31800:                                bcl->nested_sig==0) 
                   31801:                                        str=make_local_name(bcl);
                   31802:                        puttok(STRUCT);
                   31803:                        putst(str?str:cs);
                   31804:                        putch('*');
                   31805:                        putcat('P',bcl->string); // leave unencoded
                   31806:                        puttok(SM);
                   31807:                        delete str;
                   31808:                }
                   31809: }
                   31810: 
                   31811: // void classdef::print_vtbl(Pvirt vtab)
                   31812: // {
                   31813: // error('d',"%s->print_vtbl(%s) vtbl_opt %d",string,vtab->string,vtbl_opt);
                   31814: // error('d',"print_vtbl: lex_level: %d", lex_level );
                   31815: // 
                   31816: //     switch (vtbl_opt) {
                   31817: //     case -1:
                   31818: //     case 1:
                   31819: //             vlist = new vl(this,vtab,vlist);
                   31820: //     }
                   31821: //
                   31822: //     int oo = vtbl_opt;      // make `simulated static' name
                   31823: //     vtbl_opt = -1;
                   31824: //      char* str =  lex_level ? make_local_name(this) : 0;
                   31825: //      char* s = vtbl_name(vtab->string,str?str:string);
                   31826: //     vtbl_opt = oo;
                   31827: //     fprintf(out_file,"extern struct __mptr %s[];\n",s);
                   31828: //     s[2] = 'p';     // pointer, not tbl itself
                   31829: //     fprintf(out_file,"extern struct __mptr* %s;\n",s);
                   31830: //
                   31831: //       delete s;
                   31832: //     delete str;
                   31833: // }
                   31834: 
                   31835: vl* vlist;
                   31836: 
                   31837: void really_really_print(Pclass cl, Pvirt vtab, char* s, char* ss);
                   31838: 
                   31839: int p2(Pname nn, Ptype t, Pclass cl, Pvirt vtab, char* s)
                   31840: {
                   31841:        int init;
                   31842: 
                   31843:        if (t->base == FCT) {
                   31844:                Pfct f = Pfct(t);
                   31845: 
                   31846: //error('d',"p2 %n init %d inline %d virtual %d",nn,nn->n_initializer,f->f_inline,f->f_virtual);
                   31847: //error('d',"p2 %s expr %d imeasure %d body %d",s,f->f_expr,f->f_imeasure,f->body);
                   31848: //error('d',"sto %k",nn->n_sto);
                   31849:                if (nn->n_initializer
                   31850:                || nn->n_sto==STATIC
                   31851:                || f->f_inline
                   31852:                || f->f_imeasure
                   31853:                || f->f_virtual==0) return 0;
                   31854:                init = f->body!=0;
                   31855:        }
                   31856:        else
                   31857:                init = nn->n_initializer!=0;
                   31858: 
                   31859:        int oo = vtbl_opt;
                   31860:        vtbl_opt = 1;   // make sure the name is universal
                   31861:        char *cs = cl->nested_sig?cl->nested_sig:cl->string;
                   31862:         char* sstr = (cl->lex_level&&cl->nested_sig==0)? make_local_name(cl) : 0;
                   31863:         char* ss = vtbl_name(vtab->string,sstr?sstr:cs);
                   31864: 
                   31865:        if (init) {     // unique definition here
                   31866:                really_really_print(cl,vtab,ss,s);
                   31867:        }
                   31868:        else {  // unique definition elsewhere
                   31869:                char *vstr = 0;
                   31870:                if ( vtab && vtab->string ) {
                   31871:                        vstr = new char[strlen(vtab->string)+cl->strlen+1];
                   31872:                        strcpy( vstr, vtab->string );
                   31873:                        strcat( vstr, cl->string );
                   31874:                }
                   31875:                Pname nn;
                   31876:                if (nn=ptbl->look(vstr?vstr:cl->string,0)) { // use of ptbl in file
                   31877:                        fprintf(out_file,"extern struct __mptr %s[];\n",ss);
                   31878:                        s[2] = 'p';
                   31879:                        // fprintf(out_file,"struct __mptr* %s = ",s);
                   31880:                        // fprintf(out_file,"%s;\n",ss);
                   31881:                        ptbl_add_pair(s, ss);
                   31882:                        nn->n_key=HIDDEN; 
                   31883:                }
                   31884:                delete vstr;
                   31885:        }
                   31886:        vtbl_opt = oo;
                   31887: 
                   31888:        delete ss;
                   31889:        delete sstr;
                   31890: 
                   31891:        return 1;
                   31892: }
                   31893: 
                   31894: void classdef::really_print(Pvirt vtab)
                   31895: {
                   31896: // error('d',"really_print %t %d",this,vtbl_opt);
                   31897:        int oo = vtbl_opt;      // make `simulated static' name
                   31898:        vtbl_opt = -1;
                   31899:        char *cs = nested_sig?nested_sig:string;
                   31900:         char* str = (lex_level&&nested_sig==0) ? make_local_name(this) : 0;
                   31901:         char* s = vtbl_name(vtab->string,str?str:cs);
                   31902: // error('d', "really_print: %s, vtab: %s, s: %s", string, vtab->string, s );
                   31903:        vtbl_opt = oo;
                   31904: 
                   31905:        // see if needed
                   31906:        int i;
                   31907:        for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
                   31908:                Ptype t = nn->tp;
                   31909:        zse:
                   31910:                if (t)
                   31911:                switch (t->base) {
                   31912:                case TYPE:
                   31913:                        t = Pbase(t)->b_name->tp;
                   31914:                        goto zse;
                   31915: /*
                   31916:                case COBJ:
                   31917:                        if (nn->n_sto == EXTERN)
                   31918:                        {       Pclass cl = Pclass(Pbase(t)->b_name->tp);
                   31919:                                if (cl->has_ctor()) {
                   31920:                                        p2(nn,t,this,vtab,s);
                   31921:                                        return;
                   31922:                                }
                   31923:                        }
                   31924:                        break;
                   31925: */
                   31926:                case FCT:
                   31927:                        if (p2(nn,t,this,vtab,s))
                   31928:                                goto xyzzy;
                   31929:                        break;
                   31930: 
                   31931:                case OVERLOAD:
                   31932:                {       for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l)
                   31933:                                if (p2(gl->f,gl->f->tp,this,vtab,s))
                   31934:                                        goto xyzzy;
                   31935:                }
                   31936:                }
                   31937:        }
                   31938: 
                   31939:         { // must be initialized var in block to permit goto
                   31940:        char* ss = vtbl_name(vtab->string,str?str:cs);
                   31941: // error('d', "really_print: %s, vtab: %s, ss: %s", cs, vtab->string, s );
                   31942: 
                   31943:        if (vtbl_opt)
                   31944:                really_really_print(this,vtab,ss,s);
                   31945:        else {
                   31946:                char *vstr = 0;
                   31947:                if ( vtab && vtab->string ) {
                   31948:                        vstr = new char[::strlen(vtab->string)+strlen+1];
                   31949:                        strcpy( vstr, vtab->string );
                   31950:                        strcat( vstr, string );
                   31951:                }
                   31952:                Pname nn;
                   31953:                if (nn=ptbl->look(vstr?vstr:string,0)) { // use of ptbl in file
                   31954:                        fprintf(out_file,"extern struct __mptr %s[];\n",ss);
                   31955:                        s[2] = 'p';
                   31956:                        // fprintf(out_file,"struct __mptr* %s = ",s);
                   31957:                        // fprintf(out_file,"%s;\n",ss);
                   31958:                        ptbl_add_pair(s, ss);
                   31959:                        nn->n_key=HIDDEN; 
                   31960:                }
                   31961:                delete vstr;
                   31962:        }
                   31963:        delete ss;
                   31964:        }
                   31965: xyzzy:
                   31966:        delete s;
                   31967:        delete str;
                   31968: }
                   31969: 
                   31970: void really_really_print(Pclass cl, Pvirt vtab, char* s, char* ss)
                   31971: {
                   31972: // error('d',"really %s %s",s, ss);
                   31973:        // make sure function is declared before using
                   31974:        // it in vtbl initializer
                   31975:        Pname nn;
                   31976:        int i;
                   31977:        for (i=0; nn = vtab->virt_init[i].n; i++) {
                   31978:                Pfct f = Pfct(nn->tp);
                   31979:                 if (nn->n_initializer) {       // pure virtual
                   31980:                        static pv;
                   31981:                        if (pv == 0) {  // VCVC void->char assumed
                   31982:                                fprintf(out_file,"char __pure_virtual_called();\n");
                   31983:                                pv = 1;
                   31984:                        }
                   31985:                        continue;
                   31986:                }
                   31987:                if (f->base != FCT) error('i',"vtbl %n",nn);
                   31988: //extern void expand_dtor(Pclass cl);
                   31989: //             if (f->f_inline == IDTOR) expand_dtor(f->memof);
                   31990: 
                   31991:                if (nn->n_dcl_printed==0 /*|| f->f_inline*/) {
                   31992:                        if (f->f_inline && vtbl_opt) puttok(STATIC);
                   31993:                        if (f->f_result == 0) make_res(f);
                   31994:                        Ptype r = f->s_returns ? f->s_returns : f->returns;
                   31995:                        r->print();
                   31996:                        nn->print();
                   31997:                        putstring("()");
                   31998:                        puttok(SM);
                   31999:                        nn->n_dcl_printed = 1;
                   32000:                }
                   32001:        }
                   32002: 
                   32003: //     if (vtbl_opt == -1) puttok(STATIC);
                   32004: 
                   32005: 
                   32006:         fprintf(out_file,"struct __mptr %s[] = {0,0,0,\n",s);
                   32007: 
                   32008:        Pname n;
                   32009:        for (i=0; n=vtab->virt_init[i].n; i++) {
                   32010:                if (n->n_initializer)
                   32011:                        putstring("0,0,(__vptp)__pure_virtual_called,\n");
                   32012:                else {
                   32013:                        fprintf(out_file,"%d,0,(__vptp)",-vtab->virt_init[i].offset);
                   32014:                        n->print();
                   32015:                        n->n_addr_taken = 1;
                   32016:                        putstring(",\n");
                   32017:                }
                   32018:        }
                   32019:        putstring("0,0,0};\n");
                   32020: 
                   32021:        ss[2] = 'p';
                   32022:         // fprintf(out_file,"struct __mptr* %s = ",ss);
                   32023:        s[2] = 'v';
                   32024:         // fprintf(out_file,"%s;\n",s);
                   32025:        ptbl_add_pair(ss,s);
                   32026: 
                   32027:         Pname nm;
                   32028:        char *cstr = 0;
                   32029:        char *vstr = 0;
                   32030:        char *cs = cl->nested_sig?cl->nested_sig:cl->string;
                   32031:        if (cl->lex_level && cl->nested_sig==0) cstr = make_local_name( cl );
                   32032:        if ( vtab && vtab->string ) {
                   32033:                vstr = new char[strlen(vtab->string)+(cstr?strlen(cstr):strlen(cs))+1];
                   32034:                strcpy( vstr, vtab->string );
                   32035:                strcat( vstr, cstr?cstr:cs );
                   32036:        }
                   32037: 
                   32038:        if ( vstr == 0 ) vstr = cstr;
                   32039:        if ( nm = ptbl->look(vstr?vstr:cl->string,0) ) 
                   32040:                nm->n_key = HIDDEN;
                   32041:        else 
                   32042:        if ( ptbl->look(vstr?vstr:cl->string,HIDDEN) == 0 )
                   32043:                ptbl->insert(new name(vstr?vstr:cl->string),HIDDEN);
                   32044:         if (cstr == vstr) delete cstr;
                   32045:         else {
                   32046:                 delete cstr;
                   32047:                 delete vstr;
                   32048:         }
                   32049: 
                   32050: //error('d',"really-> %s",s);
                   32051: }
                   32052: 
                   32053: #include <ctype.h>
                   32054: char* vtbl_name(char* s1, char* s2)
                   32055: {
                   32056:        char* s3 = (vtbl_opt == -1 && *src_file_name) ? src_file_name : 0;
                   32057:                // if vtbl_opt == -1 fake a static (there are no portable
                   32058:                // way of doing a forward declaration of a static in C)
                   32059:        int ll = s1 ? strlen(s1) : 0;
                   32060:        int ll2 = strlen(s2);
                   32061:        int ll3 = s3 ? strlen(s3) : 0;
                   32062:         int sz = (ll+ll2+ll3+20)/32+1;  // avoid fragmentation
                   32063: 
                   32064:         sz *= 32;
                   32065: // error('d',"vtbl_name(%s,%s,%s) %d",s1?s1:"",s2,s3?s3:"",sz);
                   32066:         char* buf = new char[sz];
                   32067:        if (s3) {
                   32068:                if (s1)
                   32069:                        sprintf(buf,"__vtbl__%d%s__%d%s__%s",ll,s1,ll2,s2,s3);
                   32070:                else
                   32071:                        sprintf(buf,"__vtbl__%d%s__%s",ll2,s2,s3);
                   32072:        }
                   32073:        else if (s1)
                   32074:                sprintf(buf,"__vtbl__%d%s__%d%s",ll,s1,ll2,s2);
                   32075:        else
                   32076:                sprintf(buf,"__vtbl__%d%s",ll2,s2);
                   32077: 
                   32078:        if (vtbl_opt == -1) {
                   32079:                for (char* p = buf+ll2+11; *p; p++)
                   32080:                        if (!isalpha(*p) && !isdigit(*p)) *p = '_';
                   32081:        }
                   32082: #ifdef DENSE
                   32083:        chop(buf);
                   32084: #endif
                   32085:        return buf;
                   32086: }
                   32087: 
                   32088: void classdef::print_all_vtbls(Pclass bcl)
                   32089: {
                   32090: //error('d',"%t->print_all_vtbls(%t) vlt %d bl %d",this,bcl,virt_list,baselist);
                   32091: 
                   32092:        for (Pvirt blist = bcl->virt_list; blist; blist = blist->next) {
                   32093:                if (this != blist->vclass) continue;
                   32094:                if (blist->printed) continue;
                   32095:         //      if (blist->string==0 && find_vptr(this)==0) {        //BSopt
                   32096:         //              continue;
                   32097:         //      }
                   32098:        //      print_vtbl(blist);
                   32099:                vlist = new vl(this,blist,vlist);
                   32100:                blist->printed = 1;
                   32101:        }
                   32102: 
                   32103:        for (Pbcl b = bcl->baselist; b; b = b->next)
                   32104:                print_all_vtbls(b->bclass);
                   32105: 
                   32106:        if (this==bcl) c_body = 0;
                   32107: }
                   32108: 
                   32109: extern Pclass current_instantiation;
                   32110: void classdef::dcl_print(Pname)
                   32111: { 
                   32112: //error('d',"%t->classdef::dcl_print() -- c_body==%d defined==0%o",this,c_body,defined);
                   32113:        defined |= REF_SEEN;
                   32114: // ensure template instantiations are printed exactly once.
                   32115:         if (class_base != vanilla_class && current_instantiation != this) return;
                   32116: 
                   32117:        if (c_body==0 || c_body==3 || (defined&DEFINED)==0) return;
                   32118:        c_body = 3;
                   32119: 
                   32120:        int i;
                   32121:        for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
                   32122:                if (nn->base==NAME
                   32123:                && nn->n_union==0
                   32124:                && nn->tp->base==CLASS
                   32125:                && Pclass(nn->tp)->c_body==1)
                   32126:                        Pclass(nn->tp)->dcl_print(nn);
                   32127:                else if (nn->base == TNAME && Pbase(nn->tp)->base != COBJ)
                   32128:                        nn->dcl_print(0);
                   32129:                 else if (nn->tp && nn->tp->base == ENUM) {
                   32130:                        if(nn->n_union==0) Penum(nn->tp)->dcl_print(nn);
                   32131:                }
                   32132:        }
                   32133: 
                   32134:        TOK lvl = in_class ? NESTED : lex_level ? LOCAL : 0;
                   32135:        Pname n = ktbl->look(string,lvl);
                   32136:        if (n==0) n = ktbl->look(string,HIDDEN);
                   32137: 
                   32138:        if (n) {
                   32139:                if (n->where.line!=last_line.line
                   32140:                || n->where.file!=last_line.file)
                   32141:                        if (last_ll = n->where.line)
                   32142:                                n->where.putline();
                   32143:                        else
                   32144:                                last_line.putline();
                   32145:        }
                   32146: 
                   32147:        TOK c = csu==CLASS ? STRUCT : csu;
                   32148:        puttok(c);
                   32149: //     if (string[0]!='_' || string[1]!='_' || string[2]!='C')
                   32150: 
                   32151:         char *str = 0;
                   32152:        if ( lex_level && nested_sig == 0) str = make_local_name( this );
                   32153:        if ( nested_sig ) putstring( " __" );
                   32154:        putst(str?str:(nested_sig?nested_sig:string));
                   32155: 
                   32156:        int sm = 0;
                   32157:        int sz = tsizeof();
                   32158:        int dvirt = 0;
                   32159: 
                   32160:        if ( nested_sig )
                   32161:                fprintf(out_file,"{\t/* sizeof __%s == %d */\n",nested_sig,obj_size);
                   32162:        else
                   32163:                fprintf(out_file,"{\t/* sizeof %s == %d */\n",str?str:string,obj_size);
                   32164:        if ( last_ll ) last_line.line++;
                   32165:        delete str;
                   32166: 
                   32167:        print_members();
                   32168:        for (Pbcl b = baselist; b; b = b->next) {       // declare virtual classes
                   32169:                if (b->base != VIRTUAL) continue;
                   32170:                Pclass bcl = b->bclass;
                   32171:                dvirt += bcl->virt_count;
                   32172: //error('d',"%t in %t %d",b->bclass,this,b->allocated);
                   32173:                if (b->allocated==0) continue;
                   32174:                char* str =  0;
                   32175:                if (bcl->lex_level) str = make_local_name(bcl);
                   32176:                puttok(STRUCT);                 // struct bcl Obcl;
                   32177:                putst(str?str:bcl->string);
                   32178:                putcat('O',bcl->string); // leave unencoded
                   32179:                puttok(SM);
                   32180:                delete str;
                   32181:        }
                   32182:        putstring("};\n");
                   32183:        if ( last_ll ) last_line.line++;
                   32184: 
                   32185:        for (nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
                   32186:                if (nn->base==NAME && nn->n_union==0) {
                   32187:                        Ptype t = nn->tp;
                   32188:                        switch (t->base) {
                   32189:                        case FCT:
                   32190:                        case OVERLOAD:
                   32191:                                break;
                   32192:                        default:
                   32193:                                if (nn->n_stclass == STATIC) {
                   32194:                                        TOK b = nn->n_sto;
                   32195: //error('d',"print nn %n tp %t b %k eval %d",nn,nn->tp,b,nn->n_evaluated);
                   32196:                                /*
                   32197:                                        Pname cn;
                   32198:                                        TOK bb = ((cn=nn->tp->is_cl_obj())
                   32199:                                        && Pclass(cn->tp)->has_ctor())==0
                   32200:                                                ?0:b; // force explicit initialization
                   32201:                                        nn->n_sto = (nn->n_evaluated) ? STATIC : bb;
                   32202:                                */
                   32203:                                        nn->n_sto = (nn->n_evaluated) ? STATIC : b;
                   32204:                                        nn->dcl_print(0);
                   32205:                                        nn->n_sto = b;
                   32206:                                }
                   32207:                        }
                   32208:                }
                   32209:        }
                   32210:        if (vtbl_opt != -1) print_all_vtbls(this);      // force declaration
                   32211: //error('d',"dcl_print -> ");
                   32212: }
                   32213: 
                   32214: 
                   32215: char *
                   32216: make_local_name( Pclass cl, int ln ) 
                   32217: {
                   32218:     char *buf; 
                   32219:     if ( cl->in_fct == 0 ) error( 'i', "localC %s missingFN", cl->string ); 
                   32220:     char *fsig = Pfct(cl->in_fct->tp)->f_signature;
                   32221:     if ( fsig == 0 ) fsig = local_sign( cl->in_fct->tp );
                   32222:     char *fs = cl->in_fct->string;
                   32223:     int class_len=cl->strlen+strlen(fsig)+strlen(fs)+strlen(cl->lcl)+4;
                   32224:     int sz = (class_len+20)/32+1; // from vtbl_name()
                   32225: 
                   32226:     if ( Pfct(cl->in_fct->tp)->memof == 0 ) {
                   32227:         sz *= 32;
                   32228:         buf = new char[ sz ];
                   32229: // error('d', "make_local_name: sz: %d", sz );
                   32230: 
                   32231:          if (ln) 
                   32232:              sprintf(buf, "__%d%s__%s__%s%s", class_len, cl->string, fs, fsig, cl->lcl);
                   32233:         else
                   32234:              sprintf(buf, "%s__%s__%s%s", cl->string, fs, fsig, cl->lcl);
                   32235:     }
                   32236:     else 
                   32237:     {
                   32238:         char *cs = Pclass(Pfct(cl->in_fct->tp)->memof)->string;
                   32239:         int len = Pclass(Pfct(cl->in_fct->tp)->memof)->strlen;
                   32240:         if ( len < 10 )
                   32241:             ++class_len;
                   32242:        else 
                   32243:         if ( len > 99 )
                   32244:             class_len += 3;
                   32245:        else class_len += 2;
                   32246:        class_len += len;
                   32247:         sz = (class_len+20)/32+1; 
                   32248:        sz *= 32;
                   32249:         buf = new char[ sz ];
                   32250: // error('d', "make_local_name: sz: %d", sz );
                   32251: 
                   32252:        if ( ln )
                   32253:              sprintf(buf, "__%d%s__%s__%d%s%s%s",class_len,cl->string,fs,len,cs,fsig,cl->lcl);
                   32254:         else sprintf(buf, "%s__%s__%d%s%s%s",cl->string,fs,len,cs,fsig,cl->lcl);
                   32255:     }
                   32256: 
                   32257: #ifdef DENSE
                   32258:     chop( buf );
                   32259: #endif
                   32260: 
                   32261:     return buf;
                   32262: }
                   32263: 
                   32264: 0707071010112046021004440001630000160000010210070466055415700001500000001262print_self.c/* ident "@(#)ctrans:src/print_self.c 1.2" */
                   32265: /* print_self_default.C -- bailout versions of print_self and format_self */
                   32266: /*
                   32267:        $Source: /usr2/odi/lib.src/RCS/print_self_default.C,v $ $RCSfile: print_self_default.C,v $
                   32268:        $Revision: 1.4 $                $Date: 89/09/19 11:49:58 $
                   32269:        $Author: benson $               $Locker:  $
                   32270:        $State: Exp $
                   32271: */
                   32272: 
                   32273: #include "print_self.h"
                   32274: 
                   32275: int ostream_printf (ostream&, const char * ...);
                   32276: 
                   32277: int _Print_self::print_self (ostream& stream) const
                   32278: {
                   32279:     return ostream_printf (stream, "<%s at 0x%p>", 
                   32280:                           this->type_name(), (void *) this);
                   32281: }
                   32282: 
                   32283: int _Print_self::format_self (ostream& stream) const
                   32284: {
                   32285:     return ostream_printf (stream, "<%s at 0x%p>", 
                   32286:                           this->type_name(), (void *) this);
                   32287: }
                   32288: 0707071010112046111004440001630000160000010211170466055421300001500000001261print_self.h/* ident "@(#)ctrans:src/print_self.h 1.2" */
                   32289: /* print_self.H -- base class for objects that want to support
                   32290:    the 'official' print self for \T in printf. */
                   32291: 
                   32292: /*
                   32293:     $Header: /usr2/odi/include/RCS/print_self.H,v 1.4 89/09/19 11:49:19 benson Exp $
                   32294: 
                   32295:     Copyright (c) 1989 by Object Design, Inc., Burlington, Mass.
                   32296:     All rights reserved.
                   32297: 
                   32298: */
                   32299: 
                   32300: #ifndef _PRINT_SELF_CLASS
                   32301: #define _PRINT_SELF_CLASS
                   32302: #include <iostream.h>
                   32303: 
                   32304: class _Print_self {
                   32305:   public:
                   32306:     virtual char * type_name () const { return "OBJECT"; }
                   32307:     virtual int print_self (ostream&) const; // returns count of characters printed.
                   32308:     virtual int format_self (ostream&) const; // returns count of characters printed.
                   32309: };
                   32310: #endif
                   32311: 0707071010112044421004440001630000160000010206300466055407100000700000010531repr.c/*ident     "@(#)ctrans:src/repr.c  1.4" */
                   32312: /**************************************************************************
                   32313: 
                   32314:         C++ source for cfront, the C++ compiler front-end
                   32315:         written in the computer science research center of Bell Labs
                   32316: 
                   32317:         Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   32318:         THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   32319: 
                   32320: repr.c:
                   32321: 
                   32322: *****************************************************************************/
                   32323: 
                   32324: #include "cfront.h"
                   32325: 
                   32326: char* oper_name(TOK op)
                   32327: /*
                   32328:        return the string representation of operator "op"
                   32329: */
                   32330: {
                   32331:        switch (op) {
                   32332:        default:        error('i',"oper_name(%k)",op);
                   32333:        case GNEW:
                   32334:        case NEW:       return "__nw";
                   32335:        case GDELETE:
                   32336:        case DELETE:    return "__dl";
                   32337:        case MUL:       return "__ml";
                   32338:        case DIV:       return "__dv";
                   32339:        case MOD:       return "__md";
                   32340:        case UPLUS:
                   32341:        case PLUS:      return "__pl";
                   32342:        case MINUS:
                   32343:        case UMINUS:    return "__mi";
                   32344:        case LS:        return "__ls";
                   32345:        case RS:        return "__rs";
                   32346:        case EQ:        return "__eq";
                   32347:        case NE:        return "__ne";
                   32348:        case LT:        return "__lt";
                   32349:        case GT:        return "__gt";
                   32350:        case LE:        return "__le";
                   32351:        case GE:        return "__ge";
                   32352:        case AND:
                   32353:        case ADDROF:    return "__ad";
                   32354:        case OR:        return "__or";
                   32355:        case ER:        return "__er";
                   32356:        case ANDAND:    return "__aa";
                   32357:        case OROR:      return "__oo";
                   32358:        case NOT:       return "__nt";
                   32359:        case COMPL:     return "__co";
                   32360:        case INCR:      return "__pp";
                   32361:        case DECR:      return "__mm";
                   32362:        case CALL:      return "__cl";
                   32363:        case DEREF:     return "__vc";
                   32364:        case ASSIGN:    return "__as";
                   32365:        case REF:       return "__rf";
                   32366:        case ASPLUS:    return "__apl";
                   32367:        case ASMINUS:   return "__ami";
                   32368:        case ASMUL:     return "__amu";
                   32369:        case ASDIV:     return "__adv";
                   32370:        case ASMOD:     return "__amd";
                   32371:        case ASLS:      return "__als";
                   32372:        case ASRS:      return "__ars";
                   32373:        case ASAND:     return "__aad";
                   32374:        case ASOR:      return "__aor";
                   32375:        case ASER:      return "__aer";
                   32376:        case CTOR:      return "__ct";
                   32377:        case DTOR:      return "__dt";
                   32378: //     operator T              "__op"<signature of T>
                   32379: //     case SIZEOF:    return "sizeof";
                   32380:        case CM:        return "__cm";
                   32381:        case REFMUL:    return "__rm";
                   32382: // library functions:
                   32383: //                             "_vec_delete"
                   32384: //                             "_vec_new"
                   32385: //                             "_main"
                   32386:        }
                   32387: }
                   32388: 
                   32389: #define new_op(ss,v) keys[v]=ss
                   32390: 
                   32391: void otbl_init()
                   32392: /*
                   32393:        operator representation table
                   32394: */
                   32395: {
                   32396:        new_op("->",REF);
                   32397:        new_op("." ,DOT);
                   32398:        new_op(".* or ->*" ,REFMUL);
                   32399:        new_op("mdot" ,REFMUL);
                   32400:        new_op("!" ,NOT);
                   32401:        new_op("~" ,COMPL);
                   32402:        new_op("++",INCR);
                   32403:        new_op("--",DECR);
                   32404:        new_op("*" ,MUL);
                   32405:        new_op("&" ,AND);
                   32406:        new_op("&" ,ADDROF);
                   32407:        new_op("&" ,G_ADDROF);
                   32408:        new_op("/" ,DIV);
                   32409:        new_op("%" ,MOD);
                   32410:        new_op("+" ,PLUS);
                   32411:        new_op("+" ,UPLUS);
                   32412:        new_op("-" ,MINUS);
                   32413:        new_op("-" ,UMINUS);
                   32414:        new_op("<<",LS);
                   32415:        new_op(">>",RS);
                   32416:        new_op("<" ,LT);
                   32417:        new_op(">" ,GT);
                   32418:        new_op("<=",LE);
                   32419:        new_op(">=",GE);
                   32420:        new_op("==",EQ);
                   32421:        new_op("!=",NE);
                   32422:        new_op("^" ,ER);
                   32423:        new_op("|" ,OR);
                   32424:        new_op("&&",ANDAND);
                   32425:        new_op("||",OROR);
                   32426:        new_op("?:" ,QUEST);
                   32427: //     new_op(":" ,COLON);
                   32428:        new_op("=" ,ASSIGN);
                   32429:        new_op("," ,CM);
                   32430:        new_op("," ,G_CM);
                   32431: 
                   32432:        new_op(";" ,SM);
                   32433:        new_op("{" ,LC);
                   32434:        new_op("}" ,RC);
                   32435:        new_op("(" ,LP);
                   32436:        new_op(")" ,RP);
                   32437:        new_op("[" ,LB);
                   32438:        new_op("]" ,RB);
                   32439: 
                   32440:        new_op("+=",ASPLUS);
                   32441:        new_op("-=",ASMINUS);
                   32442:        new_op("*=",ASMUL);
                   32443:        new_op("/=",ASDIV);
                   32444:        new_op("%=",ASMOD);
                   32445:        new_op("&=",ASAND);
                   32446:        new_op("|=",ASOR);
                   32447:        new_op("^=",ASER);
                   32448:        new_op(">>=",ASRS);
                   32449:        new_op("<<=",ASLS);
                   32450: 
                   32451: //     new_op("sizeof",SIZEOF);
                   32452: //     new_op("new",NEW);
                   32453: //     new_op("delete",DELETE);
                   32454: 
                   32455:        new_op("0" ,ZERO);
                   32456:        new_op("[]" ,DEREF);
                   32457:        new_op("expression list", ELIST);
                   32458:        new_op("initializer list", ILIST);
                   32459:        new_op("static initializer", STAT_INIT);
                   32460:        new_op("()", CALL);
                   32461:        new_op("generated function call",G_CALL);
                   32462:        new_op("inline function call",ICALL);
                   32463:        new_op("cast",CAST);
                   32464:        new_op("inline argument",ANAME);
                   32465:        new_op("text",TEXT);
                   32466:        new_op(".*",MEMPTR);
                   32467: 
                   32468:        new_op("class type", COBJ);
                   32469:        new_op("enum type", EOBJ);
                   32470:        new_op("union", ANON);
                   32471: 
                   32472:        new_op("function",FCT);
                   32473:        new_op("pointer",PTR);
                   32474:        new_op("reference",RPTR);
                   32475:        new_op("array",VEC);
                   32476:        new_op("identifier",ID);
                   32477:        new_op("name",NAME);
                   32478:        new_op("...",ELLIPSIS);
                   32479:        new_op("::",MEM);
                   32480:        new_op("type name",TYPE);
                   32481:        new_op("tname",TNAME);
                   32482:        new_op("{}",BLOCK);
                   32483:        new_op("pair",PAIR);
                   32484:        new_op("declaration",DCL);
                   32485:        new_op("character constant",CCON);
                   32486:        new_op("integer constant",ICON);
                   32487:        new_op("float constant",FCON);
                   32488:        new_op("integer value",IVAL);
                   32489:        new_op("string",STRING);
                   32490:        new_op("label",LABEL);
                   32491:        new_op("'class', 'struct', or 'union'",AGGR);
                   32492:        new_op(" argument",ARG);
                   32493:        new_op(" empty expression",DUMMY);
                   32494:        new_op(" ::new",GNEW);
                   32495:        new_op(" constructor call",VALUE);
                   32496:        new_op(" ::delete",GDELETE);
                   32497:        new_op(ansi_opt?" long double":" double",LDOUBLE);
                   32498:        new_op(" typedef",NESTED); // did not want to introduce new TOKEN
                   32499: }
                   32500: 0707071010112044431004440001630000160000010206400466055407500001000000067265simpl.c/*ident    "@(#)ctrans:src/simpl.c 1.3" */
                   32501: /******************************************************************
                   32502: 
                   32503:        C++ source for cfront, the C++ compiler front-end
                   32504:        written in the computer science research center of Bell Labs
                   32505: 
                   32506:        Copyright (c) 1984 AT&T, Inc. All rights Reserved
                   32507:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   32508: 
                   32509: simpl.c:
                   32510: 
                   32511:        simplify the typechecked function
                   32512:        remove:         classes:
                   32513:                                class fct-calls
                   32514:                                operators
                   32515:                                value constructors and destructors
                   32516:                        new and delete operators (replace with function calls)
                   32517:                        initializers            (turn them into statements)
                   32518:                        constant expressions            (evaluate them)
                   32519:                        inline functions                (expand the calls)
                   32520:                        enums                           (make const ints)
                   32521:                        unreachable code                (delete it)
                   32522:        make implicit coersions explicit
                   32523: 
                   32524:        in general you cannot simplify something twice
                   32525: 
                   32526: *******************************************************************/
                   32527: 
                   32528: #include "cfront.h"
                   32529: 
                   32530: Pname new_fct;
                   32531: Pname del_fct;
                   32532: Pname vec_new_fct;
                   32533: Pname vec_del_fct;
                   32534: 
                   32535: Pstmt del_list;
                   32536: Pstmt break_del_list;
                   32537: Pstmt continue_del_list;
                   32538: 
                   32539: //bit not_inl; // is the current function an inline?
                   32540: Pname curr_fct;        // current function
                   32541: Pexpr init_list;
                   32542: Pexpr one;
                   32543: 
                   32544: Ptype Pfct_type;
                   32545: Ptype Pvptr_type;
                   32546: Pbase mptr_type;
                   32547: Ptype size_t_type;
                   32548: 
                   32549: Pstmt trim_tail(Pstmt tt);
                   32550: Pname find_vptr(Pclass);
                   32551: char *get_classname(char*);
                   32552: char *drop_classname(char*);
                   32553: loc no_where;  // 0,0
                   32554: 
                   32555: int imeasure;  // a counter trying to measure the complexity of a function
                   32556:                // body to try to avoid expanding ``monster'' inlines.
                   32557: 
                   32558: static Pclass topclass;
                   32559: 
                   32560: void simpl_init()
                   32561: {
                   32562:        char* ns = oper_name(NEW);
                   32563:        char* ds = oper_name(DELETE);
                   32564: 
                   32565:        size_t_type = Pvoid_type->tsizeof()>uint_type->tsizeof()?ulong_type:uint_type;
                   32566: 
                   32567:        Pname nw = new name(ns);
                   32568:        nw->n_oper = NEW;
                   32569:        Pname a = new name;
                   32570:        a->tp = size_t_type;
                   32571:        nw->tp = new fct(Pvoid_type,a,1);
                   32572:        new_fct = nw->dcl(gtbl,EXTERN); // void* operator new(long);
                   32573:        delete nw;
                   32574:  //    new_fct->use();
                   32575: 
                   32576:        Pname dl = new name(ds);
                   32577:        dl->n_oper = DELETE;
                   32578:        a = new name;
                   32579:        a->tp = Pvoid_type;
                   32580:        dl->tp = new fct(void_type,a,1);
                   32581:        del_fct = dl->dcl(gtbl,EXTERN);
                   32582:        delete dl;
                   32583:  //    del_fct->use();
                   32584: 
                   32585: 
                   32586:        Pname vn = new name("__vec_new");
                   32587:        Pname vd = new name("__vec_delete");
                   32588: 
                   32589:        a = new name;
                   32590:        a->tp = Pvoid_type;
                   32591:        Pname al = a;
                   32592:        a = new name;
                   32593:        a->tp = int_type;
                   32594:        a->n_list = al;
                   32595:        al = a;
                   32596:        a = new name;
                   32597:        a->tp = int_type;
                   32598:        a->n_list = al;
                   32599:        al = a;
                   32600:        a = new name;   
                   32601:        a->tp = Pvoid_type;
                   32602:        a->n_list = al;
                   32603:        al = a;                         /* (Pvoid, int, int, Pvoid) */
                   32604: 
                   32605:        vec_new_fct = gtbl->insert(vn,0);
                   32606:        delete vn;
                   32607:        vec_new_fct->tp = new fct(Pvoid_type,al,1);
                   32608:        Pfct(vec_new_fct->tp)->f_linkage = linkage_C;
                   32609:        vec_new_fct->n_scope = EXTERN;
                   32610:        PERM(vec_new_fct);
                   32611:        PERM(vec_new_fct->tp);
                   32612:        vec_new_fct->use();
                   32613:        vec_new_fct->dcl_print(0);
                   32614: 
                   32615:        a = new name;
                   32616:        a->tp = int_type;
                   32617:        al = a;
                   32618:        a = new name;
                   32619:        a->tp = int_type;
                   32620:        a->n_list = al;
                   32621:        al = a;
                   32622:        a = new name;
                   32623:        a->tp = Pvoid_type;
                   32624:        a->n_list = al;
                   32625:        al = a;
                   32626:        a = new name;
                   32627:        a->tp = int_type;
                   32628:        a->n_list = al;
                   32629:        al = a;
                   32630:        a = new name;
                   32631:        a->tp = int_type;
                   32632:        a->n_list = al;
                   32633:        al = a;
                   32634:        a = new name;   
                   32635:        a->tp = Pvoid_type;
                   32636:        a->n_list = al;
                   32637:        al = a;                         /* (Pvoid, int, int, Pvoid, int, int) */
                   32638: 
                   32639:        vec_del_fct = gtbl->insert(vd,0);
                   32640:        delete vd;
                   32641:        vec_del_fct->tp = new fct(void_type,al,1);
                   32642:        Pfct(vec_del_fct->tp)->f_linkage = linkage_C;
                   32643:        vec_del_fct->n_scope = EXTERN;
                   32644:        PERM(vec_del_fct);
                   32645:        PERM(vec_del_fct->tp);
                   32646:        vec_del_fct->use();
                   32647:        vec_del_fct->dcl_print(0);
                   32648: 
                   32649:        one = new ival(1);
                   32650:        one->tp = int_type;
                   32651:        PERM(one);
                   32652:        
                   32653:        Pfct_type = new fct(int_type,0,1);      // int (*)()
                   32654:        Pfct_type = Pfct_type->addrof();
                   32655:        PERM(Pfct_type);
                   32656: 
                   32657:        putstring("typedef int (*__vptp)();\n");
                   32658:        putstring("struct __mptr {short d; short i; __vptp f; };\n");
                   32659:        Pname b = new name("__mptr");
                   32660:         b->tp = new classdef(STRUCT);
                   32661:         b->tp->defined = 1;
                   32662:         Pclass(b->tp)->obj_size = 8;
                   32663:        mptr_type = new basetype(COBJ,b);
                   32664:        PERM(mptr_type);
                   32665: 
                   32666:        Pvptr_type = mptr_type->addrof();
                   32667:        PERM(Pvptr_type);
                   32668: }
                   32669: 
                   32670: Ptable scope;          /* current scope for simpl() */
                   32671: Pname expand_fn;       /* name of function being expanded or 0 */
                   32672: Ptable expand_tbl;     /* scope for inline function variables */
                   32673: 
                   32674: Pname classdef::has_oper(TOK op)
                   32675: {
                   32676:        Pexpr n = find_name(oper_name(op),0);
                   32677:        if (n == 0) return 0;
                   32678: 
                   32679:        while (n->base==REF || n->base==MDOT) {
                   32680:                Pexpr e = Pexpr(n);
                   32681:                n = Pname(n->mem);
                   32682:                delete e;
                   32683:        }
                   32684:        if (n->tp->base==FCT && Pname(n)->n_dcl_printed==0) Pname(n)->dcl_print(0);
                   32685:        return Pname(n);
                   32686: }
                   32687: 
                   32688: int is_expr(Pstmt s)
                   32689: /*
                   32690:        is this statement simple enough to be converted into an expression for
                   32691:        inline expansion?
                   32692: */
                   32693: {
                   32694:        int i = 0;
                   32695:        while (s->base == BLOCK) {
                   32696:                if (s->s == 0) return 1;
                   32697:                s = s->s;
                   32698:        }
                   32699:        for (Pstmt ss = s; ss; ss = ss->s_list) {
                   32700: //error('d',"ss %k",ss->base);
                   32701:                switch (ss->base) {
                   32702:                case BLOCK:
                   32703:                        if (Pblock(ss)->memtbl || is_expr(ss->s)==0) return 0;
                   32704:                case SM:
                   32705:                        if (ss->e && ss->e->base==ICALL) {
                   32706:                                Pname fn = ss->e->il->fct_name;
                   32707:                                Pfct f = Pfct(fn->tp);
                   32708:                                if (f->f_expr == 0) return 0;
                   32709:                        }
                   32710:                        break;
                   32711:                case IF:
                   32712:                        if (is_expr(ss->s)==0) return 0;
                   32713:                        if (ss->else_stmt && is_expr(ss->else_stmt)==0) return 0;
                   32714:                        break;
                   32715:                default:
                   32716:                        return 0;
                   32717:                }
                   32718:                i++;
                   32719:        }
                   32720:        return i;
                   32721: }
                   32722: 
                   32723: int no_of_returns;
                   32724: 
                   32725: void name::simpl()
                   32726: {
                   32727: //error('d',"name::simpl%n %d %k",this,tp->base,tp->base);
                   32728:        if (base == PUBLIC) return;
                   32729: 
                   32730:        if (tp == 0) error('i',"%n->N::simple(tp==0)",this);
                   32731: 
                   32732:        switch (tp->base) {
                   32733:        case 0:
                   32734:                error('i',"%n->N::simpl(tp->B==0)",this);
                   32735: 
                   32736:        case TYPE:
                   32737:        case VEC:
                   32738:        case PTR:
                   32739:        {
                   32740:                Ptype t = tp;
                   32741:        xx:
                   32742:                switch (t->base) {
                   32743:                case TYPE:      t = Pbase(t)->b_name->tp;       goto xx;
                   32744:                case VEC:       t = Pvec(t)->typ;               goto xx;
                   32745:                case PTR:       t = Pptr(t)->typ;               goto xx;
                   32746:                case FCT:       break;
                   32747:                }
                   32748:                break;
                   32749:        }
                   32750: 
                   32751:        case OVERLOAD:
                   32752:        {       for (Plist gl = Pgen(tp)->fct_list; gl; gl=gl->l) gl->f->simpl();
                   32753:                break;
                   32754:        }
                   32755: 
                   32756:        case FCT:
                   32757:        {       Pfct f = Pfct(tp);
                   32758:                Pname n;
                   32759:                Pname th = f->f_this;
                   32760: 
                   32761:                if (th) {
                   32762:                        // Make "this" a register if it is used more than twice:
                   32763:                        if (th->n_addr_taken) error("&this");
                   32764:                        th->n_stclass = (2 < th->n_used) ? REGISTER : AUTO;
                   32765:                        if (warning_opt
                   32766:                        && th->n_assigned_to
                   32767:                        && th->n_assigned_to!=FUDGE111)
                   32768:                                error('w',&where,"assignment to this (anachronism)");
                   32769:                }
                   32770: 
                   32771:                if (tp->defined & (SIMPLIFIED | ~DEFINED) ) return;
                   32772: 
                   32773:                for (n=f->f_args; n; n=n->n_list) n->simpl();
                   32774: 
                   32775:                if (f->body) {
                   32776:                        Ptable oscope = scope;
                   32777:                        Pname ocurr = curr_fct;
                   32778:                        int oim = imeasure;
                   32779:                        scope = f->body->memtbl;
                   32780: //error('d',"body");
                   32781:                        if (scope == 0) error('i',"%n memtbl missing",this);
                   32782:                        curr_fct = this;
                   32783:                        f->simpl();
                   32784:                        if (f->f_inline==0 || debug_opt)
                   32785:                                f->f_imeasure = 0;      // not a converted inline
                   32786:                        else {
                   32787:        
                   32788:                                if (warning_opt && f->f_virtual)
                   32789:                                        error('w',"virtual function %n cannot be inlined",this);
                   32790:                                // first check if the function is too large to
                   32791:                                // be worth inlining
                   32792:                                if (12<f->f_imeasure) { // cut-over point:
                   32793:                                                        // about 12 assignments
                   32794:                                                        // f->f_imeasure indicates
                   32795: 
                   32796:                                        if (warning_opt) {
                   32797:                                                error('w',"%n too large for inlining",this);
                   32798:                                        }
                   32799:                                        f->f_inline = 0;// a converted inline
                   32800: //error('d',"don't inline%n %d %d %d",this,this,f,f->f_imeasure);
                   32801:                                        scope = oscope;
                   32802:                                        tp->defined |= SIMPLIFIED;
                   32803:                                        return;
                   32804:                                }
                   32805:                                int i = 0;
                   32806:                                for (n=f->f_args; n; n=n->n_list) {
                   32807:                                        n->base = ANAME;
                   32808:                                        n->n_val = i++;
                   32809:        // ??                           if (n->n_table != scope) error('i',"aname scope: %d %n %d %d\n",n,n,n->n_table,scope);
                   32810:                                }
                   32811:                                expand_tbl = (f->returns->base!=VOID || n_oper==CTOR) ? scope : 0;
                   32812:                                expand_fn = this;
                   32813: 
                   32814:                                if (expand_tbl) {
                   32815:                                genlab:
                   32816:                                                // value returning: generate expr
                   32817:                                                // the body still holds the memtbl
                   32818:                                        Pexpr ee = Pexpr(f->body->expand());
                   32819:                                        Ptype t = 0;
                   32820:                                        if (f->s_returns) {
                   32821:                                                if (ee->tp!=f->s_returns) t = f->s_returns;
                   32822:                                        }
                   32823:                                        else if (ee->tp!=f->returns)
                   32824:                                                t = f->returns;
                   32825:                                        // VCVC assumes VOID is output as CHAR:
                   32826:                                        if (t && t==void_type)
                   32827:                                                ee = new expr(CM,ee,new cast(char_type,zero));
                   32828:                                        f->f_expr = (ee->base==CM) ? ee : new expr(CM,zero,ee);
                   32829:                                        // print.c assumes expansion into comma expression
                   32830:                                }
                   32831:                                else {
                   32832:                                        if (is_expr(f->body)) {
                   32833:                                                // can generate expr: do
                   32834:                                                expand_tbl = scope;
                   32835:                                                goto genlab;
                   32836:                                        }
                   32837:                                        // not value return: can generate block
                   32838:                                        f->f_expr = 0;
                   32839:                                        f->body = Pblock(f->body->expand());
                   32840:                                }
                   32841:                                expand_fn = 0;
                   32842:                                expand_tbl = 0;
                   32843:                        }
                   32844:                        scope = oscope;
                   32845:                        curr_fct = ocurr;
                   32846:                        imeasure = oim;
                   32847:                }
                   32848:                break;
                   32849:        }
                   32850: 
                   32851:        case CLASS:
                   32852:                Pclass(tp)->simpl();
                   32853:        }
                   32854: 
                   32855: //     if (n_initializer) n_initializer->simpl();
                   32856:         if (n_key != NESTED && n_initializer) n_initializer->simpl();
                   32857:        tp->defined |= SIMPLIFIED;
                   32858: }
                   32859: 
                   32860: Pexpr call_ctor(Ptable tbl, Pexpr p, Pexpr ctor, Pexpr args, int d, Pexpr vb_args)
                   32861: {
                   32862:        Pexpr ee = new ref(d,p,ctor);
                   32863:        if (p==0 || tbl==0) ee->tp = ctor->tp;
                   32864: //error('d',"call_ctor(tbl %d, p %d, %n, args %d)",tbl,p,ctor,args);
                   32865:        if (args && args->base!=ELIST) args = new expr(ELIST,args,0);
                   32866:        ee = new expr(G_CALL,ee,args);
                   32867:        Pname n = Pname(ctor);
                   32868:        while (n->base == MDOT) n = Pname(n->mem);
                   32869:        if (n->tp->base == FCT) ee->fct_name = n;
                   32870:        if (tbl)
                   32871:                ee = ee->typ(tbl);
                   32872:        else if (n->tp->base == FCT)
                   32873:                ee->tp = Pfct(n->tp)->s_returns;
                   32874:        if (ee->tp == any_type) return ee;
                   32875:        args = ee->e2;
                   32876: 
                   32877:        if (vb_args == 0) {             // attach zero vbase arguments
                   32878:                Pfct f = Pfct(ee->fct_name->tp);        // not n->fct_name
                   32879:                for (Pname nn = f->f_args->n_list; nn && nn!=f->argtype; nn=nn->n_list)
                   32880:                        args = new expr(ELIST,zero,args);
                   32881:        }
                   32882:        else {                          // attach vbase arguments
                   32883:                if (args) {
                   32884:                        for (Pexpr d = vb_args; d->e2; d=d->e2);
                   32885:                        d->e2 = args;
                   32886:                }
                   32887:                args = vb_args;
                   32888:        }
                   32889: 
                   32890:        ee->e2 = args;
                   32891:        return ee;
                   32892: }
                   32893: 
                   32894: Pexpr call_dtor(Pexpr p, Pexpr dtor, Pexpr arg, int d, Pexpr vb_args)
                   32895: {
                   32896: // error('d',"call dtor %k %n %t vb_args %d",d,dtor,dtor->tp,vb_args);
                   32897:        Pexpr r = new ref(d,p,dtor);
                   32898: 
                   32899:        if (arg && vb_args) 
                   32900:                arg = new ival(3);
                   32901:        else if (vb_args) 
                   32902:                arg = new ival(2);
                   32903:        else if (arg==0)
                   32904:                arg = zero;
                   32905:        if (arg->tp == 0) arg->tp = int_type;
                   32906: 
                   32907:        Pexpr aa = new expr(ELIST,arg,0); // argument controlling deallocation
                   32908:                                          // 2: destroy vbases
                   32909:                                          // 1: dealllocate, 0: don't
                   32910: 
                   32911:        Pfct f = Pfct(dtor->tp);                // attach virtual base arguments
                   32912: //     for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) {
                   32913: //             Pexpr xx = vb_args ? new cast(nn->tp,one) : zero;
                   32914: //             aa = new expr(ELIST,xx,aa);
                   32915: //     }
                   32916: 
                   32917: 
                   32918:        Pexpr ee = new call(r,aa);
                   32919:        while (dtor->base == MDOT) dtor = dtor->mem;
                   32920:        if (d == REF)   // could be virtual
                   32921:                ee->fct_name = Pname(dtor);
                   32922:        else {  // virtual suppressed, store fct name 
                   32923:                r->n_initializer = dtor;
                   32924:                ee->fct_name = 0;
                   32925:        }
                   32926:        ee->base = G_CALL;
                   32927:        ee->tp = void_type;
                   32928: 
                   32929:         if (f->memof->c_body == 1) f->memof->dcl_print(0);
                   32930:        if (Pname(dtor)->n_dcl_printed==0) Pname(dtor)->dcl_print(0);
                   32931: 
                   32932:        return ee;
                   32933: }
                   32934: 
                   32935: //extern int new_used; // pre-define new and delete only if the user didn't
                   32936: 
                   32937: Pstmt fct::dtor_simpl(Pclass cl, Pexpr th)
                   32938: {
                   32939:        Pstmt dtail = 0;
                   32940: //error('d',"simpl_dtor(%t) a %d",cl,f_args);
                   32941: //     if (new_used == 0) new_init();
                   32942: 
                   32943:        Pname fa = new name("__free");  // fake argument for dtor
                   32944:        fa->tp = int_type;
                   32945:        Pname free_arg = fa->dcl(body->memtbl,ARG);
                   32946:        free_arg->where = no_where;
                   32947:        delete fa;
                   32948:        Pname a = f_args;
                   32949:        if (a==0 || a->n_list==0) error('i',"__freeA missing in destructor for %t",cl);
                   32950:        Pname p = 0;
                   32951:        for(;;p=a,a=a->n_list) {        // replace nameless fake argument
                   32952: //error('d',"a %d %t",a,a->tp);
                   32953:                if (a->n_list == 0) {
                   32954:                //      a->n_list = free_arg;
                   32955:                        DEL(p->n_list);
                   32956:                        p->n_list = free_arg;
                   32957:                        break;
                   32958:                }
                   32959:        } 
                   32960: 
                   32961:        // generate calls to destructors for all members of class cl:
                   32962:        Ptable tbl = cl->memtbl;
                   32963:        int i = 1;
                   32964:        for (Pname m=tbl->get_mem(i); m; m=tbl->get_mem(++i) ) {
                   32965: 
                   32966:                if (m->n_stclass == STATIC || m->base == PUBLIC) continue;
                   32967: 
                   32968:                Ptype t = m->tp;
                   32969:                Pexpr ee = 0;
                   32970:                Pname cn;
                   32971:                Pname dtor;
                   32972: 
                   32973:                if (cn = t->is_cl_obj()) {
                   32974:                        Pclass cl = (Pclass)cn->tp;
                   32975:                        if (dtor = cl->has_dtor()) {    // dtor(this,0,ones);
                   32976:                                ee = new ref(REF,th,m);
                   32977:                                ee->tp = m->tp;
                   32978:                                ee = call_dtor(ee,dtor,0,DOT,one);
                   32979:                                check_visibility(dtor,0,Pclass(dtor->n_table->t_name->tp),tbl,curr_fct);
                   32980:                        }
                   32981:                }
                   32982:                else if (cl_obj_vec) {
                   32983:                        Pclass cl = Pclass(cl_obj_vec->tp);
                   32984:                        if (dtor = cl->has_dtor()) {
                   32985:        Pfct f = Pfct(dtor->tp);
                   32986:        int i = 0;
                   32987:        for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) i++;
                   32988: //error('d',"dtor %n i %d",dtor,i);
                   32989:                                ee = new ref(REF,th,m);
                   32990:                                ee->tp = m->tp;
                   32991:                                ee = cdvec(vec_del_fct,ee,cl,dtor,0,new ival(i));
                   32992:                                check_visibility(dtor,0,Pclass(dtor->n_table->t_name->tp),tbl,curr_fct);
                   32993:                        }
                   32994:                }
                   32995: 
                   32996:                if (ee) {
                   32997:                        Pstmt es = new estmt(SM,curloc,ee,0);
                   32998:                        // reverse order of destructors for members
                   32999:                        es->s_list = del_list;
                   33000:                        del_list = es;
                   33001:                        if (dtail == 0) dtail = es;
                   33002:                }
                   33003:        }
                   33004: 
                   33005: 
                   33006:        Pexpr ee = 0;
                   33007:        // look for bases with destructors:
                   33008:        // generate: dtor(base,0);
                   33009: 
                   33010:        Pbcl b = 0;     // get dtors in order with virtual bases last
                   33011:        Pbcl t = 0;
                   33012:        for (Pbcl l = cl->baselist; l; l=l->next) {
                   33013:                if (l->base != VIRTUAL) {
                   33014:                        Pbcl x = new basecl(l->bclass,0);
                   33015:                        if (t == 0)
                   33016:                                b  = x;
                   33017:                        else
                   33018:                                t->next = x;
                   33019:                        t = x;
                   33020:                        x->base = l->base;
                   33021:                        x->obj_offset = l->obj_offset;
                   33022:                }
                   33023:        }
                   33024:        for (l = cl->baselist; l; l=l->next) {
                   33025:                if (l->base == VIRTUAL) {
                   33026:                        b = new basecl(l->bclass,b);
                   33027:                        b->base = l->base;
                   33028:                        b->obj_offset = l->obj_offset;
                   33029:                }
                   33030:        }
                   33031:        Pexpr ve = 0;
                   33032: 
                   33033:        for (; b; b=l) {
                   33034:                Pclass bcl = b->bclass;
                   33035:                l = b->next;
                   33036:                Pname dtor = bcl->has_dtor();
                   33037: 
                   33038:                if (dtor) { 
                   33039:                        Pexpr val = rptr(bcl->this_type,th,b->obj_offset);
                   33040:                        val = val->contents();
                   33041:                        Pexpr e = call_dtor(val,dtor);
                   33042:                        if (b->base == VIRTUAL) {
                   33043:                                // if (x) this->x.dtor(); where x is a vbase
                   33044:                                for (Pname dd = f_this->n_list; dd!=argtype; dd=dd->n_list) 
                   33045:                                if (strcmp(dd->string,bcl->string)==0) break;
                   33046: 
                   33047:                                if (ansi_opt) { // q?void:int would be an error
                   33048:                                        e = new expr(G_CM,e,zero);
                   33049:                                        e->tp = zero_type;
                   33050:                                }
                   33051:                                e = new expr(QUEST,e,zero);
                   33052:                                Pexpr two = new ival(2);
                   33053:                                two->tp = int_type;
                   33054:                                e->cond = new expr (AND,free_arg,two);//dd;
                   33055:                        }
                   33056:                        ee = ee ? new expr(CM,e,ee) : e;
                   33057:                }
                   33058:                delete b;
                   33059:        }
                   33060: 
                   33061:        Pstmt es = ee ? new estmt(SM,curloc,ee,0) : 0;
                   33062: 
                   33063:        ee = new expr(ELIST,th,0);      // free storage
                   33064:        Pname n = new name(oper_name(DELETE));
                   33065:        Pexpr del = find_name(n,cl,scope,CALL,curr_fct);
                   33066:        if (del->tp->base==OVERLOAD || Pfct(del->tp)->nargs==2) {
                   33067:                Pexpr ss = new texpr(SIZEOF,cl,0);
                   33068:                ss->tp = uint_type;
                   33069:                ee->e2 = new expr(ELIST,ss,0);
                   33070:        }
                   33071:        ee = new call(del,ee);
                   33072:        ee->tp = ee->call_fct(scope);
                   33073: 
                   33074:        Pstmt ess = new estmt(SM,curloc,ee,0);
                   33075:        ess = new ifstmt(curloc,new expr(AND,free_arg,one),ess,0);
                   33076:        if (es)
                   33077:                es->s_list = ess;
                   33078:        else
                   33079:                es = ess;
                   33080: 
                   33081:        free_arg->use();
                   33082:        Pname(th)->use();
                   33083: 
                   33084:        if (dtail)
                   33085:                dtail->s_list = es;
                   33086:        else
                   33087:                del_list = es;
                   33088: 
                   33089:        del_list = new ifstmt(curloc,th,del_list,0);
                   33090:        if (del_list) del_list->simpl();
                   33091:        return dtail;
                   33092: }
                   33093: 
                   33094: 
                   33095: Pclass find_vbase_ptr(Pclass cl, Pclass vbase)
                   33096: {
                   33097:        for (Pbcl bb = cl->baselist; bb; bb = bb->next) {
                   33098:                if (bb->base==VIRTUAL) {
                   33099:                        if (bb->bclass==vbase && bb->ptr_offset) return cl;
                   33100:                }
                   33101:                else {
                   33102:                        Pclass f = find_vbase_ptr(bb->bclass,vbase);
                   33103:                        if (f) return f;
                   33104:                }
                   33105:        }
                   33106:        return 0;
                   33107: }
                   33108: 
                   33109: Pclass second_base(Pclass cl, Pclass base)
                   33110: {
                   33111: //error('d',"second_base(%t,%t)",cl,base);
                   33112:        for (Pbcl b = cl->baselist; b && b->base==NAME; b = b->next) {
                   33113:                if (b->bclass==base) {
                   33114:                        if (b==cl->baselist) return 0;
                   33115:                        return base;
                   33116:                }
                   33117:                Pclass bb = second_base(b->bclass,base);
                   33118:                if (bb == Pclass(-1)) continue; // not found
                   33119:                if (bb) {
                   33120:                        if (b!=cl->baselist) error('s',"C hierarchy too complicated");
                   33121:                        return bb;      // second base of b->bclass
                   33122:                }
                   33123:                if (b==cl->baselist) return 0;
                   33124:                return b->bclass;       // b->bclass is second base
                   33125:        }
                   33126:        return Pclass(-1);
                   33127: }
                   33128: 
                   33129: //Pclass topclass;
                   33130: 
                   33131: Pexpr classdef::get_vptr_exp(char *s)
                   33132: {
                   33133: //error('d',"%t::get_vptr_exp(%s)",this,s?s:"0");
                   33134:        if (c_body == 1) dcl_print(0);
                   33135:        if (c_body == 3) print_all_vtbls(this);
                   33136:        if (s == 0) return find_vptr(this);
                   33137:        Pbcl b = get_base(get_classname(s));
                   33138:        Pexpr vp = b->bclass->get_vptr_exp(drop_classname(s));
                   33139:        if (b==baselist && b->base!=VIRTUAL) return vp;
                   33140:        vp = new mdot(b->bclass->string,vp);
                   33141:        if (c_body == 1) b->bclass->dcl_print(0);
                   33142:        if (c_body == 3) b->bclass->print_all_vtbls(b->bclass);
                   33143:        if (b->base == VIRTUAL) {
                   33144:                vp->i1 = 1;
                   33145:                if (b->ptr_offset == 0) { // pointer to base in intermediate base
                   33146:                        Pclass bb = find_vbase_ptr(this,b->bclass);
                   33147:                        Pclass sb = second_base(topclass,bb);
                   33148: //error('d',"mdot %t %t : %d %t ",topclass,bb,sb,sb==Pclass(-1)?0:sb);
                   33149:                        if (sb && sb!=Pclass(-1)) vp = new mdot(sb->string,vp);
                   33150:                }
                   33151:        }
                   33152:        return vp;
                   33153: }
                   33154: 
                   33155: int fct::ctor_simpl(Pclass cl, Pexpr th)
                   33156: {
                   33157:        Ptable tbl = cl->memtbl;
                   33158: 
                   33159:        int ass_count = 0;
                   33160:        init_list = 0;
                   33161: //error('d',"ctor_simpl %t: %t",cl,this);
                   33162:        /*
                   33163:                initialization order:
                   33164:                (1)     virtual base pointers and virtual bases
                   33165:                                (they may be used in non-virtual bases)
                   33166:                (2)     non-virtual bases
                   33167:                (3)     virtual function pointers
                   33168:                (4)     members
                   33169:        */
                   33170: 
                   33171:        // initialize virtual base pointers and virtual base objects
                   33172:        for (Pbcl l = cl->baselist; l; l=l->next) {
                   33173:                Pexpr i = l->init;
                   33174:                if (l->base != VIRTUAL) continue;
                   33175:                l->init = 0;
                   33176: //error('d',"simpl virtual base %t i %d ",l->bclass,i);
                   33177: 
                   33178:                // assign virtual OP to virtual base AP
                   33179:                Pclass bc = l->bclass;
                   33180:                Pexpr dp = 0;
                   33181: 
                   33182:                // dd = pointer argument for this base;
                   33183:                // non-zero if already initialized
                   33184:                for (Pname dd = f_this->n_list; dd!=argtype; dd=dd->n_list) 
                   33185:                        if (strcmp(dd->string,bc->string)==0) break;
                   33186: 
                   33187:                // initialize virtual base object
                   33188: //error('d',"bc %t dd %n offset %d init %d",bc,dd,l->obj_offset,l->init);
                   33189:                // => bc_arg = (bc*)((char*)this+offset)
                   33190:                int off = l->obj_offset;
                   33191:                Pexpr val = rptr(bc->this_type,th,off);
                   33192:                dp = new expr(ASSIGN,dd,val);
                   33193:                dd->assign();
                   33194: 
                   33195:                // => bc::bc()
                   33196:                if (i)  {
                   33197:                        switch (i->base) {
                   33198:                        case ASSIGN:
                   33199:                        case CM:
                   33200:                                break;
                   33201:                        case CALL:
                   33202:                        case G_CALL:
                   33203:                        {       Pcall cc = Pcall(i);
                   33204:                                Pname bn = cc->fct_name;
                   33205:                                ass_count = Pfct(bn->tp)->f_this->n_assigned_to;
                   33206:                                cc->simpl();
                   33207:                                break;
                   33208:                        }
                   33209:                        default:
                   33210:                                error('i',"badBCIr %k",i->base);
                   33211:                        }
                   33212:                        dp = new expr(CM,dp,i);
                   33213:                }
                   33214: 
                   33215:                // => (bc_arg==0)?dp:bc_arg
                   33216:                for (Pname a = f_args->n_list; a; a = a->n_list)
                   33217:                        if (strcmp(bc->string,a->string)==0) {
                   33218:                                dp = new expr(QUEST,dp,a);
                   33219:                                dp->cond = new expr(EQ,a,zero);
                   33220:                                break;
                   33221:                        }
                   33222: 
                   33223:                //      Pname dpp = find_vbase_ptr(bc,cl);
                   33224:                for (Pbcl ll=cl->baselist; ll; ll=ll->next) {
                   33225:                        if (ll->bclass==bc && ll->ptr_offset) {
                   33226:                                // make sure that the delegate_arg is needed
                   33227:                                // here and not just in a base
                   33228: 
                   33229:                                // this->Pd = (bc_arg==0)?dp:bc_arg
                   33230:                                Pexpr dpp = new mdot(bc->string,th);
                   33231:                                dpp->i1 = 3;
                   33232:                                dp = new expr(ASSIGN,dpp,dp);
                   33233: //error('d',"dpp %n",dpp);
                   33234:                                break;
                   33235:                        }
                   33236:                }
                   33237: 
                   33238:                // reverse init order
                   33239:                if (dp) init_list = init_list ? new expr(CM,dp,init_list) : dp;
                   33240:        }
                   33241: 
                   33242:        //      generate: this=base::base(args) (non-virtual bases)
                   33243: {      
                   33244:        for (Pbcl l = cl->baselist; l; l=l->next) {
                   33245:                Pexpr i = l->init;
                   33246:                if (i==0 || l->base==VIRTUAL) continue;
                   33247: //error('d',"simpl base %t i %d ",l->bclass,i);
                   33248:                l->init = 0;
                   33249:        
                   33250:                switch (i->base) {
                   33251:                case ASSIGN:
                   33252:                case CM:
                   33253:                        break;
                   33254:                case CALL:
                   33255:                case G_CALL:
                   33256:                {       Pcall cc = Pcall(i);
                   33257:                        Pname bn = cc->fct_name;
                   33258:                        ass_count = Pfct(bn->tp)->f_this->n_assigned_to;
                   33259:                        cc->simpl();
                   33260:                        // assign to ``this'' only from only base
                   33261:                        if (l==cl->baselist && cl->baselist->next==0) i = new expr(ASSIGN,th,cc);
                   33262:                        break;
                   33263:                }
                   33264:                default:
                   33265:                        error('i',"badBCIr %k",i->base);
                   33266:                }
                   33267: 
                   33268:                init_list = init_list ? new expr(G_CM,init_list,i) : i;
                   33269:        }
                   33270: }
                   33271: 
                   33272:        // initialize the vptrs that are updated by this class
                   33273:        for (Pvirt blist = cl->virt_list; blist; blist = blist->next) {
                   33274:        //      if (blist->string==0 && find_vptr(cl)==0) {     //opt
                   33275: //error('d',"!!!vptr init %s in %s",blist->string,cl->string);
                   33276:        //              continue;
                   33277:        //      }
                   33278: //error('d',"vptr init %s in %s",blist->string,cl->string);
                   33279:                topclass = cl;
                   33280:                Pexpr vp = cl->get_vptr_exp(blist->string);
                   33281: 
                   33282:                 char *str = 0;
                   33283:                char *cs = cl->nested_sig?cl->nested_sig:cl->string;
                   33284:                 if (cl->lex_level && cl->nested_sig==0) str = make_local_name( cl );
                   33285:                 Pexpr vtbl = new text_expr(blist->string,str?str:cs);
                   33286:                 //Pexpr vtbl = new text_expr(blist->string,cl->string);      
                   33287:                 //      vtbl = new cast(Pvptr_type,vtbl);
                   33288: 
                   33289:                Pexpr ee = new ref(REF,th,vp);
                   33290:                ee->tp = vp->tp;
                   33291:                ee = new expr(ASSIGN,ee,vtbl);
                   33292:                init_list = init_list ? new expr(CM,init_list,ee) : ee;
                   33293:        }
                   33294: 
                   33295:        // initialize members in declaration order:
                   33296:        int i;
                   33297:        for (Pname m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i) ) {
                   33298:                Ptype t = m->tp;
                   33299:                Pname cn;
                   33300:                Pname ctor;
                   33301:                if (t == 0) continue;
                   33302: 
                   33303:                switch (t->base) {
                   33304:                case FCT:
                   33305:                case OVERLOAD:
                   33306:                case CLASS:
                   33307:                case ENUM:
                   33308:                        continue;
                   33309:                }
                   33310: 
                   33311:                switch (m->n_stclass) {
                   33312:                case STATIC:
                   33313:                case ENUM:
                   33314:                        continue;
                   33315:                }
                   33316: 
                   33317:                if (m->base == PUBLIC) continue;
                   33318: 
                   33319:                Pexpr ee = m->n_initializer;
                   33320:                if (ee) m->n_initializer = 0;   // from fct must not persist until next fct
                   33321: //error('d',"simpl m %n ee %d",m,ee);
                   33322:                if (ee) {
                   33323:                        // init of non-class mem
                   33324:                        // set in fct::mem_init()
                   33325:                }
                   33326:                else if (cn=t->is_cl_obj()) {   // try for default
                   33327:                        Pclass cl = Pclass(cn->tp);
                   33328:                        if (ctor = cl->has_ictor()) {
                   33329:                                Pexpr r = new ref(REF,th,m);
                   33330:                                ee = call_ctor(tbl,r,ctor,0,DOT);
                   33331:        check_visibility(ctor,0,Pclass(ctor->n_table->t_name->tp),tbl,curr_fct);
                   33332:                        }
                   33333:                        else if (cl->has_ctor()) {
                   33334:                                error("M%n needsIr (no defaultK forC %s)",m,cl->string);
                   33335:                        }
                   33336:                }
                   33337:                else if (cl_obj_vec) {
                   33338:                        Pclass cl = Pclass(cl_obj_vec->tp);
                   33339:                        if (ctor = cl->has_ictor()) { // _new_vec(vec,noe,sz,ctor);
                   33340:                                Pexpr mm = new ref(REF,th,m);
                   33341:                                mm->tp = m->tp;
                   33342:                                ee = cdvec(vec_new_fct,mm,cl,ctor,-1,0);
                   33343:        check_visibility(ctor,0,Pclass(ctor->n_table->t_name->tp),tbl,curr_fct);
                   33344:                        }
                   33345:                        else if (cl->has_ctor()) {
                   33346:                                error("M%n[] needsIr (no defaultK forC %s)",m,cl->string);
                   33347:                        }
                   33348:                }
                   33349:                else if (t->is_ref()) {
                   33350:                        error("RM%n needsIr",m);
                   33351:                }
                   33352:                else if (t->tconst() && vec_const==0) {
                   33353:                        error("constM%n needsIr",m);
                   33354:                }
                   33355:        
                   33356:                if (ee) {
                   33357:                        ee->simpl();
                   33358:                        init_list = init_list ? new expr(CM,init_list,ee) : ee;
                   33359:                }
                   33360:        } // for m
                   33361: //error('d',"ctor->");
                   33362:        return ass_count;
                   33363: }
                   33364: 
                   33365: void fct::simpl()
                   33366: /*
                   33367:        call only for the function definition (body != 0)
                   33368: 
                   33369:        simplify argument initializers, and base class initializer, if any
                   33370:        then simplify the body, if any
                   33371: 
                   33372:        for constructor:call allocator if this==0 and this not assigned to
                   33373:                        (auto and static objects call constructor with this!=0,
                   33374:                        the new operator generates calls with this==0)
                   33375:                        call base & member constructors
                   33376:        for destructor: call deallocator (no effect if this==0)
                   33377:                        case base & member destructors
                   33378: 
                   33379:        for arguments and function return values look for class objects
                   33380:        that must be passed by constructor X(X&).
                   33381: 
                   33382:        Allocate temporaries for class object expressions, and see if
                   33383:        class object return values can be passed as pointers.
                   33384: 
                   33385:        call constructor and destructor for local class variables.
                   33386: */
                   33387: {
                   33388:        Pexpr th = f_this;
                   33389:        Ptable tbl = body->memtbl;
                   33390:        Pstmt ss = 0;
                   33391:        Pstmt tail;
                   33392:        Pclass cl = th ? Pclass(Pbase(Pptr(th->tp)->typ)->b_name->tp) : 0;
                   33393:        Pstmt dtail = 0;
                   33394: 
                   33395:        Pname ocurr_fct = curr_fct;
                   33396:        int oret = no_of_returns;
                   33397:        int oim = imeasure;
                   33398: 
                   33399: //error('d',"fct::simpl %n %t",curr_fct,this);
                   33400: //     not_inl = f_inline==0;
                   33401:        del_list = 0;
                   33402:        continue_del_list = 0;
                   33403:        break_del_list = 0;
                   33404:        scope = tbl;
                   33405:        if (scope == 0) error('i',"F::simpl()");
                   33406:        int ass_count = 0;
                   33407:        imeasure = 0;
                   33408:        no_of_returns = 0;
                   33409: 
                   33410:        cc->stack();
                   33411:        cc->nof = curr_fct;
                   33412:        cc->ftbl = tbl;
                   33413: 
                   33414: //      modification for local classes defined within inline functions
                   33415: // error( 'd', "simpl local_class: %d", local_class );
                   33416:        for ( Plist l = local_class; l; l = l->l ) {
                   33417:                Pname n = l->f; 
                   33418:                Pclass cl = Pclass(Pbase(n->tp)->b_name->tp);
                   33419:                if ( cl->in_fct == 0 ) cl->in_fct = cc->nof;
                   33420:                if ( cl->lcl == 0 ) cl->lcl = make_name( 'L' );
                   33421:                if ( cl->c_body == 1 ) cl->dcl_print(0);
                   33422:        }
                   33423: 
                   33424:        Pfct(cc->nof->tp)->local_class = local_class; 
                   33425:        local_class = 0;
                   33426: // error( 'd', "simpl nof: %n %d local_class: %d", cc->nof, cc->nof, Pfct(cc->nof->tp)->local_class );
                   33427: 
                   33428:        switch (curr_fct->n_scope) {
                   33429:        case 0:
                   33430:        case PUBLIC:
                   33431:                cc->not = curr_fct->n_table->t_name;
                   33432:                cc->cot = Pclass(cc->not->tp);
                   33433:                cc->tot = cc->cot->this_type;
                   33434:        }
                   33435: 
                   33436:        switch (curr_fct->n_oper) {
                   33437:        case  DTOR:
                   33438:                dtail = dtor_simpl(cl,th);
                   33439:                break;
                   33440:        case CTOR:
                   33441:                ass_count = ctor_simpl(cl,th);
                   33442:        }
                   33443: 
                   33444:        tail = body->simpl();
                   33445: 
                   33446:        if (returns->base!=VOID || f_result) {  // return must have been seen
                   33447:                if (no_of_returns) {            // could be OK
                   33448:                        Pstmt tt = (tail->base==RETURN || tail->base==LABEL) ? tail : trim_tail(tail);
                   33449: 
                   33450:                        switch (tt->base) {
                   33451:                        case RETURN:
                   33452:                        case GOTO:
                   33453:                                del_list = 0;   // no need for del_list
                   33454:                                break;
                   33455:                        case SM:
                   33456:                                if (tt->e)
                   33457:                                        switch (tt->e->base) {
                   33458:                                        case ICALL:
                   33459:                                        case G_CALL:
                   33460:                                                goto chicken;
                   33461:                                        }
                   33462:                        default:
                   33463:                                if (warning_opt || strcmp(curr_fct->string,"main"))     
                   33464:                                        error('w',"maybe no value returned from%n",curr_fct);
                   33465:                        case IF:
                   33466:                        case SWITCH:
                   33467:                        case DO:
                   33468:                        case WHILE:
                   33469:                        case FOR:
                   33470:                        case LABEL:
                   33471:                        chicken:                // don't dare write a warning
                   33472:                                break;
                   33473:                        }
                   33474:                }
                   33475:                else {  // must be an error
                   33476:                        // but we don't dare complain about main()
                   33477:                //      if (strcmp(curr_fct->string,"main"))
                   33478:                //              error(Pfct(curr_fct->tp)->returns->is_cl_obj()?0:'w',"no value returned from%n",curr_fct);
                   33479:                //      else if (warning_opt)   
                   33480:                //              error('w',"no value returned from%n",curr_fct);
                   33481:                        if (Pfct(curr_fct->tp)->f_inline
                   33482:                        && Pfct(curr_fct->tp)->returns!=void_type
                   33483:                        && Pfct(curr_fct->tp)->returns->is_cl_obj())
                   33484:                                // can cause code generation errors if allowed
                   33485:                                error("no value returned from%n",curr_fct);
                   33486:                        else if (warning_opt || strcmp(curr_fct->string,"main"))        
                   33487:                                error('w',"no value returned from%n",curr_fct);
                   33488:                }
                   33489:                if (del_list) goto zaq;
                   33490:        }
                   33491:        else if (del_list) {    // return may not have been seen
                   33492:        zaq:
                   33493:                if (tail)
                   33494:                        tail->s_list = del_list;
                   33495:                else
                   33496:                        body->s = del_list;
                   33497:                tail = dtail;
                   33498:        }
                   33499: 
                   33500:        if (curr_fct->n_oper == DTOR) { // body => if (this == 0) body
                   33501: 
                   33502: // reset the vptrs that were set by this class
                   33503:        for (Pvirt blist = cl->virt_list; blist; blist = blist->next) {
                   33504: //error('d',"vptr init %s in %s",blist->string,cl->string);
                   33505:                topclass = cl;
                   33506:                Pexpr vp = cl->get_vptr_exp(blist->string);
                   33507: 
                   33508:                 char *str = 0;
                   33509:                char *cs = cl->nested_sig?cl->nested_sig:cl->string;
                   33510:                 if (cl->lex_level && cl->nested_sig==0) str = make_local_name(cl);
                   33511:                 Pexpr vtbl = new text_expr(blist->string,str?str:cs);
                   33512: 
                   33513:                Pexpr ee = new ref(REF,th,vp);
                   33514:                ee->tp = vp->tp;
                   33515:                ee = new expr(ASSIGN,ee,vtbl);
                   33516:                Pstmt es = new estmt(SM,curloc,ee,0);
                   33517:                es->s_list = body->s;
                   33518:                body->s = es;
                   33519:        }
                   33520: 
                   33521:                body->s = new ifstmt(body->where,th,body->s,0);
                   33522:        }
                   33523: 
                   33524:        if (curr_fct->n_oper == CTOR) {
                   33525: 
                   33526:                loc temploc=body->where;
                   33527:                Pstmt tempss=body->s;
                   33528:                while (tempss) {
                   33529:                        temploc=tempss->where;
                   33530:                        tempss=tempss->s_list;
                   33531:                }
                   33532:                
                   33533:                if  (Pname(th)->n_assigned_to == 0) {
                   33534:                /* generate:
                   33535:                        if (this || (this=_new( sizeof(class cl) ))) {
                   33536:                                init_list ;
                   33537:                                body;
                   33538:                        }
                   33539:                */
                   33540:                        Pname(th)->n_assigned_to = ass_count ? ass_count : FUDGE111;
                   33541:                        Pexpr sz = new texpr(SIZEOF,cl,0);
                   33542:                        (void) cl->tsizeof();
                   33543:                        sz->tp = uint_type;
                   33544:                        Pexpr ee = new expr(ELIST,sz,0);
                   33545:                                Pname n = new name(oper_name(NEW));
                   33546:                                Pexpr p = find_name(n,cl,scope,CALL,curr_fct);
                   33547: //error('d',"in ctor %n call %n",curr_fct,p);
                   33548:                                ee = new call(p,ee);
                   33549:                                (void) ee->call_fct(cl->memtbl);
                   33550:                        ee->simpl();
                   33551:                        ee = new expr(ASSIGN,th,ee);
                   33552:                        ee = new expr(OROR,th,ee);
                   33553:                        /*ifs->simpl();
                   33554:                                do not simplify
                   33555:                                or "this = " will cause an extra call of base::base
                   33556:                        */
                   33557:                        if (init_list) {
                   33558:                                Pstmt es = new estmt(SM,body->where,init_list,0);
                   33559:                                es->s_list = body->s;
                   33560:                                body->s = es;
                   33561:                        //      if (tail == 0) tail = es;
                   33562:                        }
                   33563:                        else if (body->s == 0)
                   33564:                                body->s = new estmt(SM,body->where,0,0);
                   33565:                        else if(tail->base==RETURN) {
                   33566:                                if(body->s == tail) {
                   33567:                                        delete body->s;
                   33568:                                        body->s = new estmt(SM,body->where,0,0);
                   33569:                                }
                   33570:                                else {
                   33571:                                        Pstmt pr = body->s;
                   33572:                                        while(pr->s_list != tail)
                   33573:                                                pr = pr->s_list;
                   33574:                                        delete pr->s_list;
                   33575:                                        pr->s_list = 0;
                   33576:                                }
                   33577:                        }
                   33578: 
                   33579:                        ifstmt* ifs = new ifstmt(body->where,ee,body->s,0);
                   33580:                        body->s = ifs;
                   33581:                //      if (tail == 0) 
                   33582:                        tail = ifs;
                   33583:                }
                   33584:                // generate: body; return this;
                   33585:                Pstmt st = new estmt(RETURN,temploc,th,0);
                   33586:                if (tail)
                   33587:                        tail->s_list = st;
                   33588:                else
                   33589:                        body->s = st;
                   33590:                tail = st;
                   33591:        }
                   33592:        f_imeasure = imeasure;
                   33593:        curr_fct = ocurr_fct;
                   33594:        no_of_returns = oret;
                   33595:        imeasure = oim;
                   33596:        cc->unstack();
                   33597: }
                   33598: 
                   33599: 
                   33600: void classdef::simpl()
                   33601: {
                   33602:        int i;
                   33603: //error('d',"classdef::simpl %s %d",string,defined&SIMPLIFIED);
                   33604: 
                   33605:        if (defined&SIMPLIFIED) return;
                   33606: 
                   33607:        Pclass oc = in_class;
                   33608:        in_class = this;
                   33609: 
                   33610:        for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) {
                   33611:                Pexpr i = m->n_initializer;
                   33612:                m->n_initializer = 0;
                   33613:                m->simpl();
                   33614:                m->n_initializer = i;
                   33615:        }
                   33616: 
                   33617:        in_class = oc;
                   33618: 
                   33619:        for (Plist fl=friend_list; fl; fl=fl->l) {      // simplify friends
                   33620:                Pname p = fl->f;
                   33621:                switch (p->tp->base) {
                   33622:                case FCT:
                   33623:                case OVERLOAD:
                   33624:                        p->simpl();
                   33625:                }
                   33626:        }
                   33627: 
                   33628:        defined |= SIMPLIFIED;
                   33629: }
                   33630: 0707071010112045111004440001630000160000010207100466055410100001100000140465simpl2.c/*ident   "@(#)ctrans:src/simpl2.c        1.5" */
                   33631: /******************************************************************
                   33632: 
                   33633:        C++ source for cfront, the C++ compiler front-end
                   33634:        written in the computer science research center of Bell Labs
                   33635: 
                   33636:        Copyright (c) 1984 AT&T, Inc. All rights Reserved
                   33637:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   33638: 
                   33639: simpl2.c:
                   33640: 
                   33641:        simplify the typechecked function
                   33642:        remove:         classes:
                   33643:                                class fct-calls
                   33644:                                operators
                   33645:                                value constructors and destructors
                   33646:                        new and delete operators (replace with function calls)
                   33647:                        initializers            (turn them into statements)
                   33648:                        constant expressions            (evaluate them)
                   33649:                        inline functions                (expand the calls)
                   33650:                        enums                           (make const ints)
                   33651:                        unreachable code                (delete it)
                   33652:        make implicit coersions explicit
                   33653: 
                   33654:        in general you cannot simplify something twice
                   33655: 
                   33656: *******************************************************************/
                   33657: 
                   33658: #include "cfront.h"
                   33659: #include "size.h"
                   33660: #include <ctype.h>
                   33661: 
                   33662: extern Pname Ntmp;
                   33663: Pname find_vptr(Pclass);
                   33664: 
                   33665: extern int no_of_returns;
                   33666: 
                   33667: extern Pname new_fct;
                   33668: //extern Pname del_fct;
                   33669: 
                   33670: extern Pstmt del_list;
                   33671: extern Pstmt break_del_list;
                   33672: extern Pstmt continue_del_list;
                   33673: 
                   33674: extern Pname curr_fct; // current function
                   33675: extern Pexpr init_list;
                   33676: extern int imeasure;
                   33677: 
                   33678: Pexpr cdvec(Pname f, Pexpr vec, Pclass cl, Pname cd, int tail, Pexpr i, Pexpr vec2)
                   33679: /*
                   33680:        generate a call to construct or destroy the elements of a vector
                   33681: */
                   33682: {
                   33683:        Pexpr sz = new texpr(SIZEOF,cl,0);      // sizeof elem
                   33684:        sz->tp = uint_type;
                   33685:        (void) cl->tsizeof();
                   33686:                                        
                   33687:        Pexpr esz = new texpr(SIZEOF,cl,0);     // noe = sizeof(vec)/sizeof(elem)
                   33688:        esz->tp = int_type;
                   33689: 
                   33690: Pexpr noe;
                   33691: if (vec2) noe = new texpr(SIZEOF,vec2->tp,0);
                   33692: else noe = new texpr(SIZEOF,vec->tp,0);
                   33693: 
                   33694:        // Pexpr noe = new texpr(SIZEOF,vec->tp,0);
                   33695:        noe->tp = int_type;
                   33696:        noe = new expr(DIV,noe,esz);
                   33697:        noe->tp = uint_type;
                   33698: // error('d',"cdvec tail %d i %d",tail,i);
                   33699: //     Pexpr arg = (0<=tail) ? new expr(ELIST,zero,0) : 0;     // 0 or 1 for dtors
                   33700:        Pexpr arg = (i) ? new expr(ELIST,i,0) : 0;
                   33701:        arg = (0<=tail) ? new expr(ELIST,zero,arg) : arg;       // 0 or 1 for dtors
                   33702:        arg = new expr(ELIST,cd,arg);           // constructor or destructor
                   33703:        cd->lval(ADDROF);                       // cd->take_addr();
                   33704: 
                   33705:        arg = new expr(ELIST,sz,arg);
                   33706:        arg = new expr(ELIST,noe,arg);
                   33707:        arg = new expr(ELIST,vec,arg);
                   33708: 
                   33709:        arg = new call(f,arg);
                   33710:        arg->base = G_CALL;
                   33711:        arg->fct_name = f;
                   33712: 
                   33713:        return arg;
                   33714: }
                   33715: 
                   33716: /*
                   33717: int new_used;  // pre-define new and delete only if the user didn't
                   33718: 
                   33719: void new_init()
                   33720: {
                   33721:        char* ns = oper_name(NEW);
                   33722:        char* ds = oper_name(DELETE);
                   33723: 
                   33724:        new_used = 1;
                   33725: 
                   33726:        new_fct = gtbl->look(ns,0);
                   33727:        del_fct = gtbl->look(ds,0);
                   33728: 
                   33729:        if (new_fct && !del_fct)
                   33730:                error('w',"%n defined but not operator delete()",new_fct);
                   33731:        if (del_fct && !new_fct)
                   33732:                error('w',"%n defined but not operator new()",del_fct);
                   33733: 
                   33734:         if (Pfct(new_fct->tp)->body==0) new_fct->dcl_print(0);
                   33735:         if (Pfct(del_fct->tp)->body==0) del_fct->dcl_print(0);
                   33736: }
                   33737: */
                   33738: Pstmt trim_tail(Pstmt tt)
                   33739: /*
                   33740:        strip off statements after RETURN etc.
                   33741:        NOT general: used for stripping off spurious destructor calls
                   33742: */
                   33743: {
                   33744:        if (tt == 0) return 0;
                   33745: 
                   33746:        while (tt->s_list) {
                   33747:                Pstmt tpx;
                   33748:                switch (tt->base) {
                   33749:                case PAIR:
                   33750:                        tpx = trim_tail(tt->s2);
                   33751:                        goto tpxl;
                   33752:                case BLOCK:
                   33753:                        tpx = trim_tail(tt->s);
                   33754:                tpxl:
                   33755:                        if (tpx == 0) return 0;
                   33756: 
                   33757:                        switch (tpx->base) {
                   33758:                        case SM:
                   33759:                                break;
                   33760:                        case CONTINUE:
                   33761:                        case BREAK:
                   33762:                        case GOTO:
                   33763:                        case RETURN:
                   33764:                                if (tt->s_list->base != LABEL) tt->s_list = 0;
                   33765:                        default:
                   33766:                                return tpx;
                   33767:                        }
                   33768:                default:
                   33769:                        if (tt = tt->s_list) break;
                   33770:                        return 0;
                   33771:                case RETURN:
                   33772:                        if (tt->s_list->base != LABEL) tt->s_list = 0;
                   33773:                        return tt;
                   33774:                }
                   33775:        }
                   33776: 
                   33777:        switch (tt->base) {
                   33778:        case PAIR:      return trim_tail(tt->s2);
                   33779: //     case LABEL:     return trim_tail(tt->s);
                   33780:        case BLOCK:     if (tt->s) return trim_tail(tt->s);
                   33781:        default:        return tt;
                   33782:        }
                   33783: }
                   33784: 
                   33785: extern Ptype Pfct_type;
                   33786: 
                   33787: Pexpr mptr_assign(Pexpr n, Pexpr in)
                   33788: {
                   33789:        Pexpr i1;
                   33790:        Pexpr i2;
                   33791:        Pexpr i3;
                   33792: 
                   33793:        if ( n->base == NAME ) 
                   33794:                Pname(n)->use();
                   33795: 
                   33796:        if (in->base == NAME) {
                   33797:                i1 = new mdot("d",in);
                   33798:                i1->i1 = 9;
                   33799:                i2 = new mdot("i",in);
                   33800:                i2->i1 = 9;
                   33801:                i3 = new mdot("f",in);
                   33802:                i3->i1 = 9;
                   33803:        }
                   33804:        else {
                   33805:                i1 = in->e1->e1;
                   33806:                i2 = in->e1->e2;
                   33807:                i3 = in->e2;
                   33808:        }
                   33809:        Pexpr nd = new mdot("d",n);
                   33810:        nd->i1 = 9;
                   33811:        Pexpr e1 = new expr(ASSIGN,nd,i1);
                   33812: 
                   33813:        Pexpr ni = new mdot("i",n);
                   33814:        ni->i1 = 9;
                   33815:        Pexpr e2 = new expr(ASSIGN,ni,i2);
                   33816: 
                   33817:        Pexpr nf = new mdot("f",n);
                   33818:        nf->i1 = 9;
                   33819: //     Pexpr ii = in->e2; //new cast(Pfct_type,in->e2);
                   33820:        Pexpr e3 = new expr(ASSIGN,nf,i3);
                   33821: 
                   33822:        Pexpr ee = new expr(CM,e2,e3);
                   33823:        return new expr(CM,e1,ee);
                   33824: }
                   33825: 
                   33826: Pstmt block::simpl()
                   33827: {
                   33828:        int i;
                   33829:        Pname n;
                   33830:        Pstmt ss=0, sst=0;
                   33831:        Pstmt dd=0, ddt=0;
                   33832:        Pstmt stail;
                   33833:        Ptable old_scope = scope;
                   33834:        DB( if(Sdebug>=1)
                   33835:                error('d',"%d->block::simple() own_tbl %d  memtbl %d  curr_fct%n",this,own_tbl,memtbl,curr_fct);
                   33836:        );
                   33837:        if (own_tbl == 0) {
                   33838:                ss = (s) ? s->simpl() : 0;
                   33839:                return ss;
                   33840:        }
                   33841: 
                   33842:        scope = memtbl;
                   33843:        if (scope->init_stat == 0) scope->init_stat = 1; /* table is simplified. */
                   33844: 
                   33845:        for (n=scope->get_mem(i=1); n; n=scope->get_mem(++i)) {
                   33846:                Pstmt st = 0;
                   33847:                Pname cln;
                   33848:                Pexpr in = n->n_initializer;
                   33849: // error('d',"local %k %n in %k %t",n->n_sto,n,in?in->base:0,in?in->tp:0);
                   33850:                if (in || n->n_evaluated) {
                   33851:                        scope->init_stat = 2; /* initializer in this scope */
                   33852:                        if (n->n_sto == EXTERN) {
                   33853:                                error(&n->where,"Id local extern%n",n);
                   33854:                                continue;
                   33855:                        }
                   33856:                }
                   33857: 
                   33858:                switch (n->n_scope) {
                   33859:                case ARG:
                   33860:                case 0:
                   33861:                case PUBLIC:
                   33862:                         continue;
                   33863:                }
                   33864: 
                   33865:                if (n->n_stclass == STATIC) { // local static class object
                   33866:                        /* initialization of local static objects; 
                   33867:                         * set up first pass switch
                   33868:                         *     temp_switch ? 0 
                   33869:                         *       : (stat_obj=init_expr, temp_switch=1);
                   33870:                         *
                   33871:                         * ARGS: temporary class object in init_expr with dtor
                   33872:                         *       must call dtor once in std function
                   33873:                         */
                   33874: 
                   33875:                        if ((in==0 && n->n_scope==ARGS) ||
                   33876:                                (in && in->base==STAT_INIT)) 
                   33877:                        {
                   33878:                                Pname cn;
                   33879:                                Pname x;
                   33880:                                Ptype ct;
                   33881:                                int vec_seen = 0;
                   33882: 
                   33883:                                cn = n->tp->is_cl_obj();
                   33884:                                if ( cn == 0 ) { ++vec_seen; cn = cl_obj_vec; }
                   33885: 
                   33886:                                if ( cn ) {
                   33887:                                        ct = new ptr(PTR,vec_seen?Pvec(n->tp)->typ:n->tp);
                   33888:                                        x = make_tmp('F', ct, gtbl );
                   33889:                                        x->n_initializer = zero;
                   33890:                                }
                   33891:                                else
                   33892:                                        x = make_tmp('F',int_type,scope);
                   33893: 
                   33894:                                x->n_sto = n->n_stclass = STATIC;
                   33895:                                
                   33896:                                if (in) {
                   33897:                                        if (in->e2)
                   33898:                                                in->base = ASSIGN;
                   33899:                                        else in = in->e1;
                   33900:                                }
                   33901: 
                   33902:                                Pexpr set;
                   33903:                                if ( cn ) {
                   33904:                                        x->dcl_print(0);
                   33905:                                        Pclass cl = Pclass(cn->tp);
                   33906:                                        Pname dtor = cl->has_dtor();
                   33907: 
                   33908:                                        Pexpr cc;
                   33909:                                        if ( dtor ) {
                   33910:                                                if ( vec_seen == 0 ) {
                   33911:                                                        Pexpr eee = new expr(DEREF, x, 0 );
                   33912:                                                        Pexpr c = call_dtor(eee,dtor,0,DOT,one);
                   33913:                                                        c->tp = any_type;
                   33914:                                                        cc = new expr( QUEST, c, zero );
                   33915:                                                        cc->cond = x;
                   33916:                                                }
                   33917:                                                else cc = cdvec(vec_del_fct,x,cl,dtor,0,zero,n);
                   33918:                                                cc->tp = any_type; // arghh!
                   33919: 
                   33920:                                                Pstmt dls = new estmt( SM, n->where, cc, 0 );
                   33921:                                                if ( st_dlist ) dls->s_list = st_dlist;
                   33922:                                                st_dlist = dls;
                   33923:                                        }
                   33924: 
                   33925:                                        Pexpr xe;
                   33926:                                        if (cn) {
                   33927:                                                if ( vec_seen == 0 )
                   33928:                                                        xe = new expr( G_ADDROF, 0, n );
                   33929:                                                else {
                   33930:                                                        Pexpr ee = new expr( DEREF, n, zero );
                   33931:                                                        xe = new expr( G_ADDROF, 0, ee );
                   33932:                                                }
                   33933:                                        }
                   33934: 
                   33935:                                        set = new expr(ASSIGN,x,xe);
                   33936:                                        set->tp = ct;
                   33937:                                }
                   33938:                                else {
                   33939:                                        set = new expr(ASSIGN,x,one);
                   33940:                                        set->tp = int_type;
                   33941:                                }
                   33942: 
                   33943:                                // set pointer to static object and continue
                   33944:                                // sorry for goto, but beats rewriting code
                   33945:                                if ( n->n_scope == ARGS && in == 0 ) {
                   33946:                                        set = new expr( QUEST, zero, set );
                   33947:                                        set->cond = x;
                   33948:                                        st = new estmt(SM,n->where,set,0);
                   33949:                                        goto init_stat3;
                   33950:                                }
                   33951: 
                   33952:                                in = new expr(G_CM,in,set);
                   33953:                                in = new expr(STAT_INIT,zero,in);
                   33954:                                in->cond = x;
                   33955:                        }
                   33956:                        else
                   33957:                                continue;
                   33958:                }
                   33959: 
                   33960:                if ( in ) {
                   33961:                        if ((in->base == ILIST && in->e2 == 0) ||
                   33962:                            (in->base == STRING && n->tp->base == VEC))
                   33963:                                if (ansi_opt==0) {
                   33964:                                        error('s',&n->where,"initialization of%n (automatic aggregate)",n);
                   33965:                                        continue;
                   33966:                                }
                   33967:                }    
                   33968: 
                   33969:                if (n->tp == 0) continue; /* label */
                   33970:                if (n->n_evaluated) continue;
                   33971: 
                   33972:                /* construction and destruction of temporaries is handled locally */
                   33973:                {       char* s = n->string;
                   33974:                        register char c3 = s[4];
                   33975:                        if (s[0]=='_' && s[1]=='_' && s[2]=='D' && isdigit(c3)) continue;
                   33976:                }
                   33977: 
                   33978:                if ( cln=n->tp->is_cl_obj() ) {
                   33979:                        Pclass cl = Pclass(cln->tp);
                   33980:                        Pname d = cl->has_dtor();
                   33981: 
                   33982:                        if ( n->n_stclass == STATIC   // local static class object
                   33983:                                && in && in->base==STAT_INIT )  
                   33984:                                        goto stat_init;
                   33985: 
                   33986:                        if (d) {                        // n->cl.dtor(0);
                   33987:                                Pexpr dl = call_dtor(n,d,0,DOT,one);
                   33988:                        //      Pstmt dls = new estmt(SM,n->where,dl,0);
                   33989:                                Pstmt dls = new estmt(SM,no_where,dl,0);
                   33990:                                if (dd) {
                   33991:                                        dls->s_list = dd;
                   33992:                                        dd = dls;
                   33993:                                }
                   33994:                                else
                   33995:                                        ddt = dd = dls;
                   33996:                        }
                   33997: 
                   33998: //  error('d',"%n: in %d",n,in?in->base:0);
                   33999:                        if (in) {
                   34000:                                switch (in->base) {
                   34001:                                case DEREF:             // *constructor?
                   34002:                                        if (in->e1->base == G_CALL) {
                   34003:                                                Pname fn = in->e1->fct_name;
                   34004:                                                if (fn==0 || fn->n_oper!=CTOR) goto ddd;
                   34005:                                                st = new estmt(SM,n->where,in->e1,0);
                   34006:                                                n->n_initializer = 0;
                   34007:                                                break;
                   34008:                                        }
                   34009:                                        goto ddd;
                   34010:                                case STAT_INIT:
                   34011: stat_init:
                   34012: // error('d', "block::simpl: case #1 stat_init : n: %n", n );
                   34013:                                        in->base = QUEST;
                   34014:                                        st = new estmt(SM,n->where,in,0);
                   34015:                                        n->n_initializer = 0;
                   34016:                                        break;
                   34017:                                case G_CM:
                   34018:                                        st = new estmt(SM,n->where,in->e1,0);
                   34019:                                        n->n_initializer = 0;
                   34020:                                        break;
                   34021:                                case ASSIGN:            // assignment to "n"?
                   34022:                                        if (in->e1 == n) {
                   34023:                                                st = new estmt(SM,n->where,in,0);
                   34024:                                                n->n_initializer = 0;
                   34025:                                                break;
                   34026:                                        }
                   34027:                                default:
                   34028:                                        goto ddd;
                   34029:                                }
                   34030:                        }
                   34031:                }
                   34032:                else if (cl_obj_vec) {
                   34033:                        Pclass cl = Pclass(cl_obj_vec->tp);
                   34034:                        Pname d = cl->has_dtor();
                   34035:                        Pname c = cl->has_ictor();
                   34036:                        n->n_initializer = 0;
                   34037: 
                   34038:                        if ( n->n_stclass == STATIC   // local static class object
                   34039:                                && in && in->base==STAT_INIT )  
                   34040:                                        goto stat_init2;
                   34041: 
                   34042:                        if (c) {        //  _vec_new(vec,noe,sz,ctor);
                   34043:                                if (in==0 || in->base==ILIST) {
                   34044:                                        Pexpr a = cdvec(vec_new_fct,n,cl,c,-1,0);
                   34045:                                        st = new estmt(SM,n->where,a,0);
                   34046:                                }
                   34047:                                else 
                   34048:                                        st = new estmt(SM,n->where,in,0);
                   34049:                        }
                   34050:                        // no default ctor but provided all elements with argument
                   34051:                        else if ( in ) st = new estmt(SM,n->where,in,0);
                   34052: 
                   34053:                        
                   34054:                        if (d) {        //  __vec_delete(vec,noe,sz,dtor,0);
                   34055:                                Pfct f = Pfct(d->tp);
                   34056:                                int i = 0;
                   34057:                                for (Pname nn = f->f_args->n_list; 
                   34058:                                        nn && nn->n_list; nn=nn->n_list) i++;
                   34059:                                Pexpr a = cdvec(vec_del_fct,n,cl,d,0,new ival(i));
                   34060:                        //      Pstmt dls = new estmt(SM,n->where,a,0);
                   34061:                                Pstmt dls = new estmt(SM,no_where,a,0);
                   34062:                                if (dd) {
                   34063:                                        dls->s_list = dd;
                   34064:                                        dd = dls;
                   34065:                                }
                   34066:                                else
                   34067:                                        ddt = dd = dls;
                   34068:                        }
                   34069:                }
                   34070:                else if (in) {
                   34071:                        switch (in->base) {
                   34072:                        case ILIST:
                   34073:                                switch (n->n_scope) {
                   34074:                                case FCT:
                   34075:                                        if (in->e2) { // pointer to member
                   34076:                                                Pexpr ee = mptr_assign(n,in);
                   34077:                                                st = new estmt(SM,n->where,ee,0);
                   34078:                                                n->n_initializer = 0;
                   34079:                                                break;
                   34080:                                        }
                   34081:                                case ARG:
                   34082:                                        if (ansi_opt == 0) error('s',"Ir list for localV%n",n); 
                   34083:                                }
                   34084:                                break;
                   34085:                        case STAT_INIT:
                   34086: stat_init2:
                   34087: // error('d', "block::simpl: case #2 stat_init : n: %n", n );
                   34088:                                in->base = QUEST;
                   34089:                                st = new estmt(SM,n->where,in,0);
                   34090:                                n->n_initializer = 0;
                   34091:                                break;
                   34092:                        case STRING:
                   34093:                                if (n->tp->base==VEC) break; /* BUG char vec only */
                   34094:                        default:
                   34095:                        ddd:
                   34096:                        {       Pexpr ee = new expr(ASSIGN,n,in);
                   34097:                                st = new estmt(SM,n->where,ee,0);
                   34098:                                n->n_initializer = 0;
                   34099:                        }
                   34100:                        }
                   34101:                }
                   34102: 
                   34103: init_stat3:    if (st) {
                   34104:                        if (ss)
                   34105:                                sst->s_list = st;
                   34106:                        else
                   34107:                                ss = st;
                   34108:                        sst = st;
                   34109:                }
                   34110:        }
                   34111: 
                   34112:        if (dd) {
                   34113:                Pstmt od = del_list;
                   34114:                Pstmt obd = break_del_list;
                   34115:                Pstmt ocd = continue_del_list;
                   34116: 
                   34117:                dd->simpl();
                   34118:                del_list = (od) ? Pstmt(new pair(curloc,dd,od)) : dd;
                   34119:                break_del_list = (break_del_list&&obd) ? Pstmt(new pair(curloc,dd,obd)) : dd;
                   34120:                continue_del_list = (continue_del_list&&ocd) ? Pstmt(new pair(curloc,dd,ocd)) : dd;
                   34121: 
                   34122:                stail  = s ? s->simpl() : 0;
                   34123: 
                   34124:                Pfct f = Pfct(curr_fct->tp);
                   34125:                if (this!=f->body
                   34126:                || f->returns->base==VOID
                   34127:                || (f->returns->base!=VOID && no_of_returns==0 ) // you have been warned!
                   34128:                || strcmp(curr_fct->string,"main")==0 ) {
                   34129:                // not dropping through the bottom of a value returning function
                   34130:                        if (stail) {
                   34131:                                Pstmt tt = (stail->base==RETURN || stail->base==LABEL) ? stail : trim_tail(stail);
                   34132:                                if (tt && tt->base != RETURN) stail->s_list = dd;
                   34133:                        }
                   34134:                        else
                   34135:                                s = dd;
                   34136:                        stail = ddt;
                   34137:                }
                   34138: 
                   34139:                del_list = od;
                   34140:                continue_del_list = ocd;
                   34141:                break_del_list = obd;
                   34142:        }
                   34143:        else
                   34144:                stail  = s ? s->simpl() : 0;
                   34145: 
                   34146:        if (ss) {       /* place constructor calls */
                   34147:                ss->simpl();
                   34148:                sst->s_list = s;
                   34149:                s = ss;
                   34150:                if (stail == 0) stail = sst;
                   34151:        }
                   34152:        
                   34153:        scope = old_scope;
                   34154: 
                   34155:        return stail;
                   34156: }
                   34157: 
                   34158: int no_sizeof;
                   34159: 
                   34160: void expr::simpl()
                   34161: {
                   34162:        DB(if(Sdebug>=2){
                   34163:                error('d',"%d->expr::simpl() %k",this,this?base:0);
                   34164:                if(Sdebug>=3) display_expr(this);
                   34165:        });
                   34166:        if (this==0 || permanent==2) return;    // already expanded
                   34167:        static TOK obase = 0;
                   34168: 
                   34169:        switch (base) {
                   34170:        case MDOT:
                   34171:                obase = base;
                   34172:                mem->simpl();
                   34173:                obase = 0;
                   34174:                // no break
                   34175: 
                   34176:        case ICALL:     // already expanded
                   34177:                return;
                   34178: 
                   34179:        case G_ADDROF:
                   34180:        case ADDROF:
                   34181: // error('d',"simpl & %k",e2->base);
                   34182: 
                   34183:                e2->simpl();
                   34184:                switch (e2->base) {
                   34185:                case DOT:
                   34186:                case REF:
                   34187:                {       Pref r = Pref(e2);
                   34188:                        Pname m = Pname(r->mem);
                   34189:                        while (m->base == MDOT) m = Pname(m->mem);
                   34190:                        if (m->n_stclass == STATIC) {   // & static member
                   34191:                                Pexpr x;
                   34192:                        delp:
                   34193:                                x = e2;
                   34194:                                e2 = m;
                   34195:                                r->mem = 0;
                   34196:                                DEL(x);
                   34197:                        }
                   34198:                        else if (m->tp->base == FCT) {  // & member fct
                   34199:                                Pfct f = Pfct(m->tp);
                   34200:                                if (f->f_virtual) {     // &p->f ==> p->vtbl[fi].f
                   34201:                                        int index = f->f_virtual;
                   34202:                                        Pexpr ie = index ? new ival(index):0;
                   34203:                                        if (ie) ie->tp = int_type;
                   34204:                                        Pname cn = m->n_table->t_name;
                   34205:                                        Pname vp = find_vptr(Pclass(cn->tp));
                   34206:                                        r->mem = vp;
                   34207: 
                   34208:                                        if ( obase == MDOT ) {
                   34209:                                                base = DEREF;
                   34210:                                                e1 = e2;
                   34211:                                                e2 = ie;
                   34212:                                        }
                   34213:                                        else { // support old style &b.vf
                   34214:                                                base = MDOT;
                   34215:                                                mem = new expr(DEREF,e2,ie);
                   34216:                                                string2 = "f";
                   34217:                                                i1 = 9;
                   34218:                                        }
                   34219:                                }
                   34220:                                else {
                   34221:                                        goto delp;
                   34222:                                }
                   34223:                        }
                   34224:                        break;
                   34225:                }
                   34226:                }
                   34227:                break;
                   34228:        
                   34229:        case ANDAND:
                   34230:        case OROR:
                   34231:                Ntmp = 0;
                   34232:                // no break
                   34233: 
                   34234:        default:
                   34235:                if (e1) e1->simpl();
                   34236:                if (e2) e2->simpl();
                   34237:                break;
                   34238: 
                   34239:        case CM:
                   34240:        case G_CM:
                   34241:        {       
                   34242:                Pname n = 0;
                   34243:                e1->simpl();
                   34244:                e2->simpl();
                   34245:                if (e1->base==ICALL && e1->e1==0) n = e1->il->fct_name;
                   34246:                if (e2->base==ICALL && e2->e1==0) n = e2->il->fct_name;
                   34247:                if (n) error('s',"cannot expand inline void%n called in commaE",n);
                   34248:                // no break
                   34249:        }
                   34250:        case NAME:
                   34251:        case DUMMY:
                   34252:        case ICON:
                   34253:        case FCON:
                   34254:        case CCON:
                   34255:        case IVAL:
                   34256:        // case FVAL:
                   34257:        // case LVAL:
                   34258:        case STRING:
                   34259:        case ZERO:
                   34260:        case ILIST:
                   34261: //     case MDOT:
                   34262:                return;
                   34263: /*
                   34264:        case SIZEOF:
                   34265:                base = IVAL;
                   34266:                i1 = tp2->tsizeof();
                   34267:                tp2 = 0;        // can't DEL(tp2)
                   34268:                break;
                   34269: */
                   34270:        case SIZEOF:
                   34271:                if (e1) e1->simpl();
                   34272:                return;
                   34273: 
                   34274:        case G_CALL:
                   34275:        case CALL:
                   34276:                Pcall(this)->simpl();
                   34277:                break;
                   34278: 
                   34279:        case NEW:
                   34280:        case GNEW:
                   34281:                simpl_new();
                   34282:                return;
                   34283: 
                   34284:        case DELETE:
                   34285:        case GDELETE:
                   34286:                simpl_delete();
                   34287:                break;
                   34288: 
                   34289:        case QUEST:
                   34290:                cond->simpl();
                   34291:                Ntmp = 0;
                   34292:                e2->simpl();
                   34293:                // no break
                   34294: 
                   34295:        case CAST:
                   34296:        case REF:
                   34297:                e1->simpl();
                   34298:                break;
                   34299: 
                   34300:        case DOT:
                   34301:                e1->simpl();
                   34302:                switch (e1->base) {
                   34303:                case CM:
                   34304:                case G_CM:
                   34305:                 {      // &( , name). => ( ... , &name)->
                   34306:                        Pexpr ex = e1;
                   34307:                        cfr:
                   34308:                        switch (ex->e2->base) {
                   34309:                        case NAME:
                   34310:                                base = REF;
                   34311:                                ex->e2 = ex->e2->address();
                   34312:                                break;
                   34313:                        case CM:
                   34314:                        case G_CM:
                   34315:                                ex = ex->e2;
                   34316:                                goto cfr;
                   34317:                        }
                   34318:                }
                   34319:                }
                   34320:                break;
                   34321: 
                   34322:        case ASSIGN:
                   34323:        {       
                   34324:                Pfct f = 0; 
                   34325:                Pexpr th = 0;
                   34326:                if ( curr_fct ) {
                   34327:                        f = Pfct(curr_fct->tp);
                   34328:                        th = f->f_this;
                   34329:                }
                   34330: 
                   34331:                imeasure++;
                   34332:                if (e1) e1->simpl();
                   34333:                if (e2) {
                   34334:                        Pexpr c = e2;
                   34335:                        c->simpl();
                   34336:                        while (c->base == CAST) c = c->e1;
                   34337:                        if (c->base == ILIST) e2 = c;
                   34338: 
                   34339:                        if (e2->base == ILIST) {        // pointer to member assignment
                   34340:                                Pexpr ee = mptr_assign(e1,e2);
                   34341:                                Pexpr eee = new expr(CM,ee->e2,e1);
                   34342:                                e1 = ee->e1;
                   34343:                                e2 = eee;
                   34344:                                base = CM;
                   34345:                                delete ee;
                   34346:                        }
                   34347:                }
                   34348: 
                   34349:                if (th && th==e1 && curr_fct->n_oper==CTOR && init_list) {
                   34350:                        // this=e2 => (this=e2,init_list)
                   34351:                        Pclass cl = Pclass(Pbase(Pptr(th->tp)->typ)->b_name->tp);
                   34352:                        if (cl->c_body == 1) cl->dcl_print(0);
                   34353:                        imeasure++;
                   34354:                        base = CM;
                   34355:                        e1 = new expr(ASSIGN,e1,e2);
                   34356:                        e2 = init_list;
                   34357:                        if (warning_opt)        // timid
                   34358:                                error('w',"assignment to ``this'' inK: try defining%t::operator new() instead",f->memof);
                   34359:                }
                   34360:                break;
                   34361:        }
                   34362:        }
                   34363: 
                   34364:        switch (base) {
                   34365:        case QUEST:
                   34366:        case ANDAND:
                   34367:        case OROR:
                   34368:                if (Ntmp) error('s',"temporary ofC%n with destructor needed in%kE",Ntmp,base);
                   34369:                // no break;
                   34370:        default:
                   34371:                Ntmp = 0;
                   34372:        }
                   34373:        
                   34374:        if (tp==int_type || tp==defa_type) {
                   34375:                Neval = 0;
                   34376:                no_sizeof = 1;  // do not convert sizeof's to ints
                   34377:                long i = eval();
                   34378:                no_sizeof = 0;
                   34379:                if (Neval == 0) {
                   34380:                        base = IVAL;
                   34381:                        i1 = i;
                   34382:                }
                   34383:        }
                   34384: 
                   34385: }
                   34386: 
                   34387: Pexpr vptr_entry(Pexpr pp, Pexpr ie, Pclass cl)
                   34388: {
                   34389:        Pptr ttemp = pp->tp->is_ptr_or_ref();
                   34390: 
                   34391:         if (ttemp) {
                   34392:                Ptype pt = ttemp->typ;  // check if cast pp = (base*)pp
                   34393:                Pclass pc = Pclass(pt->is_cl_obj()->tp); // is needed
                   34394:                if (pc!=cl) pp = new cast(cl,pp);
                   34395:         }
                   34396:        Pname vp = find_vptr(cl);
                   34397:        if (vp == 0) error('i',"can't find vptr");
                   34398:        Pexpr vptr = new ref(REF,pp,vp);        // pp->vptr
                   34399:        return new expr(DEREF,vptr,ie); // pp->vptr[i]
                   34400: }
                   34401: 
                   34402: Pexpr new_this(Pexpr pp, Pexpr ee)
                   34403: {
                   34404: //error('d',"new this");
                   34405:        Pexpr dee =  new mdot("d",ee);          // pp->vptr[i].d
                   34406:        dee->i1 = 9;
                   34407:        Pexpr nthis = new cast(Pchar_type,pp);
                   34408:        nthis = new expr(PLUS,nthis,dee);       // ((char*)pp)+delta
                   34409:        Ptype ct = pp->tp;
                   34410:        if (pp->base==NAME && Pname(pp)->n_xref) ct = pp->tp->addrof();
                   34411:        return new cast(ct,nthis);
                   34412: }
                   34413: 
                   34414: Pcall vcall(Pexpr pp, Pexpr ie, Pfct f, Pclass cl, Pexpr args)
                   34415: /*
                   34416:        generate a call of the virtual function with the index ``ie''
                   34417:        and type "f" in class ``cl'' for the object pointed to by ``pp''
                   34418: 
                   34419:        multiple inheritance virtual call:
                   34420: 
                   34421:        p->f(x) is resolved like this
                   34422:        pp = p;                 // avoid side effects
                   34423:        pp = p.base_object;     // often: pp = p;
                   34424:                                // done when the name was resolved
                   34425:        i = index(f);
                   34426:        entry = pp->_vtbl[i-1];
                   34427:        pp = (T*)(((char*)pp)+entry.d)
                   34428:        (*(ftype)entry.f)(pp,x)
                   34429: */
                   34430: {
                   34431: //error('d',"vcall %t",cl);
                   34432:        if (cl->c_body==1) cl->dcl_print(0);    // look for first use of cl
                   34433:                
                   34434:        imeasure+=6;
                   34435:        Pexpr ee = vptr_entry(pp,ie,cl);
                   34436: 
                   34437:        Pexpr fee = new mdot("f",ee);
                   34438:        fee->i1 = 9;
                   34439:        Ptype pft = f->addrof();
                   34440:        fee = new cast(pft,fee);                // (T)pp->vptr[i].f
                   34441:        Pexpr r = new expr(DEREF,fee,0);        // *(T)pp->vptr[i].f
                   34442:                                                // e1->tp must be 0, means "argtype encoded"
                   34443:        r->tp2 = Ptype(f->f_this);              // encode argtype
                   34444: 
                   34445:        Pexpr nthis = new_this(pp,ee);
                   34446: 
                   34447:        args = new expr(ELIST,nthis,args);
                   34448:        args->simpl();
                   34449: 
                   34450:        Pcall c = new call(r,args);
                   34451:        c->tp = f->returns;
                   34452:        return c;
                   34453: }
                   34454: 
                   34455: void call::simpl()
                   34456: /*
                   34457:        fix member function calls:
                   34458:                p->f(x) becomes f(p,x)
                   34459:                o.f(x)  becomes f(&o,x)
                   34460:        or if f is virtual:
                   34461:                p->f(x) is resolved like this
                   34462:                        pp = p;
                   34463:                        i = index(f);
                   34464:                        entry = pp->_vtbl[i-1];
                   34465:                        pp = (T*)(((char*)pp)+entry.i)
                   34466:                        (*entry.f)(pp,x)
                   34467:        replace calls to inline functions by the expanded code
                   34468: */
                   34469: {
                   34470:        Pname fn = fct_name;
                   34471: //error('d',"%d call::simpl() fn %n %d e1 %d",this,fn,fn,e1);
                   34472:        Pfct f = fn ? Pfct(fn->tp) : 0;
                   34473: 
                   34474:        if (fn == 0) e1->simpl();
                   34475: 
                   34476:        if (f) {
                   34477:                switch(f->base) {
                   34478:                case ANY:
                   34479:                        return;
                   34480:                case OVERLOAD:
                   34481:                        fct_name = fn = Pgen(f)->fct_list->f;
                   34482:                        f = Pfct(fn->tp);
                   34483:                }
                   34484:        }
                   34485: 
                   34486:        switch (e1->base) {
                   34487:        case MEMPTR:    // (p ->* q)(args)
                   34488:        {       
                   34489:                Pexpr p = e1->e1;
                   34490:                Pexpr q = e1->e2;
                   34491:                Pclass cl = Pclass(e1->tp2);
                   34492:                Pfct f = Pfct(q->tp->deref());
                   34493: 
                   34494:                if (e2) e2->simpl();
                   34495: 
                   34496:                if (f->f_this == 0) {   // might not know about ``this'' yet
                   34497:                        if (f->memof == 0) error('i',"memof missing");
                   34498:                        Pname tt = new name("this");
                   34499:                        tt->n_scope = ARG;
                   34500:                        tt->tp = f->memof->this_type;
                   34501:                        PERM(tt);
                   34502:                //      f->f_this = f->f_args = tt;
                   34503:                        tt->n_list = f->argtype;
                   34504:                //      f->f_this = tt;
                   34505:                        tt->n_list = f->f_result ? f->f_result : f->argtype;
                   34506:                        f->f_this = f->f_args = tt;
                   34507:                }
                   34508: //error('d',"f_this %d",f->f_this);    
                   34509: extern has_virt(Pclass);
                   34510: 
                   34511:                // beware of sideeffects:
                   34512:                nin = 1;
                   34513:                if (q->not_simple()) error('s',"2nd operand of .* too complicated");
                   34514:                nin = 0;
                   34515: 
                   34516:                Pexpr qq = new mdot("f",q);     // the function: (*(right type)q.f)
                   34517:                qq->i1 = 9;
                   34518:                qq = new cast(f->addrof(),qq);
                   34519:                Pexpr nc = new expr(DEREF,qq,0);
                   34520:                nc->tp2 = Ptype(f->f_this);     // encode argtype
                   34521: 
                   34522:                Pexpr nthis = new_this(p,q);    // arguments: (p+q.d,args)
                   34523:                Pexpr args = new expr(ELIST,nthis,e2);
                   34524:                imeasure+=3;
                   34525: 
                   34526:                if (has_virt(cl) == 0) {        // no virtuals: simple
                   34527:                        if (cl->defined == 0) 
                   34528:                                error("call throughP toMF before definition ofC %t",cl);
                   34529: //error('d',"no virt");
                   34530:                        // (p ->* q)(args) => (*q.f)(p+q.d,args)
                   34531:                        e1 = nc;
                   34532:                        e2 = args;
                   34533:                        return;
                   34534:                }
                   34535:                
                   34536:                if (find_vptr(cl) == 0) {       // must be a call to a second base
                   34537:                                                // that we cannot handle yet
                   34538:                                                // it is OK not to to generate
                   34539:                                                // a virtual call since a
                   34540:                                                // `sorry' will have been generated
                   34541:                                                // at the point of initialization
                   34542:                        e1 = nc;
                   34543:                        e2 = args;
                   34544:                        return;
                   34545: 
                   34546:                }
                   34547:                // beware of sideeffects:
                   34548:                nin = 1;
                   34549:                if (p->not_simple()) error('s',"1st operand of .* too complicated");
                   34550:                nin = 0;
                   34551: 
                   34552:                Pexpr c = new mdot("i",q);      // condition (q.i<0)
                   34553:                c->i1 = 9;
                   34554:                c = new expr(LT,c,zero);
                   34555:                
                   34556:                Pexpr ie = new mdot("i",q);
                   34557:                ie->i1 = 9;
                   34558: 
                   34559:                base = QUEST;
                   34560:                e1 = new call(nc,args);
                   34561:                e2 = vcall(p,ie,f,cl,e2);
                   34562:                cond = c;
                   34563:                return;
                   34564:        }
                   34565:        case DOT:
                   34566:                // if e1 is an object and not just a reference
                   34567:                // the vtbl need not be used
                   34568:        case REF:
                   34569:        {       Pref r = Pref(e1);
                   34570:                Pexpr a1 = r->e1;
                   34571:                int obj = r->n_initializer!=0;  // if B::f don't use vcall
                   34572: 
                   34573:                if (obj == 0) { // don't use vcall if we have an object
                   34574:                                // (not a pointer or a reference)
                   34575:                        if (e1->base==DOT && a1->base!=DEREF) obj = 1;
                   34576:                }
                   34577: 
                   34578: //error('d',"fct_name %n f %d %d obj %d",fct_name,f,f->f_virtual,obj);
                   34579:                if (f && obj==0 && f->f_virtual) {
                   34580:                        Pexpr a11 = 0;
                   34581: 
                   34582:                        switch(a1->base) {      // see if temporary might be needed
                   34583:                        case NAME:
                   34584:                        case MDOT:
                   34585:                                a11 = a1;
                   34586:                                break;
                   34587:                        case REF:
                   34588:                        case DOT:
                   34589:                                if (a1->e1->base==NAME
                   34590:                                || ((a1->e1->base==DOT || a1->e1->base==REF) && a1->e1->e1->base==NAME)) a11 = a1;
                   34591:                                break;
                   34592:                        case ADDROF:
                   34593:                        case G_ADDROF:
                   34594:                                if (a1->e2->base == NAME
                   34595:                                || ((a1->e2->base==DOT || a1->e2->base==REF) && a1->e2->e1->base==NAME)) a11 = a1;
                   34596:                                break;
                   34597:                        case CAST:
                   34598:                                switch (a1->e1->base) {
                   34599:                                case NAME:
                   34600:                                case MDOT:
                   34601:                                        a11 = a1;
                   34602:                                }
                   34603:                        }
                   34604: 
                   34605: //                     if( a1->base==REF && fn->n_oper==DTOR ){
                   34606: //                             a11 = a1;
                   34607: //                             goto zsw;
                   34608: //                     }
                   34609: //
                   34610:                        if (e1->base == DOT) {
                   34611: //                     zsw:
                   34612:                                if (a11) a11 = a11->address();
                   34613:                                a1 = a1->address();
                   34614:                        }
                   34615:                        
                   34616:                        if (a11 == 0) { // temporary (maybe) needed
                   34617:                                        // e->f() => (t=e,t->f(t))
                   34618:                                if (a1->base==NAME)
                   34619:                                        a11 = a1;       // &*name has become name
                   34620:                                else {
                   34621:                                        Pname nx = new name(make_name('K'));
                   34622:                                        nx->tp = a1->tp;
                   34623:                                        Pname n = nx->dcl(scope,ARG); // no init!
                   34624:                                        delete nx;
                   34625:                                        Pname cln = a1->tp->is_cl_obj();
                   34626:                                        if (cln) {
                   34627:                                                Pclass cl = Pclass(cln->tp);
                   34628:                                                if (Ntmp==0 && cl->has_dtor()) Ntmp = cln;
                   34629:                                                if (cl->has_itor()) n->n_xref = 1;
                   34630:                                        }
                   34631:                                        n->n_scope = FCT;
                   34632:                                        n->assign();
                   34633:                                        a11 = n;
                   34634:                                        a1 = new expr(ASSIGN,n,a1);
                   34635:                                        a1->tp = n->tp;
                   34636:                                        a1->simpl();
                   34637:                                        Pcall cc = new call(0,0);
                   34638:                                        *cc = *this;
                   34639:                                        base = CM;
                   34640:                                        e1 = a1;
                   34641:                                        e2 = cc;
                   34642:                                        this = cc;
                   34643:                                }
                   34644:                        }
                   34645: 
                   34646:                        int i = f->f_virtual;
                   34647:                        Pexpr ie = i?new ival(i):0;     // index
                   34648:                        Pname cn = fn->n_table->t_name;
                   34649:                        if (fn
                   34650:                        && fn->n_initializer
                   34651:                        && cc->nof
                   34652:                        && cc->nof->n_oper==CTOR
                   34653:                        && Pfct(cc->nof->tp)->memof->c_abstract
                   34654:                        && strcmp(Pfct(cc->nof->tp)->memof->string, cn->string) == 0 ) {
                   34655:                                // permit x::x( x& xx ) { xx.pvf(); }
                   34656:                                Pexpr ee = e1->e1;
                   34657:                                while ( ee && ee->base != NAME ) ee = ee->e1;
                   34658:                                if ( ee && strcmp( ee->string, "this" )==0)
                   34659:                                        error("call of pure virtualF%n inK%n",fn,cc->nof);
                   34660:                        }
                   34661:                        Pcall vc = vcall(a11,ie,f,Pclass(cn->tp),e2);
                   34662:                        *this = *vc;
                   34663:                        return; 
                   34664:                }
                   34665:        
                   34666:                Ptype tt = r->mem->tp;
                   34667:        llp:
                   34668: //error('d',"llp %t",tt);
                   34669:                switch (tt->base) {
                   34670:                // default:     // pointer to function: (n->ptr_mem)(args); do nothing
                   34671:                case TYPE:
                   34672:                        tt = Pbase(tt)->b_name->tp;
                   34673:                        goto llp;
                   34674:                case OVERLOAD:  // n->fctmem(args);
                   34675:                case FCT:
                   34676:                        if (fct_name==0) {
                   34677:                                // reconstitute fn destroyed to suppress "virtual" 
                   34678:                                fct_name = fn = Pname(e1->n_initializer);
                   34679:                                f = Pfct(fn->tp);
                   34680:                        }
                   34681: 
                   34682:                        if (e1->base == DOT) a1 = a1->address();
                   34683:                        e2 = new expr(ELIST,a1,e2);
                   34684:                        e1 = r->mem;
                   34685:                }
                   34686:        }
                   34687:        }
                   34688: 
                   34689:        if (e2) e2->simpl();
                   34690: //error('d',"fn %n inl %d imes %d",fn,f->f_inline,f->f_imeasure);
                   34691:        if (fn && f->f_inline && debug_opt==0) {
                   34692:                imeasure += f->f_imeasure;
                   34693:                Pclass cl = f->memof;
                   34694:                if (cl && cl->c_body) cl->dcl_print(0);
                   34695:                Ptable oscope = scope;
                   34696:                Pexpr ee = f->expand(fn,scope,e2);
                   34697:                scope = oscope;
                   34698:                if (ee) *Pexpr(this) = *ee;
                   34699:        }
                   34700:        else if (fn && f->f_inline==0 && f->f_imeasure) {
                   34701:                extern void uninline(Pname fn);
                   34702:                uninline(fn);
                   34703:                imeasure += 3;
                   34704:        }
                   34705:        else if (fn && debug_opt && f->f_inline==ITOR) {
                   34706:                extern void expand_itor(Pclass);
                   34707:                expand_itor(f->memof);
                   34708:        }
                   34709:        else
                   34710:                imeasure += 3;
                   34711: }
                   34712: 
                   34713: void uninline(Pname fn)
                   34714:        // inline turned static
                   34715: {
                   34716:        Pfct f = Pfct(fn->tp);
                   34717: //error('d',"uninline %n %d %d",fn,f->body,f->f_expr);
                   34718: 
                   34719:        if (warning_opt) {
                   34720:                error('w',"%n too complex for inlining",fn);
                   34721:                error('w',"out-of-line copy of %n created",fn);
                   34722:        }
                   34723:        f->f_imeasure = 0;      // now it really is just static
                   34724: 
                   34725:        Pstmt s = f->body->s;
                   34726: //     for (s = f->body->s; s; s=s->s_list)
                   34727: //error('d',"start %d %k",s->e,s->e->base);
                   34728: //      s = f->body->s;
                   34729:        while (s) {
                   34730: //error('d',"s   %k %d %k",s->base,s->e,s->e->base);
                   34731:                if (s->base == SM) {
                   34732:                        // turn comma expression into statement list
                   34733:                        Pexpr e = s->e;
                   34734:                        if (e)
                   34735:                                switch (e->base) {
                   34736:                                case CM:
                   34737:                                case G_CM:
                   34738:                                {       Pstmt ss = new estmt(SM,no_where,e->e2,0);
                   34739:                                        s->e = e->e1;
                   34740:                                        ss->s_list = s->s_list;
                   34741:                                        s->s_list = ss;
                   34742:                                        delete e;
                   34743:                                        continue;
                   34744:                                }
                   34745:                                }               
                   34746:                }
                   34747:                s = s->s_list;
                   34748:        }
                   34749: //     for (s = f->body->s; s; s=s->s_list)
                   34750: //error('d',"echo %k %d %k",s->base,s->e,s->e->base);
                   34751: 
                   34752:        fn->dcl_print(0);
                   34753: }
                   34754: 
                   34755: /*
                   34756: void ccheck(Pexpr e)
                   34757: 
                   34758:         Is there a conditional in this expression? (not perfect)
                   34759: 
                   34760: {
                   34761: //error('d',"ccheck(e %k)",e,e?e->base,0);
                   34762:        if (e)
                   34763:        switch (e->base) {
                   34764:        case QUEST:
                   34765:        case ANDAND:
                   34766:        case OROR:
                   34767:                error('s',"E too complicated: uses%k and needs temporary ofCW destructor",e->base);
                   34768:                break;
                   34769:        case LT:
                   34770:        case LE:
                   34771:        case GT:
                   34772:        case GE:
                   34773:        case EQ:
                   34774:        case NE:
                   34775:        case ASSIGN:
                   34776:        case ASPLUS:
                   34777:        case ASMINUS:
                   34778:        case G_CM:
                   34779:        case CM:
                   34780:        case PLUS:
                   34781:        case MINUS:
                   34782:        case MUL:
                   34783:        case DIV:
                   34784:        case OR:
                   34785:        case ER:
                   34786:        case AND:
                   34787:        case G_CALL:
                   34788:        case CALL:
                   34789:        case ELIST:
                   34790:        case DEREF:
                   34791:                ccheck(e->e1);
                   34792:        case NOT:
                   34793:        case COMPL:
                   34794:        case CAST:
                   34795:        case ADDROF:
                   34796:        case G_ADDROF:
                   34797:                ccheck(e->e2);
                   34798:                break;
                   34799:        case ICALL:     // check inlined arguments
                   34800:        {       Pin il = e->il;
                   34801:                for (int i = 0; il->args[i].arg && i<il->i_slots; i++) ccheck(il->args[i].arg);
                   34802:        }
                   34803:        }
                   34804: }
                   34805: */
                   34806: 
                   34807: void temp_in_cond(Pexpr ee, Pstmt ss, Ptable tbl)
                   34808: /*
                   34809:        insert destructor calls 'ss' into condition 'ee'
                   34810:        ee => (Qnn = ee, dtors, Qnn)
                   34811: */
                   34812: {
                   34813: //error('d',"temp_in_cond");
                   34814: //     ccheck(ee);
                   34815:        while (ee->base==CM || ee->base==G_CM) ee = ee->e2;
                   34816:        Ptype ct = ee->tp;
                   34817:        Pname n = new name(make_name('Q'));     // int Qnn;
                   34818:        n->tp = ct;
                   34819:        Pname tmp = n->dcl(tbl,ARG);
                   34820:        delete n;
                   34821:        tmp->n_scope = FCT;
                   34822: 
                   34823:        Pexpr v = new expr(0,0,0);
                   34824:        *v = *ee;
                   34825:        PERM(ct);
                   34826:        v = new cast(ct,v);
                   34827: 
                   34828:        tmp->n_assigned_to = 1;
                   34829:        Pexpr c = new expr(ASSIGN,tmp,v);       // Qnn = ee
                   34830:        c->tp = ct;
                   34831:        ee->base = CM;
                   34832:        ee->e1 = c;
                   34833: 
                   34834:        Pexpr ex = 0;                           // add dtors at end
                   34835: 
                   34836:        for (Pstmt sx = ss; sx; sx = sx->s_list) {
                   34837:                if (ex) {
                   34838:                        ex = new expr(CM,ex,sx->e);
                   34839:                        ex->tp = sx->e->tp;
                   34840:                }
                   34841:                else
                   34842:                        ex = sx->e;
                   34843:        }
                   34844:        ee->e2 = new expr(CM,ex,tmp);   // add Qnn at end
                   34845:        ee->e2->tp = ct;
                   34846: }
                   34847: 
                   34848: bit not_safe(Pexpr e)
                   34849: {
                   34850: 
                   34851:        switch (e->base) {
                   34852:        default:
                   34853:                return 1;
                   34854: /*
                   34855:        case CALL:
                   34856:        case G_CALL:
                   34857:        case DOT:
                   34858:        case REF:
                   34859:        case ANAME:
                   34860:                return 1;
                   34861: */
                   34862:        case NAME:
                   34863:                // if the name is automatic and has a destructor it is not safe
                   34864:                // to destroy it before returning an expression depending on it
                   34865:        {       Pname n = Pname(e);
                   34866:                if (n->n_table!=gtbl && n->n_table->t_name==0) {
                   34867:                        Pname cn = n->tp->is_cl_obj();
                   34868:                        if (cn && Pclass(cn->tp)->has_dtor()) return 1;
                   34869:                }
                   34870:        }
                   34871:        case IVAL:
                   34872:        case ICON:
                   34873:        case CCON:
                   34874:        case FCON:
                   34875:        case STRING:
                   34876:                return 0;
                   34877:        case NOT:
                   34878:        case COMPL:
                   34879:        case ADDROF:
                   34880:        case G_ADDROF:
                   34881:                return not_safe(e->e2);
                   34882:        case DEREF:
                   34883:        //      return not_safe(e->e1) || e->e2?not_safe(e->e2):0;
                   34884:        {       int i = not_safe(e->e1);
                   34885:                if (i) return i;
                   34886:                if (e->e2) return not_safe(e->e2);
                   34887:                return 0;
                   34888:        }
                   34889:        case CM:
                   34890:        case PLUS:
                   34891:        case MINUS:
                   34892:        case MUL:
                   34893:        case DIV:
                   34894:        case MOD:
                   34895:        case ASSIGN:
                   34896:        case ASPLUS:
                   34897:        case ASMINUS:
                   34898:        case ASMUL:
                   34899:        case ASDIV:
                   34900:        case OR:
                   34901:        case AND:
                   34902:        case OROR:
                   34903:        case ANDAND:
                   34904:        case LT:
                   34905:        case LE:
                   34906:        case GT:
                   34907:        case GE:
                   34908:        case EQ:
                   34909:        case NE:
                   34910:                return not_safe(e->e1) || not_safe(e->e2);
                   34911:        case QUEST:
                   34912:                return not_safe(e->cond) || not_safe(e->e1) || not_safe(e->e2);
                   34913:        }
                   34914: }
                   34915:                
                   34916:        
                   34917: Pexpr curr_expr;       /* to protect against an inline being expanded twice
                   34918:                           in a simple expression keep track of expressions
                   34919:                           being simplified
                   34920:                        */
                   34921: Pstmt stmt::simpl()
                   34922: /*
                   34923:        return a pointer to the last statement in the list, or 0
                   34924: */
                   34925: {
                   34926:        if (this == 0) error('i',"0->S::simpl()");
                   34927:        DB( if(Sdebug>=1){
                   34928:                error('d',"%d->stmt::simpl():  %k",this,base);
                   34929:                if(Sdebug>=2) display_stmt(this);
                   34930:        });
                   34931:        //Pstmt ostmt = Cstmt;
                   34932:        //if ( where.line ) Cstmt = this;
                   34933: 
                   34934:        stmtno++;
                   34935:        curr_expr = e;
                   34936: //error('d',"stmt::simpl %k s_list %d",base,s_list);
                   34937: 
                   34938:        switch (base) {
                   34939:        default:
                   34940:                error('i',"S::simpl(%k)",base);
                   34941: 
                   34942:        case ASM:
                   34943:                break;
                   34944: 
                   34945:        case BREAK:
                   34946:                if (break_del_list) {   // break => { _dtor()s; break; }
                   34947:                        Pstmt bs = new stmt(base,where,0);
                   34948:                        Pstmt dl = break_del_list->copy();
                   34949:                        base = BLOCK;
                   34950:                        s = new pair(where,dl,bs);
                   34951:                }
                   34952:                break;
                   34953: 
                   34954:        case CONTINUE:
                   34955:                if (continue_del_list) { // continue => { _dtor()s; continue; }
                   34956:                        Pstmt bs = new stmt(base,where,0);
                   34957:                        Pstmt dl = continue_del_list->copy();
                   34958:                        base = BLOCK;
                   34959:                        s = new pair(where,dl,bs);
                   34960:                }
                   34961:                break;
                   34962: 
                   34963:        case DEFAULT:
                   34964:                s->simpl();
                   34965:                break;
                   34966: 
                   34967:        case SM:
                   34968:                if (e) {
                   34969:                        if (e->base == DEREF) e = e->e1;
                   34970:                        e->simpl();
                   34971:                        if (e->base == DEREF) e = e->e1;
                   34972:                }
                   34973:                break;
                   34974: 
                   34975:        case RETURN:
                   34976:        {       /*      return x;
                   34977:                        =>
                   34978:                                { dtor()s; return x; }
                   34979:                        OR (returning an X where X(X&) is defined) =>
                   34980:                                { ctor(_result,x); _dtor()s; return; }
                   34981:                        OR (where x needs temporaries)
                   34982:                        OR (where x might involve an object to be destroyed) =>
                   34983:                                { _result = x; _dtor()s;  return _result; }
                   34984:                        return;         =>
                   34985:                                { _dtor()s; return; }
                   34986:                        OR (in constructors) =>
                   34987:                                { _dtor()s; return _this; }
                   34988:                */
                   34989:                Pstmt sx = this;
                   34990:                Pexpr ex = e;
                   34991: 
                   34992:                no_of_returns++;
                   34993: 
                   34994:                Pstmt dl = (del_list) ? del_list->copy() : 0;
                   34995:                Pfct f = Pfct(curr_fct->tp);
                   34996: 
                   34997:                if (e == 0) e = dummy;
                   34998:                if (e==dummy && curr_fct->n_oper==CTOR) e = f->f_this;
                   34999: 
                   35000: 
                   35001:                //      need to generate a temporary for mptr return
                   35002:                Pexpr tt = e;
                   35003:                while ( tt->base == CAST )
                   35004:                        tt = tt->e1;
                   35005:                if ( tt->base == ILIST )
                   35006:                        e = tt;
                   35007: 
                   35008:                if (e->base == ILIST) {
                   35009:                        extern Pbase mptr_type;
                   35010:                        extern Ptype Pvptr_type;
                   35011:                        Pexpr mptr_assign(Pexpr, Pexpr);
                   35012:                        // memptr constant
                   35013:                        // return({1,2,f}) ==> memptr t; return((t={1,2,f},&t))
                   35014: 
                   35015:                        Ptable ftbl = Pfct(curr_fct->tp)->body->memtbl;
                   35016:                        Pname temp = make_tmp('A',mptr_type,ftbl);
                   35017: 
                   35018:                        // placed in mptr_assign()
                   35019:                        // temp->use(); // necessary for inlines to force declaration
                   35020: 
                   35021:                        e = mptr_assign(temp,e);
                   35022:                        e = new expr(G_CM,e,temp);
                   35023:                        e->tp = mptr_type;
                   35024:                }
                   35025: 
                   35026:                if (f->f_result) {      // ctor(_result,x); dtors; return;
                   35027:                        if (e->base == G_CM) e = replace_temp(e,f->f_result);
                   35028:                        e->simpl();
                   35029:                        Pstmt cs = new estmt(SM,where,e,0);
                   35030:                        if (dl) cs = new pair(where,cs,dl);
                   35031:                        base = PAIR;
                   35032:                        s = cs;
                   35033:                        s2 = new estmt(RETURN,where,0,0);
                   35034: //#ifdef RETBUG
                   35035: //                     s2->empty = 1; // fudge to bypass C bug (see print.c)
                   35036: //                     s2->ret_tp = ret_tp;
                   35037: //#endif
                   35038:                }
                   35039:                else {                  // dtors; return e;
                   35040:                        e->simpl();
                   35041:                        if (dl) {
                   35042:                                if (e!=dummy && not_safe(e)) {
                   35043:                                // { _result = x; _dtor()s;  return _result; }
                   35044:                                        Ptable ftbl = Pfct(curr_fct->tp)->body->memtbl;
                   35045:                                        
                   35046:                                        Pname r = ftbl->look("_result",0);
                   35047:                                        if (r == 0) {
                   35048:                                                r = new name("_result");
                   35049:                                                r->tp = ret_tp;
                   35050:                                                Pname rn = r->dcl(ftbl,ARG);
                   35051:                                                rn->n_scope = FCT;
                   35052:                                                rn->where = no_where;
                   35053:                                                rn->assign();
                   35054:                                                delete r;
                   35055:                                                r = rn;
                   35056:                                        }
                   35057:                                        Pexpr as = new expr(ASSIGN,r,e);
                   35058:                                        as->tp = ret_tp;        // wrong if = overloaded, but then X(X&) ought to have been used 
                   35059:                                        Pstmt cs = new estmt(SM,where,as,0);
                   35060:                                        cs = new pair(where,cs,dl);
                   35061:                                        base = PAIR;
                   35062:                                        s = cs;
                   35063:                                        s2 = new estmt(RETURN,where,r,0);
                   35064:                                //      s2->ret_tp = ret_tp;
                   35065:                                }
                   35066:                                else { // { _dtor()s;  return x; }
                   35067:                                        base = PAIR;
                   35068:                                        s = dl;
                   35069:                                        s2 = new estmt(RETURN,where,e,0);
                   35070:                                }
                   35071:                                  s2->ret_tp = ret_tp;
                   35072:                        }
                   35073:                }
                   35074: 
                   35075: //             if (sx->memtbl) {
                   35076: //                     int i;
                   35077: //                     for (Pname n=sx->memtbl->get_mem(i=1); n; n=sx->memtbl->get_mem(++i)) {
                   35078: //                             Pname cn = n->tp->is_cl_obj();
                   35079: //                             if (cn && Pclass(cn->tp)->has_dtor()) {
                   35080: //                                     ccheck(ex);
                   35081: //                                     break;
                   35082: //                             }
                   35083: //                     }
                   35084: //             }
                   35085:                break;
                   35086:        }
                   35087: 
                   35088:        case WHILE:
                   35089:        case DO:
                   35090:                e->simpl();
                   35091:                {       Pstmt obl = break_del_list;
                   35092:                        Pstmt ocl = continue_del_list;
                   35093:                        break_del_list = 0;
                   35094:                        continue_del_list = 0;
                   35095:                        s->simpl();
                   35096:                        break_del_list = obl;
                   35097:                        continue_del_list = ocl;
                   35098:                }
                   35099:                break;
                   35100: 
                   35101:        case SWITCH:
                   35102:                e->simpl();
                   35103:                {       Pstmt obl = break_del_list;
                   35104:                        break_del_list = 0;
                   35105:                        s->simpl();
                   35106:                        break_del_list = obl;
                   35107:                }
                   35108:                switch (s->base) {
                   35109:                case DEFAULT:
                   35110:                case LABEL:
                   35111:                case CASE:
                   35112:                        break;
                   35113:                case BLOCK:
                   35114:                        if (s->s)
                   35115:                        switch (s->s->base) {
                   35116:                        case BREAK:     // to cope with #define Case break; case
                   35117:                        case CASE:
                   35118:                        case LABEL:
                   35119:                        case DEFAULT:
                   35120:                                break;
                   35121:                        default:
                   35122:                                goto df;
                   35123:                        }
                   35124:                        break;
                   35125:                default:
                   35126:                df:
                   35127:                        error(&s->where,"S orIdE not reached: (case label missing?)");
                   35128:                }
                   35129:                break;
                   35130: 
                   35131:        case CASE:
                   35132:                e->simpl();
                   35133:                s->simpl();
                   35134:                break;
                   35135: 
                   35136:        case LABEL:
                   35137:                if (del_list) error('s',"label in blockW destructors");
                   35138:                s->simpl();
                   35139:                break;
                   35140: 
                   35141:        case GOTO:
                   35142:                /*      If the goto is going to a different (effective) scope,
                   35143:                        then it is necessary to activate all relevant destructors
                   35144:                        on the way out of nested scopes, and issue errors if there
                   35145:                        are any constructors on the way into the target.
                   35146: 
                   35147:                        Only bother if the goto and label have different effective
                   35148:                        scopes. (If mem table of goto == mem table of label, then
                   35149:                        they're in the same scope for all practical purposes.
                   35150:                */
                   35151:                {
                   35152:                Pname n = scope->look( d->string, LABEL );
                   35153:                if (n == 0) error('i',&where,"label%n missing",d);
                   35154:                if(n->n_realscope!=scope && n->n_assigned_to) {
                   35155: 
                   35156:                        /*      Find the root of the smallest subtree containing
                   35157:                                the path of the goto.  This algorithm is quadratic
                   35158:                                only if the goto is to an inner or unrelated scope.
                   35159:                        */
                   35160: 
                   35161:                        Ptable r = 0;
                   35162: 
                   35163:                        for(Ptable q=n->n_realscope; q!=gtbl; q=q->next) {
                   35164:                                for( Ptable p = scope; p != gtbl; p = p->next ) {
                   35165:                                        if( p==q ) {
                   35166:                                                r = p;  // found root of subtree!
                   35167:                                                goto xyzzy;
                   35168:                                        }
                   35169:                                }
                   35170:                        }
                   35171: 
                   35172: xyzzy:                 if( r==0 ) error( 'i',&where,"finding root of subtree" );
                   35173: 
                   35174:                        /* At this point, r = root of subtree, n->n_realscope
                   35175:                         * = mem table of label, and scope = mem table of goto. */
                   35176: 
                   35177:                        /* Climb the tree from the label mem table to the table
                   35178:                         * preceding the root of the subtree, looking for
                   35179:                         * initializers and ctors.  If the mem table "belongs"
                   35180:                         * to an unsimplified block(s), the n_initializer field
                   35181:                         * indicates presence of initializer, otherwise initializer
                   35182:                         * information is recorded in the init_stat field of
                   35183:                         * mem table. */
                   35184: 
                   35185:                        for( Ptable p=n->n_realscope; p!=r; p=p->next )
                   35186:                                if( p->init_stat == 2 ) {
                   35187:                                        error(&where,"goto%n pastDWIr",d);
                   35188:                                        goto plugh; /* avoid multiple error msgs */
                   35189:                                }
                   35190:                                else if( p->init_stat == 0 ) {
                   35191:                                        int i;
                   35192:                                        for(Pname nn=p->get_mem(i=1);nn;nn=p->get_mem(++i))
                   35193:                                                if(nn->n_initializer||nn->n_evaluated){
                   35194:                                                        error(&nn->where,"goto%n pastId%n",d,nn);
                   35195:                                                        goto plugh;
                   35196:                                                }
                   35197:                                }
                   35198: plugh:
                   35199: 
                   35200:                        /* Proceed in a similar manner from the point of the goto,
                   35201:                         * generating the code to activate dtors before the goto. */
                   35202:                        /* There is a bug in this code.  If there are class objects
                   35203:                         * of the same name and type in (of course) different mem
                   35204:                         * tables on the path to the root of the subtree from the
                   35205:                         * goto, then the innermost object's dtor will be activated
                   35206:                         * more than once. */
                   35207: 
                   35208:                        {
                   35209:                        Pstmt dd = 0, ddt = 0;
                   35210: 
                   35211:                        for( Ptable p=scope; p!=r; p=p->next ) {
                   35212:                                int i;
                   35213:                                for(Pname n=p->get_mem(i=1);n;n=p->get_mem(++i)) {
                   35214:                Pname cln;
                   35215:                if (n->tp == 0) continue; /* label */
                   35216: 
                   35217:                if ( cln=n->tp->is_cl_obj() ) {
                   35218:                        Pclass cl = (Pclass)cln->tp;
                   35219:                        Pname d = cl->has_dtor();
                   35220: 
                   35221:                        if (d) {        /* n->cl::~cl(0); */
                   35222:                                Pexpr dl = call_dtor(n,d,0,DOT,one);
                   35223:                                Pstmt dls = new estmt(SM,n->where,dl,0);
                   35224:                                if (dd)
                   35225:                                        ddt->s_list = dls;
                   35226:                                else
                   35227:                                        dd = dls;
                   35228:                                ddt = dls;
                   35229:                        }
                   35230: 
                   35231:                }
                   35232:                else if (cl_obj_vec) {
                   35233:                        Pclass cl = (Pclass)cl_obj_vec->tp;
                   35234:                //      Pname c = cl->has_ictor();
                   35235:                        Pname d = cl->has_dtor();
                   35236: 
                   35237:                        if (d) {        //  __vec_delete(vec,noe,sz,dtor,0);
                   35238:                                Pfct f = Pfct(d->tp);
                   35239:                                int i = 0;
                   35240:                                for (Pname nn = f->f_args->n_list; 
                   35241:                                        nn && nn->n_list; nn=nn->n_list) i++;
                   35242:                                Pexpr a = cdvec(vec_del_fct,n,cl,d,0,new ival(i));
                   35243:                                Pstmt dls = new estmt(SM,n->where,a,0);
                   35244:                                if (dd)
                   35245:                                        ddt->s_list = dls;
                   35246:                                else
                   35247:                                        dd = dls;
                   35248:                                ddt = dls;
                   35249:                        }
                   35250:                }
                   35251:                                } /* end mem table scan */
                   35252:                        } /* end dtor loop */
                   35253: 
                   35254:                        /* "activate" the list of dtors obtained. */
                   35255: 
                   35256:                        if( dd ) {
                   35257:                                dd->simpl();
                   35258:                                Pstmt bs = new stmt( base, where, 0 );
                   35259:                                *bs = *this;
                   35260:                                base = PAIR;
                   35261:                                s = dd;
                   35262:                                s2 = bs;
                   35263:                        }
                   35264:                        }
                   35265:                } /* end special case for non-local goto */
                   35266:                }
                   35267:                break;
                   35268: 
                   35269:        case IF:
                   35270:                e->simpl();
                   35271:                s->simpl();
                   35272:                if (else_stmt) else_stmt->simpl();
                   35273:                break;
                   35274: 
                   35275:        case FOR:       // "for (s;e;e2) s2; => "s; for(;e,e2) s2"
                   35276:                if (for_init) for_init->simpl();
                   35277:                if (e) {
                   35278:                        curr_expr = e;
                   35279:                        e->simpl();
                   35280:                }
                   35281:                if (e2) {
                   35282:                        curr_expr = e2;
                   35283:                        e2->simpl();
                   35284:                        if (e2->base==ICALL)
                   35285:                                if (e2->e1 == 0) error('s',"cannot expand inline void%n called in forE", e2->il->fct_name);
                   35286:                }
                   35287:                {       Pstmt obl = break_del_list;
                   35288:                        Pstmt ocl = continue_del_list;
                   35289:                        break_del_list = 0;
                   35290:                        continue_del_list = 0;
                   35291:                        s->simpl();
                   35292:                        break_del_list = obl;
                   35293:                        continue_del_list = ocl;
                   35294:                }
                   35295:                break;
                   35296: 
                   35297:        case BLOCK:
                   35298:                Pblock(this)->simpl();
                   35299:                break;
                   35300: 
                   35301:        case PAIR:
                   35302:                break;
                   35303:        }
                   35304: 
                   35305:        /*if (s) s->simpl();*/
                   35306: //error('d',"base %k memtbl %d",base,memtbl);
                   35307:        if (base!=BLOCK && memtbl) {
                   35308:                Pstmt t1 = (s_list) ? s_list->simpl() : 0;
                   35309:                Pstmt tpx = t1 ? t1 : this;
                   35310: 
                   35311:                Pstmt ss = 0;
                   35312:                Pname cln;      // used for warnings
                   35313:                int i;
                   35314:                Pname tn = memtbl->get_mem(i=1);
                   35315:                for (; tn; tn=memtbl->get_mem(++i)) {
                   35316:                        if (cln = tn->tp->is_cl_obj()) {
                   35317:                                Pname d = Pclass(cln->tp)->has_dtor();
                   35318:                                if (d) {        /* n->cl::~cl(0); */
                   35319:                                        Pexpr dl = call_dtor(tn,d,0,DOT,one);
                   35320:                                        Pstmt dls = new estmt(SM,tn->where,dl,0);
                   35321:                                        dls->s_list = ss;
                   35322:                                        ss = dls;
                   35323:                                }
                   35324:                        }
                   35325:                }
                   35326: 
                   35327:                if (ss) {
                   35328:                        Pstmt t2 = ss->simpl();
                   35329: 
                   35330:                        switch (base) {
                   35331:                        case IF:
                   35332:                        case WHILE:
                   35333:                        case DO:
                   35334:                        case SWITCH:
                   35335:                                temp_in_cond(e,ss,memtbl);
                   35336:                                break;
                   35337: 
                   35338:                        case PAIR:      // can hide a return
                   35339:                        {       Pstmt ts = s2;
                   35340:                                while (ts->base==PAIR) ts = ts->s2;
                   35341:                                if (ts->base == RETURN) {       // sordid
                   35342:                                        this = ts;
                   35343:                                        goto retu;
                   35344:                                }
                   35345:                                goto def;
                   35346:                        }
                   35347:                        case RETURN:
                   35348:                        retu:
                   35349:                        {       
                   35350:                                if (e == 0) {
                   35351:                                        // return; dtors; => dtors; return;
                   35352:                                        Pstmt rs = new estmt(RETURN,where,0,0);
                   35353:                                        //rs->empty = empty;    // BSD fudge
                   35354:                                        rs->ret_tp = ret_tp;
                   35355:                                        base = PAIR;
                   35356:                                        s = ss;
                   35357:                                        s2 = rs;
                   35358:                                        //Cstmt = ostmt;
                   35359:                                        return t1 ? t1 : rs;
                   35360:                                }
                   35361: 
                   35362:                                Pname cln = e->tp->is_cl_obj();
                   35363:                                if (cln==0
                   35364:                                || Pclass(cln->tp)->has_oper(ASSIGN)==0) {
                   35365:                                        //  ... return e; dtors; =>
                   35366:                                        //  ... X r; ... r = e; dtors; return r;
                   35367:                                        Pname rv = new name("_rresult"); // NOT "_result"
                   35368:                                        rv->tp = ret_tp /* e->tp */;
                   35369:                                        if (memtbl == 0) memtbl = new table(4,0,0);
                   35370:                                        Pname n = rv->dcl(memtbl,ARG);
                   35371:                                        n->where = no_where;
                   35372:                                        n->n_scope = FCT;
                   35373:                                        n->n_assigned_to = 1;
                   35374:                                        delete rv;
                   35375:                                        Pstmt rs = new estmt(RETURN,where,n,0);
                   35376:                                        rs->ret_tp = ret_tp;
                   35377:                                        base = SM;
                   35378:                                        e = new expr(ASSIGN,n,e);
                   35379:                                        e->tp = n->tp;
                   35380:                                        Pstmt ps = new pair(where,ss,rs);
                   35381:                                        ps->s_list = s_list;
                   35382:                                        s_list = ps;
                   35383:                                        //Cstmt = ostmt;
                   35384:                                        return t1 ? t1 : rs;
                   35385:                                }
                   35386:                        }
                   35387:                                
                   35388:                        case FOR:       // don't know which expression the temp comes from
                   35389:                                error('s',&where,"E in %kS needs temporary ofC%nW destructor",base,cln);
                   35390:                                break;
                   35391: 
                   35392:                        case SM:        // place dtors after all "converted" DCLs
                   35393:                                if (t1) {
                   35394: //                                     ccheck(e);
                   35395:                                        for (Pstmt ttt, tt=this;
                   35396:                                                (ttt=tt->s_list) && ttt->base==SM;
                   35397:                                                tt = ttt) ;
                   35398:                                        t2->s_list = ttt;
                   35399:                                        tt->s_list = ss;
                   35400:                                        //Cstmt = ostmt;
                   35401:                                        return t1!=tt ? t1 : t2;
                   35402:                                }
                   35403:                        default:
                   35404:                        def:
                   35405: //                             if (e) ccheck(e);
                   35406:                                if (t1) {       // t1 == tail of statment list
                   35407:                                        t2->s_list = s_list;
                   35408:                                        s_list = ss;
                   35409:                                        //Cstmt = ostmt;
                   35410:                                        return t1;
                   35411:                                }
                   35412:                                s_list = ss;
                   35413:                                //Cstmt = ostmt;
                   35414:                                return t2;
                   35415:                        }
                   35416:                }
                   35417:                //Cstmt = ostmt;
                   35418:                return (t1) ? t1 : this;
                   35419:        }
                   35420: 
                   35421:        //Cstmt = ostmt;
                   35422:        return (s_list) ? s_list->simpl() : this;
                   35423: }
                   35424: 
                   35425: Pstmt stmt::copy()
                   35426: // now handles dtors in the expression of an IF stmt
                   35427: // not general!
                   35428: {
                   35429:        Pstmt ns = new stmt(0,curloc,0);
                   35430: 
                   35431:        *ns = *this;
                   35432:        if (s) ns->s = s->copy();
                   35433:        if (s_list) ns->s_list = s_list->copy();
                   35434: 
                   35435:        switch (base) {
                   35436:        case PAIR:
                   35437:                ns->s2 = s2->copy();
                   35438:                break;
                   35439:        }
                   35440: 
                   35441:        return ns;
                   35442: }
                   35443: 
                   35444: Pname overFound = 0;
                   35445: 
                   35446: static Pexpr 
                   35447: mk_new_with_args( Pexpr pe, Ptype tt, Pclass cl, Pexpr vec = 0 ) 
                   35448: { // allocate using operator new(sizeof(cl),args1)
                   35449:        Pexpr p;
                   35450:        Pexpr args = pe->e2;
                   35451: 
                   35452:        // Pexpr ce = new texpr(SIZEOF,tt,0);
                   35453:        Pexpr ce;
                   35454:        if (vec) 
                   35455:                ce = vec;
                   35456:        else ce = new texpr(SIZEOF,tt,0);
                   35457: 
                   35458:        (void) tt->tsizeof();
                   35459:        ce->tp = size_t_type;
                   35460:        args = new expr(ELIST,ce,args);
                   35461:        char* s = oper_name(NEW);
                   35462:        Pname n = new name(s);
                   35463:        if (pe->base == GNEW)   // ::new
                   35464:                p = gtbl->look(s,0);
                   35465:        else 
                   35466:                p = find_name(n,cl,scope,CALL,curr_fct);
                   35467:        p = new call(p,args);
                   35468:        overFound=0; // set in call_fct
                   35469:        (void) p->call_fct(cl->memtbl);
                   35470:        if (overFound && overFound->n_scope != EXTERN) 
                   35471:                check_visibility(overFound,0,cl,cc->ftbl,cc->nof);
                   35472:        overFound=0;
                   35473:        return p;
                   35474: }
                   35475: 
                   35476: void expr::simpl_new()
                   35477: /*
                   35478:        change NEW or GNEW node to CALL node
                   35479: */
                   35480: {
                   35481:        Pname cln;
                   35482:        Pname ctor;
                   35483:        int sz = 1;
                   35484: //     int esz;
                   35485:        Pexpr var_expr = 0;
                   35486:        Pexpr const_expr = 0;
                   35487:        Ptype tt = tp2;
                   35488:        Pexpr arg;
                   35489:        Pexpr szof;
                   35490:        Pname nf;
                   35491:        Pexpr init = e1;
                   35492: 
                   35493:        if (init && init->base) init = 0;       // only non-ctor init
                   35494: // error('d',"simpl_new %k e1 %k e2 %k init %k",base, e1?e1->base:0,e2?e2->base:0,init?init->base:0);
                   35495: 
                   35496:        if ((cln=tt->is_cl_obj()) && init == 0) {
                   35497:                Pclass cl = Pclass(cln->tp);
                   35498:                Pexpr p;
                   35499:                ctor=cl->has_ctor();
                   35500: // error('d',"cl %t ctor %n",cl, ctor);
                   35501:                if (e2          // placement
                   35502:                    || ctor==0  // no constructor
                   35503:                    || ctor->n_table!=cl->memtbl // inherited constructor??? 
                   35504:                    || (base==GNEW && cl->has_oper(NEW)) )
                   35505:                        p = mk_new_with_args( this, tt, cl ); // new(sizeof(cl),args1)
                   35506:                else {
                   35507:                        p = zero;       // 0->ctor(args)
                   35508:                        // check visibility anyway...
                   35509:                        (void)mk_new_with_args(this,tt,cl);
                   35510:                }
                   35511: 
                   35512:                if (ctor) {
                   35513:                        Pexpr c = e1;   // ctor call generated in expr::typ
                   35514:                        Ptype ttt = tp;
                   35515:                        c->e1->e1 = p;  // p->ctor
                   35516:                        c->simpl();
                   35517:                        *this = *c;
                   35518:                        tp = ttt;
                   35519:                        delete c;
                   35520:                }
                   35521:                else {          // (tp)new(args)
                   35522:                        base = CAST;
                   35523:                        tp2 = tp;
                   35524:                        e1 = p;
                   35525:                        e2 = 0;
                   35526:                        simpl();
                   35527:                }
                   35528:                return;
                   35529:        } else if ( cln ) {
                   35530:                Pclass cl = Pclass(cln->tp);
                   35531:                // check visibility anyway...
                   35532:                (void)mk_new_with_args(this,tt,cl);
                   35533:        }
                   35534:        
                   35535:        Pclass covn = 0;
                   35536:        if (cl_obj_vec) {
                   35537:                covn = Pclass(cl_obj_vec->tp);
                   35538:                ctor = covn->has_ictor();
                   35539:                if (ctor == 0) {
                   35540:                        if (covn->has_ctor()) error("new %s[], no defaultK",covn->string);
                   35541:                        cl_obj_vec = 0;
                   35542:                }
                   35543:        }
                   35544: 
                   35545: xxx:
                   35546: //error('d',"xxx %t",tt);
                   35547:        switch (tt->base) {
                   35548:        case TYPE:
                   35549:                tt = Pbase(tt)->b_name->tp;
                   35550:                goto xxx;
                   35551: 
                   35552:        default:
                   35553:                (void) tt->tsizeof();
                   35554:                szof = new texpr(SIZEOF,tt,0);
                   35555:                szof->tp = uint_type;
                   35556:                break;
                   35557: 
                   35558:        case VEC:
                   35559:        {       Pvec v = Pvec(tt);
                   35560: //error('d',"v %d %d",v->size,v->dim);
                   35561:                if (v->size)
                   35562:                        sz *= v->size;
                   35563:                else if (v->dim) 
                   35564:                        var_expr = v->dim;
                   35565:                else
                   35566:                        sz = 0;
                   35567:                tt = v->typ;
                   35568:                goto xxx;
                   35569:        }
                   35570:        }
                   35571: 
                   35572:        if (cl_obj_vec) { // _vec_new(0,no_of_elements,element_size,ctor)
                   35573:                const_expr = new ival(sz);
                   35574:                Pexpr noe = (var_expr) ? (sz!=1) ? new expr(MUL,const_expr,var_expr) : var_expr : const_expr;
                   35575:                const_expr = szof;
                   35576:                const_expr->tp = uint_type;
                   35577:                base = CALL;
                   35578:                arg = new expr(ELIST,ctor,0);
                   35579:                /*ctor->take_addr();*/
                   35580:                ctor->lval(ADDROF);
                   35581:                Pexpr sub=0;
                   35582:                if (e2 && e2->e1 &&
                   35583:                        e2->e1->tp &&
                   35584:                        e2->e1->tp->base != PTR ) 
                   35585:                { // new(size_t, args)
                   35586:                        Pexpr vec_sz = new expr(MUL, noe, const_expr);
                   35587:                        sub = mk_new_with_args( this, tt, covn, vec_sz );
                   35588:                }
                   35589:                arg = new expr(ELIST,const_expr,arg);
                   35590:                arg = new expr(ELIST,noe,arg);
                   35591:                // arg = new expr(ELIST,e2?e2:zero,arg);        // may be preallocated
                   35592:                arg = new expr(ELIST,e2?(sub?sub:e2):zero,arg); // may be preallocated
                   35593:                base = CAST;
                   35594:                tp2 = tp;
                   35595:                e1 = new expr(G_CALL,vec_new_fct,arg);
                   35596:                e1->fct_name = vec_new_fct;
                   35597:                e1->tp = Pfct(vec_new_fct->tp)->returns;
                   35598:                simpl();
                   35599:                return;
                   35600:        }
                   35601: 
                   35602:        /* call _new(element_size*no_of_elements) */
                   35603: //error('d',"sz %d var %d",sz,var_expr);
                   35604:        if (sz == 1)
                   35605:                arg = (var_expr) ? new expr(MUL,szof,var_expr) : szof;
                   35606:        else {
                   35607:                const_expr = new ival(sz);
                   35608:                const_expr->tp = uint_type;
                   35609:                const_expr = new expr(MUL,const_expr,szof);
                   35610:                const_expr->tp = uint_type;
                   35611:                arg = (var_expr) ? new expr(MUL,const_expr,var_expr) : const_expr;
                   35612:        }
                   35613: 
                   35614:        arg->tp = uint_type;
                   35615:        base = CAST;
                   35616:        tp2 = tp;
                   35617:        arg = new expr(ELIST,arg,e2);
                   35618:        nf = gtbl->look(oper_name(NEW),0);      // always global,
                   35619:                                                // all class object handled above
                   35620:        e1 = new expr(G_CALL,nf,arg);
                   35621:        (void) e1->call_fct(gtbl);
                   35622:        simpl();
                   35623: 
                   35624:        if (init) {     // alloc(sz) => (p=alloc(sz),*p=init,p);
                   35625:                Pexpr p = init->e1;
                   35626:                Pexpr ee = new expr(0,0,0);
                   35627:                *ee = *this;    
                   35628:                ee = new expr(ASSIGN,p,ee);     // ee: p = alloc(sz);
                   35629:                init->base = ASSIGN;
                   35630:                init->e1 = p->contents();       // init: *p = init_val
                   35631:                ee = new expr(CM,ee,init);
                   35632:                ee->simpl(); 
                   35633:                base = CM;
                   35634:                e1 = ee;
                   35635:                e2 = p;
                   35636:        }
                   35637: }
                   35638: 
                   35639: void expr::simpl_delete()
                   35640: /*
                   35641:        delete p => _delete(p);
                   35642:                    or  cl::~cl(p,1);
                   35643:        delete[s]p => _delete(p);
                   35644:                        or vec_del_fct(p,vec_sz,elem_sz,~cl,1);
                   35645: */              
                   35646: {
                   35647:        for (Ptype tt = e1->tp; tt->base==TYPE; tt=Pbase(tt)->b_name->tp);
                   35648:        tt = Pptr(tt)->typ;
                   35649: //error('d',"simpl_delete() %t",e1->tp);
                   35650:        Pname cln = tt->is_cl_obj();
                   35651:        Pname n;
                   35652:        Pclass cl;
                   35653: 
                   35654:        if (cln) {
                   35655:                cl = Pclass(cln->tp);
                   35656:                if ((cl->defined&DEFINED) == 0) error('w',"delete%t (%t not defined)",cl,cl);
                   35657:        }
                   35658:        else
                   35659:                cl = 0;
                   35660: 
                   35661:        if (cl && (n=cl->has_dtor())) { // ~cl() might be virtual
                   35662:                //xxx check for private/protected op delete
                   35663:                {
                   35664:                        Pexpr ee = new expr(ELIST,e1,0);
                   35665:                        char* s = oper_name(DELETE);
                   35666:                        Pname n;
                   35667: //error('d',"%s( %k )",s,e1->base);
                   35668:                        if (base!=GDELETE) {
                   35669:                                n = new name(s);
                   35670:                                n = (Pname)find_name(n,cl,scope,CALL,curr_fct);
                   35671: //error('d',"found%n  %t",n,n->tp);
                   35672:                                if (n->tp->base==OVERLOAD
                   35673:                                ||  Pfct(n->tp)->nargs==2) {
                   35674:                                        Pexpr ss = new texpr(SIZEOF,cl,0);
                   35675:                                        ss->tp = size_t_type;
                   35676:                                        ee->e2 = new expr(ELIST,ss,0);
                   35677:                                }
                   35678:                        }
                   35679:                        else
                   35680:                                n = gtbl->look(s,0);
                   35681: //error('d',"found%n  %t",n,n->tp);
                   35682:                        ee = new call(n,ee);
                   35683:                        ee->base = G_CALL;
                   35684: //error('d',"delete..."); display_expr(ee);
                   35685: // following commented out to avoid typ::checking problems
                   35686:                        //overFound=0; // set in call_fct
                   35687:                        //(void) ee->call_fct(cl->memtbl);
                   35688:                        //if (overFound && overFound->n_scope != EXTERN) 
                   35689:                                //check_visibility(overFound,0,cl,cc->ftbl,cc->nof);
                   35690:                        //overFound=0;
                   35691:                }
                   35692: 
                   35693: //if ( base!=GDELETE ) (void) cl->has_oper(DELETE);
                   35694: 
                   35695:                if(base==GDELETE && e2==0 || Pfct(n->tp)->f_virtual) {  // may need temp
                   35696:                        nin=1;
                   35697:                        int needtemp = e1->not_simple();
                   35698:                        nin=0;
                   35699:                        if(needtemp) {
                   35700:                                // convert:     delete [e2] e1
                   35701:                                // to:  (T=e1), delete [e2] T
                   35702:                                // where T is a new temporary.
                   35703:                                Pname tnx = new name(make_name('K'));
                   35704:                                tnx->tp = e1->tp;
                   35705:                                Pname tn = tnx->dcl(scope,FCT);
                   35706:                                delete tnx;
                   35707:                                tn->assign();
                   35708:                                e1 = new expr(ASSIGN,tn,e1);
                   35709:                                e2 = new expr(base,tn,e2);
                   35710:                                base=CM;
                   35711: 
                   35712:                                simpl();
                   35713:                                return;
                   35714:                        }
                   35715:                }
                   35716:                Pexpr r = e1;
                   35717:        
                   35718:                // handle delete p, where p has a private destructor
                   35719:                if (n->n_scope != PUBLIC) check_visibility(n,0,cl,cc->ftbl,cc->nof);
                   35720: //error('d',"e2 %d %k",e2,base);
                   35721:                if (e2 == 0) {          // e1->cl::~cl(1)
                   35722:                        Pexpr ee = call_dtor(r,n,base==GDELETE?0:one,REF,one);
                   35723:                        if (Pfct(n->tp)->f_virtual) {
                   35724:                                if (ansi_opt) { // q?void:int would be an error
                   35725:                                        ee = new expr(G_CM,ee,zero);
                   35726:                                        ee->tp = zero_type;
                   35727:                                }
                   35728:                                ee = new expr(QUEST,ee,zero);
                   35729:                                ee->tp = ee->e1->tp;
                   35730:                                ee->cond = r;
                   35731:                        }
                   35732:                        if (base == GDELETE) {
                   35733:                                char* s = oper_name(DELETE);
                   35734:                                Pexpr p = gtbl->look(s,0);
                   35735:                                e2 = new call(p,new expr(ELIST,e1,0));
                   35736:                                base = CM;
                   35737:                                e1 = ee;
                   35738:                        }
                   35739:                        else {
                   35740:                                *this = *ee;
                   35741:                                delete ee;
                   35742:                        }
                   35743:                        simpl();
                   35744:                        return;
                   35745:                }
                   35746:                else {          // del_cl_vec(e1,e2,elem_size,~cl,1);
                   35747:                        Pexpr sz = new texpr(SIZEOF,tt,0);
                   35748:                        (void)tt->tsizeof();
                   35749:                        Pfct f = Pfct(n->tp);
                   35750:                        int i = 0;
                   35751:                        Pname nn = f->f_args->n_list;
                   35752:                        for (; nn && nn->n_list; nn=nn->n_list) i++;
                   35753: //error('d',"n %n i %d",n,i);
                   35754:                        Pexpr arg = new ival(i);
                   35755:                        sz->tp = uint_type;
                   35756:                //      Pexpr arg = one;
                   35757:                        arg = new expr(ELIST,one,arg);
                   35758:                        if (Pfct(n->tp)->f_virtual) {
                   35759:                                Pexpr a = new ref(REF,e1,n);
                   35760:                                a = a->address();
                   35761:                                a = new mdot( "f", a );
                   35762:                                a->i1 = 9;
                   35763:                                arg = new expr(ELIST,a,arg);
                   35764:                        }
                   35765:                        else {
                   35766:                                arg = new expr(ELIST,n,arg);
                   35767:                                n->lval(ADDROF);        // n->take_addr();
                   35768:                        }
                   35769: 
                   35770:                        arg = new expr(ELIST,sz,arg);
                   35771:                        if (e2->base==DUMMY) {
                   35772:                                e2 = new ival(-1);      // handle `delete[]p'
                   35773:                        }
                   35774: 
                   35775:                        arg = new expr(ELIST,e2,arg);
                   35776:                        arg = new expr(ELIST,e1,arg);
                   35777:                        Pexpr ee = new expr(G_CALL,vec_del_fct,arg);
                   35778:                        ee->fct_name = vec_del_fct;
                   35779:                        ee->tp = tp;
                   35780:        //              if (ansi_opt) { // q?void:int would be an error
                   35781:        //                      ee = new expr(G_CM,ee,zero);
                   35782:        //                      ee->tp = zero_type;
                   35783:        //              }
                   35784:        //              ee = new expr(QUEST,ee,zero);
                   35785:        //              ee->tp = tp;
                   35786:        //              ee->cond = r;
                   35787:                        *this = *ee;
                   35788:                        simpl();
                   35789:                        return;
                   35790:                }
                   35791:        }
                   35792:        else if (cl_obj_vec) {
                   35793:                error("delete array of arrays");
                   35794:        }
                   35795:        else {                                  // _delete(e1)
                   35796:                Pexpr ee = new expr(ELIST,e1,0);
                   35797:                char* s = oper_name(DELETE);
                   35798:                if (cl && base!=GDELETE) {
                   35799:                        Pname n = new name(s);
                   35800:                        e1 = find_name(n,cl,scope,CALL,curr_fct);
                   35801:                        if (e1->tp->base==OVERLOAD || Pfct(e1->tp)->nargs==2) {
                   35802:                                Pexpr ss = new texpr(SIZEOF,cl,0);
                   35803:                                ss->tp = size_t_type;
                   35804:                                ee->e2 = new expr(ELIST,ss,0);
                   35805:                        }
                   35806:                }
                   35807:                else
                   35808:                        e1 = gtbl->look(s,0);
                   35809:                base = G_CALL;
                   35810:                e2 = ee;
                   35811:                overFound=0; // set in call_fct
                   35812:                (void) call_fct(scope);
                   35813:                if (overFound && overFound->n_scope != EXTERN) 
                   35814:                        check_visibility(overFound,0,cl,cc->ftbl,cc->nof);
                   35815:                overFound=0;
                   35816:        }
                   35817: 
                   35818:        Pcall(this)->simpl();
                   35819: }
                   35820: 0707071010112045371004440001630000160000010207600466055410400000700000013461size.c/*ident     "@(#)ctrans:src/size.c  1.3" */
                   35821: /*********************************************************************
                   35822: 
                   35823:        C++ source for cfront, the C++ compiler front-end
                   35824:        written in the computer science research center of Bell Labs
                   35825: 
                   35826:        Copyright (c) 1984 AT&T, Inc. All rigths Reserved
                   35827:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   35828: 
                   35829: size.c:
                   35830: 
                   35831:        initialize alignment and sizeof "constants"
                   35832: 
                   35833: **********************************************************************/
                   35834: 
                   35835: #include "cfront.h"
                   35836: #include "size.h"
                   35837: 
                   35838: int BI_IN_WORD = DBI_IN_WORD;
                   35839: int BI_IN_BYTE = DBI_IN_BYTE;
                   35840: int SZ_CHAR = DSZ_CHAR;
                   35841: int AL_CHAR = DAL_CHAR;
                   35842: int SZ_SHORT = DSZ_SHORT;
                   35843: int AL_SHORT = DAL_SHORT;
                   35844: int SZ_INT = DSZ_INT;
                   35845: int AL_INT = DAL_INT;
                   35846: int SZ_LONG = DSZ_LONG;
                   35847: int AL_LONG = DAL_LONG;
                   35848: int SZ_FLOAT = DSZ_FLOAT;
                   35849: int AL_FLOAT = DAL_FLOAT;
                   35850: int SZ_DOUBLE = DSZ_DOUBLE;
                   35851: int AL_DOUBLE = DAL_DOUBLE;
                   35852: int SZ_LDOUBLE = DSZ_LDOUBLE;
                   35853: int AL_LDOUBLE = DAL_LDOUBLE;
                   35854: int SZ_STRUCT = DSZ_STRUCT;
                   35855: int AL_STRUCT = DAL_STRUCT;
                   35856: //int SZ_FRAME = DSZ_FRAME;
                   35857: //int AL_FRAME = DAL_FRAME;
                   35858: int SZ_WORD = DSZ_WORD;
                   35859: int SZ_WPTR = DSZ_WPTR;
                   35860: int AL_WPTR = DAL_WPTR;
                   35861: int SZ_BPTR = DSZ_BPTR;
                   35862: int AL_BPTR = DAL_BPTR;
                   35863: //int SZ_TOP = DSZ_TOP;
                   35864: //int SZ_BOTTOM = DSZ_BOTTOM;
                   35865: char* LARGEST_INT = DLARGEST_INT;
                   35866: int F_SENSITIVE = DF_SENSITIVE;
                   35867: int F_OPTIMIZED =  DF_OPTIMIZED;
                   35868: 
                   35869: int arg1 = 0;
                   35870: 
                   35871: int get_line(FILE* fp)
                   35872: {
                   35873:        char s[32];
                   35874:        char s2[32];
                   35875: 
                   35876:        if (fscanf(fp,"%s %s",s2,s) == EOF) return 0;
                   35877: 
                   35878:        if (strcmp("DLARGEST_INT",s) == 0) { 
                   35879:                if (fscanf(fp," %s",s2)==EOF) return 0;
                   35880: //// get rid of quotes
                   35881:                for(int i=0;i<=strlen(s2)+1;i++)
                   35882:                        if (s2[i]== '"') {
                   35883:                                for (int j=i;j<=strlen(s2)+1;j++)
                   35884:                                        s2[j]=s2[j+1];
                   35885:                        }
                   35886:                }
                   35887:        else 
                   35888:                if (fscanf(fp,"%d ",&arg1) == EOF) return 0;
                   35889: 
                   35890:        if (strcmp("DSZ_CHAR",s) == 0) {
                   35891:                SZ_CHAR = arg1;
                   35892:                return 1;
                   35893:        }
                   35894: 
                   35895:        if (strcmp("DAL_CHAR",s) == 0) {
                   35896:                AL_CHAR = arg1;
                   35897:                return 1;
                   35898:        }
                   35899: 
                   35900:        if (strcmp("DSZ_SHORT",s) == 0) {
                   35901:                SZ_SHORT = arg1;
                   35902:                return 1;
                   35903:        }
                   35904:        
                   35905:        if (strcmp("DAL_SHORT",s) == 0) {
                   35906:                AL_SHORT = arg1;
                   35907:                return 1;
                   35908:        }
                   35909: 
                   35910:        if (strcmp("DSZ_INT",s) == 0) {
                   35911:                SZ_INT = arg1;
                   35912:                return 1;
                   35913:        }
                   35914: 
                   35915:        if (strcmp("DAL_INT",s) == 0) {
                   35916:                AL_INT=arg1;
                   35917:                return 1;
                   35918:        }
                   35919: 
                   35920:        if (strcmp("DLARGEST_INT",s) == 0) {
                   35921:                LARGEST_INT = new char[strlen(s2)+1];
                   35922:                strcpy(LARGEST_INT,s2);
                   35923:                return 1;
                   35924:        }
                   35925: 
                   35926:        if (strcmp("DSZ_LONG",s) == 0) {
                   35927:                SZ_LONG = arg1;
                   35928:                return 1;
                   35929:        }
                   35930: 
                   35931:        if (strcmp("DAL_LONG",s) == 0) {
                   35932:                AL_LONG = arg1;
                   35933:                return 1;
                   35934:        }
                   35935: 
                   35936:        if (strcmp("DSZ_FLOAT",s) == 0) {
                   35937:                SZ_FLOAT = arg1;
                   35938:                return 1;
                   35939:        }
                   35940: 
                   35941:        if (strcmp("DAL_FLOAT",s) == 0) {
                   35942:                AL_FLOAT = arg1;
                   35943:                return 1;
                   35944:        }
                   35945: 
                   35946:        if (strcmp("DSZ_DOUBLE",s) == 0) {
                   35947:                SZ_DOUBLE = arg1;
                   35948:                return 1;
                   35949:        }
                   35950: 
                   35951:        if (strcmp("DAL_DOUBLE",s) == 0) {
                   35952:                AL_DOUBLE = arg1;
                   35953:                return 1;
                   35954:        }
                   35955:        
                   35956:        if (strcmp("DSZ_LDOUBLE",s) == 0) {
                   35957:                SZ_LDOUBLE = arg1;
                   35958:                return 1;
                   35959:        }
                   35960: 
                   35961:        if (strcmp("DAL_LDOUBLE",s) == 0) {
                   35962:                AL_LDOUBLE = arg1;
                   35963:                return 1;
                   35964:        }
                   35965: 
                   35966:        if (strcmp("DBI_IN_BYTE",s) == 0) {
                   35967:                BI_IN_BYTE = arg1;
                   35968:                return 1;
                   35969:        }
                   35970: 
                   35971:        if (strcmp("DBI_IN_WORD",s) == 0) {
                   35972:                BI_IN_WORD= arg1;
                   35973:                return 1;
                   35974:        }
                   35975: 
                   35976:        if (strcmp("DSZ_STRUCT",s) == 0) {
                   35977:                SZ_STRUCT = arg1;
                   35978:                return 1;
                   35979:        }
                   35980: 
                   35981:        if (strcmp("DAL_STRUCT",s) == 0) {
                   35982:                AL_STRUCT = arg1;
                   35983:                return 1;
                   35984:        }
                   35985: 
                   35986:        if (strcmp("DF_SENSITIVE",s) == 0) {
                   35987:                F_SENSITIVE = arg1;
                   35988:                return 1;
                   35989:        }
                   35990: 
                   35991:        if (strcmp("DF_OPTIMIZED",s) == 0) {
                   35992:                F_OPTIMIZED = arg1;
                   35993:                return 1;
                   35994:        }
                   35995: 
                   35996:        if (strcmp("frame",s) == 0) {
                   35997: //             SZ_FRAME = arg1;
                   35998: //             AL_FRAME = arg2;
                   35999:                return 1;
                   36000:        }
                   36001: 
                   36002:        if (strcmp("DSZ_WORD",s) == 0) {
                   36003:                SZ_WORD = arg1;
                   36004:                return 1;
                   36005:        }
                   36006: 
                   36007:        if (strcmp("DSZ_WPTR",s) == 0) {
                   36008:                SZ_WPTR = arg1;
                   36009:                return 1;
                   36010:        }
                   36011: 
                   36012:        if (strcmp("DAL_WPTR",s) == 0) {
                   36013:                AL_WPTR = arg1;
                   36014:                return 1;
                   36015:        }
                   36016: 
                   36017:        if (strcmp("DSZ_BPTR",s) == 0) {
                   36018:                SZ_BPTR = arg1;
                   36019:                return 1;
                   36020:        }
                   36021: 
                   36022:        if (strcmp("DAL_BPTR",s) == 0) {
                   36023:                AL_BPTR = arg1;
                   36024:                return 1;
                   36025:        }
                   36026: 
                   36027:        if (strcmp("top",s) == 0) {
                   36028: //             SZ_TOP = arg1;
                   36029: //             SZ_BOTTOM = arg2;
                   36030:                return 1;
                   36031:        }
                   36032:        return 0;
                   36033: }
                   36034: 
                   36035: int read_align(char* f)
                   36036: {
                   36037:        char* p = f;
                   36038:        if (*p == 0) {
                   36039:                fprintf(stderr,"size/align file missing\n");
                   36040:                ext(1);
                   36041:        }
                   36042:        FILE* fp = fopen(f,"r");
                   36043:        if (fp == 0) return 1;
                   36044:        while (get_line(fp)) ;
                   36045:        return 0;
                   36046: }
                   36047: /*
                   36048: print_align(char* s)
                   36049: {
                   36050:        fprintf(stderr,"%s sizes and alignments\n\n",s);
                   36051: 
                   36052:        fprintf(stderr,"        size    align   largest\n");
                   36053:        fprintf(stderr,"char    %d      %d\n",SZ_CHAR,AL_CHAR);
                   36054:        fprintf(stderr,"short   %d      %d\n",SZ_SHORT,AL_SHORT);
                   36055:        fprintf(stderr,"int     %d      %d      %s\n",SZ_INT,AL_INT,LARGEST_INT);
                   36056:        fprintf(stderr,"long    %d      %d\n",SZ_LONG,AL_LONG);
                   36057:        fprintf(stderr,"float   %d      %d\n",SZ_FLOAT,AL_FLOAT);
                   36058:        fprintf(stderr,"double  %d      %d\n",SZ_DOUBLE,AL_DOUBLE);
                   36059:        fprintf(stderr,"ldouble %d      %d\n",SZ_LDOUBLE,AL_LDOUBLE);
                   36060:        fprintf(stderr,"bptr    %d      %d\n",SZ_BPTR,AL_BPTR);
                   36061:        fprintf(stderr,"wptr    %d      %d\n",SZ_WPTR,AL_WPTR);
                   36062:        fprintf(stderr,"struct  %d      %d\n",SZ_STRUCT,AL_STRUCT);
                   36063:        fprintf(stderr,"struct2 %d      %d\n",F_SENSITIVE,F_OPTIMIZED);
                   36064: //     fprintf(stderr,"frame   %d      %d\n",SZ_FRAME,AL_FRAME);
                   36065: 
                   36066:        fprintf(stderr,"%d bits in a byte, %d bits in a word, %d bytes in a word\n",
                   36067:                        BI_IN_BYTE, BI_IN_WORD, SZ_WORD);
                   36068:        return 1;
                   36069: }
                   36070: */
                   36071: 
                   36072: int c_strlen(const char* s)
                   36073: /*
                   36074:        return sizeof(s) with escapes processed
                   36075:        sizeof("") == 1         the terminating 0
                   36076:        sizeof("a") == 2
                   36077:        sizeof("\0x") == 3      0 x 0
                   36078:        sizeof("\012") == 2     '\012'
                   36079:        sizeof("\01")           '\001'
                   36080:        sizeof("\x") == 2       \ ignored
                   36081: 
                   36082: */
                   36083: {
                   36084:        int i = 1;
                   36085:         for (const char* p = s; *p; i++,p++) {
                   36086:                if (*p == '\\') {                                       // '\?
                   36087:                        switch (*++p) {
                   36088:                        case '0':
                   36089:                                switch (p[1]) {         // '\01' or '\012'
                   36090:                                case '0': case '1': case '2': case '3':
                   36091:                                case '4': case '5': case '6': case '7':
                   36092:                                        break;
                   36093:                                default:
                   36094:                                        continue;       // '\0'
                   36095:                                }
                   36096:                                /* no break */
                   36097:                        case '1': case '2': case '3':
                   36098:                        case '4': case '5': case '6': case '7':         // '\123'
                   36099:                                switch (*++p) {
                   36100:                                case '0': case '1': case '2': case '3':
                   36101:                                case '4': case '5': case '6': case '7':
                   36102:                                        switch (*++p) {
                   36103:                                        case '0': case '1': case '2': case '3':
                   36104:                                        case '4': case '5': case '6': case '7':
                   36105:                                                break;
                   36106:                                        default:
                   36107:                                                --p;
                   36108:                                        }
                   36109:                                        break;
                   36110:                                default:
                   36111:                                        --p;
                   36112:                                        break;
                   36113:                                }
                   36114:                                break;
                   36115:                        case '\n':                      // \newline doesn't count
                   36116:                                i--;
                   36117:                                break;
                   36118:                        }
                   36119:                }
                   36120:        }
                   36121:        return i;
                   36122: }
                   36123: 0707071010112045661004440001630000160000010207700466055411000000700000020157size.h/*ident     "@(#)ctrans:src/size.h  1.2" */
                   36124: /*************************************************************************
                   36125: 
                   36126:        C++ source for cfront, the C++ compiler front-end
                   36127:        written in the computer science research center of Bell Labs
                   36128: 
                   36129:        Copyright (c) 1984 AT&T, Inc. All rigths Reserved
                   36130:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   36131: 
                   36132: size.h:
                   36133:        sizes and alignments used to calculate sizeofs
                   36134: 
                   36135:        table and butffer sizes
                   36136: 
                   36137: ***************************************************************************/
                   36138: #ifndef GRAM
                   36139: extern BI_IN_WORD;
                   36140: extern BI_IN_BYTE;
                   36141:                                /*      byte sizes */
                   36142: extern SZ_CHAR;
                   36143: extern AL_CHAR;
                   36144: 
                   36145: extern SZ_SHORT;
                   36146: extern AL_SHORT;
                   36147: 
                   36148: extern SZ_INT;
                   36149: extern AL_INT;
                   36150: 
                   36151: extern SZ_LONG;
                   36152: extern AL_LONG;
                   36153: 
                   36154: extern SZ_FLOAT;
                   36155: extern AL_FLOAT;
                   36156: 
                   36157: extern SZ_DOUBLE;
                   36158: extern AL_DOUBLE;
                   36159: 
                   36160: extern SZ_LDOUBLE;
                   36161: extern AL_LDOUBLE;
                   36162: 
                   36163: extern SZ_STRUCT;      /* minimum struct size */
                   36164: extern AL_STRUCT;
                   36165: 
                   36166: //extern SZ_FRAME;
                   36167: //extern AL_FRAME;
                   36168: 
                   36169: extern SZ_WORD;
                   36170: 
                   36171: extern SZ_WPTR;
                   36172: extern AL_WPTR;
                   36173: 
                   36174: extern SZ_BPTR;
                   36175: extern AL_BPTR;        
                   36176: 
                   36177: //extern SZ_TOP;
                   36178: //extern SZ_BOTTOM;
                   36179: 
                   36180: extern char* LARGEST_INT;
                   36181: extern int F_SENSITIVE;        // is field alignment sensitive to the type of the field?
                   36182: extern int F_OPTIMIZED;        // can the compiler fit a small int field into a char?
                   36183: #endif
                   36184:                                // default sizes:
                   36185:        // Note: #if doesn't work on all systems
                   36186: #ifdef u3b
                   36187: #define Abbb
                   36188: #endif
                   36189: #ifdef u3b2
                   36190: #define Abbb
                   36191: #endif
                   36192: #ifdef u3b5
                   36193: #define Abbb
                   36194: #endif
                   36195: #ifdef u3b15
                   36196: #define Abbb
                   36197: #endif
                   36198: #ifdef pyr
                   36199: #define Abbb
                   36200: #endif
                   36201: 
                   36202: 
                   36203: #ifdef alliant
                   36204: #define Am68
                   36205: #endif
                   36206: #ifdef apollo
                   36207: #define Am68
                   36208: #endif
                   36209: #if defined(sun2) || defined(mc68010)
                   36210: #define Am68
                   36211: #endif
                   36212: #if defined(sun3) || defined(mc68020)
                   36213: #define Am68
                   36214: #endif
                   36215: #if defined(mc68k) || defined(hp9000s200) || defined(hp9000s300)
                   36216: #define Am68
                   36217: #endif
                   36218: 
                   36219: #ifdef iAPX286
                   36220: #ifdef LARGE
                   36221: #define Ai286l
                   36222: #endif
                   36223: #endif
                   36224: 
                   36225: #ifdef Abbb
                   36226:                                /* AT&T 3Bs */
                   36227: #define DBI_IN_WORD 32
                   36228: #define DBI_IN_BYTE 8
                   36229: #define DSZ_CHAR 1
                   36230: #define DAL_CHAR 1
                   36231: #define DSZ_SHORT 2
                   36232: #define DAL_SHORT 2
                   36233: #define DSZ_INT 4
                   36234: #define DAL_INT 4
                   36235: #define DSZ_LONG 4
                   36236: #define DAL_LONG 4
                   36237: #define DSZ_FLOAT 4
                   36238: #define DAL_FLOAT 4
                   36239: #define DSZ_DOUBLE 8
                   36240: #define DAL_DOUBLE 4
                   36241: #define DSZ_LDOUBLE 8
                   36242: #define DAL_LDOUBLE 4
                   36243: #define DSZ_STRUCT 4
                   36244: #define DAL_STRUCT 4
                   36245: //#define DSZ_FRAME 4
                   36246: //#define DAL_FRAME 4
                   36247: #define DSZ_WORD 4
                   36248: #define DSZ_WPTR 4
                   36249: #define DAL_WPTR 4
                   36250: #define DSZ_BPTR 4
                   36251: #define DAL_BPTR 4
                   36252: //#define DSZ_TOP 0
                   36253: //#define DSZ_BOTTOM 0
                   36254: #define DLARGEST_INT "2147483647"      /* 2**31 - 1 */
                   36255: #define DF_SENSITIVE 0
                   36256: #define DF_OPTIMIZED 1
                   36257: #else
                   36258: #ifdef Am68
                   36259:                                /* most M68K boxes */
                   36260: #if defined(hp9000s200) || defined(hp9000s300)
                   36261: #define DBI_IN_WORD 32 
                   36262: #else
                   36263: #define DBI_IN_WORD 16
                   36264: #endif
                   36265: #define DBI_IN_BYTE 8
                   36266: #define DSZ_CHAR 1
                   36267: #define DAL_CHAR 1
                   36268: #define DSZ_SHORT 2
                   36269: #define DAL_SHORT 2
                   36270: #define DSZ_INT 4
                   36271: #define DAL_INT 2
                   36272: #define DSZ_LONG 4
                   36273: #define DAL_LONG 2
                   36274: #define DSZ_FLOAT 4
                   36275: #define DAL_FLOAT 2
                   36276: #define DSZ_DOUBLE 8
                   36277: #define DAL_DOUBLE 2
                   36278: #define DSZ_LDOUBLE 8
                   36279: #define DAL_LDOUBLE 2
                   36280: #define DSZ_STRUCT 2
                   36281: #define DAL_STRUCT 2
                   36282: //#define DSZ_FRAME 4
                   36283: //#define DAL_FRAME 4
                   36284: #define DSZ_WORD 2
                   36285: #define DSZ_WPTR 4
                   36286: #define DAL_WPTR 2
                   36287: #define DSZ_BPTR 4
                   36288: #define DAL_BPTR 2
                   36289: //#define DSZ_TOP 0
                   36290: //#define DSZ_BOTTOM 0
                   36291: #define DLARGEST_INT "2147483647"      /* 2**31 - 1 */
                   36292: #define DF_SENSITIVE 0
                   36293: #define DF_OPTIMIZED 1
                   36294: #else
                   36295: #ifdef Ai286l
                   36296:                                /* Intel 80286 large model */
                   36297: #define DBI_IN_WORD 16
                   36298: #define DBI_IN_BYTE 8
                   36299: #define DSZ_CHAR 1
                   36300: #define DAL_CHAR 1
                   36301: #define DSZ_SHORT 2
                   36302: #define DAL_SHORT 2
                   36303: #define DSZ_INT 2
                   36304: #define DAL_INT 2
                   36305: #define DSZ_LONG 4
                   36306: #define DAL_LONG 2
                   36307: #define DSZ_FLOAT 4
                   36308: #define DAL_FLOAT 2
                   36309: #define DSZ_DOUBLE 8
                   36310: #define DAL_DOUBLE 2
                   36311: #define DSZ_LDOUBLE 8
                   36312: #define DAL_LDOUBLE 2
                   36313: #define DSZ_STRUCT 2
                   36314: #define DAL_STRUCT 2
                   36315: //#define DSZ_FRAME 4
                   36316: //#define DAL_FRAME 4
                   36317: #define DSZ_WORD 2
                   36318: #define DSZ_WPTR 4
                   36319: #define DAL_WPTR 2
                   36320: #define DSZ_BPTR 4
                   36321: #define DAL_BPTR 2
                   36322: //#define DSZ_TOP 0
                   36323: //#define DSZ_BOTTOM 0
                   36324: #define DLARGEST_INT "32767"   /* 2**15 - 1 */
                   36325: #define DF_SENSITIVE 0
                   36326: #define DF_OPTIMIZED 1
                   36327: #else
                   36328: #if defined(uts) || defined(hp9000s800) || defined(sun4) || defined(sparc)
                   36329:                                /* Amdahl running UTS, HP RISC */
                   36330: #define DBI_IN_WORD 32
                   36331: #define DBI_IN_BYTE 8
                   36332: #define DSZ_CHAR 1
                   36333: #define DAL_CHAR 1
                   36334: #define DSZ_SHORT 2
                   36335: #define DAL_SHORT 2
                   36336: #define DSZ_INT 4
                   36337: #define DAL_INT 4
                   36338: #define DSZ_LONG 4
                   36339: #define DAL_LONG 4
                   36340: #define DSZ_FLOAT 4
                   36341: #define DAL_FLOAT 4
                   36342: #define DSZ_DOUBLE 8
                   36343: #define DAL_DOUBLE 8
                   36344: #define DSZ_LDOUBLE 8
                   36345: #define DAL_LDOUBLE 8
                   36346: #define DSZ_STRUCT 1
                   36347: #define DAL_STRUCT 1
                   36348: #define DSZ_WORD 4
                   36349: #define DSZ_WPTR 4
                   36350: #define DAL_WPTR 4
                   36351: #define DSZ_BPTR 4
                   36352: #define DAL_BPTR 4
                   36353: #define DLARGEST_INT "2147483647"      /* 2**31 - 1 */
                   36354: #if defined(uts)
                   36355: #define DF_SENSITIVE 1
                   36356: #else
                   36357: #define DF_SENSITIVE 0
                   36358: #endif
                   36359: #define DF_OPTIMIZED 1
                   36360: #else
                   36361: #ifdef hpux 
                   36362:                                 /* hp */
                   36363: #define DBI_IN_WORD 32
                   36364: #define DBI_IN_BYTE 8
                   36365: #define DSZ_CHAR 1
                   36366: #define DAL_CHAR 1
                   36367: #define DSZ_SHORT 2
                   36368: #define DAL_SHORT 2
                   36369: #define DSZ_INT 4
                   36370: #define DAL_INT 4
                   36371: #define DSZ_LONG 4
                   36372: #define DAL_LONG 4
                   36373: #define DSZ_FLOAT 4
                   36374: #define DAL_FLOAT 4
                   36375: #define DSZ_DOUBLE 8
                   36376: #define DAL_DOUBLE 8 
                   36377: #define DSZ_LDOUBLE 8
                   36378: #define DAL_LDOUBLE 8
                   36379: #define DSZ_STRUCT 1 
                   36380: #define DAL_STRUCT 1 
                   36381: #define DSZ_WORD 4
                   36382: #define DSZ_WPTR 4
                   36383: #define DAL_WPTR 4
                   36384: #define DSZ_BPTR 4
                   36385: #define DAL_BPTR 4
                   36386: #define DLARGEST_INT "2147483647"       /* 2**31 - 1 */
                   36387: #define DF_SENSITIVE 1 
                   36388: #define DF_OPTIMIZED 1
                   36389: #else
                   36390: #if defined(vax) || defined(ibm032) || defined(i386)
                   36391:                                /* VAX, IBM 32, Intel 386 */
                   36392: #define DBI_IN_WORD 32
                   36393: #define DBI_IN_BYTE 8
                   36394: #define DSZ_CHAR 1
                   36395: #define DAL_CHAR 1
                   36396: #define DSZ_SHORT 2
                   36397: #define DAL_SHORT 2
                   36398: #define DSZ_INT 4
                   36399: #define DAL_INT 4
                   36400: #define DSZ_LONG 4
                   36401: #define DAL_LONG 4
                   36402: #define DSZ_FLOAT 4
                   36403: #define DAL_FLOAT 4
                   36404: #define DSZ_DOUBLE 8
                   36405: #define DAL_DOUBLE 4
                   36406: #define DSZ_LDOUBLE 8
                   36407: #define DAL_LDOUBLE 4
                   36408: #define DSZ_STRUCT 1
                   36409: #define DAL_STRUCT 1
                   36410: //#define DSZ_FRAME 4
                   36411: //#define DAL_FRAME 4
                   36412: #define DSZ_WORD 4
                   36413: #define DSZ_WPTR 4
                   36414: #define DAL_WPTR 4
                   36415: #define DSZ_BPTR 4
                   36416: #define DAL_BPTR 4
                   36417: //#define DSZ_TOP 0
                   36418: //#define DSZ_BOTTOM 0
                   36419: #define DLARGEST_INT "2147483647"      /* 2**31 - 1 */
                   36420: #define DF_SENSITIVE 0
                   36421: #define DF_OPTIMIZED 1
                   36422: #else
                   36423: #ifdef mc300
                   36424: #define DBI_IN_WORD 32
                   36425: #define DBI_IN_BYTE 8
                   36426: #define DSZ_CHAR 1
                   36427: #define DAL_CHAR 1
                   36428: #define DSZ_SHORT 2
                   36429: #define DAL_SHORT 2
                   36430: #define DSZ_INT 4
                   36431: #define DAL_INT 4
                   36432: #define DSZ_LONG 4
                   36433: #define DAL_LONG 4
                   36434: #define DSZ_FLOAT 4
                   36435: #define DAL_FLOAT 4
                   36436: #define DSZ_DOUBLE 8
                   36437: #define DAL_DOUBLE 4
                   36438: #define DSZ_LDOUBLE 8
                   36439: #define DAL_LDOUBLE 4
                   36440: #define DSZ_STRUCT 2
                   36441: #define DAL_STRUCT 2
                   36442: //#define DSZ_FRAME 4
                   36443: //#define DAL_FRAME 4
                   36444: #define DSZ_WORD 4
                   36445: #define DSZ_WPTR 4
                   36446: #define DAL_WPTR 4
                   36447: #define DSZ_BPTR 4
                   36448: #define DAL_BPTR 4
                   36449: //#define DSZ_TOP 0
                   36450: //#define DSZ_BOTTOM 0
                   36451: #define DLARGEST_INT "2147483647"       /* 2**31 - 1 */
                   36452: #define DF_SENSITIVE 0
                   36453: #define DF_OPTIMIZED 1
                   36454: #else
                   36455: #ifdef mips
                   36456: #define DBI_IN_BYTE 8
                   36457: #define DBI_IN_WORD 32
                   36458: #define DSZ_WORD 4
                   36459: #define DSZ_CHAR 1
                   36460: #define DAL_CHAR 1
                   36461: #define DSZ_SHORT 2
                   36462: #define DAL_SHORT 2
                   36463: #define DSZ_INT 4
                   36464: #define DAL_INT 4
                   36465: #define DLARGEST_INT "2147483647"
                   36466: #define DSZ_LONG 4
                   36467: #define DAL_LONG 4
                   36468: #define DSZ_FLOAT 4
                   36469: #define DAL_FLOAT 4
                   36470: #define DSZ_DOUBLE 8
                   36471: #define DAL_DOUBLE 8
                   36472: #define DSZ_LDOUBLE 8 
                   36473: #define DAL_LDOUBLE 8 
                   36474: #define DSZ_BPTR 4
                   36475: #define DAL_BPTR 4
                   36476: #define DSZ_WPTR 4
                   36477: #define DAL_WPTR 4
                   36478: #define DSZ_STRUCT 1
                   36479: #define DAL_STRUCT 1
                   36480: #define DF_SENSITIVE 0
                   36481: #define DF_OPTIMIZED 1
                   36482: #else
                   36483:                                /* defaults: 0 => error */
                   36484: #define DBI_IN_WORD 0
                   36485: #define DBI_IN_BYTE 0
                   36486: #define DSZ_CHAR 1
                   36487: #define DAL_CHAR 1
                   36488: #define DSZ_SHORT 0
                   36489: #define DAL_SHORT 0
                   36490: #define DSZ_INT 0
                   36491: #define DAL_INT 0
                   36492: #define DSZ_LONG 0
                   36493: #define DAL_LONG 0
                   36494: #define DSZ_FLOAT 0
                   36495: #define DAL_FLOAT 0
                   36496: #define DSZ_DOUBLE 0
                   36497: #define DAL_DOUBLE 0
                   36498: #define DSZ_LDOUBLE 0
                   36499: #define DAL_LDOUBLE 0
                   36500: #define DSZ_STRUCT 0
                   36501: #define DAL_STRUCT 0
                   36502: #define DSZ_WORD 0
                   36503: #define DSZ_WPTR 0
                   36504: #define DAL_WPTR 0
                   36505: #define DSZ_BPTR 0
                   36506: #define DAL_BPTR 0
                   36507: #define DLARGEST_INT "0"
                   36508: #define DF_SENSITIVE 0
                   36509: #define DF_OPTIMIZED 0
                   36510: #endif
                   36511: #endif
                   36512: #endif
                   36513: #endif
                   36514: #endif
                   36515: #endif
                   36516: #endif
                   36517: #endif
                   36518: 
                   36519: #define KTBLSIZE       123     /*      initial keyword table size */
                   36520: #define GTBLSIZE       257     /*      initial global name table size */
                   36521: #define CTBLSIZE       12      /*      initial class table size */
                   36522: #define TBLSIZE                20      /*      initial block table size */
                   36523: #define BLMAX          50      /*      max block nesting */
                   36524: #define MAXFILE                127     /*      max include file nesting */
                   36525: #define MAXERR         13      /* maximum number of errors before terminating */
                   36526: 
                   36527: #ifndef GRAM
                   36528: const CHUNK = 8*1024;
                   36529: void* chunk(int);
                   36530: #endif
                   36531: 0707071010112045671004440001630000160000010210000466055411300001000000015476table.c/*ident    "@(#)ctrans:src/table.c 1.3" */
                   36532: /**************************************************************************
                   36533: 
                   36534:         C++ source for cfront, the C++ compiler front-end
                   36535:         written in the computer science research center of Bell Labs
                   36536: 
                   36537:         Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   36538:         THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   36539: 
                   36540: table.c:
                   36541: 
                   36542: *****************************************************************************/
                   36543: 
                   36544: #include "cfront.h"
                   36545: #include "size.h"
                   36546: 
                   36547: #ifdef DBG
                   36548: extern long node_id;
                   36549: #define DBCHECK() if(node::allocated) error('i',"allocated node (id %d, base%k) on free list! (src: \"%s\", %d",node::id,node::base,__FILE__,__LINE__);
                   36550: #else
                   36551: #define DBCHECK() /**/
                   36552: #endif
                   36553: 
                   36554: table::table(short sz, Ptable nx, Pname n)
                   36555: /*
                   36556:        create a symbol table with "size" entries
                   36557:        the scope of table is enclosed in the scope of "nx"
                   36558: 
                   36559:        both the vector of class name pointers and the hash table
                   36560:        are initialized containing all zeroes
                   36561:        
                   36562:        to simplify hashed lookup entries[0] is never used
                   36563:        so the size of "entries" must be "size+1" to hold "size" entries
                   36564: */
                   36565: {
                   36566:        DBCHECK();
                   36567:        base = TABLE;
                   36568:        t_name = n;
                   36569:        size = sz = (sz<=0) ? 2 : sz+1;
                   36570: //fprintf(stderr,"table::table %d %s %d (%d %d)\n", this, (n)?n->string:"?", sz,(sz*3)/2);
                   36571:        entries = new Pname[sz];
                   36572:        hashsize = sz = (sz*3)/2;
                   36573:        hashtbl = new short[sz];
                   36574:        next = nx;
                   36575:        free_slot = 1;
                   36576:        DBID();
                   36577: }
                   36578: 
                   36579: table::~table()
                   36580: {
                   36581:        delete entries;
                   36582:        delete hashtbl;
                   36583: }
                   36584: 
                   36585: Pname table::look(char* s, TOK k)
                   36586: /*
                   36587:        look for "s" in table, ignore entries which are not of "k" type
                   36588:        look and insert MUST be the same lookup algorithm
                   36589: */
                   36590: {
                   36591:        Ptable t;
                   36592:        register char * p;
                   36593:        register char * q;
                   36594:        register int i;
                   36595:        Pname n;
                   36596:        int rr;
                   36597: 
                   36598: //     if (s == 0) error('i',"%d->look(0)",this);
                   36599: //     if (this == 0) error('i',"0->look(%s)",s);
                   36600: //     if (base != TABLE) error('i',"(%d,%d)->look(%s)",this,base,s);
                   36601: 
                   36602:        /* use simple hashing with linear search for overflow */
                   36603: 
                   36604:        p = s;
                   36605:        i = 0;
                   36606:        while (*p) i += (i + *p++); /* i<<1 ^ *p++ better?*/
                   36607:        rr = (0<=i) ? i : -i;
                   36608: 
                   36609:        for (t=this; t; t=t->next) {    
                   36610:                /* in this and all enclosing scopes look for name "s" */
                   36611:                Pname* np = t->entries;
                   36612:                int mx = t->hashsize;
                   36613:                short* hash = t->hashtbl;
                   36614:                int firsti = i = rr%mx;
                   36615: 
                   36616:                do {                    
                   36617:                        if (hash[i] == 0) goto not_found;
                   36618:                        n = np[hash[i]];
                   36619:                        if (n == 0) error('i',"hashed lookup");
                   36620:                        p = n->string;          /* strcmp(n->n_string,s) */
                   36621:                        q = s;
                   36622:                        while (*p && *q)
                   36623:                                if (*p++ != *q++) goto nxt;
                   36624:                        if (*p == *q) goto found;
                   36625:                nxt:
                   36626:                        if (mx <= ++i) i = 0;           /* wrap around */
                   36627:                } while (i != firsti);
                   36628: 
                   36629:        found:
                   36630:                for (; n; n=n->n_tbl_list){     /* for  all name "s"s look for a key match */
                   36631:                        if (n->n_key == k) return n;
                   36632:                }
                   36633: 
                   36634:        not_found:;
                   36635:        }
                   36636: 
                   36637:        return 0;       /* not found && no enclosing scope */
                   36638: }
                   36639: 
                   36640: bit Nold;      /* non-zero if last insert() failed */
                   36641: 
                   36642: Pname table::insert(Pname nx, TOK k)
                   36643: /*
                   36644:        the lookup algorithm MUST be the same as look
                   36645:        if nx is found return the older entry otherwise a copy of nx;
                   36646:        Nold = (nx found) ? 1 : 0;
                   36647: */
                   36648: {
                   36649:        register char * p;
                   36650:        register int i;
                   36651:        Pname n;
                   36652:        Pname* np = entries;
                   36653:        Pname* link;
                   36654:        int firsti;
                   36655:        int mx = hashsize;
                   36656:        short* hash = hashtbl;
                   36657:        char* s = nx->string;
                   36658: 
                   36659:        if (s==0) error('i',"%p->insert(0,%k)",this,k);
                   36660:        nx->n_key = k;
                   36661:        if (nx->n_tbl_list || nx->n_table) error('i',"%n in two tables",nx);
                   36662:        /* use simple hashing with linear search for overflow */
                   36663: 
                   36664:        p = s;
                   36665:        i = 0;
                   36666:        while (*p) i += (i + *p++);
                   36667:        if (i<0) i = -i;
                   36668:        firsti = i = i%mx;
                   36669: 
                   36670:        do {    /* look for name "s" */
                   36671:                if (hash[i] == 0) {
                   36672:                        hash[i] = free_slot;
                   36673:                        goto add_np;
                   36674:                }
                   36675:                n = np[hash[i]];
                   36676:                if (n == 0) error('i',"hashed lookup");
                   36677:                if (strcmp(n->string,s) == 0) goto found;
                   36678: /*
                   36679:                p = n->string;
                   36680:                q = s;
                   36681:                while (*p && *q) if (*p++ != *q++) goto nxt;
                   36682:                if (*p == *q) goto found;
                   36683:        nxt:
                   36684: */
                   36685:                if (mx <= ++i) i = 0;   /* wrap around */
                   36686:        } while (i != firsti);
                   36687: 
                   36688:        error("N table full");
                   36689: 
                   36690: found: 
                   36691: 
                   36692: 
                   36693:        for(;;) {
                   36694:                if ( k!=NESTED && n->n_key==k) { Nold = 1; return n; }
                   36695: 
                   36696:                if (n->n_tbl_list)
                   36697:                        n = n->n_tbl_list;
                   36698:                else {
                   36699:                        link = &(n->n_tbl_list);
                   36700:                        goto re_allocate;
                   36701:                }
                   36702:        }
                   36703: 
                   36704: add_np:
                   36705:        if (size <= free_slot) {
                   36706:                grow(2*size);
                   36707:                return insert(nx,k);
                   36708:        }
                   36709: 
                   36710:        link = &(np[free_slot++]);
                   36711: 
                   36712: re_allocate:
                   36713:        {       
                   36714:                Pname nw = new name;
                   36715:                *nw = *nx;
                   36716:                char* ps = new char[strlen(s)+1]; // copy string to safer store
                   36717:                strcpy(ps,s);
                   36718: //             Nstr++;
                   36719:                nw->string = ps;
                   36720:                nw->n_table = this;
                   36721:                *link = nw;
                   36722:                Nold = 0;
                   36723: //             Nname++;
                   36724:                return nw;
                   36725:        }
                   36726: }
                   36727: 
                   36728: void table::grow(int g)
                   36729: {
                   36730:        short* hash;
                   36731:        register int j;
                   36732:        int mx; 
                   36733:        register Pname* np;
                   36734:        Pname n;
                   36735: 
                   36736:        if (g <= free_slot) error('i',"table.grow(%d,%d)",g,free_slot);
                   36737:        if (g <= size) return;
                   36738: //error('d',"grow %d %s %d->%d", this, (t_name)?t_name->string:"?", size, g+1);
                   36739:        size = mx = g+1;
                   36740: 
                   36741:        np = new Pname[mx];
                   36742:        for (j=0; j<free_slot; j++) np[j] = entries[j];
                   36743:        delete entries;
                   36744:        entries = np;
                   36745: 
                   36746:        delete hashtbl;
                   36747:        hashsize = mx = (g*3)/2;
                   36748:        hash = hashtbl = new short[mx];
                   36749: 
                   36750:        for (j=1; j<free_slot; j++) {   /* rehash(np[j]); */
                   36751:                char * s = np[j]->string;
                   36752:                register char * p;
                   36753:                char * q;
                   36754:                register int i;
                   36755:                int firsti;
                   36756: 
                   36757:                p = s;
                   36758:                i = 0;
                   36759:                while (*p) i += (i + *p++);
                   36760:                if (i<0) i = -i;
                   36761:                firsti = i = i%mx;
                   36762: 
                   36763:                do {    /* look for name "s" */
                   36764:                        if (hash[i] == 0) {
                   36765:                                hash[i] = j;
                   36766:                                goto add_np;
                   36767:                        }
                   36768:                        n = np[hash[i]];
                   36769:                        if (n == 0) error('i',"hashed lookup");
                   36770:                        p = n->string;  /* strcmp(n->n_string,s) */
                   36771:                        q = s;
                   36772:                        while (*p && *q) if (*p++ != *q++) goto nxt;
                   36773:                        if (*p == *q) goto found;
                   36774:                nxt:
                   36775:                        if (mx <= ++i) i = 0;   /* wrap around */
                   36776:                } while (i != firsti);
                   36777: 
                   36778:                error('i',"rehash??");
                   36779: 
                   36780:        found:
                   36781:                error('i',"rehash failed");
                   36782: 
                   36783:        add_np:;
                   36784:        }
                   36785: }
                   36786: 
                   36787: Pname table::get_mem(int i)
                   36788: /*
                   36789:        return a pointer to the i'th entry, or 0 if it does not exist
                   36790: */
                   36791: {
                   36792:        return (i<=0 || free_slot<=i) ? 0 : entries[i];
                   36793: }
                   36794: 
                   36795: void table_delete(char* s, TOK k, int ll )
                   36796: /*
                   36797:        deletes local class entry from keyword table
                   36798:        adjusts pointers if multiple entries
                   36799:        uses same lookup as table::look and table::insert
                   36800: */
                   36801: {
                   36802:        Ptable t = ktbl;
                   36803:        register char * p;
                   36804:        register char * q;
                   36805:        register int i;
                   36806:        Pname n;
                   36807:        int rr;
                   36808: 
                   36809:        p = s;
                   36810:        i = 0;
                   36811:        while (*p) i += (i + *p++); /* i<<1 ^ *p++ better?*/
                   36812:        rr = (0<=i) ? i : -i;
                   36813: 
                   36814: // error ('d', "table_delete: %s ll: %d", s, ll );
                   36815: 
                   36816:                Pname* np = t->entries;
                   36817:                int mx = t->hashsize;
                   36818:                short* hash = t->hashtbl;
                   36819:                int firsti = i = rr%mx;
                   36820: 
                   36821:                do {                    
                   36822:                        if (hash[i] == 0) error('i',"table delete: not found: %s", s );
                   36823:                        n = np[hash[i]];
                   36824:                        if (n == 0) error('i',"table delete: hashed lookup");
                   36825:                        p = n->string;          /* strcmp(n->n_string,s) */
                   36826:                        q = s;
                   36827: // error( 'd', "table_delete: %s", p );
                   36828:                        while (*p && *q)
                   36829:                                if (*p++ != *q++) goto nxt;
                   36830:                        if (*p == *q) goto found;
                   36831:                nxt:
                   36832:                        if (mx <= ++i) i = 0;           /* wrap around */
                   36833:                } while (i != firsti);
                   36834: 
                   36835:        found:
                   36836:                for (Pname prev = n; n; prev = n, n=n->n_tbl_list){     
                   36837: // error( 'd', "table_delete: found: %s %k lex: %d", n->string, n->n_key, n->lex_level );
                   36838:                        if (n->n_key == k && n->lex_level == ll ) {
                   36839: // error( 'd', "table_delete: prev: %d n: %d n->tbl_list: %d", prev, n, n->n_tbl_list);
                   36840:                                if ( prev == n && n->n_tbl_list == 0 )
                   36841:                                        hash[i] = 0;
                   36842:                                else
                   36843:                                        prev->n_tbl_list = n->n_tbl_list;
                   36844:                                return;
                   36845:                        }
                   36846:                }
                   36847: }
                   36848: 0707071010112046031004440001630000160000010211300466055416400001300000206556template.c/* ident "@(#)ctrans:src/template.c     1.3" */
                   36849: /*******************************************************************
                   36850: * template.c
                   36851: *
                   36852: * This file contains most of the implementation for a subset of 
                   36853: * parametrized types as defined by the 1989 Stroustrup JOOP paper.  
                   36854: * The subset chosen here  was the subset relevant to the 
                   36855: * implementation of aggregates in ObjectStore.
                   36856: * 
                   36857: * The following is a list of features supported by the 
                   36858: * implementation. The list of features parallels the 
                   36859: * description of templates in the JOOP paper. 
                   36860: *      
                   36861: *      a) Class templates supported.
                   36862: *                              
                   36863: *      b) Member function templates supported.  
                   36864: *      Type-specific member functions as described at the 
                   36865: *      end of the "Outline of an implementation" section 
                   36866: *      are also supported. 
                   36867: *
                   36868: *      Non-member function templates are not supported.
                   36869: *                                              
                   36870: *      c) Template arguments may be of type "type" or 
                   36871: *      simple integral, real, double and pointer types 
                   36872: *      that are compile-time constants.
                   36873: *
                   36874: *      Default arguments are not suported.
                   36875: *
                   36876: * 
                   36877: * Restrictions:
                   36878: *      
                   36879: *      a) template definitions may not be nested.
                   36880: *                                              
                   36881: *      b) enums, or class definitions may not be 
                   36882: *      nested within a template class definition.
                   36883: *                                              
                   36884: * This file also supports an internal template facility 
                   36885: * to facilitate the implementation of ObjectStore data 
                   36886: * model features. The internal template facility is 
                   36887: * only used by compiler implementors, and is not user visible.
                   36888: *                                                      
                   36889: ************************************************************/
                   36890: 
                   36891: 
                   36892: /***********************************************************
                   36893: *      
                   36894: * TBD
                   36895: * 
                   36896: * 1) Error recovery, a never ending task, could stand improvement.
                   36897: * 
                   36898: * 2) The template copying process could probably be speeded up
                   36899: * substantially, by only placing "graph-like" nodes in the hash 
                   36900: * table. The current implementation plays it safe, and places 
                   36901: * all nodes in the hash table.
                   36902: *                      
                   36903: * 3) Clean up $name processing, it needs to be remodularized 
                   36904: * so that class templates and tree templates share the code.
                   36905: *                                                      
                   36906: * 4) Permit parametrized name default names within member 
                   36907: * functions. 
                   36908: *
                   36909: ****************************************************************/
                   36910: 
                   36911: #include "tree_copy.h"
                   36912: #include "cfront.h"
                   36913: #include <string.h>
                   36914: #include "tree_dump.h"
                   36915: #include "template.h"
                   36916: #include <stdlib.h>
                   36917: #include <ctype.h>
                   36918: #include "hash.h"
                   36919: 
                   36920: extern int bound ; // is not mentioned in the header file
                   36921: 
                   36922: const int max_string_size = 1024 ;
                   36923: 
                   36924: const int default_copy_hash_size = 1000 ;
                   36925: 
                   36926: // Save and restore global state around a template instantiation
                   36927: void state::save() {
                   36928:   
                   36929:   Cdcl = ::Cdcl ;
                   36930:   Cstmt = ::Cstmt ;
                   36931:   curloc   = ::curloc ;
                   36932: 
                   36933:   curr_file = ::curr_file ;
                   36934:   curr_expr = ::curr_expr ;
                   36935:   curr_icall = ::curr_icall ;
                   36936:   curr_loop = ::curr_loop;
                   36937:   curr_block = ::curr_block;
                   36938:   curr_switch = ::curr_switch;
                   36939: 
                   36940:   bound    =  ::bound  ;   
                   36941:   inline_restr = ::inline_restr ;
                   36942:   last_line = ::last_line ;
                   36943: 
                   36944:   no_of_badcall = ::no_of_badcall;
                   36945:   no_of_undcl = ::no_of_undcl ;
                   36946:   
                   36947:   badcall = ::badcall ;
                   36948:   undcl = ::undcl ;
                   36949: } ;
                   36950: 
                   36951: 
                   36952: void state::restore() {
                   36953:   ::Cdcl = Cdcl ;
                   36954:   ::Cstmt = Cstmt ;
                   36955:   ::curloc  = curloc ;
                   36956: 
                   36957:   ::curr_file = curr_file ;
                   36958:   ::curr_expr = curr_expr ;
                   36959:   ::curr_icall = curr_icall ;
                   36960:   ::curr_loop = curr_loop;
                   36961:   ::curr_block = curr_block;
                   36962:   ::curr_switch = curr_switch;
                   36963: 
                   36964:   ::bound    =  bound  ;   
                   36965:   ::inline_restr = inline_restr ;
                   36966:   ::last_line = last_line ;
                   36967: 
                   36968:   ::no_of_badcall = no_of_badcall;
                   36969:   ::no_of_undcl = no_of_undcl ;
                   36970:   
                   36971:   ::badcall = badcall ;
                   36972:   ::undcl = undcl ;
                   36973: } ;
                   36974: 
                   36975: 
                   36976: void state::init()  {
                   36977:   ::bound = 0 ;
                   36978:   ::inline_restr = 0 ;
                   36979:   ::no_of_badcall = ::no_of_undcl = 0 ;
                   36980:   ::undcl = ::badcall = NULL ;
                   36981:   // lastline  needs to be initialized probaly via a call to putline
                   36982:   
                   36983: }
                   36984: 
                   36985: 
                   36986: bit basetype::parametrized_class()
                   36987: { return ((base == COBJ) && 
                   36988:          Ptclass(Pbase(this)->b_name->tp)->class_base == uninstantiated_template_class) ;
                   36989: }
                   36990: 
                   36991: class_type_enum get_class_base (Pbase b) {
                   36992:   if (b->base != COBJ) error('i', "badA top ::get_class_type") ;
                   36993:   return Ptclass(Pbase(b)->b_name->tp)->class_base ;
                   36994: }
                   36995: 
                   36996: Ptclass get_template_class (Pbase b) {
                   36997:   class_type_enum t = get_class_base(b) ;
                   36998: 
                   36999:   if (! ((t == instantiated_template_class) ||
                   37000:         (t == uninstantiated_template_class)))
                   37001:     error ('i', "C is not aYC") ;
                   37002:   
                   37003:   return Ptclass(Pbase(b)->b_name->tp) ;
                   37004: }
                   37005: 
                   37006: 
                   37007: Ptempl_inst get_templ_inst(Pbase b) {
                   37008: 
                   37009:   return (get_template_class(b))->inst ;
                   37010: }
                   37011: 
                   37012:   
                   37013: bit classdef::parametrized_class()
                   37014: { return (class_base == uninstantiated_template_class) ;
                   37015: }
                   37016: 
                   37017: // Predicate to determine whether two classes are indeed the same. cfront
                   37018: // normally relies on pointer identity, however this test is insufficient when
                   37019: // parametrized class instantiationa are involved, since there are potentially
                   37020: // many instances of a COBJ and CLASS for a given instantiation.
                   37021: bit classdef::same_class(Pclass pc)
                   37022: {
                   37023:   if (this == pc) return true ;
                   37024: 
                   37025:   // An intermediate test to compensate for the fact that instantiations do
                   37026:   // not cause a copy of the syntax tree to be generated. This kludge should
                   37027:   // not be necessary once the template implementation is complete, and tree
                   37028:   // copying is implemented.
                   37029:   // Later, Sam: tree copying is now implemented, i need to remove the
                   37030:   // following two statements and rerun the test suite.
                   37031: 
                   37032:   if ((this->class_base == template_class) &&
                   37033:       (pc->class_base == instantiated_template_class) &&
                   37034:       (Ptclass(pc)->inst->def_basetype()->b_name->tp == this))
                   37035:     return true ;
                   37036:   // The inverse symmetric test
                   37037:   if ((pc->class_base == template_class) &&
                   37038:       (this->class_base == instantiated_template_class) &&
                   37039:       (Ptclass(this)->inst->def_basetype()->b_name->tp == pc))
                   37040:     return true ;
                   37041: 
                   37042:   // Check whether the templates were determined to be identical after
                   37043:   // instantiation. 
                   37044:   if ((pc->class_base == instantiated_template_class) &&
                   37045:       (this->class_base == instantiated_template_class) &&
                   37046:       (Ptclass(this)->inst->same(Ptclass(pc)->inst)))
                   37047:     return true ;
                   37048:   return false ;
                   37049: }
                   37050: 
                   37051: // determine whether two instantiations are identical; the test asumes that 
                   37052: // the templates have been instantiated.
                   37053: bool templ_inst::same(Ptempl_inst t)
                   37054: {
                   37055:   return ((forward && (forward == t->forward)) ||
                   37056:          (forward == t) || (t->forward == this)) ? true : false ;
                   37057: }
                   37058: 
                   37059: 
                   37060:                       /* Template parsing support */
                   37061: 
                   37062: // The canonical template compilation instance. 
                   37063: 
                   37064: templ_compilation *templp ;
                   37065: 
                   37066: templ_compilation::templ_compilation()
                   37067: { templates = new table(128, NULL, NULL) ;
                   37068:   any_type =  new basetype(ANY, NULL);
                   37069:   PERM(any_type) ;
                   37070: }
                   37071: 
                   37072: 
                   37073: // determine whether the string corresponds to a tree formal parameter
                   37074: Pname templ_compilation::tree_parameter(char *s) {
                   37075:   for (Plist formal = params ; formal ; formal = formal->l)
                   37076:     if (strcmp(formal->f->string, s) == 0) {
                   37077:       formal->f->n_used++ ;
                   37078:       return formal->f ;
                   37079:     }
                   37080:   return 0 ;
                   37081: }  
                   37082:   
                   37083:                                       
                   37084: // Determine whether the name refers to the canonical template class during
                   37085: // syntax analysis.
                   37086: Ptempl templ_compilation::is_template(Pname p) {
                   37087:   if (p->tp && (p->tp->base == COBJ) &&
                   37088:       (get_class_base(Pbase(p->tp)) == template_class))
                   37089:     { Pname n = templates->look(p->string, 0) ;
                   37090:       return (n ? Ptempl(n->tp) : 0) ;
                   37091:     }
                   37092:   return 0 ;
                   37093: }
                   37094: 
                   37095: 
                   37096: // determine whether the string names a template
                   37097: Ptempl templ_compilation::is_template(char *s) {
                   37098:   Pname n = templates->look(s,0) ;
                   37099:   return (n ? Ptempl(n->tp) : 0) ;
                   37100: }
                   37101: 
                   37102:   
                   37103: // Set up the environment for parsing a template. This involves setting up a
                   37104: // new nesting level into which the "type type" parameters of the template can
                   37105: // be entered, so that the lexer can find them as TNAMES. The scope is
                   37106: // deallocated by end().
                   37107: void templ_compilation::start() 
                   37108: { templp->in_progress = true ;
                   37109:   // Reinitialize the state.
                   37110:   params = param_end = NULL ; owner = NULL ;
                   37111:   modified_tn = 0 ;  // Initialize it here, since ::collect adds new types
                   37112: }
                   37113: 
                   37114: 
                   37115:   
                   37116: // Collect each parameter as it is parsed, and add it to the list of parms.
                   37117: // Validate each parameter to make sure that it is one of the acceptable
                   37118: // types. 
                   37119: void templ_compilation::collect(TOK parm_type, Pname n)
                   37120: {
                   37121:   switch (parm_type) {
                   37122:   case CLASS:
                   37123:     // A "type type" parameter, give it the "ANY" type normally used as a
                   37124:     // wildcard match internally by the compiler in cases of error.
                   37125:     n->tp =  new basetype(ANY, 0);
                   37126:     n =  n->tdef() ;           // Set it up to be a typedef.
                   37127:     n->lex_level = bl_level + 1 ; // Inner scope, so restore() can hack it
                   37128:     n->n_template_arg = template_type_formal ;
                   37129:     PERM(n) ; PERM(n->tp) ;
                   37130:     break ;
                   37131:   case STATEMENT:
                   37132:   case EXPRESSION:
                   37133:     // the argument is a post-syntax expression tree
                   37134:     n->n_template_arg =
                   37135:       ((parm_type == EXPRESSION) ? 
                   37136:        template_expr_tree_formal : template_stmt_tree_formal) ;
                   37137:     // canonical any_type is ok here
                   37138:     n->tp = any_type ;
                   37139:     PERM(n) ;
                   37140:     break ;
                   37141:   default:
                   37142:     error("theZT for%n must be CLASS, not %k", n,parm_type);
                   37143:   }
                   37144:   append_parameter(n) ;
                   37145: }
                   37146: 
                   37147: // append the "non-type" parameter to the end of the list
                   37148: void templ_compilation::append_parameter(Pname n)
                   37149: {
                   37150:   if (params){
                   37151:     param_end->l = new name_list(n, NULL) ;
                   37152:     param_end = param_end->l ;
                   37153:   }else params = param_end = new name_list(n, NULL) ;
                   37154:   PERM(n) ; PERM(n->tp) ;
                   37155: }
                   37156: 
                   37157: 
                   37158: // collect non "type type" parameters. The tp field of the name
                   37159: // indicates the type of the formal parameter. 
                   37160: void templ_compilation::collect(Pname n) 
                   37161: {
                   37162:   // The grammar alone should be sufficient to protect against undesirable
                   37163:   // types. Any additional checks go here.
                   37164:   n->n_template_arg = template_expr_formal ;
                   37165:   append_parameter(n) ;
                   37166: }
                   37167:   
                   37168: 
                   37169: 
                   37170: // validate the type for a non-type formal, and make it a const.
                   37171: static void check_non_type_formal(Pname n) {
                   37172: 
                   37173:   switch (n->tp->base) {
                   37174:   case ZTYPE:
                   37175:   case CHAR:
                   37176:   case SHORT:
                   37177:   case INT:
                   37178:   case LONG:
                   37179:   case FLOAT:
                   37180:   case DOUBLE:
                   37181:   case FIELD:
                   37182:   case EOBJ:
                   37183:   case COBJ:
                   37184:   case TYPE:
                   37185:   case ANY:
                   37186:     { // a basetype node
                   37187:       TOK bad_base = 0 ;
                   37188:       
                   37189:       if (Pbase(n->tp)->b_volatile)
                   37190:        bad_base = VOLATILE ;
                   37191:       if (Pbase(n->tp)->b_typedef)
                   37192:        bad_base = TYPEDEF ;
                   37193:       if (Pbase(n->tp)->b_inline)
                   37194:        bad_base = INLINE ;
                   37195:       if (Pbase(n->tp)->b_virtual)
                   37196:        bad_base = VIRTUAL ;
                   37197:       if (bad_base)
                   37198:        error ("bad %k declarator forY formal %n", bad_base,n);
                   37199:       
                   37200:       Pbase b = new basetype(0, 0) ;
                   37201:       *b= *Pbase(n->tp) ;
                   37202:       b->b_const = 1 ;
                   37203:       n->tp = b ;
                   37204:       break  ;
                   37205:     }
                   37206:   case PTR:
                   37207:     { Pptr b = new ptr(0,0) ;
                   37208:       *b = *Pptr(n->tp) ;
                   37209:       
                   37210:       b->rdo = 1;
                   37211:       n->tp = b ;
                   37212:       break ;
                   37213:     }
                   37214:   case RPTR:
                   37215:   case VEC:
                   37216:     break;             // constant by definition
                   37217:   default:
                   37218:     error ("badZT %t for formalZ %n", n->tp, n);
                   37219:   }
                   37220:   return ;
                   37221: }
                   37222:                
                   37223: 
                   37224: 
                   37225: // The template parameters if any, have been parsed. Member function templates
                   37226: // may choose to default their template arguments to the class arguments, if
                   37227: // so, make the defaulting happen.
                   37228: void templ_compilation::enter_parameters()
                   37229: {
                   37230:   for (Plist list = params ; list ; list = list->l) {
                   37231:     Pname n = list->f ;
                   37232:     switch(n->n_template_arg) {
                   37233:     case template_type_formal:
                   37234:       // Set them up for restoration
                   37235:       modified_tn = new name_list(n,modified_tn);
                   37236:       // Bring the names out of hiding
                   37237:       n->n_key = 0 ;
                   37238:       break ;
                   37239:     case template_expr_formal:
                   37240:       check_non_type_formal(n) ;
                   37241:       n->tp->dcl(gtbl) ;
                   37242:       break ;
                   37243:     case template_expr_tree_formal:
                   37244:     case template_stmt_tree_formal:
                   37245:       // simply note it, the guts of the processing takes place when the
                   37246:       // copy of the syntax tree is generated.
                   37247:       break ;
                   37248:     default:
                   37249:       error ('i', "badY formal" ) ;
                   37250:     }
                   37251:   }
                   37252:   // Save away the list of modified_tn, since the body processing will clobber
                   37253:   // it.
                   37254:   param_tn = modified_tn ;
                   37255:   modified_tn = 0 ;
                   37256: }
                   37257: 
                   37258: 
                   37259: 
                   37260: // Resolve the forward declaration of a template to its true definition. The
                   37261: // template and class type data structures must be reused, since there may be
                   37262: // outstanding references to them.
                   37263: void templ::resolve_forward_decl(Plist params, Pclass c) {
                   37264:   check_formals(params) ; 
                   37265:   formals = params ;
                   37266:   defined = true ;
                   37267:   definition_number = ++ definition_tick ;
                   37268:   members = c->mem_list ;
                   37269: }
                   37270: 
                   37271: void templ::instantiate_forward_decl() {
                   37272:   for (Ptempl_inst i = insts ; i ; i = i->next)
                   37273:     if (Ptclass(Pbase(i->tname->tp)->b_name->tp)->class_base ==
                   37274:        instantiated_template_class &&
                   37275:        ! i->forward)
                   37276:       { // reinstantiate it
                   37277:        i->instantiate(true) ;
                   37278:       }
                   37279: }
                   37280: 
                   37281:   
                   37282: 
                   37283: // verify thet the qualifier used to declare the member function matches the
                   37284: // template arguments in name, ie.
                   37285: // template <class P, class Q, ..> c<P,Q,..>::member_function() {}
                   37286: // match it's Ps and Qs.
                   37287: bool templ_inst::check_qualifier(Plist formals)
                   37288: {
                   37289:   Pexpr actual = actuals ;
                   37290:   for (Plist formal = formals ; formal && actual ; formal = formal->l,
                   37291:        actual = actual->e2)
                   37292:     
                   37293:     switch (formal->f->n_template_arg) {
                   37294:       
                   37295:     case template_type_formal:
                   37296:       { Pbase b = Pbase(actual->e1->tp) ;
                   37297:        
                   37298:        if (! ((b->base == TYPE) &&
                   37299:               (b->b_name->base == TNAME) &&
                   37300:               (strcmp (Pname(b->b_name)->string, formal->f->string) == 0)))
                   37301:          return false ;
                   37302:        break ;
                   37303:       }
                   37304:       
                   37305:     case template_expr_formal:
                   37306:       if (! ((actual->e1->base == NAME) &&
                   37307:             (strcmp(Pname(actual->e1)->string, formal->f->string) == 0)))
                   37308:        return false ;
                   37309:       break ;
                   37310:       
                   37311:     case template_expr_tree_formal:
                   37312:     case template_stmt_tree_formal:
                   37313:     default:
                   37314:       error ('i',"badY formal") ;
                   37315:     }
                   37316: 
                   37317:   return true ;
                   37318: }
                   37319: 
                   37320: 
                   37321: // make the class template visible when compiling the template class
                   37322: // defintion, so that it can be refernced while compiling the class body.
                   37323: void templ_compilation::introduce_class_templ(Pname namep)
                   37324: {
                   37325:   owner = is_template(namep) ;
                   37326:   // create a template definition if one did not already exist, due to a
                   37327:   // forward declaration
                   37328:   if (!owner){
                   37329:     owner = new templ(params, namep) ;
                   37330:     Pname lookup_name = templp->templates->insert(new name(namep->string), 0);
                   37331:     lookup_name->tp = Ptype(owner) ;  // lie, to permit use of the table
                   37332:   }
                   37333: }
                   37334:                            
                   37335:                            
                   37336: // The body of the template has been parsed. Finish the definition of the
                   37337: // template class. 
                   37338: void templ_compilation::end(Pname p) 
                   37339: {
                   37340:   bool forward_definition = false ;
                   37341:   // Restore the name environment to the state before the template parameters
                   37342:   // were processed.
                   37343:   modified_tn = param_tn ;
                   37344:   restore() ;
                   37345:   modified_tn = 0 ;
                   37346: 
                   37347:   if (curr_tree_template) {
                   37348:     // create an expression template
                   37349:     new tree_template(curr_tree_template,
                   37350:                      p->string, params, p->n_initializer, templ_refs) ;
                   37351:   }else {
                   37352:     if (!p->tp) {
                   37353:       error ("aC, orMF definition wasX") ;
                   37354:       return ;
                   37355:     }
                   37356:     switch(p->tp->base){
                   37357:       
                   37358:     case CLASS:
                   37359:       // Create the template type to represent the parsed template, and enter it
                   37360:       // into the global table. This is achieved simply by modifying the TNAME
                   37361:       // that was entered into ktbl to represent the class definition.
                   37362:       Pname namep = ktbl->look(p->string, 0) ;
                   37363: 
                   37364:       // check for nested definitions, they aren't supported currently. 2.1 is
                   37365:       // a good time to start supporting them, since they are nested for real.
                   37366:       for (Pname nn = Pclass(p->tp)->mem_list ; nn ; nn = nn->n_list)
                   37367:        switch (nn->base) {
                   37368:        case NAME:
                   37369:          switch(nn->tp->base) {
                   37370:          case CLASS:
                   37371:            error("CD %s not permitted within a ZizedC", nn->string) ;
                   37372:              break ;
                   37373:            case ENUM:
                   37374:              error("enumD %s not permitted within a ZizedC", nn->string) ;
                   37375:              break ;
                   37376:          }
                   37377:          break ;
                   37378:          
                   37379:        case TNAME:
                   37380:          error("typedef %s not permitted within a ZizedC", nn->string) ;
                   37381:          break ;
                   37382:        }
                   37383: 
                   37384:       owner = is_template(namep);
                   37385:       if (owner) {
                   37386:        Pclass c = Pclass(owner->basetype()->b_name->tp) ;
                   37387:        // ignore it, if it is a forward declaration following a real
                   37388:        // definition
                   37389:        if (owner->defined && (Pclass(p->tp)->mem_list != owner->members))
                   37390:          error("YC %s multiply defined", p->string) ;
                   37391: 
                   37392:        forward_definition=bool((c->defined & DEF_SEEN) && (!owner->defined));
                   37393:        if (forward_definition) owner->resolve_forward_decl(params, c) ;
                   37394:       }else 
                   37395:        // a forward declaration
                   37396:        introduce_class_templ(namep) ;
                   37397: 
                   37398:       if (templ_refs) owner->templ_refs = templ_refs ;
                   37399:       break ;
                   37400:     
                   37401:     case FCT:
                   37402:       { Pname qual = p->n_qualifier ;
                   37403:        // the function must belong to a declared template class
                   37404:        if (! qual) {
                   37405:          error('s', "onlyYMFs may beZized currently") ;
                   37406:          return ;
                   37407:        }
                   37408:        if (qual->tp && (qual->tp->base == COBJ))
                   37409:          switch (get_class_base(Pbase(qual->tp))) {
                   37410:          case uninstantiated_template_class:
                   37411:            owner = Ptclass(Pbase(qual->tp)->b_name->tp)->inst->def ;
                   37412:            // verify that the formals specified, match the template formals
                   37413:            // in name, note that the length was already matched when the
                   37414:            // instantiation was generated.
                   37415:            if (!get_template_class
                   37416:                (Pbase(qual->tp))->inst->check_qualifier(params))
                   37417:              error ("QrZs must match theY formals") ;
                   37418:            break ;
                   37419:          case template_class:
                   37420:            // the template reference was without any of the formals
                   37421:            owner = is_template(qual) ;
                   37422:            if (! owner->has_tree_expr_formals())
                   37423:              error('w',"Qr %n for %n must specifyYZs", qual, p) ;
                   37424:            break ;
                   37425:          default:
                   37426:            error ("Qr %n for %n wasn't aYC", qual, p) ;
                   37427:            return ;
                   37428:          }
                   37429:        Pfunt ft= owner->collect_function_member(p) ;
                   37430:        if (! Pfct(p->tp)->body)
                   37431:          error ("theYFM %n must have a body", p) ;
                   37432:        ft->templ_refs = templ_refs ;
                   37433:        ft->formals = params ;
                   37434:        owner->check_formals(params) ;
                   37435:        break ;
                   37436:       }
                   37437:     default: error ("C, or MF definitionX.") ;
                   37438:     }
                   37439:   }
                   37440:   // Note the template references from this definition
                   37441: 
                   37442:   clear_ref_templ() ;
                   37443:   param_end = params = 0;  // Indicates the end of template processing.
                   37444:   curr_tree_template = 0 ;
                   37445: 
                   37446:   if (forward_definition) owner->instantiate_forward_decl() ;
                   37447:   owner = 0 ;
                   37448: }
                   37449: 
                   37450: 
                   37451:                                     
                   37452: 
                   37453: // Clear the list of templates referenced during the syntax analysis of a top
                   37454: // level definition. Note that since this list is produced during syntax
                   37455: // analysis, it does not recognize instantiations that may actualy turn out to
                   37456: // be identical at instantiation after the substitution of actual parameters.
                   37457: // Thus, the list may be longer than it would be after actual argument
                   37458: // substitution. 
                   37459: void templ_compilation::clear_ref_templ() {
                   37460:   for (Pcons p = templ_refs ; p ; p = p->cdr)
                   37461:     Ptempl_inst(p->car)->refp = false ;
                   37462:   templ_refs = 0 ; last_cons = 0 ;
                   37463: }
                   37464: 
                   37465: 
                   37466: // Instantiate templates that were referenced by a non-template definition,
                   37467: // after syntax analysis has been completed on it.
                   37468: void templ_compilation::instantiate_ref_templ() {
                   37469:   for (Pcons p = templ_refs ; p ; p = p->cdr)
                   37470:     Ptempl_inst(p->car)->instantiate() ;
                   37471:   clear_ref_templ() ;
                   37472: }
                   37473: 
                   37474: 
                   37475: 
                   37476: 
                   37477: // Compile all template member body instantiations. Set in motion the
                   37478: // compilation of the graph of instantiation bodies. Note that compilation of
                   37479: // a body may in turn initiate the instantiation of templates that had not
                   37480: // previously been instantiated.
                   37481: void templ_compilation::end_of_compilation() {
                   37482:   bool change = false ;
                   37483:   do {
                   37484:     change = false ;
                   37485:     for (Ptempl p = list ; p ; p = p->next)
                   37486:       change = ( change | p->instantiate_bodies() ? true : false);
                   37487:   } while (change) ;
                   37488: }
                   37489: 
                   37490: 
                   37491: // A predicate to validate that a tname without template parameters is legit
                   37492: // in the scope, ie. that it does not need actual template arguments.
                   37493: // Currently, a tname without parameters is ok within the class definition,
                   37494: // but parameters are required within the member definition. They should not
                   37495: // be required within the member function either to be consonance with their
                   37496: // use in the class definition.
                   37497: Pname templ_compilation::check_tname(Pname p) {
                   37498:   Ptempl t = is_template(p) ;
                   37499: 
                   37500:   if (p->n_template_arg) p->n_used++ ;
                   37501:   if (!t) return p ;
                   37502:   if (in_progress && ((owner && (owner->namep == p)) ||
                   37503:                      (!owner && t->basetype()->b_name->tp == ccl)))
                   37504:      return p ;
                   37505:   error ("%n needs Y instantiationAs.", p) ;
                   37506:   return p ;
                   37507: }
                   37508: 
                   37509: 
                   37510: // This function determine when the parameters specified to a template are
                   37511: // redundant, and really refer to the current template class. Thus,
                   37512: //
                   37513: // template c<class p1, class p2> c<p1,p2>::foo { ... } ;
                   37514: // has the redundant template specification c<p1, p2> and can simply be a
                   37515: // reference to a "c" instead, 
                   37516: bool templ_compilation::current_template(Pname p, Pexpr actuals) {
                   37517:   if (in_progress &&
                   37518:       ((owner  && (owner->namep == p)) ||
                   37519:        (!owner && ((p->tp->base == COBJ) &&
                   37520:                   (Pbase(p->tp)->b_name->tp == ccl)))))
                   37521:     { // Check whether the formal and actual types are identical
                   37522:       Pexpr actual = actuals;
                   37523:       for (Plist formal = params ; formal && actual ; formal = formal->l,
                   37524:           actual = actual->e2)
                   37525:        if ((formal->f->tp == actual->e1->tp) || 
                   37526:            ((actual->e1->tp && (actual->e1->tp->base == TYPE)) &&
                   37527:             (Pbase(actual->e1->tp)->b_name->tp == formal->f->tp)))
                   37528:          continue ;
                   37529:        else break ;
                   37530:       if (!formal && !actual) return true ;
                   37531:     }
                   37532:   return false ;
                   37533: }
                   37534:   
                   37535:   
                   37536:        
                   37537: // Add a new member function to the list of functions for the template class.
                   37538: Pfunt templ::collect_function_member(Pname fname) {
                   37539:   PERM(fname) ; PERM(fname->tp) ; PERM(Pfct(fname->tp)->body) ;
                   37540:   return new function_template (*this, templp->params, fname) ;
                   37541: }
                   37542: 
                   37543: 
                   37544: // Check the formals specified for a member function or a forward definition
                   37545: // of a class, against the formals for the class.
                   37546: void basic_template::check_formals(Plist f2) {
                   37547:   
                   37548:   for (Plist f1 = formals; f1 && f2 ; f1 = f1->l, f2 = f2->l)
                   37549:     if (f1->f->base != f2->f->base) 
                   37550:       switch (f1->f->n_template_arg) {
                   37551:       case template_type_formal:
                   37552:        error ("Y formalZ mismatch,\
                   37553: %n must be a type formal parameter.", f2->f) ;
                   37554:        break ;
                   37555:       case template_expr_formal:
                   37556:        error ("formalZ mismatch, %n must be aZ ofT %t",
                   37557:               f2->f, f2->f->tp) ;
                   37558:        break ;
                   37559:       case template_expr_tree_formal:  
                   37560:       case template_stmt_tree_formal:
                   37561:        error ("formalZ mismatch, %n must be anE formalZ",
                   37562:               f2->f) ;
                   37563:        break ;
                   37564:       default:
                   37565:        error ("formalZ mismatch betweenC formal: %n andM formal: %n", f1->f, f2->f) ;
                   37566:       }else if (f1->f->n_template_arg == template_expr_formal) {
                   37567:        // the types should be identical
                   37568:        if (f1->f->tp->check(f2->f->tp, 0) == 1)
                   37569:          error ("type mismatch betweenM formal %n, andC formal %n", f2->f, f1->f) ;
                   37570:       }
                   37571:   if (f1)
                   37572:     error ("insufficient formalZs,CZ parameter %n onwards are missing", f1->f) ;
                   37573:   if (f2)
                   37574:     error ("excess formalZs,Z %n onwards not defined forC", f2->f) ;
                   37575:   
                   37576: }
                   37577: 
                   37578: // predicate to determine whether the template has expression tree formals
                   37579: bool templ::has_tree_expr_formals() {
                   37580:   
                   37581:   for (Plist formal= formals; formal ; formal = formal->l)
                   37582:     if (formal->f->n_template_arg == template_expr_tree_formal)
                   37583:       return true ;
                   37584: 
                   37585:   return false ;
                   37586: }
                   37587: 
                   37588: 
                   37589: // Check that those formals that require class actual arguments, due to their
                   37590: // use in member function bodies get them.
                   37591: bool basic_template::check_constraints(Pexpr actual)
                   37592: 
                   37593: {
                   37594:   bool ret = true ;
                   37595:   
                   37596:   for (Plist formal = formals ; formal && actual ; formal = formal->l,
                   37597:        actual = actual->e2)
                   37598:     if ((formal->f->n_template_arg == template_type_formal) &&
                   37599:        formal->f->n_template_formal_must_be_class) {
                   37600: 
                   37601:          Pname n = Pname(actual->e1) ;
                   37602: 
                   37603:          if (n && n->tp && n->tp->is_cl_obj())
                   37604:            continue ;
                   37605:          error("expected aCT actual, not %t, for the \"TT\" formal %s",
                   37606:                n->tp, formal->f->string);
                   37607:          ret = false ;
                   37608:        }
                   37609:   return ret ;
                   37610: }
                   37611: 
                   37612: 
                   37613: // Check actual template arguments, against the formals.
                   37614: bool templ::check_actual_args(Pexpr actual)
                   37615: {
                   37616:   for (Plist formal = formals ; formal && actual ; formal = formal->l,
                   37617:        actual = actual->e2)
                   37618:     switch (formal->f->n_template_arg) {
                   37619:     case template_type_formal:
                   37620:       {
                   37621:        // A "type type" parameter, any actual type that was accepted by the
                   37622:        // parse is acceptable here, just make sure that it is indeed a type.
                   37623:        // If it was parsed as a type, the grammar should have created a name
                   37624:        // node, and attached the type to it, having marked the name as a
                   37625:        // template_actual_arg_dummy.
                   37626: 
                   37627:        Pname n = Pname(actual->e1) ;
                   37628:        
                   37629:        if (!((n->base == NAME) &&
                   37630:            (n->n_template_arg == template_actual_arg_dummy))) {
                   37631:          error ("Y %s A mismatch, the Y formal:%n\
                   37632:  required aT actualZ.", namep->string, formal->f) ;
                   37633:          // recover from the error with a safe expression
                   37634:          n = new name("") ;
                   37635:          n->tp = any_type ;
                   37636:          actual->e1 = n ;
                   37637:        }
                   37638:        if ((formal->f->n_template_formal_must_be_class) &&
                   37639:            !(n->tp && n->tp->is_cl_obj()))
                   37640:          error("expected aCT actual, not %t, for the \"TT\" formal %s",
                   37641:                n->tp, formal->f->string) ;
                   37642:        break ;
                   37643:       }
                   37644:     case template_expr_formal:
                   37645:       // checking can only be done at instantiation, so postpone it 
                   37646:       break ;
                   37647:     case template_expr_tree_formal:
                   37648:     case template_stmt_tree_formal:
                   37649:       // anything is acceptable, it is a case of "implementor beware". Any
                   37650:       // illegalities will only be detected when dcl processing takes place.
                   37651:       break ;
                   37652:     default:
                   37653:       error ('i',"badY formal") ;
                   37654:     }
                   37655:   // If we provide for optionals, this is where the processing should get done.
                   37656:   if (formal)
                   37657:     error ("too fewAs supplied forY %s", namep->string) ;
                   37658:   if (actual && actual->e1) {
                   37659:     error ("too manyAs supplied forY %s", namep->string) ;
                   37660:   }
                   37661:   return bool(~(formal || actual)) ;
                   37662: }
                   37663: 
                   37664: 
                   37665: 
                   37666: 
                   37667: // Append to the list of references.
                   37668: void templ_compilation::append_ref(Ptempl_inst ref) 
                   37669: { cons *p = new cons(ref,0) ;
                   37670:   if (last_cons)
                   37671:     last_cons->cdr = p ;
                   37672:   else templ_refs =  p ;
                   37673:   last_cons = p ;
                   37674: } ;
                   37675: 
                   37676: 
                   37677: // Note the reference by a definition to the template, so that the template
                   37678: // can be instantiated before the definition is processed. 
                   37679: Ptempl_inst templ_inst::note_ref() 
                   37680: {  if ((! refp)) {
                   37681:     refp = true ;
                   37682:     templp->append_ref(this) ;
                   37683:   }
                   37684:   return this ;
                   37685: }
                   37686:   
                   37687:            
                   37688:            
                   37689: // Get an instantiation for the template with the given set of actuals. If one
                   37690: // exists, return it, otherwise create a new one. 
                   37691: Ptempl_inst templ::get_inst(Pexpr actuals, Ptempl_inst exclude)
                   37692: { Ptempl_inst inst = get_match(actuals, exclude, false) ;
                   37693:   
                   37694:   return (inst ? inst : new templ_inst(actuals, this))->note_ref() ;
                   37695: }
                   37696: 
                   37697: 
                   37698: // Find an instantiation that has the same set of actuals, exclude the
                   37699: // instantaition passed in from the set of candidates
                   37700: Ptempl_inst templ::get_match(Pexpr actuals,       
                   37701:                             Ptempl_inst exclude,  // don't match this one
                   37702:                             // Only instantiated templates match
                   37703:                             bool match_instantiated_only)    
                   37704: {  
                   37705:   for (Ptempl_inst p = insts ; p ; p = p->next)
                   37706:     if ((p != exclude) &&
                   37707:        (p->actuals_match(actuals)) &&
                   37708:        (match_instantiated_only ?
                   37709:         (Pclass(Pbase(p->tname->tp)->b_name->tp)->class_base ==
                   37710:          instantiated_template_class)
                   37711:         : true))
                   37712:       return (p->forward ? p->forward : p) ;
                   37713:   return NULL ;
                   37714: }
                   37715: 
                   37716: 
                   37717: // provides the basetype created for a given set of actuals.
                   37718: Pbase templ::inst_basetype(Pexpr actuals)
                   37719: {
                   37720:   return (check_actual_args(actuals) ?
                   37721:          Pbase(get_inst(actuals)->tname->tp) : basep) ;
                   37722: }
                   37723: 
                   37724: 
                   37725: // Validate that the name denotes a parametrized type, and prodouce a TNAME
                   37726: // for the instantiation.
                   37727: Pname parametrized_typename (Pname p, Pexpr actuals) 
                   37728: { 
                   37729:   Ptempl t = templp->is_template(p) ;
                   37730:   // A template instantiation with redundant actuals identical to the formals
                   37731:   // of the current template
                   37732:   if (templp->current_template(p, actuals)) return p ;
                   37733:   if (t) {
                   37734:     Pname tname = t->typename(actuals)  ;
                   37735:     return (tname ? tname : p) ;
                   37736:   }
                   37737:   error ("%n hasTAs but is not aZizedC", p) ;
                   37738:   return p ;
                   37739: }
                   37740: 
                   37741: 
                   37742: Pbase parametrized_basetype (Pname p, Pexpr actuals) 
                   37743: { Ptempl t = templp->is_template(p) ;
                   37744:   // A template instantiation with redundant actuals identical to the formals
                   37745:   // of the current template 
                   37746:   if (templp->current_template(p, actuals)) return Pbase(p->tp) ;
                   37747:   if (t) return t->inst_basetype(actuals) ;
                   37748:   error ("%n is not aZizedC", p) ;
                   37749:   return new basetype(TYPE, p);
                   37750: }
                   37751: 
                   37752: 
                   37753: // Similar primitive for obtaining the typename associated with an
                   37754: // instantiation. 
                   37755: Pname templ::typename(Pexpr actuals) 
                   37756: {
                   37757:   return (check_actual_args(actuals) ? get_inst(actuals)->tname : 0) ;
                   37758: }
                   37759: 
                   37760: // predicate to get past all the type nodes
                   37761: static Ptype real_type (Ptype t)
                   37762: {
                   37763:   while (t->base == TYPE) t = Pbase(t)->b_name->tp ;
                   37764:   return t ;
                   37765: }
                   37766: 
                   37767: static int expr_match(Pexpr a1, Pexpr a2) ;
                   37768: 
                   37769: // Check whether the actuals provided match the actuals for this instantiation.
                   37770: // The actuals match the formals, iff they are the same type or parametrized
                   37771: // type. 
                   37772: bool templ_inst::actuals_match(Pexpr check_actuals)
                   37773: { Pexpr ae1, ae2 ;     // the cons cells
                   37774:   Plist formal = def->formals ;
                   37775:   
                   37776:   // The lists should be the same length, since check_actuals will have taken
                   37777:   // appropriate action.
                   37778:   for (ae1=actuals, ae2=check_actuals ; formal && ae1 && ae2 ;
                   37779:        ae1=ae1->e2, ae2=ae2->e2, formal = formal->l)
                   37780: 
                   37781:     switch (formal->f->n_template_arg) {
                   37782:     
                   37783:     case template_type_formal:
                   37784:       { Ptype t1 = ae1->e1->tp, t2 = ae2->e1->tp ;
                   37785:        if (t1->check(t2,255) == 1)
                   37786:          return false ;
                   37787:        break ;
                   37788:       }
                   37789:     case template_expr_formal:
                   37790:       if (! expr_match(ae1->e1, ae2->e1)) return false ;
                   37791:       break ;
                   37792:       
                   37793:     case template_expr_tree_formal:
                   37794:     case template_stmt_tree_formal:
                   37795:       // these are internal instantiations and consequently never match
                   37796:       return false ;
                   37797:       
                   37798:     default:
                   37799:       error ('i', "bad template formal") ;
                   37800:     }
                   37801:   return true ;
                   37802: }
                   37803: 
                   37804: 
                   37805: extern char emode ;
                   37806: 
                   37807: 
                   37808: // This set of overloaded fuctions are used to accumulate name strings 
                   37809: void stradd(char *&target, char *source) {
                   37810:   while (*target++ = *source++) ;
                   37811:   target-- ;
                   37812: }
                   37813:        
                   37814: void stradd(char *&p, long i) {
                   37815:   if (!emode) {
                   37816:     *p++ = 'L' ;
                   37817:   }
                   37818:   char s[16] ;
                   37819:   
                   37820:   sprintf(s,"%ld", i) ;
                   37821:   stradd(p,s) ;
                   37822: }
                   37823: 
                   37824: void stradd(char *&p, Pname n) {
                   37825:   if (!emode){
                   37826:     char s[256] ;
                   37827:     
                   37828:     sprintf(s,"%d", strlen(n->string)) ;
                   37829:     stradd(p,s) ;
                   37830:   }
                   37831:   stradd(p, n->string) ;
                   37832: }
                   37833: 
                   37834:     
                   37835: 
                   37836: // produce a unique string suitable for use within a name; if in emode ie.
                   37837: // printing in the context of an error, print a pretty name instead.  
                   37838: char * mangled_expr(char *p, Pexpr e, bool mangle_for_address = false)
                   37839: {
                   37840:   static int mangle_address = 0 ;
                   37841:   if (e == 0) return p;
                   37842: 
                   37843:   switch (e->base) {
                   37844:   case ADDROF:
                   37845:   case G_ADDROF:
                   37846:     // unary using e2
                   37847:     // rely on the
                   37848:     mangle_address++ ;
                   37849:     p = mangled_expr(p, e->e2) ;
                   37850:     mangle_address -- ;
                   37851:     break ;
                   37852:     
                   37853:   case NAME:
                   37854:     if (mangle_address || mangle_for_address)
                   37855:       stradd(p, Pname(e)) ;
                   37856:     else if (Pname(e)->n_evaluated)
                   37857:       stradd(p, Pname(e)->n_val) ;
                   37858:     else if (Pname(e)->n_initializer)
                   37859:       p = mangled_expr(p, Pname(e)->n_initializer, mangle_for_address) ;
                   37860:     else error ('i', "couldn't mangle %n", e) ;
                   37861:     break ;
                   37862:       
                   37863:   case IVAL:
                   37864:     stradd(p, ((ival *)e)->i1) ;
                   37865:     break ;
                   37866: 
                   37867:   case CAST:
                   37868:     { // an IVAL hiding below the cast ?
                   37869:       if (e->e1->base == IVAL) 
                   37870:        stradd(p, ((ival *)e->e1)->i1) ;
                   37871:       else error ('i', "unexpected cast") ;
                   37872:       break ;
                   37873:     }
                   37874:   case ICON:
                   37875:   case CCON:
                   37876:   case FCON:
                   37877:     *p++ = 'L' ;
                   37878:     strcpy(p, e->string) ;
                   37879:     // Sam: there needs to be a better encoding scheme, but it can wait.
                   37880:     if (!emode)
                   37881:       while (*p)
                   37882:       if (! (isalnum(*p)))
                   37883:        switch(*p) {
                   37884:        case '+':
                   37885:          *p++ = 'p' ;
                   37886:          break ;
                   37887:          
                   37888:        case '-':
                   37889:          *p++ = 'm' ;
                   37890:          break ;
                   37891: 
                   37892:        case '.':
                   37893:          *p++ = 'D' ;
                   37894:          break ;
                   37895: 
                   37896:        case 'e':
                   37897:          *p++ = 'E' ;
                   37898:          break ;
                   37899:        
                   37900:        default:
                   37901:          error ('i', "bad character in constant") ;
                   37902:          break ;
                   37903:        } else p++ ;
                   37904:     break ;
                   37905:     
                   37906:   case ZERO:
                   37907:     *p++ = '0' ;
                   37908:     break ;
                   37909:     
                   37910:   default:
                   37911:     error ('i', "can't mangle %k", e->base) ;
                   37912:   }
                   37913:   return p ;
                   37914: }
                   37915: 
                   37916: // this function is invoked once at the top level
                   37917: char *mangled_expr(char *p, Pname n) {
                   37918:   if (n->n_evaluated) {
                   37919:     stradd(p, n->n_val) ;
                   37920:     return p ;
                   37921:   }
                   37922:   return mangled_expr(p, n->n_initializer,
                   37923:                      (real_type(n->tp)->base == PTR ? true : false)) ;
                   37924: }
                   37925: 
                   37926: // Generate a template instantiation name suitable for printing when it is
                   37927: // presented to the user.
                   37928: void templ_inst::print_pretty_name() 
                   37929: {
                   37930:   extern char emode ;
                   37931:   
                   37932:   fprintf(out_file, " %s<", (def->namep ? def->namep->string : "?")) ;
                   37933:   Plist formal = inst_formals ;
                   37934:   emode ++ ;  // so that dcl_print generates c++ rather than c names
                   37935:   
                   37936:   for (Pexpr ae1=actuals; formal && ae1  ; ae1=ae1->e2, formal = formal->l) {
                   37937:     switch (formal->f->n_template_arg) {
                   37938:     case template_type_formal:
                   37939:       ae1->e1->tp->dcl_print(0) ;
                   37940:       break ;
                   37941:     case template_expr_formal:
                   37942:       { char buff[256] ;
                   37943:        
                   37944:        mangled_expr(buff, ae1->e1) ;
                   37945:        fprintf(out_file, "%s", buff) ;
                   37946:        break ;
                   37947:       }
                   37948:     case template_expr_tree_formal:
                   37949:     case template_stmt_tree_formal:
                   37950:       // doesn't participate in the name generation
                   37951:       break ;
                   37952:     default:
                   37953:       error ('i', "unexpected formal") ;
                   37954:     }
                   37955: 
                   37956:     // this comma is unfortunately misplaced, since it follows a space printed
                   37957:     // out by dcl_print
                   37958:     if (formal->l) fprintf(out_file, ", ") ;
                   37959:   }
                   37960:   fprintf(out_file, ">") ;
                   37961:   emode -- ;
                   37962: }
                   37963: 
                   37964:        
                   37965: 
                   37966: // there are different representations for ICON based upon whether it has been
                   37967: // evaluated. 
                   37968: int check_for_const(Pexpr a1, Pexpr a2) {
                   37969:   Neval = 0 ;
                   37970:   if ((a1->base == NAME) &&
                   37971:       ((a2->base == ICON) || (a2->base == IVAL) || (a2->base == ZERO)))
                   37972:     { Pname n = Pname(a1) ;
                   37973:       return (n->n_evaluated && (n->n_val == a2->eval())) ;
                   37974:     }else if (((a1->base == ICON) || (a1->base == IVAL) || (a1->base == ZERO))
                   37975:              && (a2->base == NAME))
                   37976:       { Pname n = Pname(a2) ;
                   37977:        return (n->n_evaluated && (n->n_val == a1->eval())) ;
                   37978:       }
                   37979:   return false ;
                   37980: }
                   37981:   
                   37982: 
                   37983: // get past the template parameter names to get the the real expression
                   37984: static Pexpr real_expression(Pexpr e) 
                   37985: {
                   37986:   while (e && (e->base == NAME) &&
                   37987:         (Pname(e)->n_template_arg == template_expr_formal) &&
                   37988:         (! Pname(e)->n_evaluated) && Pname(e)->n_initializer)
                   37989:     e = Pname(e)->n_initializer ;
                   37990:   return e ;
                   37991: }
                   37992:         
                   37993: 
                   37994: // determine whether two expressions supplied as actual arguments to
                   37995: // a "template_expr_formal"  formal argument match. 
                   37996: static int expr_match(Pexpr a1, Pexpr a2)
                   37997: {
                   37998:   static int addr_of = 0 ;
                   37999: 
                   38000:   a1 = (addr_of ? a1 : real_expression(a1)) ;
                   38001:   a2 = (addr_of ? a2 : real_expression(a2)) ;
                   38002:   
                   38003:   if (a1 == a2) return true;
                   38004: 
                   38005:   // 
                   38006:   if (a1->base != a2->base) return check_for_const(a1, a2) ;
                   38007:   
                   38008:   switch (a1->base) {
                   38009:   case QUEST:
                   38010:     // a ternary operator
                   38011:     return ( expr_match(a1->cond, a2->cond) &&
                   38012:             expr_match(a1->e1, a2->e1) &&
                   38013:             expr_match(a1->e2, a2->e2)) ;
                   38014:   
                   38015:   case PLUS: case MINUS: case MUL: case DIV: case MOD:
                   38016:   case ER: case OR: case ANDAND: case OROR:
                   38017:   case LS: case RS:
                   38018:   case EQ: case NE: case LT: case LE: case GT: case GE:
                   38019:     // binary operator
                   38020:     return (expr_match(a1->e1, a2->e1) &&
                   38021:             expr_match(a1->e2, a2->e2)) ;
                   38022:   case UMINUS: case UPLUS:
                   38023:   case NOT: case COMPL:
                   38024:     return (expr_match(a1->e2, a2->e2)) ;
                   38025:   case ADDROF:
                   38026:     {
                   38027:       // unary using e2
                   38028:       addr_of ++ ;
                   38029:       int result = (expr_match(a1->e2, a2->e2)) ;
                   38030:       addr_of -- ;
                   38031:       return result ;
                   38032:     }
                   38033:   case CAST:
                   38034:     return (expr_match(a1->e1, a2->e1)) ;
                   38035:   case NAME:
                   38036:     if (! addr_of) {
                   38037:       Pname n1 = Pname(a1), n2 = Pname(a2) ;
                   38038: 
                   38039:       if ((n1->n_evaluated) && n2->n_evaluated && (n1->n_val == n2->n_val))
                   38040:        return true ;
                   38041:       if (n1->n_initializer &&  (! n2->n_initializer))
                   38042:        return check_for_const(n2, n1->n_initializer) ;
                   38043:       if (n2->n_initializer && (! n1->n_initializer))
                   38044:        return check_for_const(n1, n2->n_initializer) ;
                   38045:       if (n1->n_initializer &&  n2->n_initializer)
                   38046:        return expr_match(n1->n_initializer,  n2->n_initializer) ;
                   38047:     }
                   38048:     return false ;
                   38049:   case DOT:
                   38050:     return (expr_match(a1->e1, a2->e1)) ;
                   38051:   case REF:
                   38052:     return (expr_match(a1->e1, a2->e1)) ;
                   38053:   case IVAL:
                   38054:     return (ival *)a1->i1 == (ival *)a2->i1 ;
                   38055:   case ICON:
                   38056:   case CCON:
                   38057:   case FCON:
                   38058:   case STRING:
                   38059:     return (strcmp (a1->string, a2->string) == 0) ;
                   38060:   case ZERO:
                   38061:     return true ;
                   38062:   case SIZEOF:
                   38063:     { long l1 = a1->eval(), l2 = a2->eval() ;
                   38064:       return (l1 == l2) ;
                   38065:     }
                   38066:   }
                   38067:   return false ;
                   38068: }     
                   38069: 
                   38070: 
                   38071: static char * non_type_argument_signature(Pexpr e, char *p) {
                   38072:   p = e->tp->signature(p) ;
                   38073:   return mangled_expr(p, e) ;
                   38074: }
                   38075:   
                   38076: 
                   38077: 
                   38078: // generate array suffix information for an array signature. cfront does not
                   38079: // normally generate this as part of the type signature, since it only deals
                   38080: // with argument signatures, and arrays can't be arguments.
                   38081: static void add_array_type_suffix(char *&s, Ptype t) {
                   38082:   t = real_type(t) ;
                   38083:   if (t->base == VEC) {
                   38084:       Pvec v = Pvec(t);
                   38085:       int dim;
                   38086:       char a[32] ;
                   38087:       Neval = 0 ;
                   38088:       if(v->dim == 0) 
                   38089:          dim = v->size / v->typ->tsizeof();
                   38090:       else dim = (int)v->dim->eval();
                   38091:     sprintf(a, "A%d", dim) ;
                   38092:     stradd(s,a) ;
                   38093:     add_array_type_suffix(s, Pvec(t)->typ);
                   38094:   }
                   38095: }
                   38096:     
                   38097:                           
                   38098:                           
                   38099: // Generate a mangled template instantiation name. The syntax of as template
                   38100: // mangled class name is of the form:
                   38101: //   original_name__<argument type signatures>__unique_id
                   38102: // Each non-type argument is replaced by a unique id.
                   38103: char *templ_inst::mangled_name(char *ip)
                   38104: { static tree_formal_id = 0 ;
                   38105:         
                   38106:   char *start = ip ;
                   38107:   ip = start ;
                   38108:   strcpy(ip, (def->namep ? def->namep->string : "?")) ;
                   38109:   ip= start + strlen(start) ;
                   38110:   stradd(ip, "__pt__") ;
                   38111: 
                   38112:   {
                   38113:     char  a [max_string_size], *p = a ;
                   38114:   
                   38115:     Plist formal = inst_formals ;
                   38116:   
                   38117:     for (Pexpr ae1=actuals ; ae1 ; ae1=ae1->e2, formal = formal->l)
                   38118:       switch (formal->f->n_template_arg) {
                   38119:       case template_expr_formal:
                   38120:        *p++ = 'X' ;
                   38121:        // the formal must have been bound
                   38122:        p = non_type_argument_signature(formal->f, p) ;
                   38123:        break ;
                   38124:       
                   38125:       case template_type_formal:  
                   38126:        p = ae1->e1->tp->signature(p) ;
                   38127:        add_array_type_suffix(p,ae1->e1->tp) ;
                   38128:        break ;
                   38129:       
                   38130:       case template_expr_tree_formal:
                   38131:       case template_stmt_tree_formal:
                   38132:        *p++ = 'Y' ;
                   38133:        stradd(p, tree_formal_id++) ; 
                   38134:        break ;
                   38135:       
                   38136:       default:
                   38137:        error ("bad template formal:%d", formal->f->base) ;
                   38138:        break ;
                   38139:       }
                   38140:     
                   38141:     *p = 0 ;
                   38142:     sprintf(ip, "%d_", strlen(a)+1) ;
                   38143:     ip = start + strlen(start) ;
                   38144:     strcpy(ip,a) ;
                   38145:   }
                   38146:     
                   38147:   return start ;
                   38148: }
                   38149: 
                   38150: 
                   38151: 
                   38152: // The C compiler barfs when it is passed on through C++ as an automatic
                   38153: // variable 
                   38154: const char leader[]= "\t" ;
                   38155: 
                   38156: // Explain the location of an instantiation in greater detail, since it may be
                   38157: // far removed from it's textual definition.
                   38158: void templ_inst::print_error_loc() {
                   38159:   if (! head) return ; // No active instantiations
                   38160: 
                   38161:   extern void print_loc() ;
                   38162:   state current_state ;
                   38163:   char buffer[max_string_size] ;
                   38164: 
                   38165:   for (int i = 0 ; i < max_string_size; i++) buffer[i] = 0 ;
                   38166: 
                   38167:   current_state.save() ;
                   38168:   fprintf (out_file, "%sanomaly detected during the instantiation of",
                   38169:           leader) ;
                   38170:   print_pretty_name() ;
                   38171:   fprintf(out_file, "\n") ;
                   38172:   if (!head->next_active) {
                   38173:     // A more compact message for a single level of instantiation
                   38174:     context.restore() ;
                   38175:     fprintf (out_file, leader) ;
                   38176:     print_loc() ;    
                   38177:     fprintf (out_file, "was the site of the instantiation\n") ; 
                   38178:   }else {
                   38179:     // The instantiation chain is longer than one
                   38180:     fprintf (out_file, "%sthe instantiation path was:\n", leader) ;
                   38181:     for (Ptempl_inst p = head ; p ; p = p->next_active) {
                   38182:       p->context.restore() ;
                   38183:       print_loc() ;
                   38184:       fprintf (out_file, " template:") ;
                   38185:       p->print_pretty_name() ;
                   38186:       fprintf(out_file, "\n") ;
                   38187:     }
                   38188:   }
                   38189:   current_state.restore() ;
                   38190: }
                   38191: 
                   38192:   
                   38193: 
                   38194: // Generate a class name for the instantiated class. It is constructed in a
                   38195: // manner similar to the names used in the construction of overloaded functions
                   38196: char *templ_inst::instantiation_string() {
                   38197:   char  inst_name[max_string_size] ;
                   38198:   for (int i = 0 ; i < max_string_size; i++) inst_name[i] = 0 ;
                   38199:   mangled_name(inst_name) ;
                   38200:   return strdup(inst_name) ;
                   38201: } 
                   38202:   
                   38203: 
                   38204:     
                   38205: // Change the names for the class, constructors, and destructors to reflect
                   38206: // the new class instantiation name.
                   38207: void classdef::modify_inst_names(char *s)
                   38208: {
                   38209:   char *old = string ;
                   38210:   string = s ;   // Change the class name
                   38211:   // Change the constructor names
                   38212:   for (Pname p=mem_list; p; p=p->n_list)
                   38213:     if (p->tp && (p->tp->base==FCT) && (!strcmp(old, p->string)))
                   38214:       p->string = s ;
                   38215: }
                   38216: 
                   38217: // Get past the fake template argument name typename types
                   38218: Ptype non_template_arg_type(Pbase t) {
                   38219:   if ((t->base == TYPE) &&
                   38220:       (t->b_name->n_template_arg == template_type_formal))
                   38221:     return non_template_arg_type(Pbase(t->b_name->tp)) ;
                   38222:   else return t ;
                   38223: }
                   38224: 
                   38225: // follow the chain until we hit a non
                   38226: void non_template_arg_non_type(Pname n) {
                   38227:   Pexpr i = n->n_initializer; 
                   38228:   while (i &&
                   38229:         (i->base == NAME) &&
                   38230:         (Pname(i)->n_template_arg == template_expr_formal)) 
                   38231:     {
                   38232:       if (Pname(i)->n_initializer) {
                   38233:        n->n_initializer = Pname(i)->n_initializer ;
                   38234:        i = n->n_initializer ;
                   38235:        continue ;
                   38236:       }
                   38237:       if (Pname(i)->n_evaluated) {
                   38238:        n->n_evaluated = 1 ;
                   38239:        n->n_val = Pname(i)->n_val ;
                   38240:        return ;
                   38241:       }
                   38242:     }
                   38243:   return ;
                   38244: }
                   38245:       
                   38246: 
                   38247: 
                   38248: // Now that the actuals are truly resolved, ie. semantics is complete, and the
                   38249: // template is about to be instantiated.
                   38250: void forward_template_arg_types(Plist formal, Pexpr actuals)
                   38251: {   
                   38252:   for (Pexpr actual = actuals ; formal && actual ;
                   38253:        formal = formal->l, actual = actual->e2)
                   38254:     switch(formal->f->n_template_arg){
                   38255:     case template_type_formal:
                   38256:       actual->e1->tp = non_template_arg_type(Pbase(actual->e1->tp)) ;
                   38257:       break ;
                   38258:     case template_expr_formal:
                   38259:       break ;
                   38260:     case template_expr_tree_formal:
                   38261:     case template_stmt_tree_formal:
                   38262:       break ;
                   38263:     default:
                   38264:       error ('i', "bad template formal") ;
                   38265:     }
                   38266: }
                   38267:      
                   38268: // determine whether the expression supplied as an actual argument to
                   38269: // atemplate formal of type "template_expr_formal" is suitable. We are nore
                   38270: // restrictive than we need to be, simply so that the debugger can have an
                   38271: // easier time. All expressions must be of the form constant integer
                   38272: // expression, a float or double literal, or the address of a variable, or an
                   38273: // array, or function
                   38274: static int  suitable_const_expr(Pname n)
                   38275: {
                   38276:   if (n->n_evaluated) return 1 ;
                   38277: 
                   38278:   if (!n->n_initializer) return 0 ;
                   38279: 
                   38280:   switch (n->n_initializer->base) {
                   38281: 
                   38282:   case CAST:
                   38283:     { // if it is a cast of an integer value, it's fine.
                   38284:       if (n->n_initializer->e1->base == IVAL)
                   38285:        return 1 ;
                   38286:       else return 0 ;
                   38287:     }
                   38288:   
                   38289:   case FCON:
                   38290:   case ZERO:
                   38291:     return 1  ;
                   38292:   
                   38293:   case ADDROF:
                   38294:   case G_ADDROF:
                   38295:     {
                   38296:       Pname an = Pname(n->n_initializer->e2) ;
                   38297:       if (an->base != NAME) return 0 ;
                   38298:       if (an->n_stclass == STATIC) return 1 ;
                   38299:       return 0 ;
                   38300:     }
                   38301:   case NAME:
                   38302:     {
                   38303:       Pname an = Pname(n->n_initializer) ;
                   38304:       if ((an->n_stclass == STATIC) &&
                   38305:          (an->tp->base == VEC))
                   38306:        // assumes that decl processing won, so that the formal could only
                   38307:        // have been apointer
                   38308:        return 1 ;
                   38309:       return 0 ;
                   38310:     }
                   38311:   default:
                   38312:     return 0 ;
                   38313:   }
                   38314: }
                   38315: 
                   38316: 
                   38317: 
                   38318: static bool is_stmt_node(Pnode p) {
                   38319:   if (!p) return false ;
                   38320:   switch(p->base) {
                   38321:   case BREAK: case CONTINUE: case DEFAULT:
                   38322:   case SM: case WHILE: case DO: case SWITCH: case RETURN: case CASE:
                   38323:   case FOR:
                   38324:   case IF:
                   38325:   case BLOCK:
                   38326:   case PAIR: // ?
                   38327:     return true ;
                   38328:   }
                   38329:   return false ;
                   38330: }
                   38331:        
                   38332: 
                   38333: 
                   38334: static void bind_tree_expr_formal(Pname f, Pexpr actual) 
                   38335: {
                   38336:   if (actual->e1->base == TNAME)
                   38337:     error ('i', "a TNAME is not a valid argument for the formal %n",
                   38338:            f) ;
                   38339:   if (is_stmt_node(actual->e1)) {
                   38340:     error ("an expression node was expected for the expression formal parameter %n", f) ;
                   38341:     actual->e1 = zero ;
                   38342:   }
                   38343:   // bind the formal to the expression, it will be accessed from here by
                   38344:   // the hook function during the copy
                   38345:   f->n_initializer = actual->e1 ;
                   38346: }
                   38347: 
                   38348: 
                   38349: 
                   38350: // Bind the formals to the types passed in as the actuals, for the
                   38351: // instantiation, bind the non-type names to their expressions.
                   38352: void templ_inst::bind_formals()
                   38353: { Pexpr actual ;
                   38354:   Plist formal ;
                   38355:   
                   38356:   for (formal = inst_formals, actual = actuals ;
                   38357:        formal && actual ; formal = formal->l, actual = actual->e2)
                   38358:     switch (formal->f->n_template_arg) {
                   38359:       case template_type_formal:
                   38360:        {
                   38361:          formal->f->tp = non_template_arg_type(Pbase(actual->e1->tp)) ;
                   38362:          PERM(formal->f->tp) ;
                   38363:          break ;
                   38364:        }
                   38365:        
                   38366:       case template_expr_formal:
                   38367:        {
                   38368:          actual->e1 = actual->e1->typ(gtbl);
                   38369:          if (formal->f->tp->check(actual->e1->tp,ASSIGN) == 1)
                   38370:            error("template argument mismatch, expected %t for formal %n, not %t",
                   38371:                  formal->f->tp, formal->f, actual->e1->tp) ;
                   38372:          // hide the global name around decl processing of the formal name
                   38373:          Pname g = gtbl->look (formal->f->string, 0) ;
                   38374:          if (g) g->n_key = HIDDEN ;
                   38375:          // bind the non type arguments to their expressions
                   38376:          // parameters that are bound at syntax analysis, these parameters are
                   38377:          // bound during dcl processing, so ensure that they can be found.
                   38378:          formal->f->n_initializer = actual->e1 ;
                   38379:          formal->f->simpl() ;
                   38380:          formal->f = formal->f->dcl(gtbl, STATIC) ;
                   38381:          formal->f->n_key = HIDDEN ;
                   38382:          
                   38383:          PERM(formal->f) ;
                   38384:          non_template_arg_non_type(formal->f) ;
                   38385:          if (!suitable_const_expr(formal->f))
                   38386:              error("template argument for formal:%s, is not a suitable constant.",
                   38387:                    formal->f->string) ;
                   38388:          if (g) g->n_key = 0 ;
                   38389:          break ;
                   38390:        }
                   38391:        
                   38392:       case template_expr_tree_formal:
                   38393:        {
                   38394:          bind_tree_expr_formal(formal->f, actual) ;
                   38395:          break ;
                   38396:        }
                   38397:       case template_stmt_tree_formal:
                   38398:        { 
                   38399:          error("a statement tree may not be specified for a class template") ;
                   38400:          break ;
                   38401:        }
                   38402:        
                   38403:       default:
                   38404:        error ('i', "bad template formal") ;
                   38405:       }
                   38406:   
                   38407:   // now that the formals are bound, compute the instantiation string
                   38408:   char *inst_name = instantiation_string() ;
                   38409:   tname->string = instantiation_string() ;
                   38410: 
                   38411:   for (formal = inst_formals; formal ; formal = formal->l)
                   38412:     if (formal->f->n_template_arg_string)
                   38413:        error('i', "attempt to bind a template parameter multiple times") ;
                   38414:     else
                   38415:       formal->f->n_template_arg_string =
                   38416:        strcat(strcpy(calloc(strlen(formal->f->string)+strlen(inst_name)+1,1),
                   38417:                      formal->f->string), inst_name) ;
                   38418: }
                   38419: 
                   38420: 
                   38421: // Expose the non-type parameter names so that they are visible during decl
                   38422: // processing. Conflicting global names are hidden, so that they are not
                   38423: // found.
                   38424: void templ_inst::expose_parameter_names() {
                   38425: 
                   38426:   if (hidden_globals)
                   38427:     error ('i', "an expose without a hide of global names") ;
                   38428:   
                   38429:   for (Plist formal = inst_formals ; formal  ; formal = formal->l)
                   38430:     if (formal->f->n_template_arg == template_expr_formal) {
                   38431:       // Hide any visible globals
                   38432:       Pname gname = gtbl->look(formal->f->string, 0) ;
                   38433:       if (gname) {
                   38434:        // an existing global name, hide it
                   38435:        gname->n_key = HIDDEN ;
                   38436:        // note them for future restoration
                   38437:        hidden_globals = new name_list(gname,hidden_globals);
                   38438:       }
                   38439:       formal->f->n_key = 0 ;   // bring it out of hiding
                   38440:       if (formal->f != gtbl->look(formal->f->string,0))
                   38441:        error('i', "parameter could not be located in the global table") ;
                   38442:     }
                   38443: }
                   38444: 
                   38445: 
                   38446: // Hide the non-type parameter names after an instantiation, and restore any
                   38447: // globals that may have been hidden during the process.
                   38448: void templ_inst::hide_parameter_names() {
                   38449:   
                   38450:   for (Plist formal = inst_formals ; formal  ; formal = formal->l)
                   38451:     if (formal->f->n_template_arg == template_expr_formal) {
                   38452:       formal->f->n_key = HIDDEN ;
                   38453:     }
                   38454:   for (; hidden_globals; hidden_globals= hidden_globals->l)
                   38455:     hidden_globals->f->n_key= 0 ;
                   38456:   hidden_globals = 0 ;
                   38457: }
                   38458: 
                   38459: 
                   38460: 
                   38461: // Primitives for saving and restoring the compilation state around a template
                   38462: // instantiation. It also maintains the stack of template instantiations.
                   38463: void templ_inst::save_state(Pname p)  {
                   38464:   if (next_active) error ('i', "circular instantiation of a template") ;
                   38465:   context.save() ;
                   38466:   if (templ_inst::head)
                   38467:     templ_inst::head->hide_parameter_names() ;
                   38468:   next_active = templ_inst::head ; templ_inst::head = this ;
                   38469:   context.init() ;
                   38470:   Cdcl = p ; Cstmt = NULL ;
                   38471:   curr_file = (Cdcl) ? Cdcl->where.file : 0;
                   38472:   expose_parameter_names() ;
                   38473: } 
                   38474: 
                   38475: 
                   38476: void templ_inst::restore_state() {
                   38477:   context.restore() ;
                   38478:   hide_parameter_names() ;
                   38479:   templ_inst::head = next_active ; next_active = NULL ;
                   38480:   if (templ_inst::head)
                   38481:     templ_inst::head->expose_parameter_names() ;
                   38482: } 
                   38483: 
                   38484: 
                   38485: // Copy over the class definition subtree starting from COBJ down to the
                   38486: // CLASSDEF node. This minimal subtree has to exist during syntax analysis,
                   38487: // and already contains pointers into it.
                   38488: void templ_inst::kludge_copy(Pbase pbc)
                   38489: {
                   38490:   // copy just the COBJ ->b_name NAME ->tp CLASS path for now, note that the
                   38491:   // preceding path of the tree is pre-allocated, since syntax analysis needs
                   38492:   // to generate pointers to these objects.
                   38493:   Pbase pb = Pbase(tname->tp) ;
                   38494:   Pname save_b_name = pb->b_name ;
                   38495:   Ptype save_tp = pb->b_name->tp ;
                   38496: 
                   38497:   if ((pb->base != COBJ) || (pbc->base != COBJ))
                   38498:     error ('i', "cobj nodes were expected here") ;
                   38499:   
                   38500:   *pb = *pbc ;
                   38501:   pb->b_name = save_b_name ;
                   38502:   *pb->b_name = *pbc->b_name ;
                   38503:   pb->b_name->tp = save_tp ;
                   38504:   *Pclass(pb->b_name->tp) = *Pclass(pbc->b_name->tp) ;
                   38505:   Pclass(pb->b_name->tp)->class_base = instantiated_template_class ;
                   38506:   
                   38507: }
                   38508: 
                   38509: 
                   38510: // these statics probably belong in templ_inst and shouldn't be dangling
                   38511: // around
                   38512: 
                   38513: static Pbase cobj_node ;
                   38514: static Pname  cname_node ;
                   38515: static Pclass class_node ;
                   38516:             
                   38517: static void syntax_tree_copy_hook(void *,
                   38518:                             Pnode &,
                   38519:                             node_class,
                   38520:                             tree_node_action &action,
                   38521:                             int& never_see_again)
                   38522: {
                   38523:   never_see_again = 1;
                   38524:   action = tna_continue;
                   38525:   return;
                   38526: }
                   38527: 
                   38528: 
                   38529: // create a copy of the expression tree
                   38530: static Pnode copy_syntax_tree(Pnode n, int no_types = 0) {
                   38531:   pointer_hash       cht(default_copy_hash_size) ;
                   38532:     
                   38533:   tree_copy_info  info ;
                   38534: 
                   38535:   if(no_types) info.node_hook = syntax_tree_copy_hook;
                   38536: 
                   38537:   copy_tree (n, info, &cht);
                   38538: 
                   38539:   return n ;
                   38540: }
                   38541:  
                   38542: 
                   38543: 
                   38544: // hook to perform the copying of the pre-allocated class subtree
                   38545: bool templ_inst::copy_hook(Pnode &node)
                   38546: {
                   38547:   switch (node->base) {
                   38548:   case COBJ:
                   38549:     if (node == cobj_node) return false ;
                   38550:     
                   38551:     if (node == def->namep->tp) {
                   38552:       *cobj_node =  *Pbase(node) ;
                   38553:       node = cobj_node ;
                   38554:     }
                   38555:     break ;
                   38556:   case NAME:
                   38557:     if (node == cname_node) return false ;
                   38558:     if (node == sta_name) return false ;
                   38559: 
                   38560:     if (node == Pbase(def->namep->tp)->b_name) {
                   38561:       *cname_node= *Pname(node) ;
                   38562:       node = cname_node ;                
                   38563:     }else { // check for tree expression formals
                   38564:       char *s = Pname(node)->string ;
                   38565:       Pname f =  0 ;
                   38566:       if (s && (*s == '$') && (f = get_parameter(s+1)))
                   38567:        {
                   38568:          if(Pname(node)->n_list) 
                   38569:            error ('i', "n_list set in tree template formal.");
                   38570:          node = copy_syntax_tree(Pname(f)->n_initializer) ;
                   38571:          return false ;
                   38572:        }
                   38573:     }
                   38574:     break ;
                   38575:   case CLASS:
                   38576:     if (node == class_node) return false ;
                   38577:     
                   38578:     if (node == Pbase(def->namep->tp)->b_name->tp) {
                   38579:       *class_node = *Pclass(node) ;
                   38580:       node = class_node ;
                   38581:     }
                   38582:     break ;
                   38583:   }
                   38584:   return true ;
                   38585: }
                   38586: 
                   38587: 
                   38588: /*
                   38589: 
                   38590: This hook function used during a class copy.
                   38591:                       
                   38592: */
                   38593: static void copy_hook(void /* Ptempl_inst */ *p, Pnode &node,
                   38594:                      node_class, tree_node_action &action,
                   38595:                      int& never_see_again)
                   38596: {
                   38597:   action = (Ptempl_inst(p)->copy_hook(node) ? tna_continue : tna_stop ) ;
                   38598:   never_see_again = (action != tna_stop);
                   38599:   return ;
                   38600: }      
                   38601: 
                   38602:     
                   38603:     
                   38604: void establish_class_subtree_correspondence(pointer_hash &h, Pname key_tname,
                   38605:                                            Pname value_tname) 
                   38606: {
                   38607:   h[int(key_tname)] = int(value_tname) ;
                   38608:   h[int(key_tname->tp)] = int(value_tname->tp) ;
                   38609:   h[int(Pbase(key_tname->tp)->b_name)] =
                   38610:     int(Pbase(value_tname->tp)->b_name) ;
                   38611:   h[int(Pbase(key_tname->tp)->b_name->tp)] =
                   38612:     int(Pbase(value_tname->tp)->b_name->tp) ;
                   38613: }
                   38614: 
                   38615: 
                   38616: 
                   38617: 
                   38618: Pcons make_ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs)
                   38619: {
                   38620:   cons dummy(0,0), *last = &dummy ;
                   38621:   
                   38622:   for (Pcons pc = old_templ_refs ; pc ; pc = pc->cdr) {
                   38623:     
                   38624:     Ptempl_inst t = Ptempl_inst(pc->car) ;
                   38625: // +**** this doesn't work without class instances of new and delete
                   38626: // +**** dtor places this onto free_list: ugh
                   38627: // +**** want to restore this once new/delete isntances are restored
                   38628: //    expr   dummy(ELIST, 0, 0) ;
                   38629: //    elist  list(&dummy) ;
                   38630:     Pexpr   dummy = new expr(ELIST, 0, 0);
                   38631:     elist  list(dummy);
                   38632: 
                   38633:     // copy the trees corresponding to the actuals
                   38634:     for (Pexpr actual = t->actuals ; actual ; actual = actual->e2) {
                   38635:       Pnode root = actual->e1 ;
                   38636:       copy_tree (root, info, &h);
                   38637:       // make sure that references to enclosing formals are resolved
                   38638:       root = Pexpr(root)->typ(gtbl);
                   38639:       list.add(new expr(ELIST, Pexpr(root), 0)) ;
                   38640:     }
                   38641:     Pexpr new_actuals = list.head->e2 ;
                   38642:     
                   38643:     // get one if it exists, create one otherwise.
                   38644:     Ptempl_inst  treal = t->def->get_inst(new_actuals, t) ;
                   38645:     Pname new_tname = treal->tname ;
                   38646:     
                   38647:     last = last->cdr = new cons(treal,0);
                   38648: 
                   38649:     establish_class_subtree_correspondence(h, t->tname, new_tname) ;
                   38650:   }
                   38651: 
                   38652:   return dummy.cdr ;
                   38653: }
                   38654: 
                   38655: 
                   38656: 
                   38657: 
                   38658: /*
                   38659:    Remap the template references from within the body of the template. This
                   38660: action is similar to the normal tree copy operation; it would normally have
                   38661: been done during the syntax phase, that produced the tree, but since there
                   38662: isn't one, for the instantiated body, it must be done here.
                   38663: 
                   38664: */                                          
                   38665: Pcons templ_inst::ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs)
                   38666: {
                   38667:   expose_parameter_names() ;
                   38668:   Pcons new_refs = make_ref_copy(h,info,old_templ_refs) ;
                   38669:   hide_parameter_names() ;
                   38670:   return new_refs ;
                   38671: }
                   38672: 
                   38673: static bool is_forward_instantiation(Pbase b_base, Pbase f_base)
                   38674: {
                   38675:   return bool(b_base->b_name->tp->defined && f_base->b_name->tp->defined) ;
                   38676: }
                   38677: 
                   38678: 
                   38679: /*****************************************************************************
                   38680: *                                                                           *
                   38681: * If the template instantiation is found to be unique after the decl        *
                   38682: * processing of the actuals, create a copy of the post syntax graph for the  *
                   38683: * class. The edges of the graph are determined by "type nodes" that have     *
                   38684: * already been defined, and TNAME nodes that are in the global keyword      *
                   38685: * table. Special care is also taken to avoid copying nodes whose identity    *
                   38686: * must be maintained, since cfront uses them for fast type checks, these     *
                   38687: * nodes always have the "defined" flag turned on and so are never copied.    *
                   38688: *                                                                           *
                   38689: * Copying of the pre-allocated class sub-tree for the template: COBJ        *
                   38690: * ->b_name NAME ->tp CLASS                                                  *
                   38691: *                                                                           *
                   38692: * is handled by the class_copy hook above, that is invoked during the course *
                   38693: * of the copy.                                                              *
                   38694: *                                                                           *
                   38695: *                                                                           *
                   38696: * Template references from within the class need special handling, since     *
                   38697: * each instantiation of the class, results in a potentially new template     *
                   38698: * instantiation.                                                            *
                   38699: *                                                                           *
                   38700: *****************************************************************************/
                   38701: Ptempl_inst  templ_inst::class_copy(Pcons &templ_refs, bool recopy) 
                   38702: {
                   38703:   bool forward = false ; // a forward class is instantiated twice
                   38704:                
                   38705:   // associate the formals with their types, and their expressions
                   38706:   if (recopy) {
                   38707:     // remove the class def node from the table, so that it's attributes are
                   38708:     // copied. 
                   38709:     corr->del(int(Pbase(def->namep->tp)->b_name->tp)) ;
                   38710:     corr->del(int(Pbase(def->namep->tp)->b_name)) ;
                   38711:     corr->del(int(def->namep->tp)) ;
                   38712:     
                   38713:     corr->del(int(tname->tp)) ;
                   38714:     corr->del(int(Pbase(tname->tp)->b_name)) ;
                   38715:     corr->del(int(Pbase(tname->tp)->b_name->tp)) ;
                   38716:   }else corr = new pointer_hash(default_copy_hash_size) ;
                   38717:   
                   38718:   { // copy the formals & install them in the correspondence table
                   38719:     name_list dummy_formal(0,0) ; 
                   38720:     Plist last = &dummy_formal ;
                   38721:       
                   38722:     for (Plist formal = def->formals ; formal ; formal = formal->l) {
                   38723:       Pname copy_name = new name("") ;
                   38724:       *copy_name = *formal->f ;
                   38725:       copy_name->n_tbl_list = 0 ;
                   38726:       last = last->l = new name_list(copy_name, 0) ;
                   38727:       (*corr)[int(formal->f)] = (int)copy_name ;
                   38728:     }
                   38729:     inst_formals = dummy_formal.l ;
                   38730:   }
                   38731:   
                   38732:   bind_formals() ;
                   38733:   if ( ! recopy && ktbl->look(tname->string, 0)) {    
                   38734:     // formal binding may result in detecting identical instantiations
                   38735:     Ptempl_inst ti = def->get_match(actuals, this, true) ;
                   38736:     if (ti) return ti ;
                   38737:     error('i', "Generated template instantiation name %swas not unique",
                   38738:          tname->string) ;
                   38739:   }
                   38740:   
                   38741:   { 
                   38742:     tree_copy_info  info ;
                   38743:     info.node_hook = ::copy_hook ;
                   38744:     info.hook_info = this ;
                   38745:     
                   38746:     (*corr)[int(def->namep)] = int(tname) ; // make the tnames correspond
                   38747:     
                   38748:     templ_refs = ref_copy(*corr, info, templ_refs) ;
                   38749:     Pnode root = def->basep ;  // start the copy at the cobj node
                   38750: 
                   38751:     // deal with these nodes differently during the copy, ie. the nodes
                   38752:     // themselves are not copied, but their attributes are.
                   38753:     cobj_node = (Pbase)tname->tp ;
                   38754:     cname_node = Pbase( tname->tp)->b_name ;
                   38755:     class_node = Pclass(Pbase( tname->tp)->b_name->tp) ;
                   38756:     
                   38757:     copy_tree (root, info, corr);
                   38758: 
                   38759:     {  // dump the tree if the flag is set
                   38760:        extern int dump_tree ;
                   38761:        extern dcn_arg dump_tree_arg;
                   38762: 
                   38763:        if (dump_tree) display_cfront_node (dump_tree_arg, root);
                   38764:      }
                   38765:   }
                   38766:   // Perform name modifications for the class, so that it is an
                   38767:   // instantiation-specific name.
                   38768:   cname_node->string = tname->string ;
                   38769:   if (!recopy)
                   38770:     namep =  ktbl->insert(tname, 0) ;
                   38771:   else class_node->defined &= ~(DEFINED|SIMPLIFIED) ;
                   38772:   namep->tp = cobj_node;
                   38773:     
                   38774:   class_node->modify_inst_names(cname_node->string) ;
                   38775:   return 0 ;
                   38776: }
                   38777: 
                   38778: 
                   38779: /*
                   38780: This hook function is responsible for the replacement of references to
                   38781: expression when copying function bodies
                   38782: */
                   38783: static void function_copy_hook(void *current_templ_inst,
                   38784:                             Pnode &node,
                   38785:                             node_class,
                   38786:                             tree_node_action &action,
                   38787:                               int& never_see_again)
                   38788: {
                   38789:   never_see_again = 1;
                   38790: 
                   38791:   switch (node->base) {
                   38792:   case SM_PARAM:
                   38793:     error ('i', "statement parameters not permitted for member functions") ;
                   38794:     break ;
                   38795:     
                   38796:   case NAME:
                   38797:     { 
                   38798:       if(node == sta_name) {
                   38799:          action = tna_stop;
                   38800:          return;
                   38801:       }
                   38802:       char *s = Pname(node)->string ;
                   38803:       Pname f =  0 ;
                   38804:       if (s && (*s == '$') &&
                   38805:          (f = Ptempl_inst(current_templ_inst)->get_parameter(s+1))) {
                   38806:              if(Pname(node)->n_list) 
                   38807:                  error ('i', "n_list set in tree template formal.");
                   38808:              node = copy_syntax_tree(Pname(f)->n_initializer) ;
                   38809:              action = tna_stop ;
                   38810:              never_see_again = 0;
                   38811:          }else action = tna_continue ;
                   38812:       return ;
                   38813:     }
                   38814:   default:
                   38815:     action = tna_continue ;
                   38816:     return ;
                   38817:   }
                   38818: }
                   38819: 
                   38820: 
                   38821: 
                   38822: /* 
                   38823: 
                   38824: Create a copy of a function member, as part of the instantiation of a function
                   38825: body. The correspondence table is first initialized with the contents of the
                   38826: correspondence table used to instantiate the class. Copying is initiated
                   38827: in this context.
                   38828: 
                   38829: */
                   38830: 
                   38831: Pname templ_inst::function_copy(Pfunt fnt, Pcons &templ_refs)
                   38832: {
                   38833:   pointer_hash fcorr(*corr) ; // initialize it with the old hash table
                   38834:   
                   38835:   {     
                   38836:     tree_copy_info  info ;
                   38837:     Pnode           root = fnt->fn ; 
                   38838: 
                   38839:     // establish a correspondence between the formals used for the class
                   38840:     // template, andthe formals used for the function template, all references
                   38841:     // to the function template formals will be replaced by references to the
                   38842:     // instantiated class template formals after the copy has been completed.
                   38843:     
                   38844:     for (Plist fformal = fnt->formals, cformal = inst_formals ;
                   38845:         fformal ; fformal = fformal->l, cformal = cformal->l)
                   38846:       {
                   38847:        fcorr[int(fformal->f)] = int(cformal->f) ;
                   38848:        if (fcorr[int(fformal->f)] != int(cformal->f))
                   38849:          error ('i', "hash table bug") ;
                   38850:       }
                   38851: 
                   38852:     info.node_hook = ::function_copy_hook ;
                   38853:     info.hook_info = this ;
                   38854: 
                   38855:     templ_refs = ref_copy(fcorr, info,  templ_refs) ;
                   38856:     if (fcorr[int(def->namep)] != int(tname))
                   38857:       error ('i', "template to instantiation typename correspondence is missing") ;
                   38858:     
                   38859:     copy_tree (root, info, &fcorr);
                   38860: 
                   38861:     {  // dump the tree if the flag is set
                   38862:       extern int dump_tree ;
                   38863:       extern dcn_arg dump_tree_arg;
                   38864: 
                   38865:       if (dump_tree)
                   38866:        display_cfront_node (dump_tree_arg, root);
                   38867:     }
                   38868:     return Pname(root) ;
                   38869:   }
                   38870: }
                   38871:   
                   38872:      
                   38873: /*****************************************************************************
                   38874: *                                                                           *
                   38875: * A matching template was found at instantiation time, which was not        *
                   38876: * detected at syntax analysis time. This can happen, when an instantiation   *
                   38877: * has as its arguments not real types but template arguments, so that       *
                   38878: * matches cannot be detected until the templates are bound. Note that it is  *
                   38879: * also possible to match a template that is in the process of being         *
                   38880: * instantiated further up the instantiation call chain. In such cases, the   *
                   38881: * kludge_copy operation will copy over an incomplete class subtree, which    *
                   38882: * will be recopied with the completed one after the instantiation is        *
                   38883: * completed, in templ_inst::instantiate.                                    *
                   38884: *                                                                           *
                   38885: *****************************************************************************/
                   38886: void templ_inst::instantiate_match(Ptempl_inst match)
                   38887: { Pbase pb = Pbase(match->tname->tp) ;
                   38888:   kludge_copy(pb) ;
                   38889:   forward = match ;            // Note the fact that this template was matched
                   38890: }
                   38891: 
                   38892: 
                   38893: Pclass current_instantiation = 0 ;
                   38894: 
                   38895: // Do the class declaration instantiation.
                   38896: void templ_inst::instantiate(bool reinstantiate)
                   38897: {
                   38898:   Pcons templ_refs = def->templ_refs  ;
                   38899:   if (! reinstantiate) {
                   38900:     switch (Ptclass(Pbase(tname->tp)->b_name->tp)->class_base) {
                   38901:     case instantiated_template_class: 
                   38902:       return ;
                   38903:     case uninstantiated_template_class: 
                   38904:       break ;
                   38905:     case vanilla_class:
                   38906:     case template_class:               // the canonical template class
                   38907:     default: 
                   38908:       error ('i', "attempt to instantiate a non-template class") ;
                   38909:     }
                   38910:     status = class_instantiated ;
                   38911:     // Check whether, the template has already been instantiated, if so use it.
                   38912:     forward_template_arg_types(def->formals, actuals) ;
                   38913:     Ptempl_inst match = def->get_match(actuals, this, true) ;
                   38914:     
                   38915:     if (match || (match = class_copy(templ_refs, false))){
                   38916:       instantiate_match(match) ;
                   38917:       return ;
                   38918:     }
                   38919:   }else class_copy(templ_refs, true) ;
                   38920: 
                   38921:   Pbase pb = Pbase(tname->tp) ;
                   38922:   
                   38923:   // Save the state around decl processing
                   38924:   { save_state(def->namep) ;
                   38925:     
                   38926:     if (def->open_instantiations++ > 1) {
                   38927:       error ("an infinite instantiation sequence was initiated") ;
                   38928:       def->open_instantiations-- ;
                   38929:       return ;
                   38930:     }
                   38931:     // Mark the class as instantiated so that there are no circular
                   38932:     // instantiations. 
                   38933:     Pclass(pb->b_name->tp)->class_base = instantiated_template_class ;
                   38934: 
                   38935:     // if it is a forward reference, rely on the usual compilation to
                   38936:     // provide an error message, if indeed it is an error, and not a
                   38937:     // benign forward reference such as: friend class foo<X,Y> 
                   38938:          
                   38939:     if (def->basep->b_name->tp->defined) {
                   38940: 
                   38941:       // Put out the typedefs for the template parameters do this before the
                   38942:       // call to name::dcl below, since dcl processing will emit c declarations
                   38943:       // that make use of the type
                   38944:       for (Plist formal = inst_formals; formal ; formal = formal->l)
                   38945:        switch(formal->f->n_template_arg) {
                   38946:        case template_expr_tree_formal:
                   38947:        case template_stmt_tree_formal:
                   38948:          break ;
                   38949:        default:
                   38950:          formal->f->dcl_print(0) ;
                   38951:        }
                   38952:       // Instantiate the parametrized types referenced by this template
                   38953:       for (Pcons pc = templ_refs ; pc ; pc = pc->cdr)
                   38954:        Ptempl_inst(pc->car)->instantiate() ;
                   38955:       
                   38956:       if (!((pb->b_name->dcl(gtbl, EXTERN) == 0 ) || error_count)) {
                   38957:        pb->b_name->simpl() ;
                   38958:        
                   38959:        if (pb->b_name->tp->base != CLASS)
                   38960:          error('i', "a classdef was expected in templ_inst::instantiate") ;
                   38961:        
                   38962:        current_instantiation =  Pclass(pb->b_name->tp) ;
                   38963:        pb->b_name->dcl_print(0) ;
                   38964:        if (! (pb->b_name->tp->defined & DEFINED))
                   38965:          error ('i', "dcl class is not yet defined") ;
                   38966:        current_instantiation = 0 ;
                   38967:       }
                   38968:     }
                   38969: 
                   38970:     // bash every template instantiation class that has been forwarded to
                   38971:     // it, with the decl processed version.
                   38972:     for (Ptempl_inst clone = def->insts ; clone ; clone = clone->next)
                   38973:       if (clone != this) {
                   38974:        if (clone->forward == this)
                   38975:          clone->kludge_copy(Pbase(tname->tp)) ;
                   38976:        else {
                   38977:          // resolve references to forward declarations
                   38978:          if (this == def->get_match(clone->actuals, clone, true)) {
                   38979:            clone->kludge_copy(Pbase(tname->tp)) ;
                   38980:            clone->forward = this ;
                   38981:          }
                   38982:        }
                   38983:       }
                   38984:     Pclass result = Pclass(pb->b_name->tp);
                   38985:       
                   38986:     // dcl_print the member functions, so that they can be referenced
                   38987:     int i = 0 ;
                   38988:     for (Pname fn= Pclass(pb->b_name->tp)->memtbl->get_mem(i=1); fn;
                   38989:         fn=Pclass(pb->b_name->tp)->memtbl->get_mem(++i))
                   38990:       if ((fn->base == NAME) && (fn->tp->base == FCT))
                   38991:        fn->dcl_print(0) ;
                   38992:     
                   38993:     restore_state() ;
                   38994:     def->open_instantiations-- ;
                   38995:   }
                   38996: }
                   38997: 
                   38998: /* Template Constructors  */
                   38999: 
                   39000: 
                   39001: templ::templ(Plist parms, Pname p) {
                   39002:   namep   = p ;
                   39003:   formals = parms ;
                   39004: 
                   39005:   if (!formals) error ("a parametrized type must have parameters !") ;
                   39006: 
                   39007:   basep   = Pbase(namep->tp) ;
                   39008: 
                   39009:   Pclass(basep->b_name->tp)->class_base = template_class ;
                   39010:   defined = ((basep->b_name->tp->defined & DEF_SEEN) ? true : false) ;
                   39011:   if (defined)
                   39012:     members = Pclass(basep->b_name->tp)->mem_list ;
                   39013:   
                   39014:   PERM(namep) ; PERM(namep->tp) ;
                   39015:   // Chain on to the list of templates for the compilation.
                   39016:   next = templp->list ;
                   39017:   templp->list = this ;
                   39018: }
                   39019: 
                   39020: 
                   39021: templ_inst::templ_inst (Pexpr act, Ptempl owner)
                   39022: {
                   39023:   // Set up the basetype for the class, so that nodes that need to point to it
                   39024:   // during syntax processing can do so. Theese objects are merely
                   39025:   // place-holders during syntax analysis, and are actually filled in during
                   39026:   // the copy phase of instantiation.
                   39027:   Pclass c ;
                   39028:   
                   39029:   def = owner ;
                   39030:   tname = new name(def->namep->string) ;
                   39031:   tname->base = TNAME ;
                   39032:   tname->tp = new basetype(COBJ, new name(def->namep->string)) ;
                   39033:   Pbase(tname->tp)->b_name->tp = c = new templ_classdef(this) ;
                   39034:   PERM(tname) ; PERM(tname->tp) ; PERM(Pbase(tname->tp)->b_name) ;
                   39035:   PERM(Pbase(tname->tp)->b_name->tp) ;
                   39036: 
                   39037:   // initialize the member list so that set_scope can do the right thing
                   39038:   c->mem_list = Pclass(def->basetype()->b_name->tp)->mem_list ;
                   39039:   
                   39040:   actuals = act ;
                   39041:   next = owner->insts ;
                   39042:   owner->insts = this ;
                   39043: }
                   39044: 
                   39045: 
                   39046: templ_classdef::templ_classdef(Ptempl_inst i): classdef(CLASS) {
                   39047:   inst = i ;
                   39048:   class_base = uninstantiated_template_class ;
                   39049:   string = unparametrized_tname()->string ;
                   39050: }
                   39051: 
                   39052: 
                   39053: // Create a new function template.
                   39054: function_template::function_template (templ &owner, Plist params, Pname n)
                   39055: {
                   39056:   definition_number = ++definition_tick ;
                   39057:                      
                   39058:   if (owner.fns_end)
                   39059:     owner.fns_end->next = this ;
                   39060:   else owner.fns = this ;
                   39061:   owner.fns_end = this ;
                   39062:   formals   = params ;
                   39063:   fn        = n ;
                   39064:   PERM(n) ; PERM(n->tp) ;
                   39065: }
                   39066: 
                   39067: 
                   39068: // create the tree template
                   39069: tree_template::tree_template(TOK tree_kind, char *s, Plist params, Pnode tree,
                   39070:                             Pcons references) 
                   39071: {
                   39072:   string = s ;
                   39073:   formals = params;
                   39074:   e = tree ;
                   39075:   if (!e)
                   39076:     error('w', "the internal template %s does not have an associated body", s);
                   39077:   templ_refs = references ;
                   39078:   kind = tree_kind ;
                   39079: 
                   39080:   // add the expression template too the list of known templates
                   39081:   if (get(s)) {
                   39082:       error ("duplicate definition of the internal template %s", s) ;
                   39083:       return ;
                   39084:     }
                   39085:   // link it in
                   39086:   next = templ_compilation::tree_templates ;
                   39087:   templ_compilation::tree_templates = this ;
                   39088: 
                   39089:   // check that formals weren't misspelt
                   39090:   for (Plist formal = formals ; formal ; formal = formal->l)
                   39091:     if (! formal->f->n_used)
                   39092:       error('w', "the formal parameter %n was not referenced within the template body",formal->f) ;
                   39093: }
                   39094: 
                   39095: 
                   39096: // lookup an internal expression template
                   39097: Ptreet tree_template::get(char *s) {
                   39098:   for (Ptreet o = templ_compilation::tree_templates ; o ; o = o->next)
                   39099:     if (strcmp(o->string, s) == 0) return o ;
                   39100:   return 0 ;
                   39101: }
                   39102:  
                   39103:  
                   39104: Pname tree_template::get_parameter(char *s) {
                   39105:   for (Plist formal = formals ; formal ; formal = formal->l) {
                   39106:     if (strcmp(formal->f->string, s)== 0)
                   39107:       return formal->f ;
                   39108:   }
                   39109:   return 0 ;
                   39110: }
                   39111: 
                   39112: 
                   39113: 
                   39114: // Sam: some remodularization seems to be in order here, so that this method
                   39115: // can be shared
                   39116: Pname templ_inst::get_parameter(char *s) {
                   39117:   for (Plist formal = inst_formals ; formal ; formal = formal->l) {
                   39118:     if (strcmp(formal->f->string, s)== 0)
                   39119:       return formal->f ;
                   39120:   }
                   39121:   return 0 ;
                   39122: }
                   39123: 
                   39124: Pexpr tree_template::expand(Pexpr)  
                   39125: {
                   39126:   error('i', "no support for tree templates") ;
                   39127:   return 0 ;
                   39128: }
                   39129: 
                   39130:   
                   39131: // Instantiate each function member body. It assumes that the class
                   39132: // declaration has been instantiated. The return value indicates whether an
                   39133: // instantiation of bodies actually took place. This function is only invoked
                   39134: // at the end of a file compilation, after all source text has been processed. 
                   39135: bool templ::instantiate_bodies(){
                   39136:   bool change = false ;
                   39137:   // Perform the instantiation of the member function bodies.
                   39138:   if (!fns) return change ;
                   39139:   
                   39140:   for (Ptempl_inst inst = insts ;  inst ; inst = inst->next)
                   39141:     if (!inst->forward && (inst->status == class_instantiated)) {
                   39142:       // Set up the environment for the declaration, and subsequent compilation
                   39143:       // of the function bodies.
                   39144:       inst->status = body_instantiated ; change = true ;
                   39145: 
                   39146:       {  Pclass ic = inst->get_class() ; int i ;
                   39147:        // note all the overriding definitions explicitly provided by the user
                   39148:        for (Pname fn= ic->memtbl->get_mem(i=1); fn; fn=ic->memtbl->get_mem(++i))
                   39149:             if ((fn->base == NAME) && (fn->tp->base == FCT) && Pfct(fn->tp)->body)
                   39150:          fn->n_redefined = 1 ;
                   39151:        }
                   39152: 
                   39153:       for (Pfunt fnt = fns;  fnt ; fnt = fnt->next) {
                   39154:        Pcons templ_ref_copy = fnt->templ_refs ;
                   39155:        Pname fn = inst->function_copy(fnt, templ_ref_copy) ;
                   39156:        
                   39157:        // Change the qualifier to be the name of the instantiated, rather than
                   39158:        // the parametrized class name
                   39159:        fn->n_qualifier = inst->namep ;
                   39160: if (fn->n_oper != TYPE ) // cond contains type information
                   39161:        fn->n_table = 0; 
                   39162:        fn->n_tbl_list = 0 ;
                   39163:        
                   39164:        // Note that the formals were bound to the actuals when the class decl
                   39165:        // was instantiated, so the binding is not redone.
                   39166:        
                   39167:        // Modify constructor and destructor names.
                   39168:        if (!strcmp(fn->string, namep->string))
                   39169:          fn->string = inst->namep->string ;    
                   39170:        { inst->save_state(fn) ;
                   39171:          // Instantiate the parametrized types referenced by this template
                   39172:          for (Pcons pc = templ_ref_copy ; pc ; pc = pc->cdr)
                   39173:            Ptempl_inst(pc->car)->instantiate() ;
                   39174: 
                   39175:          // ensure that "type type" formals constrained to be class definitions are
                   39176:          if (!fnt->check_constraints(inst->actuals))continue ;
                   39177: 
                   39178:          if ( ((fn = fn->dcl(gtbl, EXTERN)) == 0) || error_count) {
                   39179:            inst->restore_state() ;
                   39180:            continue ;
                   39181:          }
                   39182:          fn->simpl() ;
                   39183:          fn->dcl_print(0) ;
                   39184:          inst->restore_state() ;
                   39185:        }
                   39186:       }
                   39187:     }
                   39188:   return change ;
                   39189: }
                   39190: 0707071010112046121004440001630000160000010212600466055421700001300000040045template.h/* ident "@(#)ctrans:src/template.h     1.2" */
                   39191: /* -*- Mode:C++ -*- */
                   39192: /*
                   39193:        $Source: /usr3/lang/benson/work/stripped_cfront/RCS/template.h,v $ $RCSfile: template.h,v $
                   39194:        $Revision: 1.4 $                $Date: 90/04/02 11:31:35 $
                   39195:        $Author: sam $          $Locker:  $
                   39196:        $State: Exp $
                   39197: */
                   39198: /*
                   39199:     $Header: /usr3/lang/benson/work/stripped_cfront/RCS/template.h,v 1.4 90/04/02 11:31:35 sam Exp $
                   39200: 
                   39201:     Copyright 1989 by Object Design, Inc., Burlington, Mass.
                   39202:     All rights reserved.
                   39203: 
                   39204: */
                   39205: 
                   39206: 
                   39207: /*****************************************************************************
                   39208: *                                                                           *
                   39209: * This file contains types pertinent to the implementation of the           *
                   39210: * parametrized type facility.                                               *
                   39211: *                                                                           *
                   39212: *****************************************************************************/
                   39213: 
                   39214: enum bool { true = 1, false = 0 } ;
                   39215: 
                   39216: typedef class templ *Ptempl ;
                   39217: 
                   39218: typedef class templ_inst *Ptempl_inst ;
                   39219: 
                   39220: typedef class function_template *Pfunt ;
                   39221: 
                   39222: typedef class templ_classdef *Ptclass ;
                   39223: 
                   39224: typedef class tree_template *Ptreet ;
                   39225: 
                   39226: 
                   39227: // A Lisp style cons cell to help build lists. The parametrized type facility,
                   39228: // should obviate the need for this type-unsafe nonsense.
                   39229: class cons {
                   39230: public:
                   39231:   void *car ;
                   39232:   cons *cdr ;
                   39233:   cons (void *pcar, cons *pcdr) { car = pcar ; cdr = pcdr ; } ;
                   39234: } ;
                   39235: 
                   39236: typedef cons *Pcons ;
                   39237: 
                   39238: 
                   39239: 
                   39240: /*****************************************************************************
                   39241: *                                                                           *
                   39242: * The class template_compilation holds the state, and the associated methods *
                   39243: * used during template compilation. There is exactly one instance of the     *
                   39244: * type, it is mainly a device used to enforce modularity.  In reality, it    *
                   39245: * would never need to be instantiated since all it's members are static.     *
                   39246: * However, since the type::mem for of reference is not supported as         *
                   39247: * yet(cfront 1.2), we need an instantiation to get to the members via       *
                   39248: * pointer syntax instead.                                                   *
                   39249: *                                                                           *
                   39250: * A templ_compilation holds the state relevant to the syntax analysis of a   *
                   39251: * class or member function template definition.                                     *
                   39252: *                                                                           *
                   39253: *****************************************************************************/
                   39254: 
                   39255: class templ_compilation {
                   39256:   static  Plist param_end,   // make append easier
                   39257:                 param_tn ;   // The type names introduced by the parameters
                   39258: 
                   39259: public:
                   39260:   static Ptempl  list ;      // The list of templates for the compilation
                   39261:   static Plist   params ;    // The list of parameters to the template
                   39262:   static Ptempl  owner  ;    // The template when compiling a member
                   39263:                              //     function.
                   39264:   static table   *templates ; // The templates defined during this compilation
                   39265:   
                   39266:   static Ptreet  tree_templates; // The list of tree templates
                   39267: 
                   39268:   static bool    in_progress; // a template compilation is in progress
                   39269:   // instantiation parameter parsing in progress. Used in the lexer to ensure
                   39270:   // that name string are consed in the heap, rather than being retained as
                   39271:   // pointers into the lex buffer.
                   39272:   static int     parameters_in_progress ;
                   39273: 
                   39274:   // the list of templates referenced by the top level definition being compiled.
                   39275:   static Pcons   templ_refs ;
                   39276:   static Pcons   last_cons ;
                   39277:   static Ptype   any_type ;  // canonical "ANY" type for formal parms
                   39278:   
                   39279:   // true, if currently compiling an expression tree template
                   39280:   static TOK   curr_tree_template ;
                   39281: 
                   39282:   void append_ref(Ptempl_inst ref) ;
                   39283:   void start() ;
                   39284:   
                   39285:   void collect(TOK parm_type, Pname namep) ;
                   39286:   void collect(Pname namep) ;
                   39287: 
                   39288:   void enter_parameters() ;
                   39289:   void introduce_class_templ(Pname cnamep) ;
                   39290:   void end(Pname class_name) ;
                   39291:   Pname forward_declaration(Pname class_name) ;
                   39292:   void instantiate_ref_templ() ;
                   39293:   void clear_ref_templ() ;
                   39294: 
                   39295:   Pname check_tname(Pname p) ;
                   39296:   bool  current_template(Pname p, Pexpr actuals) ;
                   39297:   Ptempl is_template(Pname p) ;
                   39298:   Ptempl is_template(char *s);
                   39299:   void end_of_compilation() ;   // Done with compilation, instantiate bodies
                   39300:   templ_compilation()  ;
                   39301: 
                   39302:   static Pname tree_parameter(char *s) ; // return true if the name is a tree parameter
                   39303: 
                   39304: private:
                   39305:   void append_parameter(Pname p) ;
                   39306:   
                   39307: } ;
                   39308: 
                   39309: 
                   39310: 
                   39311: // The canonical template_compilation instance. templ_compilation exists as a
                   39312: // class simply to provide a code and data packaging mechanism. There is
                   39313: // exactly one generated instance of it.
                   39314: 
                   39315: extern templ_compilation *templp ;
                   39316: 
                   39317: // should actually be static member functions of templ_compilation
                   39318: Pname parametrized_typename (Pname p, Pexpr actuals) ;
                   39319: Pbase parametrized_basetype (Pname p, Pexpr actuals) ;
                   39320: 
                   39321: 
                   39322: 
                   39323: 
                   39324: // the basis for class and member function templates
                   39325: class basic_template {
                   39326:   friend templ_compilation ;
                   39327: protected:
                   39328:   Plist       formals ;        // The formal arguments to the template
                   39329:   Pcons       templ_refs ;     // The templates referenced by this template
                   39330: 
                   39331:   // check class constraints placed on formals while processing member
                   39332:   // function bodies. 
                   39333:   bool check_constraints(Pexpr actuals) ;
                   39334:   
                   39335:   // ensure that use of formals is consistent across, class, member and
                   39336:   // forward declarations
                   39337:   void check_formals(Plist formals) ;
                   39338: 
                   39339: public:
                   39340:   // used to order template class definitions for instantiations. Not being
                   39341:   // used as yet.
                   39342:   int        definition_number ;
                   39343: 
                   39344:   // used to generate the definition numbers, used by the above member.
                   39345:   static int definition_tick ;
                   39346:         
                   39347:   Plist get_formals() {return formals ;}
                   39348: } ;
                   39349: 
                   39350: 
                   39351: 
                   39352: // the template for a class
                   39353: class templ  : public basic_template { 
                   39354:   Pbase       basep ;          // COBJ basetype for the template
                   39355:   Ptempl_inst insts  ;         // instantiations of the template
                   39356:   Pfunt       fns  ;           // member function declarations
                   39357:   Pfunt       fns_end ;        // last fun in the above list
                   39358:   
                   39359:   // Use these state variables to set up the correct state for error
                   39360:   // processing. They are used by the "error" routines for statement numbers.
                   39361:   Pname       Cdcl ;
                   39362:   Pstmt       Cstmt ;
                   39363:   
                   39364:   friend templ_inst ;
                   39365:   friend function_template ;
                   39366: 
                   39367:   // used to detect loops during instantiation; a count greater than two is
                   39368:   // indicative of a non-terminating instantiation sequence
                   39369:   int         open_instantiations ;
                   39370:   
                   39371:   Ptempl_inst get_match(Pexpr actuals,
                   39372:                        Ptempl_inst exclude,
                   39373:                        bool match_instantiated_only) ;
                   39374:   bool check_actual_args (Pexpr actuals) ;
                   39375: 
                   39376: public:
                   39377:   Ptempl      next ;           // connects all the class templates in the comp
                   39378:   Pname       namep ;          // the TNAME for the template class
                   39379:   bool        defined ;        // the actual definition, not just a forward
                   39380:                               // declaration has been seen.
                   39381: 
                   39382:   Pname       members ;        // note the members to catch redefinition errors
                   39383: 
                   39384:   Ptempl_inst get_inst(Pexpr actuals, Ptempl_inst exclude = 0) ;
                   39385:   templ(Plist parms, Pname p) ;
                   39386:   void resolve_forward_decl(Plist parms, Pclass c) ;
                   39387:   void instantiate_forward_decl() ;
                   39388:   
                   39389:   // The uninstantiated base type
                   39390:   Pbase basetype() {return basep; }
                   39391:   // The basetype for a specific instantiation
                   39392:   Pbase inst_basetype(Pexpr actuals) ;
                   39393: 
                   39394:   Pname typename(Pexpr actuals) ;
                   39395:   
                   39396:   Pfunt collect_function_member(Pname fname) ;
                   39397:   bool  has_tree_expr_formals() ;
                   39398:   bool instantiate_bodies() ;
                   39399: } ;
                   39400: 
                   39401: 
                   39402: 
                   39403: // Member function templates
                   39404: class function_template : public basic_template {
                   39405:   Pname       fn ;             // The name of the member function
                   39406:   Pfunt       next ;           // connects the list of member functions
                   39407: 
                   39408:   friend templ ;
                   39409:   friend templ_inst ;
                   39410: 
                   39411: public:
                   39412:   function_template (templ & owner, Plist params, Pname n) ;
                   39413: } ;
                   39414: 
                   39415: 
                   39416: 
                   39417: // compiler internal expression templates, used to implement Objectstore constructs
                   39418: class tree_template : public basic_template {
                   39419:   TOK         kind ;          // STATEMENT or EXPRESSION
                   39420:   Pnode       e ;             // the post-syntax tree representing the
                   39421:                              // expression or statement constituting the
                   39422:                               // template.
                   39423:   Ptreet      next ;          // the next expression template
                   39424:   static      int count ;     // the number of instantiations
                   39425:                                 
                   39426: public:
                   39427:   char        *string ;       // the name used for template lookup
                   39428:   tree_template(TOK tree_kind, char *s, Plist params, Pnode tree,
                   39429:                Pcons references) ;
                   39430:   static  Ptreet get(char *s) ;
                   39431:   Pname   get_parameter(char *s) ;
                   39432:   static  void test() ;
                   39433:   Pexpr expand(Pexpr actuals) ;
                   39434: } ;
                   39435: 
                   39436: 
                   39437: 
                   39438: 
                   39439: // Global state variables that must be saved around an instantiation. The
                   39440: // saving of state was required in the implementstion that interspersed decl
                   39441: // processing and instantiation, rather than the current strategy, which only
                   39442: // forces instantiations at the top level outside of any dcl-processing
                   39443: // context. It is retained in case we ever go back to the "interspersed" style
                   39444: // of instantiation. 
                   39445: class state {
                   39446: 
                   39447: public:
                   39448:   Pname       Cdcl ;      // the global variables used by the error routines
                   39449:   Pstmt       Cstmt ;
                   39450:   Pname       dcl_list ;  // Holds the list of typedef names that are hidden
                   39451:   Loc         curloc ;
                   39452:   
                   39453:   int         curr_file ;
                   39454:   Pexpr       curr_expr ;
                   39455:   Pin         curr_icall ;
                   39456:   Pstmt       curr_loop;
                   39457:   Pblock      curr_block;
                   39458:   Pstmt       curr_switch;
                   39459: 
                   39460:   int         bound  ;   
                   39461:   int         inline_restr ;
                   39462:   Loc         last_line ;
                   39463: 
                   39464:   int         no_of_badcall;
                   39465:   int         no_of_undcl ;
                   39466:   
                   39467:   Pname       badcall ;
                   39468:   Pname       undcl ;
                   39469: 
                   39470:   state() {} ; // prevent used before set warnings.
                   39471:   void save() ;
                   39472:   
                   39473:   void init() ; 
                   39474:   void restore() ; 
                   39475: } ;
                   39476: 
                   39477: 
                   39478: class pointer_hash ; 
                   39479: class tree_copy_info ;
                   39480: 
                   39481: 
                   39482: // A template starts out being uninstantiated, and is class_instantiated when
                   39483: // there is a refrence to it with actual arguments. It is body_instantiated at
                   39484: // the end of compilation, when all its function members are instantiated.
                   39485: enum inst_status { uninstantiated, class_instantiated, body_instantiated };
                   39486: 
                   39487: // templ_inst captures the arguments used in the instantiation of a template.
                   39488: // These instantiations are rooted in the templ object. 
                   39489: class templ_inst {
                   39490:   
                   39491:   friend class template_instantiation ;
                   39492: 
                   39493:   Pname      tname ;         // The instantiation name, it is the TNAME that
                   39494:                              // leads up to an actual instantiation of the class
                   39495:   Pname      namep ;         // The version of TNAME in the ktbl
                   39496:   Pexpr      actuals ;       // instantiation arguments, chained using ELIST
                   39497:                             // as an expression "cons" node, e1 is the car
                   39498:                             // and e2 the cdr. The car points to a name node.
                   39499:   Ptempl_inst next ;         // The linked list of instantiations for this
                   39500:                              // template.
                   39501:   Ptempl_inst next_active ;  // The list of currently active instantiations.
                   39502:   state       context ;      // the context of this instantiation
                   39503:   Ptempl_inst forward ;      // This instantiation is the same as the one
                   39504:                              // pointed to.
                   39505: 
                   39506:   // Contains the list of global names that are hidden during an
                   39507:   // instantiation.
                   39508:   Plist hidden_globals ;
                   39509: 
                   39510:   // The class correspondence table. This table is initialized 
                   39511:   // when the class definition is instantiated. Subsequently, it is used to
                   39512:   // initial member correspondence tables before the copy process is
                   39513:   // initiated.
                   39514:   pointer_hash        *corr ;
                   39515: 
                   39516:   // the instantiation's copy of the formals
                   39517:   Plist  inst_formals ;
                   39518:        
                   39519:   inst_status status ;
                   39520:   
                   39521:   friend class templ ;
                   39522:   friend class templ_classdef ;
                   39523:   friend class tree_template ;
                   39524:   friend Pcons make_ref_copy(pointer_hash &h, tree_copy_info &info,
                   39525:                             Pcons old_templ_refs);
                   39526:   
                   39527:   templ_inst (Pexpr act,  Ptempl owner) ;
                   39528:   bool actuals_match(Pexpr check_actuals) ;
                   39529:   void instantiate_match(Ptempl_inst match) ;
                   39530:   void kludge_copy(Pbase source_base) ;
                   39531:   // create a copy of the class type subtree preparatory to the ensuing
                   39532:   // instantiation. Return a non-zero value, only if there was no need to
                   39533:   // create a copy, ie. an identical instantiation already existed.
                   39534:   Ptempl_inst class_copy(Pcons &templ_refs, bool recopy) ;
                   39535:   Pcons ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs) ;
                   39536:     
                   39537:   // save and restore state around the template instantiation
                   39538:   void save_state(Pname p) ;
                   39539:   void restore_state() ;
                   39540:   
                   39541:   // Used to collect references to this template by a definition
                   39542:   Ptempl_inst note_ref() ;
                   39543:   char *instantiation_string() ;
                   39544:   
                   39545:   void expose_parameter_names() ;
                   39546:   void hide_parameter_names() ;
                   39547:   
                   39548: public:
                   39549:   Ptempl        def ;           // The template definition, for which this is an
                   39550:                             // instantiation.
                   39551:   bool         refp ;        // A flag used to note template references during
                   39552:                             // a C++ definition
                   39553:   void print_error_loc() ;   // Wants to be a static function
                   39554:   // Bind the formals before an instantiation
                   39555:   void bind_formals() ;
                   39556: 
                   39557:   Ptempl_inst canonical_instantiation() {
                   39558:     return ( forward ? forward : this ) ;
                   39559:   }
                   39560: 
                   39561:   // get the class associated with this instantiation
                   39562:   Pclass get_class() { return Pclass(Pbase(tname->tp)->b_name->tp) ;}
                   39563:                              
                   39564:   void instantiate(bool reinstantiate = false) ;
                   39565:   static Ptempl_inst head ;  // Head of the list of active instantiations.
                   39566:   void print_pretty_name() ;
                   39567:   char *mangled_name(char *buffer) ;
                   39568:   // The uninstantiated basetype
                   39569:   Pbase def_basetype() { return def->basep ; } ;
                   39570:   // A general way of determining whether two template instantiations are
                   39571:   // the same
                   39572:   bool  same(Ptempl_inst t) ;
                   39573:   bool copy_hook(Pnode&) ;
                   39574:   // return a copy of the function tree starting with it's name
                   39575:   Pname function_copy(Pfunt fnt, Pcons &templ_refs) ;
                   39576: 
                   39577:   // special check for instantiations used in qualifiers for template function
                   39578:   // member declarations. 
                   39579:   bool check_qualifier(Plist formals) ;
                   39580:   Pname get_parameter(char *s) ;
                   39581: } ;
                   39582: 
                   39583: 
                   39584: 
                   39585: // Experimental debugging toggle
                   39586: extern int zdebug  ;
                   39587: 
                   39588: 
                   39589: // The class node used for template classes.
                   39590: // Rep invariant:
                   39591: // class_base == uninstantiated_template_class ||
                   39592: // class_base  == instantiated_template_class
                   39593: 
                   39594: class templ_classdef : public classdef {
                   39595: public:
                   39596:   Ptempl_inst inst ;              // a pointer to the instantiation; the
                   39597:                                  // instantiation also points back to it via
                   39598:                                   // the tname ->cobj->name->class path
                   39599:   templ_classdef(Ptempl_inst i) ;
                   39600:   Pname unparametrized_tname() { return inst->def->namep ; } 
                   39601:   void instantiate() { inst->instantiate() ; }
                   39602: 
                   39603: } ;
                   39604: 
                   39605: 
                   39606: // Safe accessor functions for navigating through COBJ base classes
                   39607: 
                   39608: extern class_type_enum get_class_base (Pbase b) ;
                   39609: 
                   39610: extern Ptclass get_template_class (Pbase b) ;
                   39611: 
                   39612: extern Ptempl_inst get_templ_inst(Pbase b) ;
                   39613:  
                   39614: 
                   39615: /*
                   39616:    $Log:       template.h,v $
                   39617:  * Revision 1.4  90/04/02  11:31:35  sam
                   39618:  * Made comments current.
                   39619:  * 
                   39620:  * Revision 1.3  90/03/30  18:50:55  sam
                   39621:  * 1) Added the introduce_class_templ member function to the templ_compilation 
                   39622:  * class.
                   39623:  * 2) Rationalized the definition of class templ. Made basic_template be it's
                   39624:  * base class, instead of type. The latter was the base type, simply so that
                   39625:  * it could be stored in a table associating strings with types. Don't have
                   39626:  * to resolve to such kludgery in the PT world.
                   39627:  * 3) Added the member open_instantiations to detect non-terminating
                   39628:  * instantiations
                   39629:  * 
                   39630:  * Revision 1.2  90/03/27  10:16:27  sam
                   39631:  * > Merged in revision 1.13 from the main line of development 
                   39632:  * 
                   39633:  * Revision 1.1  89/11/20  08:50:58  benson
                   39634:  * Initial revision
                   39635:  * 
                   39636:  * Revision 1.11  89/10/16  15:25:00  sam
                   39637:  * use pointer_hash rather than Hash as the type of the correspondence table.
                   39638:  * 
                   39639:  * Revision 1.10  89/09/26  16:44:34  sam
                   39640:  * fix the forward declaration of template classes
                   39641:  * 
                   39642:  * Revision 1.9  89/09/18  16:37:37  sam
                   39643:  * provide for error recovery upon argument mismatch in a template instantiation
                   39644:  * 
                   39645:  * 
                   39646:  * Revision 1.8  89/09/15  09:31:50  benson
                   39647:  * move tree_template.string into the public section.
                   39648:  * 
                   39649:  * Revision 1.7  89/08/30  13:02:12  sam
                   39650:  * added support for dealing with __expressions in class formal templates
                   39651:  * 
                   39652:  * Revision 1.6  89/08/28  09:42:05  sam
                   39653:  * Support for nested references in internal templates. These nested 
                   39654:  * references are instantiated whenever an expansion takes place.
                   39655:  * 
                   39656:  * Revision 1.5  89/08/23  10:26:00  sam
                   39657:  * support for BS style formal syntax. refer to 1.5 templates.c for more 
                   39658:  * detailed comments.
                   39659:  * 
                   39660:  * Revision 1.4  89/08/11  14:57:09  sam
                   39661:  *  implementation of multiple instantiation templates.
                   39662:  * 
                   39663:  * Revision 1.3  89/07/27  11:33:40  sam
                   39664:  * the comments in template.c 1.3 describe the modifications.
                   39665:  * 
                   39666:  * Revision 1.2  89/07/07  14:34:11  sam
                   39667:  * Added the templ_classdef::unparametrized_type_name() function member, as part
                   39668:  * of the base init fix.
                   39669:  * 
                   39670:  * Revision 1.1  89/06/29  09:21:32  benson
                   39671:  * Initial revision
                   39672:  * 
                   39673:  * Revision 1.1  89/06/22  16:29:29  sam
                   39674:  * Initial revision
                   39675:  * 
                   39676: 
                   39677: 
                   39678:    end_log
                   39679: */
                   39680: 
                   39681: 
                   39682: 
                   39683: /*
                   39684:    $Log $
                   39685: 
                   39686: 
                   39687:    end_log
                   39688: */
                   39689: 0707071010112045701004440001630000160000010210100466055411600001000000012452token.h/*ident    "@(#)ctrans:src/token.h 1.4" */
                   39690: /**************************************************************************
                   39691: 
                   39692:        C++ source for cfront, the C++ compiler front-end
                   39693:        written in the computer science research center of Bell Labs
                   39694: 
                   39695:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   39696:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   39697: 
                   39698: token.h:
                   39699: 
                   39700: *****************************************************************************/
                   39701: /*
                   39702: #ifndef PRESAFE
                   39703: extern "C" {
                   39704: #endif
                   39705: 
                   39706: extern void free(char*);                       // alloc.h
                   39707: extern char* malloc(unsigned);
                   39708: extern char* calloc(unsigned, unsigned);
                   39709: 
                   39710: extern strncmp(const char*, const char*, const);       // string.h
                   39711: extern strcmp(const char*, const char*);
                   39712: extern int strlen(const char*);
                   39713: extern char* strcpy(char*, const char*);
                   39714: 
                   39715: #ifdef apollo
                   39716:        extern void set_sbrk_size(int);
                   39717: #endif
                   39718: 
                   39719: #ifndef PRESAFE
                   39720: }
                   39721: #endif
                   39722: */
                   39723: 
                   39724: #include <malloc.h>
                   39725: #include <string.h>
                   39726: #include <stdio.h>
                   39727: 
                   39728: extern void lex_clear();
                   39729: extern void otbl_init();
                   39730: 
                   39731: //#define yylex()      lalex()
                   39732: 
                   39733: #define putstring(s)   fputs(s,out_file)
                   39734: #define putst(s)       (fputs(s,out_file),putc(' ',out_file))
                   39735: #define putch(c)       putc(c,out_file)
                   39736: #define putcat(c,s)    (putc(c,out_file),fputs(s,out_file))
                   39737: 
                   39738:                        /* token numbers for C parser   */
                   39739: 
                   39740: #define MAXTOK 255
                   39741: extern char* keys[MAXTOK+1];
                   39742: 
                   39743: #define EOFTOK 0       /*      EOF     */
                   39744:                        /* keywords in alphabetical order */
                   39745: #define ASM            1
                   39746: #define AUTO           2
                   39747: #define BREAK          3
                   39748: #define CASE           4
                   39749: #define CHAR           5
                   39750: #define CLASS          6
                   39751: #define CONTINUE       7
                   39752: #define DEFAULT                8
                   39753: #define DELETE         9
                   39754: #define DO             10
                   39755: #define DOUBLE         11
                   39756: #define ELSE           12
                   39757: #define ENUM           13
                   39758: #define EXTERN         14
                   39759: #define FLOAT          15
                   39760: #define FOR            16
                   39761: #define FORTRAN                17
                   39762: #define FRIEND         18
                   39763: #define GOTO           19
                   39764: #define IF             20
                   39765: #define INT            21
                   39766: #define LONG           22
                   39767: #define NEW            23
                   39768: #define OPERATOR       24
                   39769: #define PUBLIC         25
                   39770: #define CONST          26
                   39771: #define REGISTER       27
                   39772: #define RETURN         28
                   39773: #define SHORT          29
                   39774: #define SIZEOF         30
                   39775: #define STATIC         31
                   39776: #define STRUCT         32
                   39777: #define SWITCH         33
                   39778: #define THIS           34
                   39779: #define TYPEDEF                35
                   39780: #define UNION          36
                   39781: #define UNSIGNED       37
                   39782: #define VOID           38
                   39783: #define WHILE          39
                   39784: 
                   39785:                        /* operators in priority order (sort of) */
                   39786: #define LP             40
                   39787: #define RP             41
                   39788: #define LB             42
                   39789: #define RB             43
                   39790: #define REF            44
                   39791: #define DOT            45
                   39792: #define NOT            46
                   39793: #define COMPL          47
                   39794: #define INCR           48
                   39795: #define DECR           49
                   39796: #define MUL            50
                   39797: #define DIV            51
                   39798: #define AND            52
                   39799: #define MOD            53
                   39800: #define PLUS           54
                   39801: #define MINUS          55
                   39802: #define LS             56
                   39803: #define RS             57
                   39804: #define LT             58
                   39805: #define LE             59
                   39806: #define GT             60
                   39807: #define GE             61
                   39808: #define EQ             62
                   39809: #define NE             63
                   39810: #define ER             64
                   39811: #define OR             65
                   39812: #define ANDAND         66
                   39813: #define OROR           67
                   39814: #define QUEST          68
                   39815: #define COLON          69
                   39816: #define ASSIGN         70
                   39817: #define CM             71
                   39818: #define SM             72
                   39819: #define LC             73
                   39820: #define RC             74
                   39821: 
                   39822: #define INLINE         75
                   39823: #define OVERLOAD       76
                   39824: #define VIRTUAL                77
                   39825: #define COERCE         78
                   39826: #define PROTECTED      79
                   39827: 
                   39828:                        /* constants etc. */
                   39829: #define ID             80
                   39830: #define STRING         81
                   39831: #define ICON           82
                   39832: #define FCON           83
                   39833: #define CCON           84
                   39834: #define NAME           85
                   39835: #define ZERO           86
                   39836: 
                   39837:                        /* groups of tokens */
                   39838: #define ASOP           90      /* op= */
                   39839: #define RELOP          91      /* LE GE LT GT */
                   39840: #define EQUOP          92      /* EQ NE */
                   39841: #define DIVOP          93      /* DIV MOD */
                   39842: #define SHIFTOP                94      /* LS RS */
                   39843: #define ICOP           95      /* INCR DECR */
                   39844: #define UNOP           96      /* NOT COMPL */
                   39845: #define TYPE           97
                   39846:        /* TYPE =       INT FLOAT CHAR DOUBLE REGISTER STATIC EXTERN AUTO
                   39847:                        LONG SHORT UNSIGNED INLINE FRIEND VIRTUAL */
                   39848: 
                   39849:                        /* new tokens generated by syn() */
                   39850: #define UMINUS         107
                   39851: #define FCT            108
                   39852: #define CALL           109
                   39853: #define VEC            110
                   39854: #define DEREF          111
                   39855: #define ADDROF         112
                   39856: #define CAST           113
                   39857: //#define ENDCAST              122
                   39858: #define FIELD          114
                   39859: #define LABEL          115
                   39860: #define BLOCK          116
                   39861: //#define QUA          117
                   39862: #define DCL            118     /* local declaration statement */
                   39863: #define COBJ           119
                   39864: #define EOBJ           121
                   39865: #define TNAME          123
                   39866: #define ILIST          124
                   39867: #define PTR            125
                   39868: 
                   39869: #define ASPLUS         126
                   39870: #define ASMINUS                127
                   39871: #define ASMUL          128
                   39872: #define ASDIV          129
                   39873: #define ASMOD          130
                   39874: #define ASAND          131
                   39875: #define ASOR           132
                   39876: #define ASER           133
                   39877: #define ASLS           134
                   39878: #define ASRS           135
                   39879: 
                   39880: #define ARG            136
                   39881: #define ARGS           137
                   39882: #define ZTYPE          138
                   39883: #define ARGT           139
                   39884: #define ELIST          140
                   39885: #define ANY            141
                   39886: #define TABLE          142
                   39887: #define LOC            143
                   39888: #define DUMMY          144
                   39889: #define G_ADDROF       145
                   39890: #define G_CALL         146
                   39891: #define G_CM           147
                   39892: #define IVAL           150
                   39893: //#define FVAL         151
                   39894: //#define LVAL         152
                   39895: #define ELLIPSIS       155
                   39896: #define AGGR           156
                   39897: #define VALUE          157     /* constructor call */
                   39898: #define RPTR           158     /* reference */
                   39899: #define HIDDEN         159
                   39900: #define MEM            160
                   39901: #define CTOR           161
                   39902: #define DTOR           162
                   39903: #define CONST_PTR      163
                   39904: #define CONST_RPTR     164
                   39905: #define TEXT           165
                   39906: #define PAIR           166
                   39907: #define ANON           167
                   39908: #define ICALL          168
                   39909: #define ANAME          169
                   39910: #define VOLATILE       170
                   39911: #define SIGNED         171
                   39912: #define UPLUS          172
                   39913: #define MEMPTR         173
                   39914: #define PRIVATE                174
                   39915: #define PR             175     /* PUBLIC PRIVATE or PROTECTED */
                   39916: #define MDOT           177
                   39917: #define TSCOPE         178
                   39918: #define DECL_MARKER    179
                   39919: #define REFMUL         180
                   39920: #define LDOUBLE                181
                   39921: #define LINKAGE         182
                   39922: #define LOCAL          183
                   39923: #define GNEW           184
                   39924: #define TEMPLATE       185
                   39925: #define STAT_INIT      186
                   39926: #define CATCH          187
                   39927: #define GDELETE                188
                   39928: //#define CONVERT      189
                   39929: #define NESTED         190
                   39930: #define TRY            191
                   39931: 
                   39932: // class parameterized types constants
                   39933: #define XVIRT           200 /* class virt */
                   39934: #define XNLIST          201 /* struct name_list */
                   39935: #define XILINE          202
                   39936: #define XIA             203
                   39937: #define STATEMENT        205
                   39938: #define EXPRESSION       206
                   39939: #define SM_PARAM         207 
                   39940: #define TEMPLATE_TEST    208
                   39941: #define PTNAME           209
                   39942: #define NEW_INIT_KLUDGE  210
                   39943: #define XDELETED_NODE    211
                   39944: #define DUMMY_LAST_NODE  212
                   39945: 
                   39946: //#define SYN  1
                   39947: //#define TYP  2
                   39948: //#define SIMPL        3
                   39949: //#define ERROR        4
                   39950: 
                   39951: //#define ICTOR 88
                   39952: //#define IDTOR 89
                   39953: 0707071010112046131004440001630000160000010212340466055422200001600000006724token_names.h/* ident "@(#)ctrans:src/token_names.h       1.2" */
                   39954: struct _token_name { char * string; int val; } token_names [] = {
                   39955:        { "EOFTOK",     0 },
                   39956:        { "ASM",        1 },
                   39957:        { "AUTO",       2 },
                   39958:        { "BREAK",      3 },
                   39959:        { "CASE",       4 },
                   39960:        { "CHAR",       5 },
                   39961:        { "CLASS",      6 },
                   39962:        { "CONTINUE",   7 },
                   39963:        { "DEFAULT",    8 },
                   39964:        { "DELETE",     9 },
                   39965:        { "DO", 10 },
                   39966:        { "DOUBLE",     11 },
                   39967:        { "ELSE",       12 },
                   39968:        { "ENUM",       13 },
                   39969:        { "EXTERN",     14 },
                   39970:        { "FLOAT",      15 },
                   39971:        { "FOR",        16 },
                   39972:        { "FORTRAN",    17 },
                   39973:        { "FRIEND",     18 },
                   39974:        { "GOTO",       19 },
                   39975:        { "IF", 20 },
                   39976:        { "INT",        21 },
                   39977:        { "LONG",       22 },
                   39978:        { "NEW",        23 },
                   39979:        { "OPERATOR",   24 },
                   39980:        { "RETURN",     28 },
                   39981:        { "PUBLIC",     25 },
                   39982:        { "CONST",      26 },
                   39983:        { "REGISTER",   27 },
                   39984:        { "RETURN",     28 },
                   39985:        { "SHORT",      29 },
                   39986:        { "SIZEOF",     30 },
                   39987:        { "STATIC",     31 },
                   39988:        { "STRUCT",     32 },
                   39989:        { "SWITCH",     33 },
                   39990:        { "THIS",       34 },
                   39991:        { "TYPEDEF",    35 },
                   39992:        { "UNION",      36 },
                   39993:        { "UNSIGNED",   37 },
                   39994:        { "VOID",       38 },
                   39995:        { "WHILE",      39 },
                   39996:        { "LP", 40 },
                   39997:        { "RP", 41 },
                   39998:        { "LB", 42 },
                   39999:        { "RB", 43 },
                   40000:        { "REF",        44 },
                   40001:        { "DOT",        45 },
                   40002:        { "NOT",        46 },
                   40003:        { "COMPL",      47 },
                   40004:        { "INCR",       48 },
                   40005:        { "DECR",       49 },
                   40006:        { "MUL",        50 },
                   40007:        { "DIV",        51 },
                   40008:        { "AND",        52 },
                   40009:        { "MOD",        53 },
                   40010:        { "PLUS",       54 },
                   40011:        { "MINUS",      55 },
                   40012:        { "LS", 56 },
                   40013:        { "RS", 57 },
                   40014:        { "LT", 58 },
                   40015:        { "LE", 59 },
                   40016:        { "GT", 60 },
                   40017:        { "GE", 61 },
                   40018:        { "EQ", 62 },
                   40019:        { "NE", 63 },
                   40020:        { "ER", 64 },
                   40021:        { "OR", 65 },
                   40022:        { "ANDAND",     66 },
                   40023:        { "OROR",       67 },
                   40024:        { "QUEST",      68 },
                   40025:        { "COLON",      69 },
                   40026:        { "ASSIGN",     70 },
                   40027:        { "CM", 71 },
                   40028:        { "SM", 72 },
                   40029:        { "LC", 73 },
                   40030:        { "RC", 74 },
                   40031:        { "INLINE",     75 },
                   40032:        { "OVERLOAD",   76 },
                   40033:        { "VIRTUAL",    77 },
                   40034:        { "COERCE",     78 },
                   40035:        { "PROTECTED",  79 },
                   40036:        { "ID", 80 },
                   40037:        { "STRING",     81 },
                   40038:        { "ICON",       82 },
                   40039:        { "FCON",       83 },
                   40040:        { "CCON",       84 },
                   40041:        { "NAME",       85 },
                   40042:        { "ZERO",       86 },
                   40043:        { "ICTOR",      88 },
                   40044:        { "IDTOR",      89 },
                   40045:        { "ASOP",       90 },
                   40046:        { "RELOP",      91 },
                   40047:        { "EQUOP",      92 },
                   40048:        { "DIVOP",      93 },
                   40049:        { "SHIFTOP",    94 },
                   40050:        { "ICOP",       95 },
                   40051:        { "UNOP",       96 },
                   40052:        { "TYPE",       97 },
                   40053:        { "UMINUS",     107 },
                   40054:        { "FCT",        108 },
                   40055:        { "CALL",       109 },
                   40056:        { "VEC",        110 },
                   40057:        { "DEREF",      111 },
                   40058:        { "ADDROF",     112 },
                   40059:        { "CAST",       113 },
                   40060:        { "FIELD",      114 },
                   40061:        { "LABEL",      115 },
                   40062:        { "BLOCK",      116 },
                   40063:        { "QUA",        117 },
                   40064:        { "DCL",        118 },
                   40065:        { "COBJ",       119 },
                   40066:        { "EOBJ",       121 },
                   40067:        { "TNAME",      123 },
                   40068:        { "ILIST",      124 },
                   40069:        { "PTR",        125 },
                   40070:        { "ASPLUS",     126 },
                   40071:        { "ASMINUS",    127 },
                   40072:        { "ASMUL",      128 },
                   40073:        { "ASDIV",      129 },
                   40074:        { "ASMOD",      130 },
                   40075:        { "ASAND",      131 },
                   40076:        { "ASOR",       132 },
                   40077:        { "ASER",       133 },
                   40078:        { "ASLS",       134 },
                   40079:        { "ASRS",       135 },
                   40080:        { "ARG",        136 },
                   40081:        { "KNOWN",      137 },
                   40082:        { "ZTYPE",      138 },
                   40083:        { "ARGT",       139 },
                   40084:        { "ELIST",      140 },
                   40085:        { "ANY",        141 },
                   40086:        { "TABLE",      142 },
                   40087:        { "LOC",        143 },
                   40088:        { "DUMMY",      144 },
                   40089:        { "G_ADDROF",   145 },
                   40090:        { "G_CALL",     146 },
                   40091:        { "G_CM",       147 },
                   40092:        { "IVAL",       150 },
                   40093:        { "FVAL",       151 },
                   40094:        { "LVAL",       152 },
                   40095:        { "ELLIPSIS",   155 },
                   40096:        { "AGGR",       156 },
                   40097:        { "VALUE",      157 },
                   40098:        { "RPTR",       158 },
                   40099:        { "HIDDEN",     159 },
                   40100:        { "MEM",        160 },
                   40101:        { "CTOR",       161 },
                   40102:        { "DTOR",       162 },
                   40103:        { "CONST_PTR",  163 },
                   40104:        { "CONST_RPTR", 164 },
                   40105:        { "TEXT",       165 },
                   40106:        { "PAIR",       166 },
                   40107:        { "ANON",       167 },
                   40108:        { "ICALL",      168 },
                   40109:        { "ANAME",      169 },
                   40110:        { "VOLATILE",   170 },
                   40111:        { "SIGNED",     171 },
                   40112:        { "UPLUS",      172 },
                   40113:        { "MEMPTR",     173 },
                   40114:        { "PRIVATE",    174 },
                   40115:        { "PR", 175 },
                   40116:        { "MDOT",       177 },
                   40117:        { "TSCOPE",     178 },
                   40118:        { "DECL_MARKER",        179 },
                   40119:        { "REFMUL",     180 },
                   40120:        { "LDOUBLE",    181 },
                   40121:        { "LINKAGE",    182 },
                   40122:        { "LOCAL",      183 },
                   40123:        { "GNEW",       184 },
                   40124:        { "TEMPLATE",   185 },
                   40125:        { "STAT_INIT",  186 },
                   40126:        { "CATCH",      187 },
                   40127:        { "GDELETE",    188 },
                   40128:        { "CONVERT",    189 },
                   40129:        { "XVIRT",      200 },
                   40130:        { "XNLIST",     201 },
                   40131:        { "XILINE",     202 },
                   40132:        { "XIA",        203 },
                   40133:        { "STATEMENT",  205 },
                   40134:        { "EXPRESSION", 206 },
                   40135:        { "SM_PARAM",   207 },
                   40136:        { "TEMPLATE_TEST",      208 },
                   40137:        { "PTNAME",     209 },
                   40138:        { "NEW_INIT_KLUDGE", 210 },
                   40139:        { "XDELETED_NODE",      211 },
                   40140:        { "DUMMY_LAST_TOKEN",   212 },
                   40141: };
                   40142: 0707071010112045711004440001630000160000010156650466055412200001100000002515tqueue.h/*ident   "@(#)ctrans:src/tqueue.h        1.3" */
                   40143: /**************************************************************************
                   40144: 
                   40145:         C++ source for cfront, the C++ compiler front-end
                   40146:         written in the computer science research center of Bell Labs
                   40147: 
                   40148:         Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   40149:         THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   40150: 
                   40151: tqueue.h:
                   40152: 
                   40153: *****************************************************************************/
                   40154: 
                   40155: #ifndef EOF
                   40156: #include <stdio.h>
                   40157: #endif
                   40158: 
                   40159: struct toknode {
                   40160:        TOK      tok;                   /* token for parser */
                   40161:        bit      used;                  /* token has been processed by lalex() */
                   40162:        YYSTYPE  retval;                        /* $arg */
                   40163:        loc      place;
                   40164:        toknode* next;
                   40165:        toknode* last;
                   40166:        static toknode* free_toks;
                   40167:        void*   operator new(size_t);
                   40168:        void    operator delete(void*,size_t);
                   40169:                toknode(TOK,YYSTYPE,loc);
                   40170: };
                   40171: extern toknode* front;
                   40172: extern toknode* rear;
                   40173: 
                   40174: extern void addtok(TOK,YYSTYPE,loc);   /* add tok to rear of Q */
                   40175: extern TOK deltok(int);                        /* take tok from front of Q */
                   40176: extern TOK tlex();
                   40177: 
                   40178: // interface to parser
                   40179: extern TOK lalex();
                   40180: extern int yychar;
                   40181: extern YYSTYPE yylval;
                   40182: extern TOK     la_look();
                   40183: extern void    la_backup( TOK, YYSTYPE );
                   40184: extern int     la_cast();
                   40185: extern void    check_decl();
                   40186: extern void    check_cast();
                   40187: extern TOK     lalex();
                   40188: 
                   40189: // save / restore implicit inline functions
                   40190: extern toknode*        save_text();
                   40191: extern void    restore_text();
                   40192: 0707071010112046041004440001630000160000010211700466055416700001400000014274tree_copy.c/* ident "@(#)ctrans:src/tree_copy.c   1.3" */
                   40193: /*
                   40194:        $Source: /usr3/lang/benson/work/stripped_cfront/RCS/tree_copy.c,v $ $RCSfile: tree_copy.c,v $
                   40195:        $Revision: 1.1 $                $Date: 89/11/20 08:51:04 $
                   40196:        $Author: benson $               $Locker:  $
                   40197:        $State: Exp $
                   40198: */
                   40199:  
                   40200: /* utilities to copy pieces of cfront trees. 
                   40201:    what we have here is a somewhat parameterizable
                   40202:    action procedure for the tree walker.
                   40203: 
                   40204:    We may make more versions of this for template expansion
                   40205:    and saving things in files, or we may just make it possible
                   40206:    for this to swing more ways. 
                   40207: */
                   40208: 
                   40209: #include "cfront.h"
                   40210: #include "tree_walk.h"
                   40211: #include "tree_copy.h"
                   40212: #include <memory.h>
                   40213: 
                   40214: /* determine whether "n" is a an already defined type */
                   40215: static unsigned int type_is_defined(Pnode n) {
                   40216:   return (Ptype(n)->defined & DEFINED) ;
                   40217: }
                   40218: 
                   40219: void
                   40220: copy_walker (Pnode& node, node_class cl, void * info, 
                   40221:             tree_node_action& action, int, Pnode, tree_walk_tree&,
                   40222:             int& register_in_hash)
                   40223: {
                   40224:     union {
                   40225:        Pnode node;
                   40226:        Pvirt vr;
                   40227:        Plist list;
                   40228:        Pgen g;
                   40229:        Pvec vc;
                   40230:        Pfct f;
                   40231:        Ptable t;
                   40232:        Pbase  bt;
                   40233:        Pexpr  x;
                   40234:        Pstmt  s;
                   40235:        Penum  e;
                   40236:        Pclass c;
                   40237:        Pbcl   bcl;
                   40238:        Pin    iline;
                   40239:        ia   * ia;
                   40240:        Pname  n;
                   40241:        Pptr p;
                   40242:       } n;
                   40243:     Pnode original_node = node;
                   40244: 
                   40245:     tree_copy_info * tci = (tree_copy_info *)info;
                   40246:     action = tna_continue;
                   40247: 
                   40248:     /* first, give an application-specific hook a shot at the node. */
                   40249: 
                   40250:     tci->check_node(node, cl, action, register_in_hash);
                   40251:     if(action != tna_continue) return;    
                   40252: 
                   40253:     if(node != original_node) { /* a replacement */
                   40254:       n.node = node;
                   40255:     } else /* ok, nothing funny, we just go ahead and copy */
                   40256:       switch (cl) {
                   40257:       default:
                   40258:        break;  
                   40259:       case nc_eof:
                   40260:        n.node = Pnode(tci->malloc(sizeof (node)));
                   40261:        *n.node = *node;
                   40262:        goto Replace;
                   40263: 
                   40264:       case nc_virt:
                   40265:        n.vr = Pvirt(tci->malloc(sizeof(virt)));
                   40266:        *n.vr = *Pvirt(node);
                   40267:        goto Replace;
                   40268: 
                   40269:       case nc_nlist:
                   40270:        n.list = Plist(tci->malloc(sizeof(name_list)));
                   40271:        *n.list = *Plist(node);
                   40272:        goto Replace;
                   40273: 
                   40274:       case nc_gen:
                   40275:        n.g = Pgen(tci->malloc(sizeof(gen)));
                   40276:        *n.g = *Pgen(node);
                   40277:        goto Replace;
                   40278: 
                   40279:       case nc_vec: 
                   40280:        n.vc = Pvec(tci->malloc(sizeof(vec)));
                   40281:        *n.vc = *Pvec(node);
                   40282:        goto Replace;
                   40283: 
                   40284:       case nc_ptr:
                   40285:        n.p = Pptr(tci->malloc(sizeof(ptr)));
                   40286:        *n.p = *Pptr(node);
                   40287:        goto Replace;
                   40288: 
                   40289:       case nc_fct:
                   40290:        n.f = Pfct(tci->malloc(sizeof(fct)));
                   40291:        *n.f = *Pfct(node);
                   40292:        if(n.f->f_signature) {
                   40293:            n.f->f_signature =
                   40294:                (char *)tci->malloc(strlen(Pfct(node)->f_signature)+1);
                   40295:            strcpy(n.f->f_signature, Pfct(node)->f_signature);
                   40296:        };
                   40297:        goto Replace;
                   40298: 
                   40299:       case nc_table:
                   40300:        n.t = Ptable(tci->malloc(sizeof(table)));
                   40301:        *n.t = *Ptable(node);
                   40302:        n.t->entries = (Pname *)tci->malloc(sizeof(Pname) * n.t->size);
                   40303:        memcpy((char *)n.t->entries, (char *)Ptable(node)->entries, n.t->size * sizeof(Pname));
                   40304:        n.t->hashtbl = (short *)tci->malloc(sizeof(short) * n.t->hashsize);
                   40305:        memcpy((char *)n.t->hashtbl, (char *)Ptable(node)->hashtbl, n.t->hashsize * sizeof (short));
                   40306:        goto Replace;
                   40307: 
                   40308:       case nc_basetype:
                   40309:        // Don't copy types that have already been dealt with
                   40310:        if (type_is_defined(node)) {
                   40311:          action = tna_stop ;
                   40312:          return ;
                   40313:        }
                   40314:        n.bt = Pbase(tci->malloc(sizeof(basetype)));
                   40315:        *n.bt = *Pbase(node);
                   40316:        if(n.bt->discriminator(0) == 2 && n.bt->b_linkage) {
                   40317:            n.bt->b_linkage = tci->malloc(strlen(n.bt->b_linkage) + 1);
                   40318:            strcpy(n.bt->b_linkage, Pbase(node)->b_linkage);
                   40319:        }
                   40320:        goto Replace;
                   40321: 
                   40322:       case nc_expr:
                   40323:        // cfront needs identity maintaied for these nodes
                   40324:        if ((node == dummy) || (node == zero)) {
                   40325:          action = tna_stop ;
                   40326:          return ;
                   40327:        }
                   40328:        n.x = Pexpr(tci->malloc(sizeof(expr)));
                   40329:        *n.x = *Pexpr(node);
                   40330:        if(n.x->discriminator(1) == 3 && n.x->string) {
                   40331:            n.x->string = tci->malloc(strlen(n.x->string) + 1);
                   40332:            strcpy(n.x->string, Pexpr(node)->string);
                   40333:        }
                   40334:        if(n.x->discriminator(2) == 3 && n.x->string2) {
                   40335:            n.x->string2 = tci->malloc(strlen(n.x->string2) + 1);
                   40336:            strcpy(n.x->string2, Pexpr(node)->string2);
                   40337:        }
                   40338:        goto Replace;
                   40339: 
                   40340:       case nc_stmt:
                   40341:        n.s = Pstmt(tci->malloc(sizeof(stmt)));
                   40342:        *n.s = *Pstmt(node);
                   40343:        goto Replace;
                   40344: 
                   40345:       case nc_enumdef:
                   40346:        if (type_is_defined(node)) {
                   40347:          action = tna_stop ;
                   40348:          return ;
                   40349:        }
                   40350:        n.e = Penum(tci->malloc(sizeof(enumdef)));
                   40351:        *n.e = *Penum(node);
                   40352:        if(n.e->string) {
                   40353:            n.e->string = tci->malloc(n.e->strlen+1);
                   40354:            strcpy(n.e->string, Penum(node)->string);
                   40355:        }
                   40356:        goto Replace;
                   40357: 
                   40358:       case nc_classdef:
                   40359:        // Don't copy types that have already been dealt with
                   40360:        if (type_is_defined(node)) {
                   40361:          action = tna_stop ;
                   40362:          return ;
                   40363:        }
                   40364:        n.c = Pclass(tci->malloc(sizeof(classdef)));
                   40365:        *n.c = *Pclass(node);
                   40366:        if(n.c->string) {
                   40367:            n.c->string = tci->malloc(strlen(n.c->string)+1);
                   40368:            strcpy(n.c->string, Pclass(node)->string);
                   40369:        }
                   40370:        goto Replace;
                   40371: 
                   40372:       case nc_baseclass:
                   40373:        n.bcl = Pbcl(tci->malloc(sizeof(struct basecl)));
                   40374:        *n.bcl = *Pbcl(node);
                   40375:        goto Replace;
                   40376: 
                   40377:       case nc_iline:
                   40378:        n.iline = Pin(tci->malloc(sizeof(iline)));
                   40379:        *n.iline = *Pin(node);
                   40380:        goto Replace;
                   40381: 
                   40382:       case nc_ia:
                   40383:        n.ia = (ia *)tci->malloc(sizeof(ia));
                   40384:        *n.ia = *(ia *)node;
                   40385:        goto Replace;
                   40386: 
                   40387:       case nc_name:
                   40388:        /* check for globalosity */
                   40389:        if(Pname(node)->string && (node == (node->base == TNAME ? ktbl : gtbl)->look(Pname(node)->string, 0))) {
                   40390:            action = tna_stop;
                   40391:            return;
                   40392:        }
                   40393:        n.n = Pname(tci->malloc(sizeof(name)));
                   40394:        *n.n = *Pname(node);
                   40395: /* First, hack exprosity */
                   40396:        if(n.x->discriminator(1) == 3 && n.n->string) {
                   40397:            n.n->string = tci->malloc(strlen(n.n->string) + 1);
                   40398:            strcpy(n.n->string, Pexpr(node)->string);
                   40399:        }
                   40400:        if(n.x->discriminator(2) == 3 && n.n->string2) {
                   40401:            n.n->string2 = tci->malloc(strlen(n.n->string2) + 1);
                   40402:            strcpy(n.n->string2, Pexpr(node)->string2);
                   40403: /* ok, name stuff */
                   40404:        }
                   40405:        if(n.n->n_anon) {
                   40406:            n.n->n_anon = tci->malloc(strlen(n.n->n_anon)+1);
                   40407:            strcpy(n.n->n_anon, Pname(node)->n_anon);
                   40408:        }
                   40409:        if(n.n->n_template_arg_string) {
                   40410:            n.n->n_template_arg_string =
                   40411:                tci->malloc(strlen(n.n->n_template_arg_string)+1);
                   40412:            strcpy(n.n->n_template_arg_string, Pname(node)->n_template_arg_string);
                   40413:        }
                   40414:     }
                   40415:   Replace:
                   40416:     node = n.node;
                   40417:     action = tna_continue;
                   40418:     return;
                   40419: }
                   40420: 
                   40421: static int call_error (int i, const char * s)
                   40422: {
                   40423:     return error (i, s);
                   40424: }
                   40425: 
                   40426: void
                   40427: copy_tree (Pnode& node, tree_copy_info& tci, Hash * cht)
                   40428: {
                   40429:     tree_walk_control twc;
                   40430: 
                   40431:     twc.call_i_error = 1;
                   40432:     twc.i_error = call_error; /* ... in type of error confuses compiler */
                   40433:     twc.action_proc = copy_walker;
                   40434:     twc.nodes_seen_hash = cht;
                   40435:     twc.callback_info = (void *)&tci;
                   40436: 
                   40437:     walk_tree (twc, node);
                   40438: }
                   40439: 
                   40440: 0707071010112046141004440001630000160000010210160466055422600001400000003011tree_copy.h/* ident "@(#)ctrans:src/tree_copy.h   1.2" */
                   40441: /* -*- Mode: C -*- begin include file tree_copy.H 
                   40442:    argument class for copying trees. */
                   40443: 
                   40444: #include "hash.h"
                   40445: #include "tree_walk.h"
                   40446: 
                   40447: /* The copier procedure expects one of these as its 
                   40448:     info pointer */
                   40449: 
                   40450: class tree_copy_info {
                   40451:   public:
                   40452: /* If non-zero, this procedure is called at each node.
                   40453:    it returns an action. It cannot currently return
                   40454:    a node of a different class and also return an
                   40455:    action other than tna_stop, since the walker won't
                   40456:    notice that the rug has been removed from beneath its feet. 
                   40457:    The procedure must set the last argument to indicate whether
                   40458:    or not to register the node in the hash table and use the
                   40459:    replacement every future time it is encountered.
                   40460: */
                   40461: 
                   40462:     void (* node_hook) (void * info, Pnode&, node_class, tree_node_action&,
                   40463:                        int&);
                   40464: 
                   40465:     /* if this is nonzero it is used to allocate space for
                   40466:        the copies. We don't run constructors since we always
                   40467:        bit copy over the new copy. */
                   40468:     char * (* malloc_hook) (void * info, size_t);
                   40469:     void * hook_info;
                   40470:     tree_copy_info ()
                   40471:        {
                   40472:            hook_info = 0;
                   40473:            node_hook = 0;
                   40474:            malloc_hook = 0;
                   40475:        }; 
                   40476:     char * malloc (size_t s) {
                   40477:        return malloc_hook ? malloc_hook(hook_info, s) : ::malloc (s);
                   40478:     };
                   40479:     void check_node (Pnode& n,
                   40480:                     node_class cl, 
                   40481:                     tree_node_action& action, 
                   40482:                     int& never_see_again) {
                   40483:        if(node_hook)
                   40484:            node_hook(hook_info, n, cl, action, never_see_again);
                   40485:     };
                   40486: };
                   40487: 
                   40488: void copy_tree (Pnode& n, tree_copy_info& tci, Hash * cht = 0);
                   40489: 
                   40490: /* End tree_copy.H */
                   40491: 
                   40492: 0707071010112046161004440001630000160000010213300466055423500001400000061200tree_dump.c/* ident "@(#)ctrans:src/tree_dump.c   1.2" */
                   40493: /* -*- Mode:C++ -*- */
                   40494: /* tree_dump.C -- utilities for displaying the cfront tree. */
                   40495: /* BIM 890530 */
                   40496: /* rewritten 890712 to use the tree-walking facilities */
                   40497: 
                   40498: /*
                   40499:        $Source: /usr3/lang/benson/work/stripped_cfront/RCS/tree_dump.c,v $ $RCSfile: tree_dump.c,v $
                   40500:        $Revision: 1.1 $                $Date: 89/11/20 08:50:22 $
                   40501:        $Author: benson $               $Locker:  $
                   40502:        $State: Exp $
                   40503: 
                   40504: 
                   40505: */
                   40506: 
                   40507: #include "tree_dump.h"
                   40508: #include <stdio.h>
                   40509: #include <malloc.h>
                   40510: #include "template.h"
                   40511: #include "token_names.h"
                   40512: 
                   40513: const int Indent_Increment = 4;
                   40514: static char badnamebuf[100];
                   40515: 
                   40516: char *
                   40517: token_name(TOK t)
                   40518: {
                   40519:     char * bnb = badnamebuf;
                   40520: 
                   40521:     if((int) t == -1) return "-1";
                   40522:     if(t > DUMMY_LAST_NODE) {
                   40523: bad:
                   40524:        printf_to_string(bnb, sizeof(badnamebuf), 
                   40525:                         "<unknown token %d>", (int) t);
                   40526:        return bnb;
                   40527:     } 
                   40528:     int x;
                   40529:     for (x = 0; x < DUMMY_LAST_NODE; x++) {
                   40530:        if(token_names[x].val == t) return token_names[x].string;
                   40531:     }
                   40532:     goto bad;
                   40533: }
                   40534: 
                   40535: class displayer{
                   40536:   public:
                   40537:     dcn_arg * arg;
                   40538:     Pnode node;
                   40539:     Pnode node_address;
                   40540:     displayer (dcn_arg& d) { arg = &d; indent = 0; print_null_values = 0; };
                   40541:     void do_node (Pnode& node, node_class cl, tree_node_action& action, int depth, Pnode);
                   40542:   private:
                   40543:     enum ppc {print_ptr_copy = 0, print_ptr_copied = 1};
                   40544:     int indent;
                   40545:     int err;
                   40546:     int print_null_values;
                   40547:     void printf (const char *, ...);
                   40548:     void catprintf (const char *, ...);
                   40549:     void print_ptr (const char *, Pnode);
                   40550:     void print_ptr (Pnode, ppc = print_ptr_copy);
                   40551:     void minimal ();
                   40552:     void a_basetype ();
                   40553:     void a_basecl() ;
                   40554:     void a_type() ;
                   40555:     void a_node() ;
                   40556:     void a_name ();
                   40557:     void a_expr (int from_name = 0);
                   40558:     void a_fct ();
                   40559:     void a_stmt ();
                   40560:     void a_enumdef ();
                   40561:     void a_table();
                   40562:     void a_classdef ();
                   40563:     void a_gen ();
                   40564:     void a_vec ();
                   40565:     void a_ptr ();
                   40566:     void a_virt ();
                   40567:     void a_nlist ();
                   40568:     void a_iline ();
                   40569:     void a_elist ();
                   40570:     void a_ia ();
                   40571:     void a_by_name ();
                   40572:     void print_loc(loc&);
                   40573:     void * display_address () { return node_address; }
                   40574:     void fetch (void * addr, unsigned long length, void *& taddr);
                   40575:     void fetch_string (void * addr, unsigned long length, void *& taddr);
                   40576:     void free_fetched(void *);
                   40577:     void flag (int, const char *);
                   40578:     void print_string (const char *, void *);
                   40579:     void print_string_brief (void *);
                   40580:     void null_field (const char *);
                   40581:     void nz_printf(const char *format, const int i) ;
                   40582:     void nz_printf(const char *format, const char *p) ;
                   40583:     void nz_printf(const char *format, const long l) ;
                   40584:     void ind();
                   40585: };
                   40586: 
                   40587: const char many_spaces[] = "                                                                                                                                                                                                        ";
                   40588: 
                   40589: inline void
                   40590: displayer::ind()
                   40591: {
                   40592:     arg->output_stream->write(many_spaces, indent);
                   40593: }
                   40594: 
                   40595: /* call me for full lines */
                   40596: 
                   40597: void
                   40598: displayer::printf (const char * format, ...)
                   40599: {
                   40600:     va_list args;
                   40601:     va_start(args, format);
                   40602: 
                   40603:     ind();
                   40604:     vostream_printf (format, args, *arg->output_stream);
                   40605:     arg->output_stream->write("\n", 1);
                   40606:     va_end (args);
                   40607: }
                   40608: 
                   40609: void
                   40610: displayer::catprintf (const char * format, ...)
                   40611: {
                   40612:     va_list args;
                   40613:     va_start(args, format);
                   40614: 
                   40615:     vostream_printf (format, args, *arg->output_stream);
                   40616:     va_end (args);
                   40617: }
                   40618: 
                   40619: void
                   40620: displayer::minimal ()
                   40621: {
                   40622:     print_ptr(node, print_ptr_copied);
                   40623: }    
                   40624: 
                   40625: void
                   40626: displayer::print_ptr(const char * label, Pnode node)
                   40627: {
                   40628:     if(node || print_null_values) {
                   40629:        ind();
                   40630:        catprintf("%s:\t", label);
                   40631:        print_ptr(node);
                   40632:        catprintf("\n");
                   40633:     }
                   40634: }
                   40635: 
                   40636: 
                   40637: void
                   40638: displayer::print_ptr(Pnode node, ppc copy_ptr)
                   40639: {
                   40640:     void * string = 0;
                   40641:     void * ncopy;
                   40642:     void * na = (void *)node;
                   40643: 
                   40644:     if(node) {
                   40645: 
                   40646:        if(copy_ptr == print_ptr_copy) {
                   40647:            fetch(na, sizeof(node), ncopy);
                   40648:            node = Pnode(ncopy);
                   40649:        } else ncopy = node;
                   40650: 
                   40651:        switch(node->base) {
                   40652:        case CLASS:
                   40653:            free_fetched(ncopy);
                   40654:            fetch(na, sizeof(classdef),ncopy);
                   40655:            node = Pnode(ncopy);
                   40656:            string = Pclass(node)->string;
                   40657:            break;
                   40658:        case ENUM:
                   40659:            free_fetched(ncopy);
                   40660:            fetch(na, sizeof(enumdef),ncopy);
                   40661:            node = Pnode(ncopy);
                   40662:            string = Penum(node)->string;
                   40663:            break;
                   40664:        case NAME:
                   40665:        case TNAME:
                   40666:        case PUBLIC:
                   40667:        case PROTECTED:
                   40668:            if(!node->baseclass) {
                   40669:                free_fetched(ncopy);
                   40670:                fetch(na, sizeof(name),ncopy);
                   40671:                node = Pnode(ncopy);
                   40672:                string = Pname(node)->string;
                   40673:            }
                   40674:            break;
                   40675:        }
                   40676:        if(string) {
                   40677:            catprintf("<%s |0x%p ", token_name(node->base), na);
                   40678:            print_string_brief(string);
                   40679:            catprintf(">");
                   40680:        }
                   40681:        else catprintf("<%s |0x%p>", token_name(node->base), na);
                   40682:        free_fetched (ncopy);
                   40683:     }
                   40684:     else catprintf("Null");
                   40685: }
                   40686: 
                   40687: void
                   40688: displayer::do_node (Pnode& n, node_class cl, tree_node_action& action,
                   40689:         int depth, Pnode na)
                   40690: {
                   40691:     int forced_min = 0;
                   40692:     int printed_min = 0;
                   40693:     int prune = 0;
                   40694: 
                   40695:     switch(cl) {
                   40696:       case nc_table:
                   40697:        if(depth > 0 && !arg->walk_tables)prune = 1;
                   40698:       case nc_fct:
                   40699:       case nc_classdef:
                   40700:       case nc_enumdef:
                   40701:        if(arg->stop_at_top && depth > 1) prune = 1;
                   40702:        break;
                   40703:     }
                   40704: 
                   40705:     if((arg->max_depth > 0) && (depth >= arg->max_depth))
                   40706:        prune = 1;
                   40707: 
                   40708:     if(prune || arg->max_depth == 0)
                   40709:        action = tna_stop;
                   40710:     else action = tna_continue;
                   40711: 
                   40712:     node = n;
                   40713:     node_address = na;
                   40714: 
                   40715:     if(arg->verbose == dt_brief || prune) {
                   40716:        printed_min = 1;
                   40717:        minimal();
                   40718:     }
                   40719:     else {
                   40720:        switch(cl)
                   40721:            {
                   40722:              default:
                   40723:            case nc_unused:
                   40724:                ostream_printf(*arg->error_stream, "Unknown node %d\n", node->base);
                   40725:                forced_min = 1;
                   40726: 
                   40727:            case nc_eof:
                   40728:                minimal();
                   40729:                printed_min = 1;
                   40730:                break;
                   40731: 
                   40732:            case nc_virt:
                   40733:                a_virt ();
                   40734:                break;
                   40735: 
                   40736:            case nc_nlist:
                   40737:                a_nlist();
                   40738:                break;
                   40739: 
                   40740:            case nc_gen:
                   40741:                a_gen();
                   40742:                break;
                   40743: 
                   40744:            case nc_vec:
                   40745:                a_vec();
                   40746:                break;
                   40747: 
                   40748:            case nc_ptr:
                   40749:                a_ptr();
                   40750:                break;
                   40751: 
                   40752:            case nc_fct:
                   40753:                a_fct();
                   40754:                break;
                   40755: 
                   40756:            case nc_table:
                   40757:                a_table();
                   40758:                break;
                   40759: 
                   40760:            case nc_basetype:
                   40761:                a_basetype();
                   40762:                break;
                   40763: 
                   40764:            case nc_name:
                   40765:                a_name();
                   40766:                break;
                   40767: 
                   40768:            case nc_expr:
                   40769:                a_expr();
                   40770:                break;
                   40771: 
                   40772:            case nc_stmt:
                   40773:                a_stmt();
                   40774:                break;
                   40775: 
                   40776:            case nc_enumdef:
                   40777:                a_enumdef();
                   40778:                break;
                   40779: 
                   40780:            case nc_classdef:
                   40781:                a_classdef();
                   40782:                break;
                   40783: 
                   40784:            case nc_baseclass:
                   40785:                a_basecl ();
                   40786:                break;
                   40787: 
                   40788:            case nc_iline:
                   40789:                a_iline();
                   40790:                break;
                   40791: 
                   40792:            case nc_ia:
                   40793:                a_ia();
                   40794:                break;
                   40795: 
                   40796:            }
                   40797:        if(printed_min) catprintf(">");
                   40798:     }
                   40799: }
                   40800: 
                   40801: 
                   40802: void
                   40803: displayer::flag(int f, const char * n)
                   40804: {
                   40805:     if(f)catprintf("%s", n);
                   40806: }
                   40807: 
                   40808: void
                   40809: displayer::free_fetched (void * addr)
                   40810: {
                   40811:     if (arg->fetcher != null_tfp) /* not in the same address space. */
                   40812:        free ((char *)addr);
                   40813: }    
                   40814: 
                   40815: 
                   40816: void
                   40817: displayer::fetch (void * addr, unsigned long length, void *& taddr)
                   40818: {
                   40819:     if (arg->fetcher == null_tfp) {    /* in the same address space. */
                   40820:        taddr = addr;
                   40821:        err = 0;
                   40822:     } else {
                   40823:        taddr = (void *)malloc ((unsigned int)length);
                   40824:        err = arg->fetcher (arg->fetcher_info,
                   40825:                            addr,
                   40826:                            length,
                   40827:                            0,
                   40828:                            taddr);
                   40829:     }
                   40830: }
                   40831: 
                   40832: void
                   40833: displayer::fetch_string (void * addr, unsigned long length, void *& taddr)
                   40834: {
                   40835:     if (arg->fetcher == null_tfp) {    /* in the same address space. */
                   40836:        taddr = addr;
                   40837:        err = 0;
                   40838:     } else {
                   40839:        taddr = (void *)malloc ((unsigned int)length);
                   40840:        err = arg->fetcher (arg->fetcher_info,
                   40841:                            addr,
                   40842:                            length,
                   40843:                            1,
                   40844:                            taddr);
                   40845:     }
                   40846: }
                   40847: 
                   40848: /* Print the field, only if it has a non_zero value, or requested to print */
                   40849: /* always */
                   40850: void
                   40851: displayer::nz_printf(const char *format, const int i)
                   40852: {
                   40853:     if (i || print_null_values) {
                   40854:        printf(format, i) ;
                   40855:     }
                   40856: } 
                   40857: 
                   40858: void
                   40859: displayer::nz_printf(const char *format, const char *p)
                   40860: {
                   40861:     if (p || print_null_values) {
                   40862:        printf(format, (p ? p : "0")) ;
                   40863:     }
                   40864: } 
                   40865: 
                   40866: 
                   40867: void 
                   40868: displayer::nz_printf(const char *format, const long i)
                   40869: {
                   40870:     if (i || print_null_values) {
                   40871:        printf(format, i) ;
                   40872:     }
                   40873: } 
                   40874: 
                   40875: void 
                   40876: displayer::a_node() 
                   40877: {
                   40878:     struct node &n = *node ;
                   40879: 
                   40880:     nz_printf("$node", n.permanent);
                   40881: //    nz_printf("n_key:\t%d", (int)n.n_key) ;
                   40882:     nz_printf("permanent:\t%d", n.permanent) ;
                   40883:     nz_printf("baseclass:\t%d", n.baseclass) ;
                   40884: }
                   40885:   
                   40886:   
                   40887: 
                   40888: void 
                   40889: displayer::a_type()
                   40890: {
                   40891:     struct type& t = *Ptype(node);
                   40892:     int show_up =  t.defined  /* || t.inline_temp_index != 0 */;
                   40893: 
                   40894:     if(show_up) {
                   40895:        printf("$type") ;
                   40896:        nz_printf("defined:\t%d", t.defined) ;
                   40897:        // nz_printf("inline_temp_index:\t%d", t.inline_temp_index);
                   40898:        indent += Indent_Increment;
                   40899:     }
                   40900:     a_node();
                   40901:     if(show_up) indent -= Indent_Increment;
                   40902: } 
                   40903:   
                   40904: 
                   40905:   
                   40906:   
                   40907: 
                   40908: void
                   40909: displayer::null_field(const char * name)
                   40910: {
                   40911:   nz_printf( "%s:\t0", name);
                   40912: }
                   40913: 
                   40914: 
                   40915: void 
                   40916: displayer::a_basecl()
                   40917: {
                   40918:     struct basecl& bc = *Pbcl(node);
                   40919: 
                   40920:     printf("$basecl %s |0x%p",
                   40921:           token_name(node->base),
                   40922:           node_address);
                   40923:     
                   40924:     nz_printf ("ppp:\t%s", token_name(bc.ppp)) ;
                   40925:     nz_printf ("allocated:\t%d", bc.allocated) ;
                   40926:     nz_printf ("promoted:\t%d", bc.promoted) ;
                   40927:     print_ptr("bclass", bc.bclass);
                   40928:     nz_printf ("ptr_offset:\t%d", bc.ptr_offset) ;
                   40929:     nz_printf ("obj_offset:\t%d", bc.obj_offset) ;
                   40930:     indent += Indent_Increment;
                   40931:     a_node();                  /* do the supertype. */
                   40932:     indent -= Indent_Increment;
                   40933: }
                   40934: 
                   40935: 
                   40936: 
                   40937: 
                   40938: void
                   40939: displayer::a_basetype ()
                   40940: {
                   40941:     struct basetype& bt = *Pbase(node);
                   40942:   
                   40943:     printf("$basetype %s |0x%p",
                   40944:           token_name(node->base),
                   40945:           node_address);
                   40946: 
                   40947:     ind();
                   40948:     catprintf("Flags:\t");
                   40949:     flag(bt.b_unsigned, "unsigned ");
                   40950:     flag(bt.b_signed, "signed ");
                   40951:     flag(bt.b_volatile, "volatile ");
                   40952:     flag(bt.b_const, "const ");
                   40953:     flag(bt.b_typedef, "typedef ");
                   40954:     flag(bt.b_virtual, "virtual ");
                   40955:     flag(bt.b_short, "short ");
                   40956:     flag(bt.b_long, "long ");
                   40957:     catprintf("\n");
                   40958:     nz_printf( "b_bits:\t%d", bt.b_bits);
                   40959:     nz_printf( "b_offset:\t%d", bt.b_offset);
                   40960:     nz_printf( "b_sto:\t%s", bt.b_sto ? token_name(bt.b_sto) : 0);
                   40961:     switch(bt.discriminator(0)) {
                   40962:       case 1:
                   40963:        print_ptr("b_fieldtype", bt.b_fieldtype);
                   40964:        break;
                   40965:       case 2:
                   40966:        nz_printf( "b_linkage:\t%s", bt.b_linkage ? "C" : "0(C++)");
                   40967:     }
                   40968: 
                   40969:     print_ptr("b_name", bt.b_name);
                   40970:     print_ptr("b_table", bt.b_table);
                   40971:     // print_ptr("b_field", bt.b_field);
                   40972:     print_ptr("b_xname", bt.b_xname);
                   40973: 
                   40974:     indent += Indent_Increment;
                   40975:     a_type();                  /* do the supertype. */
                   40976:     indent -= Indent_Increment;
                   40977:     
                   40978: }
                   40979: 
                   40980: void
                   40981: displayer::print_loc(loc& loc)
                   40982: {
                   40983:   catprintf("file %d line %d", (int)loc.file, (int)loc.line);
                   40984: }
                   40985: 
                   40986: 
                   40987: void
                   40988: displayer::print_string_brief(void * addr)
                   40989: {
                   40990:   void * tmp;
                   40991:   
                   40992:   fetch_string (addr, 1000, tmp);
                   40993:   *arg->output_stream << (char *)tmp;
                   40994:   free_fetched (tmp);
                   40995: }
                   40996: 
                   40997: void
                   40998: displayer::print_string(const char * label, void * addr)
                   40999: {
                   41000:   ind();
                   41001:   catprintf("%s:\t", label);
                   41002:   print_string_brief(addr);
                   41003:   *arg->output_stream << "\n";
                   41004: }
                   41005: 
                   41006: void
                   41007: displayer::a_expr(int from_name)
                   41008: {
                   41009:     struct expr& e = *Pexpr(node);
                   41010:   
                   41011:     if(from_name) printf("$expr");
                   41012:     else printf("$expr %s |0x%p",
                   41013:                token_name(node->base),
                   41014:                node_address);
                   41015:   
                   41016:     print_ptr("tp", e.tp);
                   41017:   
                   41018:     switch(e.discriminator(1)) {
                   41019:       case 0: break;
                   41020:       case 1:
                   41021:        print_ptr("e1", e.e1);
                   41022:        break;
                   41023:       case 2:
                   41024:        printf("i1:\t%ld", e.i1);
                   41025:        break;
                   41026:       case 3:
                   41027:        print_string("string", (void *)e.string);
                   41028:     }
                   41029: 
                   41030:     switch(e.discriminator(2)) {
                   41031:       case 0: break;
                   41032:       case 1:
                   41033:        print_ptr("e2", e.e2);
                   41034:        break;
                   41035:       case 2:
                   41036:        printf("i2:\t%ld", e.i2);
                   41037:        break;
                   41038:       case 3:
                   41039:        print_string("string2", (void *)e.string2);
                   41040:        break;
                   41041:       case 4:
                   41042:        print_ptr("n_initializer", e.n_initializer);
                   41043:     }
                   41044: 
                   41045:     switch(e.discriminator(3)) {
                   41046:       case 0:
                   41047:        break;
                   41048:       case 1: print_ptr ("tp2", e.tp2); break;
                   41049:       case 2: print_ptr ("fct_name", e.fct_name); break;
                   41050:       case 3: print_ptr ("cond", e.cond); break;
                   41051:       case 4: print_ptr ("mem", e.mem); break;
                   41052:       case 5: print_ptr ("as_type", e.as_type); break;
                   41053:       case 6: print_ptr ("n_table", e.n_table); break;
                   41054:       case 7: print_ptr ("il", e.il); break;
                   41055:       case 8: print_ptr ("query_this", e.query_this); break;
                   41056:     }
                   41057: 
                   41058:   indent += Indent_Increment;
                   41059:   a_node();
                   41060:   indent -= Indent_Increment;
                   41061: 
                   41062: }
                   41063: 
                   41064: void
                   41065: displayer::a_name()
                   41066: {
                   41067:     struct name& n = *Pname(node);
                   41068: 
                   41069: 
                   41070:     ind();
                   41071:     catprintf("$name %s |0x%p ",
                   41072:              token_name(node->base),
                   41073:              node_address);
                   41074:     print_string_brief((void *)n.string);
                   41075:     *arg->output_stream << "\n";
                   41076: 
                   41077:     nz_printf("n_key:\t%d", (int)n.n_key) ;
                   41078:     nz_printf( "n_oper:\t\t%s", n.n_oper ?
                   41079:              token_name(n.n_oper) : 0);
                   41080:     nz_printf( "n_sto:\t\t%s", n.n_sto ?
                   41081:              token_name(n.n_sto) : 0);
                   41082:     nz_printf( "n_stclass:\t%s", n.n_stclass ?
                   41083:              token_name(n.n_stclass) : 0);
                   41084:     nz_printf( "n_scope:\t%s", n.n_scope ?
                   41085:              token_name(n.n_scope) : 0);
                   41086:     nz_printf( "n_union:\t%d", n.n_union);
                   41087:     nz_printf( "n_evaluated:\t%d", n.n_evaluated);
                   41088:     nz_printf( "n_xref:\t\t%d", n.n_xref);
                   41089:     nz_printf( "lex_level:\t%d", n.lex_level);
                   41090:     nz_printf( "n_protect:\t%s", n.n_protect ?
                   41091:              token_name(n.n_protect) : 0);
                   41092:     if (n.n_dcl_printed || print_null_values) {
                   41093:        ind();
                   41094:        catprintf("n_dcl_printed:\t%d", n.n_dcl_printed);
                   41095: 
                   41096:        switch(n.n_dcl_printed)
                   41097:            {
                   41098:            case 0:
                   41099:                catprintf("(not)\n");
                   41100:                break;
                   41101:            case 1:
                   41102:                printf("(declaration)\n");
                   41103:                break;
                   41104:            case 2:
                   41105:                printf("(definition)\n");
                   41106:                break;
                   41107:            }
                   41108:        
                   41109:     }
                   41110:     if(n.n_template_arg) {
                   41111:        ind();
                   41112:        catprintf( "n_template_arg:\t");
                   41113:        switch(n.n_template_arg) 
                   41114:            { 
                   41115:            case template_type_formal:
                   41116:                catprintf("template_type_formal\n");
                   41117:                break;
                   41118:            case template_expr_formal:
                   41119:                catprintf("template_expr_formal\n");
                   41120:                break;
                   41121:            case template_stmt_tree_formal:
                   41122:                catprintf("template_stmt_formal\n");
                   41123:                break;
                   41124:            case template_expr_tree_formal:
                   41125:                catprintf("template_expr_tree_formal\n");
                   41126:                break;
                   41127:            case template_actual_arg_dummy:
                   41128:                catprintf("template_actual_arg_dummy\n");
                   41129:                break;
                   41130:            } ;
                   41131:     }
                   41132:     nz_printf( "n_addr_taken:\t%d", n.n_addr_taken);
                   41133:     nz_printf( "n_used:\t\t%d", n.n_used);
                   41134:     nz_printf( "n_assigned_to:\t%d", n.n_assigned_to);
                   41135:     ind();
                   41136:     catprintf("loc:\t\t");
                   41137:     print_loc(n.where);
                   41138:     catprintf("\n");
                   41139:     nz_printf( "n_offset:\t%d", n.n_offset);
                   41140:     // if(n.output_string) { print_string("output_string", (void *)n.output_string); }
                   41141:     nz_printf( "n_val:\t\t%ld", n.n_val);
                   41142: 
                   41143:     print_ptr("n_list", n.n_list);
                   41144:     print_ptr("n_tbl_list", n.n_tbl_list);
                   41145:     if(n.n_gen_fct_name)
                   41146:        print_string("n_gen_fct_name", n.n_gen_fct_name);
                   41147:     if(n.n_template_arg_string) {
                   41148:        print_string("n_template_arg_string",
                   41149:                     n.n_template_arg_string);
                   41150:     }
                   41151:     switch(n.discriminator(0)) {
                   41152:     case 2: print_ptr("n_realscope", n.n_realscope); break;
                   41153:     case 1: print_ptr("n_qualifier", n.n_qualifier); break;
                   41154:     }
                   41155:     nz_printf("n_val:\t%ld", n.n_val);
                   41156: 
                   41157:     indent += Indent_Increment;
                   41158:     a_expr(1);                 /* do the supertype. */
                   41159:     indent -= Indent_Increment;
                   41160: }
                   41161: 
                   41162: void
                   41163: displayer::a_fct()
                   41164: {
                   41165:     struct fct& f = *Pfct(node);
                   41166: 
                   41167:     printf("$fct %s |0x%p",
                   41168:           token_name(node->base),
                   41169:           node_address);
                   41170: 
                   41171: 
                   41172:     printf("nargs:\t\t%d", f.nargs);
                   41173:     printf("nargs_known:\t%d%s", f.nargs_known,
                   41174:           f.nargs_known == 0 ? " UNKNOWN" :
                   41175:           (f.nargs_known == 1 ? " KNOWN" :
                   41176:            (f.nargs_known == ELLIPSIS ? "ELLIPSIS" : "" )));
                   41177:     nz_printf( "f_vdef:\t\t%d", f.f_vdef);
                   41178:     printf("f_inline:\t%d%s", f.f_inline,
                   41179:           f.f_inline == 0 ? "" :
                   41180:           f.f_inline == 1 ? " inline" :
                   41181:           f.f_inline == 2 ? " inline in expansion" : "");
                   41182:     nz_printf( "f_const:\t\t%d", f.f_const);
                   41183:     nz_printf( "f_static:\t\t%d", f.f_static);
                   41184:     nz_printf( "f_virtual:\t%d", f.f_virtual);
                   41185:     nz_printf( "f_imeasure:\t%d", f.f_imeasure);
                   41186:     print_string("f_signature", (void *)f.f_signature);
                   41187: 
                   41188:     print_ptr("returns", f.returns);
                   41189:     print_ptr("argtype", f.argtype);
                   41190:     print_ptr("s_returns", f.s_returns);
                   41191:     print_ptr("f_this", f.f_this);
                   41192:     print_ptr("memof", f.memof);
                   41193:     print_ptr("body", f.body);
                   41194:     print_ptr("f_init", f.f_init);
                   41195:     print_ptr("f_expr", f.f_expr);
                   41196:     print_ptr("last_expanded", f.last_expanded);
                   41197:     print_ptr("f_result", f.f_result);
                   41198:     print_ptr("f_args", f.f_args);
                   41199:     print_ptr("local_classes", f.local_class);
                   41200:     
                   41201:     indent += Indent_Increment;
                   41202:     a_type();                  /* do the supertype. */
                   41203:     indent -= Indent_Increment;
                   41204: }
                   41205: 
                   41206: void
                   41207: displayer::a_stmt ()
                   41208: {
                   41209:     struct stmt& s = *Pstmt(node);
                   41210: 
                   41211:     ind();
                   41212:     catprintf("$stmt %s |0x%p ",
                   41213:              token_name(node->base),
                   41214:              node_address);
                   41215:     print_loc(s.where);
                   41216:     *arg->output_stream << "\n";
                   41217: 
                   41218:     ind();
                   41219:     *arg->output_stream << "where:\t";
                   41220:     print_loc(s.where);
                   41221:     *arg->output_stream << "\n";
                   41222: 
                   41223:     print_ptr("s", s.s);
                   41224:     print_ptr("s_list", s.s_list);
                   41225:     print_ptr("memtbl", s.memtbl);
                   41226:     switch(s.discriminator(0)) {
                   41227:       case 1: print_ptr("d", s.d); break;
                   41228:       case 2: print_ptr("e2", s.e2); break;
                   41229:       case 3: print_ptr("has_default", s.has_default); break;
                   41230:       case 4: nz_printf("case_value:\t0x%x", s.case_value);
                   41231:       case 5: print_ptr("ret_tp", s.ret_tp); break;
                   41232:     }
                   41233:     switch(s.discriminator(1)) {
                   41234:       case 1: print_ptr("e", s.e); break;
                   41235:       case 2: nz_printf("own_tbl:\t%d", s.own_tbl); break;
                   41236:       case 3: print_ptr("s2", s.s2); break;
                   41237:     }
                   41238: 
                   41239:     switch(s.discriminator(2)) {
                   41240:        case 1: print_ptr("for_init", s.for_init); break;
                   41241:        case 2: print_ptr("else_stmt",s.for_init); break;
                   41242:        case 3: print_ptr("case_list", s.case_list); break;
                   41243:     }
                   41244: }
                   41245: 
                   41246: void
                   41247: displayer::a_enumdef ()
                   41248: {
                   41249:    struct enumdef& e = *Penum(node);
                   41250: 
                   41251:    printf("$enumdef %s |0x%p",
                   41252:          token_name(node->base),
                   41253:          node_address);
                   41254: 
                   41255:    nz_printf( "e_body:\t\t%d", e.e_body);
                   41256:    nz_printf( "no_of_enumerators: %d", 
                   41257:             e.no_of_enumerators);
                   41258:    nz_printf( "strlen:\t%d", e.strlen);
                   41259:    print_string ("string", (void *)e.string);
                   41260: 
                   41261:    print_ptr("mem", e.mem);
                   41262:    print_ptr("e_type", e.e_type);
                   41263:    indent += Indent_Increment;
                   41264:    a_type();                   /* do the supertype. */
                   41265:    indent -= Indent_Increment;
                   41266: }
                   41267: 
                   41268: void
                   41269: displayer::a_classdef ()
                   41270: {
                   41271:     struct classdef& c = *Pclass(node);
                   41272: 
                   41273:     ind();
                   41274:     catprintf("$classdef %s |0x%p ",
                   41275:              token_name(node->base),
                   41276:              node_address);
                   41277:     print_string_brief(c.string);
                   41278:     *arg->output_stream << "\n";
                   41279:     ind();
                   41280:     catprintf("class_base:\t");
                   41281:     switch(c.class_base) 
                   41282:        { 
                   41283:          case vanilla_class:
                   41284:            *arg->output_stream << "vanilla_class\n";
                   41285:            break;
                   41286:          case template_class:
                   41287:            *arg->output_stream << "template_class\n";
                   41288: Template_Class:            
                   41289:            nz_printf("inst:\t\t%p", (int)Ptclass(&c)->inst);
                   41290:            break;
                   41291:          case instantiated_template_class:
                   41292:            *arg->output_stream << "instantiated_template_class\n";
                   41293:            goto Template_Class;
                   41294:          case uninstantiated_template_class:
                   41295:            *arg->output_stream << "uninstantiated_template_class\n";
                   41296:            goto Template_Class;
                   41297:          case relationship_class:
                   41298:            *arg->output_stream << "relationship_class\n";
                   41299:            break;
                   41300:          case defining_class:
                   41301:            *arg->output_stream << "defining_class\n";
                   41302:            break;
                   41303:        }
                   41304: 
                   41305:     nz_printf( "c_body:\t\t%d", c.c_body);
                   41306:     printf("csu:\t\t%s", 
                   41307:           token_name(c.csu));
                   41308:     nz_printf( "obj_align:\t%d", c.obj_align);
                   41309:     if(c.c_xref) {
                   41310:        ind();
                   41311:        catprintf( "c_xref:\t%x", c.c_xref);
                   41312:        flag(c.c_xref & 1, "has-vptr ");
                   41313:        flag(c.c_xref & 2, "X(X&)-defined ");
                   41314:        flag(c.c_xref & 4, "operator=(X&)-defined ");
                   41315:        flag(c.c_xref & 8, "has-vbaseptr(s) ");
                   41316:        *arg->output_stream << "\n";
                   41317:     }
                   41318:     nz_printf( "virt_count:\t%d", c.virt_count);
                   41319:     nz_printf( "virt_merge:\t%d", c.virt_merge);
                   41320:     nz_printf( "c_abstract:\t%d", c.c_abstract);
                   41321:     nz_printf( "has_vvtab:\t%d", c.has_vvtab);
                   41322:     nz_printf( "strlen:\t%d", c.strlen);
                   41323:     print_string ("string", (void *)c.string);
                   41324:     nz_printf( "obj_size:\t%d", c.obj_size);
                   41325:     nz_printf( "real_size:\t%d", c.real_size);
                   41326:     nz_printf("lex_level:\t%d", c.lex_level);
                   41327:     if(c.lcl)print_string("lcl", c.lcl);
                   41328: 
                   41329:     print_ptr("baselist", c.baselist);
                   41330:     print_ptr("mem_list", c.mem_list);
                   41331:     print_ptr("memtbl", c.memtbl);
                   41332:     print_ptr("friend_list", c.friend_list);
                   41333:     print_ptr("pubdef", c.pubdef);
                   41334:     print_ptr("tn_list", c.tn_list); /* not brief */
                   41335:     print_ptr("in_class", c.in_class);
                   41336:     print_ptr("in_fct", c.in_fct);
                   41337:     print_ptr("this_type", c.this_type);
                   41338:     print_ptr("virt_list", c.virt_list); 
                   41339:     print_ptr("c_ctor", c.c_ctor);
                   41340:     print_ptr("c_dtor", c.c_dtor);
                   41341:     print_ptr("c_itor", c.c_itor);
                   41342:     print_ptr("conv", c.conv);
                   41343:     indent += Indent_Increment;
                   41344:     a_type();                  /* do the supertype. */
                   41345:     indent -= Indent_Increment;
                   41346: }
                   41347: 
                   41348: 
                   41349: void
                   41350: displayer::a_virt()
                   41351: {
                   41352:     virt& v = *Pvirt(node);
                   41353:     void * vna;
                   41354:     void * vna_e;
                   41355:     int vx;
                   41356: 
                   41357:     printf("$virt %s |0x%p ",
                   41358:           token_name(node->base),
                   41359:           node_address);
                   41360:     
                   41361:     print_ptr("next", v.next);
                   41362:     if(v.n_init) {
                   41363:        printf("n_init:\t%d", v.n_init);
                   41364:        printf("virt_init:");
                   41365:        for (vna = v.virt_init, vx = 0; vx < (v.n_init - 1);
                   41366:             vna = (char *)vna + sizeof (velem), vx++)
                   41367:            {
                   41368:                fetch(vna, sizeof (velem), vna_e);
                   41369:                struct velem * ve = (struct velem *) vna_e;
                   41370:                ind();
                   41371:                catprintf("%d offset %d\t", vx, ve->offset);
                   41372:                print_ptr(ve->n);
                   41373:                free_fetched(vna_e);
                   41374:            }
                   41375:     }
                   41376:     print_ptr("vclass", v.vclass);
                   41377:     nz_printf( "\nis_vbase:\t %d", v.is_vbase);
                   41378:     nz_printf( "\nprinted:\t %d", v.printed);
                   41379: }
                   41380: 
                   41381: void
                   41382: displayer::a_table ()
                   41383: {
                   41384:    struct table& t = *Ptable(node);
                   41385:    int x;
                   41386:    int y;
                   41387:    void * nlist;
                   41388:    void * slist;
                   41389: 
                   41390:    printf("$table %s |0x%p",
                   41391:          token_name(node->base),
                   41392:          node_address);
                   41393: 
                   41394:     printf("init_stat:\t%d%s", t.init_stat,
                   41395:           t.init_stat == 0 ? " not simplified" :
                   41396:           t.init_stat == 1 ? " simplified, no inits" :
                   41397:           t.init_stat == 2 ? " simplified, inits" :
                   41398:           "");
                   41399:    printf("size:\t%d", t.size);
                   41400:    printf("hashsize:\t%d", t.hashsize);
                   41401:    printf("free_slot:\t%d", t.free_slot);
                   41402: 
                   41403:    /* it looks like there is an array of Pnames here ... */
                   41404:    *arg->output_stream << "\n";
                   41405:    ind();
                   41406:    *arg->output_stream << "entries:\n";
                   41407:    fetch((void *)t.entries, t.size * sizeof(Pname), nlist);
                   41408:    Pname * tmp_nlist = (Pname *)nlist;
                   41409:    for(x = 0; x < t.size; x ++) {
                   41410:        if(tmp_nlist[x]) {
                   41411:           ind();
                   41412:           *arg->output_stream << x;
                   41413:           *arg->output_stream << "\t";
                   41414:           print_ptr(tmp_nlist[x]);
                   41415:           unsigned char tmp_name_s[sizeof(name)];
                   41416:           void * tmp_name;
                   41417:           tmp_name = (void *)&tmp_name_s[0];
                   41418:           fetch(tmp_nlist[x], sizeof(name), tmp_name);
                   41419:           catprintf(" key %d\n", Pname(tmp_name)->n_key);
                   41420:        }
                   41421:    }
                   41422:    free_fetched(nlist);
                   41423:    /* and then an array of shorts for the hash table. */
                   41424:    /* we really need a tabular format here, alright. */
                   41425:    ind();
                   41426:    *arg->output_stream << "hashtbl:\n";
                   41427:    fetch(t.hashtbl, t.hashsize * sizeof(short), slist);
                   41428:    short * tmp_slist = (short *)slist;
                   41429:    for(x = 0;; x++ ) {
                   41430:        for (y = 0; y < 11; y ++) {
                   41431:        if(((x * 12) + y) > t.hashsize) break;
                   41432:           catprintf("%6d ", tmp_slist[(x*12)+y]);
                   41433:        }
                   41434:        *arg->output_stream << "\n";
                   41435:        if(((x * 12) + y) > t.hashsize) break;
                   41436:    }
                   41437: 
                   41438:    free_fetched (slist);
                   41439: 
                   41440:    print_ptr("t_name", t.t_name);
                   41441:    print_ptr("real_block", t.real_block);
                   41442:    print_ptr("name", t.t_name);
                   41443:    print_ptr("next", t.next);
                   41444: }
                   41445: 
                   41446: void
                   41447: displayer::a_gen ()
                   41448: {
                   41449:     struct gen& g = *Pgen(node);
                   41450: 
                   41451:     printf("$gen %s |0x%p",
                   41452:           token_name(node->base),
                   41453:           node_address);
                   41454: 
                   41455:     print_ptr ("fct_list", g.fct_list);
                   41456:     indent += Indent_Increment;
                   41457:     a_type();                  /* do the supertype. */
                   41458:     indent -= Indent_Increment;
                   41459: }
                   41460: 
                   41461: void
                   41462: displayer::a_vec ()
                   41463: {
                   41464:    struct vec& v = *Pvec(node);
                   41465: 
                   41466:    printf("$vec %s |0x%p",
                   41467:          token_name(node->base),
                   41468:          node_address);
                   41469:    printf("size:\t\t%d", v.size);
                   41470:    print_ptr ("typ", v.typ);
                   41471:    print_ptr ("dim", v.dim);
                   41472: }
                   41473: 
                   41474: void
                   41475: displayer::a_ptr ()
                   41476: {
                   41477:     struct ptr& p = *Pptr(node);
                   41478: 
                   41479:     printf("$ptr %s |0x%p",
                   41480:           token_name(node->base),
                   41481:           node_address);
                   41482:     ind();
                   41483:     printf("rdo:\t\t%d", p.rdo);
                   41484:     ind();
                   41485: 
                   41486:     print_ptr ("typ", p.typ);
                   41487:     print_ptr ("memof", p.memof);
                   41488: }
                   41489: 
                   41490: 
                   41491: void
                   41492: displayer::a_nlist()
                   41493: {
                   41494:     name_list& n = *Plist(node);
                   41495: 
                   41496:     printf("$name_list %s |0x%p ",
                   41497:           token_name(node->base),
                   41498:           node_address);
                   41499:     
                   41500:     print_ptr("f", n.f);
                   41501:     print_ptr("l", n.l);
                   41502: }
                   41503: 
                   41504: void
                   41505: displayer::a_iline()
                   41506: {
                   41507:     struct iline& i = *(struct iline *)node;
                   41508: 
                   41509:     printf("$iline %s |0x%p ",
                   41510:           token_name(node->base),
                   41511:           node_address);
                   41512:     
                   41513:     print_ptr("fct_name", i.fct_name);
                   41514:     print_ptr("i_next", i.i_next);
                   41515:     print_ptr("i_table", i.i_table);
                   41516:     nz_printf("i_slots:\t%d", i.i_slots);
                   41517:     print_ptr("i_args", i.i_args);
                   41518: }
                   41519: 
                   41520: void
                   41521: displayer::a_ia()
                   41522: {
                   41523:     struct ia& i = *(struct ia *)node;
                   41524: 
                   41525:     printf("$ia %s |0x%p ",
                   41526:           token_name(node->base),
                   41527:           node_address);
                   41528:     
                   41529:     print_ptr("local", i.local);
                   41530:     print_ptr("arg", i.arg);
                   41531:     print_ptr("tp", i.tp);
                   41532: }
                   41533: 
                   41534: static int fetcher (void * info,
                   41535:                    void * pointer,
                   41536:                    unsigned long length,
                   41537:                    int zero_stop,  /* for character strings.*/
                   41538:                    void * target)
                   41539: {
                   41540:     displayer * d = (displayer *)info;
                   41541:     if(d->arg->fetcher)
                   41542:        return d->arg->fetcher(d->arg->fetcher_info, pointer, length,
                   41543:                               zero_stop, target);
                   41544: }
                   41545: 
                   41546: static void 
                   41547: do_node (Pnode& node, node_class cl, void * info, tree_node_action& action,
                   41548:         int depth, Pnode na, tree_walk_tree&, int&)
                   41549: {
                   41550:     displayer * d = (displayer *)info;
                   41551:     d->do_node(node, cl, action, depth, na);
                   41552:     d->arg->output_stream->write("\n", 1);
                   41553: }
                   41554: 
                   41555: 
                   41556: /* Note -- declared extern "C" in tree_dump.h. */
                   41557: 
                   41558: void
                   41559: display_cfront_node (dcn_arg& arg, Pnode n)
                   41560: {
                   41561:     tree_walk_control twc;
                   41562:     displayer d (arg);
                   41563:     
                   41564:     if(arg.verbose == dt_normal)arg.max_depth = 0;
                   41565:     twc.callback_info = (void *)&d;
                   41566:     if(arg.fetcher) twc.fetcher = fetcher;
                   41567:     twc.action_proc = do_node;
                   41568:     twc.error_stream = arg.error_stream;
                   41569:     twc.nodes_seen_hash = arg.nodes_seen_hash;
                   41570:     twc.resolve_by_name = 0;   /* we want to display the by_name nodes */
                   41571:     twc.dont_chase_lists_top = 1; /* don't display n_list or s_list peers
                   41572:                                     at the top level. */
                   41573: 
                   41574:     walk_tree(twc, n);
                   41575: 
                   41576:     arg.error_stream->flush();
                   41577:     arg.output_stream->flush();
                   41578: }
                   41579: 
                   41580: 
                   41581: extern "C" void _fcout();
                   41582: void _fcout () { cout.flush(); }
                   41583: 0707071010112046001004440001630000160000010207660466055415100001400000003407tree_dump.h/* ident "@(#)ctrans:src/tree_dump.h   1.2" */
                   41584: /* -*- Mode: C -*- Begin tree_dump.h */
                   41585: 
                   41586: #ifndef _DUMP_TREE
                   41587: #define _DUMP_TREE
                   41588: 
                   41589: #include "tree_walk.h"
                   41590: #include <iostream.h>
                   41591: #include "hash.h"
                   41592: 
                   41593: enum dump_tree_verbosity {
                   41594:     dt_brief = 1,              /* minimal identification */
                   41595:     dt_normal = 2,             /* all data, outpointers Brief (one level) */
                   41596:     dt_recursive_0 = 3,                /* minimal, but recurse down.
                   41597:                                   (outpointers Recursive_0) */
                   41598:     dt_recursive_1 = 4,                /* all data, outpointers Recursive_2. */
                   41599: };
                   41600: 
                   41601: class dcn_arg {
                   41602:   public:
                   41603:     int version;
                   41604:     dump_tree_verbosity verbose;
                   41605:     tree_fetch_proc fetcher;
                   41606:     void * fetcher_info;
                   41607:     ostream* output_stream;
                   41608:     ostream* error_stream;
                   41609:     int max_depth;
                   41610:     Hash * nodes_seen_hash;
                   41611:     /* end of version 1 */
                   41612:     int walk_tables;
                   41613:     /* end of version 2 */
                   41614:     int stop_at_top;
                   41615:     dcn_arg () { version = 2; 
                   41616:                 nodes_seen_hash = 0;
                   41617:                 fetcher = null_tfp; 
                   41618:                 output_stream = &cout;
                   41619:                 error_stream = &cerr; 
                   41620:                 max_depth = -1;
                   41621:                 walk_tables = 1;
                   41622:                 stop_at_top = 0;
                   41623:             };
                   41624: };
                   41625: 
                   41626: 
                   41627: extern "C" {
                   41628:     void display_cfront_node (dcn_arg&, Pnode);
                   41629: }
                   41630: #else
                   41631: 
                   41632: typedef enum dump_tree_verbosity {
                   41633:     dt_brief = 1,              /* minimal identification */
                   41634:     dt_normal = 2,             /* all data, outpointers Brief (one level) */
                   41635:     dt_recursive_0 = 3,                /* minimal, but recurse down.
                   41636:                                   (outpointers Recursive_0) */
                   41637:     dt_recursive_1 = 4,                /* all data, outpointers Recursive_2. */
                   41638: } dump_tree_verbosity;
                   41639: 
                   41640: struct dcn_arg {
                   41641:     int version;               /* must be 1 for now. */
                   41642:     dump_tree_verbosity verbose;
                   41643:     int (*fetcher) ();
                   41644:     void * fetcher_info;
                   41645:     void * output_stream;      /* these are c++ streams */
                   41646:     void * error_stream;
                   41647:     int max_depth;
                   41648:     void * nodes_seen_hash;
                   41649:     int walk_tables;
                   41650:     int stop_at_top;
                   41651: };
                   41652: 
                   41653: void display_cfront_node ();
                   41654: #endif
                   41655: 
                   41656: /* End tree_dump.h */
                   41657: 0707071010112046051004440001630000160000010212000466055417300001400000066517tree_walk.c/* ident "@(#)ctrans:src/tree_walk.c   1.2" */
                   41658: /* 
                   41659:        tree_walk.c
                   41660:        Utilities for tree-walking 
                   41661: */
                   41662: 
                   41663: #include "cfront.h"
                   41664: #include "tree_walk.h"
                   41665: #include <stdarg.h>
                   41666: #include "hash.h"
                   41667: // #include <alloca.h>
                   41668: // ************ need to add an explicit call of free
                   41669: // ************ make it an ifdef
                   41670: // ??? #include <streamdefs.h>
                   41671: #include <malloc.h>
                   41672: 
                   41673: class walker {
                   41674:     tree_walk_control control;
                   41675:     Pnode orig_addr;
                   41676:     Hash *nodes_seen_hash;
                   41677:     int depth;
                   41678:     int made_ht;
                   41679:     tree_walk_tree * cur_tree;
                   41680:   public:
                   41681:     walker(tree_walk_control& c) ;
                   41682:  
                   41683:     ~walker () {
                   41684:        if(made_ht) delete nodes_seen_hash;
                   41685:     }
                   41686:     tree_node_action walk (Pnode&);
                   41687:     tree_node_action walk_ (Pnode& n) 
                   41688:     {
                   41689:        if(n) {
                   41690:            int save_depth = depth;
                   41691:            tree_walk_tree * save_cur_tree = cur_tree;
                   41692: 
                   41693:            depth ++;
                   41694:            if(control.alloc_stack_bytes) {
                   41695:                cur_tree = (tree_walk_tree *)
                   41696:                    // alloca (control.alloc_stack_bytes + sizeof (tree_walk_tree));
                   41697:                    malloc(control.alloc_stack_bytes + sizeof (tree_walk_tree));
                   41698:                cur_tree->parent = save_cur_tree;
                   41699:            }
                   41700:            tree_node_action r = walk(n);
                   41701:            depth = save_depth;
                   41702:            return r;
                   41703:        } else return tna_continue;
                   41704:     }
                   41705:        
                   41706:     tree_node_action walk(Pgen& n) 
                   41707:     { return walk_ ((struct node * &)n); };
                   41708:     tree_node_action walk(Pvec& n) 
                   41709:     { return walk_ ((struct node * &)n); };
                   41710:     tree_node_action walk(Pptr& n) 
                   41711:     { return walk_ ((struct node * &)n); };
                   41712:     tree_node_action walk(Ptype& n) 
                   41713:     { return walk_ ((struct node * &)n); };
                   41714:     tree_node_action walk(Pfct& n) 
                   41715:     { return walk_ ((struct node * &)n); };
                   41716:     tree_node_action walk(Ptable& n) 
                   41717:     { return walk_ ((struct node * &)n); };
                   41718:     tree_node_action walk(Pbase& n) 
                   41719:     { return walk_ ((struct node * &)n); };
                   41720:     tree_node_action walk(Pname& n) 
                   41721:     { return walk_ ((struct node * &)n); };
                   41722:      tree_node_action walk(Pexpr& n) 
                   41723:     { return walk_ ((struct node * &)n); };
                   41724:     tree_node_action walk(Pstmt& n) 
                   41725:     { return walk_ ((struct node * &)n); };
                   41726:     tree_node_action walk(Pblock& n) 
                   41727:     { return walk_ ((struct node * &)n); };
                   41728:     tree_node_action walk(Penum& n) 
                   41729:     { return walk_ ((struct node * &)n); };
                   41730:     tree_node_action walk(Pclass& n) 
                   41731:     { return walk_ ((struct node * &)n); };
                   41732:     tree_node_action walk(Pvirt& n) 
                   41733:     { return walk_ ((struct node * &)n); };
                   41734:     tree_node_action walk(Plist& n) 
                   41735:     { return walk_ ((struct node * &)n); };
                   41736:     tree_node_action walk(Pin& n) 
                   41737:     { return walk_ ((struct node * &)n); };
                   41738:     tree_node_action walk(struct ia * & n) 
                   41739:     { return walk_ ((struct node * &)n); };
                   41740:     tree_node_action walk(Pbcl& n) 
                   41741:     { return walk_ ((struct node * &)n); };
                   41742:   private:
                   41743:     int fetching () {  return (control.fetcher != null_tfp); } ;
                   41744:     void free_fetched (void *);
                   41745:     int fetch (void *, unsigned long, void *&);
                   41746:     int fetch (void * a, unsigned long l, Pnode& p) 
                   41747:     {
                   41748:        int ret;
                   41749:        void * t;               /* this is an output argument */
                   41750:        ret = fetch(a,l,t);
                   41751:        if(!ret) {
                   41752:            p = Pnode(t);
                   41753:        }
                   41754:        return ret;
                   41755:     };
                   41756:     // void error (const char *,...); ?? at&t -- to get it up quick, line 155
                   41757:     void error ( char *, unsigned long=0 );
                   41758:     tree_node_action pre_act_on_node (Pnode node, node_class nc,
                   41759:                                      Pnode node_copy, Pnode& replacement);
                   41760:                                       
                   41761:     tree_node_action a_gen (Pnode, Pgen, Pnode&);
                   41762:     tree_node_action a_vec (Pnode, Pvec, Pnode&);
                   41763:     tree_node_action a_ptr (Pnode, Pptr, Pnode&);
                   41764:     tree_node_action a_fct (Pnode, Pfct, Pnode&);
                   41765:     tree_node_action a_table (Pnode, Ptable, Pnode&);
                   41766:     tree_node_action a_basetype (Pnode, Pbase, Pnode&);
                   41767:     tree_node_action a_name(Pnode, Pname, Pnode&);
                   41768:     tree_node_action a_expr (Pnode, Pexpr, Pnode&);
                   41769:     tree_node_action a_stmt (Pnode, Pstmt, Pnode&);
                   41770:     tree_node_action a_enumdef (Pnode, Penum, Pnode&);
                   41771:     tree_node_action a_classdef (Pnode, Pclass, Pnode&);
                   41772:     tree_node_action a_virt (Pnode, Pvirt, Pnode&);
                   41773:     tree_node_action a_name_list (Pnode, Plist, Pnode&);
                   41774:     tree_node_action a_iline (Pnode, Pin, Pnode&);
                   41775:     tree_node_action a_ia (Pnode, struct ia *, Pnode&);
                   41776:     tree_node_action a_baseclass (Pnode, Pbcl, Pnode&);
                   41777:     tree_node_action a_expr_guts (Pexpr);
                   41778: };
                   41779: 
                   41780: 
                   41781: walker::walker(tree_walk_control& c) 
                   41782: { control = c;
                   41783:   made_ht = 0;
                   41784:   if (c.nodes_seen_hash)
                   41785:     nodes_seen_hash = c.nodes_seen_hash;
                   41786:   else {
                   41787:     nodes_seen_hash = new pointer_hash (100);
                   41788:     made_ht = 1;
                   41789:   }
                   41790:   depth = 0;
                   41791:   cur_tree = 0;
                   41792: }
                   41793: 
                   41794: 
                   41795: tree_node_action
                   41796: walk_tree (tree_walk_control& c, Pnode& n)
                   41797: {
                   41798:     walker w (c);
                   41799:     return w.walk(n);
                   41800: }
                   41801: 
                   41802: 
                   41803: /* error messages are of finite length, so no need to run
                   41804:    around mallocing strings */
                   41805: 
                   41806: // void walker::error (const char * format, ...)
                   41807: void walker::error (char *format, unsigned long v)
                   41808: {
                   41809:     va_list args;
                   41810:     va_start(args, format);
                   41811:     if(control.call_i_error) {
                   41812:        char buf[1000];
                   41813:        // vsprintf(buf, format, args);
                   41814:         // vsprintf not universal: by inspection
                   41815:         // all calls are currently of 1 or 0 arguments
                   41816:        sprintf(buf, format, v);
                   41817:        (*control.i_error)('i', buf);
                   41818:     } else {
                   41819:        vostream_printf (format, args, *control.error_stream);
                   41820:        *control.error_stream << "\n";
                   41821:        control.error_stream->flush();
                   41822:     }
                   41823:     va_end (args);
                   41824: }
                   41825: 
                   41826: 
                   41827: void
                   41828: walker::free_fetched (void * addr)
                   41829: {
                   41830:     if (control.fetcher != null_tfp)   /* null indicates no cross-address-space */
                   41831:        free ((char *)addr);    
                   41832: }    
                   41833: 
                   41834: int
                   41835: walker::fetch (void * addr, unsigned long length, void*& taddr)
                   41836: {
                   41837:     int err;
                   41838: 
                   41839:     if (control.fetcher == null_tfp) { 
                   41840:        taddr = addr;
                   41841:        return 0;
                   41842:     } else {
                   41843:        taddr = (void *)malloc ((unsigned int)length);
                   41844:        if(taddr == 0) {
                   41845:           error ("walker::fetch: failed to malloc %d bytes.", length);
                   41846:           return 1;
                   41847:        }
                   41848: 
                   41849:        err = (*control.fetcher) (control.callback_info, addr, length, 0, taddr);
                   41850:        if(err) {
                   41851:           error("walker::fetch: fetcher returned %d.", err);
                   41852:           return 1;
                   41853:        }
                   41854:    }
                   41855: }
                   41856: 
                   41857: /* ::walk is called with a node pointer and a reference to
                   41858:    a replacement node pointer. When it returns,
                   41859:    replacement will be set if the action procedure
                   41860:    called on the node decided to copy it or replace it.
                   41861:    There are two possible modularities. 
                   41862:    In case there is cross-address-space action,
                   41863:    ::walk can't call the action procedure until it has
                   41864:    entered the case on node bases. Once it has,
                   41865:    it calls the per-structure-type procedure,
                   41866:    which calls the action proc. If the action 
                   41867:    proc supplies a replacement, then that replacement
                   41868:    will be returned up via the reference parameters to 
                   41869:    the per-structure procedures.
                   41870: 
                   41871:    It the action procedure returns tna_continue,
                   41872:    then the walk continues against the new copy of the node
                   41873:    so that further replacements are reflected in the new copies.
                   41874:    This prevents replacement from being meaningful cross-address-space,
                   41875:    since the new copy will presumably be in the current 
                   41876:    (and not the cross) address space. That is, if the node
                   41877:    is replaced by the action proc, the pointers in the new 
                   41878:    node will drive the subsequent tree walk. Usually one
                   41879:    would just bitcopy, and then they would be replaced in turn.
                   41880: */
                   41881: 
                   41882: tree_node_action
                   41883: walker::walk (Pnode& top)
                   41884: {
                   41885:     Pnode replacement = 0;
                   41886:     tree_node_action err;
                   41887:     int class_err;
                   41888:     node_class nclass;
                   41889:     Pnode node = 0; /* assign to shut up compiler,
                   41890:                       which dosen't recognize pass-by-reference as a set */
                   41891: 
                   41892:     orig_addr = top;
                   41893: 
                   41894:     if(fetching ()) {
                   41895:        if(fetch((void *)top, sizeof (struct node), node))
                   41896:            return tna_error;
                   41897:     } else node = top;
                   41898: 
                   41899: /* This has a complete catalog of bases, rather than just a list
                   41900:    of those associated with data structures. Its important
                   41901:    to detect the errs.
                   41902: */   
                   41903: 
                   41904:     nclass = classify_node (node, class_err);
                   41905: 
                   41906:     if(class_err) {
                   41907:        error("walker::walk: unknown node type %d.", node->base);
                   41908:        free_fetched ((void *)node);
                   41909:        err = tna_error;
                   41910:        goto Return;
                   41911:     }
                   41912:     
                   41913:     switch(nclass)
                   41914:     {
                   41915:       default:
                   41916:       case nc_unused:
                   41917:        error("walker::walk: unused node type %d.", node->base);
                   41918:        err = tna_error;
                   41919:        goto Return;
                   41920: 
                   41921:       case nc_eof:
                   41922:        break;
                   41923: 
                   41924:       case nc_virt:
                   41925:        fetch((void *)top, sizeof (struct virt), node);
                   41926:        err = a_virt(top, Pvirt (node), replacement);
                   41927:        break;
                   41928: 
                   41929:       case nc_nlist:
                   41930:        fetch((void *)top, sizeof (struct name_list), node);
                   41931:        err = a_name_list(top, (struct name_list *)node, replacement);
                   41932:        break;
                   41933: 
                   41934:       case nc_iline:
                   41935:        fetch((void *)top, sizeof (struct iline), node);
                   41936:        err = a_iline(top, (struct iline *)node, replacement);
                   41937:        break;
                   41938: 
                   41939:       case nc_gen:
                   41940:        fetch((void *)top, sizeof (struct gen), node);
                   41941:        err = a_gen(top, Pgen (node), replacement);
                   41942:        break;
                   41943: 
                   41944:       case nc_vec:
                   41945:        fetch((void *)top, sizeof (struct vec), node);
                   41946:        err = a_vec(top, Pvec(node), replacement);
                   41947:        break;
                   41948: 
                   41949:       case nc_ptr:
                   41950:        fetch((void *)top, sizeof (struct ptr), node);
                   41951:        err = a_ptr(top, Pptr(node), replacement);
                   41952:        break;
                   41953: 
                   41954:       case nc_fct:
                   41955:        fetch((void *)top, sizeof (struct fct), node);
                   41956:        err = a_fct(top, Pfct(node), replacement);
                   41957:        break;
                   41958: 
                   41959:       case nc_table:
                   41960:        fetch((void *)top, sizeof (struct table), node);
                   41961:        err = a_table(top, Ptable(node), replacement);
                   41962:        break;
                   41963: 
                   41964:       case nc_basetype:
                   41965:        fetch((void *)top, sizeof (struct basetype), node);
                   41966:        err = a_basetype(top, Pbase(node), replacement);
                   41967:        break;
                   41968: 
                   41969:       case nc_name:
                   41970:        fetch((void *)top, sizeof (struct name), node);
                   41971:        err = a_name(top, Pname(node), replacement);
                   41972:        break;
                   41973: 
                   41974:       case nc_expr:
                   41975:        fetch((void *)top, sizeof (struct expr), node);
                   41976:        err = a_expr(top, Pexpr(node), replacement);
                   41977:        break;
                   41978: 
                   41979:       case nc_stmt:
                   41980:        fetch((void *)top, sizeof (struct stmt), node);
                   41981:        err = a_stmt(top, Pstmt(node), replacement);
                   41982:        break;
                   41983: 
                   41984:       case nc_enumdef:
                   41985:        fetch((void *)top, sizeof (struct enumdef), node);
                   41986:        err = a_enumdef(top, Penum(node), replacement);
                   41987:        break;
                   41988: 
                   41989:       case nc_classdef:
                   41990:        fetch((void *)top, sizeof (struct classdef), node);
                   41991:        err = a_classdef(top, Pclass(node), replacement);
                   41992:        break;
                   41993: 
                   41994:       case nc_ia:
                   41995:        fetch((void *)top, sizeof (struct ia), node);
                   41996:        err = a_ia(top, (struct ia *)node, replacement);
                   41997:        break;
                   41998: 
                   41999:       case nc_baseclass:
                   42000:        fetch((void *)top, sizeof (struct basecl), node);
                   42001:        err = a_baseclass(top, Pbcl(node), replacement);
                   42002:        break;
                   42003: 
                   42004:     }
                   42005: 
                   42006:     if(replacement) {
                   42007:        if (fetching ()) {
                   42008:            error
                   42009:                ("walker::walk: Attempt to replace tree in cross-address space mode.");
                   42010:            err = tna_error;
                   42011:        } 
                   42012:        else top = replacement;
                   42013:     }
                   42014:        
                   42015:     if (control.post_action_proc && err != tna_error) {
                   42016:        tree_node_action post_err;
                   42017:        Pnode& post_repl = node;
                   42018: 
                   42019:        (*control.post_action_proc) (post_repl, nclass, control.callback_info, post_err,
                   42020:                                     depth, orig_addr, *cur_tree);
                   42021:        if(post_err != tna_continue) err = post_err;
                   42022:        if(post_repl != node) {
                   42023:            if (fetching ()) {
                   42024:                error
                   42025:                    ("walker::walk: Attempt to replace tree in cross-address space mode.");
                   42026:                err = tna_error;
                   42027:            } 
                   42028:            else top = post_repl;
                   42029:        }
                   42030:     }
                   42031: 
                   42032:     free_fetched((void *) node);
                   42033: 
                   42034: Return:
                   42035:     return err;
                   42036: }
                   42037: 
                   42038: /* This is called in pre-order for each node. Then
                   42039:    post_act_on_node is called after whatever recursive
                   42040:    processing ensues.
                   42041:    
                   42042:    This is called from each of the structure-specific procedures
                   42043:    to give the action procedure an opportunity to act.
                   42044:    It can return a replacement pointer and control
                   42045:    whether to examine the insides of the node.
                   42046:    */
                   42047: 
                   42048: tree_node_action 
                   42049: walker::pre_act_on_node (Pnode node, node_class nc,
                   42050:                       Pnode node_copy, Pnode& replacement)
                   42051: {
                   42052: /* If we have been here before, then we never proceed */
                   42053: /* node_copy is != node when a fetcher is in use */
                   42054: 
                   42055:     int found;
                   42056:     int old_node;
                   42057:     tree_node_action action;
                   42058:     Pnode new_node;
                   42059:     int register_in_hash = 1;
                   42060: 
                   42061:     nodes_seen_hash->action((int)node, 0, Hash::probe, found, old_node);
                   42062: 
                   42063:     if(found) {
                   42064:        new_node = Pnode(old_node);
                   42065:        if(new_node != node) replacement = new_node;
                   42066:        return tna_stop; /* no need to proceed */
                   42067:     }
                   42068: 
                   42069:     /* OK, we don't know from a previous pass. Call our actor */
                   42070: 
                   42071:     new_node = fetching () && node_copy ? node_copy : node;
                   42072: 
                   42073:     (*control.action_proc)(new_node, nc, control.callback_info, action, 
                   42074:                           depth, orig_addr, *cur_tree,
                   42075:                           register_in_hash);
                   42076: 
                   42077:     if(action != tna_error && !fetching () && new_node != node) {
                   42078:        replacement = new_node;
                   42079:        if(register_in_hash)
                   42080:            nodes_seen_hash->action((int)node, 
                   42081:                                    (int)new_node, 
                   42082:                                    Hash::insert, 0, 0);
                   42083:     }
                   42084:     else {
                   42085:        if(register_in_hash)
                   42086:            nodes_seen_hash->action((int)node, (int) node, Hash::insert, 0, 0);
                   42087:     }
                   42088:     return action;
                   42089: }                         
                   42090: 
                   42091: tree_node_action walker::a_table(Pnode ta, Ptable t, Pnode& replacement) 
                   42092: {
                   42093:     /* no unions */
                   42094: 
                   42095:     tree_node_action action;
                   42096:     action = pre_act_on_node(ta, nc_table, Pnode(t), replacement);
                   42097:     if(action != tna_continue) return action;
                   42098: 
                   42099: /* -----------------------------*/
                   42100: /* For Now, Never Walk a Table. */
                   42101: 
                   42102:     action = tna_stop; return action;
                   42103: 
                   42104: /* An array of pointers. 
                   42105:  * The action procedure is responsible for allocating a new one
                   42106:  * of those if it replaced and continued. 
                   42107:  * *** end of comment
                   42108: 
                   42109:     if(!fetching () && replacement)
                   42110:        t = Ptable(replacement);
                   42111: 
                   42112:     Pname * t_entries;
                   42113: 
                   42114:     if(fetching ()) {
                   42115:        void * temp;
                   42116:        fetch((void *)t->entries, t->size * sizeof(Pname), temp);
                   42117:        t_entries = (Pname *)temp;
                   42118:     }
                   42119:     else t_entries = t->entries;
                   42120: 
                   42121:     for(int nx = 0; nx < t->size; nx ++) {
                   42122:        action = walk(t_entries[nx]);
                   42123:        if(action == tna_error) return action;
                   42124:     }
                   42125: 
                   42126:     if(fetching ()) free_fetched ((void *)t_entries);
                   42127:     
                   42128:     Pnode n = Pnode(t->real_block);
                   42129: 
                   42130:     action = walk(t->real_block);
                   42131:     if(action == tna_error) return action;
                   42132:     
                   42133:     action = walk(t->next);
                   42134:     action = walk(t->t_name);
                   42135:     return tna_continue;
                   42136: */ // don't walk table
                   42137: }
                   42138: 
                   42139: tree_node_action walker::a_enumdef (Pnode ta, Penum e, Pnode& replacement) 
                   42140: {
                   42141:     tree_node_action action = pre_act_on_node(ta, nc_enumdef, Pnode(e), replacement);
                   42142: 
                   42143:     action = walk(e->mem);
                   42144:     if(action == tna_error) return action;
                   42145: 
                   42146:     action = walk(e->e_type);
                   42147: 
                   42148:     return tna_continue;
                   42149: }    
                   42150: 
                   42151: tree_node_action walker::a_virt(Pnode ta, Pvirt v, Pnode& replacement) 
                   42152: {
                   42153:     /* no unions */
                   42154: 
                   42155:     int nx;
                   42156:     tree_node_action action = pre_act_on_node(ta, nc_enumdef, Pnode(v), replacement);
                   42157: 
                   42158:     if(action != tna_continue) return action;
                   42159: 
                   42160:     if(!fetching () && replacement)
                   42161:        v = Pvirt(replacement);
                   42162: 
                   42163: /* an array of velem structures. */
                   42164: 
                   42165:     velem * v_virt_init;
                   42166: 
                   42167:     if(fetching ()) {
                   42168:        void * t;
                   42169:        fetch((void *)v->virt_init, v->n_init * sizeof(velem), t);
                   42170:        v_virt_init = (velem *)t;
                   42171:     }
                   42172:     else v_virt_init = v->virt_init;
                   42173: 
                   42174:     for(nx = 0; nx < v->n_init; nx ++) {
                   42175:        action = walk(v_virt_init[nx].n);
                   42176:        if(action == tna_error) return action;
                   42177:     }
                   42178: 
                   42179:     if(fetching ()) free_fetched ((void *)v_virt_init);
                   42180:     
                   42181:     action = walk(v->vclass);
                   42182:     
                   42183:     return tna_continue;
                   42184: }
                   42185: 
                   42186: tree_node_action walker::a_classdef(Pnode ta, Pclass c, Pnode& replacement) 
                   42187: {
                   42188: 
                   42189:     tree_node_action action = pre_act_on_node(ta, nc_classdef, Pnode(c), replacement);
                   42190: 
                   42191:     if(action != tna_continue) return action;
                   42192: 
                   42193:     if(!fetching () && replacement)
                   42194:        c = Pclass(replacement);
                   42195: 
                   42196:     action = walk(c->baselist);
                   42197:     if(action == tna_error) return action;
                   42198: 
                   42199:     action=walk(c->mem_list);
                   42200:     if(action == tna_error) return action;
                   42201:     
                   42202:     action=walk(c->memtbl);
                   42203:     if(action == tna_error) return action;
                   42204: 
                   42205:     action=walk(c->friend_list);
                   42206:     if(action == tna_error) return action;
                   42207: 
                   42208:     action=walk(c->pubdef);
                   42209:     if(action == tna_error) return action;
                   42210:     
                   42211:     action=walk(c->tn_list);
                   42212:     if(action == tna_error) return action;
                   42213: 
                   42214:     action=walk(c->in_class);
                   42215:     if(action == tna_error) return action;
                   42216: 
                   42217:     action=walk(c->in_fct);
                   42218:     if(action == tna_error) return action;
                   42219: 
                   42220:     action=walk(c->this_type);
                   42221:     if(action == tna_error) return action;
                   42222: 
                   42223:     action=walk(c->virt_list);
                   42224:     if(action == tna_error) return action;
                   42225: 
                   42226:     action=walk(c->c_ctor);
                   42227:     if(action == tna_error) return action;
                   42228:     action=walk(c->c_dtor);
                   42229:     if(action == tna_error) return action;
                   42230:     action=walk(c->c_itor);
                   42231:     if(action == tna_error) return action;
                   42232: 
                   42233:     action=walk(c->conv);
                   42234:     if(action == tna_error) return action;
                   42235: 
                   42236:     return tna_continue;
                   42237: }
                   42238: 
                   42239: tree_node_action walker::a_basetype(Pnode ta, Pbase b, Pnode& replacement) 
                   42240: {
                   42241: 
                   42242:     tree_node_action action = pre_act_on_node(ta, nc_basetype, Pnode(b), replacement);
                   42243:     int derr;
                   42244: 
                   42245:     if(action != tna_continue) return action;
                   42246: 
                   42247:     if(!fetching () && replacement)
                   42248:        b = Pbase(replacement);
                   42249: 
                   42250:     action = walk(b->b_name);
                   42251:     if(action == tna_error) return action;
                   42252: 
                   42253:     action = walk(b->b_table);
                   42254:     if(action == tna_error) return action;
                   42255: 
                   42256:     // action = walk(b->b_field);
                   42257:     // if(action == tna_error) return action;
                   42258: 
                   42259:     action = walk(b->b_xname);
                   42260:     if(action == tna_error) return action;
                   42261: 
                   42262:     switch(derr = b->discriminator(0)) {
                   42263:       case 0: break;
                   42264:       case 1:
                   42265:        action = walk(b->b_fieldtype);
                   42266:        if(action == tna_error) return action;
                   42267:        break;
                   42268:       case 2: break;
                   42269:       default:
                   42270:        error ("a_basetype: discrim error %d.", derr);
                   42271:        return tna_error;
                   42272:     }
                   42273: 
                   42274:     return tna_continue;
                   42275: }
                   42276: 
                   42277: tree_node_action walker::a_fct(Pnode ta, Pfct f, Pnode& replacement) 
                   42278: {
                   42279: 
                   42280:     tree_node_action action = pre_act_on_node(ta, nc_fct, Pnode(f), replacement);
                   42281: 
                   42282:     if(action != tna_continue) return action;
                   42283: 
                   42284:     if(!fetching () && replacement)
                   42285:        f = Pfct(replacement);
                   42286: 
                   42287:     action = walk(f->returns);
                   42288:     if(action == tna_error) return action;
                   42289: 
                   42290:     action = walk(f->argtype);
                   42291:     if(action == tna_error) return action;
                   42292: 
                   42293:     action = walk(f->s_returns);
                   42294:     if(action == tna_error) return action;
                   42295: 
                   42296:     action = walk(f->f_this);
                   42297:     if(action == tna_error) return action;
                   42298: 
                   42299:     action = walk(f->memof);
                   42300:     if(action == tna_error) return action;
                   42301: 
                   42302:     action = walk(f->body);
                   42303:     if(action == tna_error) return action;
                   42304: 
                   42305:     action = walk(f->f_init);
                   42306:     if(action == tna_error) return action;
                   42307: 
                   42308:     action = walk(f->f_expr);
                   42309:     if(action == tna_error) return action;
                   42310: 
                   42311:     action = walk(f->last_expanded);
                   42312:     if(action == tna_error) return action;
                   42313: 
                   42314:     action = walk(f->f_result);
                   42315:     if(action == tna_error) return action;
                   42316: 
                   42317:     action = walk(f->f_args);
                   42318:     if(action == tna_error) return action;
                   42319: 
                   42320:     return tna_continue;
                   42321: }
                   42322: 
                   42323: tree_node_action walker::a_name_list(Pnode ta, Plist l, Pnode& replacement) 
                   42324: {
                   42325: 
                   42326:     int cl_error;
                   42327:     tree_node_action action = pre_act_on_node(ta, nc_nlist, Pnode(l), replacement);
                   42328: 
                   42329:     if(action == tna_stop) {
                   42330:        if(!fetching () && replacement)
                   42331:            l = Plist(replacement);
                   42332:        cl_error = 0;
                   42333:        if((classify_node(Pnode(l), cl_error) == nc_nlist) && !cl_error) {
                   42334:            action = walk(l->l);
                   42335:            if(action == tna_error) return action;
                   42336:        }
                   42337:     }
                   42338: 
                   42339:     if(action != tna_continue) return action;
                   42340: 
                   42341:     if(!fetching () && replacement)
                   42342:        l = Plist(replacement);
                   42343: 
                   42344:     action = walk(l->f);
                   42345:     if(action == tna_error) return action;
                   42346: 
                   42347:     action = walk(l->l);
                   42348:     if(action == tna_error) return action;
                   42349: 
                   42350:     return tna_continue;
                   42351: }
                   42352: 
                   42353: tree_node_action walker::a_gen(Pnode ta, Pgen g, Pnode& replacement) 
                   42354: {
                   42355: 
                   42356:     tree_node_action action = pre_act_on_node(ta, nc_gen, Pnode(g), replacement);
                   42357: 
                   42358:     if(action != tna_continue) return action;
                   42359: 
                   42360:     if(!fetching () && replacement)
                   42361:        g = Pgen(replacement);
                   42362: 
                   42363:     action = walk(g->fct_list);
                   42364:     if(action == tna_error) return action;
                   42365: 
                   42366:     return tna_continue;
                   42367: }
                   42368: 
                   42369: tree_node_action walker::a_vec(Pnode ta, Pvec v, Pnode& replacement) 
                   42370: {
                   42371: 
                   42372:     tree_node_action action = pre_act_on_node(ta, nc_vec, Pnode(v), replacement);
                   42373: 
                   42374:     if(action != tna_continue) return action;
                   42375: 
                   42376:     if(!fetching () && replacement)
                   42377:        v = Pvec(replacement);
                   42378: 
                   42379:     action = walk(v->typ);
                   42380:     if(action == tna_error) return action;
                   42381: 
                   42382:     action = walk(v->dim);
                   42383:     if(action == tna_error) return action;
                   42384: 
                   42385:     return tna_continue;
                   42386: }
                   42387: 
                   42388: tree_node_action walker::a_ptr(Pnode ta, Pptr p, Pnode& replacement) 
                   42389: {
                   42390: 
                   42391:     tree_node_action action = pre_act_on_node(ta, nc_ptr, Pnode(p), replacement);
                   42392: 
                   42393:     if(action != tna_continue) return action;
                   42394: 
                   42395:     if(!fetching () && replacement)
                   42396:        p = Pptr(replacement);
                   42397: 
                   42398:     action = walk(p->typ);
                   42399:     if(action == tna_error) return action;
                   42400: 
                   42401:     action = walk(p->memof);
                   42402:     if(action == tna_error) return action;
                   42403: 
                   42404:     return tna_continue;
                   42405: }
                   42406: 
                   42407: 
                   42408: tree_node_action walker::a_expr_guts(Pexpr e)
                   42409: {
                   42410:     int derr;
                   42411:     tree_node_action action;
                   42412: 
                   42413:     switch(derr = e->discriminator (0)) {
                   42414:       case 1:
                   42415:        action = walk(e->tp);
                   42416:        if(action == tna_error) return action;
                   42417:        break;
                   42418:       case 0:
                   42419:        break;
                   42420:       default:
                   42421:        error ("a_expr: discrim error %d on union 0.", derr);
                   42422:        return tna_error;
                   42423:     }
                   42424: 
                   42425:     switch(derr = e->discriminator (1)) {
                   42426:       case 0:
                   42427:        break;
                   42428:       default:
                   42429:        error ("a_expr: discrim error %d on union 1.", derr);
                   42430:        return tna_error;
                   42431:       case 1:
                   42432:        action = walk(e->e1);
                   42433:        if(action == tna_error) return action;
                   42434:        break;
                   42435:       case 2:
                   42436:        break;
                   42437:       case 3:
                   42438:        break;
                   42439:     }
                   42440: 
                   42441:     switch(derr = e->discriminator (2)) {
                   42442:       case 0:
                   42443:        break;
                   42444:       default:
                   42445:        error ("a_expr: discrim error %d on union 2.", derr);
                   42446:        return tna_error;
                   42447:       case 1:
                   42448:        /* elists are special. e2 for an elist is a peer, not
                   42449:           a child. */
                   42450:        if(e->base != ELIST) {
                   42451:            action = walk(e->e2);
                   42452:            if(action == tna_error) return action;
                   42453:        }
                   42454:        break;
                   42455:       case 2:
                   42456:        break;
                   42457:       case 3:
                   42458:        break;
                   42459:       case 4:
                   42460:        action = walk(e->n_initializer);
                   42461:        if(action == tna_error) return action;
                   42462:        break;
                   42463:     }
                   42464:     
                   42465:     switch(derr = e->discriminator (3)) {
                   42466:       case 0:
                   42467:        break;
                   42468:       default:
                   42469:        error ("a_expr: discrim error %d on union 3.", derr);
                   42470:        return tna_error;
                   42471:       case 1:
                   42472:        action = walk(e->tp2);
                   42473:        if(action == tna_error) return action;
                   42474:        break;
                   42475:       case 2:
                   42476:        action = walk(e->fct_name);
                   42477:        if(action == tna_error) return action;
                   42478:        break;
                   42479:       case 3:
                   42480:        action = walk(e->cond);
                   42481:        if(action == tna_error) return action;
                   42482:        break;
                   42483:       case 4:
                   42484:        action = walk(e->mem);
                   42485:        if(action == tna_error) return action;
                   42486:        break;
                   42487:       case 5:
                   42488:        action = walk(e->as_type);
                   42489:        if(action == tna_error) return action;
                   42490:        break;
                   42491:       case 6:
                   42492:        action = walk(e->n_table);
                   42493:        if(action == tna_error) return action;
                   42494:        break;
                   42495:       case 7:
                   42496:        action = walk(e->il);
                   42497:        if(action == tna_error) return action;
                   42498:        break;
                   42499:       case 8:
                   42500:        action = walk(e->query_this);
                   42501:        if(action == tna_error) return action;
                   42502:        break;
                   42503:     }
                   42504:     return tna_continue;
                   42505: }
                   42506: 
                   42507: 
                   42508: tree_node_action walker::a_expr(Pnode ta, Pexpr e, Pnode& replacement) 
                   42509: {
                   42510:     tree_node_action action = pre_act_on_node(ta, nc_expr, Pnode(e), replacement);
                   42511: 
                   42512:     if(action == tna_stop) {
                   42513:        if(!fetching () && replacement)
                   42514:            e = Pexpr(replacement);
                   42515:        /* ELIST implies that e2 is a peer, not a child */
                   42516:        if(e->base == ELIST) {
                   42517:            action = walk(e->e2);
                   42518:            return action;
                   42519:        }
                   42520:     }
                   42521:        
                   42522:     if(action != tna_continue) return action;
                   42523: 
                   42524:     if(!fetching () && replacement)
                   42525:        e = Pexpr(replacement);
                   42526: 
                   42527:     action = a_expr_guts(e);
                   42528:     if (action == tna_error) return action;
                   42529:     if(e->base == ELIST)
                   42530:        action = walk(e->e2);
                   42531:     return action;
                   42532: }
                   42533: 
                   42534: tree_node_action walker::a_baseclass(Pnode ta, Pbcl b, Pnode& replacement) 
                   42535: {
                   42536:     tree_node_action action = pre_act_on_node(ta, nc_baseclass, Pnode(b), replacement);
                   42537: 
                   42538:     if(action != tna_continue) return action;
                   42539: 
                   42540:     if(!fetching () && replacement)
                   42541:        b = Pbcl(replacement);
                   42542: 
                   42543:     action = walk(b->bclass);
                   42544:     if(action == tna_error) return action;
                   42545: 
                   42546:     action = walk(b->init);
                   42547:     if(action == tna_error) return action;
                   42548: 
                   42549:     action = walk(b->next);
                   42550:     if(action == tna_error) return action;
                   42551: 
                   42552:     return tna_continue;
                   42553: }
                   42554: 
                   42555: 
                   42556: /* a name is also an expr. */
                   42557:    
                   42558: 
                   42559: tree_node_action walker::a_name(Pnode ta, Pname n, Pnode& replacement) 
                   42560: {
                   42561:     int derr;
                   42562:     int cl_error;
                   42563:     tree_node_action action = pre_act_on_node(ta, nc_name, Pnode(n), replacement);
                   42564: 
                   42565:     /* n_list is a sibling, not a child. We always process it
                   42566:        except in case of an error. */
                   42567:     if(action == tna_stop) {
                   42568:        cl_error = 0;
                   42569:        if(!fetching () && replacement)
                   42570:            n = Pname(replacement);
                   42571:        if((classify_node(Pnode(n), cl_error) == nc_name) && !cl_error) {
                   42572:            if(depth > 0 || !control.dont_chase_lists_top) {
                   42573:                action = walk(n->n_list); 
                   42574:                if(action == tna_error) return action;
                   42575:            }
                   42576:        }
                   42577:        return tna_stop;
                   42578:     }  
                   42579: 
                   42580:     if(action != tna_continue) return action;
                   42581: 
                   42582:     if(!fetching () && replacement)
                   42583:        n = Pname(replacement);
                   42584: 
                   42585: /* We don't walk n_tbl_list. Its not part of the graph.
                   42586:    */
                   42587: 
                   42588:     switch(derr = n->discriminator(0)) {
                   42589:       case 0:
                   42590:        break;
                   42591:       case 1:
                   42592:        action = walk(n->n_qualifier);
                   42593:        if(action == tna_error) return action;
                   42594:        break;
                   42595:       case 2:
                   42596:        action = walk(n->n_realscope);
                   42597:        if(action == tna_error) return action;
                   42598:        break;
                   42599:       default:
                   42600:        error ("a_name: discrim error %d on union 0.", derr);
                   42601:        return tna_error;
                   42602:     }
                   42603: 
                   42604:     action = a_expr_guts(Pexpr(n));
                   42605:     if(action == tna_error) return action;
                   42606: 
                   42607:     if(depth > 0 || !control.dont_chase_lists_top) {
                   42608:        action = walk(n->n_list);
                   42609:        if(action == tna_error) return action;
                   42610:     }
                   42611:     
                   42612:     return action;
                   42613: }
                   42614:     
                   42615: /* --- NOTE: s_list should be deferred until AFTER the post-action
                   42616:    procedure is called, if there is one. Since no one uses
                   42617:    post-actions yet I haven't bothered to make this fix.
                   42618:    --benson */
                   42619: 
                   42620: tree_node_action walker::a_stmt(Pnode ta, Pstmt s, Pnode& replacement) 
                   42621: {
                   42622:     int cl_error;
                   42623:     int derr;
                   42624:     tree_node_action action = pre_act_on_node(ta, nc_stmt, Pnode(s), replacement);
                   42625: 
                   42626:     if(action == tna_stop) {
                   42627:        if(!fetching () && replacement)
                   42628:            s = Pstmt(replacement);
                   42629:        cl_error = 0;
                   42630:        if((classify_node(Pnode(s), cl_error) == nc_stmt) && !cl_error) {
                   42631:            /* s_list is not our subordinate, it is our peer */
                   42632:            if(depth > 0 || !control.dont_chase_lists_top) {
                   42633:                action = walk(s->s_list); /* continue walk of sibs */
                   42634:                if (action == tna_error) return tna_error;
                   42635:            }
                   42636:        }
                   42637:        return tna_stop;
                   42638:     }
                   42639: 
                   42640:     if(action != tna_continue) return action;
                   42641: 
                   42642:     if(!fetching () && replacement)
                   42643:        s = Pstmt(replacement);
                   42644: 
                   42645:     action = walk(s->s);
                   42646:     if(action == tna_error) return action;
                   42647: 
                   42648:     action = walk(s->memtbl);
                   42649:     if(action == tna_error) return action;
                   42650: 
                   42651:     switch(derr = s->discriminator(0)) {
                   42652:       default:
                   42653:        error ("a_stmt: discrim error %d on union 0.", derr);
                   42654:        return tna_error;
                   42655:       case 4:
                   42656:       case 0: break;
                   42657:       case 1:
                   42658:        action = walk(s->d);
                   42659:        if(action == tna_error) return action;
                   42660:        break;
                   42661:       case 2:
                   42662:        action = walk(s->e2);
                   42663:        if(action == tna_error) return action;
                   42664:        break;
                   42665:       case 3:
                   42666:        action = walk(s->has_default);
                   42667:        if(action == tna_error) return action;
                   42668:        break;
                   42669:       case 5:
                   42670:        action = walk(s->ret_tp);
                   42671:        if(action == tna_error) return action;
                   42672:        break;
                   42673:     }
                   42674: 
                   42675:     switch(derr = s->discriminator(1)) {
                   42676:       default:
                   42677:        error ("a_stmt: discrim error %d on union 1.", derr);
                   42678:        return tna_error;
                   42679:       case 2:
                   42680:       case 0: break;
                   42681:       case 1:
                   42682:        action = walk(s->e);
                   42683:        if(action == tna_error) return action;
                   42684:        break;
                   42685:       case 3:
                   42686:        action = walk(s->s2);
                   42687:        if(action == tna_error) return action;
                   42688:        break;
                   42689:     }
                   42690: 
                   42691:     switch(derr = s->discriminator(2)) {
                   42692:       default:
                   42693:        error ("a_stmt: discrim error %d on union 2.", derr);
                   42694:        return tna_error;
                   42695:       case 0: break;
                   42696:       case 1:
                   42697:        action = walk(s->for_init);
                   42698:        if(action == tna_error) return action;
                   42699:        break;
                   42700:       case 2:
                   42701:        action = walk(s->else_stmt);
                   42702:        if(action == tna_error) return action;
                   42703:        break;
                   42704:       case 3:
                   42705:        action = walk(s->case_list);
                   42706:        if(action == tna_error) return action;
                   42707:        break;
                   42708:     }
                   42709: 
                   42710:     if(depth > 0 || !control.dont_chase_lists_top) {
                   42711:        action = walk(s->s_list);
                   42712:        if(action == tna_error) return action;
                   42713:     }
                   42714: 
                   42715:     return tna_continue;
                   42716: }
                   42717: 
                   42718: tree_node_action walker::a_ia(Pnode ta, struct ia * ia, Pnode& replacement) 
                   42719: {
                   42720:     tree_node_action action = pre_act_on_node(ta, nc_ia, Pnode(ia), replacement);
                   42721: 
                   42722:     if(action != tna_continue) return action;
                   42723: 
                   42724:     if(!fetching () && replacement)
                   42725:        ia = (struct ia *)&replacement;
                   42726: 
                   42727:     action = walk(ia->local);
                   42728:     if(action == tna_error) return action;
                   42729: 
                   42730:     action = walk(ia->arg);
                   42731:     if(action == tna_error) return action;
                   42732:     
                   42733:     action = walk(ia->tp);
                   42734:     if(action == tna_error) return action;
                   42735: 
                   42736:     return tna_continue;
                   42737: }
                   42738: 
                   42739: tree_node_action walker::a_iline(Pnode ta, Pin iline, Pnode& replacement) 
                   42740: {
                   42741:     tree_node_action action = pre_act_on_node(ta, nc_iline, Pnode(iline), replacement);
                   42742: 
                   42743:     if(action != tna_continue) return action;
                   42744: 
                   42745:     if(!fetching () && replacement)
                   42746:        iline = Pin(replacement);
                   42747: 
                   42748:     action = walk(iline->fct_name);
                   42749:     if(action == tna_error) return action;
                   42750: 
                   42751:     action = walk(iline->i_next);
                   42752:     if(action == tna_error) return action;
                   42753:     
                   42754:     action = walk(iline->i_table);
                   42755:     if(action == tna_error) return action;
                   42756: 
                   42757:     action = walk(iline->i_args);
                   42758:     if(action == tna_error) return action;
                   42759: 
                   42760:     return tna_continue;
                   42761: }
                   42762: 0707071010112046151004440001630000160000010107200466055423100001400000004551tree_walk.h/* ident "@(#)ctrans:src/tree_walk.h   1.2" */
                   42763: /* -*- Mode: C -*- Begin include file tree_walk.H */
                   42764: /*
                   42765:        $Source: /usr3/lang/benson/work/stripped_cfront/RCS/tree_walk.H,v $ $RCSfile: tree_walk.H,v $
                   42766:        $Revision: 1.1 $                $Date: 89/11/20 08:51:05 $
                   42767:        $Author: benson $               $Locker:  $
                   42768:        $State: Exp $
                   42769: */
                   42770: 
                   42771: #ifndef _TREE_WALK
                   42772: #define _TREE_WALK
                   42773: 
                   42774: #include "cfront.h"
                   42775: #include "node_classes.h"
                   42776: #include <iostream.h>
                   42777: #include "ios_printf.h"
                   42778: #include "hash.h"
                   42779: 
                   42780: enum tree_node_action {
                   42781:     tna_continue = 0,          /* plain vanilla */
                   42782:     tna_stop = 1,              /* don't proceed */
                   42783:     tna_error = 2,             /* stop entire walk now. */
                   42784: };
                   42785: 
                   42786: /* procedural interface to indirect via a pointer. */
                   42787: typedef int (*tree_fetch_proc) (void * info,
                   42788:                                void * pointer,
                   42789:                                unsigned long length,
                   42790:                                int zero_stop,  /* for character strings.*/
                   42791:                                void * target);
                   42792: 
                   42793: 
                   42794: const tree_fetch_proc null_tfp = (tree_fetch_proc) 0;
                   42795: 
                   42796: class tree_walk_tree {
                   42797:   public:
                   42798:     tree_walk_tree * parent;
                   42799:     char storage[1];           /* variable amt, specified by caller. */
                   42800: };
                   42801: 
                   42802: /* The trailing int here controls whether to remember the
                   42803:    node in the hash table to short-circuit meeting it again */
                   42804: 
                   42805: typedef void (*tree_pre_action)
                   42806:     (Pnode&, node_class, void *, tree_node_action&, int, Pnode, 
                   42807:      tree_walk_tree&, int&);
                   42808: 
                   42809: 
                   42810: typedef void (*tree_post_action)
                   42811:     (Pnode&, node_class, void *, tree_node_action&, int, Pnode, 
                   42812:      tree_walk_tree&);
                   42813: 
                   42814: typedef void (*errorp) (char, const char *);
                   42815: 
                   42816: class tree_walk_control {
                   42817:   public:
                   42818:     int version;
                   42819:     void * callback_info;
                   42820:     tree_fetch_proc fetcher;
                   42821:     tree_pre_action action_proc;
                   42822:     tree_post_action post_action_proc;
                   42823:     int (*i_error) (int, const char *); /* usually part of cfront */
                   42824:     int call_i_error;          /* if 0, just use the following */
                   42825:     ostream * error_stream;
                   42826:     Hash * nodes_seen_hash;    /* allows this to be global over
                   42827:                                 more than one call to the walker. */
                   42828:     int resolve_by_name;
                   42829:     int alloc_stack_bytes;
                   42830:     /* if on, n_list and s_list are ignored for the very top node. 
                   42831:        this is for the benefit of the printer. */
                   42832:     int dont_chase_lists_top;
                   42833:     tree_walk_control () {
                   42834:        version = 1;
                   42835:        callback_info = 0;
                   42836:        fetcher = null_tfp;
                   42837:        call_i_error = 0;
                   42838:        error_stream = &cerr;
                   42839:        nodes_seen_hash = 0;
                   42840:        resolve_by_name = 1;    /* the dumper turns this off */
                   42841:        alloc_stack_bytes = 0;
                   42842:        post_action_proc = 0;
                   42843:        dont_chase_lists_top = 0;
                   42844:     }
                   42845: };
                   42846: 
                   42847: tree_node_action walk_tree (tree_walk_control& c, Pnode& n);
                   42848: 
                   42849: #endif
                   42850: 0707071010112045721004440001630000160000010210200466055412600000600000054504typ.c/*ident      "@(#)ctrans:src/typ.c   1.4" */
                   42851: /**************************************************************************
                   42852: 
                   42853:        C++ source for cfront, the C++ compiler front-end
                   42854:        written in the computer science research center of Bell Labs
                   42855: 
                   42856:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   42857:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   42858: 
                   42859: typ.c:
                   42860: 
                   42861: 
                   42862: ***************************************************************************/
                   42863:  
                   42864: #include "cfront.h"
                   42865: #include "size.h"
                   42866: 
                   42867: Pbase short_type;
                   42868: Pbase int_type;
                   42869: Pbase char_type;
                   42870: Pbase long_type;
                   42871: 
                   42872: Pbase uchar_type;
                   42873: Pbase ushort_type;
                   42874: Pbase uint_type;
                   42875: Pbase ulong_type;
                   42876: 
                   42877: Pbase zero_type;
                   42878: Pbase float_type;
                   42879: Pbase double_type;
                   42880: Pbase ldouble_type;
                   42881: Pbase void_type;
                   42882: Pbase any_type;
                   42883: 
                   42884: Ptype Pint_type;
                   42885: Ptype Pchar_type;
                   42886: Ptype Pvoid_type;
                   42887: Ptype Pfctvec_type;
                   42888: 
                   42889: Ptable gtbl;
                   42890: Ptable ptbl;
                   42891: 
                   42892: Pname Cdcl;
                   42893: Pstmt Cstmt;
                   42894: 
                   42895: bit new_type;
                   42896: 
                   42897: void echeck(Ptype t1, Ptype t2)
                   42898: /*
                   42899:        t1 is an enum, t2 is assigned to it
                   42900: */
                   42901: {
                   42902:        if (t1 == t2) return;
                   42903: 
                   42904: //error('d',"echeck(%t,%t) %d %d",t1,t2,t1->base,t2->base);
                   42905: //error('d',"se %d promote: %d",suppress_error, enum_promote);
                   42906:        if (t1->base==EOBJ
                   42907:        && t2->base==EOBJ
                   42908:        && Pbase(t1)->b_name->tp == Pbase(t2)->b_name->tp) return;
                   42909: 
                   42910:        if (enum_promote) return;
                   42911:        error(strict_opt?0:'w',"%t assigned to %t (anachronism)",t2,t1);
                   42912: }
                   42913: 
                   42914: 
                   42915: Ptype np_promote(TOK oper, TOK r1, TOK r2, Ptype t1, Ptype t2, TOK p)
                   42916: /*
                   42917:        an arithmetic operator "oper" is applied to "t1" and "t2",
                   42918:        types t1 and t2 has been checked and belongs to catagories
                   42919:        "r1" and "r2", respectively:
                   42920:                A       ANY
                   42921:                Z       ZERO
                   42922:                I       CHAR, SHORT, INT, LONG, FIELD, or EOBJ
                   42923:                F       FLOAT DOUBLE LDOUBLE
                   42924:                P       PTR (to something) or VEC (of something)
                   42925:        test for compatability of the operands,
                   42926:        if (p) return the promoted result type
                   42927: */
                   42928: {
                   42929:        if (r2 == 'A') return t1;
                   42930: 
                   42931: //error('d',"promote(%t,%t,%k)",t1,t2,oper);
                   42932: 
                   42933:        switch (r1) {
                   42934:        case 'A':       return t2;
                   42935:        case 'Z':
                   42936:                switch (r2) {
                   42937:                case 'Z':               return int_type;
                   42938:                case 'I':
                   42939:                case 'F':
                   42940:                        if(oper==DEREF) return any_type;
                   42941:                        return (p) ? Pbase(t2)->arit_conv(0) : 0;
                   42942:                case 'P': switch (oper) {
                   42943:                        case PLUS:
                   42944:                        case ASPLUS:    if(t2!=Pvoid_type) break;
                   42945:                        default:        return any_type;
                   42946:                        }
                   42947:                        return t2;
                   42948:                case FCT:       error("zero%kF",oper); return any_type;
                   42949:                default:        error('i',"zero(%d)",r2);
                   42950:                }
                   42951:        case 'I':
                   42952:                switch (r2) {
                   42953:                case 'Z': t2 = 0;
                   42954:                case 'I':
                   42955:                case 'F': 
                   42956:                        if(oper==DEREF) return any_type;
                   42957:                        return (p) ? Pbase(t1)->arit_conv(Pbase(t2)) : 0;
                   42958:                case 'P': switch (oper) {
                   42959:                        case PLUS:
                   42960:                        case ASPLUS:    if(t2!=Pvoid_type) break;
                   42961:                        default:        error("int%kP",oper); return any_type;
                   42962:                        }
                   42963:                        return t2;
                   42964:                case FCT: error("int%kF",oper); return any_type;
                   42965:                default: error('i',"int(%d)",r2); return any_type;
                   42966:                }
                   42967:        case 'F':
                   42968:                switch (r2) {
                   42969:                case 'Z': t2 = 0;
                   42970:                case 'I':
                   42971:                case 'F': 
                   42972:                        if(oper==DEREF) return any_type;
                   42973:                        return (p) ? Pbase(t1)->arit_conv(Pbase(t2)) : 0;
                   42974:                case 'P': error("float%kP",oper); return any_type;
                   42975:                case FCT: error("float%kF",oper); return any_type;
                   42976:                default: error('i',"float(%d)",r2); return any_type;
                   42977:                }
                   42978:        case 'P':
                   42979:                switch (r2) {
                   42980:                case 'Z': return t1;
                   42981:                case 'I':
                   42982:                        switch (oper) {
                   42983:                        case PLUS:
                   42984:                        case MINUS:
                   42985:                        case ASPLUS:
                   42986:                        case ASMINUS:
                   42987:                                if (t1->check(Pvoid_type,0)==0) {
                   42988:                                        return any_type;
                   42989:                                }
                   42990:                                break;
                   42991:                        default: error("P%k int",oper); return any_type;
                   42992:                        }
                   42993:                        return t1;
                   42994:                case 'F': error("P%k float",oper); return any_type;
                   42995:                case 'P':
                   42996:                        if (t1->check(t2,ASSIGN)) {
                   42997:                                switch (oper) {
                   42998:                                case EQ:
                   42999:                                case NE:
                   43000:                                case LE:
                   43001:                                case GE:
                   43002:                                case GT:
                   43003:                                case LT:
                   43004:                                case QUEST:
                   43005:                                        if (t2->check(t1,ASSIGN) == 0) goto zz;
                   43006:                                }
                   43007:                                error("T mismatch:%t %k%t",t1,oper,t2);
                   43008:                                return any_type;
                   43009:                        }
                   43010:                        zz:
                   43011:                        switch (oper) {
                   43012:                        case MINUS:     
                   43013:                                return (t2!=Pvoid_type) ? int_type : any_type;
                   43014:                        case ASMINUS:   error("P -=P"); return any_type;
                   43015:                        case PLUS:      error("P +P"); return any_type;
                   43016:                        case ASPLUS:    error("P +=P"); return any_type;
                   43017:                        case LS:
                   43018:                        case RS:        return any_type;
                   43019:                        default:        return (t1!=Pvoid_type) ? t1 : any_type;
                   43020:                        }
                   43021:                case FCT:       return t1;
                   43022:                default:        error('i',"P(%d)",r2);
                   43023:                }
                   43024:        case FCT:
                   43025:                if(oper == QUEST) {
                   43026:                        switch (r2) {
                   43027:                        case 'Z':
                   43028:                                return any_type;
                   43029:                        case 'P':
                   43030:                                return t2;
                   43031:                        case 'I':
                   43032:                        case 'F':
                   43033:                                error("F%k%t",oper,t2);
                   43034:                        default:
                   43035:                                return t1;
                   43036:                        }
                   43037:                }
                   43038:                error("F%k%t",oper,t2);
                   43039:                return any_type;
                   43040:        default:
                   43041:                error('i',"np_promote(%d,%d)",r1,r2);
                   43042:        }
                   43043: }
                   43044: 
                   43045: TOK type::kind(TOK oper, TOK v)
                   43046: /*     v ==    'I'     integral
                   43047:                'N'     numeric
                   43048:                'P'     numeric or pointer
                   43049: */
                   43050: {
                   43051:        Ptype t = this;
                   43052:        if (this == 0) error('i',"type::kind(): this==0");
                   43053: xx:
                   43054:        switch (t->base) {
                   43055:        case ANY:       return 'A';
                   43056:        case ZTYPE:     return 'Z';
                   43057:        case FIELD:
                   43058:        case CHAR:
                   43059:        case SHORT:
                   43060:        case INT:
                   43061:        case LONG:
                   43062:        case EOBJ:      return 'I';
                   43063:        case FLOAT:
                   43064:        case LDOUBLE:
                   43065:        case DOUBLE:    if (v == 'I') error("float operand for %k",oper);       return 'F';
                   43066:        case VEC:
                   43067:        case PTR:       if (v != 'P') error("P operand for %k",oper);
                   43068:                        switch (oper) {
                   43069:                        case INCR:
                   43070:                        case DECR:
                   43071:                        case MINUS:
                   43072:                        case PLUS:
                   43073:                        case ASMINUS:
                   43074:                        case ASPLUS:
                   43075:                                if (t->base==PTR
                   43076:                                && (Pptr(t)->memof || Pptr(t)->typ->base==FCT))
                   43077:                                        error("%t operand of%k",this,oper);
                   43078:                                else
                   43079:                                        Pptr(t)->typ->tsizeof(); // get increment
                   43080:                                break;
                   43081:                        default:
                   43082:                                if (t->base==PTR
                   43083:                                && (Pptr(t)->memof || Pptr(t)->typ->base==FCT))
                   43084:                                        error("%t operand of%k",this,oper);
                   43085:                        case ANDAND:
                   43086:                        case OROR:
                   43087:                        case ASSIGN:
                   43088:                        case NE:
                   43089:                        case EQ:
                   43090:                        case IF:
                   43091:                        case WHILE:
                   43092:                        case DO:
                   43093:                        case FOR:
                   43094:                        case QUEST:
                   43095:                        case NOT:
                   43096:                                        break;
                   43097:                        }
                   43098:                        return 'P';
                   43099:        case RPTR:      error("R operand for %k",oper);                 return 'A';
                   43100:        case TYPE:      t = Pbase(t)->b_name->tp;                       goto xx;
                   43101:        case FCT:       if (v != 'P') error("F operand for %k",oper);   return FCT;
                   43102:        case OVERLOAD:  error("overloaded operand for %k",oper);        return 'A';
                   43103:        case CLASS:
                   43104:        case ENUM:      error("%k operand for %k",base,oper);           return 'A';
                   43105:        default:        error("%t operand for %k",this,oper);           return 'A';
                   43106:        }
                   43107: }
                   43108: 
                   43109: void type::dcl(Ptable tbl)
                   43110: /*
                   43111:        go through the type (list) and
                   43112:        (1) evaluate vector dimensions
                   43113:        (2) evaluate field sizes
                   43114:        (3) lookup struct tags, etc.
                   43115:        (4) handle implicit tag declarations
                   43116: */
                   43117: {
                   43118: static arg_fudge;
                   43119: 
                   43120:        Ptype t = this;
                   43121: 
                   43122:        if (this == 0) error('i',"T::dcl(this==0)");
                   43123:        if (tbl->base != TABLE) error('i',"T::dcl(%d)",tbl->base);
                   43124: 
                   43125: xx:
                   43126: //error('d',"type::dcl %k",t->base);
                   43127:        switch (t->base) {
                   43128:        case TYPE:
                   43129:                t = Pbase(t)->b_name->tp;
                   43130:                goto xx;
                   43131:        case PTR:
                   43132:        case RPTR:
                   43133:        {       Pptr p = Pptr(t);
                   43134:                t = p->typ;
                   43135:                if (t->base == TYPE) {
                   43136:                        Ptype tt = Pbase(t)->b_name->tp;
                   43137:                        if (tt->base == FCT) p->typ = tt;
                   43138:                        return;
                   43139:                }
                   43140:                goto xx;
                   43141:        }
                   43142: 
                   43143:        case VEC:
                   43144:        {       Pvec v = Pvec(t);
                   43145:                Pexpr e = v->dim;
                   43146:                if (e) {
                   43147:                        Ptype et;
                   43148:                        v->dim = e = e->typ(tbl);
                   43149:                        et = e->tp;
                   43150:                        if (et->integral(0) == 'A') {
                   43151:                                error("UN in array dimension");
                   43152:                        }
                   43153:                        else {
                   43154:                                long i;
                   43155:                                Neval = 0;
                   43156:                                i = e->eval();
                   43157:                                if (Neval == 0) {
                   43158:                                        if (largest_int<i)
                   43159:                                                error("array dimension too large");
                   43160:                                        v->size = int(i);
                   43161: 
                   43162:                                if ( lcl_tbl == 0 )
                   43163: 
                   43164:                                        DEL(v->dim);
                   43165:                                        v->dim = 0;
                   43166:                                }
                   43167: 
                   43168:                                if (new_type) {
                   43169:                                        if (Neval)
                   43170:                                                ;
                   43171:                                        else if (i == 0)
                   43172:                                                v->dim = zero;
                   43173:                                        else if (i < 0) {
                   43174:                                                error("negative array dimension");
                   43175:                                                i = 1;
                   43176:                                        }
                   43177:                                }
                   43178:                                else {
                   43179:                                        if (Neval)
                   43180:                                                error("%s",Neval);
                   43181:                                        else if (i == 0)
                   43182:                                                error('w',"array dimension == 0");
                   43183:                                        else if (i < 0) {
                   43184:                                                error("negative array dimension");
                   43185:                                                i = 1;
                   43186:                                        }
                   43187:                                }
                   43188:                        }
                   43189:                }
                   43190:                t = v->typ;
                   43191:        llx:
                   43192:                switch (t->base) {
                   43193:                case TYPE:
                   43194:                        t = Pbase(t)->b_name->tp;
                   43195:                        goto llx;
                   43196:                case FCT:
                   43197:                        v->typ = t;
                   43198:                        break;
                   43199:                case VEC:                               
                   43200:                        if (Pvec(t)->dim==0 && Pvec(t)->size==0) error("null dimension (something like [][] seen)");
                   43201:                        if (arg_fudge) {
                   43202:                                v->base = PTR;  // X[12][10] ==> X(*)[10]
                   43203:                                Pptr(v)->rdo = 0;
                   43204:                                Pptr(v)->memof = 0;
                   43205:                        }
                   43206:                }
                   43207:                goto xx;
                   43208:        }
                   43209: 
                   43210:        case FCT:
                   43211:        {       Pfct f = Pfct(t);
                   43212: void dargs(Pname, Pfct, Ptable);
                   43213:                if (f->argtype) dargs(0,f,tbl);
                   43214:                for (Pname n=f->argtype; n; n = n->n_list) {
                   43215:                        arg_fudge++;
                   43216:                        n->tp->dcl(tbl);
                   43217:                        arg_fudge--;
                   43218:                }
                   43219:                Pname cn = f->returns->is_cl_obj();
                   43220:                if (cn && Pclass(cn->tp)->has_itor())
                   43221:                        make_res(f);
                   43222:                else if (f->f_this == 0)
                   43223:                        f->f_args = f->argtype;
                   43224:                t = f->returns;
                   43225:                goto xx;
                   43226:        }
                   43227: 
                   43228:        case FIELD:
                   43229:        {       Pbase f = Pbase(t);
                   43230:                Pexpr e = Pexpr(f->b_name);
                   43231:                long i;
                   43232:                Ptype et;
                   43233:                e = e->typ(tbl);
                   43234:                f->b_name = Pname(e);
                   43235:                et = e->tp;
                   43236:                if (et->integral(0) == 'A') {
                   43237:                        error("UN in field size");
                   43238:                        i = 1;
                   43239:                }
                   43240:                else {
                   43241:                        Neval = 0;
                   43242:                        i = e->eval();
                   43243:                        if (Neval)
                   43244:                                error("%s",Neval);
                   43245:                        else if (i < 0) {
                   43246:                                error("negative field size");
                   43247:                                i = 1;
                   43248:                        }
                   43249:                        else if (f->b_fieldtype->tsizeof()*BI_IN_BYTE < i)
                   43250:                                error("field size > sizeof(%t)",f->b_fieldtype);
                   43251:                        DEL(e);
                   43252:                }
                   43253:                f->b_bits = int(i);
                   43254:                f->b_name = 0;
                   43255:                break;
                   43256:        }
                   43257:        }
                   43258: }
                   43259: 
                   43260: bit vrp_equiv;         // vector == pointer equivalence used in check()
                   43261: bit const_problem;     // types differs only in const
                   43262: int Vcheckerror;
                   43263: 
                   43264: bit type::check(Ptype t, TOK oper)
                   43265: /*
                   43266:        check if "this" can be combined with "t" by the operator "oper"
                   43267: 
                   43268:        used for check of
                   43269:                        assignment types                (oper==ASSIGN)
                   43270:                        declaration compatability       (oper==0)
                   43271:                         parameterized type formals      (oper==255)
                   43272:                           as for (oper==0) but
                   43273:                           special checking for ANY types
                   43274:                        argument types                  (oper==ARG)
                   43275:                        return types                    (oper==RETURN)
                   43276:                        overloaded function name match  (oper==OVERLOAD)
                   43277:                        overloaded function coercion    (oper==COERCE)
                   43278:                        virtual function match          (oper==VIRTUAL)
                   43279: 
                   43280:        NOT for arithmetic operators
                   43281: 
                   43282:        return 1 if the check failed
                   43283: 
                   43284:        checking of const const* and *const is a mess
                   43285: */
                   43286: {
                   43287:         const unsigned int strict_any_check = (oper == 255);
                   43288: 
                   43289:        Ptype t1 = this;
                   43290:        Ptype t2 = t;
                   43291:        Ptype tt1 = this;
                   43292:        Ptype tt2 = t;
                   43293:        int cnst1 = 0;
                   43294:        int cnst2 = 0;
                   43295:        TOK b1, b2;
                   43296:        bit first = 1;
                   43297:        TOK r;
                   43298:        int vv;
                   43299:        int ptr_count = 0;
                   43300:        int fct_seen = 0;
                   43301:        int over;
                   43302:        Pptr p1 = 0;
                   43303:        Pptr p2 = 0;
                   43304:        int p_count = 0;
                   43305: 
                   43306:         if (strict_any_check) oper = 0;
                   43307: 
                   43308: //error('d',"check %k %t %t",oper,t1,t2);
                   43309:        if (t1==0 || t2==0) error('i',"check(%p,%p,%d)",t1,t2,oper);
                   43310: 
                   43311:        if (oper==VIRTUAL) {
                   43312:                vv = 1;
                   43313:                Vcheckerror = 0;
                   43314:                oper = 0;
                   43315:        }
                   43316:        else
                   43317:                vv = 0;
                   43318: 
                   43319:        if (oper == OVERLOAD) {
                   43320:                over = 1;
                   43321:                oper = 0;
                   43322:        }
                   43323:        else
                   43324:                over = 0;
                   43325: 
                   43326:        const_problem = 0;
                   43327: 
                   43328:        while (t1 && t2) {
                   43329:        top:
                   43330: //error('d',"top: %t (%d) %t (%d)",t1,t1->base,t2,t2->base);
                   43331:                if (t1 == t2) {
                   43332:                        if (cnst1==cnst2) return 0;
                   43333:                        if (oper) {
                   43334: //error('d',"oper %d cnst1 %d cnst2 %d ptr %d",oper,cnst1,cnst2,tt1->is_ptr());
                   43335:                                if (tt1 = tt1->is_ptr()) {
                   43336: 
                   43337:                                        // const* = int*
                   43338:                                        if (cnst2<cnst1) return 0;
                   43339: 
                   43340:                                        // int* = int *const
                   43341:                                        if (cnst2==1 && tt2->tconst()) {
                   43342:                                                // check for int* = const *const
                   43343:                                                tt2 = tt2->is_ptr();
                   43344:                                                if (tt2->tconst()) return 1;
                   43345:                                                return 0;
                   43346:                                        }
                   43347:                                }
                   43348:                                else {  // int = const allowed
                   43349:                                        if (oper==ARG || cnst1<cnst2) return 0;
                   43350:                                }
                   43351:                        }
                   43352:                        else {
                   43353:                                if (p_count) {
                   43354:                                        int pr1 = p1->rdo ? 1 : 0;
                   43355:                                        int pr2 = p2->rdo ? 1 : 0;
                   43356:                                        if (pr1+cnst1==pr2+cnst2)
                   43357:                                                return 0;
                   43358:                                }
                   43359:                        //      const_problem = 1;
                   43360:                        }
                   43361: 
                   43362:                        const_problem = 1;
                   43363:                        return 1;
                   43364:                }
                   43365: 
                   43366:                 if  ((t1->base == ANY || t2->base == ANY)) {
                   43367:                           if (! strict_any_check) return 0;
                   43368:                           // Perform the check for strict_any, ie. the
                   43369:                           return ((t1 == t2) ? 0 : 1) ;
                   43370:                 }
                   43371: 
                   43372:                b1 = t1->base;
                   43373:                switch (b1) {
                   43374:                case TYPE:
                   43375:                        if (Pbase(t1)->b_const) cnst1++;
                   43376:                        t1 = Pbase(t1)->b_name->tp;
                   43377:                        goto top;
                   43378:                }
                   43379: 
                   43380:                b2 = t2->base;
                   43381:                switch (b2) {
                   43382:                case TYPE:
                   43383:                        if (Pbase(t2)->b_const) cnst2++;
                   43384:                        t2 = Pbase(t2)->b_name->tp;
                   43385:                        goto top;
                   43386:                }
                   43387: 
                   43388: //error('d',"oper %k b1 %k b2 %k",oper,b1,b2);
                   43389:                if (b1 != b2) {
                   43390:                        switch (b1) {
                   43391:                        case PTR:
                   43392:                                switch (b2) {
                   43393:                                case VEC:
                   43394:                                        if (ptr_count) return 1;
                   43395:                                        // ptr/vec equivalence does not
                   43396:                                        // apply to declaration matching
                   43397:                                        t1 = Pptr(t1)->typ;
                   43398:                                        t2 = Pvec(t2)->typ;
                   43399:                                        if (oper == 0 && over==0) return 1;
                   43400:                                        ptr_count++;
                   43401:                                        first = 0;
                   43402:                                        goto top;
                   43403:                                case FCT:
                   43404:                                        t1 = Pptr(t1)->typ;
                   43405:                                        if (t1->base!=VOID) 
                   43406:                                                if (first==0 || t1->base!=b2) return 1;
                   43407:                                        first = 0;
                   43408:                                        goto top;
                   43409:                                }
                   43410:                                first = 0;
                   43411:                                break;
                   43412: 
                   43413:                         case FCT:
                   43414:                                 switch( b2 ) {
                   43415:                                 case PTR:
                   43416:                                         t2 = Pptr(t2)->typ;
                   43417:                                         if (t1->base!=VOID
                   43418:                                        && (first==0||t2->base!=b1)) return 1;
                   43419:                                         first = 0;
                   43420:                                         goto top;
                   43421:                                 }
                   43422:                                 first = 0;
                   43423:                                 break;
                   43424: 
                   43425:                        case VEC:
                   43426:                                switch (b2) {
                   43427:                                case PTR:
                   43428:                                        if (ptr_count) return 1;
                   43429:                                        t1 = Pvec(t1)->typ;
                   43430:                                        t2 = Pptr(t2)->typ;
                   43431:                                        switch (oper) {
                   43432:                                        case ARG:
                   43433:                                        case ASSIGN:
                   43434:                                        case COERCE:
                   43435:                                                break;
                   43436:                                        case 0:
                   43437:                                                if (over) break;
                   43438:                                        default:
                   43439:                                                return 1;
                   43440:                                        }
                   43441:                                        ptr_count++;
                   43442:                                        first = 0;
                   43443:                                        goto top;
                   43444:                                }
                   43445:                                first = 0;
                   43446:                                break;
                   43447:                        }
                   43448:                        goto base_check; 
                   43449:                }
                   43450: 
                   43451:                switch (b1) {
                   43452:                case VEC:
                   43453: //error('d',"vec %k %d %d",oper,Pvec(t1)->size,Pvec(t2)->size);
                   43454:                        if (first==0 && Pvec(t1)->size!=Pvec(t2)->size) return 1;
                   43455:                        first = 0;
                   43456:                        t1 = Pvec(t1)->typ;
                   43457:                        t2 = Pvec(t2)->typ;
                   43458:                        ptr_count++;
                   43459:                        break;
                   43460: 
                   43461:                case PTR:
                   43462:                case RPTR:
                   43463:                        first = 0;
                   43464:                        p1 = Pptr(t1);
                   43465:                        p2 = Pptr(t2);
                   43466:                        p_count++;
                   43467: 
                   43468:                        if (p1->memof != p2->memof) {
                   43469: 
                   43470:                                if(p1->memof!=0 && p2->memof!=0
                   43471:                                    && p1->memof->baseof(p2->memof)==0)
                   43472:                                        return 1;
                   43473: 
                   43474:                                int flag1=0,flag2=0;
                   43475:                                t1 = p1->typ;
                   43476:                                t2 = p2->typ;
                   43477:                                while (t1->base == TYPE) {
                   43478:                                        flag1++;
                   43479:                                        t1 = Pbase(t1)->b_name->tp;
                   43480:                                }
                   43481:                                while (t2->base == TYPE) {
                   43482:                                        flag2++;
                   43483:                                        t2 = Pbase(t2)->b_name->tp;
                   43484:                                }
                   43485:                                if (t1 != t2 || (!flag1 && !flag2)) {
                   43486:                                        if (p1->memof==0
                   43487:                                        || p2->memof==0
                   43488:                                        || p1->memof->baseof(p2->memof)==0)
                   43489:                                                return 1;
                   43490:                                        Nstd++;
                   43491:                                }
                   43492:                        }
                   43493: 
                   43494:                        t1 = p1->typ;
                   43495:                        t2 = p2->typ;
                   43496:                        ptr_count++;
                   43497: 
                   43498:                        if (oper==0) {
                   43499:                                int pr1 = p1->rdo ? 1 : 0;
                   43500:                                int pr2 = p2->rdo ? 1 : 0;
                   43501:                                if (pr1+cnst1!=pr2+cnst2
                   43502:                                && cnst1+Pbase(t1)->b_const!=cnst2+Pbase(t2)->b_const) {
                   43503:                                        // const_problem only if nothing
                   43504:                                        // more serious is wrong
                   43505:                                        if (t1->check(t2,0) == 0) const_problem = 1;
                   43506:                                        return 1;
                   43507:                                }
                   43508: 
                   43509:                                if (b1==RPTR && t1->tconst()!=t2->tconst())
                   43510:                                        const_problem = 1;
                   43511:                        }
                   43512:                        break;
                   43513: 
                   43514:                case FCT:
                   43515:                        first = 0;
                   43516:                {       Pfct f1 = Pfct(t1);
                   43517:                        Pfct f2 = Pfct(t2);
                   43518:                        Pname a1 = f1->argtype;
                   43519:                        Pname a2 = f2->argtype;
                   43520:                        TOK k1 = f1->nargs_known;
                   43521:                        TOK k2 = f2->nargs_known;
                   43522:                        int n1 = f1->nargs;
                   43523:                        int n2 = f2->nargs;
                   43524: //error('d',"f1%t f2%t",f1,f2);
                   43525:                        if (f1->memof != f2->memof) {
                   43526:                                if (f1->memof==0 && f2->f_this==0)      //SSS
                   43527:                                        goto sss;
                   43528:                                if (vv == 0)    // match even if private base class
                   43529:                                        if (f1->memof==0
                   43530:                                        || f2->memof==0
                   43531:                                        || f1->memof->baseof(f2->memof)==0) return 1;
                   43532:                                Nstd++;
                   43533:                                sss:;   //SSS
                   43534:                        }
                   43535: 
                   43536:                        if (k1 != k2) return 1;
                   43537: 
                   43538:                        if (n1!=n2 && k1 && k2) {
                   43539:                                goto aaa;
                   43540:                        }
                   43541:                        else if (a1 && a2) {
                   43542:                                int i = 0;
                   43543:                                while (a1 && a2) {
                   43544:                                        i++;
                   43545:                                        if (a1->tp->check(a2->tp,over?OVERLOAD:0)) return 1;
                   43546:                                        a1 = a1->n_list;
                   43547:                                        a2 = a2->n_list;
                   43548:                                }
                   43549:                                if (a1 || a2) goto aaa;
                   43550:                        }
                   43551:                        else if (a1 || a2) {
                   43552:                        aaa:
                   43553: //error('d',"aaa k1 %d k2 %d",k1,k2);
                   43554:                                if (k1 == ELLIPSIS) {
                   43555:                                        switch (oper) {
                   43556:                                        case 0:
                   43557:                                                if (a2 && k2==0) break;
                   43558:                                                return 1;
                   43559:                                        case ASSIGN:
                   43560:                                                if (a2 && k2==0) break;
                   43561:                                                return 1;
                   43562:                                        case ARG:
                   43563:                                                if (a1) return 1;
                   43564:                                                break;
                   43565:                                //      case OVERLOAD:
                   43566:                                        case COERCE:
                   43567:                                                return 1;
                   43568:                                        }
                   43569:                                }
                   43570:                                else if (k2 == ELLIPSIS) {
                   43571:                                        return 1;
                   43572:                                }
                   43573:                                else if (k1 || k2) {
                   43574:                                        return 1;
                   43575:                                }
                   43576:                        }
                   43577: 
                   43578:                        t1 = f1->returns;
                   43579:                        t2 = f2->returns;
                   43580:                        fct_seen = 1;
                   43581: 
                   43582:                        switch (oper) { //CCC
                   43583:                        case 0:
                   43584:                                if (f1->f_const!=f2->f_const) {
                   43585:                                        if (t1->check(t2,0)==0) const_problem = 1;
                   43586:                                        return 1;
                   43587:                                //      if (vv == 0) return 1;
                   43588:                                //      Vcheckerror = 1;
                   43589:                                }
                   43590:                                break;
                   43591:                        default:        // really pointer to function
                   43592:                                if (f1->f_const && f2->f_const==0) return 1;
                   43593:                        }
                   43594: 
                   43595: 
                   43596:                        if (vv && t1->check(t2,0)) { Vcheckerror = 1; return 1; }
                   43597:                }
                   43598:                        break;
                   43599: 
                   43600:                case FIELD:
                   43601:                        goto field_check;
                   43602:                case CHAR:
                   43603:                case SHORT:
                   43604:                case INT:
                   43605:                case LONG:
                   43606:                        goto int_check;
                   43607:                case FLOAT:
                   43608:                case DOUBLE:
                   43609:                case LDOUBLE:
                   43610:                        goto float_check;
                   43611:                case EOBJ:
                   43612:                        goto enum_check;
                   43613:                case COBJ:
                   43614:                        goto cla_check;
                   43615:                case ZTYPE:
                   43616:                case VOID:
                   43617:                        return 0;
                   43618:                default:
                   43619:                        error('i',"T::check(o=%d %d %d)",oper,b1,b2);
                   43620:                }
                   43621:        }
                   43622: 
                   43623:        if (t1 || t2) {
                   43624:                const_problem = 0;      // not a problem: the type itself is bad
                   43625:                return 1;
                   43626:        }
                   43627:        return 0;
                   43628: 
                   43629: field_check:
                   43630:        switch (oper) {
                   43631:        case 0:
                   43632:        case ARG:
                   43633:                error('i',"check field?");
                   43634:        }
                   43635:        return 0;
                   43636: 
                   43637: enum_check:
                   43638: //error('d',"enum check %t %t",t1,t2);
                   43639:        if (Pbase(t1)->b_name->tp != Pbase(t2)->b_name->tp) goto base_check;
                   43640:        goto const_check;
                   43641: 
                   43642: float_check:
                   43643:        if (first==0 && b1!=b2 && b2!=ZTYPE) return 1;
                   43644:        // no break
                   43645: 
                   43646: int_check:
                   43647: //error('d',"int_check");
                   43648:        if (Pbase(t1)->b_unsigned != Pbase(t2)->b_unsigned) {
                   43649:                if (first == 0) return 1;
                   43650:                if (oper /*&& oper!=OVERLOAD*/)
                   43651:                        Nstd++;
                   43652:                else
                   43653:                        return 1;
                   43654:        }
                   43655:        // no break
                   43656: 
                   43657: const_check:
                   43658: //error('d',"const_check %t (%d) %t (%d)",t1,t1->tconst(),t2,t2->tconst());
                   43659:        if (oper==0) {
                   43660: //error('d',"oper==0: t1 %t t2 %t cnst1 %d cnst2 %d",t1,t2,cnst1,cnst2);
                   43661:                if (t1->tconst()+cnst1!=t2->tconst()+cnst2) {
                   43662:                        const_problem = 1;
                   43663:                        return 1;
                   43664:                }
                   43665:        }
                   43666:        else if (first==0) {
                   43667:                if (t1->tconst()+cnst1==0 && t2->tconst()+cnst2) {
                   43668: //error('d',"t1 %t t2 %t cnst1 %d cnst2 %d",t1,t2,cnst1,cnst2);
                   43669: //error('d',"tt1 %t %d cnst1 %d cnst2 %d",tt1,tt1->is_ptr(),cnst1,cnst2);
                   43670: //error('d',"tt2 %t",tt2);
                   43671:                        if (tt1->is_ptr()) {
                   43672:                                if (fct_const || vec_const) cnst2--;
                   43673: 
                   43674:                                // const* = int*
                   43675:                                if (cnst2-tt2->tconst()<cnst1-tt1->tconst()) return 0;
                   43676: 
                   43677:                                // int* = *const
                   43678:                                //if (cnst2==1 && tt2->tconst()) return 0;
                   43679: 
                   43680:                                // const T* = const T*
                   43681:                                if (t2->tconst()+cnst2==t1->tconst()+cnst1) return 0;
                   43682:                        }
                   43683:                        else {  // int = const allowed
                   43684:                                if (cnst1<cnst2) return 0;
                   43685:                        }
                   43686:                        const_problem = 1;
                   43687:                        return 1;
                   43688:                }
                   43689:                else {  // const* vs int *const
                   43690: /*
                   43691:  //error('d',"t1 %t cnst1 %d t2 %t cnst2 %d",t1,cnst1,t2,cnst2);
                   43692:                        if (tt1->is_ptr()) {
                   43693:                                int tt1c = tt1->tconst();
                   43694:                                int tt2c = tt2->tconst() - fct_const - vec_const;
                   43695:  //error('d',"tt1c %d tt2c %d",tt1c,tt2c);
                   43696:                                if (tt1c<tt2c) return 1;
                   43697:                                int t1c = t1->tconst();
                   43698:                                int t2c = t2->tconst() - fct_const - vec_const;
                   43699:  //error('d',"t1c %d t2c %d",t1c,t2c);
                   43700:                                if (cnst1+t1c<cnst2+t2c) return 1;
                   43701:                                if (tt2c<tt1c   // *const = *
                   43702:                                && cnst1+t1c>cnst2+t2c) // T = constT
                   43703:                                        return 1;
                   43704:                        }
                   43705: */
                   43706:                        
                   43707:                }
                   43708:        }
                   43709:        else {
                   43710: //error('d',"first t1 %t t2 %t cnst1 %d cnst2 %d",t1,t2,cnst1,cnst2);
                   43711:        }
                   43712: //error('d',"return 0");
                   43713:        return 0;
                   43714: 
                   43715: cla_check:
                   43716:        {       Pname n1 = Pbase(t1)->b_name;
                   43717:                Pname n2 = Pbase(t2)->b_name;
                   43718: //error('d',"cla_check %n %n ptr_count %d",n1,n2,ptr_count);
                   43719:                if (n1 == n2) goto const_check;
                   43720: 
                   43721:                 // once again, a more comprehensive check for classes,
                   43722:                 // since they may be parametrized.
                   43723:                 if ((t1->base == COBJ) && (t2->base == COBJ) &&
                   43724:                    ((Pclass(n1->tp)->same_class(Pclass(n2->tp)))))
                   43725:                         goto const_check;
                   43726: 
                   43727:                if (/*first || */1<ptr_count || fct_seen) return 1;
                   43728: 
                   43729:                switch (oper) {
                   43730:                case ARG:
                   43731:                case ASSIGN:
                   43732:                case RETURN:
                   43733:                case COERCE:
                   43734:                {
                   43735:                        ppbase = PUBLIC;
                   43736:                        if (Pclass(n2->tp)->is_base(n1->string)) {
                   43737:                                if (ppbase!=PUBLIC) {
                   43738:                                        const_problem = 0;
                   43739:                                //      vrp_equiv = 0;
                   43740:                                        return 1;       // private or protected base
                   43741:                                }
                   43742:                                Nstd++;
                   43743:                                goto const_check;
                   43744:                        }
                   43745:                }
                   43746:                        // no break
                   43747:                case 0:
                   43748:                case OVERLOAD:
                   43749:                        const_problem = 0;
                   43750:                //      vrp_equiv = 0;
                   43751:                        return 1;
                   43752:                }
                   43753: 
                   43754:                goto const_check;
                   43755:        }
                   43756: 
                   43757: base_check:
                   43758: //error('d',"base_check t1=%t t2=%t oper=%d %s",t1,t2,oper,first?"first":"");
                   43759: //error('d',"ptr_count %d",ptr_count);
                   43760:        if (oper)
                   43761:        if (first || 1!=ptr_count) {
                   43762:                if (b1==VOID || b2==VOID) return 1;
                   43763:        }
                   43764:        else {
                   43765:                if (b1 == VOID) {               // check for void* = T*
                   43766:                        register Ptype tpx = this;
                   43767:                tpxloop:
                   43768:                        switch (tpx->base) {    // t1 == void*
                   43769:                        default:
                   43770:                                        const_problem = 0;
                   43771:                                        return 1;
                   43772:                        case VOID:      break;
                   43773:                        case PTR:
                   43774:                        case VEC:       tpx = Pvec(tpx)->typ;
                   43775:                                        goto tpxloop;
                   43776:                        case TYPE:      tpx = Pbase(tpx)->b_name->tp;
                   43777:                                        goto tpxloop;
                   43778:                        }
                   43779: 
                   43780:                        tpx = t;
                   43781:                bloop:
                   43782:                        switch (tpx->base) {    // t2 == T*
                   43783:                        default:
                   43784:                                        const_problem = 0;
                   43785:                                        return 1;
                   43786:                        case VEC:
                   43787:                        case PTR:
                   43788:                        case FCT:       Nstd++;
                   43789:                                //      return 0;
                   43790:                                        goto const_check; // prevent void* = const*
                   43791:                        case TYPE:      tpx = Pbase(tpx)->b_name->tp;
                   43792:                                        goto bloop;
                   43793:                        }
                   43794:                }
                   43795: 
                   43796:                if (b2 != ZTYPE) {
                   43797:                        const_problem = 0;
                   43798:                        return 1;
                   43799:                }
                   43800:        }
                   43801: //error('d',"oper %d b1 %d b2 %d cp %d",oper,b1,b2,const_problem);
                   43802:        switch (oper) {
                   43803:        case 0:
                   43804:                if (b1 != b2) {
                   43805:                        const_problem = 0; // we have a bigger problem
                   43806:                //      vrp_equiv = 0;
                   43807:                }
                   43808:                return 1;
                   43809:        case COERCE:    // could probably be merged with the cases below
                   43810:                switch (b1) {
                   43811:                case EOBJ:
                   43812:                case ZTYPE:
                   43813:                case CHAR:
                   43814:                case SHORT:
                   43815:                case INT:
                   43816:                        switch (b2) {
                   43817:                                case LONG:
                   43818:                                case FLOAT:
                   43819:                                case DOUBLE:
                   43820:                                case LDOUBLE:
                   43821:                                case EOBJ:
                   43822:                                case ZTYPE:
                   43823:                                case CHAR:
                   43824:                                case SHORT:
                   43825:                                case INT:
                   43826:                                case FIELD:
                   43827:                                        Nstd++;
                   43828:                                        suppress_error++;
                   43829:                                        if (b1 == EOBJ) echeck(t1,t2);
                   43830:                                        suppress_error--;
                   43831:                                        goto const_check;
                   43832:                        }
                   43833:                        return 1;
                   43834:                case LONG:      // char, short, and int promotes to long
                   43835:                        switch (b2) {
                   43836:                                case FLOAT:
                   43837:                                case DOUBLE:
                   43838:                                case LDOUBLE:
                   43839:                        case ZTYPE:
                   43840:                        case EOBJ:
                   43841:                        case CHAR:
                   43842:                        case SHORT:
                   43843:                        case INT:
                   43844:                        case FIELD:
                   43845:                                Nstd++;
                   43846:                                goto const_check;
                   43847:                        }
                   43848:                        return 1;
                   43849:                case FLOAT:
                   43850:                //      switch (b2) {
                   43851:                //      case ZTYPE:
                   43852:                //              Nstd++;
                   43853:                //      case FLOAT:
                   43854:                //      case DOUBLE:
                   43855:                //              goto const_check;
                   43856:                //      }
                   43857:                //      return 1;
                   43858:                case DOUBLE:    // char, short, int, and float promotes to double
                   43859:                case LDOUBLE:
                   43860:                        switch (b2) {
                   43861:                        case LONG:
                   43862:                        case ZTYPE:
                   43863:                        case EOBJ:
                   43864:                        case CHAR:
                   43865:                        case SHORT:
                   43866:                        case INT:
                   43867:                //              Nstd++;
                   43868:                        case FLOAT:
                   43869:                        case DOUBLE:
                   43870:                        case LDOUBLE:
                   43871: Nstd++;
                   43872:                                goto const_check;
                   43873:                        }
                   43874:                        return 1;
                   43875:                case PTR:
                   43876:                        switch (b2) {
                   43877:                        case ZTYPE:
                   43878:                                Nstd++;
                   43879:                                goto const_check;
                   43880:                        }
                   43881:                case RPTR:
                   43882:                case VEC:
                   43883:                case COBJ:
                   43884:                case FCT:
                   43885:                        return 1;
                   43886:                }
                   43887:        case ARG:
                   43888:        case ASSIGN:
                   43889:        case RETURN:
                   43890:                switch (b1) {
                   43891:                case COBJ:
                   43892:                        return 1;
                   43893:                case EOBJ:
                   43894:                case ZTYPE:
                   43895:                case CHAR:
                   43896:                case SHORT:
                   43897:                case INT:
                   43898:                case LONG:
                   43899:                        suppress_error++;
                   43900:                        r = t2->num_ptr(ASSIGN);
                   43901:                        suppress_error--;
                   43902:                        switch (r) {
                   43903:                        case 'F':
                   43904:                        //      if (oper!=ARG) error('w',"%t assigned to%t",t2,t1);
                   43905:                                break;
                   43906:                        case 'A':
                   43907:                        case 'P':
                   43908:                        case FCT:       return 1;
                   43909:                        }
                   43910:                        if (b1 == EOBJ) echeck(t1,t2);  
                   43911:                        break;
                   43912:                case FLOAT:
                   43913:                case DOUBLE:
                   43914:                case LDOUBLE:
                   43915:                        suppress_error++;
                   43916:                        r = t2->numeric(ASSIGN);
                   43917:                        suppress_error--;
                   43918:                        switch (r) {    
                   43919:                        case 'A':
                   43920:                        case 'P':
                   43921:                        case FCT:       return 1;
                   43922:                        }
                   43923:                        break;
                   43924:                case VEC:
                   43925:                        if(oper==ARG && b2==ZTYPE) goto const_check;
                   43926:                        return 1;
                   43927:                case PTR:
                   43928:                        suppress_error++;
                   43929:                        r = t2->num_ptr(ASSIGN);
                   43930:                        suppress_error--;
                   43931:                        switch (r) {
                   43932:                        case 'A':
                   43933:                        case 'I':
                   43934:                        case 'F':       return 1;
                   43935:                        case FCT:       if (Pptr(t1)->typ->base != FCT) return 1;
                   43936:                        }
                   43937:                        break;
                   43938:                case RPTR:
                   43939:                        return 1;
                   43940:                case FCT:
                   43941:                        switch (oper) {
                   43942:                        case ARG:
                   43943:                        case ASSIGN:
                   43944:                                return 1;
                   43945:                        }
                   43946:                }       
                   43947:                break;
                   43948:        }
                   43949:        goto const_check;
                   43950: }
                   43951: 
                   43952: 0707071010112045731004440001630000160000010210500466055413100000700000022542typ2.c/*ident     "@(#)ctrans:src/typ2.c  1.3" */
                   43953: /**************************************************************************
                   43954: 
                   43955:        C++ source for cfront, the C++ compiler front-end
                   43956:        written in the computer science research center of Bell Labs
                   43957: 
                   43958:        Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   43959:        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   43960: 
                   43961: typ2.c:
                   43962: 
                   43963: ***************************************************************************/
                   43964:  
                   43965: #include "cfront.h"
                   43966: #include "size.h"
                   43967: 
                   43968: extern int chars_in_largest;
                   43969: int largest_int;
                   43970: 
                   43971: void typ_init()
                   43972: {      
                   43973:        chars_in_largest = strlen(LARGEST_INT);
                   43974:        largest_int = int(str_to_long(LARGEST_INT));
                   43975: 
                   43976:        defa_type = new basetype(INT,0);        // note defa_type!=int_type
                   43977:        int_type = new basetype(INT,0);         // but they both represent `int'
                   43978: 
                   43979:        PERM(int_type); int_type->defined = DEFINED ;
                   43980:        PERM(defa_type); defa_type->defined = DEFINED ;
                   43981: 
                   43982:        moe_type = new basetype(INT,0);
                   43983:        PERM(moe_type); moe_type->defined = DEFINED ;
                   43984:        moe_type->b_const = 1;
                   43985:        moe_type->check(0);
                   43986: 
                   43987:        uint_type = new basetype(INT,0);
                   43988:        PERM(uint_type); uint_type->defined = DEFINED ;
                   43989:        uint_type->type_adj(UNSIGNED);
                   43990:        uint_type->check(0);
                   43991: 
                   43992:        long_type = new basetype(LONG,0);
                   43993:        PERM(long_type); long_type->defined = DEFINED ;
                   43994:        long_type->check(0);
                   43995: 
                   43996:        ulong_type = new basetype(LONG,0);
                   43997:        PERM(ulong_type); ulong_type->defined = DEFINED ;
                   43998:        ulong_type->type_adj(UNSIGNED);
                   43999:        ulong_type->check(0);
                   44000: 
                   44001:        short_type = new basetype(SHORT,0);
                   44002:        PERM(short_type); short_type->defined = DEFINED ;
                   44003:        short_type->check(0);
                   44004: 
                   44005:        ushort_type = new basetype(SHORT,0);
                   44006:        PERM(ushort_type); ushort_type->defined = DEFINED ;
                   44007:        ushort_type->type_adj(UNSIGNED);
                   44008:        ushort_type->check(0);
                   44009: 
                   44010:        float_type = new basetype(FLOAT,0);
                   44011:        PERM(float_type); float_type->defined = DEFINED ;
                   44012: 
                   44013:        double_type = new basetype(DOUBLE,0);
                   44014:        PERM(double_type); double_type->defined = DEFINED ;
                   44015: 
                   44016:        ldouble_type = new basetype(LDOUBLE,0);
                   44017:        PERM(ldouble_type); ldouble_type->defined = DEFINED ;
                   44018: 
                   44019:        zero_type = new basetype(ZTYPE,0);
                   44020:        PERM(zero_type); zero_type->defined = DEFINED ;
                   44021:        zero->tp = zero_type;
                   44022: 
                   44023:        void_type = new basetype(VOID,0);
                   44024:        PERM(void_type); void_type->defined = DEFINED ;
                   44025: 
                   44026:        char_type = new basetype(CHAR,0);
                   44027:        PERM(char_type); char_type->defined = DEFINED ;
                   44028: 
                   44029:        uchar_type = new basetype(CHAR,0);
                   44030:        PERM(uchar_type); uchar_type->defined = DEFINED ;
                   44031:        uchar_type->type_adj(UNSIGNED);
                   44032:        uchar_type->check(0);
                   44033: 
                   44034:        Pchar_type = char_type->addrof();
                   44035:        PERM(Pchar_type); Pchar_type->defined = DEFINED ;
                   44036: 
                   44037:        Pint_type = int_type->addrof();
                   44038:        PERM(Pint_type); Pint_type->defined = DEFINED ;
                   44039: 
                   44040:        Pvoid_type = void_type->addrof();
                   44041:        PERM(Pvoid_type); Pvoid_type->defined = DEFINED ;
                   44042: 
                   44043:        Pfctvec_type = new fct(int_type,0,0);   // must be last, see basetype::normalize()
                   44044:        Pfctvec_type = Pfctvec_type->addrof();
                   44045:        Pfctvec_type = Pfctvec_type->addrof();
                   44046:        PERM(Pfctvec_type); Pfctvec_type->defined = DEFINED ;
                   44047: 
                   44048:        gtbl = new table(GTBLSIZE,0,0);
                   44049:        gtbl->t_name = new name("global");
                   44050:        ptbl = new table(CTBLSIZE,0,0);
                   44051:        ptbl->t_name = new name("ptbl");
                   44052: }
                   44053: 
                   44054: bit enum_promote;
                   44055: 
                   44056: Pbase basetype::arit_conv(Pbase t)
                   44057: /*
                   44058:        perform the "usual arithmetic conversions" C ref Manual 6.6
                   44059:        on "this" op "t"
                   44060:        "this" and "t" are integral or floating
                   44061:        "t" may be 0
                   44062: */
                   44063: {
                   44064:        while (base == TYPE) this = Pbase(Pbase(this)->b_name->tp);
                   44065: // error('d', "arit_conv: this: %k %d %t %d", base, base, this, this );
                   44066: 
                   44067:        bit l;
                   44068:        bit u;
                   44069:        bit f;
                   44070:        bit l1 = (base == LONG);
                   44071:        bit u1 = b_unsigned;
                   44072:        bit f1 = (base==FLOAT || base==DOUBLE || base==LDOUBLE);
                   44073:        if (t) {
                   44074:                while (t->base == TYPE) t = Pbase(Pbase(t)->b_name->tp);
                   44075: // error('d', "arit_conv: t: %k %d %t %d", t->base, t->base, t, t );
                   44076: 
                   44077:                bit l2 = (t->base == LONG);
                   44078:                bit u2 = t->b_unsigned;
                   44079:                bit f2 = (t->base==FLOAT || t->base==DOUBLE || base==LDOUBLE);
                   44080:                l = l1 || l2;
                   44081:                u = u1 || u2;
                   44082:                f = f1 || f2;
                   44083:        }
                   44084:        else {
                   44085:                l = l1;
                   44086:                u = u1;
                   44087:                f = f1;
                   44088:        }
                   44089: 
                   44090:        if (f) {
                   44091:                if (base==LDOUBLE || (t && t->base==LDOUBLE)) return ldouble_type;
                   44092:                if (base==DOUBLE || (t && t->base==DOUBLE)) return double_type;
                   44093:                return float_type;
                   44094:        }
                   44095:        if (l & u) return ulong_type;
                   44096:        if (l & !u) return long_type;
                   44097:        if (u) {
                   44098:                if (base==INT || (t && t->base==INT)) return uint_type;
                   44099:                if (SZ_SHORT==SZ_INT) // ANSIism
                   44100:                        if (base==SHORT || (t && t->base==SHORT)) return uint_type;
                   44101:                return int_type;
                   44102:        }
                   44103: 
                   44104:        if (t && t->base == EOBJ && base == EOBJ) enum_promote = 1;
                   44105:        return int_type;
                   44106: }
                   44107: 
                   44108: bit vec_const = 0;
                   44109: bit fct_const = 0;
                   44110: 
                   44111: bit type::tconst()
                   44112: /*
                   44113:        is this type a constant
                   44114: */
                   44115: {
                   44116:        Ptype t = this;
                   44117:        vec_const = 0;
                   44118:        fct_const = 0;
                   44119: //error('d',"tconst %t",t);
                   44120: xxx:
                   44121:        switch (t->base) {
                   44122:        case TYPE:
                   44123:                if (Pbase(t)->b_const) return 1;
                   44124:                t = Pbase(t)->b_name->tp;
                   44125:                goto xxx;
                   44126:        case VEC:
                   44127:                vec_const = 1;
                   44128:                return 1;
                   44129:        case PTR:
                   44130:        case RPTR:
                   44131:                return Pptr(t)->rdo;
                   44132:        case FCT:
                   44133:        case OVERLOAD:
                   44134:                fct_const = 1;
                   44135:                return 1;
                   44136:        default:
                   44137:                return Pbase(t)->b_const;
                   44138:        }
                   44139: }
                   44140: 
                   44141: TOK type::set_const(bit mode)
                   44142: /*
                   44143:        make someting a constant or variable, return old status
                   44144: */
                   44145: {
                   44146:        Ptype t = this;
                   44147:        int m;
                   44148: xxx:
                   44149:        switch (t->base) {
                   44150:        case TYPE:
                   44151:                m = Pbase(t)->b_const;
                   44152:                Pbase(t)->b_const = mode;
                   44153:                t = Pbase(t)->b_name->tp;
                   44154:                goto xxx;
                   44155:        case ANY:
                   44156:        case RPTR:
                   44157:        case VEC:
                   44158:                return t->base;         // constant by definition
                   44159:        case PTR:
                   44160:                m = Pptr(t)->rdo;
                   44161:                Pptr(t)->rdo = mode;
                   44162:                return m;
                   44163:        default:
                   44164:                m = Pbase(t)->b_const;
                   44165:                Pbase(t)->b_const = mode;
                   44166:                return m;
                   44167:        }
                   44168: }
                   44169: 
                   44170: Pptr type::is_ref()
                   44171: {
                   44172:        Ptype t = this;
                   44173: xxx:
                   44174:        switch (t->base) {
                   44175:        case TYPE:      t = Pbase(t)->b_name->tp; goto xxx;
                   44176:        case RPTR:      return Pptr(t);
                   44177:        default:        return 0;
                   44178:        }
                   44179: }
                   44180: 
                   44181: Pclass Mptr;
                   44182: 
                   44183: Pptr type::is_ptr()
                   44184: {
                   44185:        Ptype t = this;
                   44186: xxx:
                   44187:        switch (t->base) {
                   44188:        case TYPE:      t = Pbase(t)->b_name->tp; goto xxx;
                   44189:        case PTR:
                   44190:        case VEC:       Mptr = Pptr(t)->memof;
                   44191:                        return Pptr(t);
                   44192:        default:        return 0;
                   44193:        }
                   44194: }
                   44195: 
                   44196: Pptr type::is_ptr_or_ref()
                   44197: {
                   44198:        Ptype t = this;
                   44199: xxx:
                   44200:        switch (t->base) {
                   44201:        case TYPE:      t = Pbase(t)->b_name->tp; goto xxx;
                   44202:        case PTR:
                   44203:        case RPTR:
                   44204:        case VEC:       Mptr = Pptr(t)->memof;
                   44205:                        return Pptr(t);
                   44206:        default:        return 0;
                   44207:        }
                   44208: }
                   44209: 
                   44210: int type::align()
                   44211: {
                   44212:        Ptype t = this;
                   44213: xx:
                   44214: /*fprintf(stderr,"align %d %d\n",t,t->base);*/
                   44215:        switch (t->base) {
                   44216:        case TYPE:      t = Pbase(t)->b_name->tp; goto xx;
                   44217:        case COBJ:      t = Pbase(t)->b_name->tp; goto xx;
                   44218:        case VEC:       t = Pvec(t)->typ; goto xx;
                   44219:        case ANY:       return 1;
                   44220:        case CHAR:      return AL_CHAR;
                   44221:        case SHORT:     return AL_SHORT;
                   44222:        case INT:       return AL_INT;
                   44223:        case LONG:      return AL_LONG;
                   44224:        case FLOAT:     return AL_FLOAT;
                   44225:        case DOUBLE:    return AL_DOUBLE;
                   44226:        case LDOUBLE:   return AL_LDOUBLE;
                   44227:        case PTR:
                   44228:        case RPTR:      return AL_WPTR;
                   44229:        case CLASS:     return Pclass(t)->obj_align;
                   44230:        case ENUM:
                   44231:        case EOBJ:      return AL_INT;
                   44232:        case VOID:      error("illegal use of void"); return AL_INT;
                   44233:        default:        error('i',"(%d,%k)->type::align",t,t->base);
                   44234:        }
                   44235: }
                   44236: 
                   44237: bit fake_sizeof;
                   44238: 
                   44239: int type::tsizeof(int ptmc)
                   44240: /*
                   44241:        the sizeof type operator
                   44242:        return the size in bytes of the types representation
                   44243: */
                   44244: {
                   44245:        Ptype t = this;
                   44246: zx:
                   44247: //error('d',"zx %t %d",t,t->base);
                   44248:        if (t == 0) error('i',"typ.tsizeof(t==0)");
                   44249:        switch (t->base) {
                   44250:        case TYPE:
                   44251:                t = Pbase(t)->b_name->tp;
                   44252:                goto zx;
                   44253:        case COBJ:
                   44254:                t = Pbase(t)->b_name->tp;
                   44255:                if (t == 0) return 0;   // ``fake'' generated classes: _Sdd
                   44256:                goto zx;
                   44257: 
                   44258:        case ANY:       return 1;
                   44259:        case VOID:      return 0;
                   44260:        case ZTYPE:     return SZ_WPTR; /* assume pointer */
                   44261:        case CHAR:      return SZ_CHAR;
                   44262:        case SHORT:     return SZ_SHORT;
                   44263:        case INT:       return SZ_INT;
                   44264:        case LONG:      return SZ_LONG;
                   44265:        case FLOAT:     return SZ_FLOAT;
                   44266:        case DOUBLE:    return SZ_DOUBLE;
                   44267:        case LDOUBLE:   return SZ_LDOUBLE;
                   44268: 
                   44269:        case VEC:
                   44270:                {       Pvec v = Pvec(t);
                   44271:                        if (v->size == 0) {
                   44272:                                if (fake_sizeof == 0) error('w',"sizeof array with undeclared dimension");
                   44273:                                return SZ_WPTR; // vector argument has sizeof ptr
                   44274:                        }
                   44275:                        return v->size * v->typ->tsizeof();
                   44276:                }
                   44277:        case RPTR:      
                   44278:        case PTR:
                   44279:        {       
                   44280:                int k = (Pptr(t)->memof && !ptmc)?sizeof(short)+sizeof(short):0;
                   44281:                t = Pptr(t)->typ;
                   44282:        xxx:
                   44283:                switch (t->base) {
                   44284:                default:        return SZ_WPTR;
                   44285:                case CHAR:      return SZ_BPTR;
                   44286:                case FCT:       return SZ_WPTR+k;
                   44287:                case TYPE:      t = Pbase(t)->b_name->tp; goto xxx;
                   44288:                }
                   44289:        }
                   44290:        case FIELD:
                   44291:                error("sizeof(field)");
                   44292:                return Pbase(t)->b_bits/BI_IN_BYTE+1;
                   44293:        case FCT:
                   44294:                error("sizeof(function)");
                   44295:                return 0;
                   44296: 
                   44297:        case CLASS:     
                   44298:        {
                   44299:                 Pclass cl = Pclass(t);
                   44300:                if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) {
                   44301:                        error("%tU, size not known",cl);
                   44302:                        return SZ_INT;
                   44303:                }
                   44304:                if (cl->c_body == 1)    // detect first allocation or sizeof
                   44305:                        cl->dcl_print(0);
                   44306:                return cl->obj_size;
                   44307:        }
                   44308: 
                   44309:        case EOBJ:
                   44310:        case ENUM:      return SZ_INT;
                   44311: 
                   44312:        default:        return 0;       // deref can be called for any type
                   44313:                        //error('i',"sizeof(%d)",t->base);
                   44314:        }
                   44315: }
                   44316: 
                   44317: bit type::vec_type()
                   44318: {
                   44319:        Ptype t = this;
                   44320: xx:
                   44321:        switch (t->base) {
                   44322:        case ANY:
                   44323:        case VEC:
                   44324:        case PTR:
                   44325:        case RPTR:      return 1;
                   44326:        case TYPE:      t = Pbase(t)->b_name->tp; goto xx;
                   44327:        default:        return 0;
                   44328:        }
                   44329: }
                   44330: 
                   44331: int ref_initializer;
                   44332: 
                   44333: Ptype type::deref()
                   44334: /*     index==1:       *p
                   44335:        index==0:       p[expr]
                   44336: */
                   44337: {
                   44338: //error('d',"%t -> deref() refd %d",this,ref_initializer);
                   44339:        Ptype t = this;
                   44340: xx:
                   44341:        switch (t->base) {
                   44342:        case TYPE:
                   44343:                t = Pbase(t)->b_name->tp;
                   44344:                goto xx;
                   44345:        case PTR:
                   44346:        case RPTR:
                   44347:        case VEC:
                   44348:        {       if (t == Pvoid_type) error("void* dereferenced");
                   44349:                Ptype tt = t = Pvec(t)->typ;
                   44350:                if (ref_initializer == 0) {
                   44351:                        while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp;
                   44352:                        if (tt->base == COBJ) { 
                   44353:                                tt = Pbase(tt)->b_name->tp;
                   44354:                                if (tt && Pclass(tt)->defined&(DEFINED|SIMPLIFIED))
                   44355:                                        (void) t->tsizeof();
                   44356:                         }
                   44357:                }
                   44358:                // no break
                   44359:        }
                   44360:        case ANY:
                   44361:                return t;
                   44362:        default:
                   44363:                error("nonP dereferenced");
                   44364:                return any_type;
                   44365:        }
                   44366: }
                   44367: 
                   44368: Pfct type::memptr()
                   44369: // is ``this'' a pointer to member function
                   44370: {
                   44371:        Ptype t = this;
                   44372:        while (t->base == TYPE) t = Pbase(t)->b_name->tp;
                   44373:        if (t->base != PTR || Pptr(t)->memof==0) return 0;
                   44374: 
                   44375:        t = Pptr(t)->typ;
                   44376:        while (t->base == TYPE) t = Pbase(t)->b_name->tp;
                   44377:        return (t->base == FCT) ? Pfct(t) : 0;
                   44378: }
                   44379: 0707071010112045741004440001630000160000010177160466055413400001200000002731typedef.h/*ident  "@(#)ctrans:src/typedef.h       1.2" */
                   44380: /**************************************************************************
                   44381: 
                   44382:         C++ source for cfront, the C++ compiler front-end
                   44383:         written in the computer science research center of Bell Labs
                   44384: 
                   44385:         Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   44386:         THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   44387: 
                   44388: typedef.h:
                   44389: 
                   44390: *****************************************************************************/
                   44391: 
                   44392: typedef unsigned char TOK;
                   44393: typedef unsigned char bit;     // sometimes used as bits
                   44394: typedef class node * PP;
                   44395: typedef int (*PFI)();
                   44396: typedef void (*PFV)();
                   44397: typedef class node * Pnode;
                   44398: typedef struct key * Pkey;
                   44399: typedef class name * Pname;
                   44400: typedef class basetype * Pbase;
                   44401: typedef class basecl* Pbcl;
                   44402: typedef class type * Ptype;
                   44403: typedef class fct  * Pfct;
                   44404: typedef class field * Pfield;
                   44405: typedef class expr * Pexpr;
                   44406: typedef class qexpr * Pqexpr;
                   44407: typedef class texpr * Ptexpr;
                   44408: typedef class classdef * Pclass;
                   44409: typedef class enumdef * Penum;
                   44410: typedef class stmt * Pstmt;
                   44411: typedef class estmt * Pestmt;
                   44412: typedef class tstmt * Ptstmt;
                   44413: typedef class vec * Pvec;
                   44414: typedef class ptr * Pptr;
                   44415: typedef class block * Pblock;
                   44416: typedef class table * Ptable;
                   44417: typedef struct loc Loc;
                   44418: typedef class call * Pcall;
                   44419: typedef class gen* Pgen;
                   44420: typedef class ref * Pref;
                   44421: typedef class name_list * Plist;
                   44422: typedef class iline * Pin;
                   44423: typedef class nlist * Pnlist;
                   44424: typedef class slist * Pslist;
                   44425: typedef class elist * Pelist;
                   44426: typedef class virt * Pvirt;
                   44427: typedef char* Pchar;
                   44428: 
                   44429: 0707071010112045751004440001630000160000010201670466055413700001200000001374yystype.h/*ident  "@(#)ctrans:src/yystype.h       1.2" */
                   44430: /**************************************************************************
                   44431: 
                   44432:         C++ source for cfront, the C++ compiler front-end
                   44433:         written in the computer science research center of Bell Labs
                   44434: 
                   44435:         Copyright (c) 1984 AT&T, Inc. All Rights Reserved
                   44436:         THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
                   44437: 
                   44438: yystype:
                   44439: 
                   44440: *****************************************************************************/
                   44441: 
                   44442: typedef union {
                   44443:        char*   s;
                   44444:        TOK     t;
                   44445:        int     i;
                   44446:        loc     l;
                   44447:        Pname   pn;
                   44448:        Ptype   pt;
                   44449:        Pexpr   pe;
                   44450:        Pstmt   ps;
                   44451:        Pbase   pb;
                   44452:        Pnlist  nl;
                   44453:        Pslist  sl;
                   44454:        Pelist  el;
                   44455:        Pbcl    pbc;
                   44456:        Pptr    pp;
                   44457:        PP      p;      // fudge: pointer to all class node objects
                   44458:        Plist   pl;     // fudge: pointer to all class node objects
                   44459: } YYSTYPE;
                   44460: extern YYSTYPE yylval;
                   44461: 0707071010112045751004440001630000160000010201670466055413700001300000000000TRAILER!!!ss node objects
                   44462: } YYSTYPE;
                   44463: extern YYSTYPE yylval;
                   44464: 0707071010112045751004440001630000160000010201670466055413700001300000000000TRAILER!!!ss node objects
                   44465: } YYSTYPE;
                   44466: extern YYSTYPE yylval;
                   44467: 0707071010112045751004440001630000160000010201670466055413700001300000000000TRAILER!!!ss node objects
                   44468: } YYSTYPE;
                   44469: extern YYSTYPE yylval;
                   44470: 070707101011204575100444000163000016000001020167046

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.