Ping?

On Mon, Nov 16, 2015 at 10:09:29AM -0800, Serguey Parkhomovsky wrote:
> Hi Philip,
> 
> Thanks for the detailed explanation on comparison functions for qsort. I
> have looked through your changes, and have only found one issue:
> 
> > 2) totalcmp(A,B) and totalcmp(B,A) both return <0 if both A and B have 
> >    name==0 and cycleno!=0, and they both return >0 if both A and B have 
> >    naem==0 and cycleno==0, violating the consistency requirement.
> 
> The logic is still not quite right with totalcmp; it is still
> inconsistent where both A and B have:
> * name == 0 && cycleno == 0 (both return -1)
> * name != 0 && cycleno == 0 (both return -1)
> * name != 0 && cycleno != 0 (both return -1)
> 
> As well, if name == 0 && cycleno != 0, the code will drop through and
> there will be a null pointer dereference:
> 
>     if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
>       return -1;
>     if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
>       return 1;
> 
> What do you think of the following diff? I've put some of the boolean logic
> into variables to enhance readability.
> 
> Index: arcs.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/gprof/arcs.c,v
> retrieving revision 1.13
> diff -u -p -u -r1.13 arcs.c
> --- arcs.c    20 Aug 2015 22:32:41 -0000      1.13
> +++ arcs.c    16 Nov 2015 17:41:55 -0000
> @@ -95,9 +95,14 @@ addarc(nltype *parentp, nltype *childp, 
>  nltype       **topsortnlp;
>  
>  int
> -topcmp(nltype **npp1, nltype **npp2)
> +topcmp(const void *v1, const void *v2)
>  {
> -    return (*npp1) -> toporder - (*npp2) -> toporder;
> +    const nltype * const *npp1 = v1;
> +    const nltype * const *npp2 = v2;
> +
> +    if ((*npp1) -> toporder < (*npp2) -> toporder)
> +     return -1;
> +    return (*npp1) -> toporder > (*npp2) -> toporder;
>  }
>  
>  nltype **
> Index: gprof.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/gprof/gprof.h,v
> retrieving revision 1.14
> diff -u -p -u -r1.14 gprof.h
> --- gprof.h   19 Oct 2013 13:51:40 -0000      1.14
> +++ gprof.h   16 Nov 2015 17:41:55 -0000
> @@ -281,10 +281,10 @@ void            sortchildren(nltype *);
>  void         sortmembers(nltype *);
>  void         sortparents(nltype *);
>  void         tally(struct rawarc *);
> -int          timecmp(nltype **, nltype **);
> +int          timecmp(const void *, const void *);
>  void         timepropagate(nltype *);
> -int          topcmp(nltype **, nltype **);
> -int          totalcmp(nltype **, nltype **);
> +int          topcmp(const void *, const void *);
> +int          totalcmp(const void *, const void *);
>  
>  #define      LESSTHAN        -1
>  #define      EQUALTO         0
> Index: printgprof.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/gprof/printgprof.c,v
> retrieving revision 1.13
> diff -u -p -u -r1.13 printgprof.c
> --- printgprof.c      20 Aug 2015 22:32:41 -0000      1.13
> +++ printgprof.c      16 Nov 2015 17:41:55 -0000
> @@ -35,7 +35,7 @@
>  #include "gprof.h"
>  #include "pathnames.h"
>  
> -int namecmp(nltype **, nltype **);
> +int namecmp(const void *, const void *);
>  
>  void
>  printprof()
> @@ -66,21 +66,19 @@ printprof()
>  }
>  
>  int
> -timecmp(nltype **npp1, nltype **npp2)
> +timecmp(const void *v1, const void *v2)
>  {
> -    double   timediff;
> -    long     calldiff;
> +    const nltype * const *npp1 = v1;
> +    const nltype * const *npp2 = v2;
>  
> -    timediff = (*npp2) -> time - (*npp1) -> time;
> -    if ( timediff > 0.0 )
> +    if ((*npp2) -> time < (*npp1) -> time)
> +     return -1;
> +    if ((*npp2) -> time > (*npp1) -> time)
>       return 1 ;
> -    if ( timediff < 0.0 )
> +    if ((*npp2) -> ncall < (*npp1) -> ncall)
>       return -1;
> -    calldiff = (*npp2) -> ncall - (*npp1) -> ncall;
> -    if ( calldiff > 0 )
> +    if ((*npp2) -> ncall > (*npp1) -> ncall)
>       return 1;
> -    if ( calldiff < 0 )
> -     return -1;
>      return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
>  }
>  
> @@ -233,26 +231,37 @@ printgprof(nltype **timesortnlp)
>       *       all else being equal, sort by names.
>       */
>  int
> -totalcmp(nltype **npp1, nltype **npp2)
> +totalcmp(const void *v1, const void *v2)
>  {
> -    nltype           *np1 = *npp1;
> -    nltype           *np2 = *npp2;
> -    double           diff;
> -
> -    diff =    ( np1 -> propself + np1 -> propchild )
> -         - ( np2 -> propself + np2 -> propchild );
> -    if ( diff < 0.0 )
> +    const nltype *np1 = *(const nltype **)v1;
> +    const nltype *np2 = *(const nltype **)v2;
> +    double t1, t2;
> +    int np1noname, np2noname, np1cyclehdr, np2cyclehdr;
> +
> +    t1 = np1 -> propself + np1 -> propchild;
> +    t2 = np2 -> propself + np2 -> propchild;
> +    if ( t2 > t1 )
>           return 1;
> -    if ( diff > 0.0 )
> +    if ( t2 < t1 )
>           return -1;
> -    if ( np1 -> name == 0 && np1 -> cycleno != 0 ) 
> +
> +    np1noname = ( np1 -> name == 0 );
> +    np2noname = ( np2 -> name == 0 );
> +    np1cyclehdr = ( np1noname && np1 -> cycleno != 0 );
> +    np2cyclehdr = ( np2noname && np2 -> cycleno != 0 );
> +
> +    if ( np1cyclehdr && !np2cyclehdr )
>       return -1;
> -    if ( np2 -> name == 0 && np2 -> cycleno != 0 )
> +    else if ( !np1cyclehdr && np2cyclehdr )
>       return 1;
> -    if ( np1 -> name == 0 )
> +
> +    if ( np1noname && !np2noname )
>       return -1;
> -    if ( np2 -> name == 0 )
> +    else if ( !np1noname && np2noname )
>       return 1;
> +    else if ( np1noname && np2noname )
> +     return 0;
> +
>      if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
>       return -1;
>      if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
> @@ -642,8 +651,11 @@ printblurb(const char *blurbname)
>  }
>  
>  int
> -namecmp(nltype **npp1, nltype **npp2)
> +namecmp(const void *v1, const void *v2)
>  {
> +    const nltype * const *npp1 = v1;
> +    const nltype * const *npp2 = v2;
> +
>      return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
>  }
>  

Reply via email to