@Routine Analyzer Source File Analysis - objects.c6

objects.c Source Code

LGo to: Contents; Previous section; Beginning of section; Next file in section; Previous file in section.

Q

Routines In This File (Alphabetical)



 Line Name
----- -----  534 compare_caller2  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


V     1: /****************************************************************************/     2: /*									    */1     3: /*  FACILITY:	Routine Analyzer					    */     4: /*									    */7     5: /*  MODULE:	Object Management Support				    */     6: /*									    */O     7: /*  AUTHOR:	Steve Branam, Network Product Support Group, Digital	    */>     8: /*		Equipment Corporation, Littleton, MA, USA.		    */     9: /*									    */V    10: /*  DESCRIPTION: This module contains all support routines for managing the */V    11: /*  object types used by Routine Analyzer. They are: source files; routine  */V    12: /*  definitions; and routine references. These objects are all descendents  */V    13: /*  of the List Entry generic type, which means that they are linkable via  */V    14: /*  a list entry header. This allows them to be stored in arbitrary ordered */V    15: /*  and unordered lists, stacks, and queues. Support routines are supplied  */V    16: /*  for creating and destroying objects from the heap, and for comparing,   */2    17: /*  finding, and sorting them.						    */    18: /*									    */*    19: /*  REVISION HISTORY:							    */    20: /*									    */7    21: /*  V0.1-00 24-AUG-1994 Steve Branam					    */    22: /*									    */(    23: /*	Original version.						    */    24: /*									    */V    25: /****************************************************************************/    26:     27: #include "ranalyzer.h"    28: V    29: /*************************************************************************++*/

bROUTINE def_ident. Go to: mNext routine in file; Routines in this file.



    30: char *def_ident(V    31: /* Formats an indentification string for a definition entry. The string	    */P    32: /* includes the routine name and the source file name (if known).	    */    33:     34:     DEFINITION    35: 	    *aDef-    36: 	    /* (READ, BY ADDR):  					    */7    37: 	    /* Definition entry to identify.				    */    38: P    39: )	/* Returns formatted string ptr.  WARNING: The returned ptr is the  */O    40: 	/* address of a statically-defined string buffer, so the string	    */7    41: 	/* must be read from it immediately.				    */O    42: 	/*****************************************************************--*/    43: 	    44: {3    45: 					    /* Trace name string buffer.    */6    46:     static char	strbuf[MAX_ROUTINE_IDENT + 1];    47: 6    48:     sprintf(strbuf, "%s - %s", def_name(aDef),#    49: 	(isdefined_routine(aDef) ?6    50: 	source_name(def_source(aDef)) : "External"));    51:     return strbuf;	    52: }
GEND def_ident. Go to: Beginning of routine.





    53: V    54: /*************************************************************************++*/

aROUTINE new_lang. Go to: mNext routine in file; Routines in this file.



'    55: LANGUAGE_TRANSLATION *new_lang(M    56: /* Creates and initializes a new language translation record.		    */    57:     58:     char    *aFileExt,,    59: 	    /* (READ, BY ADDR):						    */7    60: 	    /* Source file extension string.				    */    61:     62:     SOURCE_LANGUAGE    63: 	    vCode+    64: 	    /* (READ, BY VAL):						    */0    65: 	    /* Source language code.					    */    66: 9    67: )	/* Returns ptr to initialized record.				    */O    68: 	/*****************************************************************--*/    69: 	    70: {B    71:     LANGUAGE_TRANSLATION		    /* Ptr to new record.	    */    72: 	    *record;    73: 2    74:     if ((record = (LANGUAGE_TRANSLATION *)4    75: 	    obj_alloc(sizeof(LANGUAGE_TRANSLATION),G    76: 		sizeof(LANGUAGE_TRANSLATION), OBJ_NAME_LANGTRANS)) != NULL) {    77: 	inc_nlang();#    78: 	record->code   = vCode;Q    79: 	record->fext   = new_str(aFileExt, MAX_FILE_NAME, OBJ_NAME_LANG_EXT);#    80: 	if (trace_obj_enabled()) {M    81: 	    trace_new_obj(record, OBJ_NAME_LANGTRANS, aFileExt, num_lang());
    82: 	}
    83:     }    84:     return record;	    85: }
FEND new_lang. Go to: Beginning of routine.





    86: V    87: /*************************************************************************++*/

bROUTINE free_lang. Go to: mNext routine in file; Routines in this file.



