Annotation of researchv10no/cmd/cfront/ooptcfront/tree_walk.c, revision 1.1.1.1

1.1       root        1: /* -*- Mode: C -*- */
                      2: /*
                      3:        $Source: /usr3/lang/benson/work/stripped_cfront/RCS/tree_walk.c,v $ $RCSfile: tree_walk.c,v $
                      4:        $Revision: 1.1 $                $Date: 89/11/20 08:51:06 $
                      5:        $Author: benson $               $Locker:  $
                      6:        $State: Exp $
                      7: */
                      8: 
                      9: /* Utilities for tree-walking */
                     10: 
                     11: #include "cfront.h"
                     12: #include "tree_walk.H"
                     13: #include <stdarg.h>
                     14: #include "hash.h"
                     15: // #include <alloca.h>
                     16: // need to add an explicit call of free
                     17: #include <streamdefs.h>
                     18: #include <malloc.h>
                     19: 
                     20: class walker {
                     21:     tree_walk_control control;
                     22:     Pnode orig_addr;
                     23:     Hash *nodes_seen_hash;
                     24:     int depth;
                     25:     int made_ht;
                     26:     tree_walk_tree * cur_tree;
                     27:   public:
                     28:     walker(tree_walk_control& c) ;
                     29:  
                     30:     ~walker () {
                     31:        if(made_ht) delete nodes_seen_hash;
                     32:     }
                     33:     tree_node_action walk (Pnode&);
                     34:     tree_node_action walk_ (Pnode& n) 
                     35:     {
                     36:        if(n) {
                     37:            int save_depth = depth;
                     38:            tree_walk_tree * save_cur_tree = cur_tree;
                     39: 
                     40:            depth ++;
                     41:            if(control.alloc_stack_bytes) {
                     42:                cur_tree = (tree_walk_tree *)
                     43:                    // alloca (control.alloc_stack_bytes + sizeof (tree_walk_tree));
                     44:                    malloc(control.alloc_stack_bytes + sizeof (tree_walk_tree));
                     45:                cur_tree->parent = save_cur_tree;
                     46:            }
                     47:            tree_node_action r = walk(n);
                     48:            depth = save_depth;
                     49:            return r;
                     50:        } else return tna_continue;
                     51:     }
                     52:        
                     53:     tree_node_action walk(Pgen& n) 
                     54:     { return walk_ ((struct node * &)n); };
                     55:     tree_node_action walk(Pvec& n) 
                     56:     { return walk_ ((struct node * &)n); };
                     57:     tree_node_action walk(Pptr& n) 
                     58:     { return walk_ ((struct node * &)n); };
                     59:     tree_node_action walk(Ptype& n) 
                     60:     { return walk_ ((struct node * &)n); };
                     61:     tree_node_action walk(Pfct& n) 
                     62:     { return walk_ ((struct node * &)n); };
                     63:     tree_node_action walk(Ptable& n) 
                     64:     { return walk_ ((struct node * &)n); };
                     65:     tree_node_action walk(Pbase& n) 
                     66:     { return walk_ ((struct node * &)n); };
                     67:     tree_node_action walk(Pname& n) 
                     68:     { return walk_ ((struct node * &)n); };
                     69:      tree_node_action walk(Pexpr& n) 
                     70:     { return walk_ ((struct node * &)n); };
                     71:     tree_node_action walk(Pstmt& n) 
                     72:     { return walk_ ((struct node * &)n); };
                     73:     tree_node_action walk(Pblock& n) 
                     74:     { return walk_ ((struct node * &)n); };
                     75:     tree_node_action walk(Penum& n) 
                     76:     { return walk_ ((struct node * &)n); };
                     77:     tree_node_action walk(Pclass& n) 
                     78:     { return walk_ ((struct node * &)n); };
                     79:     tree_node_action walk(Pvirt& n) 
                     80:     { return walk_ ((struct node * &)n); };
                     81:     tree_node_action walk(Plist& n) 
                     82:     { return walk_ ((struct node * &)n); };
                     83:     tree_node_action walk(Pin& n) 
                     84:     { return walk_ ((struct node * &)n); };
                     85:     tree_node_action walk(struct ia * & n) 
                     86:     { return walk_ ((struct node * &)n); };
                     87:     tree_node_action walk(Pbcl& n) 
                     88:     { return walk_ ((struct node * &)n); };
                     89:   private:
                     90:     int fetching () {  return (control.fetcher != null_tfp); } ;
                     91:     void free_fetched (void *);
                     92:     int fetch (void *, unsigned long, void *&);
                     93:     int fetch (void * a, unsigned long l, Pnode& p) 
                     94:     {
                     95:        int ret;
                     96:        void * t;               /* this is an output argument */
                     97:        ret = fetch(a,l,t);
                     98:        if(!ret) {
                     99:            p = Pnode(t);
                    100:        }
                    101:        return ret;
                    102:     };
                    103:     // void error (const char *,...); ?? at&t -- to get it up quick, line 155
                    104:     void error ( char *, unsigned long=0 );
                    105:     tree_node_action pre_act_on_node (Pnode node, node_class nc,
                    106:                                      Pnode node_copy, Pnode& replacement);
                    107:                                       
                    108:     tree_node_action a_gen (Pnode, Pgen, Pnode&);
                    109:     tree_node_action a_vec (Pnode, Pvec, Pnode&);
                    110:     tree_node_action a_ptr (Pnode, Pptr, Pnode&);
                    111:     tree_node_action a_fct (Pnode, Pfct, Pnode&);
                    112:     tree_node_action a_table (Pnode, Ptable, Pnode&);
                    113:     tree_node_action a_basetype (Pnode, Pbase, Pnode&);
                    114:     tree_node_action a_name(Pnode, Pname, Pnode&);
                    115:     tree_node_action a_expr (Pnode, Pexpr, Pnode&);
                    116:     tree_node_action a_stmt (Pnode, Pstmt, Pnode&);
                    117:     tree_node_action a_enumdef (Pnode, Penum, Pnode&);
                    118:     tree_node_action a_classdef (Pnode, Pclass, Pnode&);
                    119:     tree_node_action a_virt (Pnode, Pvirt, Pnode&);
                    120:     tree_node_action a_name_list (Pnode, Plist, Pnode&);
                    121:     tree_node_action a_iline (Pnode, Pin, Pnode&);
                    122:     tree_node_action a_ia (Pnode, struct ia *, Pnode&);
                    123:     tree_node_action a_baseclass (Pnode, Pbcl, Pnode&);
                    124:     tree_node_action a_expr_guts (Pexpr);
                    125: };
                    126: 
                    127: 
                    128: walker::walker(tree_walk_control& c) 
                    129: { control = c;
                    130:   made_ht = 0;
                    131:   if (c.nodes_seen_hash)
                    132:     nodes_seen_hash = c.nodes_seen_hash;
                    133:   else {
                    134:     nodes_seen_hash = new pointer_hash (100);
                    135:     made_ht = 1;
                    136:   }
                    137:   depth = 0;
                    138:   cur_tree = 0;
                    139: }
                    140: 
                    141: 
                    142: tree_node_action
                    143: walk_tree (tree_walk_control& c, Pnode& n)
                    144: {
                    145:     walker w (c);
                    146:     return w.walk(n);
                    147: }
                    148: 
                    149: 
                    150: /* error messages are of finite length, so no need to run
                    151:    around mallocing strings */
                    152: 
                    153: // void walker::error (const char * format, ...)
                    154: void walker::error (char *format, unsigned long v)
                    155: {
                    156:     va_list args;
                    157:     va_start(args, format);
                    158:     if(control.call_i_error) {
                    159:        char buf[1000];
                    160:        // vsprintf(buf, format, args);
                    161:         // vsprintf not universal: by inspection
                    162:         // all calls are currently of 1 or 0 arguments
                    163:        sprintf(buf, format, v);
                    164:        (*control.i_error)('i', buf);
                    165:     } else {
                    166:        vostream_printf (format, args, *control.error_stream);
                    167:        *control.error_stream << "\n";
                    168:        control.error_stream->flush();
                    169:     }
                    170:     va_end (args);
                    171: }
                    172: 
                    173: 
                    174: void
                    175: walker::free_fetched (void * addr)
                    176: {
                    177:     if (control.fetcher != null_tfp)   /* null indicates no cross-address-space */
                    178:        free ((char *)addr);    
                    179: }    
                    180: 
                    181: int
                    182: walker::fetch (void * addr, unsigned long length, void*& taddr)
                    183: {
                    184:     int err;
                    185: 
                    186:     if (control.fetcher == null_tfp) { 
                    187:        taddr = addr;
                    188:        return 0;
                    189:     } else {
                    190:        taddr = (void *)malloc ((unsigned int)length);
                    191:        if(taddr == 0) {
                    192:           error ("walker::fetch: failed to malloc %d bytes.", length);
                    193:           return 1;
                    194:        }
                    195: 
                    196:        err = (*control.fetcher) (control.callback_info, addr, length, 0, taddr);
                    197:        if(err) {
                    198:           error("walker::fetch: fetcher returned %d.", err);
                    199:           return 1;
                    200:        }
                    201:    }
                    202: }
                    203: 
                    204: /* ::walk is called with a node pointer and a reference to
                    205:    a replacement node pointer. When it returns,
                    206:    replacement will be set if the action procedure
                    207:    called on the node decided to copy it or replace it.
                    208:    There are two possible modularities. 
                    209:    In case there is cross-address-space action,
                    210:    ::walk can't call the action procedure until it has
                    211:    entered the case on node bases. Once it has,
                    212:    it calls the per-structure-type procedure,
                    213:    which calls the action proc. If the action 
                    214:    proc supplies a replacement, then that replacement
                    215:    will be returned up via the reference parameters to 
                    216:    the per-structure procedures.
                    217: 
                    218:    It the action procedure returns tna_continue,
                    219:    then the walk continues against the new copy of the node
                    220:    so that further replacements are reflected in the new copies.
                    221:    This prevents replacement from being meaningful cross-address-space,
                    222:    since the new copy will presumably be in the current 
                    223:    (and not the cross) address space. That is, if the node
                    224:    is replaced by the action proc, the pointers in the new 
                    225:    node will drive the subsequent tree walk. Usually one
                    226:    would just bitcopy, and then they would be replaced in turn.
                    227: */
                    228: 
                    229: tree_node_action
                    230: walker::walk (Pnode& top)
                    231: {
                    232:     Pnode replacement = 0;
                    233:     tree_node_action err;
                    234:     int class_err;
                    235:     node_class nclass;
                    236:     Pnode node = 0; /* assign to shut up compiler,
                    237:                       which dosen't recognize pass-by-reference as a set */
                    238: 
                    239:     orig_addr = top;
                    240: 
                    241:     if(fetching ()) {
                    242:        if(fetch((void *)top, sizeof (struct node), node))
                    243:            return tna_error;
                    244:     } else node = top;
                    245: 
                    246: /* This has a complete catalog of bases, rather than just a list
                    247:    of those associated with data structures. Its important
                    248:    to detect the errs.
                    249: */   
                    250: 
                    251:     nclass = classify_node (node, class_err);
                    252: 
                    253:     if(class_err) {
                    254:        error("walker::walk: unknown node type %d.", node->base);
                    255:        free_fetched ((void *)node);
                    256:        err = tna_error;
                    257:        goto Return;
                    258:     }
                    259:     
                    260:     switch(nclass)
                    261:     {
                    262:       default:
                    263:       case nc_unused:
                    264:        error("walker::walk: unused node type %d.", node->base);
                    265:        err = tna_error;
                    266:        goto Return;
                    267: 
                    268:       case nc_eof:
                    269:        break;
                    270: 
                    271:       case nc_virt:
                    272:        fetch((void *)top, sizeof (struct virt), node);
                    273:        err = a_virt(top, Pvirt (node), replacement);
                    274:        break;
                    275: 
                    276:       case nc_nlist:
                    277:        fetch((void *)top, sizeof (struct name_list), node);
                    278:        err = a_name_list(top, (struct name_list *)node, replacement);
                    279:        break;
                    280: 
                    281:       case nc_iline:
                    282:        fetch((void *)top, sizeof (struct iline), node);
                    283:        err = a_iline(top, (struct iline *)node, replacement);
                    284:        break;
                    285: 
                    286:       case nc_gen:
                    287:        fetch((void *)top, sizeof (struct gen), node);
                    288:        err = a_gen(top, Pgen (node), replacement);
                    289:        break;
                    290: 
                    291:       case nc_vec:
                    292:        fetch((void *)top, sizeof (struct vec), node);
                    293:        err = a_vec(top, Pvec(node), replacement);
                    294:        break;
                    295: 
                    296:       case nc_ptr:
                    297:        fetch((void *)top, sizeof (struct ptr), node);
                    298:        err = a_ptr(top, Pptr(node), replacement);
                    299:        break;
                    300: 
                    301:       case nc_fct:
                    302:        fetch((void *)top, sizeof (struct fct), node);
                    303:        err = a_fct(top, Pfct(node), replacement);
                    304:        break;
                    305: 
                    306:       case nc_table:
                    307:        fetch((void *)top, sizeof (struct table), node);
                    308:        err = a_table(top, Ptable(node), replacement);
                    309:        break;
                    310: 
                    311:       case nc_basetype:
                    312:        fetch((void *)top, sizeof (struct basetype), node);
                    313:        err = a_basetype(top, Pbase(node), replacement);
                    314:        break;
                    315: 
                    316:       case nc_name:
                    317:        fetch((void *)top, sizeof (struct name), node);
                    318:        err = a_name(top, Pname(node), replacement);
                    319:        break;
                    320: 
                    321:       case nc_expr:
                    322:        fetch((void *)top, sizeof (struct expr), node);
                    323:        err = a_expr(top, Pexpr(node), replacement);
                    324:        break;
                    325: 
                    326:       case nc_stmt:
                    327:        fetch((void *)top, sizeof (struct stmt), node);
                    328:        err = a_stmt(top, Pstmt(node), replacement);
                    329:        break;
                    330: 
                    331:       case nc_enumdef:
                    332:        fetch((void *)top, sizeof (struct enumdef), node);
                    333:        err = a_enumdef(top, Penum(node), replacement);
                    334:        break;
                    335: 
                    336:       case nc_classdef:
                    337:        fetch((void *)top, sizeof (struct classdef), node);
                    338:        err = a_classdef(top, Pclass(node), replacement);
                    339:        break;
                    340: 
                    341:       case nc_ia:
                    342:        fetch((void *)top, sizeof (struct ia), node);
                    343:        err = a_ia(top, (struct ia *)node, replacement);
                    344:        break;
                    345: 
                    346:       case nc_baseclass:
                    347:        fetch((void *)top, sizeof (struct basecl), node);
                    348:        err = a_baseclass(top, Pbcl(node), replacement);
                    349:        break;
                    350: 
                    351:     }
                    352: 
                    353:     if(replacement) {
                    354:        if (fetching ()) {
                    355:            error
                    356:                ("walker::walk: Attempt to replace tree in cross-address space mode.");
                    357:            err = tna_error;
                    358:        } 
                    359:        else top = replacement;
                    360:     }
                    361:        
                    362:     if (control.post_action_proc && err != tna_error) {
                    363:        tree_node_action post_err;
                    364:        Pnode& post_repl = node;
                    365: 
                    366:        (*control.post_action_proc) (post_repl, nclass, control.callback_info, post_err,
                    367:                                     depth, orig_addr, *cur_tree);
                    368:        if(post_err != tna_continue) err = post_err;
                    369:        if(post_repl != node) {
                    370:            if (fetching ()) {
                    371:                error
                    372:                    ("walker::walk: Attempt to replace tree in cross-address space mode.");
                    373:                err = tna_error;
                    374:            } 
                    375:            else top = post_repl;
                    376:        }
                    377:     }
                    378: 
                    379:     free_fetched((void *) node);
                    380: 
                    381: Return:
                    382:     return err;
                    383: }
                    384: 
                    385: /* This is called in pre-order for each node. Then
                    386:    post_act_on_node is called after whatever recursive
                    387:    processing ensues.
                    388:    
                    389:    This is called from each of the structure-specific procedures
                    390:    to give the action procedure an opportunity to act.
                    391:    It can return a replacement pointer and control
                    392:    whether to examine the insides of the node.
                    393:    */
                    394: 
                    395: tree_node_action 
                    396: walker::pre_act_on_node (Pnode node, node_class nc,
                    397:                       Pnode node_copy, Pnode& replacement)
                    398: {
                    399: /* If we have been here before, then we never proceed */
                    400: /* node_copy is != node when a fetcher is in use */
                    401: 
                    402:     int found;
                    403:     int old_node;
                    404:     tree_node_action action;
                    405:     Pnode new_node;
                    406:     int register_in_hash = 1;
                    407: 
                    408:     nodes_seen_hash->action((int)node, 0, Hash::probe, found, old_node);
                    409: 
                    410:     if(found) {
                    411:        new_node = Pnode(old_node);
                    412:        if(new_node != node) replacement = new_node;
                    413:        return tna_stop; /* no need to proceed */
                    414:     }
                    415: 
                    416:     /* OK, we don't know from a previous pass. Call our actor */
                    417: 
                    418:     new_node = fetching () && node_copy ? node_copy : node;
                    419: 
                    420:     (*control.action_proc)(new_node, nc, control.callback_info, action, 
                    421:                           depth, orig_addr, *cur_tree,
                    422:                           register_in_hash);
                    423: 
                    424:     if(action != tna_error && !fetching () && new_node != node) {
                    425:        replacement = new_node;
                    426:        if(register_in_hash)
                    427:            nodes_seen_hash->action((int)node, 
                    428:                                    (int)new_node, 
                    429:                                    Hash::insert, 0, 0);
                    430:     }
                    431:     else {
                    432:        if(register_in_hash)
                    433:            nodes_seen_hash->action((int)node, (int) node, Hash::insert, 0, 0);
                    434:     }
                    435:     return action;
                    436: }                         
                    437: 
                    438: tree_node_action walker::a_table(Pnode ta, Ptable t, Pnode& replacement) 
                    439: {
                    440:     /* no unions */
                    441: 
                    442:     int nx;
                    443:     tree_node_action action;
                    444: 
                    445:     action = pre_act_on_node(ta, nc_table, Pnode(t), replacement);
                    446: 
                    447:     if(action != tna_continue) return action;
                    448: 
                    449: /* -----------------------------*/
                    450: /* For Now, Never Walk a Table. */
                    451: 
                    452:     action = tna_stop; return action;
                    453: 
                    454: /* an array of pointers. */
                    455: /* The action procedure is responsable for allocating a new one
                    456:    of those if it replaced and continued. */
                    457: 
                    458:     if(!fetching () && replacement)
                    459:        t = Ptable(replacement);
                    460: 
                    461:     Pname * t_entries;
                    462: 
                    463:     if(fetching ()) {
                    464:        void * temp;
                    465:        fetch((void *)t->entries, t->size * sizeof(Pname), temp);
                    466:        t_entries = (Pname *)temp;
                    467:     }
                    468:     else t_entries = t->entries;
                    469: 
                    470:     for(nx = 0; nx < t->size; nx ++) {
                    471:        action = walk(t_entries[nx]);
                    472:        if(action == tna_error) return action;
                    473:     }
                    474: 
                    475:     if(fetching ()) free_fetched ((void *)t_entries);
                    476:     
                    477:     Pnode n = Pnode(t->real_block);
                    478: 
                    479:     action = walk(t->real_block);
                    480:     if(action == tna_error) return action;
                    481:     
                    482:     action = walk(t->next);
                    483: 
                    484:     action = walk(t->t_name);
                    485: 
                    486:     return tna_continue;
                    487: }
                    488: 
                    489: tree_node_action walker::a_enumdef (Pnode ta, Penum e, Pnode& replacement) 
                    490: {
                    491:     tree_node_action action = pre_act_on_node(ta, nc_enumdef, Pnode(e), replacement);
                    492: 
                    493:     action = walk(e->mem);
                    494:     if(action == tna_error) return action;
                    495: 
                    496:     action = walk(e->e_type);
                    497: 
                    498:     return tna_continue;
                    499: }    
                    500: 
                    501: tree_node_action walker::a_virt(Pnode ta, Pvirt v, Pnode& replacement) 
                    502: {
                    503:     /* no unions */
                    504: 
                    505:     int nx;
                    506:     tree_node_action action = pre_act_on_node(ta, nc_enumdef, Pnode(v), replacement);
                    507: 
                    508:     if(action != tna_continue) return action;
                    509: 
                    510:     if(!fetching () && replacement)
                    511:        v = Pvirt(replacement);
                    512: 
                    513: /* an array of velem structures. */
                    514: 
                    515:     velem * v_virt_init;
                    516: 
                    517:     if(fetching ()) {
                    518:        void * t;
                    519:        fetch((void *)v->virt_init, v->n_init * sizeof(velem), t);
                    520:        v_virt_init = (velem *)t;
                    521:     }
                    522:     else v_virt_init = v->virt_init;
                    523: 
                    524:     for(nx = 0; nx < v->n_init; nx ++) {
                    525:        action = walk(v_virt_init[nx].n);
                    526:        if(action == tna_error) return action;
                    527:     }
                    528: 
                    529:     if(fetching ()) free_fetched ((void *)v_virt_init);
                    530:     
                    531:     action = walk(v->vclass);
                    532:     
                    533:     return tna_continue;
                    534: }
                    535: 
                    536: tree_node_action walker::a_classdef(Pnode ta, Pclass c, Pnode& replacement) 
                    537: {
                    538: 
                    539:     tree_node_action action = pre_act_on_node(ta, nc_classdef, Pnode(c), replacement);
                    540: 
                    541:     if(action != tna_continue) return action;
                    542: 
                    543:     if(!fetching () && replacement)
                    544:        c = Pclass(replacement);
                    545: 
                    546:     action = walk(c->baselist);
                    547:     if(action == tna_error) return action;
                    548: 
                    549:     action=walk(c->mem_list);
                    550:     if(action == tna_error) return action;
                    551:     
                    552:     action=walk(c->memtbl);
                    553:     if(action == tna_error) return action;
                    554: 
                    555:     action=walk(c->friend_list);
                    556:     if(action == tna_error) return action;
                    557: 
                    558:     action=walk(c->pubdef);
                    559:     if(action == tna_error) return action;
                    560:     
                    561:     action=walk(c->tn_list);
                    562:     if(action == tna_error) return action;
                    563: 
                    564:     action=walk(c->in_class);
                    565:     if(action == tna_error) return action;
                    566: 
                    567:     action=walk(c->in_fct);
                    568:     if(action == tna_error) return action;
                    569: 
                    570:     action=walk(c->this_type);
                    571:     if(action == tna_error) return action;
                    572: 
                    573:     action=walk(c->virt_list);
                    574:     if(action == tna_error) return action;
                    575: 
                    576:     action=walk(c->c_ctor);
                    577:     if(action == tna_error) return action;
                    578:     action=walk(c->c_dtor);
                    579:     if(action == tna_error) return action;
                    580:     action=walk(c->c_itor);
                    581:     if(action == tna_error) return action;
                    582: 
                    583:     action=walk(c->conv);
                    584:     if(action == tna_error) return action;
                    585: 
                    586:     return tna_continue;
                    587: }
                    588: 
                    589: tree_node_action walker::a_basetype(Pnode ta, Pbase b, Pnode& replacement) 
                    590: {
                    591: 
                    592:     tree_node_action action = pre_act_on_node(ta, nc_basetype, Pnode(b), replacement);
                    593:     int derr;
                    594: 
                    595:     if(action != tna_continue) return action;
                    596: 
                    597:     if(!fetching () && replacement)
                    598:        b = Pbase(replacement);
                    599: 
                    600:     action = walk(b->b_name);
                    601:     if(action == tna_error) return action;
                    602: 
                    603:     action = walk(b->b_table);
                    604:     if(action == tna_error) return action;
                    605: 
                    606:     action = walk(b->b_field);
                    607:     if(action == tna_error) return action;
                    608: 
                    609:     action = walk(b->b_xname);
                    610:     if(action == tna_error) return action;
                    611: 
                    612:     switch(derr = b->discriminator(0)) {
                    613:       case 0: break;
                    614:       case 1:
                    615:        action = walk(b->b_fieldtype);
                    616:        if(action == tna_error) return action;
                    617:        break;
                    618:       case 2: break;
                    619:       default:
                    620:        error ("a_basetype: discrim error %d.", derr);
                    621:        return tna_error;
                    622:     }
                    623: 
                    624:     return tna_continue;
                    625: }
                    626: 
                    627: tree_node_action walker::a_fct(Pnode ta, Pfct f, Pnode& replacement) 
                    628: {
                    629: 
                    630:     tree_node_action action = pre_act_on_node(ta, nc_fct, Pnode(f), replacement);
                    631: 
                    632:     if(action != tna_continue) return action;
                    633: 
                    634:     if(!fetching () && replacement)
                    635:        f = Pfct(replacement);
                    636: 
                    637:     action = walk(f->returns);
                    638:     if(action == tna_error) return action;
                    639: 
                    640:     action = walk(f->argtype);
                    641:     if(action == tna_error) return action;
                    642: 
                    643:     action = walk(f->s_returns);
                    644:     if(action == tna_error) return action;
                    645: 
                    646:     action = walk(f->f_this);
                    647:     if(action == tna_error) return action;
                    648: 
                    649:     action = walk(f->memof);
                    650:     if(action == tna_error) return action;
                    651: 
                    652:     action = walk(f->body);
                    653:     if(action == tna_error) return action;
                    654: 
                    655:     action = walk(f->f_init);
                    656:     if(action == tna_error) return action;
                    657: 
                    658:     action = walk(f->f_expr);
                    659:     if(action == tna_error) return action;
                    660: 
                    661:     action = walk(f->last_expanded);
                    662:     if(action == tna_error) return action;
                    663: 
                    664:     action = walk(f->f_result);
                    665:     if(action == tna_error) return action;
                    666: 
                    667:     action = walk(f->f_args);
                    668:     if(action == tna_error) return action;
                    669: 
                    670:     return tna_continue;
                    671: }
                    672: 
                    673: tree_node_action walker::a_name_list(Pnode ta, Plist l, Pnode& replacement) 
                    674: {
                    675: 
                    676:     int cl_error;
                    677:     tree_node_action action = pre_act_on_node(ta, nc_nlist, Pnode(l), replacement);
                    678: 
                    679:     if(action == tna_stop) {
                    680:        if(!fetching () && replacement)
                    681:            l = Plist(replacement);
                    682:        cl_error = 0;
                    683:        if((classify_node(Pnode(l), cl_error) == nc_nlist) && !cl_error) {
                    684:            action = walk(l->l);
                    685:            if(action == tna_error) return action;
                    686:        }
                    687:     }
                    688: 
                    689:     if(action != tna_continue) return action;
                    690: 
                    691:     if(!fetching () && replacement)
                    692:        l = Plist(replacement);
                    693: 
                    694:     action = walk(l->f);
                    695:     if(action == tna_error) return action;
                    696: 
                    697:     action = walk(l->l);
                    698:     if(action == tna_error) return action;
                    699: 
                    700:     return tna_continue;
                    701: }
                    702: 
                    703: tree_node_action walker::a_gen(Pnode ta, Pgen g, Pnode& replacement) 
                    704: {
                    705: 
                    706:     tree_node_action action = pre_act_on_node(ta, nc_gen, Pnode(g), replacement);
                    707: 
                    708:     if(action != tna_continue) return action;
                    709: 
                    710:     if(!fetching () && replacement)
                    711:        g = Pgen(replacement);
                    712: 
                    713:     action = walk(g->fct_list);
                    714:     if(action == tna_error) return action;
                    715: 
                    716:     return tna_continue;
                    717: }
                    718: 
                    719: tree_node_action walker::a_vec(Pnode ta, Pvec v, Pnode& replacement) 
                    720: {
                    721: 
                    722:     tree_node_action action = pre_act_on_node(ta, nc_vec, Pnode(v), replacement);
                    723: 
                    724:     if(action != tna_continue) return action;
                    725: 
                    726:     if(!fetching () && replacement)
                    727:        v = Pvec(replacement);
                    728: 
                    729:     action = walk(v->typ);
                    730:     if(action == tna_error) return action;
                    731: 
                    732:     action = walk(v->dim);
                    733:     if(action == tna_error) return action;
                    734: 
                    735:     return tna_continue;
                    736: }
                    737: 
                    738: tree_node_action walker::a_ptr(Pnode ta, Pptr p, Pnode& replacement) 
                    739: {
                    740: 
                    741:     tree_node_action action = pre_act_on_node(ta, nc_ptr, Pnode(p), replacement);
                    742: 
                    743:     if(action != tna_continue) return action;
                    744: 
                    745:     if(!fetching () && replacement)
                    746:        p = Pptr(replacement);
                    747: 
                    748:     action = walk(p->typ);
                    749:     if(action == tna_error) return action;
                    750: 
                    751:     action = walk(p->memof);
                    752:     if(action == tna_error) return action;
                    753: 
                    754:     return tna_continue;
                    755: }
                    756: 
                    757: 
                    758: tree_node_action walker::a_expr_guts(Pexpr e)
                    759: {
                    760:     int derr;
                    761:     tree_node_action action;
                    762: 
                    763:     switch(derr = e->discriminator (0)) {
                    764:       case 1:
                    765:        action = walk(e->tp);
                    766:        if(action == tna_error) return action;
                    767:        break;
                    768:       case 0:
                    769:        break;
                    770:       default:
                    771:        error ("a_expr: discrim error %d on union 0.", derr);
                    772:        return tna_error;
                    773:     }
                    774: 
                    775:     switch(derr = e->discriminator (1)) {
                    776:       case 0:
                    777:        break;
                    778:       default:
                    779:        error ("a_expr: discrim error %d on union 1.", derr);
                    780:        return tna_error;
                    781:       case 1:
                    782:        action = walk(e->e1);
                    783:        if(action == tna_error) return action;
                    784:        break;
                    785:       case 2:
                    786:        break;
                    787:       case 3:
                    788:        break;
                    789:     }
                    790: 
                    791:     switch(derr = e->discriminator (2)) {
                    792:       case 0:
                    793:        break;
                    794:       default:
                    795:        error ("a_expr: discrim error %d on union 2.", derr);
                    796:        return tna_error;
                    797:       case 1:
                    798:        /* elists are special. e2 for an elist is a peer, not
                    799:           a child. */
                    800:        if(e->base != ELIST) {
                    801:            action = walk(e->e2);
                    802:            if(action == tna_error) return action;
                    803:        }
                    804:        break;
                    805:       case 2:
                    806:        break;
                    807:       case 3:
                    808:        break;
                    809:       case 4:
                    810:        action = walk(e->n_initializer);
                    811:        if(action == tna_error) return action;
                    812:        break;
                    813:     }
                    814:     
                    815:     switch(derr = e->discriminator (3)) {
                    816:       case 0:
                    817:        break;
                    818:       default:
                    819:        error ("a_expr: discrim error %d on union 3.", derr);
                    820:        return tna_error;
                    821:       case 1:
                    822:        action = walk(e->tp2);
                    823:        if(action == tna_error) return action;
                    824:        break;
                    825:       case 2:
                    826:        action = walk(e->fct_name);
                    827:        if(action == tna_error) return action;
                    828:        break;
                    829:       case 3:
                    830:        action = walk(e->cond);
                    831:        if(action == tna_error) return action;
                    832:        break;
                    833:       case 4:
                    834:        action = walk(e->mem);
                    835:        if(action == tna_error) return action;
                    836:        break;
                    837:       case 5:
                    838:        action = walk(e->as_type);
                    839:        if(action == tna_error) return action;
                    840:        break;
                    841:       case 6:
                    842:        action = walk(e->n_table);
                    843:        if(action == tna_error) return action;
                    844:        break;
                    845:       case 7:
                    846:        action = walk(e->il);
                    847:        if(action == tna_error) return action;
                    848:        break;
                    849:       case 8:
                    850:        action = walk(e->query_this);
                    851:        if(action == tna_error) return action;
                    852:        break;
                    853:     }
                    854:     return tna_continue;
                    855: }
                    856: 
                    857: 
                    858: tree_node_action walker::a_expr(Pnode ta, Pexpr e, Pnode& replacement) 
                    859: {
                    860:     tree_node_action action = pre_act_on_node(ta, nc_expr, Pnode(e), replacement);
                    861: 
                    862:     if(action == tna_stop) {
                    863:        if(!fetching () && replacement)
                    864:            e = Pexpr(replacement);
                    865:        /* ELIST implies that e2 is a peer, not a child */
                    866:        if(e->base == ELIST) {
                    867:            action = walk(e->e2);
                    868:            return action;
                    869:        }
                    870:     }
                    871:        
                    872:     if(action != tna_continue) return action;
                    873: 
                    874:     if(!fetching () && replacement)
                    875:        e = Pexpr(replacement);
                    876: 
                    877:     action = a_expr_guts(e);
                    878:     if (action == tna_error) return action;
                    879:     if(e->base == ELIST)
                    880:        action = walk(e->e2);
                    881:     return action;
                    882: }
                    883: 
                    884: tree_node_action walker::a_baseclass(Pnode ta, Pbcl b, Pnode& replacement) 
                    885: {
                    886:     tree_node_action action = pre_act_on_node(ta, nc_baseclass, Pnode(b), replacement);
                    887: 
                    888:     if(action != tna_continue) return action;
                    889: 
                    890:     if(!fetching () && replacement)
                    891:        b = Pbcl(replacement);
                    892: 
                    893:     action = walk(b->bclass);
                    894:     if(action == tna_error) return action;
                    895: 
                    896:     action = walk(b->init);
                    897:     if(action == tna_error) return action;
                    898: 
                    899:     action = walk(b->next);
                    900:     if(action == tna_error) return action;
                    901: 
                    902:     return tna_continue;
                    903: }
                    904: 
                    905: 
                    906: /* a name is also an expr. */
                    907:    
                    908: 
                    909: tree_node_action walker::a_name(Pnode ta, Pname n, Pnode& replacement) 
                    910: {
                    911:     int derr;
                    912:     int cl_error;
                    913:     tree_node_action action = pre_act_on_node(ta, nc_name, Pnode(n), replacement);
                    914: 
                    915:     /* n_list is a sibling, not a child. We always process it
                    916:        except in case of an error. */
                    917:     if(action == tna_stop) {
                    918:        cl_error = 0;
                    919:        if(!fetching () && replacement)
                    920:            n = Pname(replacement);
                    921:        if((classify_node(Pnode(n), cl_error) == nc_name) && !cl_error) {
                    922:            if(depth > 0 || !control.dont_chase_lists_top) {
                    923:                action = walk(n->n_list); 
                    924:                if(action == tna_error) return action;
                    925:            }
                    926:        }
                    927:        return tna_stop;
                    928:     }  
                    929: 
                    930:     if(action != tna_continue) return action;
                    931: 
                    932:     if(!fetching () && replacement)
                    933:        n = Pname(replacement);
                    934: 
                    935: /* We don't walk n_tbl_list. Its not part of the graph.
                    936:    */
                    937: 
                    938:     switch(derr = n->discriminator(0)) {
                    939:       case 0:
                    940:        break;
                    941:       case 1:
                    942:        action = walk(n->n_qualifier);
                    943:        if(action == tna_error) return action;
                    944:        break;
                    945:       case 2:
                    946:        action = walk(n->n_realscope);
                    947:        if(action == tna_error) return action;
                    948:        break;
                    949:       default:
                    950:        error ("a_name: discrim error %d on union 0.", derr);
                    951:        return tna_error;
                    952:     }
                    953: 
                    954:     action = a_expr_guts(Pexpr(n));
                    955:     if(action == tna_error) return action;
                    956: 
                    957:     if(depth > 0 || !control.dont_chase_lists_top) {
                    958:        action = walk(n->n_list);
                    959:        if(action == tna_error) return action;
                    960:     }
                    961:     
                    962:     return action;
                    963: }
                    964:     
                    965: /* --- NOTE: s_list should be deferred until AFTER the post-action
                    966:    procedure is called, if there is one. Since no one uses
                    967:    post-actions yet I haven't bothered to make this fix.
                    968:    --benson */
                    969: 
                    970: tree_node_action walker::a_stmt(Pnode ta, Pstmt s, Pnode& replacement) 
                    971: {
                    972:     int cl_error;
                    973:     int derr;
                    974:     tree_node_action action = pre_act_on_node(ta, nc_stmt, Pnode(s), replacement);
                    975: 
                    976:     if(action == tna_stop) {
                    977:        if(!fetching () && replacement)
                    978:            s = Pstmt(replacement);
                    979:        cl_error = 0;
                    980:        if((classify_node(Pnode(s), cl_error) == nc_stmt) && !cl_error) {
                    981:            /* s_list is not our subordinate, it is our peer */
                    982:            if(depth > 0 || !control.dont_chase_lists_top) {
                    983:                action = walk(s->s_list); /* continue walk of sibs */
                    984:                if (action == tna_error) return tna_error;
                    985:            }
                    986:        }
                    987:        return tna_stop;
                    988:     }
                    989: 
                    990:     if(action != tna_continue) return action;
                    991: 
                    992:     if(!fetching () && replacement)
                    993:        s = Pstmt(replacement);
                    994: 
                    995:     action = walk(s->s);
                    996:     if(action == tna_error) return action;
                    997: 
                    998:     action = walk(s->memtbl);
                    999:     if(action == tna_error) return action;
                   1000: 
                   1001:     switch(derr = s->discriminator(0)) {
                   1002:       default:
                   1003:        error ("a_stmt: discrim error %d on union 0.", derr);
                   1004:        return tna_error;
                   1005:       case 4:
                   1006:       case 0: break;
                   1007:       case 1:
                   1008:        action = walk(s->d);
                   1009:        if(action == tna_error) return action;
                   1010:        break;
                   1011:       case 2:
                   1012:        action = walk(s->e2);
                   1013:        if(action == tna_error) return action;
                   1014:        break;
                   1015:       case 3:
                   1016:        action = walk(s->has_default);
                   1017:        if(action == tna_error) return action;
                   1018:        break;
                   1019:       case 5:
                   1020:        action = walk(s->ret_tp);
                   1021:        if(action == tna_error) return action;
                   1022:        break;
                   1023:     }
                   1024: 
                   1025:     switch(derr = s->discriminator(1)) {
                   1026:       default:
                   1027:        error ("a_stmt: discrim error %d on union 1.", derr);
                   1028:        return tna_error;
                   1029:       case 2:
                   1030:       case 0: break;
                   1031:       case 1:
                   1032:        action = walk(s->e);
                   1033:        if(action == tna_error) return action;
                   1034:        break;
                   1035:       case 3:
                   1036:        action = walk(s->s2);
                   1037:        if(action == tna_error) return action;
                   1038:        break;
                   1039:     }
                   1040: 
                   1041:     switch(derr = s->discriminator(2)) {
                   1042:       default:
                   1043:        error ("a_stmt: discrim error %d on union 2.", derr);
                   1044:        return tna_error;
                   1045:       case 0: break;
                   1046:       case 1:
                   1047:        action = walk(s->for_init);
                   1048:        if(action == tna_error) return action;
                   1049:        break;
                   1050:       case 2:
                   1051:        action = walk(s->else_stmt);
                   1052:        if(action == tna_error) return action;
                   1053:        break;
                   1054:       case 3:
                   1055:        action = walk(s->case_list);
                   1056:        if(action == tna_error) return action;
                   1057:        break;
                   1058:     }
                   1059: 
                   1060:     if(depth > 0 || !control.dont_chase_lists_top) {
                   1061:        action = walk(s->s_list);
                   1062:        if(action == tna_error) return action;
                   1063:     }
                   1064: 
                   1065:     return tna_continue;
                   1066: }
                   1067: 
                   1068: tree_node_action walker::a_ia(Pnode ta, struct ia * ia, Pnode& replacement) 
                   1069: {
                   1070:     tree_node_action action = pre_act_on_node(ta, nc_ia, Pnode(ia), replacement);
                   1071: 
                   1072:     if(action != tna_continue) return action;
                   1073: 
                   1074:     if(!fetching () && replacement)
                   1075:        ia = (struct ia *)&replacement;
                   1076: 
                   1077:     action = walk(ia->local);
                   1078:     if(action == tna_error) return action;
                   1079: 
                   1080:     action = walk(ia->arg);
                   1081:     if(action == tna_error) return action;
                   1082:     
                   1083:     action = walk(ia->tp);
                   1084:     if(action == tna_error) return action;
                   1085: 
                   1086:     return tna_continue;
                   1087: }
                   1088: 
                   1089: tree_node_action walker::a_iline(Pnode ta, Pin iline, Pnode& replacement) 
                   1090: {
                   1091:     tree_node_action action = pre_act_on_node(ta, nc_iline, Pnode(iline), replacement);
                   1092: 
                   1093:     if(action != tna_continue) return action;
                   1094: 
                   1095:     if(!fetching () && replacement)
                   1096:        iline = Pin(replacement);
                   1097: 
                   1098:     action = walk(iline->fct_name);
                   1099:     if(action == tna_error) return action;
                   1100: 
                   1101:     action = walk(iline->i_next);
                   1102:     if(action == tna_error) return action;
                   1103:     
                   1104:     action = walk(iline->i_table);
                   1105:     if(action == tna_error) return action;
                   1106: 
                   1107:     action = walk(iline->i_args);
                   1108:     if(action == tna_error) return action;
                   1109: 
                   1110:     return tna_continue;
                   1111: }
                   1112: 
                   1113: static char rcsinfo[] = "$Header: /usr3/lang/benson/work/stripped_cfront/RCS/tree_walk.c,v 1.1 89/11/20 08:51:06 benson Exp $";
                   1114: 
                   1115: 
                   1116: /*
                   1117:    $Log:       tree_walk.c,v $
                   1118:  * Revision 1.1  89/11/20  08:51:06  benson
                   1119:  * Initial revision
                   1120:  * 
                   1121:  * Revision 1.17  89/10/20  14:32:06  benson
                   1122:  * fixes to n_list processing and related items.
                   1123:  * 
                   1124:  * Revision 1.16  89/10/04  19:03:50  dysak
                   1125:  * Let the tree walker know about the n_persistent_db member of
                   1126:  * a name node.
                   1127:  * 
                   1128:  * Revision 1.15  89/10/02  09:58:33  benson
                   1129:  * finish the job.
                   1130:  * 
                   1131:  * Revision 1.14  89/10/02  09:44:30  benson
                   1132:  * use hash table subclass.
                   1133:  * 
                   1134:  * Revision 1.13  89/09/18  08:20:21  benson
                   1135:  * flush freeze drying support.
                   1136:  * 
                   1137:  * Revision 1.12  89/09/14  15:28:37  benson
                   1138:  * don't especially prune at the gtbl and ktbl. Leave it to client to
                   1139:  * do all pruning of this kind.
                   1140:  * 
                   1141:  * Revision 1.11  89/09/13  09:21:26  benson
                   1142:  * .10 also stops walking tables, ever. At least until we discover
                   1143:  * a use for it.
                   1144:  * 
                   1145:  * Revision 1.10  89/09/13  09:20:43  benson
                   1146:  * rename aggregate to collection.
                   1147:  * 
                   1148:  * Revision 1.9  89/09/02  22:07:13  benson
                   1149:  * keep things out of the hash table. Used for template formals.
                   1150:  * 
                   1151:  * Revision 1.8  89/08/29  13:41:05  benson
                   1152:  * don't walk n_tbl_list
                   1153:  * 
                   1154:  * Revision 1.7  89/08/24  08:44:52  benson
                   1155:  * support for an activation stack.  
                   1156:  * 
                   1157:  * Revision 1.5  89/08/11  14:59:55  sam
                   1158:  * 
                   1159:  * 
                   1160:  * Revision 1.4  89/07/27  13:32:28  benson
                   1161:  * walk through stmt.memtbl.
                   1162:  * 
                   1163:  * Revision 1.3  89/07/21  16:48:48  benson
                   1164:  * fixes and extensions for frozen trees, notably support for BY_NAME.
                   1165:  * 
                   1166:  * Revision 1.2  89/07/18  15:18:52  benson
                   1167:  * fix bugs.
                   1168:  * 
                   1169:  * Revision 1.1  89/07/14  10:55:49  benson
                   1170:  * Initial revision
                   1171:  * 
                   1172: 
                   1173:    end_log
                   1174: */

unix.superglobalmegacorp.com

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