Annotation of researchv10no/cmd/cfront/xptcfront/cfront.cpio, revision 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.