(    88: LANGUAGE_TRANSLATION *free_lang(V    89: /* Frees a source language translation record. The file extension string is */K    90: /* not freed; it is assumed to be picked up by another ptr.		    */    91:      92:     LANGUAGE_TRANSLATION    93: 	    *aLangTrans-    94: 	    /* (DELETE, BY ADDR):					    */4    95: 	    /* Translation block to free.				    */    96: *    97: )	/* Returns NULL ptr.						    */O    98: 	/*****************************************************************--*/    99: 	   100: {   101:     dec_nlang();&   102:     if (trace_obj_enabled()) {N   103: 	trace_free_obj(aLangTrans, OBJ_NAME_LANGTRANS, lang_fext(aLangTrans),   104: 	    num_lang());
   105:     }E   106:     return obj_free(aLangTrans, sizeof(LANGUAGE_TRANSLATION),   107: 	OBJ_NAME_LANGTRANS);	   108: }
GEND free_lang. Go to: Beginning of routine.





   109: V   110: /*************************************************************************++*/

aROUTINE new_file. Go to: mNext routine in file; Routines in this file.



   111: SOURCEFILE *new_file(E   112: /* Creates and initializes a new source file record.			    */   113: !   114:     char    *aSourceName,,   115: 	    /* (READ, BY ADDR):						    */3   116: 	    /* Source file name string.					    */   117:    118:     int	    vTabSize+   119: 	    /* (READ, BY VAL):						    */0   120: 	    /* Source text tab size.					    */   121: 9   122: )	/* Returns ptr to initialized record.				    */O   123: 	/*****************************************************************--*/0   124: 	   125: { :   126:     SOURCEFILE				    /* Ptr to new record.	    */   127: 	    *record;/   128: F   129:     if ((record = (SOURCEFILE *) obj_alloc(sizeof(SOURCEFILE),A   130: 	    sizeof(SOURCEFILE), OBJ_NAME_SOURCEFILE)) != NULL) {t   131: 	inc_nfiles();'   132: 	record->tabsize = vTabSize;1)   133: 	record->seqnum	= num_files();/>   134: 	record->name	= new_str(aSourceName, MAX_FILE_NAME,"   135: 			    OBJ_NAME_FILENAME);L   136: 	record->author	= new_str(PROGRAM_AUTHOR, sizeof(PROGRAM_AUTHOR),$   137: 			    OBJ_NAME_AUTHORNAME);#   138: 	if (trace_obj_enabled()) {mD   139: 	    trace_new_obj(record, OBJ_NAME_SOURCEFILE, aSourceName,   140: 		num_files());a
   141: 	}
   142:     }=   143:     return record;	   144: }H
FEND new_file. Go to: Beginning of routine.





E   145: V   146: /*************************************************************************++*/

bROUTINE free_file. Go to: mNext routine in file; Routines in this file.

l

   147: SOURCEFILE *free_file(2   148: /* Frees a source file record.						    */   149:    150:     SOURCEFILE   151: 	    *aSourceFile#-   152: 	    /* (DELETE, BY ADDR):					    */4/   153: 	    /* Source file to free.					    */O   154: *   155: )	/* Returns NULL ptr.						    */O   156: 	/*****************************************************************--*/	   157: 	   158: {    159:     dec_nfiles();	&   160:     if (trace_obj_enabled()) {9   161: 	trace_free_obj(aSourceFile, OBJ_NAME_SOURCEFILE, 4   162: 	    source_name(aSourceFile), num_files());
   163:     }r/   164:     free_str(source_name(aSourceFile));	R   165:     return obj_free(aSourceFile, sizeof(SOURCEFILE), OBJ_NAME_SOURCEFILE);	   166: }C
GEND free_file. Go to: Beginning of routine.

*



s   167: V   168: /*************************************************************************++*/

eROUTINE compare_file. Go to: tmNext routine in file; Routines in this file.

/

