bye-bye
This commit is contained in:
parent
23648f2b8f
commit
3d111f943c
294
proc/compare.c
294
proc/compare.c
@ -1,294 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 1994 Charles Blake and Michael K. Johnson
|
||||
* This file is a part of procps, which is distributable
|
||||
* under the conditions of the GNU Library General Public License.
|
||||
* See the file COPYING for details.
|
||||
*
|
||||
* Copyright 2002 Albert Cahalan
|
||||
*/
|
||||
|
||||
#include <string.h> /* for strcmp */
|
||||
#include <stdio.h> /* for parse error output */
|
||||
|
||||
#include "readproc.h" /* for proc_t */
|
||||
|
||||
#include "compare.h" /* for this code */
|
||||
|
||||
|
||||
/*
|
||||
This module was written by Charles Blake for procps.
|
||||
|
||||
mult_lvl_cmp:
|
||||
slick general purpose multi-level compare function I invented.
|
||||
sort_depth:
|
||||
the number of levels of functions *to use*. This means many more levels
|
||||
can be defined than mult_lvl_cmp tres out. If this is 1 then mult_lvl_cmp
|
||||
is just a trivial wrapper around (*sort_function[0]).
|
||||
sort_direction:
|
||||
multiplicative factor for the output of cmp_whatever.
|
||||
1 ==> default order, -1 ==> reverse order, 0 ==> forced equality
|
||||
The 0 bit is the neat part. Since a value of zero is the code for equality
|
||||
multiplying the output of cmp_foo(a,b) forces a==b to be true. This is a
|
||||
convenient way to turn sorting off in middle levels of a multi-level sort.
|
||||
If time is a problem, reforming the whole sort_function array to not include
|
||||
these unsorted middle levels will be faster since then cmp_foo won't even
|
||||
be called. It might simplify some code depending upon how you organize it.
|
||||
sort_function[]:
|
||||
array of function pointers that points to our family of comparison functions
|
||||
(I have named them cmp_* but mult_lvl_cmp doesn't care what they're named).
|
||||
This may be declared and initialized like so:
|
||||
int (*sort_function[])(void* a, void* b)={&cmp_foo, &cmp_bar, &cmp_hiho};
|
||||
You could also use my command line '-O' parser below.
|
||||
|
||||
Note that we only descend levels until the order is determined. If we descend
|
||||
all levels, that means that the items are equal at all levels, so we return 0.
|
||||
Otherwise we return whatever the level's cmp_foo function would have returned.
|
||||
This allows whatever default behavior you want for cmp_foo. sort_direction[]
|
||||
reverses this default behavior, but mult_lvl_cmp doesn't decide that ascending
|
||||
or descending is the default. That is the job of your cmp_foo's.
|
||||
*/
|
||||
|
||||
/* the only reason these are global is because qsort(3) likes it that way.
|
||||
It's also a little more efficient if mult_lvl_cmp() is called many times.
|
||||
*/
|
||||
|
||||
static int sort_depth = 0;
|
||||
static int sort_direction[10]; /* storage for 10 levels, but 4 would be plenty!*/
|
||||
static int (*sort_function[10])(void* a, void* b);
|
||||
|
||||
int mult_lvl_cmp(void* a, void* b) {
|
||||
int i, cmp_val;
|
||||
for(i = 0; i < sort_depth; i++) {
|
||||
cmp_val = sort_direction[i] * (*sort_function[i])(a,b);
|
||||
if (cmp_val != 0)
|
||||
return cmp_val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* qsort(3) compliant comparison functions for all members of the ps_proc
|
||||
structure (in the same order in which they appear in the proc_t declaration)
|
||||
return is {-1,0,1} as {a<b, a==b, a>b}
|
||||
default ordering is ascending for all members. (flip 1,-1 to reverse)
|
||||
*/
|
||||
/* pre-processor macros to cut down on source size (and typing!)
|
||||
Note the use of the string concatenation operator ##
|
||||
*/
|
||||
#define CMP_STR(NAME) \
|
||||
static int cmp_ ## NAME(proc_t** P, proc_t** Q) { \
|
||||
return strcmp((*P)->NAME, (*Q)->NAME); \
|
||||
}
|
||||
|
||||
#define CMP_INT(NAME) \
|
||||
static int cmp_ ## NAME (proc_t** P, proc_t** Q) { \
|
||||
if ((*P)->NAME < (*Q)->NAME) return -1; \
|
||||
if ((*P)->NAME > (*Q)->NAME) return 1; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
/* Define the (46!) cmp_ functions with the above macros for every element
|
||||
of proc_t. If the binary gets too big, we could nuke inessentials.
|
||||
*/
|
||||
|
||||
/* CMP_STR(cmdline) */
|
||||
/* CMP_STR(ruser) */
|
||||
CMP_STR(euser)
|
||||
CMP_STR(cmd)
|
||||
/* CMP_INT(state) */
|
||||
/* CMP_STR(ttyc) */
|
||||
CMP_INT(euid)
|
||||
CMP_INT(pid)
|
||||
CMP_INT(ppid)
|
||||
CMP_INT(pgrp)
|
||||
CMP_INT(session)
|
||||
CMP_INT(tty)
|
||||
CMP_INT(tpgid)
|
||||
CMP_INT(utime)
|
||||
CMP_INT(stime)
|
||||
CMP_INT(cutime)
|
||||
CMP_INT(cstime)
|
||||
/* CMP_INT(priority) */
|
||||
CMP_INT(nice)
|
||||
CMP_INT(start_time)
|
||||
/* CMP_INT(signal) */
|
||||
/* CMP_INT(blocked) */
|
||||
/* CMP_INT(sigignore) */
|
||||
/* CMP_INT(sigcatch) */
|
||||
CMP_INT(flags)
|
||||
CMP_INT(min_flt)
|
||||
CMP_INT(cmin_flt)
|
||||
CMP_INT(maj_flt)
|
||||
CMP_INT(cmaj_flt)
|
||||
/* CMP_INT(timeout) */
|
||||
CMP_INT(vsize)
|
||||
CMP_INT(rss)
|
||||
/* CMP_INT(rss_rlim) */
|
||||
/* CMP_INT(start_code) */
|
||||
/* CMP_INT(end_code) */
|
||||
/* CMP_INT(start_stack) */
|
||||
/* CMP_INT(kstk_esp) */
|
||||
/* CMP_INT(kstk_eip) */
|
||||
/* CMP_INT(wchan) */
|
||||
CMP_INT(pcpu)
|
||||
CMP_INT(size)
|
||||
CMP_INT(resident)
|
||||
CMP_INT(share)
|
||||
/* CMP_INT(trs) */
|
||||
/* CMP_INT(lrs) */
|
||||
/* CMP_INT(drs) */
|
||||
/* CMP_INT(dt) */
|
||||
|
||||
/* define user interface to sort keys. Fairly self-explanatory. */
|
||||
|
||||
static struct cmp_fun_struct {
|
||||
char letter; /* single option-letter for key */
|
||||
char name[15]; /* long option name for key */
|
||||
int (*fun)(proc_t**, proc_t**); /* pointer to cmp_key */
|
||||
} cmp[] = {
|
||||
/* { '?', "cmdline", &cmp_cmdline }, */
|
||||
{ 'u', "user", &cmp_euser },
|
||||
/* { '?', "ruser", &cmp_ruser }, */
|
||||
{ 'c', "cmd", &cmp_cmd },
|
||||
/* { '?', "state", &cmp_state }, */
|
||||
/* { '?', "ttyc", &cmp_ttyc }, */
|
||||
{ 'U', "uid", &cmp_euid },
|
||||
{ 'p', "pid", &cmp_pid },
|
||||
{ 'P', "ppid", &cmp_ppid },
|
||||
{ 'g', "pgrp", &cmp_pgrp },
|
||||
{ 'o', "session", &cmp_session },
|
||||
{ 't', "tty", &cmp_tty },
|
||||
{ 'G', "tpgid", &cmp_tpgid },
|
||||
{ 'k', "utime", &cmp_utime },
|
||||
{ 'K', "stime", &cmp_stime },
|
||||
{ 'j', "cutime", &cmp_cutime },
|
||||
{ 'J', "cstime", &cmp_cstime },
|
||||
/* { '?', "counter", &cmp_counter }, */
|
||||
{ 'y', "priority", &cmp_nice },
|
||||
{ 'T', "start_time", &cmp_start_time },
|
||||
/* { '?', "signal", &cmp_signal }, */
|
||||
/* { '?', "blocked", &cmp_blocked }, */
|
||||
/* { '?', "sigignore", &cmp_sigignore }, */
|
||||
/* { '?', "sigcatch", &cmp_sigcatch }, */
|
||||
{ 'f', "flags", &cmp_flags },
|
||||
{ 'm', "min_flt", &cmp_min_flt },
|
||||
{ 'n', "cmin_flt", &cmp_cmin_flt },
|
||||
{ 'M', "maj_flt", &cmp_maj_flt },
|
||||
{ 'N', "cmaj_flt", &cmp_cmaj_flt },
|
||||
/* { 'C', "timeout", &cmp_timeout }, */
|
||||
{ 'v', "vsize", &cmp_vsize },
|
||||
{ 'r', "rss", &cmp_rss },
|
||||
/* { '?', "rss_rlim", &cmp_rss_rlim }, */
|
||||
/* { '?', "start_code", &cmp_start_code }, */
|
||||
/* { '?', "end_code", &cmp_end_code }, */
|
||||
/* { '?', "start_stack", &cmp_start_stack }, */
|
||||
/* { '?', "kstk_esp", &cmp_kstk_esp }, */
|
||||
/* { '?', "kstk_eip", &cmp_kstk_eip }, */
|
||||
/* { '?', "wchan", &cmp_wchan }, */
|
||||
{ 'C', "pcpu", &cmp_pcpu },
|
||||
{ 's', "size", &cmp_size },
|
||||
{ 'R', "resident", &cmp_resident },
|
||||
{ 'S', "share", &cmp_share },
|
||||
/* { '?', "trs", &cmp_trs }, */
|
||||
/* { '?', "lrs", &cmp_lrs }, */
|
||||
/* { '?', "drs", &cmp_drs }, */
|
||||
/* { '?', "dt", &cmp_dt }, */
|
||||
{ '\0',"terminator", NULL }
|
||||
};
|
||||
|
||||
/* command line option parsing. Assign sort_{depth,direction[],function[]}
|
||||
based upon a string of the form:
|
||||
[+-]a[+-]b[+-]c...
|
||||
with a,b,c,... being letter flags corresponding to a particular sort
|
||||
key and the optional '-' specifying a reverse sort on that key. + doesn't
|
||||
mean anything, but it keeps things looking balanced...
|
||||
*/
|
||||
const char *parse_sort_opt(const char* opt) {
|
||||
int i, next_dir=1;
|
||||
for(; *opt ; ++opt) {
|
||||
if (*opt == '-' || *opt == '+') {
|
||||
if (*opt == '-')
|
||||
next_dir = -1;
|
||||
opt++;
|
||||
continue;
|
||||
}
|
||||
for (i = 0; cmp[i].letter; i++)
|
||||
if (*opt == cmp[i].letter)
|
||||
break;
|
||||
if (!cmp[i].letter) { /* failed, clear and return */
|
||||
sort_depth=0;
|
||||
for (i=0;i<10;i++){
|
||||
sort_direction[i]=0;
|
||||
sort_function[i]=(cmp_t)NULL;
|
||||
}
|
||||
return "Unknown sort key.";
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"sort level %d: key %s, direction % d\n",
|
||||
sort_depth, cmp[i].name, next_dir);
|
||||
#endif
|
||||
sort_function[sort_depth] = (cmp_t)cmp[i].fun;
|
||||
sort_direction[sort_depth++] = next_dir;
|
||||
next_dir = 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *parse_long_sort(const char* opt) {
|
||||
char* comma;
|
||||
int i, more_keys, next_dir=1;
|
||||
do {
|
||||
if (*opt == '-' || *opt == '+') {
|
||||
if (*opt == '-')
|
||||
next_dir = -1;
|
||||
more_keys = 1;
|
||||
opt++;
|
||||
continue;
|
||||
}
|
||||
more_keys = ((comma=index(opt,',')) != NULL);
|
||||
/* keys are ',' delimited */
|
||||
if (more_keys)
|
||||
*comma='\0'; /* terminate for strcmp() */
|
||||
for(i = 0; cmp[i].letter; ++i)
|
||||
if (strcmp(opt, cmp[i].name) == 0)
|
||||
break;
|
||||
if (!cmp[i].letter) { /* failed, clear and return */
|
||||
sort_depth=0;
|
||||
for (i=0;i<10;i++){
|
||||
sort_direction[i]=0;
|
||||
sort_function[i]=(cmp_t)NULL;
|
||||
}
|
||||
return "Unknown sort key.";
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
"sort level %d: key %s, direction % d\n",
|
||||
sort_depth, cmp[i].name, next_dir);
|
||||
#endif
|
||||
sort_function[sort_depth] = (cmp_t)cmp[i].fun;
|
||||
sort_direction[sort_depth++] = next_dir;
|
||||
next_dir = 1;
|
||||
}
|
||||
opt = comma + 1; /* do next loop on next key, if more keys, else done*/
|
||||
} while (more_keys);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void reset_sort_options (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
sort_depth=0;
|
||||
for (i=0;i<10;i++){
|
||||
sort_direction[i]=0;
|
||||
sort_function[i]=(cmp_t)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void register_sort_function (int dir, cmp_t func)
|
||||
{
|
||||
sort_function[sort_depth] = func;
|
||||
sort_direction[sort_depth++] = dir;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
typedef int (*cmp_t)(void*,void*); /* for function pointer casts */
|
||||
|
||||
extern void register_sort_function (int dir, cmp_t func);
|
||||
extern void reset_sort_options(void);
|
||||
extern int mult_lvl_cmp(void* a, void* b);
|
||||
extern const char *parse_sort_opt(const char* opt);
|
||||
extern const char *parse_long_sort(const char* opt);
|
||||
|
Loading…
Reference in New Issue
Block a user