Annotation of researchv10no/cmd/cfront/optcfront/lalex.c, revision 1.1.1.1

1.1       root        1: /*ident        "@(#)ctrans:src/lalex.c 1.20" */
                      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: lalex.c:
                     11: 
                     12:        lookahead 
                     13: 
                     14: *****************************************************************************/
                     15: #include <stdio.h>
                     16: 
                     17: #ifdef c_plusplus
                     18: overload is_empty;
                     19: #endif
                     20: 
                     21: #include "cfront.h"
                     22: #include "yystype.h"
                     23: #include "tqueue.h"
                     24: #include "template.h"
                     25: 
                     26: #ifdef DBG
                     27: #define LDB(val,a) { if(Ldebug>=val) {a;} }
                     28: #else
                     29: #define LDB(val,a) /**/
                     30: #endif
                     31: 
                     32: #ifdef DBG
                     33: static char*
                     34: image( int t )
                     35: {
                     36:        if(keys[t]) return keys[t];
                     37:        else { static char b[20];
                     38:                sprintf(b,"token(%d)",t);
                     39:                return b;
                     40:        }
                     41: }
                     42: static void
                     43: printok( toknode* t )
                     44: {
                     45:        switch(t->tok) {
                     46:        default:
                     47:                fprintf(stderr,"\t%s",image(t->tok));
                     48:                break;
                     49:        case ID: case ICON: case CCON: case FCON: case STRING:
                     50:                fprintf(stderr,"ID '%s'",t->retval.s);
                     51:                break;
                     52:        case TNAME:
                     53:                fprintf(stderr,"TNAME '%s'",t->retval.pn->string);
                     54:                break;
                     55:        case PTNAME:
                     56:                fprintf(stderr,"PTNAME '%s'",t->retval.pn->string);
                     57:                break;
                     58:        case TSCOPE:
                     59:                fprintf(stderr,"TSCOPE '%s'::",t->retval.pn->string);
                     60:                break;
                     61:        case MEMPTR:
                     62:                fprintf(stderr,"MEMPTR '%s'::*",t->retval.pn->string);
                     63:                break;
                     64:        }
                     65:        putc(' ',stderr);
                     66:        t->place.put(stderr);
                     67:        putc('\n',stderr);
                     68: }
                     69: static void
                     70: showQ( char* where )
                     71: /*
                     72:        display token Q
                     73: */
                     74: {
                     75:        fprintf(stderr,"TOKEN Q (%s):\n",where);
                     76:        for (register toknode* t = front; t; t = t->next) printok(t);
                     77:        putc('\n',stderr);
                     78: }
                     79: #endif
                     80: 
                     81: int bl_level;
                     82: 
                     83: static int  laexpr( TOK );
                     84: static int  latype( TOK );
                     85: static int  la_decl();
                     86: static TOK  lookahead();
                     87: 
                     88: /* make this a toknode! */
                     89: static int lasttk = 0;         // one token history
                     90: static YYSTYPE lastval;        // yylval lasttk value 
                     91: 
                     92: int must_be_expr = 0;          // handle redundant parentheses
                     93: int must_be_id = 0;            // !0, TNAME => ID, i.e., int X
                     94: 
                     95: loc curloc;
                     96: int curr_file;
                     97: 
                     98: toknode* latok;                        // current lookahead token
                     99: toknode* front = 0;
                    100: toknode* rear  = 0;
                    101: 
                    102: const  TQCHUNK = 16;
                    103: 
                    104: void*
                    105: toknode::operator new(size_t)
                    106: {
                    107:        register toknode* p;
                    108: 
                    109:        if ((p=free_toks) == 0) {
                    110:                register toknode* q;
                    111:                free_toks = q = (toknode*)malloc( TQCHUNK * sizeof(toknode) );
                    112:                p = free_toks;
                    113:                for (; q != &p[TQCHUNK-1]; q->next = q+1, ++q);
                    114:                q->next = 0;
                    115:        }
                    116:        free_toks = p->next;
                    117:        return p;
                    118: }
                    119: 
                    120: toknode::toknode(TOK t, YYSTYPE r, loc tloc)
                    121: {
                    122:        tok = t;
                    123:        used = 0;
                    124:        retval = r;
                    125:        place = tloc;
                    126:        next = last = 0;
                    127: }
                    128: 
                    129: void
                    130: toknode::operator delete(void* vp,size_t)
                    131: {
                    132:        register toknode* p = (toknode*)vp;
                    133:        p->next = free_toks;
                    134:        free_toks = p;
                    135:        vp = 0;
                    136: }
                    137: 
                    138: #define USE_TOKEN(T,W) \
                    139:        LDB(2,error('d',&(T)->place,"use_token('%k','%s')",(T)->tok,W);); \
                    140:        if ( !(T)->used ) use_token(T);
                    141: 
                    142: Ptype
                    143: return_nstd_local_type( Pname n, TOK &sw )
                    144: { 
                    145:        Ptype tt;
                    146:        switch ( n->tp->base ) {
                    147:                case EOBJ:
                    148:                case COBJ:
                    149:                        tt = Pbase(n->tp)->b_name->tp;
                    150:                        sw = n->tp->base;
                    151:                        break;
                    152:                default:
                    153:                        tt = n->tpdef;
                    154:                        sw = NESTED; // in repr.c, prints ``typedef''
                    155:                        break;
                    156:        }
                    157:        return tt;
                    158: }
                    159: 
                    160: static Pname
                    161: local_nested_kludge( Pname n, Pname tn )
                    162: /*
                    163:  * for backward compatibility with 2.0
                    164:  * in transitional model of nested class types
                    165:  * 
                    166:  * struct T { ... };
                    167:  * foobar() {
                    168:  *     class X {
                    169:  *             typedef int T;
                    170:  *             // ...
                    171:  *     };
                    172:  *     T t;
                    173:  * }
                    174:  *
                    175:  * pure nested classes, choose global struct T{};
                    176:  * no nested classes, choose typedef int T
                    177:  * transitional model: choose typedef, and generate warning
                    178:  * BUG: local typedefs and enums do not have lex_level set
                    179:  */
                    180: {
                    181: // error( 'd', "local_nested_kludge: n: %n", n );
                    182:        for ( Pname nn = n; nn; nn = nn->n_tbl_list )
                    183:        {
                    184:                Pname local_class;
                    185:                TOK ntd;
                    186:                if ( nn->n_key != NESTED ) continue;
                    187:                Ptype tt = return_nstd_local_type(nn,ntd);
                    188:                Pclass cl = tt->in_class;
                    189:                while ( cl->in_class ) cl = cl->in_class;
                    190:                if (cl->lex_level && 
                    191:                        (local_class = ktbl->look(cl->string,LOCAL)))
                    192:                {
                    193:                        // same typedef at nested and non-nested scope
                    194:                        if (ntd == NESTED && tn && tn->tp == nn->tp )
                    195:                                ; 
                    196:                        else
                    197:                                error('w',"%s occurs at outer and nested localC scope; using %k %t::%s", n->string,ntd,cl,n->string);
                    198: 
                    199: /*
                    200:                        if ( ntd == NESTED && nn->n_dcl_printed != 2 ) {
                    201:                                nn->dcl_print(0);
                    202:                                nn->n_dcl_printed = 2;
                    203:                        }
                    204: */
                    205:                        return nn;
                    206:                }
                    207:        }
                    208:        return 0;
                    209: }
                    210: 
                    211: enum { one_back, two_back };
                    212:        
                    213: static void
                    214: use_token( toknode* T )
                    215: /*
                    216:        lookup TNAMEs here instead of in tlex()
                    217:        maintain block level
                    218: */
                    219: {
                    220:        static TOK last_tokens[2];  // TSCOPE not reduced at this point
                    221:        static Pname last_tname;    // tname :: id, where id is nested class
                    222:        static Pname tdef_name;     // typedef tname tdef_name
                    223:        T->used = 1;
                    224: 
                    225:        DB(if(Ldebug>=1) {
                    226:                error('d',&T->place,"\n*** use_token(%k )",T->tok);
                    227:                printok(T);
                    228:                error('D',&T->place,"    lasttk%k last_tname%n last tokens%k%k",lasttk,last_tname,last_tokens[one_back],last_tokens[two_back]);
                    229:        });
                    230: 
                    231:        switch ( T->tok ) {
                    232:        case ID:
                    233:                Pname n;
                    234: // error('d', &T->place, "use_token: %s", T->retval.s );
                    235:                if ( last_tokens[one_back] == MEM &&
                    236:                        last_tokens[two_back] == TNAME &&
                    237:                        (n=ktbl->look(T->retval.s,NESTED))) 
                    238:                { // TYPEDEF :: ID, nested class ctor 
                    239:                        if (tdef_name && tdef_name->n_key==NESTED &&
                    240:                                strcmp(tdef_name->string,n->string)==0)
                    241:                        {
                    242:                                T->tok = TNAME;
                    243:                                T->retval.pn = n;
                    244:                                break;
                    245:                        }       
                    246:                        else { // TNAME :: ID, where ID may be nested class
                    247:                        for ( Pname nn = n; nn; nn = nn->n_tbl_list )
                    248:                        {
                    249:                                TOK sw;
                    250:                                if ( nn->n_key != NESTED ) continue;
                    251:                                Ptype tt = return_nstd_local_type(nn,sw);
                    252:                                Pclass cl = tt->in_class;
                    253:                                if (cl == 0) { 
                    254:                                        error("%nU",nn);
                    255:                                        T->tok = TNAME;
                    256:                                        T->retval.pn=nn;
                    257:                                        break;
                    258:                                }
                    259:                                if (strcmp(last_tname->string,cl->string)==0)
                    260:                                {
                    261:                                        T->tok = TNAME;
                    262:                                        T->retval.pn = nn;
                    263:                                        break;
                    264:                                }       
                    265:                        }
                    266:                        }
                    267:                }
                    268:                else
                    269:                if ( bl_level && 
                    270:                        // TNAME:: and :: cannot refer to ``local'' TNAME
                    271:                        last_tokens[one_back] != MEM  && 
                    272:                        (n=ktbl->look(T->retval.s,LOCAL)) ) 
                    273:                {
                    274:                        DB( if(Ldebug>=1)error( 'd', &T->place, "use_token: local class instance: %n", n ) );
                    275:                        T->tok = TNAME;
                    276:                        T->retval.pn = n;
                    277:                } 
                    278:                else if ( n=ktbl->look(T->retval.s,0) ) {
                    279:                        DB( if(Ldebug>=1)error( 'd', &T->place, "use_token:GC instance: %n", n ) );
                    280: // error( 'd', &T->place, "use_token:GC instance: %n %t", n, n->tp );
                    281: 
                    282:                        // X:: ?, then n cannot be a global TNAME
                    283:                        //      except in the case of a constructor
                    284:                        if (last_tokens[one_back] == MEM &&
                    285:                                last_tokens[two_back] == TNAME &&
                    286:                                strcmp(T->retval.s,last_tname->string))
                    287:                                        ; // do nothing; i.e., return ID
                    288:                        else 
                    289:                        if ( bl_level && n->tp->base != COBJ &&
                    290:                                last_tokens[one_back] == MEM &&
                    291:                                last_tokens[two_back] != TNAME &&
                    292:                                gtbl->look(T->retval.s,0))
                    293:                                        ; // do nothing: local typedefs & enums not implemented
                    294:                        else {
                    295:                                Pname nn = 0;
                    296:                                TOK ntd;
                    297:                                if (bl_level && (nn=ktbl->look(T->retval.s,NESTED)))
                    298:                                {
                    299:                                        (void) return_nstd_local_type(n,ntd);
                    300:                                        nn = local_nested_kludge(nn,ntd==NESTED?n:0);
                    301:                                }
                    302:                                T->tok = TNAME;
                    303:                                T->retval.pn = nn?nn:n;
                    304:                        }
                    305:                }
                    306: #ifdef DBG
                    307:                else if(Ldebug>=1)
                    308:                        error('d',&T->place,"use_token: id %s",T->retval.s);
                    309: #endif
                    310:                break;
                    311:        case LC: ++bl_level; break;
                    312:        case RC: --bl_level; break;
                    313:        }
                    314:        
                    315:        if (T->tok != COMPL || last_tokens[one_back] != MEM) {
                    316:                last_tokens[two_back] = last_tokens[one_back];
                    317:                last_tokens[one_back] = T->tok; 
                    318:                if (T->tok == TNAME) last_tname = T->retval.pn;
                    319:                if ( last_tname && 
                    320:                        last_tname->tp->base == TYPE )
                    321:                {
                    322:                        tdef_name = last_tname;
                    323:                        do
                    324:                                tdef_name = Pbase(tdef_name->tp)->b_name;
                    325:                        while ( tdef_name->tp->base == TYPE );
                    326:                }
                    327:        }
                    328: }
                    329: 
                    330: void
                    331: addtok(TOK t, YYSTYPE r, loc tloc)
                    332: {
                    333:        toknode* T = new toknode(t,r,tloc);
                    334:        if (front == 0)
                    335:                front = rear = T;
                    336:        else {
                    337:                rear->next = T;
                    338:                T->last = rear;
                    339:                rear = T;
                    340:        }
                    341: //error('d',&tloc,"addtok: %k '%s'",t,t==ID?r.s:"");
                    342: //showQ("addtok");
                    343: }
                    344: 
                    345: extern TOK
                    346: deltok( int noset = 0 )
                    347: {
                    348:        register toknode* T = front;
                    349:        USE_TOKEN(T,"deltok");
                    350:        register TOK tk = T->tok;
                    351:        if ( !noset ) { yylval = T->retval; curloc = T->place; }
                    352:        curr_file = curloc.file;
                    353:        if (front = front->next)
                    354:                front->last = 0;
                    355:        else
                    356:                latok = rear = 0;
                    357:        delete T;
                    358:        return tk;
                    359: }
                    360: 
                    361: static void
                    362: add_tokens()
                    363: /*
                    364:     extend lookahead token queue when depleted
                    365: */
                    366: {
                    367:     TOK tk = tlex();
                    368:     if ( tk != ID )
                    369:        return;
                    370: 
                    371:     while (tk == ID || tk == MEM || tk == DOT )  
                    372:        tk = tlex(); 
                    373: }
                    374: 
                    375: extern TOK
                    376: la_look()
                    377: /*
                    378:        peek at head of token queue
                    379: */
                    380: {
                    381:     LDB(1,fprintf(stderr,"\n*** la_look()"));
                    382:     if ( front == 0 )
                    383:        add_tokens();
                    384: 
                    385:     latok = front;
                    386:     USE_TOKEN(latok,"la_look");
                    387:     LDB(1,fprintf(stderr," -- %s\n",image(latok->tok)));
                    388:     return latok->tok;
                    389: }
                    390: 
                    391: #define NEXTTOK() ( (yychar==-1) ? (yychar=lalex(),yychar) : yychar )
                    392: void
                    393: check_decl()
                    394: /*
                    395:        Lookahead to direct parsing of local/arg type declarations
                    396:        la_decl() returns 1 if lookahead sees a declaration.
                    397: */
                    398: {
                    399:        TOK tk2;
                    400:        switch( NEXTTOK() ) {
                    401:        default:
                    402:        break;
                    403:        case TSCOPE: //XXX
                    404:                tk2 = la_look();
                    405:                while ( tk2 == TSCOPE ) tk2 = lookahead();
                    406:                if ( tk2 == TNAME ) {
                    407:                    toknode* t = latok;
                    408:                    if(t->tok!=TNAME)
                    409:                        error('i',&t->place,"check_decl() token scan");
                    410:                    tk2 = lookahead();
                    411:                    if ( tk2 == LP && la_decl() ) {
                    412:                        t->tok = DECL_MARKER; //TNAME
                    413:                    }
                    414:                }
                    415:                break;
                    416:        case TYPE: case TNAME:
                    417:            if ( la_look() == LP && la_decl() ) {
                    418:                must_be_id = 0;
                    419:                DECL_TYPE=yychar;
                    420:                yychar = DECL_MARKER;
                    421:            }
                    422:        }
                    423: }
                    424: 
                    425: void
                    426: check_cast()
                    427: /*
                    428:        Lookahead to direct parsing of cast
                    429:        la_cast() returns 1 if lookahead sees an ambiguous old-style C cast.
                    430: */
                    431: {
                    432:        TOK tk2;
                    433:        switch( NEXTTOK() ) {
                    434:        case TSCOPE: //XXX
                    435:                tk2 = la_look();
                    436:                while ( tk2 == TSCOPE ) tk2 = lookahead();
                    437:                if ( tk2 == TNAME ) {
                    438:                    toknode* t = latok;
                    439:                    if(t->tok!=TNAME)
                    440:                          error('i',&t->place,"check_cast() token scan");
                    441:                    tk2 = lookahead();
                    442:                    if ( tk2 == LP && la_decl() ) {
                    443:                        t->tok = DECL_MARKER;//TNAME
                    444:                    }
                    445:                }
                    446:                break;
                    447:        case TYPE: case TNAME:
                    448:            if ( la_look() == LP && la_cast() ) {
                    449:                must_be_id = 0;
                    450:                DECL_TYPE = yychar;
                    451:                yychar = DECL_MARKER;
                    452:            }
                    453:        }
                    454: }
                    455: 
                    456: 
                    457: static int
                    458: latype( TOK t )
                    459: {
                    460:        switch ( t ) {
                    461:        default: // includes friend, typedef, storage classes, etc.
                    462:                return 0;
                    463:        case CHAR: case SHORT: case INT: case LONG:
                    464:        case FLOAT: case DOUBLE:
                    465:         case UNSIGNED:
                    466:                return 1;
                    467:        }
                    468: }
                    469: 
                    470: static int
                    471: laexpr( TOK t )
                    472: {
                    473:        switch ( t ) {
                    474:        default: 
                    475:                return 0;
                    476:        case RETURN: case NEW: case AND: case ANDAND: case OR: case OROR:
                    477:        case SIZEOF: case NOT: case COMPL: case MUL: case PLUS: case MINUS: 
                    478:        case ER: case ASSIGN: case ASOP: case RELOP: case EQUOP: case DIVOP: 
                    479:        case SHIFTOP: case ICOP:
                    480:                return 1;
                    481:        }
                    482: }
                    483: 
                    484: static toknode *get_next_token(toknode *t) {
                    485:   if (! t->next)
                    486:     add_tokens() ;
                    487:   
                    488:   return t->next ;
                    489: }
                    490: 
                    491: 
                    492: static int template_tscope(Pname tn, toknode *lt) 
                    493: /* provide the looakhead for determining TSCOPE tokens when the name is a
                    494:  * parametrized type name; the lookahead here is non-trivial, because it
                    495:  * involves stepping over the template arguments. 
                    496:  */
                    497: {
                    498:   int nest = 0 ; // the LT has been fetched
                    499: 
                    500:   if (lt->tok != LT) error ('i', "a `<' token was expected") ;  
                    501: 
                    502:   // assume the worst, ensure that name strings are consed in the heap
                    503:   templp->parameters_in_progress++ ;
                    504:   
                    505:   for (toknode *t = lt;; t = get_next_token(t))    
                    506:     switch (t->tok) {
                    507:       
                    508:     case LT:
                    509:        ++nest;
                    510:        continue;
                    511:     case GT:
                    512:        // ***************
                    513:        // need to fold in awareness of x::y::z
                    514:        if (--nest == 0) {
                    515:                t = get_next_token(t);
                    516:                if (t->tok == MEM) {
                    517:                // determine whether it is a memptr
                    518:                        if (t->next == 0) add_tokens();
                    519:                        if (t->next->tok == MUL) {
                    520:                                t->tok = MEMPTR;
                    521:                                t->next = t->next->next ;
                    522:                } else  t->tok = TSCOPE ;
                    523:                t->retval.pn  = tn ;
                    524:                --templp->parameters_in_progress;
                    525:                return 1;
                    526:        } 
                    527:        else  return 0 ;
                    528:       }
                    529:       continue;
                    530: 
                    531:     case SM: case LC: case RC: // a quick exit in case of error
                    532:     case EOFTOK:
                    533:        --templp->parameters_in_progress;
                    534:        return 0 ;
                    535:       
                    536:     default:
                    537:        continue;
                    538:     }
                    539: }
                    540: 
                    541: static TOK
                    542: lookahead()
                    543: /*
                    544:     advance lookahead pointer, lexing at end of Q
                    545:     handle occurrences of TNAME and TSCOPE
                    546:     (should be kept up to date with lalex())
                    547: */
                    548: {
                    549:     TOK tk;
                    550:     TOK tk2;
                    551:     TOK prev_tk = 0;
                    552:     YYSTYPE lastval;
                    553: 
                    554:     if ( latok == rear ) {
                    555:        add_tokens();
                    556:        if ( latok )
                    557:            latok = latok->next;
                    558:        else
                    559:            latok = front;
                    560:     }
                    561:     else
                    562:        latok = latok->next;
                    563: 
                    564:     if ( latok->last ) {
                    565:        prev_tk = latok->last->tok;
                    566:        lastval = latok->last->retval;
                    567:     }
                    568: 
                    569: nexttok:
                    570:     USE_TOKEN(latok,"lookahead1");
                    571:     tk = latok->tok;
                    572:     if ( tk == ID || tk == TNAME ) 
                    573:     {
                    574:        if (latok->next == 0) add_tokens();
                    575:        USE_TOKEN(latok->next,"lookahead2");
                    576:        /* TOK */ tk2 = latok->next->tok;
                    577:        if ( tk == TNAME ) {
                    578:           if (tk2 == LT) {
                    579:              // a parametrized type name -- differentiate from TNAME 
                    580:              // so that it can be dealt with in the grammar. 
                    581:              if (template_tscope(latok->retval.pn, latok->next)) tk = PTNAME;
                    582:           }
                    583:            else  
                    584:           if ( tk2 == MEM || tk2 == DOT ) {
                    585: tscope:        
                    586:                tk = TSCOPE;
                    587: // error('d',"lookahead: tk: %k tk2: %k", tk, tk2 );
                    588: // XXX -- should be modified to loop and do lookup
                    589:                latok = latok->next;
                    590:                if (latok->next == 0) add_tokens();
                    591:                USE_TOKEN(latok->next,"lookahead3");
                    592:                tk2 = latok->next->tok;
                    593:                if ( tk2 == MUL ) {
                    594:                        tk = MEMPTR;
                    595:                        latok = latok->next;
                    596:                }
                    597:            }
                    598:            else if (( prev_tk == MUL && tk2 != RP )
                    599:                        || prev_tk == AND )
                    600:                {
                    601:                tk = ID;
                    602:                latok->retval.pn->hide();
                    603:                latok->tok = ID;
                    604:                latok->retval.s = latok->retval.pn->string;
                    605:                }
                    606:        }
                    607:        else if ( tk2 == MEM ) {
                    608:                // ID ::
                    609:        //XXX   latok = latok->next->next;
                    610:        //XXX   goto nexttok;
                    611:                goto tscope; // treat as tscope
                    612:        }
                    613: 
                    614:        if ( tk == ID &&
                    615:                ( tk2 == ID ||
                    616:                ( prev_tk == ID && ( tk2 == COLON || tk2 == LC )))) {
                    617:                        // ID ID
                    618:                        latok = latok->next;
                    619:                        goto nexttok;
                    620:                        }
                    621:     }
                    622: 
                    623:        if ( tk == ID ) {
                    624:                Pname nstd = ktbl->look(latok->retval.s,NESTED);
                    625:                if (nstd && (must_be_id == 0 ||
                    626:                        must_be_id && prev_tk == LP)) {
                    627: extern Pname check_for_nested(Pname,TOK,YYSTYPE,TOK); // use this in lalex, too
                    628:                                Pname n = check_for_nested(nstd,prev_tk,lastval,tk2);
                    629:                                if ( n ) {
                    630:                                        tk = latok->tok = TNAME;
                    631:                                        latok->retval.pn = n;
                    632:                                }
                    633:                }
                    634:        }
                    635: 
                    636:     return tk;
                    637: }
                    638: 
                    639: static Pname mem_sel = 0;
                    640: 
                    641: static Pname
                    642: do_local_class( Pname n, int lex_level ) 
                    643: { /*
                    644:    * modify to ``do_local_type:
                    645:    *   do local types: enums and typedefs
                    646:    */
                    647:        Pname nn = n;
                    648:        if ( n->tp ) { // already a TNAME
                    649:                Pclass cl = n->tp->base==COBJ ? Pclass(Pbase(n->tp)->b_name->tp) : 0;
                    650:                if ( n->lex_level != lex_level || (cl && cl->lcl) ) {
                    651:                        local_hide( n );
                    652:                        nn = new name( n->string );
                    653:                        nn->lex_level = lex_level>=0?lex_level:0;
                    654:                }
                    655:                else 
                    656:                if ( lex_level == n->lex_level && cl->defined ) {
                    657:                        error( "localC %n redefined", n );
                    658:                        return n;
                    659:                }
                    660:        }
                    661: 
                    662:        nn = nn->tname( lastval.t );
                    663:        modified_tn = modified_tn->l;
                    664:        nn->n_key = LOCAL;
                    665:        local_class = new name_list( nn, local_class );
                    666:        local_blk = new name_list( nn, local_blk );
                    667: 
                    668: // error('d', "do_local_class: nn %n tp %t", nn, Pclass(Pbase(nn->tp)->b_name->tp));
                    669:        return nn;
                    670: }
                    671: 
                    672: static char*
                    673: make_nested_name( char *s, Pclass cl )
                    674: { // Q<cnt>_<class_names><space><null>
                    675:        const nested_depth = 9;
                    676:        char *str_arr[nested_depth];
                    677:        int  size_arr[nested_depth];
                    678:        int cnt = 2;
                    679:        int size = 4; // Q,<cnt>,<_>,<null>
                    680: 
                    681:        str_arr[0] = s; str_arr[1] = cl->string; 
                    682: 
                    683:        size += size_arr[0] = strlen(s); 
                    684:        size += size_arr[1] = cl->strlen?cl->strlen:strlen(cl->string);
                    685: 
                    686:        for (Pclass nc = cl->in_class; nc; nc = nc->in_class ) {
                    687:                if (cnt > nested_depth-1) error('s',"nested depth class beyond %d unsupported",nested_depth);
                    688:                size += size_arr[cnt] = nc->strlen?nc->strlen:strlen(nc->string);
                    689:                str_arr[cnt++] = nc->string; 
                    690:        }
                    691: 
                    692:        for ( int i=0; i<cnt; i++ ) // <nnn><string>
                    693:                size += size_arr[i]>99?3:size_arr[i]<10?1:2;
                    694: 
                    695: //error('d', "make_nested_name( %s, %t ) cnt: %d size: %d", s, cl, cnt, size );
                    696:        char *result = new char[size];
                    697:        sprintf(result, "Q%d_", cnt );
                    698:        size = 3;
                    699:        for ( i=cnt; i; i-- ) {
                    700:                sprintf(result+size,"%d%s", size_arr[i-1], str_arr[i-1]);
                    701:                size += size_arr[i-1] + (size_arr[i-1]>99?3:size_arr[i-1]<10?1:2);
                    702:        }
                    703: 
                    704: //error('d', "size: %d ", size );
                    705:        result[size] = '\0';
                    706: //error('d', "make_nested_name result: %s", result );
                    707:        return result;
                    708: }
                    709: 
                    710: int is_empty( Pclass cl, bit const_chk )
                    711: { /*   for nested class check, empty means *no* members
                    712:    *    for const object check, means no *data* members
                    713:    */
                    714: 
                    715: // error('d',"%t->is_empty: max: %d real_size: %d", cl, cl->memtbl->max(),cl->real_size );
                    716: 
                    717:        int mbr_cnt = cl->memtbl->max();
                    718:        if ( mbr_cnt == 0 ) return 1;
                    719: 
                    720:        if ( cl->baselist == 0 && cl->real_size!=1 )
                    721:                return 0;
                    722: 
                    723:        // empty class to turn on transitional nested class scope
                    724:        if ( const_chk == 0 && 
                    725:                ( cl->baselist != 0 || mbr_cnt > 1 )) return 0;
                    726: 
                    727:        int i = 1;
                    728:        for (Pname nn=cl->memtbl->get_mem(i); nn; nn=cl->memtbl->get_mem(++i)) {
                    729:                if (nn->base==NAME && 
                    730:                        nn->n_union==0 && 
                    731:                        nn->tp->base!=FCT && 
                    732:                        nn->tp->base!=OVERLOAD && 
                    733:                        nn->tp->base!=CLASS && 
                    734:                        nn->tp->base!=ENUM && 
                    735:                        nn->tp->base!=EOBJ && 
                    736:                        nn->n_stclass != STATIC) 
                    737:                        {
                    738:                                if ( nn->string[0]=='_' &&
                    739:                                        nn->string[1]=='_' &&
                    740:                                        nn->string[2]=='W' )
                    741:                                                return 1;
                    742:                                else return 0;
                    743:                        }
                    744:        }
                    745: 
                    746:        return 1; // if here, no data members encountered
                    747: }
                    748: 
                    749: static int
                    750: is_empty( Penum en )
                    751: { // is this an empty enum ??
                    752: 
                    753: // error('d', "%t no_of_enumerators: %d", en, en->no_of_enumerators);
                    754:        if ( en->no_of_enumerators != 0 )
                    755:                return 0;
                    756: 
                    757:        return 1;
                    758: }
                    759: 
                    760: static Pname
                    761: check_nested_type( Pname nm )
                    762: {
                    763: // error('d', "check nested type: %n ccl: %t", nm, ccl );
                    764: 
                    765:        Pname nx, n = ktbl->look(nm->string, NESTED);
                    766:        if ( n == 0 || n == nm ) return nm;
                    767: 
                    768:        int cnt = 1;
                    769:        for (nx = n; n; n=n->n_tbl_list ) 
                    770:                if (n->n_key == NESTED) ++cnt;
                    771: 
                    772:        if ( cnt > 1 ) {
                    773:                error( "ambiguous nested type %s (%d instances), use x::y syntax", nm->string, cnt );
                    774:                error( 'i', "cannot recover from previous errors" );
                    775:        }
                    776:        else { 
                    777:                TOK ntk;
                    778:                Ptype tt = return_nstd_local_type(nx,ntk);
                    779:                error('w', "use %t:: to access nested %k %s (anachronism)", tt->in_class, ntk, nx->string);
                    780:        }
                    781:        return nx;
                    782: }
                    783: 
                    784: static int
                    785: in_local_class( Pclass cl )
                    786: {
                    787:        if ( cl->lex_level )
                    788:                return 1;
                    789:        if ( cl->in_class )
                    790:                return in_local_class( cl->in_class );
                    791:        return 0;
                    792: }
                    793: 
                    794: static Pname
                    795: do_nested_type( Pname n ) 
                    796: {
                    797:        Pname nn = n;
                    798:        char *str = 0;
                    799: 
                    800: // error('d', "do_nested_type: %s in_typedef: %d ccl: %t", n->string, in_typedef, ccl );
                    801:        if ( in_typedef && ccl->string[0]=='_'
                    802:        &&  ccl->string[1]=='_'
                    803:        &&  ccl->string[2]=='C') return n;
                    804: 
                    805:        if ( n->tp ) 
                    806:         { // already a TNAME :
                    807:          // hide existing instance, encode new instance
                    808:          /*
                    809:           * need handle the anomaly:
                    810:           * class x;
                    811:           * x *p;
                    812:           * class y {
                    813:           *    class x{ ... }; // oops
                    814:           * };
                    815:           */
                    816:                if (n->tp->base==COBJ) {
                    817:                        Pclass cl = Pclass(Pbase(n->tp)->b_name->tp);
                    818:                        if (cl->defined == 0 && lasttk == AGGR) {
                    819:                                error('w',"forwardD ofC%n resolved to nested%t::%s",n,ccl,n->string);
                    820:                                cl->lcl = new char[9];
                    821:                                strcpy(cl->lcl,"FUDGE007"); // license to hack
                    822:                                n->lex_level=Pbase(n->tp)->b_name->lex_level=0;
                    823:                                return n;
                    824:                        }
                    825:                } 
                    826:                else if (n->tp->base==EOBJ) { // watch out for enum x;
                    827:                        Penum en = Penum(Pbase(n->tp)->b_name->tp);
                    828:                        if (en->defined == 0 && lasttk == ENUM) return n;
                    829:                }
                    830: 
                    831:                nested_hide( n );
                    832:                nn = new name( n->string );
                    833:                str = make_nested_name( n->string, ccl );
                    834:        }
                    835:        else
                    836:        // make sure we haven't already seen a nested instance
                    837:        // if so, for transition, this needs to be an error
                    838:        if (ktbl->look( n->string, NESTED ))
                    839:                error("multiple type %s nestings (to do this define an empty class/enum %s {};)",n->string,n->string); 
                    840:        if ( in_typedef ) {
                    841:                if (strcmp(ccl->string, nn->string)==0) { // class x { typedef T x;
                    842:                        error( "nested Tdef %s redefines immediately enclosing class", nn->string );
                    843:                        error( 'i', "cannot recover from previous errors" );
                    844:                }
                    845: 
                    846:                // make sure there isn't an identifier at global scope being defined
                    847:                // by a nested typedef -- previously an error; keep it so for transition
                    848:                Pname tn;
                    849:                if ( n->tp == 0 && in_local_class(ccl)==0 &&
                    850:                      (tn=gtbl->look(n->string,0))) {
                    851:                        error( "nested Tdef %s redefinesG %n", n->string, tn );
                    852:                        error( 'i', "cannot recover from previous errors" );
                    853:                }
                    854: 
                    855:                nn->tpdef = new type;
                    856:                nn->tpdef->nested_sig = str;
                    857:                nn->tpdef->in_class = ccl;
                    858:                nn->tpdef->lex_level = NESTED;
                    859:                PERM(nn->tpdef);
                    860:        }
                    861:        else {
                    862:                nn = nn->tname( lastval.t );
                    863:                Pname tn = Pbase(nn->tp)->b_name;
                    864:                Ptype tt = tn->tp;
                    865:                if ( tt->defined && tt->in_class == ccl) {
                    866:                        error( "nested %t redefines immediately enclosing class", nn->string );
                    867:                        error( 'i', "cannot recover from previous errors" );
                    868:                }
                    869:                tt->nested_sig = str;
                    870:                modified_tn = modified_tn->l;
                    871:                nn->lex_level = tn->lex_level = 0;
                    872:                nested_type = new name_list( nn, nested_type );
                    873:        }
                    874:        nn->n_key = NESTED;
                    875:        return nn;
                    876: }
                    877: 
                    878: static Pname dtor_seen;
                    879: static int in_expr;
                    880: extern int in_sizeof;
                    881: 
                    882: extern TOK
                    883: lalex()
                    884: /*  return next token to grammar  */
                    885: {
                    886:     register TOK tk;
                    887:     if ( front == 0 )
                    888:        add_tokens();           // extend lookahead queue
                    889:     LDB(1,fprintf(stderr,"\n*** lalex()\n");showQ("before"));
                    890: 
                    891: gettok:
                    892:     tk = deltok();
                    893: // error('d',&curloc,"lalex: just got %k '%s' in_typedef: %d",tk,tk==ID?yylval.s:tk==TNAME?yylval.pn->string:"", in_typedef);
                    894: 
                    895:     if ( tk == ID || tk == TNAME ) 
                    896:     {
                    897:        TOK tk2 = la_look();
                    898:        int lex_level = bl_level - in_class_decl - (tk2 == LC );
                    899: 
                    900:        if ( tk == TNAME )
                    901:        {
                    902: //error('d', "lalex tname %n;   lasttk: %k tk2: %k", yylval.pn, lasttk, tk2);
                    903: //error('d', "    must_be_id: %d must_be_expr %d  decl_type %d",must_be_id,must_be_expr,DECL_TYPE);
                    904: //error('d', "    bl_level: %d parsing_members %d",bl_level,parsing_class_members);
                    905:            if ( tk2 == LP 
                    906:                && (bl_level == 0 || parsing_class_members) 
                    907:                && ( laexpr(lasttk) == 0 ) 
                    908:                && must_be_expr == 0
                    909:                && DECL_TYPE == 0 ) {
                    910:                        if (la_decl()) {
                    911:                                must_be_id = 0;
                    912:                                DECL_TYPE = tk;
                    913:                                tk = DECL_MARKER;
                    914:                                goto ret;
                    915:                        }
                    916:            }
                    917: 
                    918:            // note: *** can handle local typedefs here, too!
                    919:            if ( in_typedef && 
                    920:                        in_typedef->base != 0 && 
                    921:                        ccl && in_mem_fct == 0 &&
                    922:                        (tk2 == SM || tk2 == RP || tk2 == LB))
                    923:                                yylval.pn = do_nested_type(yylval.pn);
                    924:        
                    925:            if ( lasttk == AGGR || lasttk == ENUM ) {
                    926:                if ( tk2 == LC || tk2 == COLON ) { // class definition  
                    927:                        if ( lex_level 
                    928:                                && (in_class_decl==0 || in_mem_fct)
                    929:                                && lasttk != ENUM )  // temporary
                    930:                                        yylval.pn = do_local_class( yylval.pn, lex_level );
                    931:                        else 
                    932:                        if ( in_class_decl && ccl )
                    933:                                yylval.pn = do_nested_type( yylval.pn );
                    934:                }
                    935:            } 
                    936: 
                    937:           if (tk2 == LT) {
                    938:              // a parametrized type name
                    939:              if (template_tscope(yylval.pn,latok)) 
                    940:                        tk = PTNAME ;
                    941:           } else  
                    942:           if ( tk2 == MEM || (tk2 == DOT && mem_sel == 0 )) {  
                    943:                if (tk2==DOT)
                    944:                        error(strict_opt?0:'w',"``.'' used for qualification; please use ``::'' (anachronism)");
                    945: crunch:
                    946:                tk = TSCOPE;
                    947:                {//XXX -- should be modified to do lookup and del at each ::
                    948:                  while ( (tk2 = lookahead()) == TSCOPE ) ;
                    949:                  if ( tk2 == TNAME ) {
                    950:                        tk2 = lookahead();
                    951:                        if ( tk2 == LP 
                    952:                        && (bl_level == 0 || parsing_class_members) 
                    953:                        && ( laexpr(lasttk) == 0 ) 
                    954:                        && must_be_expr == 0
                    955:                        && DECL_TYPE == 0 ) {
                    956:                                if (la_decl()) {
                    957:                                        must_be_id = 0;
                    958:                                        //DECL_TYPE = tk;//???
                    959:                                        DECL_TYPE = TNAME;
                    960:                                        //front should be ::
                    961:                                        front->tok = TSCOPE;
                    962:                                        front->retval.pn = yylval.pn;
                    963:                                        yylval.pn = 0;
                    964:                                        tk = DECL_MARKER;
                    965:                                        goto ret;
                    966:                                }
                    967:                        }
                    968:                  }
                    969:                }
                    970:                tk2 = deltok(1);
                    971:                tk2 = la_look();
                    972:                if ( tk2 == MUL ) {
                    973:                        tk = MEMPTR;
                    974:                        tk2 = deltok(1);
                    975:                }
                    976:            }
                    977:            // Have a TNAME.  Check to be sure.
                    978:            else if ( must_be_id ){
                    979: //error('d',"lalex: must_be_id: <tname %n> <%k>",yylval.pn,tk2);
                    980:                if ( in_class_decl 
                    981:                        && lasttk == TYPE 
                    982:                        && tk2 == LP
                    983:                        && strcmp(yylval.pn->string,ccl->string) == 0 )
                    984:                        error("%nK with returnT", yylval.pn);
                    985: 
                    986:                else if ( lasttk == TYPE && lastval.t == OVERLOAD
                    987:                          && ( tk2 == SM || tk2 == LP ) )
                    988:                        { 
                    989:                        tk = ID;
                    990:                        yylval.pn->hide();
                    991:                        yylval.pn = new name( yylval.pn->string );
                    992:                        yylval.pn->n_oper = TNAME;
                    993:                        }
                    994:                else if ( lasttk == OPERATOR ||
                    995:                        in_typedef && yylval.pn->n_key == NESTED)
                    996:                                must_be_id = 0;
                    997:                else if ( lasttk != TSCOPE // watch out for X::X
                    998:                     || lastval.pn != yylval.pn 
                    999:                     || (in_typedef && 
                   1000:                                in_typedef->check( yylval.pn->tp,0) == 0 )) 
                   1001:                {
                   1002:                        tk = ID;
                   1003:                        if ( in_typedef && (lasttk == MUL || lasttk == REF)) {
                   1004:                                defer_check = 1;
                   1005:                                in_tag = yylval.pn;
                   1006:                        }
                   1007: 
                   1008:                        if ( lasttk == MEM && yylval.pn->lex_level ) {
                   1009:                                Pname nn = gtbl->look( yylval.pn->string, 0 );
                   1010:                                if (nn == 0 )
                   1011:                                        error( "%k%s undeclared", lasttk, yylval.pn->string);
                   1012:                                else
                   1013:                                        yylval.pn = nn;
                   1014:                        }
                   1015:                        else {
                   1016: // error('d',"lalex: else: lasttk: %k", lasttk );
                   1017:                                if (lasttk!=DOT && lasttk!=REF
                   1018:                                &&  lasttk!=TSCOPE && lasttk != GOTO ) {
                   1019:                                    // handle typedefs in basetype::check
                   1020:                                    //    when type is available
                   1021:                                    if (!in_typedef) {
                   1022: // error('d',"\"%s\" line %d: hiding%n",__FILE__,__LINE__,yylval.pn);
                   1023:                                        yylval.pn->hide();
                   1024:                                    }
                   1025:                                    yylval.pn = new name(yylval.pn->string);
                   1026:                                    yylval.pn->n_oper = TNAME;
                   1027:                                } else
                   1028:                                    yylval.pn = new name(yylval.pn->string);
                   1029:                        }
                   1030:                        if ( defer_check ) defer_check = 0;
                   1031:                }
                   1032:            } // must_be_id
                   1033: 
                   1034:            if ( in_class_decl &&
                   1035:                ccl->lex_level &&
                   1036:                yylval.pn->lex_level != 0 && 
                   1037:                yylval.pn->tp && 
                   1038:                (yylval.pn->tp->base != COBJ && yylval.pn->tp->base != EOBJ)) 
                   1039:            {
                   1040:                Pname n = gtbl->look( yylval.pn->string,0);
                   1041:                if ( in_mem_fct ) {
                   1042:                     if (n && n->base == TNAME ) {
                   1043:                        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 );
                   1044:                        yylval.pn = n;
                   1045:                    } else
                   1046:                        error( "local typedef %sis not in scope of inline member function of local class %s", yylval.pn->string, ccl->string);
                   1047:                }
                   1048:            }
                   1049: 
                   1050:            // if we still have a TNAME, make sure have the right TNAME
                   1051:            // possibility of ananchronistic reference to nested type
                   1052:            Ptype nbt = yylval.pn->tp;
                   1053:            if (tk == TNAME && curr_scope == 0 && nbt && // Y y; not X::Y y;
                   1054:                (nbt->base == EOBJ || nbt->base == COBJ))
                   1055:            {
                   1056:                Ptype t = Pbase(nbt)->b_name->tp;
                   1057:                if ( ccl && t->in_class &&
                   1058:                        strcmp(t->in_class->string, ccl->string)) 
                   1059:                {
                   1060:                        switch( nbt->base ) {
                   1061:                                case COBJ:
                   1062:                                        if (is_empty(Pclass(t)))
                   1063:                                                yylval.pn = check_nested_type( yylval.pn );
                   1064:                                        break;
                   1065:                                case EOBJ:
                   1066:                                        if (is_empty(Penum(t)))
                   1067:                                                yylval.pn = check_nested_type( yylval.pn );
                   1068:                                        break;
                   1069:                        };
                   1070:                }
                   1071:            }
                   1072:         }
                   1073:        else 
                   1074:         { // tk == ID 
                   1075:                char *s = yylval.s;
                   1076:                Pname n = ktbl->look( s, HIDDEN );
                   1077:                Pname nstd = ktbl->look( s, NESTED );
                   1078: 
                   1079:                // inside a class definition, ccl, that is nested 
                   1080:                // s is a nested class name, and is the name of ccl
                   1081:                if (ccl && ccl->in_class && nstd && 
                   1082:                        strcmp(s, ccl->string)==0)
                   1083:                {
                   1084:                        for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
                   1085:                                Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ)
                   1086:                                                ? Pbase(nn->tp)->b_name->tp : nn->tpdef;
                   1087:                                Pclass cl = tt->in_class; 
                   1088:                                if ( nn->n_key != NESTED ) continue;
                   1089:                                if (strcmp(ccl->in_class->string,cl->string) == 0) {
                   1090:                                        tk = TNAME;
                   1091:                                        yylval.pn = nn;
                   1092:                                        n = nstd = nn;
                   1093:                                        }
                   1094:                        }
                   1095:                }
                   1096: 
                   1097:                if (tk2 == MEM) {
                   1098:                    // ID ::
                   1099:                    if (n) {
                   1100:                        yylval.pn = n;
                   1101:                /*XXX*/ goto crunch;
                   1102:                    } 
                   1103:                    else
                   1104:                    if (nstd &&
                   1105:                        nstd->n_tbl_list==0)
                   1106:                    {
                   1107:                        yylval.pn = nstd;
                   1108:                        tk = TSCOPE;
                   1109:                        tk2 = deltok(1);
                   1110:                        tk2 = la_look();
                   1111:                        if (tk2 == MUL ) {
                   1112:                                tk = MEMPTR;
                   1113:                                tk2 = deltok(1);
                   1114:                        }
                   1115:                    }
                   1116:                    else {
                   1117:                        error( "%s:: %sis not aTN", s, s ); 
                   1118:                        tk2 = deltok(1);
                   1119:                        goto gettok;
                   1120:                    }
                   1121:                } 
                   1122:                else  // transitional kludge
                   1123:                if ( n && nstd && n == nstd )  
                   1124:                        ; // null statement
                   1125: 
                   1126:                // Have an ID. Check last token to be sure.
                   1127:                else if (lasttk==ENUM || lasttk==AGGR &&
                   1128:                                // template <class id, class id>
                   1129:                                (tk2 != GT && tk2 != CM)) 
                   1130:                        {
                   1131:                        int fd = tk2!=LC && tk2!=COLON;
                   1132:                        tk = TNAME;
                   1133:                        if ( nstd ) { 
                   1134:                                // in transitional model, need flag this as error
                   1135:                                if ( fd == 0 ) { // real definition
                   1136:                                        if ( ccl == 0 )
                   1137:                                                error("nested andG%k %s(to do this placeG%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS, s); 
                   1138:                                        else
                   1139:                                                error("multiple nested%k %s(to do this placeG%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS,s); 
                   1140:                                        error( 'i', "cannot recover from previous errors" );
                   1141:                                }
                   1142:                        }
                   1143:                        else 
                   1144:                        // new tag, define it
                   1145:                        if (n==0 || 
                   1146:                                (n->n_template_arg == template_type_formal))
                   1147:                        {
                   1148: // error('d', "ccl: %t fd: %d, in_mem_fct: %d, in_class_decl: %d", ccl, fd, in_mem_fct, in_class_decl);
                   1149:                                n = new name( s );
                   1150:                                if ( fd )  // struct X*, etc.
                   1151:                                        n->lex_level=0; 
                   1152:                                else
                   1153:                                        n->lex_level=lex_level>=0?lex_level:0;
                   1154: 
                   1155:                                if ( ccl && fd == 0 && 
                   1156:                                        in_class_decl && 
                   1157:                        (bl_level == ccl->lex_level + in_class_decl + 1))
                   1158:                                                n = do_nested_type( n );
                   1159:                                else
                   1160:                                // note: ***** modify to handle local typedef
                   1161:                                // note: ***** add local enums
                   1162:                                if ( n->lex_level &&
                   1163:                                        lasttk != ENUM ) // temporary
                   1164:                                                n = do_local_class( n, n->lex_level );
                   1165:                                else {
                   1166:                                        n = n->tname( lastval.t );
                   1167:                                        modified_tn = modified_tn->l;
                   1168:                                        if (gtbl->look(n->string,0)) statStat = n;
                   1169:                                }
                   1170:                        }
                   1171:                        else {
                   1172:                                if (n->tp->base!=COBJ && n->tp->base!=EOBJ) {
                   1173:                                        error( 'i', "hidden%n:%t",n,n->tp );
                   1174:                                        goto gettok;
                   1175:                                }
                   1176: 
                   1177:                                if ( tk2 == LC || tk2 == COLON ) { 
                   1178:                                        // class declared and hidden but not yet defined
                   1179:                                        // may have ctor defined which invalidates hiding
                   1180:                                        statStat = n;
                   1181:                                        n->n_key = 0; // inside class definition it cannot be hidden
                   1182:                                }
                   1183:                        }
                   1184:                        yylval.pn = nstd?nstd:n; 
                   1185:                }
                   1186:                else {
                   1187:                        tk = ID;
                   1188:                        yylval.pn = new name( s );
                   1189:                }
                   1190: 
                   1191:                if ( tk == ID ) 
                   1192:                {
                   1193:                    switch ( tk2 ) {
                   1194:                    case ID: case TNAME: case AGGR: case ENUM:
                   1195:                    {
                   1196:                        Pname n = 0; 
                   1197: 
                   1198:                        if ((curr_scope||ccl) && nstd) {
                   1199:                        // within class scope in which nested class is visible
                   1200:                        // curr_scope == set by TSCOPE, X::foo() { ... }
                   1201:                        // ccl == parsing class definition ``ccl''
                   1202: 
                   1203:                                char *str = curr_scope?curr_scope->string:ccl->string;
                   1204:                                for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
                   1205:                                        Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ)
                   1206:                                                        ? Pbase(nn->tp)->b_name->tp : nn->tpdef;
                   1207:                                        Pclass cl = tt->in_class; 
                   1208:                                        if ( nn->n_key != NESTED ) continue;
                   1209:                                        if ( strcmp(str,cl->string) == 0){      
                   1210:                                                tk = TNAME;
                   1211:                                                yylval.pn = nn;
                   1212:                                                if (lasttk == TYPE && 
                   1213:                                                        lastval.t == TYPEDEF )
                   1214:                                                                in_typedef = yylval.pn->tp;
                   1215:                                                break;
                   1216:                                        }
                   1217:                                }
                   1218:                        }
                   1219:                        if (tk == TNAME) break; // found nested class
                   1220: 
                   1221:                        n = ktbl->look( s, HIDDEN ); 
                   1222:                        if ( n ) {
                   1223:                                Pname nn = n;
                   1224:                                switch ( n->tp->base ) {
                   1225:                                        default:
                   1226:                                                error("typedef %sis not visible in this scope", s );
                   1227:                                                break;
                   1228:                                        case COBJ:
                   1229:                                                if (is_empty(Pclass(Pbase(n->tp)->b_name->tp)))
                   1230:                                                        n = check_nested_type( nn );
                   1231:                                                if (nn == n)
                   1232:                                                        error("%sis hidden: use struct %s%s", s,s,front->retval.s);
                   1233:                                                break;
                   1234:                                        case EOBJ:
                   1235:                                                if (is_empty(Penum(Pbase(n->tp)->b_name->tp)))
                   1236:                                                        n = check_nested_type( nn );
                   1237:                                                if (nn == n)
                   1238:                                                        error("%sis hidden: use enum %s%s", s,s,front->retval.s);
                   1239:                                                break;
                   1240:                                };
                   1241:                                tk = TNAME;
                   1242:                                yylval.pn = n;
                   1243:                        }
                   1244:                        else  
                   1245:                        if (n=ktbl->look(s,NESTED)) 
                   1246:                        {
                   1247:                                TOK ntk;
                   1248:                                bit ok = 0;
                   1249:                                Ptype tt = return_nstd_local_type(n,ntk);
                   1250:                                Pclass cl = tt->in_class; 
                   1251:                                if (ccl) {
                   1252:                                        // x::y unncessary with in_class,
                   1253:                                        // a derived class of in_class
                   1254:                                        // or classes enclosing in_class
                   1255:                                        if (ccl==cl || ccl->has_base(cl))
                   1256:                                                ok++;
                   1257:                                        else {
                   1258:                                        for (Pclass eccl=ccl->in_class;eccl; eccl=eccl->in_class)
                   1259:                                                if ( eccl == cl ) { ok++; break; }
                   1260:                                        }
                   1261:                                }
                   1262:                                if (!ok)
                   1263:                                        error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, n->string );
                   1264:                                tk = TNAME;
                   1265:                                yylval.pn = n;
                   1266:                        }
                   1267:                        else { // probably a typo
                   1268:                            if ( tk2 == ID )
                   1269:                                error("%s%s: %sis not aTN", s,front->retval.s,s);
                   1270:                            else if ( tk2 == TNAME )
                   1271:                                error("%s%s: %sis not aTN", s,front->retval.pn->string,s);
                   1272:                            else 
                   1273:                                error("%s%k: %sis not aTN", s,front->retval.t,s);
                   1274:                            goto gettok;
                   1275:                        }
                   1276:                         break;
                   1277:                    }
                   1278:                    case DOT: case REF:
                   1279:                         mem_sel = yylval.pn;
                   1280:                         break;
                   1281:                    default:
                   1282:                        if ( lasttk == TNAME && tk2 == LC )  
                   1283:                        {
                   1284:                                error("T%s %k: %s is unexpected", s, tk2, s );
                   1285:                                goto gettok;
                   1286:                        }
                   1287:                        
                   1288:                        // have an ID.  lets just make sure it should not be a TNAME
                   1289:                        if (curr_scope||ccl||nstd) {
                   1290:                                if (ccl && in_typedef && 
                   1291:                                        in_typedef->base != 0 &&  
                   1292:                                        in_mem_fct == 0 &&
                   1293:                                        (tk2 == SM || tk2 == RP || tk2 == LB)) 
                   1294:                                        {
                   1295:                                                yylval.pn = do_nested_type( yylval.pn );
                   1296:                                                tk = TNAME;
                   1297:                                        }
                   1298:                                else
                   1299:                                if (nstd && must_be_id == 0 && (in_expr == 0 || (lasttk==LP && tk2==RP))) {
                   1300: // error('d',"nstd: %n must_be_id 0 have id tk2: %k lasttk: %k",nstd,tk2,lasttk);
                   1301: // error('d',"nstd: in_expr %d lex_level %d",in_expr,lex_level);
                   1302:                                        Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0);
                   1303:                                        for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
                   1304:                                                TOK ntk;
                   1305:                                                bit ok = 0;
                   1306:                                                Ptype tt = return_nstd_local_type(nn,ntk);
                   1307:                                                Pclass cl = tt->in_class; 
                   1308: // error('d',"xcl: %t ccl: %t", xcl, ccl );
                   1309:                                                if ( xcl ) {
                   1310:                                                        if (xcl==cl || xcl->has_base(cl) || ccl == cl)
                   1311:                                                                ok++;
                   1312:                                                        else {
                   1313:                                                        for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class)
                   1314:                                                                if ( eccl == cl ) { ok++; break; }
                   1315:                                                        }
                   1316:                                                }
                   1317:                                                        
                   1318:                                                if (nn == nstd)
                   1319:                                                {
                   1320:                                                if (
                   1321:                                                    // special case: foo(X,
                   1322:                                                    // in_arg_list not set until **after** X is handled
                   1323:                                                    ((in_arg_list || lasttk==LP) &&  // foo(nestedX
                   1324:                                                        (tk2==CM || tk2==ASSIGN || 
                   1325:                                                                (tk2==RP && lasttk!=MUL && lasttk!=REF))) 
                   1326:                                                    || // class x : public nestedX
                   1327:                                                        (tk2==LC && (lasttk==PR || lasttk==VIRTUAL))
                   1328:                                                    || // nestedX [*&]
                   1329:                                                        (tk2 == MUL || tk2==AND)
                   1330:                                                    || (lasttk==LP && tk2==RP)
                   1331:                                                    || (lasttk==TSCOPE && lastval.pn == nn) 
                   1332:                                                    || (lasttk==COMPL && dtor_seen == nn) 
                   1333:                                                    || (lasttk==TYPE && lastval.t == TYPEDEF)
                   1334:                                                     || lasttk == OPERATOR
                   1335:                                                    || lasttk == NEW || in_sizeof )
                   1336:                                                {  // must be type name, and it must be nested: 
                   1337:                                                        if ( nstd->n_tbl_list == 0 ) { // only one: ok
                   1338:                                                                if (lasttk != TSCOPE && !ok )
                   1339:                                                                        error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, nn->string);
                   1340:                                                                break;
                   1341:                                                        }
                   1342:                                                        else {
                   1343:                                                                if (lasttk != TSCOPE && lasttk != TYPE && !ok){
                   1344:                                                                        error("ambiguous nested type %s, use %t::%s",nn->string,xcl,nn->string);
                   1345:                                                                        error( 'i', "cannot recover from previous errors" );
                   1346:                                                                }
                   1347:                                                        }
                   1348:                                                }
                   1349: 
                   1350:                                            }
                   1351:                                                if ( nn->n_key != NESTED ) continue;
                   1352:                                                if (xcl && 
                   1353:                                                        strcmp(xcl->string,cl->string) == 0) break;
                   1354:                                        } // end: for nn = nstd
                   1355: 
                   1356:                                        if (nn) {
                   1357:                                                tk = TNAME;
                   1358:                                                yylval.pn = nn;
                   1359:                                                if (lasttk == TYPE && 
                   1360:                                                        lastval.t == TYPEDEF )
                   1361:                                                                in_typedef = yylval.pn->tp;
                   1362:                                        }
                   1363:                                }  // end: if (nstd)
                   1364:                        } // end: if (curr_scope||ccl)
                   1365:                         break;
                   1366:                    } // end: switch tk2
                   1367:                } // end: if (tk == ID)
                   1368:            }
                   1369: 
                   1370: // error('d',"testing for in_expr: in_expr: %d tk: %k", in_expr, tk );
                   1371: // error('d',"testing for in_expr: tk2: %k lasttk: %k", tk2, lasttk );
                   1372:            if (lex_level && tk==ID && tk2==LP &&
                   1373:                        (lasttk==LC || lasttk==RC || lasttk==RP ||
                   1374:                        lasttk == ASSIGN || lasttk == SM))
                   1375:                                in_expr = 1;
                   1376:            else in_expr = 0;
                   1377:        
                   1378:        }
                   1379:         if ( tk == TNAME || ( tk == TYPE && latype(yylval.t) )
                   1380: // XXX     || tk == TSCOPE || tk == MEM 
                   1381:           || tk == REF || tk == DOT || tk == GOTO 
                   1382:           || tk == MEMPTR )
                   1383:           // TNAME cannot immediately follow a type name,
                   1384:           // scope operator, right curly, selection, or goto
                   1385:                must_be_id = 1;
                   1386:        else
                   1387:                must_be_id = 0;
                   1388: 
                   1389:         switch ( tk ) {
                   1390:            case SM:
                   1391:                mem_sel = 0; // no break
                   1392:                in_expr = 0;
                   1393:            case RP: case RC: must_be_expr = 0; break;
                   1394:            case COLON: 
                   1395:                if  (lasttk == RP || 
                   1396:                    (lasttk == TYPE && lastval.t == CONST)) 
                   1397:                        must_be_expr = 1;
                   1398:                break;
                   1399:            case SIZEOF:
                   1400:                in_sizeof = 1;
                   1401:                break;
                   1402:        };
                   1403: ret:
                   1404:     if ( tk == COMPL && lasttk == TSCOPE )
                   1405:         dtor_seen = lastval.pn;
                   1406:     else dtor_seen = 0;
                   1407:     lasttk = tk;
                   1408:     lastval = yylval;
                   1409:     LDB(1,showQ("after");
                   1410:        fprintf(stderr,"returning '%s'",image(tk));
                   1411:        if ( tk==ID || tk==TNAME ) fprintf(stderr," -- '%s'",yylval.pn->string);
                   1412:        fprintf(stderr,"\n");
                   1413:     );
                   1414: // error('d',"returning tk: %k dtor_seen: %n", tk,dtor_seen );
                   1415:     return tk;
                   1416: }
                   1417: 
                   1418: extern void
                   1419: la_backup( TOK t, YYSTYPE r )
                   1420: /*
                   1421:     called by parser to push token back on front of queue
                   1422: */
                   1423: {
                   1424:     LDB(1,fprintf(stderr,"\n*** la_backup( '%s', ...)\n",image(t)));
                   1425:     if ( t == ID ) { Pname n = r.pn; r.s = n->string; DEL(n); }
                   1426:     register toknode* T = new toknode(t,r,curloc);
                   1427:     if (front) {
                   1428:        front->last = T;
                   1429:        T->next = front;
                   1430:        T->last = 0;
                   1431:        front = T;
                   1432:     } else
                   1433:        front = rear = T;
                   1434:     lasttk = 0;
                   1435: }
                   1436: 
                   1437: extern int
                   1438: la_sctype( TOK t )
                   1439: {
                   1440: //error('d',&latok->place,"la_sctype(%k ) -- latok ==%k",t,latok->tok);
                   1441:        if ( t != latok->tok && t != TSCOPE && t != MEMPTR )
                   1442:                error( 'i', &latok->place, "la_sctype, lalex.c" );
                   1443: 
                   1444:        switch( latok->retval.t ) {
                   1445:                case TYPEDEF:
                   1446:                case EXTERN:
                   1447:                case STATIC:
                   1448:                case AUTO:
                   1449:                case REGISTER:
                   1450:                case OVERLOAD:
                   1451:                case INLINE:
                   1452:                case FRIEND:
                   1453:                case CONST:
                   1454:                case VOLATILE:
                   1455:                        return 1; 
                   1456:                default:
                   1457:                        return 0; 
                   1458:        }
                   1459: }
                   1460: 
                   1461: extern int
                   1462: la_cast()
                   1463: /*
                   1464:        called in reduction of term_lp to check for ambiguous prefix-style cast
                   1465:        if result is 1, caller inserts DECL_MARKER to force reduction of cast
                   1466: */
                   1467: {
                   1468:        // yychar already designates TYPE or TNAME
                   1469:        // LP must start the lookahead queue!
                   1470:        LDB(1,fprintf(stderr,"\n*** la_cast()\n"););
                   1471:        int tk, tk2 = latok->tok;
                   1472: 
                   1473:        for ( ; ; ) {
                   1474:            tk = tk2;
                   1475:            tk2 = lookahead();
                   1476: 
                   1477:            switch( tk ) {
                   1478:            case LP:
                   1479:                if ( tk2 == MUL || tk2 == AND ||
                   1480:                        tk2 == TSCOPE || tk2 == MEMPTR )
                   1481:                    // T ( * ...
                   1482:                    // T ( C ::* ...
                   1483:                    continue;
                   1484:                else
                   1485:                    // T ( exp )
                   1486:                    return 0;
                   1487:            case MUL: case AND:
                   1488:                //if ( tk2 == SCTYPE )
                   1489:                if ( la_sctype( tk2 ) )
                   1490:                    // T ( * const ...
                   1491:                    // T ( * volatile ...
                   1492:                    tk2 = lookahead();
                   1493:                continue;
                   1494:            case MEMPTR:
                   1495:                if ( tk2 == RP ) continue;
                   1496:                break;
                   1497:            case TSCOPE:
                   1498:                if ( tk2 == MUL )
                   1499:                    // T ( C :: * ...
                   1500:                    continue;
                   1501:                else
                   1502:                    // T ( exp )
                   1503:                    return 0;
                   1504:            case RP: case LB:
                   1505:                // T (*)()
                   1506:                // T (*[])()
                   1507:                return 1;
                   1508:            }
                   1509: 
                   1510:            return 0;
                   1511:        }
                   1512: }
                   1513: 
                   1514: static int
                   1515: la_decl()
                   1516: /*
                   1517:        handles ambiguities
                   1518:                type (*x) ()
                   1519:                type (*x) []
                   1520:        at start of arg list / statement
                   1521:        return val == 1 if lookahead finds a declaration
                   1522:                (used for error messages only)
                   1523:        if declaration is "ambiguous" (i.e., can't be recognized with
                   1524:                1-symbol lookahead), insert DECL_MARKER to force reduction
                   1525:                of "type"
                   1526: */
                   1527: {
                   1528:        
                   1529:        // LP must start the lookahead queue!
                   1530:        LDB(1,fprintf(stderr,"\n*** la_decl()\n"););
                   1531:        int tk, tk2 = latok->tok;
                   1532:        int paren = 0;
                   1533:        int ptr = 0;
                   1534: 
                   1535:        for ( ; ; ) {
                   1536: 
                   1537:            tk = tk2;
                   1538:            tk2 = lookahead();
                   1539: 
                   1540: // fprintf(stderr,"\nla_decl:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]);
                   1541:            switch( tk ) {
                   1542:            case LP:
                   1543:                if ( tk2 == MUL || tk2 == AND || tk2 == TSCOPE ) {
                   1544:                    // T ( * ...
                   1545:                    ++paren;
                   1546:                    ptr = 1;
                   1547:                    continue;
                   1548:                } else
                   1549:                if ( tk2 == MEMPTR ) {
                   1550:                // T ( C ::*  ...
                   1551:                        return 1;
                   1552:                } else 
                   1553:                // possible redundant parens
                   1554:                if ( tk2 == ID && lookahead() == RP ) {
                   1555:                        TOK tp = lookahead();
                   1556: // error( 'd', "tp %k tk: %k tk2: %k", tp, tk, tk2 );
                   1557: // error( 'd', "bl_level: %d, in_class_decl: %d", bl_level,in_class_decl );
                   1558:                        if ( tp == SM || tp == CM || tp == ASSIGN )
                   1559:                        {
                   1560:                                // member initialization list
                   1561:                                if ( tp != SM && in_arg_list == 0 ) return 1;
                   1562:                        }
                   1563:                        else 
                   1564:                        if ( tp == RP && (bl_level-in_class_decl==0))
                   1565:                                return 1;
                   1566:                        if ( tp != LP ) 
                   1567:                                return 0;
                   1568:                        latok=latok->last; // restore lookahead
                   1569:                        ++paren;
                   1570:                        continue;
                   1571:                        }
                   1572:                else
                   1573:                    // T ( exp )
                   1574:                    return 0;
                   1575:            case MUL: case AND:
                   1576:                //if ( tk2 == SCTYPE )
                   1577:                if ( la_sctype( tk2 ))
                   1578:                    // T ( * const ...
                   1579:                    // T ( * volatile ...
                   1580:                    return 1;
                   1581:                else {
                   1582:                    ptr = 0;
                   1583:                    continue;
                   1584:                }
                   1585:            case MEMPTR:
                   1586:                // T ( C :: * ...
                   1587:                return 1;
                   1588:            case TSCOPE:
                   1589:                if ( tk2 == MUL ) //??tk SHOULD HAVE TRANSLATED TO MEMPTR!!
                   1590:                    // T ( C :: * ...
                   1591:                    return 1;
                   1592:                else if ( ptr )
                   1593:                    // T ( exp )
                   1594:                    return 0;
                   1595:                else if ( tk2 == ID || tk2 == OPERATOR )
                   1596:                    // T ( * C :: id ...
                   1597:                    continue;
                   1598:                else
                   1599:                    // error
                   1600:                    return 0;
                   1601:            }
                   1602: 
                   1603:            break;
                   1604:        }
                   1605: 
                   1606:        if ( tk == RP || tk == LB )
                   1607:            // T (*)()
                   1608:            // T (*[])()
                   1609:            return 1;
                   1610: 
                   1611:        if ( tk != ID && tk != OPERATOR )
                   1612:            // T ( exp )
                   1613:            return 0;
                   1614: 
                   1615:        if ( tk == OPERATOR )
                   1616:            switch ( tk2 ) {
                   1617:            case PLUS: case MINUS: case MUL: case REFMUL:
                   1618:             case AND: case OR: case ER: case SHIFTOP: case EQUOP: 
                   1619:            case DIVOP: case RELOP: case ANDAND: case OROR: 
                   1620:            case NOT: case COMPL: case ICOP: case ASSIGN: 
                   1621:             case ASOP: case NEW: case GNEW: case DELETE:
                   1622:                // OPERATOR oper
                   1623:                tk2 = lookahead();
                   1624:                break;
                   1625:            case LP:
                   1626:                // OPERATOR ()
                   1627:                tk2 = lookahead();
                   1628:                if ( tk2 == RP ) {
                   1629:                    tk2 = lookahead();
                   1630:                    break;
                   1631:                } else
                   1632:                    return 0;
                   1633:            case LB:
                   1634:                // OPERATOR []
                   1635:                tk2 = lookahead();
                   1636:                if ( tk2 == LB ) {
                   1637:                    tk2 = lookahead();
                   1638:                    break;
                   1639:                } else
                   1640:                    return 0;
                   1641:            default:    // illegal operator
                   1642:                return 0;
                   1643:            }
                   1644: 
                   1645:        int allow_lp = 1;
                   1646:        int allow_rp = 1;
                   1647:        for ( ; ; ) {
                   1648:            tk = tk2;
                   1649:            tk2 = lookahead();
                   1650: 
                   1651: // fprintf(stderr,"\nla_decl2:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]);
                   1652:            switch( tk ) {
                   1653:            case LP:
                   1654:                if ( !allow_lp )
                   1655:                    // T ( * id [ exp ] ( ...
                   1656:                    return 0;
                   1657: 
                   1658:                // Current lookahead will be a decl if
                   1659:                // the next lookahead is an arg decl
                   1660:                if ( tk2 == RP || tk2 == ENUM || tk2==AGGR 
                   1661:                        || tk2==ELLIPSIS || la_sctype( tk2 )) 
                   1662:                    // T ( * id ()
                   1663:                    // T ( * id ) ()
                   1664:                    return 1;
                   1665: 
                   1666:                if ( tk2 == TYPE || tk2 == TNAME ) {
                   1667:                    // T ( * id ) ( T2 ...
                   1668:                    if ( lookahead() == LP && !la_decl() )
                   1669:                        return 0;
                   1670:                    return 1;
                   1671:                }
                   1672: 
                   1673:                return 0;
                   1674:            case LB:
                   1675:                 if ( tk2 == RB || lookahead() == RB )
                   1676:                    // T ( * id [] ...
                   1677:                    return 1;
                   1678:                else {
                   1679:                    // T ( * id [ exp ] ...
                   1680:                    allow_lp = 0;
                   1681:                    allow_rp = 1;
                   1682:                    while ( lookahead() != RB );
                   1683:                    tk2 = lookahead();
                   1684:                    continue;
                   1685:                }
                   1686:            case RP:
                   1687: // error ('d', "rp: allow_rp: %d paren: %d", allow_rp, paren );
                   1688:                if ( !allow_rp || !paren )
                   1689:                    // T ( * id ) )
                   1690:                    return 0;
                   1691: // permit redundant parentheses
                   1692:                else 
                   1693:                if ( tk2 == SM || tk2 == CM || tk2 == ASSIGN )
                   1694:                        return 1;
                   1695:                else
                   1696:                if ( tk2 == RP && (bl_level-in_class_decl == 0))
                   1697:                        return 1;
                   1698:                else
                   1699:                {
                   1700:                    // T ( * id ) ...
                   1701:                    allow_lp = 1;
                   1702:                    allow_rp = 0;
                   1703:                    --paren;
                   1704:                    continue;
                   1705:                }
                   1706:            default:
                   1707:                return 0;
                   1708:            }
                   1709:        }
                   1710: }
                   1711: 
                   1712: 
                   1713: 
                   1714: /*
                   1715: **     PROCESSING OF INLINE MEMBER FUNCTIONS
                   1716: */
                   1717: static int la_snarf();
                   1718: 
                   1719: extern toknode*
                   1720: save_text()
                   1721: /*
                   1722:        save text of inline def on q of class
                   1723: */
                   1724: {
                   1725:        // Q should contain at least the tokens < FDEF, X ... >
                   1726:        // where X is either LC or COLON (start of ftn)
                   1727:        LDB(2,fprintf(stderr,"save_text()"));
                   1728:        LDB(3,fprintf(stderr,"front: %s",image(front->tok)));
                   1729:        LDB(3,fprintf(stderr,"front->next: %s",image(front->next->tok)));
                   1730:        latok = front->next;
                   1731:        if ( la_snarf() ) {
                   1732:                // append this set of tokens to
                   1733:                // inline tokenq for class
                   1734:                toknode* t = front; // FDEF
                   1735:                if ( ccl->c_funqf == 0 )
                   1736:                        ccl->c_funqf = front;
                   1737:                else {
                   1738:                        ccl->c_funqr->next = front;
                   1739:                        front->last = ccl->c_funqr;
                   1740:                }
                   1741:                ccl->c_funqr = latok;
                   1742:                front = latok->next;
                   1743:                latok->next = 0;
                   1744:                if (front)  front->last = 0;
                   1745:                return t;
                   1746:        }
                   1747:        return 0;
                   1748: }
                   1749: 
                   1750: 
                   1751: extern void
                   1752: restore_text()
                   1753: /*
                   1754:        restore tokens for member inlines onto token q
                   1755: */
                   1756: {
                   1757:        LDB(2,fprintf(stderr,"restore_text()"));
                   1758:        if (ccl->c_funqf == 0)  // no inlines on Q
                   1759:                return;
                   1760:        LDB(3,fprintf(stderr,"  Q present: %d,%d",ccl->c_funqf,ccl->c_funqr));
                   1761:        LDB(3,fprintf(stderr,"  front==%s",image(ccl->c_funqf->tok)));
                   1762:        LDB(3,fprintf(stderr,"  rear ==%s",image(ccl->c_funqr->tok)));
                   1763:        ccl->c_funqr->next = front;
                   1764:        if (front)  front->last = ccl->c_funqr;
                   1765:        front = ccl->c_funqf;
                   1766:        ccl->c_funqf = ccl->c_funqr = 0;
                   1767: }
                   1768: 
                   1769: 
                   1770: static void
                   1771: del_tokens( toknode* marker )
                   1772: /*
                   1773:     delete tokens from marker to latok, not inclusive
                   1774: */
                   1775: {
                   1776:     if ( marker == 0 || marker == latok || marker->next == 0 )
                   1777:        error('i', "bad token queue");
                   1778: 
                   1779:     LDB(2,fprintf(stderr,"del_tokens: %s..%s\n",image(marker->tok),image(latok->tok)));
                   1780: 
                   1781:     register toknode* tt = marker->next;
                   1782:     if ( tt == latok ) return;
                   1783:     marker->next = latok;
                   1784:     latok->last->next = 0;
                   1785:     latok->last = marker;
                   1786:     register toknode* tx = tt;
                   1787:     do {
                   1788:        LDB(3,fprintf(stderr,"  deleting %s\n",image(tt->tok)));
                   1789:        tx = tx->next;
                   1790:        delete tt;
                   1791:        tt = tx;
                   1792:     } while ( tx );
                   1793: }
                   1794: 
                   1795: 
                   1796: static int
                   1797: la_snarf()
                   1798: /*
                   1799:        scan function def without processing declarations
                   1800: */
                   1801: {
                   1802:        LDB(2,fprintf(stderr,"la_snarf()"));
                   1803:        loc *L = &latok->place;
                   1804:        //DBPLACE(1,L.l,L.f);
                   1805:        int parens = 0;
                   1806:        int paren_error = 0;
                   1807:        toknode* marker = latok;
                   1808:        switch ( latok->tok ) {
                   1809:        default:
                   1810:                error('i', L, "bad token Q snarfing function: %d", latok->tok);
                   1811:        case COLON:
                   1812:                break;
                   1813:        case LC:
                   1814:                --bl_level;
                   1815:                goto eatf;
                   1816:        }
                   1817:        LDB(2,fprintf(stderr,"\"eat\" member initializers"));
                   1818:        for (;;) {
                   1819:                if (latok->next == 0) add_tokens();
                   1820:                switch ( (latok=latok->next)->tok ) {
                   1821:                case LP:
                   1822:                        ++parens;
                   1823:                default:
                   1824:                        LDB(3,fprintf(stderr,"...%s",image(latok->tok)));
                   1825:                        continue;
                   1826:                case RP:
                   1827:                        if ( (--parens < 0) && (paren_error++ == 0) )
                   1828:                                error(0,&latok->place,"unbalanced ()");
                   1829:                        continue;
                   1830:                case LC:
                   1831:                case RC:
                   1832:                        if ( parens <= 0 )
                   1833:                                goto eatf;
                   1834:                        continue;
                   1835:                case SM:
                   1836:                        if ( parens <= 0 ) {
                   1837:                                error(0, L, "illegal bit field");
                   1838:                                del_tokens( front );
                   1839:                                delete front;
                   1840:                                front = latok;
                   1841:                                front->last = 0;
                   1842:                                return 0;
                   1843:                        }
                   1844:                        continue;
                   1845:                case EOFTOK:
                   1846:                        error('i',&latok->place,"unexpected end of file");
                   1847:                } // switch
                   1848:        } // for
                   1849: 
                   1850:        eatf:
                   1851:        int level = 1;
                   1852:        for (;;) {
                   1853:                if (latok->next == 0) add_tokens();
                   1854:                switch ( (latok=latok->next)->tok ) {
                   1855:                case LC:
                   1856:                        ++level;
                   1857:                default:
                   1858:                        LDB(3,fprintf(stderr,"...%s",image(latok->tok)));
                   1859:                        continue;
                   1860:                case RC:
                   1861:                        LDB(3,fprintf(stderr,"...RC"));
                   1862:                        if (--level <= 0) {
                   1863:                                if (level < 0) {
                   1864:                                        error(0,&latok->place,"unexpected '}'");
                   1865:                                        goto bad;
                   1866:                                }
                   1867:                                return 1;
                   1868:                        }
                   1869:                        break;
                   1870:                case EOFTOK:
                   1871:                        error('e', &latok->place, "unbalanced {}");
                   1872:                        goto bad;
                   1873:                } // switch
                   1874:        } // for
                   1875:        bad:
                   1876:                del_tokens( marker );
                   1877:                marker->tok = SM;
                   1878:                return 0;
                   1879: }
                   1880: 
                   1881: Pname check_for_nested( Pname nstd, TOK lasttk, YYSTYPE lastval, TOK tk2)
                   1882: {
                   1883: // error('d',"nstd: %n must_be_id 0 tk2: %k lasttk: %d",nstd,tk2,lasttk);
                   1884:        TOK tk = ID;
                   1885:        Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0);
                   1886: 
                   1887:        for (Pname nn=nstd; nn; nn=nn->n_tbl_list) {
                   1888:                TOK ntk;
                   1889:                bit ok = 0;
                   1890:                Ptype tt = return_nstd_local_type(nn,ntk);
                   1891:                Pclass cl = tt->in_class; 
                   1892:                if ( xcl ) {
                   1893:                        if (xcl==cl || xcl->has_base(cl))
                   1894:                                ok++;
                   1895:                        else {
                   1896:                                for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class)
                   1897:                                if ( eccl == cl ) { ok++; break; }
                   1898:                        }
                   1899:                }
                   1900:                                                        
                   1901:                if (nn == nstd)
                   1902:                {
                   1903:                        if ( ((in_arg_list || lasttk==LP) &&  // foo(nestedX
                   1904:                                (tk2==CM || tk2==ASSIGN || tk2==RP)) 
                   1905:                            || (tk2==LC && (lasttk==PR || lasttk==VIRTUAL))
                   1906:                            || (tk2 == MUL || tk2==AND)
                   1907:                            || (lasttk==LP && tk2==RP)
                   1908:                            || (lasttk==TSCOPE && lastval.pn == nn) 
                   1909:                            || (lasttk==COMPL && dtor_seen == nn) 
                   1910:                            || (lasttk==TYPE && lastval.t == TYPEDEF)
                   1911:                            || lasttk == NEW || in_sizeof )
                   1912:                        {  
                   1913:                                if ( nstd->n_tbl_list == 0 ) { // only one: ok
                   1914:                                        break;
                   1915:                                } else {
                   1916:                                        if (lasttk != TSCOPE && !ok){
                   1917:                                                error("ambiguous nested type %s, use X::%s",nn->string,nn->string);
                   1918:                                                error( 'i', "cannot recover from previous errors" );
                   1919:                                        }
                   1920:                                }
                   1921:                        }
                   1922:                }
                   1923:                if ( nn->n_key != NESTED ) continue;
                   1924:                if (xcl && strcmp(xcl->string,cl->string) == 0) break;
                   1925:        } // end: for nn = nstd
                   1926:        return nn;
                   1927: }
                   1928: 

unix.superglobalmegacorp.com

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