Pristine Ack-5.5
[Ack-5.5.git] / util / grind / scope.cc
1 /* $Id: scope.cc,v 1.4 1994/06/24 11:01:09 ceriel Exp $ */
2
3 /* Scope mechanism */
4
5 #include        <assert.h>
6 #include        <alloc.h>
7 #include        <out.h>
8
9 #include        "position.h"
10 #include        "file.h"
11 #include        "idf.h"
12 #include        "type.h"
13 #include        "symbol.h"
14 #include        "scope.h"
15 #include        "avl.h"
16
17 p_scope PervasiveScope, CurrentScope, FileScope;
18
19 /* STATICALLOCDEF "scope" 10 */
20
21 static AVL_tree ScopeTree;
22
23 static int
24 cmp_starts(s1, s2)
25   char  *s1, *s2;
26 {
27   register p_scope c1 = (p_scope)s1, c2 = (p_scope)s2;
28
29   return c1->sc_start < c2->sc_start
30          ? -1
31          : c1->sc_start == c2->sc_start
32            ? 0
33            : 1;
34 }
35
36 /*ARGSUSED*/
37 open_scope(name, has_activation)
38   p_symbol name;
39   int has_activation;
40 {
41   register p_scope sc = new_scope();
42
43   sc->sc_has_activation_record = has_activation;
44   sc->sc_static_encl = CurrentScope;
45   sc->sc_definedby = name;
46   sc->sc_proclevel = CurrentScope->sc_proclevel;
47                         /* sc_proclevel possibly reset by caller */
48   CurrentScope = sc;
49 }
50
51 init_scope()
52 {
53   register p_scope sc = new_scope();
54
55   PervasiveScope = sc;
56   CurrentScope = sc;
57   open_scope((p_symbol) 0, 0);          /* this one will be closed at the
58                                            first N_SO
59                                         */
60   ScopeTree = create_avl_tree(cmp_starts);
61 }
62
63 close_scope()
64 {
65   register p_scope sc = CurrentScope;
66
67   assert(sc != 0);
68   CurrentScope = sc->sc_static_encl;
69 }
70
71 add_scope_addr(scope)
72   p_scope       scope;
73 {
74   add_to_avl_tree(ScopeTree, (char *)scope);
75 }
76
77 /* extern p_scope       get_scope_from_addr(t_addr a);
78    Returns the scope of the code at address 'a', or 0 if it could not be found.
79 */
80 p_scope
81 get_scope_from_addr(a)
82   t_addr a;
83 {
84   t_scope sc;
85
86   sc.sc_start = a;
87   return (p_scope) find_ngt(ScopeTree, (char *) &sc);
88 }
89
90 /* extern p_scope       get_next_scope_from_addr(t_addr a);
91    Returns the scope following the one of the code at address 'a',
92    and that has an activation record,
93    or 0 if it could not be found.
94 */
95 p_scope
96 get_next_scope_from_addr(a)
97   t_addr a;
98 {
99   t_scope sc;
100
101   sc.sc_start = a;
102   for (;;) {
103         p_scope psc = (p_scope) find_nlt(ScopeTree, (char *) &sc);
104         if (! psc || psc->sc_has_activation_record) return psc;
105         sc.sc_start = psc->sc_start+1;
106   }
107   /*NOTREACHED*/
108 }
109
110 /* extern int   has_static_link(p_scope sc);
111    Returns 1 if the procedure of this scope takes a static link.
112 */
113 int
114 has_static_link(sc)
115   register p_scope      sc;
116 {
117   return sc->sc_proclevel > 1;
118 }
119
120 /* extern p_scope       base_scope(p_scope sc);
121    Returns the closest enclosing scope of 'sc' that has an activation record.
122 */
123 p_scope
124 base_scope(sc)
125   register p_scope      sc;
126 {
127   while (sc && ! sc->sc_has_activation_record) {
128         sc = sc->sc_static_encl;
129   }
130   return sc;
131 }
132
133 /* extern int   scope_encloses(p_scope scope, from_scope);
134    Returns 1 if scope encloses from from_scope, 0 otherwise.
135 */
136 int
137 scope_encloses(scope, from_scope)
138   p_scope       scope, from_scope;
139 {
140   register p_scope sc = from_scope;
141
142   while (sc) {
143         if (sc == scope) return 1;
144         sc = sc->sc_static_encl;
145   }
146   return 0;
147 }