5   169: int compare_file(sV   170: /* Compares two file information records for ordering by file name. Entries */1   171: /* are sorted alphabetically.						    *//   172:    173:     SOURCEFILE   174: 	    *aSourceFile1,*,   175: 	    /* (READ, BY ADDR):						    */3   176: 	    /* First record to compare.					    */*   177:    178:     SOURCEFILE   179: 	    *aSourceFile2,   180: 	    /* (READ, BY ADDR):						    */3   181: 	    /* Second record to compare.				    */*
   182: 	    *H   183: )	/* Returns status value indicating comparison results:		    */3   184: 	/*    0	- File names are equal.					    */*K   185: 	/*  < 0 - File name of aSourceFile1 is less than name of	    */>'   186: 	/*	  aSourceFile2.						    */=N   187: 	/*  > 0 - File name of aSourceFile1 is greater than name of	    */'   188: 	/*	  aSourceFile2.						    */iO   189: 	/*****************************************************************--*/(   190: 	   191: {aP   192:     return strcmp(source_name(aSourceFile1), source_name(aSourceFile2));	   193: }o
JEND compare_file. Go to: Beginning of routine.





    194: V   195: /*************************************************************************++*/

`ROUTINE new_def. Go to: mNext routine in file; Routines in this file.

o

m   196: DEFINITION *new_def(K   197: /* Creates and initializes a new routine definition record.		    */    198:    199:     char    *aName,r,   200: 	    /* (READ, BY ADDR):						    *//   201: 	    /* Routine name string.					    */    202:    203:     SOURCEFILE   204: 	    *aSourceRecord9,   205: 	    /* (READ, BY ADDR):						    */.   206: 	    /* Source file record.					    */   207: 9   208: )	/* Returns ptr to initialized record.				    */EO   209: 	/*****************************************************************--*/*   210: 	   211: {*:   212:     DEFINITION				    /* Ptr to new record.	    */   213: 	    *record;0   214: F   215:     if ((record = (DEFINITION *) obj_alloc(sizeof(DEFINITION),A   216: 	    sizeof(DEFINITION), OBJ_NAME_DEFINITION)) != NULL) {n   217: 	inc_ndefs(); R   218: 	record->name = new_str(aName, MAX_ROUTINE_NAME, OBJ_NAME_ROUTINENAME);/   219: 	set_def_source(record, aSourceRecord);e#   220: 	if (trace_obj_enabled()) { K   221: 	    trace_new_obj(record, OBJ_NAME_DEFINITION, aName, num_defs()); )   222: 	    if (aSourceRecord != NULL) {2   223: 		printf("       Source file %s @ %lxh\n",9   224: 		    source_name(aSourceRecord), aSourceRecord);    225: 	    }   226: 	    else {	G   227: 		puts("       No source file (routine call, not definition)");*   228: 	    }
   229: 	}
   230:     }*   231:     return record;	   232: }
EEND new_def. Go to: Beginning of routine.

o



    233: V   234: /*************************************************************************++*/

aROUTINE free_def. Go to: mNext routine in file; Routines in this file.

M

_   235: DEFINITION *free_def( 8   236: /* Frees a routine definition record.					    */   237:    238:     DEFINITION   239: 	    *aDef-   240: 	    /* (DELETE, BY ADDR):					    */n.   241: 	    /* Definition to free.					    */   242: *   243: )	/* Returns NULL ptr.						    */O   244: 	/*****************************************************************--*/*   245: 	   246: {*   247:     dec_ndefs();&   248:     if (trace_obj_enabled()) {C   249: 	trace_free_obj(aDef, OBJ_NAME_DEFINITION, def_ident(aDef),d   250: 	    num_defs());A
   251:     }uK   252:     return obj_free(aDef, sizeof(DEFINITION), OBJ_NAME_DEFINITION);T	   253: }*
FEND free_def. Go to: Beginning of routine.





i   254: V   255: /*************************************************************************++*/

bROUTINE trace_def. Go to: mNext 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):  					    */A4   262: 	    /* Definition entry to trace.				    */   263:    264:     char    *aAction-   265: 	    /* (READ, BY ADDR):  					    */NL   266: 	    /* Action string describing what is being done to entry.	    */   267: .   268: )	/* No return value.      					    */O   269: 	/*****************************************************************--*/*   270: 	   271: {*&   272:     if (trace_obj_enabled()) {I   273: 	printf("TRACE: %s %s %s @ %lxh\n", aAction, OBJ_NAME_DEFINITION,t$   274: 	    def_ident(aDef), aDef);
   275:     }<	   276: }u
GEND trace_def. Go to: Beginning of routine.

e



1   277: V   278: /*************************************************************************++*/

dROUTINE compare_def. Go to: mNext routine in file; Routines in this file.

t

    279: int compare_def(V   280: /* Compares two routine definition entries for ordering by routine, file    */V   281: /* names, and line number (some languages allow multiple definition of the  */V   282: /* same routine name within different scopes in the same module). Entries   */V   283: /* are sorted alphabetically, with a special provision. If either or both   */V   284: /* routine is currently undefined (i.e. the source file is not yet known),  */V   285: /* they will be considered equal, since either 1) they are both forward	    */T   286: /* references to an as yet undefined routine, or 2) one is the actual	    */T   287: /* definition, while the other is just a reference, in which case the	    */V   288: /* source information from the defined one is copied to the undefined one.  */   289:    290:     DEFINITION   291: 	    *aDef1,-   292: 	    /* (MODIFY, BY ADDR):					    */1L   293: 	    /* First entry to compare. The source information may be	    */%   294: 	    /* updated.							    */H   295:    296:     DEFINITION   297: 	    *aDef2*-   298: 	    /* (MODIFY, BY ADDR):					    */*M   299: 	    /* Second entry to compare. The source information may be	    */t(   300: 	    /* updated.		   					    */
   301: 	    "H   302: )	/* Returns status value indicating comparison results:		    */J   303: 	/*    0	- Routine, file names, and line numbers are equal.	    */M   304: 	/*  < 0 - Routine/file name/line of aDef1 less than aDef2.	    */ P   305: 	/*  > 0 - Routine/file name/line of aDef1 greater than aDef2.	    */O   306: 	/*****************************************************************--*/    307: 	   308: {*?   309:     int	    cmpstat;			    /* Comparison status.	    */    310:    311:     /*+									    */U   312:     /*	Compare routine names. If they are unequal, no further comparison   */NU   313:     /*	is needed. Otherwise, if both routines are defined, compare their   */U   314:     /*	files names and line numbers to determine final comparison status.  */l   315:     /*-									    */   316: E   317:     if ((cmpstat = ustrncmp(def_name(aDef1), def_name(aDef2),nH   318: 	max(strlen(def_name(aDef1)), strlen(def_name(aDef2))))) == 0) {L   319: 	if (isdefined_routine(aDef1) && isdefined_routine(aDef2)) {O   320: 	    if ((cmpstat = compare_file(def_source(aDef1), def_source(aDef2)))_   321: 		== 0) {8   322: 		cmpstat = def_begin(aDef1) - def_begin(aDef2);   323: 	    }   324: 	}				       325: 	else {   326:    327: 	    /*+								    */N   328: 	    /*	One or both is undefined, assume either one is the actual   */N   329: 	    /*	definition and the other is actually a reference to it, or  */N   330: 	    /*	both are actually just references. In either case they are  */N   331: 	    /*	equal in that they represent the same routine. Copy the	    */N   332: 	    /*	source information from the defined one to the undefined    */>   333: 	    /*	one so they will both be truly equal.			    */   334: 	    /*								    */s   335: 		       336: 	    cmpstat = 0;:O   337: 	    if (isdefined_routine(aDef2)) { /* aDef2 is the defined one.    */ 3   338: 		set_def_source(aDef1, def_source(aDef2));    339: 	    }<   340: 	    else {			    /* Vice versa (or both undef).  */3   341: 		set_def_source(aDef2, def_source(aDef1));1   342: 	    }   343: 	}				    
   344:     }*   345:     return cmpstat;*	   346: }*
IEND compare_def. Go to: Beginning of routine.

m



1   347: V   348: /*************************************************************************++*/

iROUTINE compare_def_file. Go to: *mNext routine in file; Routines in this file.

e

A   349: int compare_def_file("V   350: /* Compares two routine definition entries for ordering by file name and    */U   351: /* line number, i.e. by the order in which they occurred in the files.	    */iV   352: /* Entries are sorted alphabetically, with the provision that undefined	    */8   353: /* routines sort before defined ones.					    */   354:    355:     DEFINITION   356: 	    *aDef1,,   357: 	    /* (READ, BY ADDR):						    */2   358: 	    /* First entry to compare.					    */   359:    360:     DEFINITION   361: 	    *aDef2s,   362: 	    /* (READ, BY ADDR):						    */3   363: 	    /* Second entry to compare.					    */*
   364: 	    -H   365: )	/* Returns status value indicating comparison results:		    */<   366: 	/*    0	- File and line numbers are equal.			    */B   367: 	/*  < 0 - File/line of aDef1 less than aDef2.			    */D   368: 	/*  > 0 - File/line of aDef1 greater than aDef2.		    */O   369: 	/*****************************************************************--*/R   370: 	   371: { ?   372:     int	    cmpstat;			    /* Comparison status.	    */e   373:    374:     /*+									    */U   375:     /*	If both routines are defined, compare file names and line numbers.  */LT   376:     /*	Otherwise, undefined one is less than defined one (or both are	    */E   377:     /*	undefined, and entries are considered equal).			    */    378:     /*-									    */   379: O   380:     if (isdefined_routine(aDef1) && isdefined_routine(aDef2)) { K   381: 	if ((cmpstat = compare_file(def_source(aDef1), def_source(aDef2)))0   382: 	    == 0) {;   383: 	    cmpstat = def_begin(aDef1) - def_begin(aDef2);*
   384: 	}
   385:     }*V   386:     else if (isdefined_routine(aDef2)) {    /* aDef2 is the defined one.    */   387: 	cmpstat = -1;
   388:     }dJ   389:     else if (isdefined_routine(aDef1)) {    /* Vice versa.		    */   390: 	cmpstat = 1;o
   391:     }f4   392:     else {				    /* Both undefined.		    */   393: 	cmpstat = 0;i
   394:     }e   395:     return cmpstat; 	   396: }E
NEND compare_def_file. Go to: Beginning of routine.





i   397: V   398: /*************************************************************************++*/

aROUTINE find_def. Go to: mNext routine in file; Routines in this file.

2

    399: DEFINITION *find_def(V   400: /* Searches the global routine list for a routine definition entry from the */V   401: /* specified source file. If an entry is not found, creates and initializes */0   402: /* a new one and returns it.						    */   403:    404:     char    *aName,*,   405: 	    /* (READ, BY ADDR):						    */6   406: 	    /* Routine name string to find.				    */   407:    408:     SOURCEFILE   409: 	    *aSourceRecordf,   410: 	    /* (READ, BY ADDR):						    */O   411: 	    /* Source file record to find. If a NULL ptr is passed, any	    */nO   412: 	    /* routine definition from any file will satisfy the request.   */0N   413: 	    /* In any case, if a definition entry must be created, the	    */O   414: 	    /* value passed as aSourceRecord will be used to initialize the */22   415: 	    /* definition source file.					    */   416:    417: H   418: )	/* Returns ptr to found (and possibly created) record.		    */O   419: 	/*****************************************************************--*/*   420: 	   421: {*<   422:     DEFINITION				    /* Ptr to search entry.	    */   423: 	    *searchdef;;   424:     DEFINITION				    /* Ptr to found entry.	    */   425: 	    *curdef;a   426:    427:     /*+									    */U   428:     /*	Create a temporary search entry and use it to search the definition */U   429:     /*	list for a match. If a match is found, discard the search entry and */*U   430:     /*	return the found entry. Otherwise, add the search entry to the list */0S   431:     /*	and return it as the "found" entry. This guarantees that this	    */<=   432:     /*	routine will always "find" an entry.				    */.   433:     /*-									    */   434: 6   435:     searchdef = new_def(aName, aSourceRecord);I   436:     if ((curdef = find_ordered_entry(global_deflist(), searchdef,a&   437: 		    compare_def)) != NULL) {D   438: 	free_def(searchdef);		    /* Found match, return it.	    */   439: 	return curdef;3
   440:     } <   441:     else {				    /* Match not found, use search  */4   442: 	add_def(searchdef);		    /* entry.			    */   443: 	return searchdef;
   444:     }5	   445: }i
FEND find_def. Go to: Beginning of routine.





o   446: V   447: /*************************************************************************++*/

`ROUTINE new_ref. Go to: mNext routine in file; Routines in this file.



	   448: REFERENCE *new_ref(iJ   449: /* Creates and initializes a new routine reference record.		    */   450:    451:     long    vLine,+   452: 	    /* (READ, BY VAL):						    */2J   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):						    */5   463: 	    /* Caller's definition record.				    */    464: 9   465: )	/* Returns ptr to initialized record.				    */hO   466: 	/*****************************************************************--*/*   467: 	   468: {39   469:     REFERENCE				    /* Ptr to new record.	    */p   470: 	    *record;   471: W   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;u,   477: 	record->caller     = aCallerDef;#   478: 	if (trace_obj_enabled()) { J   479: 	    trace_new_obj(record, OBJ_NAME_REFERENCE, def_name(aRefDef),    480: 		num_refs());I   481: 	    printf("       Definition is @ %lxh, caller is %s @ %lxh\n",dJ   482: 		aRefDef, (aCallerDef == NULL ? "(none)" : def_name(aCallerDef)),4   483: 		(aCallerDef == NULL ? NULL : aCallerDef));
   484: 	}
   485:     }   486:     return record;	   487: }d
