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