From 2199af404a92cac238728564f2f022255c5716ce Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Sat, 28 Jun 2014 00:00:00 -0500 Subject: [PATCH] top: maximize recent locale aware numeric enhancements When startup argument parsing was recently enhanced to account for LC_NUMERIC settings, some user input logic dealing with numbers fails to exploit that capability. This patch extends such enhancements to a running top. Reference(s): commit f7b84f45c7ae99c276de9954fc16cdc4ff7f36f0 http://www.freelists.org/post/procps/topwatch-floating-point-input,2 Signed-off-by: Jim Warner --- NEWS | 1 + top/top.c | 40 +++++++++++++++++++--------------------- top/top.h | 2 +- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/NEWS b/NEWS index 33cb0bd1..83809e78 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ procps-ng-3.3.10 * top is now immune to distortions when system time is reset * top standardized the key support with prompted input * top missing summary area info added to man document, ubuntu #574624 + * top properly responds to the current locale LC_NUMERIC setting * top provides alternate graph modes for cpu states and memory usage diff --git a/top/top.c b/top/top.c index 4e8ea68b..29875374 100644 --- a/top/top.c +++ b/top/top.c @@ -1258,6 +1258,21 @@ static char *ioline (const char *prompt) { #endif + /* + * 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 routine provides the i/o in support of files whose size * cannot be determined in advance. Given a stream pointer, he'll @@ -1302,11 +1317,10 @@ static float get_float (const char *prompt) { if (line[0] == kbd_ESC || Frames_signal) return GET_NUM_ESC; if (!line[0]) return GET_NUM_NOT; // note: we're not allowing negative floats - if (strcspn(line, "+,.0123456789")) { + if (!mkfloat(line, &f, 0) || f < 0) { show_msg(N_txt(BAD_numfloat_txt)); return GET_NUM_BAD; } - sscanf(line, "%f", &f); return f; } // end: get_float @@ -1315,18 +1329,17 @@ static float get_float (const char *prompt) { * Get an integer from the user, returning INT_MIN for error */ static int get_int (const char *prompt) { char *line; - int n; + float f; line = ioline(prompt); if (line[0] == kbd_ESC || Frames_signal) return GET_NUM_ESC; if (!line[0]) return GET_NUM_NOT; // note: we've got to allow negative ints (renice) - if (strcspn(line, "-+0123456789")) { + if (!mkfloat(line, &f, 1)) { show_msg(N_txt(BAD_integers_txt)); return GET_NUM_BAD; } - sscanf(line, "%d", &n); - return n; + return (int)f; } // end: get_int @@ -1349,21 +1362,6 @@ static inline const char *hex_make (KLONG num, int noz) { } // 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 */ struct osel_s { diff --git a/top/top.h b/top/top.h index 85984019..26532f0b 100644 --- a/top/top.h +++ b/top/top.h @@ -677,12 +677,12 @@ typedef struct WIN_t { //atic int ioch (int ech, char *buf, unsigned cnt); //atic int iokey (int action); //atic char *ioline (const char *prompt); +//atic int mkfloat (const char *str, float *num, int whole); //atic int readfile (FILE *fp, char **baddr, size_t *bsize, size_t *bread); /*------ Small Utility routines ----------------------------------------*/ //atic float get_float (const char *prompt); //atic int get_int (const char *prompt); //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 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);