EEND new_ref. Go to: Beginning of routine.





    488: V   489: /*************************************************************************++*/

aROUTINE free_ref. Go to: amNext routine in file; Routines in this file.

.

h   490: REFERENCE *free_ref(7   491: /* Frees a routine reference record.					    *//   492:    493:     REFERENCEl   494: 	    *aRef-   495: 	    /* (DELETE, BY ADDR):					    */3-   496: 	    /* Reference to free.					    */    497: *   498: )	/* Returns NULL ptr.						    */O   499: 	/*****************************************************************--*/    500: 	   501: {e   502:     dec_nrefs();&   503:     if (trace_obj_enabled()) {1   504: 	trace_free_obj(aRef, OBJ_NAME_REFERENCE,:   505: 	    def_ident(ref_definition(aRef)), num_refs());
   506:     }*J   507:     return obj_free(aRef, sizeof(REFERENCE), OBJ_NAME_DEFINITION);	   508: }H
FEND free_ref. Go to: Beginning of routine.





*   509: V   510: /*************************************************************************++*/

bROUTINE trace_ref. Go to: mNext routine in file; Routines in this file.

e

n   511: void trace_ref(f;   512: /* Traces an action on a reference entry.				    */    513:    514:     REFERENCEe   515: 	    *aRef,*-   516: 	    /* (READ, BY ADDR):  					    */o3   517: 	    /* Reference entry to trace.				    */t   518:    519:     char    *aAction-   520: 	    /* (READ, BY ADDR):  					    */,L   521: 	    /* Action string describing what is being done to entry.	    */   522: .   523: )	/* No return value.      					    */O   524: 	/*****************************************************************--*/    525: 	   526: {r&   527:     if (trace_obj_enabled()) {H   528: 	printf("TRACE: %s %s %s @ %lxh\n", aAction, OBJ_NAME_REFERENCE,4   529: 	    def_ident(ref_definition(aRef)), aRef);
   530:     }t	   531: }l
