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