top: tweak argument parsing for some locale situations
Boy I hate locale stuff. For code I thought was pretty robust, Jaromir sure proved that it wasn't. Anyway, me thinks this commit closes some gaps and will cause top to behave appropriately under various locale settings. It does *not* permit top to respond to the ',' and '.' floating point separator without regard to the locale. It does, however, enforce proper LC_NUMERIC responses. Let's look on this commit as an interim solution until Jaromir can create that proposed 'fp_decode' function. Who knows, he might even borrow some of our mkfloat(). [ An aside: the coreutils sleep and timeout programs ] [ claim to permit floating point arguments. However, ] [ neither one will accept the comma separator should ] [ the locale be a country that in fact uses a comma. ] [ In other words, with this commit we are way ahead! ] Reference(s): http://www.freelists.org/post/procps/topwatch-floating-point-input http://www.freelists.org/post/procps/topwatch-floating-point-input,1 Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
parent
cec1976511
commit
f7b84f45c7
50
top/top.c
50
top/top.c
@ -1349,6 +1349,21 @@ static inline const char *hex_make (KLONG num, int noz) {
|
|||||||
} // end: hex_make
|
} // end: hex_make
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make locale aware float (but maybe restrict to whole numbers). */
|
||||||
|
static int mkfloat (const char *str, float *num, int whole) {
|
||||||
|
char *ep;
|
||||||
|
|
||||||
|
if (whole)
|
||||||
|
*num = (float)strtol(str, &ep, 0);
|
||||||
|
else
|
||||||
|
*num = strtof(str, &ep);
|
||||||
|
if (ep != str && *ep == '\0' && *num < MAXINT)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
} // end: mkfloat
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This sructure is hung from a WIN_t when other filtering is active */
|
* This sructure is hung from a WIN_t when other filtering is active */
|
||||||
struct osel_s {
|
struct osel_s {
|
||||||
@ -3640,7 +3655,6 @@ static void parse_args (char **args) {
|
|||||||
. we tolerate NO whitespace and NO switches -- maybe too tolerant? */
|
. we tolerate NO whitespace and NO switches -- maybe too tolerant? */
|
||||||
static const char numbs_str[] = "+,-.0123456789";
|
static const char numbs_str[] = "+,-.0123456789";
|
||||||
float tmp_delay = MAXFLOAT;
|
float tmp_delay = MAXFLOAT;
|
||||||
char *p;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
while (*args) {
|
while (*args) {
|
||||||
@ -3648,6 +3662,8 @@ static void parse_args (char **args) {
|
|||||||
|
|
||||||
while (*cp) {
|
while (*cp) {
|
||||||
char ch;
|
char ch;
|
||||||
|
float tmp;
|
||||||
|
|
||||||
switch ((ch = *cp)) {
|
switch ((ch = *cp)) {
|
||||||
case '\0':
|
case '\0':
|
||||||
break;
|
break;
|
||||||
@ -3668,9 +3684,10 @@ static void parse_args (char **args) {
|
|||||||
if (cp[1]) ++cp;
|
if (cp[1]) ++cp;
|
||||||
else if (*args) cp = *args++;
|
else if (*args) cp = *args++;
|
||||||
else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
|
else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
|
||||||
/* a negative delay will be dealt with shortly... */
|
if (!mkfloat(cp, &tmp_delay, 0))
|
||||||
if (1 != sscanf(cp, "%f", &tmp_delay))
|
|
||||||
error_exit(fmtmk(N_fmt(BAD_delayint_fmt), cp));
|
error_exit(fmtmk(N_fmt(BAD_delayint_fmt), cp));
|
||||||
|
if (0 > tmp_delay)
|
||||||
|
error_exit(N_txt(DELAY_badarg_txt));
|
||||||
break;
|
break;
|
||||||
case 'H':
|
case 'H':
|
||||||
Thread_mode = 1;
|
Thread_mode = 1;
|
||||||
@ -3688,8 +3705,9 @@ static void parse_args (char **args) {
|
|||||||
if (cp[1]) cp++;
|
if (cp[1]) cp++;
|
||||||
else if (*args) cp = *args++;
|
else if (*args) cp = *args++;
|
||||||
else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
|
else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
|
||||||
if (1 != sscanf(cp, "%d", &Loops) || 1 > Loops)
|
if (!mkfloat(cp, &tmp, 1) || 1.0 > tmp)
|
||||||
error_exit(fmtmk(N_fmt(BAD_niterate_fmt), cp));
|
error_exit(fmtmk(N_fmt(BAD_niterate_fmt), cp));
|
||||||
|
Loops = (int)tmp;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
if (cp[1]) cp++;
|
if (cp[1]) cp++;
|
||||||
@ -3709,15 +3727,18 @@ static void parse_args (char **args) {
|
|||||||
for (i = 0; i < EU_MAXPFLGS; i++)
|
for (i = 0; i < EU_MAXPFLGS; i++)
|
||||||
puts(N_col(i));
|
puts(N_col(i));
|
||||||
bye_bye(NULL);
|
bye_bye(NULL);
|
||||||
case 'p':
|
case 'p': {
|
||||||
|
int pid; char *p;
|
||||||
if (Curwin->usrseltyp) error_exit(N_txt(SELECT_clash_txt));
|
if (Curwin->usrseltyp) error_exit(N_txt(SELECT_clash_txt));
|
||||||
do { int pid;
|
do {
|
||||||
if (cp[1]) cp++;
|
if (cp[1]) cp++;
|
||||||
else if (*args) cp = *args++;
|
else if (*args) cp = *args++;
|
||||||
else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
|
else error_exit(fmtmk(N_fmt(MISSING_args_fmt), ch));
|
||||||
if (Monpidsidx >= MONPIDMAX)
|
if (Monpidsidx >= MONPIDMAX)
|
||||||
error_exit(fmtmk(N_fmt(LIMIT_exceed_fmt), MONPIDMAX));
|
error_exit(fmtmk(N_fmt(LIMIT_exceed_fmt), MONPIDMAX));
|
||||||
if (1 != sscanf(cp, "%d", &pid) || 0 > pid)
|
if (1 != sscanf(cp, "%d", &pid)
|
||||||
|
|| strpbrk(cp, "+-.")
|
||||||
|
|| 0 > pid)
|
||||||
error_exit(fmtmk(N_fmt(BAD_mon_pids_fmt), cp));
|
error_exit(fmtmk(N_fmt(BAD_mon_pids_fmt), cp));
|
||||||
if (!pid) pid = getpid();
|
if (!pid) pid = getpid();
|
||||||
for (i = 0; i < Monpidsidx; i++)
|
for (i = 0; i < Monpidsidx; i++)
|
||||||
@ -3727,7 +3748,7 @@ static void parse_args (char **args) {
|
|||||||
if (!(p = strchr(cp, ','))) break;
|
if (!(p = strchr(cp, ','))) break;
|
||||||
cp = p;
|
cp = p;
|
||||||
} while (*cp);
|
} while (*cp);
|
||||||
break;
|
} break;
|
||||||
case 's':
|
case 's':
|
||||||
Secure_mode = 1;
|
Secure_mode = 1;
|
||||||
break;
|
break;
|
||||||
@ -3751,15 +3772,14 @@ static void parse_args (char **args) {
|
|||||||
Width_mode = -1;
|
Width_mode = -1;
|
||||||
if (cp[1]) pn = &cp[1];
|
if (cp[1]) pn = &cp[1];
|
||||||
else if (*args) { pn = *args; ai = 1; }
|
else if (*args) { pn = *args; ai = 1; }
|
||||||
if (pn && !(ci = strspn(pn, "0123456789"))) { ai = 0; pn = NULL; }
|
if (pn && !(ci = strspn(pn, numbs_str))) { ai = 0; pn = NULL; }
|
||||||
if (pn && (1 != sscanf(pn, "%d", &Width_mode)
|
if (pn && (!mkfloat(pn, &tmp, 1) || tmp < W_MIN_COL))
|
||||||
|| Width_mode < W_MIN_COL))
|
error_exit(fmtmk(N_fmt(BAD_widtharg_fmt), pn));
|
||||||
error_exit(fmtmk(N_fmt(BAD_widtharg_fmt), pn, W_MIN_COL-1));
|
Width_mode = (int)tmp;
|
||||||
cp++;
|
cp++;
|
||||||
args += ai;
|
args += ai;
|
||||||
if (pn) cp = pn + ci;
|
if (pn) cp = pn + ci;
|
||||||
continue;
|
} continue;
|
||||||
}
|
|
||||||
default :
|
default :
|
||||||
error_exit(fmtmk(N_fmt(UNKNOWN_opts_fmt)
|
error_exit(fmtmk(N_fmt(UNKNOWN_opts_fmt)
|
||||||
, *cp, Myname, N_txt(USAGE_abbrev_txt)));
|
, *cp, Myname, N_txt(USAGE_abbrev_txt)));
|
||||||
@ -3776,8 +3796,6 @@ static void parse_args (char **args) {
|
|||||||
if (MAXFLOAT > tmp_delay) {
|
if (MAXFLOAT > tmp_delay) {
|
||||||
if (Secure_mode)
|
if (Secure_mode)
|
||||||
error_exit(N_txt(DELAY_secure_txt));
|
error_exit(N_txt(DELAY_secure_txt));
|
||||||
if (0 > tmp_delay)
|
|
||||||
error_exit(N_txt(DELAY_badarg_txt));
|
|
||||||
Rc.delay_time = tmp_delay;
|
Rc.delay_time = tmp_delay;
|
||||||
}
|
}
|
||||||
} // end: parse_args
|
} // end: parse_args
|
||||||
|
@ -682,6 +682,7 @@ typedef struct WIN_t {
|
|||||||
//atic float get_float (const char *prompt);
|
//atic float get_float (const char *prompt);
|
||||||
//atic int get_int (const char *prompt);
|
//atic int get_int (const char *prompt);
|
||||||
//atic inline const char *hex_make (KLONG num, int noz);
|
//atic inline const char *hex_make (KLONG num, int noz);
|
||||||
|
//atic int mkfloat (const char *str, float *num, int whole);
|
||||||
//atic void osel_clear (WIN_t *q);
|
//atic void osel_clear (WIN_t *q);
|
||||||
//atic inline int osel_matched (const WIN_t *q, FLG_t enu, const char *str);
|
//atic inline int osel_matched (const WIN_t *q, FLG_t enu, const char *str);
|
||||||
//atic const char *user_certify (WIN_t *q, const char *str, char typ);
|
//atic const char *user_certify (WIN_t *q, const char *str, char typ);
|
||||||
|
@ -312,7 +312,7 @@ static void build_norm_nlstab (void) {
|
|||||||
Norm_nlstab[LIMIT_exceed_fmt] = _("pid limit (%d) exceeded");
|
Norm_nlstab[LIMIT_exceed_fmt] = _("pid limit (%d) exceeded");
|
||||||
Norm_nlstab[BAD_mon_pids_fmt] = _("bad pid '%s'");
|
Norm_nlstab[BAD_mon_pids_fmt] = _("bad pid '%s'");
|
||||||
Norm_nlstab[MISSING_args_fmt] = _("-%c requires argument");
|
Norm_nlstab[MISSING_args_fmt] = _("-%c requires argument");
|
||||||
Norm_nlstab[BAD_widtharg_fmt] = _("bad width arg '%s', must > %d");
|
Norm_nlstab[BAD_widtharg_fmt] = _("bad width arg '%s'");
|
||||||
Norm_nlstab[UNKNOWN_opts_fmt] = _(""
|
Norm_nlstab[UNKNOWN_opts_fmt] = _(""
|
||||||
"unknown option '%c'\n"
|
"unknown option '%c'\n"
|
||||||
"Usage:\n %s%s");
|
"Usage:\n %s%s");
|
||||||
|
Loading…
Reference in New Issue
Block a user