GEND trace_ref. Go to: Beginning of routine.

g



D   532: V   533: /*************************************************************************++*/

gROUTINE compare_caller. Go to: mNext routine in file; Routines in this file.

*

i   534: int compare_caller(nV   535: /* Compares two reference entries for ordering by caller routine. Entries   */V   536: /* are sorted alphabetically, and by line number within the same caller.    */   537:    538:     REFERENCE_   539: 	    *aRef1,,   540: 	    /* (READ, BY ADDR):						    */2   541: 	    /* First entry to compare.					    */   542:    543:     REFERENCEa   544: 	    *aRef2f,   545: 	    /* (READ, BY ADDR):						    */3   546: 	    /* Second entry to compare. 				    */h
   547: 	     H   548: )	/* Returns status value indicating comparison results:		    */0   549: 	/*    0	- Callers are equal.					    */D   550: 	/*  < 0 - Caller from aRef1 is less than aRef2.			    */F   551: 	/*  > 0 - Caller from aRef1 is greater than aRef2.		    */O   552: 	/*****************************************************************--*/0   553: 	   554: {r?   555:     int	    cmpstat;			    /* Comparison status.	    */*   556:    557:     /*+									    */Q   558:     /*	If the caller names are the same, compare the line numbers.	    */x   559:     /*-									    */   560: U   561:     if ((cmpstat = compare_def(ref_caller(aRef1), ref_caller(aRef2))) == 0) {o9   562: 	cmpstat = ref_offset(aRef1) - ref_offset(aRef2);i
   563:     }0   564:     return cmpstat;i	   565: } 
