|
|
1.1 root 1: #include <stdio.h>
2: #include "common.h"
3: #include "code.h"
4: #include "sym.h"
5: #include "machine.h"
6:
7: /*
8: * Routines to enumerate paths of a tree. Firt call path_setup to
9: * initialize the internal data structure. Each component of the
10: * path may be consecutively retrieved by calling path_getsym.
11: */
12:
13: /*
14: * For trees, a path is defined to be the sequence of nodes and edges
15: * from the root to a leaf. A path is represented here as a list of
16: * path components. Each component is represented by the following
17: * strucutre and may either be a pointer to a node or an integer.
18: * If the integer is i then the next component is the ith child of the
19: * previous component in the list. For example, "a 3 b 1 c" is a path
20: * for the tree "a(x,y,b(c,k))". The tag field indicates whether the
21: * component is a node or a branch.
22: * When the component represents a node then the node field points
23: * the corresponding Node structure. When the component is a branch then
24: * branch is the index of the current branch followed (1 is leftmost...)
25: * and node is a list of all unexamined children.
26: */
27: struct path {
28: int tag;
29: #define P_NODE 0
30: #define P_BRANCH 1
31: int branch;
32: Node *node;
33: };
34:
35: /*
36: * The path component list is stored in the path array. Path_length
37: * is the length of the path. Path_ptr points to the first unread
38: * component of the path component list. (see path_getsym
39: * and path_build for details)
40: */
41: struct path path[2*MAXPATH];
42: static int path_length;
43: static struct path *path_ptr = NULL;
44:
45: /*
46: * Given a tree, path_setup updates the path array with the leftmost
47: * of a subtree starting at root. The leftmost path is produced by
48: * following the leftmost branch of every encountered interior node
49: * starting at the root. Note that this routine can be used to layout
50: * the leftmost branch of a subtree into part of the path array and for
51: * initializing the path array with the leftmost path of the whole tree.
52: */
53: void
54: path_setup(root)
55: Node *root;
56: {
57: for(;;) {
58: register struct path *pp = &path[path_length++];
59: Node *ep;
60: assert (root!=NULL);
61:
62: /* Place node in the component list */
63: pp->tag = P_NODE;
64: pp->node = root;
65:
66: /* If leaf encountered exit */
67: if ((ep=root->children)==NULL)
68: break;
69:
70: /*
71: * Mark that the left branch (i.e. 1st in our numbering
72: * scheme) was followed.
73: */
74: pp = &path[path_length++];
75: pp->tag = P_BRANCH;
76: pp->branch = 1;
77: pp->node = ep->siblings;
78: root = ep;
79: }
80: path_ptr = path;
81: }
82:
83: /*
84: * Path_build generates the next path of the tree and returns 0 if
85: * there are no more paths. Each path can be associated
86: * with exactly one leaf. Hence the ordering of paths generated by
87: * this routine is the same as a left to right ordering of the leaves.
88: */
89: path_build()
90: {
91: Node *np, *ep;
92: struct path *pp = &path[path_length-1];
93:
94: /*
95: * Assert that the end of the last path was indeed
96: * a leaf.
97: */
98: assert (pp->tag == P_NODE);
99: assert ((pp->node)->children == NULL);
100:
101: /*
102: * back up until we find a node that still has children
103: */
104: pp--;
105: while (pp >= &path[1] && pp->node==NULL) pp -= 2;
106:
107: /*
108: * If we hit the beginning of the path array, there are
109: * no more leaves and hence no more paths.
110: */
111: if (pp < &path[1]) {
112: /* reset path_length */
113: path_length = 0;
114: return(0);
115: }
116:
117: /*
118: * append the new leftmost branch onto the rest of
119: * the path component list.
120: */
121: pp->branch++;
122: np = pp->node;
123: pp->node = np->siblings;
124: path_length = pp-path+1;
125: path_setup(np);
126: return(1);
127: }
128:
129: /*
130: * Get the next component in the path component list.
131: * When the end of a path is reached, NULL is returned and
132: * the next call will retrieve the first component of the next path.
133: * EOF is returned if there are no more paths.
134: * A return value of 1 indicates that the value returned in mi is
135: * valid.
136: */
137: int
138: path_getsym(mi)
139: register struct machine_input *mi;
140: {
141: if(path_ptr > &path[path_length]) {
142: /*
143: * When the end of that path is passed, generate the
144: * next path.
145: */
146: if(!path_build())
147: return(EOF);
148: path_ptr = path;
149: }
150: if (path_ptr == &path[path_length]) {
151: /*
152: * Path_ptr just encountered the end of
153: * the path, return a marker value
154: * to notify caller.
155: */
156: mi->value = 0;
157: path_ptr++;
158: return(NULL);
159: } else if (path_ptr->tag != P_BRANCH) {
160: /*
161: * Translate the right machine input value
162: */
163: mi->sym = (path_ptr->node)->sym;
164: switch((mi->sym)->attr) {
165:
166: case A_NODE:
167: mi->value = MV_NODE((mi->sym)->unique);
168: break;
169:
170: case A_LABEL:
171: mi->value = MV_LABEL((mi->sym)->unique);
172: break;
173:
174: default:
175: assert(0);
176: }
177: } else {
178: mi->value = MV_BRANCH(path_ptr->branch);
179: }
180: path_ptr++;
181: return(1);
182: }
183:
184: /*
185: * Prints out path for debugging
186: */
187: void
188: prpath()
189: {
190: register int i;
191: for(i=0; i < path_length; i++) {
192: struct path *pp = &path[i];
193: if (pp->tag==P_NODE) {
194: struct node *np = pp->node;
195: printf("[%s]", (np->sym)->name);
196: } else {
197: assert (pp->tag == P_BRANCH);
198: printf("%d", pp->branch);
199: }
200: }
201: putchar('\n');
202:
203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.