]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/compiler/core/dependency.c
Security-54.tar.gz
[apple/security.git] / SecuritySNACCRuntime / compiler / core / dependency.c
1 /*
2 * compiler/core/dependency.c - sorts types/values in order of dependency.
3 * typeDefs list is re-ordered
4 * going from independent->dependent types
5 *
6 * this is done after all import linking is done
7 *
8 * Mike Sample
9 * 91/08/12
10 * Copyright (C) 1991, 1992 Michael Sample
11 * and the University of British Columbia
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/compiler/core/dependency.c,v 1.1 2001/06/20 21:27:56 dmitch Exp $
19 * $Log: dependency.c,v $
20 * Revision 1.1 2001/06/20 21:27:56 dmitch
21 * Adding missing snacc compiler files.
22 *
23 * Revision 1.1.1.1 1999/03/16 18:06:46 aram
24 * Originals from SMIME Free Library.
25 *
26 * Revision 1.4 1995/07/25 19:41:22 rj
27 * changed `_' to `-' in file names.
28 *
29 * Revision 1.3 1994/10/08 03:48:37 rj
30 * since i was still irritated by cpp standing for c++ and not the C preprocessor, i renamed them to cxx (which is one known suffix for C++ source files). since the standard #define is __cplusplus, cplusplus would have been the more obvious choice, but it is a little too long.
31 *
32 * Revision 1.2 1994/09/01 00:31:56 rj
33 * snacc_config.h removed; dependency.h includet.
34 *
35 * Revision 1.1 1994/08/28 09:49:00 rj
36 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
37 *
38 */
39
40 #include <stdio.h>
41
42 #include "asn-incl.h"
43 #include "mem.h"
44 #include "asn1module.h"
45 #include "snacc-util.h"
46 #include "dependency.h"
47
48
49 /* prototypes */
50
51 void SortTypeDependencies PROTO ((Module *m));
52
53 void SortInterModuleDependencies PROTO ((ModuleList *m));
54
55 TypeDefList *RemoveAndSortIndependents PROTO ((TypeDefList *tdl));
56
57 void SortTypeDefs PROTO ((TypeDefList *tdl));
58
59 void BuildLocalRefList PROTO ((Type *t, TypeDefList *refList));
60
61 void BuildWeightedLocalRefList PROTO ((Type *t, TypeDefList *refList));
62
63
64 long int GetElmtIndex PROTO ((TypeDef *td, TypeDefList *tdl));
65
66 /*
67 void MoveAfter PROTO ((unsigned long int currIndex, unsigned long int afterIndex, AsnList *l));
68 */
69
70 /*
71 * Sorts type dependencies by reodering TypeDefs linear list
72 * with least dependent types followed by dependent types
73 */
74 void
75 SortAllDependencies PARAMS ((modList),
76 ModuleList *modList)
77 {
78 Module *m;
79
80 FOR_EACH_LIST_ELMT (m, modList)
81 {
82 SortTypeDependencies (m);
83 }
84
85 /* SortInterModuleDependencies (modList); */
86
87 } /* SortAllDependencies */
88
89
90 /*
91 * This attempts to sort the types in order of dependency
92 * (least dependent --> dependent)
93 *
94 * This should only be called after the CTypeInfo or CxxTypeInfo
95 * has been added to the types.
96 * (the isPtr field is used to help determine ordering)
97 *
98 * Algorithm: (wierd!)
99 *
100 * First separte the ASN.1 type defs into 4 separate groups
101 *
102 * 1. Type defs that are defined directly from primitive/library types
103 * eg Foo ::= INTEGER {one (1), two (2) }
104 *
105 * 2. Type defs reference no local types in a way that needs a
106 * forward decl. of the ref'd type (ie ptr refs)
107 *
108 * 3. Type defs that reference local types in a way that needs
109 * a previous decl of the ref'd type (ie non ptr refs for SET/SEQ
110 * elmts)
111 *
112 * 4. Type defs that are not referenced by any local types
113 * (hence no local types depend on them so they can go last)
114 *
115 *
116 * The type defs in group 3 are further sorted by the SortTypeDefs routine
117 *
118 * Then all of the groups are merged in the order 1-2-3-4.
119 *
120 * Some wierd recursive types might cause problems...
121 *
122 *
123 * MS 92
124 */
125 void
126 SortTypeDependencies PARAMS ((m),
127 Module *m)
128 {
129 TypeDef *curr;
130 TypeDefList *prims;
131 TypeDefList *noRefs;
132 TypeDefList *refs;
133 TypeDefList *notRefd;
134 TypeDef **newElmtHndl;
135
136 prims = AsnListNew (sizeof (void*));
137 noRefs = AsnListNew (sizeof (void*));
138 refs = AsnListNew (sizeof (void*));
139 notRefd = AsnListNew (sizeof (void*));
140
141 /* put each TypeDef in the appropriate list (1-4)*/
142 FOR_EACH_LIST_ELMT (curr, m->typeDefs)
143 {
144 if (IsDefinedByLibraryType (curr->type))
145 newElmtHndl = (TypeDef**) AsnListAppend (prims);
146
147 else if (curr->localRefCount == 0)
148 newElmtHndl = (TypeDef**) AsnListAppend (notRefd);
149
150 else
151 {
152 /* get list of local types that this type def refs */
153 curr->refList = AsnListNew (sizeof (void*));
154 BuildLocalRefList (curr->type, curr->refList);
155
156 if (LIST_EMPTY (curr->refList))
157 {
158 newElmtHndl = (TypeDef**) AsnListAppend (noRefs);
159 Free (curr->refList);
160 curr->refList = NULL;
161 }
162 else
163 newElmtHndl = (TypeDef**) AsnListAppend (refs);
164 }
165
166 *newElmtHndl = curr;
167 }
168
169 /* sort problem types */
170 SortTypeDefs (refs);
171
172 /* free refList space */
173 FOR_EACH_LIST_ELMT (curr, refs)
174 {
175 if (curr->refList != NULL)
176 {
177 AsnListFree (curr->refList);
178 curr->refList = NULL;
179 }
180 }
181
182 /*
183 * combine the typdef lists with the prims followed by the
184 * types that don't reference other types
185 * then prims, followed by composite types
186 */
187 prims = AsnListConcat (prims, noRefs);
188 prims = AsnListConcat (prims, refs);
189 prims = AsnListConcat (prims, notRefd);
190
191 AsnListFree (m->typeDefs);
192 Free (noRefs);
193 Free (refs);
194 Free (notRefd);
195
196 m->typeDefs = prims;
197
198 } /* SortTypeDependencies */
199
200
201
202
203 /*
204 * Attempt to sort modules in order of "depends on none" to
205 * "depends on all" where a dependency is caused by importing
206 * from another module.
207 * cyclic dependencies are a pain
208 */
209 /*
210 * Not implemented yet... perhaps best left in user's hands
211 * ie set it by the cmd line order
212 */
213 /*
214 void
215 SortInterModuleDependencies PARAMS ((m),
216 ModuleList *m)
217 {
218
219 } SortInterModuleDependencies */
220
221
222
223 /*
224 * Given a non-empty TypeDef list, the refLists of TypeDefs
225 * are used to divide the list into two lists, one list
226 * that is sorted the order of dependency (independed-->dependent)
227 * and the other list contains types that are mutually dependent
228 * (recursive or depend on recursive types)
229 * The sorted list is returned and the passed in list has those
230 * TypeDefs that are now in the sorted list removed.
231 */
232 TypeDefList*
233 RemoveAndSortIndependents PARAMS ((tdl),
234 TypeDefList *tdl)
235 {
236 TypeDef *last;
237 TypeDef *currTd;
238 TypeDef **tdHndl;
239 TypeDef *tdRef;
240 AsnListNode *nextListNode;
241 long int tdIndex;
242 long int lastSLCount;
243 TypeDefList *subList;
244 int keep;
245
246 /*
247 * iterate through the list making sub lists that don't depend
248 * on the others in the active list. Join sub lists in order
249 * and then deal with the active list if any
250 */
251 lastSLCount = -1; /* just to start */
252 subList = AsnListNew (sizeof (void*));
253
254 if (LIST_EMPTY (tdl))
255 return subList;
256
257 /* iterate through each type def in the tdl */
258 while ((LIST_COUNT (subList) > lastSLCount) && !LIST_EMPTY (tdl))
259 {
260 lastSLCount = LIST_COUNT (subList);
261 last = (TypeDef*)LAST_LIST_ELMT (tdl);
262 SET_CURR_LIST_NODE (tdl, FIRST_LIST_NODE (tdl));
263 currTd = (TypeDef*)CURR_LIST_ELMT (tdl);
264 while (1)
265 {
266 nextListNode = NEXT_LIST_NODE (tdl);
267 keep = 0;
268
269 /*
270 * iterate through this type def's local type refs.
271 *
272 * if any type def in the current type's local type ref list
273 * is in the tdl, then teh current type must remain in the tdl
274 * because it depends on that type.
275 */
276 FOR_EACH_LIST_ELMT (tdRef, currTd->refList)
277 {
278 /* don't worry about recursive refs to self */
279 if (tdRef != currTd)
280 {
281 /*
282 * if the tdRef is not in tdl
283 * GetElmtIndex will return < 0
284 * if the tdRef is in the tdl, then the
285 * currTd must remain in the tdl.
286 */
287 tdIndex = GetElmtIndex (tdRef, tdl);
288 if (tdIndex >= 0)
289 keep = 1;
290 }
291 }
292 if (!keep)
293 {
294 /* append to sublist and remove for tdl */
295 tdHndl = (TypeDef**) AsnListAppend (subList);
296 *tdHndl = currTd;
297 AsnListRemove (tdl);
298 }
299 if (currTd == last)
300 break; /* exit while */
301
302 SET_CURR_LIST_NODE (tdl, nextListNode);
303 currTd = (TypeDef*)CURR_LIST_ELMT (tdl);
304 }
305 }
306 return subList;
307
308 } /* RemoveAndSortIndependents */
309
310
311 /*
312 * Given a list of types that depend on each other, this attempts
313 * to sort the list from independent--> most dependent.
314 *
315 * Kind of wierd algorithm
316 * 1. first separate and sort out linearly dependent types and place in
317 * a properly ordered list (RemoveAndSortIndependents) (call it "A")
318 *
319 * 2. if types with non-linear (recursive) dependencies remain,
320 * divide them into two groups, recursive (call it "B")(see recursive.c)
321 * and non-recursive (call it "C". The non-recursive ones will depend
322 * on the recursive ones (otherwise step 1 would have grabbed 'em).
323 *
324 * 3. Sort the types in list C as done in step one - there should be
325 * no problems (ie unsorted leftovers) since none of them are recursive.
326 *
327 * 4. For the recursive types in list B, re-do their refLists such that
328 * any types ref'd by a Ptr are not included in the refList
329 * (may have to update this wrt how the ref is used -
330 * eg in an inline of the ref'ing type). Then sort as in Step 1.
331 * Any types that could not be sorted have a definite problem and
332 * compiliation problems will occur. (.. And the code generation
333 * technique must be changed)
334 * (for C only the SET OF and SEQ OF Types are stripped from this
335 * since they are 'generic' - ie don't depend on the list elmt type)
336 *
337 * 5. re-combine all of the lists in order of dependency ie
338 * A-B-(B's leftovers)-C
339 *
340 * (the stripped C lists go after 'A')
341 */
342 void
343 SortTypeDefs PARAMS ((tdl),
344 TypeDefList *tdl)
345 {
346 TypeDef *last;
347 TypeDef *currTd;
348 TypeDef **tdHndl;
349 TypeDef *tmpTd;
350 TypeDef *tdRef;
351 AsnListNode *tdNodeToMove;
352 AsnListNode *nextListNode;
353 long int maxRefCount;
354 TypeDefList *subList; /* "A" */
355 TypeDefList *nonRec;
356 TypeDefList *sortedRec; /* "B" */
357 TypeDefList *sortedNonRec; /* "C" */
358 TypeDefList *cLists;
359
360 if ((tdl == NULL) || (LIST_EMPTY (tdl)))
361 return;
362
363 subList = RemoveAndSortIndependents (tdl);
364
365 /* return if simple sort worked (no recursive types) */
366 if (LIST_EMPTY (tdl))
367 {
368 *tdl = *subList;
369 Free (subList);
370 return;
371 }
372
373 /*
374 * divide the remaining interdepedent types into
375 * two groups recursive and non-recursive.
376 * leave the recursive in the tdl and put the others in a new list.
377 * The non-recursive ones obviously depend on the recursive
378 * on since all of the simple type dependencies have been
379 * dealt with by RemoveAndSortIndependents
380 */
381 last = (TypeDef*)LAST_LIST_ELMT (tdl);
382 SET_CURR_LIST_NODE (tdl, FIRST_LIST_NODE (tdl));
383 currTd = (TypeDef*)CURR_LIST_ELMT (tdl);
384 nonRec = AsnListNew (sizeof (void*));
385
386 while (1)
387 {
388 nextListNode = NEXT_LIST_NODE (tdl);
389
390 if (!currTd->recursive)
391 {
392 tdHndl = (TypeDef**)AsnListAppend (nonRec);
393 *tdHndl = currTd;
394 AsnListRemove (tdl);
395 }
396
397 if (currTd == last)
398 break; /* exit while */
399
400 SET_CURR_LIST_NODE (tdl, nextListNode);
401 currTd = (TypeDef*)CURR_LIST_ELMT (tdl);
402 }
403
404 /* sort the non-recusive types */
405 sortedNonRec = RemoveAndSortIndependents (nonRec);
406
407 if (!LIST_EMPTY (nonRec))
408 {
409 fprintf (stderr,"SortTypeDefs: internal compiler error - non recursive type defs failed sort.\n");
410 sortedNonRec = AsnListConcat (sortedNonRec, nonRec);
411 }
412 Free (nonRec);
413
414 /*
415 * Remove list types from the list since they are generic.
416 * put them in "cLists".
417 * then re-do the dependency list for each type definition that
418 * remain in the recursive list with weighting - ie types
419 * that are ref'd as ptrs don't count. Then re-sort.
420 */
421 last = (TypeDef*)LAST_LIST_ELMT (tdl);
422 SET_CURR_LIST_NODE (tdl, FIRST_LIST_NODE (tdl));
423 currTd = (TypeDef*)CURR_LIST_ELMT (tdl);
424
425 cLists = AsnListNew (sizeof (void*));
426 while (1)
427 {
428 nextListNode = NEXT_LIST_NODE (tdl);
429
430 /* nuke old ref list */
431 AsnListFree (currTd->refList);
432 currTd->refList = NULL;
433
434 /* for C only, remove lists since they are generic */
435 if ((currTd->cTypeDefInfo != NULL) &&
436 ((currTd->type->basicType->choiceId == BASICTYPE_SETOF) ||
437 (currTd->type->basicType->choiceId == BASICTYPE_SEQUENCEOF)))
438 {
439 tdHndl = (TypeDef**)AsnListAppend (cLists);
440 *tdHndl = currTd;
441 AsnListRemove (tdl);
442 }
443
444 if (currTd == last)
445 break; /* exit while */
446
447 SET_CURR_LIST_NODE (tdl, nextListNode);
448 currTd = (TypeDef*)CURR_LIST_ELMT (tdl);
449 }
450
451
452
453 FOR_EACH_LIST_ELMT (currTd, tdl)
454 {
455 currTd->refList = AsnListNew (sizeof (void*));
456 BuildWeightedLocalRefList (currTd->type, currTd->refList);
457 }
458
459 sortedRec = RemoveAndSortIndependents (tdl);
460
461 /*
462 * now merge subLists and put in tdl:
463 * tdl = cLists + sortedRec + impossible rec in tdl + sorted nonRec
464 */
465 subList = AsnListConcat (subList, cLists);
466 subList = AsnListConcat (subList, sortedRec);
467 subList = AsnListConcat (subList, tdl);
468 subList = AsnListConcat (subList, sortedNonRec);
469 *tdl = *subList;
470
471 Free (cLists);
472 Free (subList);
473 Free (sortedRec);
474 Free (sortedNonRec);
475
476 } /* SortTypeDefs */
477
478
479
480
481 /*
482 * Builds list of TypeDefs in this module that the given type refs.
483 * Does not follow type refs to include their type refs.
484 */
485 void
486 BuildLocalRefList PARAMS ((t, refList),
487 Type *t _AND_
488 TypeDefList *refList)
489 {
490 NamedType *e;
491 TypeDef **tdHndl;
492
493 switch (t->basicType->choiceId)
494 {
495 case BASICTYPE_CHOICE:
496 case BASICTYPE_SET:
497 case BASICTYPE_SEQUENCE:
498 FOR_EACH_LIST_ELMT (e, t->basicType->a.choice)
499 {
500 BuildLocalRefList (e->type, refList);
501 }
502 break;
503
504 case BASICTYPE_SETOF:
505 case BASICTYPE_SEQUENCEOF:
506 BuildLocalRefList (t->basicType->a.setOf, refList);
507 break;
508
509 case BASICTYPE_LOCALTYPEREF:
510 tdHndl = (TypeDef**)AsnListAppend (refList);
511 *tdHndl = t->basicType->a.localTypeRef->link;
512 break;
513
514 /*
515 * default: other types are not aggregate and
516 * and can be ignored
517 */
518 }
519 } /* BuildLocalRefList */
520
521
522 /*
523 * Builds list of TypeDefs in this module that the given type references.
524 * Does not follow type refs to include their type refs.
525 * Does not include types that are ref'd as ptrs since
526 * If the target lang is C the type SET OF/SEQ OF types reference
527 * are not counted due to the current 'genericness' of the C list type
528 * (it doesn't need type info)
529 * they shouldn't affect type ordering.
530 */
531 void
532 BuildWeightedLocalRefList PARAMS ((t, refList),
533 Type *t _AND_
534 TypeDefList *refList)
535 {
536 NamedType *e;
537 TypeDef **tdHndl;
538
539 switch (t->basicType->choiceId)
540 {
541 case BASICTYPE_CHOICE:
542 case BASICTYPE_SET:
543 case BASICTYPE_SEQUENCE:
544 FOR_EACH_LIST_ELMT (e, t->basicType->a.choice)
545 {
546 BuildWeightedLocalRefList (e->type, refList);
547 }
548 break;
549
550
551
552 case BASICTYPE_SETOF:
553 case BASICTYPE_SEQUENCEOF:
554 /*
555 * normalize makes embedded list defs into
556 * separate type defs now so this clause will
557 * not fire. (ie they will be a LOCAL_TYPEREF
558 * to the removed list type instead)
559 */
560
561 /*
562 * list types for C don't really depend on
563 * the component type (void*). So if the target lang
564 * is C then can achieve better ordering
565 * for ugly recursive defs by using this relaxation
566 * (ie not including the component type in the ref list)
567 */
568 if (t->cTypeRefInfo == NULL)
569 BuildWeightedLocalRefList (t->basicType->a.setOf, refList);
570
571 break;
572
573 case BASICTYPE_LOCALTYPEREF:
574
575 if (((t->cxxTypeRefInfo != NULL) &&
576 !(t->cxxTypeRefInfo->isPtr)) ||
577 ((t->cTypeRefInfo != NULL) && !(t->cTypeRefInfo->isPtr)))
578 {
579 tdHndl = (TypeDef**)AsnListAppend (refList);
580 *tdHndl = t->basicType->a.localTypeRef->link;
581 }
582 break;
583
584 /*
585 * default: other types are not aggregate and
586 * and can be ignored
587 */
588 }
589 } /* BuildWeightedLocalRefList */
590
591
592
593 /*
594 * Returns the index (starting a 0 for the first elmt)
595 * of the given td in the td list (tdl)
596 * returns -1 if td is not in the list
597 */
598 long int
599 GetElmtIndex PARAMS ((td, tdl),
600 TypeDef *td _AND_
601 TypeDefList *tdl)
602 {
603 void *tmp;
604 TypeDef *tmpTd;
605 long int index;
606
607 index = 0;
608 tmp = (void*) CURR_LIST_NODE (tdl);
609 FOR_EACH_LIST_ELMT (tmpTd, tdl)
610 {
611 if (tmpTd == td)
612 {
613 SET_CURR_LIST_NODE (tdl, tmp);
614 return index;
615 }
616 else
617 index++;
618 }
619
620 SET_CURR_LIST_NODE (tdl, tmp);
621 return -1;
622
623 } /* GetElmtIndex */
624
625
626
627
628
629 /*
630 * Attempts to order the types in tdl from independent-->most depenedent
631 * uses insertion after TypeDef that the given type def depends on.
632 * Hoky - doesn't work very well - differing results depending on
633 * initial order
634 NO LONGER USED
635 void
636 AttemptDependencySort PARAMS ((tdl),
637 TypeDefList *tdl)
638 {
639 TypeDef *last;
640 TypeDef *currTd;
641 TypeDef **tdHndl;
642 TypeDef *tdRef;
643 AsnListNode *nextListNode;
644 long int tdIndex;
645 long int maxTdIndex;
646 long int currIndex;
647
648 if (LIST_EMPTY (tdl))
649 return;
650
651 last = (TypeDef*)LAST_LIST_ELMT (tdl);
652
653 FOR_EACH_LIST_ELMT (currTd, tdl)
654 {
655 currTd->visited = FALSE;
656 }
657
658 SET_CURR_LIST_NODE (tdl, FIRST_LIST_NODE (tdl));
659 currTd = (TypeDef*)CURR_LIST_ELMT (tdl);
660
661 while (1)
662 {
663 nextListNode = NEXT_LIST_NODE (tdl);
664
665 if (!currTd->visited)
666 {
667 currTd->visited = TRUE;
668 maxTdIndex = -1;
669 FOR_EACH_LIST_ELMT (tdRef, currTd->refList)
670 {
671 tdIndex = GetElmtIndex (tdRef, tdl);
672 if (tdIndex > maxTdIndex)
673 maxTdIndex = tdIndex;
674 }
675 }
676
677 currIndex = GetElmtIndex (currTd, tdl);
678
679 if ((maxTdIndex >= 0) && (currIndex < maxTdIndex))
680 {
681 MoveAfter (currIndex, maxTdIndex, tdl);
682 }
683
684 if (currTd == last)
685 break;
686
687 SET_CURR_LIST_NODE (tdl, nextListNode);
688 currTd = (TypeDef*)CURR_LIST_ELMT (tdl);
689 }
690 } AttemptDependencySort */
691
692
693
694 /*
695 * Moves list node at currIndex to after Node at afterIndex
696 * in the given list l. Indexes start at 0 for the first elmt.
697 * May confuse the 'curr' pointer of the list
698 NO LONGER USED
699 void
700 MoveAfter PARAMS ((currIndex, afterIndex, l),
701 unsigned long int currIndex _AND_
702 unsigned long int afterIndex _AND_
703 AsnList *l)
704 {
705 void *tmp;
706 AsnListNode *nodeToMove;
707 AsnListNode *afterNode;
708 int i;
709
710 if ((l == NULL) ||
711 (LIST_COUNT (l) <= currIndex) ||
712 (LIST_COUNT (l) <= afterIndex))
713 {
714 fprintf (stderr,"Internal compiler error - index confusion in MoveAfter\n");
715 return;
716 }
717
718 tmp = (void*) CURR_LIST_NODE (l);
719
720 nodeToMove = l->first;
721 for (i = 0; i < currIndex; i++)
722 nodeToMove = nodeToMove->next;
723
724 afterNode = l->first;
725 for (i = 0; i < afterIndex; i++)
726 afterNode = afterNode->next;
727
728 pop out node to move
729 if (nodeToMove->next)
730 nodeToMove->next->prev = nodeToMove->prev;
731 else
732 l->last = nodeToMove->prev;
733
734 if (nodeToMove->prev)
735 nodeToMove->prev->next = nodeToMove->next;
736 else
737 l->first = nodeToMove->next;
738
739 insert node to move after selected node
740 nodeToMove->next = afterNode->next;
741 nodeToMove->prev = afterNode;
742
743 if (afterNode->next)
744 afterNode->next->prev = nodeToMove;
745 else
746 l->last = nodeToMove;
747
748 afterNode->next = nodeToMove;
749
750 } MoveAfter */