LEND compare_caller. Go to: Beginning of routine.





    566: V   567: /*************************************************************************++*/

lROUTINE compare_caller_name. Go to: mNext routine in file; Routines in this file.



     568: int compare_caller_name(U   569: /* Compares two reference entries for equality by caller routine name.	    */w<   570: /* Entries are not sorted by this routine.				    */   571:    572:     REFERENCEt   573: 	    *aRef1,,   574: 	    /* (READ, BY ADDR):						    */2   575: 	    /* First entry to compare.					    */   576:    577:     REFERENCE4   578: 	    *aRef28,   579: 	    /* (READ, BY ADDR):						    */3   580: 	    /* Second entry to compare. 				    */*
   581: 	    *H   582: )	/* Returns status value indicating comparison results:		    */0   583: 	/*    0	- Callers are equal.					    */3   584: 	/*   -1 - Callers are not equal.				    */PO   585: 	/*****************************************************************--*/	   586: 	   587: {    588:     /*+									    */3   589:     /*	Compare the caller names.					    */    590:     /*-									    */   591: X   592:     if (strcmp(def_name(ref_caller(aRef1)), def_name(ref_caller(aRef2))) != 0) {   593: 	return -1; 
   594:     }    595:     else {   596: 	return 0;
   597:     }u	   598: }a
