1 | /* |
---|
2 | node.c - Code to support building a linked version of an MP tree |
---|
3 | in the server. Label and Reference annotations are |
---|
4 | supported, but the Label must occur before the Reference. |
---|
5 | |
---|
6 | CHANGE LOG: |
---|
7 | May 21, 1995 - SG fixed m_get_node() to properly handle dummy |
---|
8 | nodes when a reference annotation is found. |
---|
9 | Also discovered that free_tree() will croak |
---|
10 | trying to access a shared substructure that |
---|
11 | was previously freed. |
---|
12 | May 27, 1995 - SG added routines to copy a node and its descendants, |
---|
13 | including annotations. This solves, for the time being, |
---|
14 | the problem of freeing memory for shared substructures. |
---|
15 | Whenever a reference annotation is found, we copy the |
---|
16 | shared substructure. The alternative is to do our own |
---|
17 | memory management, maintaining a reference count for each |
---|
18 | node, and allow multiple pointers to the same node. |
---|
19 | */ |
---|
20 | #include "MP.h" |
---|
21 | #include "gmp.h" |
---|
22 | #include "node.h" |
---|
23 | #include "label.h" |
---|
24 | |
---|
25 | /* |
---|
26 | We maintain a table a labels and a pointer to the root of the |
---|
27 | subtree to which the label refers. This TABLE is freed after |
---|
28 | processing each tree to ensure that we don't get labels |
---|
29 | confused across trees. The TABLE is a linear linked list of |
---|
30 | label entries. In the future we might want to make it a |
---|
31 | hashed table(?). |
---|
32 | */ |
---|
33 | static label_entry_t *TABLE = NULL; |
---|
34 | |
---|
35 | void process_label(); |
---|
36 | label_entry_t * find_label(); |
---|
37 | static void make_entry(); |
---|
38 | node_t *copy_node(); |
---|
39 | |
---|
40 | IMP_ApIntCopy(dest, src) |
---|
41 | MP_INT *dest; |
---|
42 | MP_INT *src; |
---|
43 | { |
---|
44 | int size; |
---|
45 | |
---|
46 | dest->_mp_alloc = src->_mp_alloc; |
---|
47 | dest->_mp_size = src->_mp_size; |
---|
48 | size = (src->_mp_size < 0) ? -1 * src->_mp_size : src->_mp_size; |
---|
49 | dest->_mp_d = (unsigned long *)malloc(sizeof(long) * size); |
---|
50 | bcopy((char *)src->_mp_d, (char *)dest->_mp_d, sizeof(long) * size); |
---|
51 | } |
---|
52 | |
---|
53 | IMP_ApRealCopy(dest, src) |
---|
54 | mpf_t dest; |
---|
55 | mpf_t src; |
---|
56 | { |
---|
57 | int size; |
---|
58 | |
---|
59 | dest->_mp_prec = src->_mp_prec; |
---|
60 | dest->_mp_size = src->_mp_size; |
---|
61 | dest->_mp_exp = src->_mp_exp; |
---|
62 | size = (src->_mp_size < 0) ? -1 * src->_mp_size : src->_mp_size; |
---|
63 | dest->_mp_d = (unsigned long *)malloc(sizeof(long) * size); |
---|
64 | bcopy((char *)src->_mp_d, (char *)dest->_mp_d, sizeof(long) * size); |
---|
65 | } |
---|
66 | |
---|
67 | annot_t *copy_annotation(original) |
---|
68 | annot_t *original; |
---|
69 | { |
---|
70 | annot_t *cpy = (annot_t *) malloc(sizeof(annot_t)); |
---|
71 | |
---|
72 | cpy->type = original->type; |
---|
73 | cpy->dtag = original->dtag; |
---|
74 | cpy->flags = original->flags; |
---|
75 | cpy->node = NULL; |
---|
76 | cpy->next = NULL; |
---|
77 | if (original->node != NULL) |
---|
78 | cpy->node = copy_node(original->node); |
---|
79 | if (original->next != NULL) |
---|
80 | cpy->next = copy_annotation(original->next); |
---|
81 | |
---|
82 | return cpy; |
---|
83 | } |
---|
84 | |
---|
85 | |
---|
86 | node_t* copy_node(original) |
---|
87 | node_t *original; |
---|
88 | { |
---|
89 | node_t **ochild, **child, *cpy = (node_t *) malloc(sizeof(node_t)); |
---|
90 | int i, datasize; |
---|
91 | |
---|
92 | cpy->annot_list = NULL; |
---|
93 | cpy->child_list = NULL; |
---|
94 | cpy->num_children = original->num_children; |
---|
95 | cpy->num_annots = original->num_annots; |
---|
96 | cpy->type = original->type; |
---|
97 | cpy->dtag = original->dtag; |
---|
98 | |
---|
99 | switch (cpy->type) { |
---|
100 | case MP_Sint8Type: |
---|
101 | case MP_Uint8Type: |
---|
102 | case MP_BooleanType: datasize = 1; break; |
---|
103 | case MP_Sint32Type: |
---|
104 | case MP_Uint32Type: |
---|
105 | case MP_Real32Type: datasize = 4; break; |
---|
106 | case MP_Real64Type: datasize = 8; break; |
---|
107 | case MP_IdentifierType: |
---|
108 | case MP_ConstantType: |
---|
109 | case MP_StringType: |
---|
110 | case MP_MetaType: |
---|
111 | case MP_OperatorType: datasize = strlen(original->data) + 1; |
---|
112 | break; |
---|
113 | case MP_RawType: datasize = original->num_children; break; |
---|
114 | case MP_CommonConstantType: |
---|
115 | case MP_CommonOperatorType: |
---|
116 | case MP_CommonLatinIdentifierType: |
---|
117 | case MP_CommonGreekIdentifierType: datasize = 1; break; |
---|
118 | case MP_ApIntType: datasize = sizeof(MP_INT); break; |
---|
119 | case MP_ApRealType: datasize = sizeof(__mpf_struct); |
---|
120 | default: |
---|
121 | fprintf(stderr,"copy_node: unknown type %d\n", cpy->type); |
---|
122 | free(cpy); |
---|
123 | return NULL; |
---|
124 | } |
---|
125 | cpy->data = (char *) malloc(datasize); |
---|
126 | if (cpy->type == MP_ApIntType) { |
---|
127 | mpz_init((MP_INT *)cpy->data); |
---|
128 | IMP_ApIntCopy(cpy->data, original->data); |
---|
129 | } |
---|
130 | else if (cpy->type == MP_ApRealType) { |
---|
131 | mpf_init((__mpf_struct *)cpy->data); |
---|
132 | IMP_ApRealCopy(cpy->data, original->data); |
---|
133 | } |
---|
134 | else bcopy(original->data, cpy->data, datasize); |
---|
135 | |
---|
136 | if ((original->num_children > 0) && (original->type != MP_RawType)) { |
---|
137 | cpy->child_list = (node_t **)malloc(cpy->num_children * sizeof(node_t *)); |
---|
138 | for (i = 0, child = cpy->child_list, ochild = original->child_list; |
---|
139 | i < cpy->num_children; i++, child++, ochild++) { |
---|
140 | *child = copy_node(*ochild); |
---|
141 | } |
---|
142 | } |
---|
143 | |
---|
144 | if (original->annot_list != NULL) |
---|
145 | cpy->annot_list = copy_annotation(original->annot_list); |
---|
146 | |
---|
147 | return cpy; |
---|
148 | } |
---|
149 | |
---|
150 | |
---|
151 | |
---|
152 | /****************************************************************** |
---|
153 | * FUNCTION: m_get_annot |
---|
154 | * ARGUMENT: link - pointer to a stream structure |
---|
155 | * RETURN: pointer to an annotation structure |
---|
156 | * PURPOSE: Retrieve a single annotation from the data stream |
---|
157 | * associated with link. If the annotation is valuated, |
---|
158 | * fetch the MP tree associated with the annotation. |
---|
159 | ******************************************************************/ |
---|
160 | annot_t * |
---|
161 | m_get_annot(link) |
---|
162 | MP_Link_t *link; |
---|
163 | { |
---|
164 | char *s = NULL; |
---|
165 | annot_t *anp = (annot_t *)malloc(sizeof(annot_t)); |
---|
166 | node_t *dnp; |
---|
167 | |
---|
168 | anp->type = anp->flags = 0; |
---|
169 | anp->node = NULL; |
---|
170 | anp->next = NULL; |
---|
171 | |
---|
172 | MP_GetAnnotationPacket(link, &(anp->dtag), &(anp->type), &(anp->flags)); |
---|
173 | if (anp->flags & MP_AnnotValuated) |
---|
174 | anp->node = m_get_node(link); |
---|
175 | |
---|
176 | return anp; |
---|
177 | } |
---|
178 | |
---|
179 | /****************************************************************** |
---|
180 | * FUNCTION: m_get_node |
---|
181 | * ARGUMENT: link - pointer to a stream structure |
---|
182 | * RETURN: pointer to a node structure |
---|
183 | * PURPOSE: Retrieve a node from the data stream associated with |
---|
184 | * link. If the node has annotations, fetch them. |
---|
185 | * Then if the node has children, fetch them too. |
---|
186 | * |
---|
187 | * This routine handles Label and Reference annotations. |
---|
188 | * Label annotations are placed in the label TABLE along |
---|
189 | * with a pointer to the labelled node. Finding a |
---|
190 | * Reference annotation causes a lookup in the label |
---|
191 | * TABLE. An error message is printed to stderr if |
---|
192 | * the Referenced label is not found in the TABLE and |
---|
193 | * the Referencing node is left unchanged. If the label |
---|
194 | * is found, the Referencing node is freed and a pointer |
---|
195 | * to the labelled node is returned in its place. |
---|
196 | * Further annotations of the Referencing node are read, |
---|
197 | * but ignored. It is assumed that the Referencing node |
---|
198 | * has no children. No check is made for this! |
---|
199 | ******************************************************************/ |
---|
200 | node_t * |
---|
201 | m_get_node(link) |
---|
202 | MP_Link_t *link; |
---|
203 | { |
---|
204 | MP_NodeType_t node_type = 0; |
---|
205 | MP_AnnotType_t annot_type = 0; |
---|
206 | MP_NumAnnot_t num_annots = 0; |
---|
207 | MP_NumChild_t num_child = 0; |
---|
208 | MP_NodeHeader_t hdr = 0; |
---|
209 | MP_Common_t cval = 0; |
---|
210 | MP_ApInt_t apint; |
---|
211 | MP_ApReal_t apreal; |
---|
212 | int i, more = 1, referenced_node = 0; |
---|
213 | node_t *dnp = (node_t *)malloc(sizeof(node_t)); |
---|
214 | annot_t *annotp; |
---|
215 | node_t **child, *ref_nodep = NULL; |
---|
216 | label_entry_t *labelp = NULL; |
---|
217 | char c, *cp; |
---|
218 | unsigned char uc; |
---|
219 | u_long ui; |
---|
220 | |
---|
221 | dnp->type = 0; |
---|
222 | dnp->data = NULL; |
---|
223 | dnp->dtag = 0; |
---|
224 | dnp->annot_list = NULL; |
---|
225 | dnp->child_list = NULL; |
---|
226 | dnp->num_children = dnp->num_annots = 0; |
---|
227 | |
---|
228 | IMP_GetNodeHeader(link, &(dnp->type), &(dnp->dtag), &cval, |
---|
229 | &(dnp->num_annots), &(dnp->num_children)); |
---|
230 | switch(dnp->type) { |
---|
231 | case MP_Sint32Type: |
---|
232 | dnp->data = (char *)malloc(sizeof(MP_Sint32_t)); |
---|
233 | IMP_GetSint32(link, (long*) dnp->data); |
---|
234 | break; |
---|
235 | case MP_Uint32Type: |
---|
236 | dnp->data = (char *)malloc(sizeof(MP_Uint32_t)); |
---|
237 | IMP_GetUint32(link, (unsigned long *)dnp->data); |
---|
238 | break; |
---|
239 | case MP_Sint8Type: |
---|
240 | dnp->data = (char *)malloc(sizeof(MP_Sint8_t)); |
---|
241 | *(dnp->data) = (MP_Sint8_t) cval; |
---|
242 | break; |
---|
243 | case MP_Uint8Type: |
---|
244 | dnp->data = (char *)malloc(sizeof(MP_Uint8_t)); |
---|
245 | *(dnp->data) = (MP_Uint8_t) cval; |
---|
246 | /* bcopy (&ui, dnp->data, 4);*/ |
---|
247 | break; |
---|
248 | case MP_BooleanType: |
---|
249 | dnp->data = (char *)malloc(sizeof(MP_Boolean_t)); |
---|
250 | *(dnp->data) = (MP_Boolean_t) cval; |
---|
251 | /* bcopy (&ui, dnp->data, 4);*/ |
---|
252 | break; |
---|
253 | case MP_Real32Type: |
---|
254 | dnp->data = (char *)malloc(sizeof(float)); |
---|
255 | IMP_GetReal32(link, (float *)dnp->data); |
---|
256 | break; |
---|
257 | case MP_Real64Type: |
---|
258 | dnp->data = (char *)malloc(sizeof(double)); |
---|
259 | IMP_GetReal64(link, (double *)dnp->data); |
---|
260 | break; |
---|
261 | case MP_IdentifierType: |
---|
262 | IMP_GetIdentifier(link, &(dnp->data)); |
---|
263 | break; |
---|
264 | case MP_CommonLatinIdentifierType: |
---|
265 | case MP_CommonGreekIdentifierType: |
---|
266 | case MP_CommonConstantType: |
---|
267 | case MP_CommonOperatorType: |
---|
268 | dnp->data = (char *)malloc(1); |
---|
269 | *(dnp->data) = cval; |
---|
270 | break; |
---|
271 | case MP_ConstantType: |
---|
272 | IMP_GetString(link, &(dnp->data)); |
---|
273 | break; |
---|
274 | case MP_StringType: |
---|
275 | IMP_GetString(link, &(dnp->data)); |
---|
276 | break; |
---|
277 | case MP_MetaType: |
---|
278 | IMP_GetMetaType(link, &(dnp->data)); |
---|
279 | break; |
---|
280 | case MP_RawType: |
---|
281 | IMP_GetRaw(link, &(dnp->data), &(dnp->num_children)); |
---|
282 | break; |
---|
283 | case MP_ApIntType: |
---|
284 | dnp->data = (char *)malloc(sizeof(__mpz_struct)); |
---|
285 | mpz_init((mpz_ptr)dnp->data); |
---|
286 | IMP_GetApInt(link, (MP_ApInt_t)&(dnp->data)); |
---|
287 | break; |
---|
288 | case MP_ApRealType: |
---|
289 | dnp->data = (char *)malloc(sizeof(__mpf_struct)); |
---|
290 | mpf_init((mpf_ptr)dnp->data); |
---|
291 | IMP_GetApReal(link, (MP_ApReal_t)&(dnp->data)); |
---|
292 | break; |
---|
293 | case MP_OperatorType: |
---|
294 | IMP_GetOperator(link, &(dnp->data)); |
---|
295 | break; |
---|
296 | default : fprintf(stderr, "server - m_get_node: unknown type %d\n", node_type); |
---|
297 | exit(1); |
---|
298 | } |
---|
299 | |
---|
300 | /* first we get the annotations, if there are any */ |
---|
301 | if (dnp->num_annots > 0) { |
---|
302 | annotp = dnp->annot_list = m_get_annot(link); |
---|
303 | /* look for Label and Reference annotations */ |
---|
304 | if (annotp->type == MP_AnnotMpLabel) |
---|
305 | process_label(annotp->node->data, dnp); |
---|
306 | else if (annotp->type == MP_AnnotMpRef) { |
---|
307 | if ((labelp = find_label(annotp->node->data)) != NULL) { |
---|
308 | referenced_node = MP_TRUE; |
---|
309 | ref_nodep= labelp->lnode; |
---|
310 | } |
---|
311 | else |
---|
312 | fprintf(stderr, "unknown label reference: %s\n", |
---|
313 | annotp->node->data); |
---|
314 | } |
---|
315 | for (i = 0; i < dnp->num_annots - 1; i++) { |
---|
316 | annotp->next = m_get_annot(link); |
---|
317 | annotp = annotp->next; |
---|
318 | if (annotp->type == MP_AnnotMpLabel) |
---|
319 | process_label(annotp->node->data, dnp); |
---|
320 | else if (annotp->type == MP_AnnotMpRef) { |
---|
321 | if ((labelp = find_label(annotp->node->data)) != NULL) { |
---|
322 | referenced_node = MP_TRUE; |
---|
323 | ref_nodep = labelp->lnode; |
---|
324 | } |
---|
325 | else |
---|
326 | fprintf(stderr, "unknown reference: %s\n", |
---|
327 | annotp->node->data); |
---|
328 | } |
---|
329 | } |
---|
330 | } |
---|
331 | |
---|
332 | /* For now assume that a node with a referenced label is */ |
---|
333 | /* a dummy node and that the child field is 0. We _don't_ */ |
---|
334 | /* check this. Return a pointer to the _labelled_ node. */ |
---|
335 | /* Also, we are abandoning all remaining annotations. */ |
---|
336 | /* What does the specification have to say about this? */ |
---|
337 | |
---|
338 | if (referenced_node == MP_TRUE) { |
---|
339 | free(dnp->data); free(dnp); |
---|
340 | return ref_nodep; |
---|
341 | } |
---|
342 | |
---|
343 | /* now get the children : do special check for raw type since */ |
---|
344 | /* we have a double use of the num_children field. */ |
---|
345 | if ((dnp->num_children > 0) && (dnp->type != MP_RawType)) { |
---|
346 | dnp->child_list = (node_t **)malloc(dnp->num_children * sizeof(node_t *)); |
---|
347 | for (i = 0,child = dnp->child_list; i < dnp->num_children; i++,child++) |
---|
348 | *child = m_get_node(link); |
---|
349 | } |
---|
350 | return dnp; |
---|
351 | } |
---|
352 | |
---|
353 | |
---|
354 | /****************************************************************** |
---|
355 | * FUNCTION: print_node |
---|
356 | * ARGUMENT: dnp - a pointer to the root of a subtree. |
---|
357 | * fd - file descriptor where we will print the tree. |
---|
358 | * RETURN: int indicating if there are more trees to retrieve. |
---|
359 | * This is indicated by the absence of the MP_QUIT node. |
---|
360 | * 1 = there are more trees to retrieve. |
---|
361 | * 0 = this is the MP_QUIT node, we are done. |
---|
362 | * PURPOSE: Print a node in the data stream. This includes any |
---|
363 | * annotations the node may have as well as its |
---|
364 | * children. The data is sent to standard out and to |
---|
365 | * the file associated with file descriptor fd. |
---|
366 | ******************************************************************/ |
---|
367 | int |
---|
368 | print_node(dnp, fd) |
---|
369 | node_t *dnp; |
---|
370 | FILE *fd; |
---|
371 | { |
---|
372 | char *str = NULL, c; |
---|
373 | node_t **p; |
---|
374 | MP_INT apint; |
---|
375 | short flags; |
---|
376 | int i, j, more = 1; |
---|
377 | MP_Uint8_t t; |
---|
378 | |
---|
379 | switch(dnp->type){ |
---|
380 | case MP_Sint32Type: |
---|
381 | printf("%-20s %-30d %d\n", "MP_Sint32" , |
---|
382 | (long) *((long *)dnp->data), dnp->num_annots); |
---|
383 | fprintf(fd,"MP_Sint32Type %d %d\n", |
---|
384 | (long) *((long *)dnp->data), dnp->num_annots); |
---|
385 | break; |
---|
386 | case MP_Uint32Type: |
---|
387 | printf("%-20s %-30u %d\n", "MP_Uint32", |
---|
388 | (long) *((long *)dnp->data), dnp->num_annots); |
---|
389 | fprintf(fd, "MP_Uint32Type %d %u\n", |
---|
390 | (long) *((long *)dnp->data), dnp->num_annots); |
---|
391 | break; |
---|
392 | case MP_Sint8Type: |
---|
393 | printf("%-20s %-30d %d\n", "MP_Sint8", |
---|
394 | *(dnp->data), dnp->num_annots); |
---|
395 | fprintf(fd,"MP_Sint8Type %d %u\n", *(dnp->data) ,dnp->num_annots); |
---|
396 | break; |
---|
397 | case MP_Uint8Type: |
---|
398 | t = (MP_Uint8_t)*((MP_Uint8_t *)dnp->data); |
---|
399 | printf("%-20s %-30d %d\n", "MP_Uint8", t, dnp->num_annots); |
---|
400 | fprintf(fd,"MP_Uint8Type %u %u\n", t, dnp->num_annots); |
---|
401 | break; |
---|
402 | case MP_BooleanType: |
---|
403 | c = (*((MP_Boolean_t *)dnp->data) == 1) ? 'T' : 'F'; |
---|
404 | printf("%-20s %-30c %d\n", "MP_Boolean", c, dnp->num_annots); |
---|
405 | fprintf(fd,"MP_BooleanType %c %d\n", c, dnp->num_annots); |
---|
406 | break; |
---|
407 | case MP_Real32Type: |
---|
408 | printf("%-20s %-30.10G %d\n", "MP_Real32", |
---|
409 | (float) *((float *)dnp->data), dnp->num_annots); |
---|
410 | fprintf(fd, "MP_Real32Type %d %20.10G\n", |
---|
411 | (float) *((float *)dnp->data), dnp->num_annots); |
---|
412 | break; |
---|
413 | case MP_Real64Type: |
---|
414 | printf("%-20s %-30.15lG %d\n", "MP_Real64", |
---|
415 | (double) *((double *)dnp->data), dnp->num_annots); |
---|
416 | fprintf(fd, "MP_Real64Type %d %20.15lG\n", |
---|
417 | (double) *((double *)dnp->data), dnp->num_annots); |
---|
418 | break; |
---|
419 | case MP_CommonLatinIdentifierType: |
---|
420 | printf("%-20s %-5d %-30c %-7d\n", "MP_LatinIdentifier", |
---|
421 | dnp->dtag, *(dnp->data), dnp->num_annots); |
---|
422 | fprintf(fd, "MP_CommonLatinIdentifierType %d %c %d\n", |
---|
423 | dnp->dtag, *(dnp->data), dnp->num_annots); |
---|
424 | break; |
---|
425 | case MP_CommonGreekIdentifierType: |
---|
426 | printf("%-20s %-5d %-30c %-7d\n", "MP_GreekIdentifier", |
---|
427 | dnp->dtag, *(dnp->data), dnp->num_annots); |
---|
428 | fprintf(fd, "MP_CommonGreekIdentifierType %d %c %d\n", |
---|
429 | dnp->dtag, *(dnp->data), dnp->num_annots); |
---|
430 | break; |
---|
431 | case MP_IdentifierType: |
---|
432 | printf("%-20s %-5d %-30s %-7d\n", "MP_Identifier", |
---|
433 | dnp->dtag, dnp->data, dnp->num_annots); |
---|
434 | fprintf(fd, "MP_IdentifierType %d %s %d\n", |
---|
435 | dnp->dtag, dnp->data, dnp->num_annots); |
---|
436 | break; |
---|
437 | case MP_ConstantType: |
---|
438 | printf("%-20s %-5d %-30s %-7d\n", "MP_Constant", |
---|
439 | dnp->dtag, dnp->data, dnp->num_annots); |
---|
440 | fprintf(fd, "MP_ConstantType %d %s %d\n", |
---|
441 | dnp->dtag, dnp->data, dnp->num_annots); |
---|
442 | break; |
---|
443 | case MP_CommonConstantType: |
---|
444 | printf("%-20s %-5d %-30d %-7d\n", "MP_CommonCnst", |
---|
445 | dnp->dtag, *((MP_Common_t *)dnp->data), dnp->num_annots); |
---|
446 | fprintf(fd, "MP_CommonConstantType %d %d %d\n", |
---|
447 | dnp->dtag, *((MP_Common_t *)dnp->data), dnp->num_annots); |
---|
448 | break; |
---|
449 | case MP_StringType: |
---|
450 | printf("%-20s %-20s %d\n", "MP_String", |
---|
451 | dnp->data, dnp->num_annots); |
---|
452 | fprintf(fd, "MP_StringType %s %d\n", |
---|
453 | dnp->data, dnp->num_annots); |
---|
454 | break; |
---|
455 | case MP_MetaType: |
---|
456 | printf("%-20s %-5d %-30s %-7d\n", "MP_Meta", |
---|
457 | dnp->dtag, dnp->data, dnp->num_annots); |
---|
458 | fprintf(fd, "MP_MetaType %d %s %d\n", |
---|
459 | dnp->dtag, dnp->data, dnp->num_annots); |
---|
460 | break; |
---|
461 | case MP_RawType: |
---|
462 | str = malloc(dnp->num_children + 1); |
---|
463 | memcpy(str, dnp->data, dnp->num_children); |
---|
464 | str[dnp->num_children] = '\0'; /* make the output nice */ |
---|
465 | printf("%-20s %-30s %d\n", "MP_Raw", str, dnp->num_annots); |
---|
466 | fprintf(fd, "MP_RawType %s %d\n", str, dnp->num_annots); |
---|
467 | free(str); |
---|
468 | break; |
---|
469 | case MP_ApIntType: |
---|
470 | printf("%-20s ", "MP_ApInt"); |
---|
471 | fprintf(fd, "MP_ApIntType "); |
---|
472 | printf(" %d\n", dnp->num_annots); |
---|
473 | fprintf(fd, " %d\n", dnp->num_annots); |
---|
474 | mpz_out_str(stdout,10, (mpz_ptr) dnp->data); |
---|
475 | mpz_out_str(fd, 10, (mpz_ptr) dnp->data); |
---|
476 | printf(" %d\n", dnp->num_annots); |
---|
477 | fprintf(fd, " %d\n", dnp->num_annots); |
---|
478 | fflush(stdout);fflush(fd); |
---|
479 | break; |
---|
480 | case MP_ApRealType: |
---|
481 | printf("%-20s ", "MP_ApReal"); |
---|
482 | fprintf(fd, "MP_ApRealType "); |
---|
483 | mpf_out_str(stdout, 10, 0, (mpf_ptr) dnp->data); |
---|
484 | mpf_out_str(fd, 10, 0, (mpf_ptr) dnp->data); |
---|
485 | printf(" %d\n",dnp->num_annots); |
---|
486 | fprintf(fd, " %d\n", dnp->num_annots); |
---|
487 | fflush(stdout);fflush(fd); |
---|
488 | break; |
---|
489 | case MP_OperatorType: |
---|
490 | printf("%-20s %-5d %-30s %-7d %-9d\n", "MP_Op", |
---|
491 | dnp->dtag, dnp->data, dnp->num_annots, dnp->num_children); |
---|
492 | fprintf(fd, "MP_OperatorType %d %s %d %d\n", |
---|
493 | dnp->dtag, dnp->data, dnp->num_annots, dnp->num_children); |
---|
494 | break; |
---|
495 | case MP_CommonOperatorType: |
---|
496 | printf(" %-20s %-5d %-30d %-7d% -5d\n", "MP_CommonOp", |
---|
497 | dnp->dtag, *((MP_Common_t *)dnp->data), dnp->num_annots, |
---|
498 | dnp->num_children); |
---|
499 | fprintf(fd, "MP_CommonOperatorType %d %d %d %d\n", |
---|
500 | dnp->dtag, *((MP_Common_t *)dnp->data), dnp->num_annots, |
---|
501 | dnp->num_children); |
---|
502 | if (!(more = !(dnp->dtag == MP_MpDict && |
---|
503 | *((MP_Common_t *)dnp->data) == MP_CopMpEndSession))) |
---|
504 | return 0; |
---|
505 | break; |
---|
506 | default : fprintf(stderr, "server: unknown type %d\n", dnp->type); |
---|
507 | } |
---|
508 | if (dnp->annot_list != NULL) print_annot(dnp->annot_list, fd); |
---|
509 | |
---|
510 | if ((dnp->num_children > 0) && (dnp->type != MP_RawType)) { |
---|
511 | p = dnp->child_list; |
---|
512 | for (i = 0; i < dnp->num_children; i++, p++){ |
---|
513 | print_node(*p, fd); |
---|
514 | } |
---|
515 | } |
---|
516 | return more; |
---|
517 | } |
---|
518 | |
---|
519 | |
---|
520 | /****************************************************************** |
---|
521 | * FUNCTION: print_annot |
---|
522 | * ARGUMENT: anp - a pointer to an annotation structure. |
---|
523 | * fd - file descriptor where we will print the tree. |
---|
524 | * RETURN: none. |
---|
525 | * PURPOSE: Print an annotation node to standard output and to |
---|
526 | * the file associated with file descriptor fd. This |
---|
527 | * includes any arguments the annotation has (if it |
---|
528 | * is valuated). The next annotation in the list, if |
---|
529 | * it exists, is recursively printed. |
---|
530 | ******************************************************************/ |
---|
531 | void |
---|
532 | print_annot(anp, fd) |
---|
533 | annot_t *anp; |
---|
534 | FILE *fd; |
---|
535 | { char *annotstr = NULL; |
---|
536 | |
---|
537 | annotstr = (char *) annot_to_str(anp->dtag, anp->type); |
---|
538 | printf("%-20s %-5d flags: 0x%X\n", annotstr, anp->dtag, |
---|
539 | anp->flags); |
---|
540 | fprintf(fd,"%s %d %X\n", annotstr, anp->dtag, anp->flags); |
---|
541 | if (anp->node != NULL) |
---|
542 | print_node(anp->node, fd); |
---|
543 | if (anp->next != NULL) print_annot(anp->next, fd); |
---|
544 | } |
---|
545 | |
---|
546 | |
---|
547 | /****************************************************************** |
---|
548 | * FUNCTION: find_label |
---|
549 | * ARGUMENT: label - a char string containing the label. |
---|
550 | * RETURN: Success - a pointer to the entry in the label TABLE |
---|
551 | * containing label. |
---|
552 | * Failure - NULL. |
---|
553 | * PURPOSE: Look for label among the collection of label entries |
---|
554 | * maintained by TABLE. This TABLE is cleaned out (freed) |
---|
555 | * after each tree is processed. |
---|
556 | ******************************************************************/ |
---|
557 | label_entry_t * |
---|
558 | find_label(label) |
---|
559 | char *label; |
---|
560 | { |
---|
561 | label_entry_t *cp, *p = TABLE; |
---|
562 | |
---|
563 | while (p != NULL) { |
---|
564 | if (strcmp(p->label, label) == 0) break; |
---|
565 | p = p->next; |
---|
566 | } |
---|
567 | if (p != NULL) { |
---|
568 | cp = (label_entry_t *) malloc(sizeof(label_entry_t)); |
---|
569 | cp->lnode = copy_node(p->lnode); |
---|
570 | return cp; |
---|
571 | } |
---|
572 | else return p; |
---|
573 | } |
---|
574 | |
---|
575 | |
---|
576 | node_t * |
---|
577 | process_ref(label, node) |
---|
578 | char *label; |
---|
579 | node_t **node; |
---|
580 | { |
---|
581 | ref_node_t *r; |
---|
582 | label_entry_t *p; |
---|
583 | |
---|
584 | if ((p = find_label(label)) == NULL) { |
---|
585 | /* p = make_entry(label, *node); */ |
---|
586 | r = (ref_node_t *)malloc (sizeof(ref_node_t)); |
---|
587 | r->next = p->ref_list; |
---|
588 | p->ref_list = r; |
---|
589 | } |
---|
590 | return (p->lnode); |
---|
591 | } |
---|
592 | |
---|
593 | |
---|
594 | |
---|
595 | /****************************************************************** |
---|
596 | * FUNCTION: process_label |
---|
597 | * ARGUMENT: label - a char string containing the label. |
---|
598 | * node - a pointer to the node structure associated |
---|
599 | * with this label. |
---|
600 | * RETURN: None. |
---|
601 | * PURPOSE: Determine if the label is already in the label TABLE. |
---|
602 | * If yes, print an error announcing the duplicate and |
---|
603 | * return (don't do anything else). |
---|
604 | * If no, place the label in the TABLE and associated |
---|
605 | * node with it. |
---|
606 | * |
---|
607 | * COMMENT: Consider having the routine return an error value |
---|
608 | * to identify duplicate labels so the caller can |
---|
609 | * decide what should be done. |
---|
610 | ******************************************************************/ |
---|
611 | void |
---|
612 | process_label(label, node) |
---|
613 | char *label; |
---|
614 | node_t *node; |
---|
615 | { |
---|
616 | label_entry_t *p; |
---|
617 | |
---|
618 | if ((p = find_label(label)) != NULL) /* check for a duplicate */ |
---|
619 | fprintf(stderr,"duplicate label found: %s\n", label); |
---|
620 | else /* not a duplicate, so put it in the table */ |
---|
621 | make_entry(label, node); |
---|
622 | |
---|
623 | } |
---|
624 | |
---|
625 | |
---|
626 | /****************************************************************** |
---|
627 | * FUNCTION: make_entry |
---|
628 | * ARGUMENT: label - a char string containing the label. |
---|
629 | * node - a pointer to the node structure associated |
---|
630 | * with this label. |
---|
631 | * RETURN: None. |
---|
632 | * PURPOSE: Make an entry in TABLE for the (label, node) pair. |
---|
633 | * It is assumed at this point that label is not |
---|
634 | * already in the TABLE. |
---|
635 | ******************************************************************/ |
---|
636 | static void |
---|
637 | make_entry (label, node) |
---|
638 | char *label; |
---|
639 | node_t *node; |
---|
640 | { |
---|
641 | label_entry_t *p = (label_entry_t *)malloc(sizeof(label_entry_t)); |
---|
642 | |
---|
643 | p->label = (char *)malloc(strlen(label) + 1); |
---|
644 | strcpy(p->label, label); |
---|
645 | p->ref_list = NULL; |
---|
646 | p->lnode = node; |
---|
647 | p->next = TABLE; |
---|
648 | TABLE = p; |
---|
649 | } |
---|
650 | |
---|
651 | |
---|
652 | /****************************************************************** |
---|
653 | * FUNCTION: free_annotation |
---|
654 | * ARGUMENT: annotp - a pointer to an annotation structure. |
---|
655 | * RETURN: None. |
---|
656 | * PURPOSE: Free the memory allocated to the annotation structure. |
---|
657 | * If the annotation is valuated, free its argument first. |
---|
658 | ******************************************************************/ |
---|
659 | static void |
---|
660 | free_annotation(annotp) |
---|
661 | annot_t *annotp; |
---|
662 | { |
---|
663 | if (annotp->node != NULL) free_tree(annotp->node); |
---|
664 | free(annotp); |
---|
665 | } |
---|
666 | |
---|
667 | |
---|
668 | /****************************************************************** |
---|
669 | * FUNCTION: free_tree |
---|
670 | * ARGUMENT: dnp - a pointer to a node structure. |
---|
671 | * RETURN: None. |
---|
672 | * PURPOSE: Free up the memory of the nodes and annotations |
---|
673 | * rooted at the subtree pointed to by dnp. |
---|
674 | ******************************************************************/ |
---|
675 | void |
---|
676 | free_tree(dnp) |
---|
677 | node_t *dnp; |
---|
678 | { |
---|
679 | annot_t *annotp, *next_annotp; |
---|
680 | node_t **childp; |
---|
681 | int i; |
---|
682 | |
---|
683 | /* first we free the annotations */ |
---|
684 | for (i = 0, annotp = dnp->annot_list; i < dnp->num_annots; i++) { |
---|
685 | next_annotp = annotp->next; |
---|
686 | free_annotation(annotp); |
---|
687 | annotp = next_annotp; |
---|
688 | } |
---|
689 | |
---|
690 | /* free the children, if there are any */ |
---|
691 | if ((dnp->num_children > 0) && (dnp->type != MP_RawType)) |
---|
692 | for (i = 0, childp = dnp->child_list; i < dnp->num_children; i++, childp++) |
---|
693 | free_tree(*childp); |
---|
694 | |
---|
695 | if (dnp->type == MP_ApIntType) mpz_clear((MP_INT *)dnp->data); |
---|
696 | else free(dnp->data); |
---|
697 | |
---|
698 | /* now free the pointers to the children and the node itself */ |
---|
699 | free(dnp->child_list); |
---|
700 | free(dnp); |
---|
701 | |
---|
702 | } |
---|
703 | |
---|
704 | /****************************************************************** |
---|
705 | * FUNCTION: free_label_table |
---|
706 | * ARGUMENT: None. TABLE is accessed globally. |
---|
707 | * RETURN: None. |
---|
708 | * PURPOSE: Free up the memory of the label entries pointed |
---|
709 | * to by TABLE. Set TABLE to NULL on exit. |
---|
710 | ******************************************************************/ |
---|
711 | void |
---|
712 | free_label_table() |
---|
713 | { |
---|
714 | label_entry_t *lp = TABLE, *nlp; |
---|
715 | |
---|
716 | while (lp != NULL) { |
---|
717 | nlp = lp->next; |
---|
718 | free(lp->label); |
---|
719 | free(lp); |
---|
720 | lp = nlp; |
---|
721 | } |
---|
722 | TABLE = NULL; |
---|
723 | } |
---|
724 | |
---|
725 | /* |
---|
726 | static void |
---|
727 | fix_refs(node, ref_list) |
---|
728 | node_t *node; |
---|
729 | ref_node_t **ref_list; |
---|
730 | { |
---|
731 | ref_node_t *p = *ref_list; |
---|
732 | |
---|
733 | while (p != NULL) { |
---|
734 | *(p->node) = node; |
---|
735 | p = p->next; |
---|
736 | free(*ref_list); |
---|
737 | *ref_list = p; |
---|
738 | } |
---|
739 | } |
---|
740 | */ |
---|