Go to: Contents; Previous section; Beginning of section; Next file in section; Previous file in section.
Line Name
----- ----
534 compare_caller
568 compare_caller_name
279 compare_def
349 compare_def_file
169 compare_file
601 compare_ref
30 def_ident
677 discard_dup_refs
399 find_def
634 find_ref_in_tree
235 free_def
147 free_file
88 free_lang
490 free_ref
196 new_def
111 new_file
55 new_lang
448 new_ref
745 sort_file_order
256 trace_def
511 trace_ref
BEGINNING OF FILE
1: /****************************************************************************/
2: /* */
3: /* FACILITY: Routine Analyzer */
4: /* */
5: /* MODULE: Object Management Support */
6: /* */
7: /* AUTHOR: Steve Branam, Network Product Support Group, Digital */
8: /* Equipment Corporation, Littleton, MA, USA. */
9: /* */
10: /* DESCRIPTION: This module contains all support routines for managing the */
11: /* object types used by Routine Analyzer. They are: source files; routine */
12: /* definitions; and routine references. These objects are all descendents */
13: /* of the List Entry generic type, which means that they are linkable via */
14: /* a list entry header. This allows them to be stored in arbitrary ordered */
15: /* and unordered lists, stacks, and queues. Support routines are supplied */
16: /* for creating and destroying objects from the heap, and for comparing, */
17: /* finding, and sorting them. */
18: /* */
19: /* REVISION HISTORY: */
20: /* */
21: /* V0.1-00 24-AUG-1994 Steve Branam */
22: /* */
23: /* Original version. */
24: /* */
25: /****************************************************************************/
26:
27: #include "ranalyzer.h"
28:
29: /*************************************************************************++*/
ROUTINE def_ident. Go to:
Next routine in file; Routines in this file.
30: char *def_ident(
31: /* Formats an indentification string for a definition entry. The string */
32: /* includes the routine name and the source file name (if known). */
33:
34: DEFINITION
35: *aDef
36: /* (READ, BY ADDR): */
37: /* Definition entry to identify. */
38:
39: ) /* Returns formatted string ptr. WARNING: The returned ptr is the */
40: /* address of a statically-defined string buffer, so the string */
41: /* must be read from it immediately. */
42: /*****************************************************************--*/
43:
44: {
45: /* Trace name string buffer. */
46: static char strbuf[MAX_ROUTINE_IDENT + 1];
47:
48: sprintf(strbuf, "%s - %s", def_name(aDef),
49: (isdefined_routine(aDef) ?
50: source_name(def_source(aDef)) : "External"));
51: return strbuf;
52: }
END def_ident. Go to: Beginning of routine.
53:
54: /*************************************************************************++*/
ROUTINE new_lang. Go to:
Next routine in file; Routines in this file.
55: LANGUAGE_TRANSLATION *new_lang(
56: /* Creates and initializes a new language translation record. */
57:
58: char *aFileExt,
59: /* (READ, BY ADDR): */
60: /* Source file extension string. */
61:
62: SOURCE_LANGUAGE
63: vCode
64: /* (READ, BY VAL): */
65: /* Source language code. */
66:
67: ) /* Returns ptr to initialized record. */
68: /*****************************************************************--*/
69:
70: {
71: LANGUAGE_TRANSLATION /* Ptr to new record. */
72: *record;
73:
74: if ((record = (LANGUAGE_TRANSLATION *)
75: obj_alloc(sizeof(LANGUAGE_TRANSLATION),
76: sizeof(LANGUAGE_TRANSLATION), OBJ_NAME_LANGTRANS)) != NULL) {
77: inc_nlang();
78: record->code = vCode;
79: record->fext = new_str(aFileExt, MAX_FILE_NAME, OBJ_NAME_LANG_EXT);
80: if (trace_obj_enabled()) {
81: trace_new_obj(record, OBJ_NAME_LANGTRANS, aFileExt, num_lang());
82: }
83: }
84: return record;
85: }
END new_lang. Go to: Beginning of routine.
86:
87: /*************************************************************************++*/
ROUTINE free_lang. Go to:
Next routine in file; Routines in this file.
88: LANGUAGE_TRANSLATION *free_lang(
89: /* Frees a source language translation record. The file extension string is */
90: /* not freed; it is assumed to be picked up by another ptr. */
91:
92: LANGUAGE_TRANSLATION
93: *aLangTrans
94: /* (DELETE, BY ADDR): */
95: /* Translation block to free. */
96:
97: ) /* Returns NULL ptr. */
98: /*****************************************************************--*/
99:
100: {
101: dec_nlang();
102: if (trace_obj_enabled()) {
103: trace_free_obj(aLangTrans, OBJ_NAME_LANGTRANS, lang_fext(aLangTrans),
104: num_lang());
105: }
106: return obj_free(aLangTrans, sizeof(LANGUAGE_TRANSLATION),
107: OBJ_NAME_LANGTRANS);
108: }
END free_lang. Go to: Beginning of routine.
109:
110: /*************************************************************************++*/
ROUTINE new_file. Go to:
Next routine in file; Routines in this file.
111: SOURCEFILE *new_file(
112: /* Creates and initializes a new source file record. */
113:
114: char *aSourceName,
115: /* (READ, BY ADDR): */
116: /* Source file name string. */
117:
118: int vTabSize
119: /* (READ, BY VAL): */
120: /* Source text tab size. */
121:
122: ) /* Returns ptr to initialized record. */
123: /*****************************************************************--*/
124:
125: {
126: SOURCEFILE /* Ptr to new record. */
127: *record;
128:
129: if ((record = (SOURCEFILE *) obj_alloc(sizeof(SOURCEFILE),
130: sizeof(SOURCEFILE), OBJ_NAME_SOURCEFILE)) != NULL) {
131: inc_nfiles();
132: record->tabsize = vTabSize;
133: record->seqnum = num_files();
134: record->name = new_str(aSourceName, MAX_FILE_NAME,
135: OBJ_NAME_FILENAME);
136: record->author = new_str(PROGRAM_AUTHOR, sizeof(PROGRAM_AUTHOR),
137: OBJ_NAME_AUTHORNAME);
138: if (trace_obj_enabled()) {
139: trace_new_obj(record, OBJ_NAME_SOURCEFILE, aSourceName,
140: num_files());
141: }
142: }
143: return record;
144: }
END new_file. Go to: Beginning of routine.
145:
146: /*************************************************************************++*/
ROUTINE free_file. Go to:
Next routine in file; Routines in this file.
147: SOURCEFILE *free_file(
148: /* Frees a source file record. */
149:
150: SOURCEFILE
151: *aSourceFile
152: /* (DELETE, BY ADDR): */
153: /* Source file to free. */
154:
155: ) /* Returns NULL ptr. */
156: /*****************************************************************--*/
157:
158: {
159: dec_nfiles();
160: if (trace_obj_enabled()) {
161: trace_free_obj(aSourceFile, OBJ_NAME_SOURCEFILE,
162: source_name(aSourceFile), num_files());
163: }
164: free_str(source_name(aSourceFile));
165: return obj_free(aSourceFile, sizeof(SOURCEFILE), OBJ_NAME_SOURCEFILE);
166: }
END free_file. Go to: Beginning of routine.
167:
168: /*************************************************************************++*/
ROUTINE compare_file. Go to:
Next routine in file; Routines in this file.
169: int compare_file(
170: /* Compares two file information records for ordering by file name. Entries */
171: /* are sorted alphabetically. */
172:
173: SOURCEFILE
174: *aSourceFile1,
175: /* (READ, BY ADDR): */
176: /* First record to compare. */
177:
178: SOURCEFILE
179: *aSourceFile2
180: /* (READ, BY ADDR): */
181: /* Second record to compare. */
182:
183: ) /* Returns status value indicating comparison results: */
184: /* 0 - File names are equal. */
185: /* < 0 - File name of aSourceFile1 is less than name of */
186: /* aSourceFile2. */
187: /* > 0 - File name of aSourceFile1 is greater than name of */
188: /* aSourceFile2. */
189: /*****************************************************************--*/
190:
191: {
192: return strcmp(source_name(aSourceFile1), source_name(aSourceFile2));
193: }
END compare_file. Go to: Beginning of routine.
194:
195: /*************************************************************************++*/
ROUTINE new_def. Go to:
Next routine in file; Routines in this file.
196: DEFINITION *new_def(
197: /* Creates and initializes a new routine definition record. */
198:
199: char *aName,
200: /* (READ, BY ADDR): */
201: /* Routine name string. */
202:
203: SOURCEFILE
204: *aSourceRecord
205: /* (READ, BY ADDR): */
206: /* Source file record. */
207:
208: ) /* Returns ptr to initialized record. */
209: /*****************************************************************--*/
210:
211: {
212: DEFINITION /* Ptr to new record. */
213: *record;
214:
215: if ((record = (DEFINITION *) obj_alloc(sizeof(DEFINITION),
216: sizeof(DEFINITION), OBJ_NAME_DEFINITION)) != NULL) {
217: inc_ndefs();
218: record->name = new_str(aName, MAX_ROUTINE_NAME, OBJ_NAME_ROUTINENAME);
219: set_def_source(record, aSourceRecord);
220: if (trace_obj_enabled()) {
221: trace_new_obj(record, OBJ_NAME_DEFINITION, aName, num_defs());
222: if (aSourceRecord != NULL) {
223: printf(" Source file %s @ %lxh\n",
224: source_name(aSourceRecord), aSourceRecord);
225: }
226: else {
227: puts(" No source file (routine call, not definition)");
228: }
229: }
230: }
231: return record;
232: }
END new_def. Go to: Beginning of routine.
233:
234: /*************************************************************************++*/
ROUTINE free_def. Go to:
Next routine in file; Routines in this file.
235: DEFINITION *free_def(
236: /* Frees a routine definition record. */
237:
238: DEFINITION
239: *aDef
240: /* (DELETE, BY ADDR): */
241: /* Definition to free. */
242:
243: ) /* Returns NULL ptr. */
244: /*****************************************************************--*/
245:
246: {
247: dec_ndefs();
248: if (trace_obj_enabled()) {
249: trace_free_obj(aDef, OBJ_NAME_DEFINITION, def_ident(aDef),
250: num_defs());
251: }
252: return obj_free(aDef, sizeof(DEFINITION), OBJ_NAME_DEFINITION);
253: }
END free_def. Go to: Beginning of routine.
254:
255: /*************************************************************************++*/
ROUTINE trace_def. Go to:
Next routine in file; Routines in this file.
256: void trace_def(
257: /* Traces an action on a definition entry. */
258:
259: DEFINITION
260: *aDef,
261: /* (READ, BY ADDR): */
262: /* Definition entry to trace. */
263:
264: char *aAction
265: /* (READ, BY ADDR): */
266: /* Action string describing what is being done to entry. */
267:
268: ) /* No return value. */
269: /*****************************************************************--*/
270:
271: {
272: if (trace_obj_enabled()) {
273: printf("TRACE: %s %s %s @ %lxh\n", aAction, OBJ_NAME_DEFINITION,
274: def_ident(aDef), aDef);
275: }
276: }
END trace_def. Go to: Beginning of routine.
277:
278: /*************************************************************************++*/
ROUTINE compare_def. Go to:
Next routine in file; Routines in this file.
279: int compare_def(
280: /* Compares two routine definition entries for ordering by routine, file */
281: /* names, and line number (some languages allow multiple definition of the */
282: /* same routine name within different scopes in the same module). Entries */
283: /* are sorted alphabetically, with a special provision. If either or both */
284: /* routine is currently undefined (i.e. the source file is not yet known), */
285: /* they will be considered equal, since either 1) they are both forward */
286: /* references to an as yet undefined routine, or 2) one is the actual */
287: /* definition, while the other is just a reference, in which case the */
288: /* source information from the defined one is copied to the undefined one. */
289:
290: DEFINITION
291: *aDef1,
292: /* (MODIFY, BY ADDR): */
293: /* First entry to compare. The source information may be */
294: /* updated. */
295:
296: DEFINITION
297: *aDef2
298: /* (MODIFY, BY ADDR): */
299: /* Second entry to compare. The source information may be */
300: /* updated. */
301:
302: ) /* Returns status value indicating comparison results: */
303: /* 0 - Routine, file names, and line numbers are equal. */
304: /* < 0 - Routine/file name/line of aDef1 less than aDef2. */
305: /* > 0 - Routine/file name/line of aDef1 greater than aDef2. */
306: /*****************************************************************--*/
307:
308: {
309: int cmpstat; /* Comparison status. */
310:
311: /*+ */
312: /* Compare routine names. If they are unequal, no further comparison */
313: /* is needed. Otherwise, if both routines are defined, compare their */
314: /* files names and line numbers to determine final comparison status. */
315: /*- */
316:
317: if ((cmpstat = ustrncmp(def_name(aDef1), def_name(aDef2),
318: max(strlen(def_name(aDef1)), strlen(def_name(aDef2))))) == 0) {
319: if (isdefined_routine(aDef1) && isdefined_routine(aDef2)) {
320: if ((cmpstat = compare_file(def_source(aDef1), def_source(aDef2)))
321: == 0) {
322: cmpstat = def_begin(aDef1) - def_begin(aDef2);
323: }
324: }
325: else {
326:
327: /*+ */
328: /* One or both is undefined, assume either one is the actual */
329: /* definition and the other is actually a reference to it, or */
330: /* both are actually just references. In either case they are */
331: /* equal in that they represent the same routine. Copy the */
332: /* source information from the defined one to the undefined */
333: /* one so they will both be truly equal. */
334: /* */
335:
336: cmpstat = 0;
337: if (isdefined_routine(aDef2)) { /* aDef2 is the defined one. */
338: set_def_source(aDef1, def_source(aDef2));
339: }
340: else { /* Vice versa (or both undef). */
341: set_def_source(aDef2, def_source(aDef1));
342: }
343: }
344: }
345: return cmpstat;
346: }
END compare_def. Go to: Beginning of routine.
347:
348: /*************************************************************************++*/
ROUTINE compare_def_file. Go to:
Next routine in file; Routines in this file.
349: int compare_def_file(
350: /* Compares two routine definition entries for ordering by file name and */
351: /* line number, i.e. by the order in which they occurred in the files. */
352: /* Entries are sorted alphabetically, with the provision that undefined */
353: /* routines sort before defined ones. */
354:
355: DEFINITION
356: *aDef1,
357: /* (READ, BY ADDR): */
358: /* First entry to compare. */
359:
360: DEFINITION
361: *aDef2
362: /* (READ, BY ADDR): */
363: /* Second entry to compare. */
364:
365: ) /* Returns status value indicating comparison results: */
366: /* 0 - File and line numbers are equal. */
367: /* < 0 - File/line of aDef1 less than aDef2. */
368: /* > 0 - File/line of aDef1 greater than aDef2. */
369: /*****************************************************************--*/
370:
371: {
372: int cmpstat; /* Comparison status. */
373:
374: /*+ */
375: /* If both routines are defined, compare file names and line numbers. */
376: /* Otherwise, undefined one is less than defined one (or both are */
377: /* undefined, and entries are considered equal). */
378: /*- */
379:
380: if (isdefined_routine(aDef1) && isdefined_routine(aDef2)) {
381: if ((cmpstat = compare_file(def_source(aDef1), def_source(aDef2)))
382: == 0) {
383: cmpstat = def_begin(aDef1) - def_begin(aDef2);
384: }
385: }
386: else if (isdefined_routine(aDef2)) { /* aDef2 is the defined one. */
387: cmpstat = -1;
388: }
389: else if (isdefined_routine(aDef1)) { /* Vice versa. */
390: cmpstat = 1;
391: }
392: else { /* Both undefined. */
393: cmpstat = 0;
394: }
395: return cmpstat;
396: }
END compare_def_file. Go to: Beginning of routine.
397:
398: /*************************************************************************++*/
ROUTINE find_def. Go to:
Next routine in file; Routines in this file.
399: DEFINITION *find_def(
400: /* Searches the global routine list for a routine definition entry from the */
401: /* specified source file. If an entry is not found, creates and initializes */
402: /* a new one and returns it. */
403:
404: char *aName,
405: /* (READ, BY ADDR): */
406: /* Routine name string to find. */
407:
408: SOURCEFILE
409: *aSourceRecord
410: /* (READ, BY ADDR): */
411: /* Source file record to find. If a NULL ptr is passed, any */
412: /* routine definition from any file will satisfy the request. */
413: /* In any case, if a definition entry must be created, the */
414: /* value passed as aSourceRecord will be used to initialize the */
415: /* definition source file. */
416:
417:
418: ) /* Returns ptr to found (and possibly created) record. */
419: /*****************************************************************--*/
420:
421: {
422: DEFINITION /* Ptr to search entry. */
423: *searchdef;
424: DEFINITION /* Ptr to found entry. */
425: *curdef;
426:
427: /*+ */
428: /* Create a temporary search entry and use it to search the definition */
429: /* list for a match. If a match is found, discard the search entry and */
430: /* return the found entry. Otherwise, add the search entry to the list */
431: /* and return it as the "found" entry. This guarantees that this */
432: /* routine will always "find" an entry. */
433: /*- */
434:
435: searchdef = new_def(aName, aSourceRecord);
436: if ((curdef = find_ordered_entry(global_deflist(), searchdef,
437: compare_def)) != NULL) {
438: free_def(searchdef); /* Found match, return it. */
439: return curdef;
440: }
441: else { /* Match not found, use search */
442: add_def(searchdef); /* entry. */
443: return searchdef;
444: }
445: }
END find_def. Go to: Beginning of routine.
446:
447: /*************************************************************************++*/
ROUTINE new_ref. Go to:
Next routine in file; Routines in this file.
448: REFERENCE *new_ref(
449: /* Creates and initializes a new routine reference record. */
450:
451: long vLine,
452: /* (READ, BY VAL): */
453: /* Line number in source file where routine is called. */
454:
455: DEFINITION
456: *aRefDef,
457: /* (READ, BY ADDR): */
458: /* Refenced routine's definition record. */
459:
460: DEFINITION
461: *aCallerDef
462: /* (READ, BY ADDR): */
463: /* Caller's definition record. */
464:
465: ) /* Returns ptr to initialized record. */
466: /*****************************************************************--*/
467:
468: {
469: REFERENCE /* Ptr to new record. */
470: *record;
471:
472: if ((record = (REFERENCE *) obj_alloc(sizeof(REFERENCE), sizeof(REFERENCE),
473: OBJ_NAME_REFERENCE)) != NULL) {
474: inc_nrefs();
475: record->definition = aRefDef;
476: record->line = vLine;
477: record->caller = aCallerDef;
478: if (trace_obj_enabled()) {
479: trace_new_obj(record, OBJ_NAME_REFERENCE, def_name(aRefDef),
480: num_refs());
481: printf(" Definition is @ %lxh, caller is %s @ %lxh\n",
482: aRefDef, (aCallerDef == NULL ? "(none)" : def_name(aCallerDef)),
483: (aCallerDef == NULL ? NULL : aCallerDef));
484: }
485: }
486: return record;
487: }
END new_ref. Go to: Beginning of routine.
488:
489: /*************************************************************************++*/
ROUTINE free_ref. Go to:
Next routine in file; Routines in this file.
490: REFERENCE *free_ref(
491: /* Frees a routine reference record. */
492:
493: REFERENCE
494: *aRef
495: /* (DELETE, BY ADDR): */
496: /* Reference to free. */
497:
498: ) /* Returns NULL ptr. */
499: /*****************************************************************--*/
500:
501: {
502: dec_nrefs();
503: if (trace_obj_enabled()) {
504: trace_free_obj(aRef, OBJ_NAME_REFERENCE,
505: def_ident(ref_definition(aRef)), num_refs());
506: }
507: return obj_free(aRef, sizeof(REFERENCE), OBJ_NAME_DEFINITION);
508: }
END free_ref. Go to: Beginning of routine.
509:
510: /*************************************************************************++*/
ROUTINE trace_ref. Go to:
Next routine in file; Routines in this file.
511: void trace_ref(
512: /* Traces an action on a reference entry. */
513:
514: REFERENCE
515: *aRef,
516: /* (READ, BY ADDR): */
517: /* Reference entry to trace. */
518:
519: char *aAction
520: /* (READ, BY ADDR): */
521: /* Action string describing what is being done to entry. */
522:
523: ) /* No return value. */
524: /*****************************************************************--*/
525:
526: {
527: if (trace_obj_enabled()) {
528: printf("TRACE: %s %s %s @ %lxh\n", aAction, OBJ_NAME_REFERENCE,
529: def_ident(ref_definition(aRef)), aRef);
530: }
531: }
END trace_ref. Go to: Beginning of routine.
532:
533: /*************************************************************************++*/
ROUTINE compare_caller. Go to:
Next routine in file; Routines in this file.
534: int compare_caller(
535: /* Compares two reference entries for ordering by caller routine. Entries */
536: /* are sorted alphabetically, and by line number within the same caller. */
537:
538: REFERENCE
539: *aRef1,
540: /* (READ, BY ADDR): */
541: /* First entry to compare. */
542:
543: REFERENCE
544: *aRef2
545: /* (READ, BY ADDR): */
546: /* Second entry to compare. */
547:
548: ) /* Returns status value indicating comparison results: */
549: /* 0 - Callers are equal. */
550: /* < 0 - Caller from aRef1 is less than aRef2. */
551: /* > 0 - Caller from aRef1 is greater than aRef2. */
552: /*****************************************************************--*/
553:
554: {
555: int cmpstat; /* Comparison status. */
556:
557: /*+ */
558: /* If the caller names are the same, compare the line numbers. */
559: /*- */
560:
561: if ((cmpstat = compare_def(ref_caller(aRef1), ref_caller(aRef2))) == 0) {
562: cmpstat = ref_offset(aRef1) - ref_offset(aRef2);
563: }
564: return cmpstat;
565: }
END compare_caller. Go to: Beginning of routine.
566:
567: /*************************************************************************++*/
ROUTINE compare_caller_name. Go to:
Next routine in file; Routines in this file.
568: int compare_caller_name(
569: /* Compares two reference entries for equality by caller routine name. */
570: /* Entries are not sorted by this routine. */
571:
572: REFERENCE
573: *aRef1,
574: /* (READ, BY ADDR): */
575: /* First entry to compare. */
576:
577: REFERENCE
578: *aRef2
579: /* (READ, BY ADDR): */
580: /* Second entry to compare. */
581:
582: ) /* Returns status value indicating comparison results: */
583: /* 0 - Callers are equal. */
584: /* -1 - Callers are not equal. */
585: /*****************************************************************--*/
586:
587: {
588: /*+ */
589: /* Compare the caller names. */
590: /*- */
591:
592: if (strcmp(def_name(ref_caller(aRef1)), def_name(ref_caller(aRef2))) != 0) {
593: return -1;
594: }
595: else {
596: return 0;
597: }
598: }
END compare_caller_name. Go to: Beginning of routine.
599:
600: /*************************************************************************++*/
ROUTINE compare_ref. Go to:
Next routine in file; Routines in this file.
601: int compare_ref(
602: /* Compares two reference entries for equality by routine definition. */
603: /* Entries are not sorted by this routine. */
604:
605: REFERENCE
606: *aRef1,
607: /* (READ, BY ADDR): */
608: /* First entry to compare. */
609:
610: REFERENCE
611: *aRef2
612: /* (READ, BY ADDR): */
613: /* Second entry to compare. */
614:
615: ) /* Returns status value indicating comparison results: */
616: /* 0 - Definitions are equal. */
617: /* -1 - Definitions are not equal. */
618: /*****************************************************************--*/
619:
620: {
621: /*+ */
622: /* Compare the definitions. */
623: /*- */
624:
625: if (compare_def(ref_definition(aRef1), ref_definition(aRef2)) != 0) {
626: return -1;
627: }
628: else {
629: return 0;
630: }
631: }
END compare_ref. Go to: Beginning of routine.
632:
633: /*************************************************************************++*/
ROUTINE find_ref_in_tree. Go to:
Next routine in file; Routines in this file.
634: REFERENCE *find_ref_in_tree(
635: /* Find the first reference to a routine in a call tree. */
636:
637: DEFINITION
638: *aTreeRoot,
639: /* (READ, BY ADDR): */
640: /* Routine definition entry that is root of this call tree. */
641:
642: char *aName
643: /* (READ, BY ADDR): */
644: /* Routine name to search for. */
645:
646: ) /* Returns ptr to found reference, or NULL if no matching reference */
647: /* found. */
648: /*****************************************************************--*/
649:
650: {
651: REFERENCE /* Current reference being */
652: *curref; /* checked at this level. */
653: REFERENCE /* Reference found in a */
654: *foundref; /* subtree. */
655:
656: /*+ */
657: /* For each routine referenced at this level, see if it matches the */
658: /* name. If not, recursively search that routine's subtree for a match */
659: /* and return the match if found. If no match is found at this level */
660: /* or any sublevels, no such reference exists in this tree. */
661: /*- */
662:
663: for (curref = list_first(def_refs(aTreeRoot)); curref != NULL;
664: curref = next_entry(curref)) {
665: if (strcmp(def_name(ref_definition(curref)), aName) == 0) {
666: return curref; /* Found it at this level! */
667: }
668: else if ((foundref = find_ref_in_tree(ref_definition(curref), aName))
669: != NULL) {
670: return foundref; /* Found it in a subtree! */
671: }
672: }
673: return NULL; /* Did not find it anywhere. */
674: }
END find_ref_in_tree. Go to: Beginning of routine.
675:
676: /*************************************************************************++*/
ROUTINE discard_dup_refs. Go to:
Next routine in file; Routines in this file.
677: void discard_dup_refs(
678: /* Discards any duplicate reference entries in any definition ref and */
679: /* caller lists. This leaves at most one reference for each routine in any */
680: /* list. */
681:
682: /* No arguments. */
683:
684: ) /* No return value. */
685: /*****************************************************************--*/
686:
687: {
688: DEFINITION /* Current routine entry. */
689: *curdef;
690: REFERENCE /* Current routine */
691: *curref; /* reference. */
692: LIST curlist; /* Current list being */
693: /* trimmed. */
694:
695: for (curdef = list_first(global_deflist()); curdef != NULL;
696: curdef = next_entry(curdef)) {
697:
698: /*+ */
699: /* First, if the current routine is defined, trim its reference */
700: /* list. To do this, move the reference list to a temporary list, */
701: /* clearing the definition's list. For each reference in the */
702: /* temporary list, see if a matching entry already exists in the */
703: /* definition's list. If so, this is a duplicate, discard it; */
704: /* otherwise, add it to the definition's list. This regrows the */
705: /* definition's list back with only one reference to each routine. */
706: /*- */
707:
708: if (isdefined_routine(curdef)) {
709: trace_def(curdef, "Trim refs");
710: copy_list(def_refs(curdef), &curlist);
711: init_list(def_refs(curdef));
712: while ((curref = dequeue_entry(&curlist)) != NULL) {
713: if (find_ref(curdef, curref)) {
714: free_ref(curref); /* Duplicate, discard it. */
715: }
716: else {
717: add_ref(curdef, curref); /* New one, keep it. */
718: trace_ref(curref, "Keep ref");
719: }
720: }
721: }
722:
723: /*+ */
724: /* Now, regardless of whether or not the routine is defined, trim */
725: /* its caller list, using the same procedure. */
726: /*- */
727:
728: trace_def(curdef, "Trim callers");
729: /* Move list to temporary. */
730: copy_list(def_callers(curdef), &curlist);
731: init_list(def_callers(curdef));
732: while ((curref = dequeue_entry(&curlist)) != NULL) {
733: if (find_caller(curdef, curref)) {
734: free_ref(curref); /* Duplicate, discard it. */
735: }
736: else {
737: add_caller(curdef, curref); /* New one, keep it. */
738: trace_ref(curref, "Keep caller");
739: }
740: }
741: }
742: }
END discard_dup_refs. Go to: Beginning of routine.
743:
744: /*************************************************************************++*/
ROUTINE sort_file_order. Go to:
Next routine in file; Routines in this file.
745: void sort_file_order(
746: /* Resorts the global definition list in order by file, then routine within */
747: /* file. */
748:
749: /* No arguments. */
750:
751: ) /* No return value. */
752: /*****************************************************************--*/
753:
754: {
755: DEFINITION /* Current routine entry. */
756: *curdef;
757: LIST templist; /* Temporary list. */
758:
759: /* */
760: /* Perform an insertion sort on the global definition list. To do */
761: /* this, move the definition list to a temporary list, clearing the */
762: /* definition list. For each definition, dequeue it from the temporary */
763: /* list and insert it back into the definition list according the */
764: /* file/routine/line ordering. */
765: /*- */
766:
767: copy_list(global_deflist(), &templist);
768: init_list(global_deflist());
769: while ((curdef = dequeue_entry(&templist)) != NULL) {
770: trace_def(curdef, "Sort file order");
771: insert_ordered_entry(global_deflist(), curdef, compare_def_file);
772: }
773: }
END sort_file_order. Go to: Beginning of routine.
774:
END OF FILE
TOTAL: 21 routines, 34 Avg Length
Go to: Contents; Previous section; Beginning of section; Next file in section; Previous file in section.