QEND compare_caller_name. Go to: Beginning of routine.





    599: V   600: /*************************************************************************++*/

dROUTINE compare_ref. Go to: mNext routine in file; Routines in this file.



t   601: int compare_ref(T   602: /* Compares two reference entries for equality by routine definition.	    */<   603: /* Entries are not sorted by this routine.				    */   604:    605:     REFERENCEi   606: 	    *aRef1,,   607: 	    /* (READ, BY ADDR):						    */2   608: 	    /* First entry to compare.					    */   609:    610:     REFERENCE0   611: 	    *aRef2=,   612: 	    /* (READ, BY ADDR):						    */3   613: 	    /* Second entry to compare. 				    */<
   614: 	    rH   615: )	/* Returns status value indicating comparison results:		    */3   616: 	/*    0	- Definitions are equal.				    */a7   617: 	/*   -1 - Definitions are not equal.				    */ O   618: 	/*****************************************************************--*/    619: 	   620: {    621:     /*+									    */2   622:     /*	Compare the definitions.					    */   623:     /*-									    */   624: Q   625:     if (compare_def(ref_definition(aRef1), ref_definition(aRef2)) != 0) {4   626: 	return -1;I
   627:     }    628:     else {   629: 	return 0;
   630:     }		   631: }4
IEND compare_ref. Go to: Beginning of routine.

p



i   632: V   633: /*************************************************************************++*/

iROUTINE find_ref_in_tree. Go to: 1mNext routine in file; Routines in this file.

N

E$   634: REFERENCE *find_ref_in_tree(H   635: /* Find the first reference to a routine in a call tree.		    */   636:    637:     DEFINITION   638: 	    *aTreeRoot,,   639: 	    /* (READ, BY ADDR):						    */O   640: 	    /* Routine definition entry that is root of this call tree.	    */	   641:    642:     char    *aName,   643: 	    /* (READ, BY ADDR):						    */5   644: 	    /* Routine name to search for.				    */    645: P   646: )	/* Returns ptr to found reference, or NULL if no matching reference */   647: 	/* found.							    */nO   648: 	/*****************************************************************--*/o   649: 	   650: {H>   651:     REFERENCE				    /* Current reference being	    */<   652: 	    *curref;			    /* checked at this level.	    */;   653:     REFERENCE				    /* Reference found in a	    */x2   654: 	    *foundref;			    /* subtree.			    */   655:    656:     /*+									    */U   657:     /*	For each routine referenced at this level, see if it matches the    */(U   658:     /*	name. If not, recursively search that routine's subtree for a match */EU   659:     /*	and return the match if found. If no match is found at this level   *//N   660:     /*	or any sublevels, no such reference exists in this tree.	    */   661:     /*-									    */   662: J   663:     for (curref = list_first(def_refs(aTreeRoot)); curref != NULL;'   664: 	curref = next_entry(curref)) {_D   665: 	if (strcmp(def_name(ref_definition(curref)), aName) == 0) {B   666: 	    return curref;		    /* Found it at this level!	    */
   667: 	}N   668: 	else if ((foundref = find_ref_in_tree(ref_definition(curref), aName))   669: 	    != NULL) { C   670: 	    return foundref;		    /* Found it in a subtree!	    */*
   671: 	}
   672:     }*A   673:     return NULL;			    /* Did not find it anywhere.    */+	   674: }H
NEND find_ref_in_tree. Go to: Beginning of routine.





    675: V   676: /*************************************************************************++*/

iROUTINE discard_dup_refs. Go to: mNext routine in file; Routines in this file.



