File: | src/usr.bin/gprof/printgprof.c |
Warning: | line 679, column 24 Array access (from variable 'namesortnlp') results in a null pointer dereference |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: printgprof.c,v 1.15 2016/12/22 16:36:18 krw Exp $ */ | |||
2 | /* $NetBSD: printgprof.c,v 1.5 1995/04/19 07:16:21 cgd Exp $ */ | |||
3 | ||||
4 | /* | |||
5 | * Copyright (c) 1983, 1993 | |||
6 | * The Regents of the University of California. All rights reserved. | |||
7 | * | |||
8 | * Redistribution and use in source and binary forms, with or without | |||
9 | * modification, are permitted provided that the following conditions | |||
10 | * are met: | |||
11 | * 1. Redistributions of source code must retain the above copyright | |||
12 | * notice, this list of conditions and the following disclaimer. | |||
13 | * 2. Redistributions in binary form must reproduce the above copyright | |||
14 | * notice, this list of conditions and the following disclaimer in the | |||
15 | * documentation and/or other materials provided with the distribution. | |||
16 | * 3. Neither the name of the University nor the names of its contributors | |||
17 | * may be used to endorse or promote products derived from this software | |||
18 | * without specific prior written permission. | |||
19 | * | |||
20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |||
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |||
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
30 | * SUCH DAMAGE. | |||
31 | */ | |||
32 | ||||
33 | #include <string.h> | |||
34 | ||||
35 | #include "gprof.h" | |||
36 | #include "pathnames.h" | |||
37 | ||||
38 | int namecmp(const void *, const void *); | |||
39 | ||||
40 | void | |||
41 | printprof() | |||
42 | { | |||
43 | nltype *np; | |||
44 | nltype **sortednlp; | |||
45 | int index; | |||
46 | ||||
47 | actime = 0.0; | |||
48 | printf( "\f\n" ); | |||
49 | flatprofheader(); | |||
50 | /* | |||
51 | * Sort the symbol table in by time | |||
52 | */ | |||
53 | sortednlp = calloc( nname , sizeof(nltype *) ); | |||
54 | if ( sortednlp == (nltype **) 0 ) | |||
55 | warnx("[printprof] ran out of memory for time sorting"); | |||
56 | for ( index = 0 ; index < nname ; index += 1 ) { | |||
57 | sortednlp[ index ] = &nl[ index ]; | |||
58 | } | |||
59 | qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); | |||
60 | for ( index = 0 ; index < nname ; index += 1 ) { | |||
61 | np = sortednlp[ index ]; | |||
62 | flatprofline( np ); | |||
63 | } | |||
64 | actime = 0.0; | |||
65 | free( sortednlp ); | |||
66 | } | |||
67 | ||||
68 | int | |||
69 | timecmp(const void *v1, const void *v2) | |||
70 | { | |||
71 | const nltype * const *npp1 = v1; | |||
72 | const nltype * const *npp2 = v2; | |||
73 | ||||
74 | if ((*npp2) -> time < (*npp1) -> time) | |||
75 | return -1; | |||
76 | if ((*npp2) -> time > (*npp1) -> time) | |||
77 | return 1 ; | |||
78 | if ((*npp2) -> ncall < (*npp1) -> ncall) | |||
79 | return -1; | |||
80 | if ((*npp2) -> ncall > (*npp1) -> ncall) | |||
81 | return 1; | |||
82 | return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); | |||
83 | } | |||
84 | ||||
85 | /* | |||
86 | * header for flatprofline | |||
87 | */ | |||
88 | void | |||
89 | flatprofheader() | |||
90 | { | |||
91 | ||||
92 | if (bflag) | |||
93 | printblurb( _PATH_FLAT_BLURB"/usr/share/misc/gprof.flat" ); | |||
94 | printf("\ngranularity: each sample hit covers %ld byte(s)", | |||
95 | (long) scale * sizeof(UNIT)); | |||
96 | if (totime > 0.0) | |||
97 | printf(" for %.2f%% of %.2f seconds\n\n" , 100.0/totime, totime / hz); | |||
98 | else { | |||
99 | printf( " no time accumulated\n\n" ); | |||
100 | /* | |||
101 | * this doesn't hurt sinc eall the numerators will be zero. | |||
102 | */ | |||
103 | totime = 1.0; | |||
104 | } | |||
105 | printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , | |||
106 | "% " , "cumulative" , "self " , "" , "self " , "total " , "" ); | |||
107 | printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n" , | |||
108 | "time" , "seconds " , "seconds" , "calls" , | |||
109 | "ms/call" , "ms/call" , "name" ); | |||
110 | } | |||
111 | ||||
112 | void | |||
113 | flatprofline(nltype *np) | |||
114 | { | |||
115 | ||||
116 | if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) { | |||
117 | return; | |||
118 | } | |||
119 | actime += np -> time; | |||
120 | printf( "%5.1f %10.2f %8.2f" , | |||
121 | 100 * np -> time / totime , actime / hz , np -> time / hz ); | |||
122 | if ( np -> ncall != 0 ) { | |||
123 | printf( " %8ld %8.2f %8.2f " , np -> ncall , | |||
124 | 1000 * np -> time / hz / np -> ncall , | |||
125 | 1000 * ( np -> time + np -> childtime ) / hz / np -> ncall ); | |||
126 | } else { | |||
127 | printf( " %8.8s %8.8s %8.8s " , "" , "" , "" ); | |||
128 | } | |||
129 | printname( np ); | |||
130 | printf( "\n" ); | |||
131 | } | |||
132 | ||||
133 | void | |||
134 | gprofheader() | |||
135 | { | |||
136 | ||||
137 | if ( bflag ) { | |||
138 | printblurb( _PATH_CALLG_BLURB"/usr/share/misc/gprof.callg" ); | |||
139 | } | |||
140 | printf( "\ngranularity: each sample hit covers %ld byte(s)" , | |||
141 | (long) scale * sizeof(UNIT) ); | |||
142 | if ( printtime > 0.0 ) { | |||
143 | printf( " for %.2f%% of %.2f seconds\n\n" , | |||
144 | 100.0/printtime , printtime / hz ); | |||
145 | } else { | |||
146 | printf( " no time propagated\n\n" ); | |||
147 | /* | |||
148 | * this doesn't hurt, since all the numerators will be 0.0 | |||
149 | */ | |||
150 | printtime = 1.0; | |||
151 | } | |||
152 | printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , | |||
153 | "" , "" , "" , "" , "called" , "total" , "parents"); | |||
154 | printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" , | |||
155 | "index" , "%time" , "self" , "descendents" , | |||
156 | "called" , "self" , "name" , "index" ); | |||
157 | printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , | |||
158 | "" , "" , "" , "" , "called" , "total" , "children"); | |||
159 | printf( "\n" ); | |||
160 | } | |||
161 | ||||
162 | void | |||
163 | gprofline(nltype *np) | |||
164 | { | |||
165 | char kirkbuffer[ BUFSIZ1024 ]; | |||
166 | ||||
167 | snprintf(kirkbuffer, sizeof kirkbuffer, "[%d]" , np -> index ); | |||
168 | printf( "%-6.6s %5.1f %7.2f %11.2f" , kirkbuffer , | |||
169 | 100 * ( np -> propself + np -> propchild ) / printtime , | |||
170 | np -> propself / hz , np -> propchild / hz ); | |||
171 | if ( ( np -> ncall + np -> selfcalls ) != 0 ) { | |||
172 | printf( " %7ld" , np -> npropcall ); | |||
173 | if ( np -> selfcalls != 0 ) { | |||
174 | printf( "+%-7ld " , np -> selfcalls ); | |||
175 | } else { | |||
176 | printf( " %7.7s " , "" ); | |||
177 | } | |||
178 | } else { | |||
179 | printf( " %7.7s %7.7s " , "" , "" ); | |||
180 | } | |||
181 | printname( np ); | |||
182 | printf( "\n" ); | |||
183 | } | |||
184 | ||||
185 | void | |||
186 | printgprof(nltype **timesortnlp) | |||
187 | { | |||
188 | int index; | |||
189 | nltype *parentp; | |||
190 | ||||
191 | /* | |||
192 | * Print out the structured profiling list | |||
193 | */ | |||
194 | gprofheader(); | |||
195 | for ( index = 0 ; index < nname + ncycle ; index ++ ) { | |||
196 | parentp = timesortnlp[ index ]; | |||
197 | if ( zflag == 0 && | |||
198 | parentp -> ncall == 0 && | |||
199 | parentp -> selfcalls == 0 && | |||
200 | parentp -> propself == 0 && | |||
201 | parentp -> propchild == 0 ) { | |||
202 | continue; | |||
203 | } | |||
204 | if ( ! parentp -> printflag ) { | |||
205 | continue; | |||
206 | } | |||
207 | if ( parentp -> name == 0 && parentp -> cycleno != 0 ) { | |||
208 | /* | |||
209 | * cycle header | |||
210 | */ | |||
211 | printcycle( parentp ); | |||
212 | printmembers( parentp ); | |||
213 | } else { | |||
214 | printparents( parentp ); | |||
215 | gprofline( parentp ); | |||
216 | printchildren( parentp ); | |||
217 | } | |||
218 | printf( "\n" ); | |||
219 | printf( "-----------------------------------------------\n" ); | |||
220 | printf( "\n" ); | |||
221 | } | |||
222 | free( timesortnlp ); | |||
223 | } | |||
224 | ||||
225 | /* | |||
226 | * sort by decreasing propagated time | |||
227 | * if times are equal, but one is a cycle header, | |||
228 | * say that's first (e.g. less, i.e. -1). | |||
229 | * if one's name doesn't have an underscore and the other does, | |||
230 | * say the one is first. | |||
231 | * all else being equal, sort by names. | |||
232 | */ | |||
233 | int | |||
234 | totalcmp(const void *v1, const void *v2) | |||
235 | { | |||
236 | const nltype *np1 = *(const nltype **)v1; | |||
237 | const nltype *np2 = *(const nltype **)v2; | |||
238 | double t1, t2; | |||
239 | int np1noname, np2noname, np1cyclehdr, np2cyclehdr; | |||
240 | ||||
241 | t1 = np1 -> propself + np1 -> propchild; | |||
242 | t2 = np2 -> propself + np2 -> propchild; | |||
243 | if ( t2 > t1 ) | |||
244 | return 1; | |||
245 | if ( t2 < t1 ) | |||
246 | return -1; | |||
247 | ||||
248 | np1noname = ( np1 -> name == 0 ); | |||
249 | np2noname = ( np2 -> name == 0 ); | |||
250 | np1cyclehdr = ( np1noname && np1 -> cycleno != 0 ); | |||
251 | np2cyclehdr = ( np2noname && np2 -> cycleno != 0 ); | |||
252 | ||||
253 | if ( np1cyclehdr && !np2cyclehdr ) | |||
254 | return -1; | |||
255 | else if ( !np1cyclehdr && np2cyclehdr ) | |||
256 | return 1; | |||
257 | ||||
258 | if ( np1noname && !np2noname ) | |||
259 | return -1; | |||
260 | else if ( !np1noname && np2noname ) | |||
261 | return 1; | |||
262 | else if ( np1noname && np2noname ) | |||
263 | return 0; | |||
264 | ||||
265 | if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' ) | |||
266 | return -1; | |||
267 | if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' ) | |||
268 | return 1; | |||
269 | if ( np1 -> ncall > np2 -> ncall ) | |||
270 | return -1; | |||
271 | if ( np1 -> ncall < np2 -> ncall ) | |||
272 | return 1; | |||
273 | return strcmp( np1 -> name , np2 -> name ); | |||
274 | } | |||
275 | ||||
276 | void | |||
277 | printparents(nltype *childp) | |||
278 | { | |||
279 | nltype *parentp; | |||
280 | arctype *arcp; | |||
281 | nltype *cycleheadp; | |||
282 | ||||
283 | if ( childp -> cyclehead != 0 ) { | |||
284 | cycleheadp = childp -> cyclehead; | |||
285 | } else { | |||
286 | cycleheadp = childp; | |||
287 | } | |||
288 | if ( childp -> parents == 0 ) { | |||
289 | printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" , | |||
290 | "" , "" , "" , "" , "" , "" ); | |||
291 | return; | |||
292 | } | |||
293 | sortparents( childp ); | |||
294 | for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { | |||
295 | parentp = arcp -> arc_parentp; | |||
296 | if ( childp == parentp || ( arcp -> arc_flags & DEADARC0x01 ) || | |||
297 | ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { | |||
298 | /* | |||
299 | * selfcall or call among siblings | |||
300 | */ | |||
301 | printf( "%6.6s %5.5s %7.7s %11.11s %7ld %7.7s " , | |||
302 | "" , "" , "" , "" , | |||
303 | arcp -> arc_count , "" ); | |||
304 | printname( parentp ); | |||
305 | printf( "\n" ); | |||
306 | } else { | |||
307 | /* | |||
308 | * regular parent of child | |||
309 | */ | |||
310 | printf( "%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld " , | |||
311 | "" , "" , | |||
312 | arcp -> arc_time / hz , arcp -> arc_childtime / hz , | |||
313 | arcp -> arc_count , cycleheadp -> npropcall ); | |||
314 | printname( parentp ); | |||
315 | printf( "\n" ); | |||
316 | } | |||
317 | } | |||
318 | } | |||
319 | ||||
320 | void | |||
321 | printchildren(nltype *parentp) | |||
322 | { | |||
323 | nltype *childp; | |||
324 | arctype *arcp; | |||
325 | ||||
326 | sortchildren( parentp ); | |||
327 | arcp = parentp -> children; | |||
328 | for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { | |||
329 | childp = arcp -> arc_childp; | |||
330 | if ( childp == parentp || ( arcp -> arc_flags & DEADARC0x01 ) || | |||
331 | ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { | |||
332 | /* | |||
333 | * self call or call to sibling | |||
334 | */ | |||
335 | printf( "%6.6s %5.5s %7.7s %11.11s %7ld %7.7s " , | |||
336 | "" , "" , "" , "" , arcp -> arc_count , "" ); | |||
337 | printname( childp ); | |||
338 | printf( "\n" ); | |||
339 | } else { | |||
340 | /* | |||
341 | * regular child of parent | |||
342 | */ | |||
343 | printf( "%6.6s %5.5s %7.2f %11.2f %7ld/%-7ld " , | |||
344 | "" , "" , | |||
345 | arcp -> arc_time / hz , arcp -> arc_childtime / hz , | |||
346 | arcp -> arc_count , childp -> cyclehead -> npropcall ); | |||
347 | printname( childp ); | |||
348 | printf( "\n" ); | |||
349 | } | |||
350 | } | |||
351 | } | |||
352 | ||||
353 | void | |||
354 | printname(nltype *selfp) | |||
355 | { | |||
356 | ||||
357 | if ( selfp -> name != 0 ) { | |||
358 | printf( "%s" , selfp -> name ); | |||
359 | # ifdef DEBUG | |||
360 | if ( debug & DFNDEBUG1 ) { | |||
361 | printf( "{%d} " , selfp -> toporder ); | |||
362 | } | |||
363 | if ( debug & PROPDEBUG512 ) { | |||
364 | printf( "%5.2f%% " , selfp -> propfraction ); | |||
365 | } | |||
366 | # endif /* DEBUG */ | |||
367 | } | |||
368 | if ( selfp -> cycleno != 0 ) { | |||
369 | printf( " <cycle %d>" , selfp -> cycleno ); | |||
370 | } | |||
371 | if ( selfp -> index != 0 ) { | |||
372 | if ( selfp -> printflag ) { | |||
373 | printf( " [%d]" , selfp -> index ); | |||
374 | } else { | |||
375 | printf( " (%d)" , selfp -> index ); | |||
376 | } | |||
377 | } | |||
378 | } | |||
379 | ||||
380 | void | |||
381 | sortchildren(nltype *parentp) | |||
382 | { | |||
383 | arctype *arcp; | |||
384 | arctype *detachedp; | |||
385 | arctype sorted; | |||
386 | arctype *prevp; | |||
387 | ||||
388 | /* | |||
389 | * unlink children from parent, | |||
390 | * then insertion sort back on to sorted's children. | |||
391 | * *arcp the arc you have detached and are inserting. | |||
392 | * *detachedp the rest of the arcs to be sorted. | |||
393 | * sorted arc list onto which you insertion sort. | |||
394 | * *prevp arc before the arc you are comparing. | |||
395 | */ | |||
396 | sorted.arc_childlist = 0; | |||
397 | for (arcp = parentp -> children; arcp; arcp = detachedp) { | |||
398 | detachedp = arcp -> arc_childlist; | |||
399 | /* | |||
400 | * consider *arcp as disconnected | |||
401 | * insert it into sorted | |||
402 | */ | |||
403 | for ( prevp = &sorted ; | |||
404 | prevp -> arc_childlist ; | |||
405 | prevp = prevp -> arc_childlist ) { | |||
406 | if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN-1 ) { | |||
407 | break; | |||
408 | } | |||
409 | } | |||
410 | arcp -> arc_childlist = prevp -> arc_childlist; | |||
411 | prevp -> arc_childlist = arcp; | |||
412 | } | |||
413 | /* | |||
414 | * reattach sorted children to parent | |||
415 | */ | |||
416 | parentp -> children = sorted.arc_childlist; | |||
417 | } | |||
418 | ||||
419 | void | |||
420 | sortparents(nltype *childp) | |||
421 | { | |||
422 | arctype *arcp; | |||
423 | arctype *detachedp; | |||
424 | arctype sorted; | |||
425 | arctype *prevp; | |||
426 | ||||
427 | /* | |||
428 | * unlink parents from child, | |||
429 | * then insertion sort back on to sorted's parents. | |||
430 | * *arcp the arc you have detached and are inserting. | |||
431 | * *detachedp the rest of the arcs to be sorted. | |||
432 | * sorted arc list onto which you insertion sort. | |||
433 | * *prevp arc before the arc you are comparing. | |||
434 | */ | |||
435 | sorted.arc_parentlist = 0; | |||
436 | for (arcp = childp->parents; arcp; arcp = detachedp) { | |||
437 | detachedp = arcp->arc_parentlist; | |||
438 | /* | |||
439 | * consider *arcp as disconnected | |||
440 | * insert it into sorted | |||
441 | */ | |||
442 | for (prevp = &sorted; prevp->arc_parentlist; | |||
443 | prevp = prevp->arc_parentlist) | |||
444 | if (arccmp(arcp , prevp->arc_parentlist) != GREATERTHAN1) | |||
445 | break; | |||
446 | arcp->arc_parentlist = prevp->arc_parentlist; | |||
447 | prevp->arc_parentlist = arcp; | |||
448 | } | |||
449 | /* | |||
450 | * reattach sorted arcs to child | |||
451 | */ | |||
452 | childp -> parents = sorted.arc_parentlist; | |||
453 | } | |||
454 | ||||
455 | /* | |||
456 | * print a cycle header | |||
457 | */ | |||
458 | void | |||
459 | printcycle(nltype *cyclep) | |||
460 | { | |||
461 | char kirkbuffer[ BUFSIZ1024 ]; | |||
462 | ||||
463 | snprintf(kirkbuffer, sizeof kirkbuffer, "[%d]" , cyclep->index); | |||
464 | printf("%-6.6s %5.1f %7.2f %11.2f %7ld", kirkbuffer, | |||
465 | 100 * (cyclep->propself + cyclep->propchild) / printtime, | |||
466 | cyclep->propself / hz, cyclep->propchild / hz, cyclep->npropcall); | |||
467 | if (cyclep -> selfcalls != 0) | |||
468 | printf("+%-7ld" , cyclep->selfcalls); | |||
469 | else | |||
470 | printf(" %7.7s" , ""); | |||
471 | printf(" <cycle %d as a whole>\t[%d]\n" , | |||
472 | cyclep->cycleno , cyclep->index ); | |||
473 | } | |||
474 | ||||
475 | /* | |||
476 | * print the members of a cycle | |||
477 | */ | |||
478 | void | |||
479 | printmembers(nltype *cyclep) | |||
480 | { | |||
481 | nltype *memberp; | |||
482 | ||||
483 | sortmembers( cyclep ); | |||
484 | for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { | |||
485 | printf( "%6.6s %5.5s %7.2f %11.2f %7ld" , "", "", | |||
486 | memberp->propself / hz, memberp->propchild / hz, memberp->npropcall ); | |||
487 | if (memberp -> selfcalls != 0) | |||
488 | printf("+%-7ld" , memberp -> selfcalls); | |||
489 | else | |||
490 | printf(" %7.7s", ""); | |||
491 | printf(" "); | |||
492 | printname(memberp); | |||
493 | printf("\n"); | |||
494 | } | |||
495 | } | |||
496 | ||||
497 | /* | |||
498 | * sort members of a cycle | |||
499 | */ | |||
500 | void | |||
501 | sortmembers(nltype *cyclep) | |||
502 | { | |||
503 | nltype *todo; | |||
504 | nltype *doing; | |||
505 | nltype *prev; | |||
506 | ||||
507 | /* | |||
508 | * detach cycle members from cyclehead, | |||
509 | * and insertion sort them back on. | |||
510 | */ | |||
511 | todo = cyclep -> cnext; | |||
512 | cyclep -> cnext = 0; | |||
513 | for (doing = todo; doing; doing = todo) { | |||
514 | todo = doing -> cnext; | |||
515 | for (prev = cyclep; prev -> cnext; prev = prev -> cnext) | |||
516 | if (membercmp(doing, prev->cnext ) == GREATERTHAN1) | |||
517 | break; | |||
518 | doing -> cnext = prev -> cnext; | |||
519 | prev -> cnext = doing; | |||
520 | } | |||
521 | } | |||
522 | ||||
523 | /* | |||
524 | * major sort is on propself + propchild, | |||
525 | * next is sort on ncalls + selfcalls. | |||
526 | */ | |||
527 | int | |||
528 | membercmp(nltype *this , nltype *that) | |||
529 | { | |||
530 | double thistime = this -> propself + this -> propchild; | |||
531 | double thattime = that -> propself + that -> propchild; | |||
532 | long thiscalls = this -> ncall + this -> selfcalls; | |||
533 | long thatcalls = that -> ncall + that -> selfcalls; | |||
534 | ||||
535 | if ( thistime > thattime ) { | |||
536 | return GREATERTHAN1; | |||
537 | } | |||
538 | if ( thistime < thattime ) { | |||
539 | return LESSTHAN-1; | |||
540 | } | |||
541 | if ( thiscalls > thatcalls ) { | |||
542 | return GREATERTHAN1; | |||
543 | } | |||
544 | if ( thiscalls < thatcalls ) { | |||
545 | return LESSTHAN-1; | |||
546 | } | |||
547 | return EQUALTO0; | |||
548 | } | |||
549 | /* | |||
550 | * compare two arcs to/from the same child/parent. | |||
551 | * - if one arc is a self arc, it's least. | |||
552 | * - if one arc is within a cycle, it's less than. | |||
553 | * - if both arcs are within a cycle, compare arc counts. | |||
554 | * - if neither arc is within a cycle, compare with | |||
555 | * arc_time + arc_childtime as major key | |||
556 | * arc count as minor key | |||
557 | */ | |||
558 | int | |||
559 | arccmp(arctype *thisp, arctype *thatp) | |||
560 | { | |||
561 | nltype *thisparentp = thisp -> arc_parentp; | |||
562 | nltype *thischildp = thisp -> arc_childp; | |||
563 | nltype *thatparentp = thatp -> arc_parentp; | |||
564 | nltype *thatchildp = thatp -> arc_childp; | |||
565 | double thistime; | |||
566 | double thattime; | |||
567 | ||||
568 | # ifdef DEBUG | |||
569 | if ( debug & TIMEDEBUG16 ) { | |||
570 | printf( "[arccmp] " ); | |||
571 | printname( thisparentp ); | |||
572 | printf( " calls " ); | |||
573 | printname ( thischildp ); | |||
574 | printf( " %f + %f %ld/%ld\n" , | |||
575 | thisp -> arc_time , thisp -> arc_childtime , | |||
576 | thisp -> arc_count , thischildp -> ncall ); | |||
577 | printf( "[arccmp] " ); | |||
578 | printname( thatparentp ); | |||
579 | printf( " calls " ); | |||
580 | printname( thatchildp ); | |||
581 | printf( " %f + %f %ld/%ld\n" , | |||
582 | thatp -> arc_time , thatp -> arc_childtime , | |||
583 | thatp -> arc_count , thatchildp -> ncall ); | |||
584 | printf( "\n" ); | |||
585 | } | |||
586 | # endif /* DEBUG */ | |||
587 | if ( thisparentp == thischildp ) { | |||
588 | /* this is a self call */ | |||
589 | return LESSTHAN-1; | |||
590 | } | |||
591 | if ( thatparentp == thatchildp ) { | |||
592 | /* that is a self call */ | |||
593 | return GREATERTHAN1; | |||
594 | } | |||
595 | if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 && | |||
596 | thisparentp -> cycleno == thischildp -> cycleno ) { | |||
597 | /* this is a call within a cycle */ | |||
598 | if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && | |||
599 | thatparentp -> cycleno == thatchildp -> cycleno ) { | |||
600 | /* that is a call within the cycle, too */ | |||
601 | if ( thisp -> arc_count < thatp -> arc_count ) { | |||
602 | return LESSTHAN-1; | |||
603 | } | |||
604 | if ( thisp -> arc_count > thatp -> arc_count ) { | |||
605 | return GREATERTHAN1; | |||
606 | } | |||
607 | return EQUALTO0; | |||
608 | } else { | |||
609 | /* that isn't a call within the cycle */ | |||
610 | return LESSTHAN-1; | |||
611 | } | |||
612 | } else { | |||
613 | /* this isn't a call within a cycle */ | |||
614 | if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && | |||
615 | thatparentp -> cycleno == thatchildp -> cycleno ) { | |||
616 | /* that is a call within a cycle */ | |||
617 | return GREATERTHAN1; | |||
618 | } else { | |||
619 | /* neither is a call within a cycle */ | |||
620 | thistime = thisp -> arc_time + thisp -> arc_childtime; | |||
621 | thattime = thatp -> arc_time + thatp -> arc_childtime; | |||
622 | if ( thistime < thattime ) | |||
623 | return LESSTHAN-1; | |||
624 | if ( thistime > thattime ) | |||
625 | return GREATERTHAN1; | |||
626 | if ( thisp -> arc_count < thatp -> arc_count ) | |||
627 | return LESSTHAN-1; | |||
628 | if ( thisp -> arc_count > thatp -> arc_count ) | |||
629 | return GREATERTHAN1; | |||
630 | return EQUALTO0; | |||
631 | } | |||
632 | } | |||
633 | } | |||
634 | ||||
635 | void | |||
636 | printblurb(const char *blurbname) | |||
637 | { | |||
638 | FILE *blurbfile; | |||
639 | int input; | |||
640 | ||||
641 | blurbfile = fopen( blurbname , "r" ); | |||
642 | if ( blurbfile == NULL((void *)0) ) { | |||
643 | warn("fopen: %s", blurbname ); | |||
644 | return; | |||
645 | } | |||
646 | while ( ( input = getc( blurbfile )(!__isthreaded ? (--(blurbfile)->_r < 0 ? __srget(blurbfile ) : (int)(*(blurbfile)->_p++)) : (getc)(blurbfile)) ) != EOF(-1) ) | |||
647 | putchar( input )(!__isthreaded ? __sputc(input, (&__sF[1])) : (putc)(input , (&__sF[1]))); | |||
648 | ||||
649 | fclose( blurbfile ); | |||
650 | } | |||
651 | ||||
652 | int | |||
653 | namecmp(const void *v1, const void *v2) | |||
654 | { | |||
655 | const nltype * const *npp1 = v1; | |||
656 | const nltype * const *npp2 = v2; | |||
657 | ||||
658 | return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); | |||
659 | } | |||
660 | ||||
661 | void | |||
662 | printindex() | |||
663 | { | |||
664 | nltype **namesortnlp; | |||
665 | nltype *nlp; | |||
666 | int index, nnames, todo, i, j; | |||
667 | char peterbuffer[ BUFSIZ1024 ]; | |||
668 | ||||
669 | /* | |||
670 | * Now, sort regular function name alphbetically | |||
671 | * to create an index. | |||
672 | */ | |||
673 | namesortnlp = calloc( nname + ncycle , sizeof(nltype *) ); | |||
| ||||
674 | if ( namesortnlp == (nltype **) 0 ) | |||
675 | warnx("ran out of memory for sorting"); | |||
676 | for ( index = 0 , nnames = 0 ; index < nname ; index++ ) { | |||
677 | if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 ) | |||
678 | continue; | |||
679 | namesortnlp[nnames++] = &nl[index]; | |||
| ||||
680 | } | |||
681 | qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp ); | |||
682 | for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) { | |||
683 | namesortnlp[todo++] = &cyclenl[index]; | |||
684 | } | |||
685 | printf( "\f\nIndex by function name\n\n" ); | |||
686 | index = ( todo + 2 ) / 3; | |||
687 | for ( i = 0; i < index ; i++ ) { | |||
688 | for ( j = i; j < todo ; j += index ) { | |||
689 | nlp = namesortnlp[ j ]; | |||
690 | if ( nlp -> printflag ) { | |||
691 | snprintf(peterbuffer, sizeof peterbuffer, "[%d]" , nlp -> index ); | |||
692 | } else { | |||
693 | snprintf(peterbuffer, sizeof peterbuffer, "(%d)" , nlp -> index ); | |||
694 | } | |||
695 | if ( j < nnames ) { | |||
696 | printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name ); | |||
697 | } else { | |||
698 | printf( "%6.6s " , peterbuffer ); | |||
699 | snprintf(peterbuffer, sizeof peterbuffer, "<cycle %d>" | |||
700 | , nlp -> cycleno ); | |||
701 | printf( "%-19.19s" , peterbuffer ); | |||
702 | } | |||
703 | } | |||
704 | printf( "\n" ); | |||
705 | } | |||
706 | free( namesortnlp ); | |||
707 | } |