c   677: void discard_dup_refs(T   678: /* Discards any duplicate reference entries in any definition ref and	    */V   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.						    */O   685: 	/*****************************************************************--*/    686: 	   687: {,9   688:     DEFINITION					/* Current routine entry.   */(   689: 	    *curdef; 3   690:     REFERENCE					/* Current routine	    */H.   691: 	    *curref;				/* reference.		    */<   692:     LIST    curlist;				/* Current list being	    */!   693: 						/* trimmed.		    */*   694: G   695:     for (curdef = list_first(global_deflist()); curdef != NULL;0'   696: 	curdef = next_entry(curdef)) {t   697:    698: 	/*+								    */O   699: 	/*  First, if the current routine is defined, trim its reference    */PO   700: 	/*  list. To do this, move the reference list to a temporary list,  */ M   701: 	/*  clearing the definition's list. For each reference in the	    */ O   702: 	/*  temporary list, see if a matching entry already exists in the   */_N   703: 	/*  definition's list. If so, this is a duplicate, discard it;	    */O   704: 	/*  otherwise, add it to the definition's list. This regrows the    */4O   705: 	/*  definition's list back with only one reference to each routine. */o   706: 	/*-								    */   707: )   708: 	if (isdefined_routine(curdef)) {u,   709: 	    trace_def(curdef, "Trim refs");7   710: 	    copy_list(def_refs(curdef), &curlist); )   711: 	    init_list(def_refs(curdef));eE   712: 	    while ((curref = dequeue_entry(&curlist)) != NULL) {R+   713: 		if (find_ref(curdef, curref)) {		*?   714: 		    free_ref(curref);		/* Duplicate, discard it.   */4   715: 		}    716: 		else {B   717: 		    add_ref(curdef, curref);	/* New one, keep it.	    */,   718: 		    trace_ref(curref, "Keep ref");   719: 		}m   720: 	    }
   721: 	}   722:    723: 	/*+								    */O   724: 	/*  Now, regardless of whether or not the routine is defined, trim  */r@   725: 	/*  its caller list, using the same procedure.			    */   726: 	/*-								    */   727: +   728: 	trace_def(curdef, "Trim callers"); ,   729: 						/* Move list to temporary.  */6   730: 	copy_list(def_callers(curdef), &curlist);(   731: 	init_list(def_callers(curdef));A   732: 	while ((curref = dequeue_entry(&curlist)) != NULL) {3/   733: 	    if (find_caller(curdef, curref)) {l;   734: 		free_ref(curref);		/* Duplicate, discard it.   */4   735: 	    }   736: 	    else {FA   737: 		add_caller(curdef, curref);	/* New one, keep it.	    */ +   738: 		trace_ref(curref, "Keep caller");m   739: 	    }
   740: 	}
   741:     } 	   742: }i
NEND discard_dup_refs. Go to: Beginning of routine.





    743: V   744: /*************************************************************************++*/

hROUTINE sort_file_order. Go to: mNext routine in file; Routines in this file.

a

u   745: void sort_file_order(:V   746: /* Resorts the global definition list in order by file, then routine within */   747: /* file.								    */   748: )   749:     /* No arguments.							    */*   750: )   751: )	/* No return value.						    */ O   752: 	/*****************************************************************--*/0   753: 	   754: { 9   755:     DEFINITION					/* Current routine entry.   */e   756: 	    *curdef;e:   757:     LIST    templist;				/* Temporary list.	    */   758:    759:     /*									    */5U   760:     /*	Perform an insertion sort on the global definition list.  To do	    */gU   761:     /*	this, move the definition list to a temporary list, clearing the    */*U   762:     /*	definition list. For each definition, dequeue it from the temporary */TT   763:     /*	list and insert it back into the definition list according the	    */5   764:     /*	file/routine/line ordering.					    */e   765:     /*-									    */   766: 7   767:     copy_list(global_deflist(), &templist);e(   768:     init_list(global_deflist());E   769:     while ((curdef = dequeue_entry(&templist)) != NULL) {t.   770: 	trace_def(curdef, "Sort file order");J   771: 	insert_ordered_entry(global_deflist(), curdef, compare_def_file);
   772:     } 	   773: }m
MEND sort_file_order. Go to: Beginning of routine.

/



D   774: 
END OF FILE !TOTAL: 21 routines, 34 Avg Length*

LGo to: Contents; Previous section; Beginning of section; Next file in section; Previous file in section.