top: honor old rcfiles after change to field additions

This patch will restore the previously abandoned older
rcfile support. To be honest, I wasn't sure this would
be possible given the vast difference between formats.

But after some very intense hacking our newlib top can
again fully support seamless migration from some older
'char' based file to this new 'int' based file format.

[ top even supports a 20+ year old 3.2.8 config file ]

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2022-03-13 00:00:00 -06:00 committed by Craig Small
parent 40040adf34
commit 980dc08a5b
2 changed files with 144 additions and 10 deletions

123
top/top.c
View File

@ -3582,6 +3582,99 @@ static void before (char *me) {
} // end: before
/*
* A configs_file *Helper* function responsible for transorming
* a 3.2.8 - 3.3.17 format 'fieldscur' into our integer based format */
static int cfg_xform (WIN_t *q, char *flds, const char *defs) {
#define CVTon(c) ((c) |= 0x80)
static struct {
int old, new;
} flags_tab[] = {
#define old_View_NOBOLD 0x000001
#define old_VISIBLE_tsk 0x000008
#define old_Qsrt_NORMAL 0x000010
#define old_Show_HICOLS 0x000200
#define old_Show_THREAD 0x010000
{ old_View_NOBOLD, View_NOBOLD },
{ old_VISIBLE_tsk, Show_TASKON },
{ old_Qsrt_NORMAL, Qsrt_NORMAL },
{ old_Show_HICOLS, Show_HICOLS },
{ old_Show_THREAD, 0 }
#undef old_View_NOBOLD
#undef old_VISIBLE_tsk
#undef old_Qsrt_NORMAL
#undef old_Show_HICOLS
#undef old_Show_THREAD
};
static char null_flds[] = "abcdefghijklmnopqrstuvwxyz";
static const char fields_src[] = CVT_FORMER;
char fields_dst[PFLAGSSIZ], *p1, *p2;
int c, f, i, x, *pn;
if (Rc.id == 'a') {
// first we'll touch up this window's winflags ...
x = q->rc.winflags;
q->rc.winflags = 0;
for (i = 0; i < MAXTBL(flags_tab); i++) {
if (x & flags_tab[i].old) {
x &= ~flags_tab[i].old;
q->rc.winflags |= flags_tab[i].new;
}
}
q->rc.winflags |= x;
// now let's convert old top's more limited fields ...
if (CVT_FLDMAX > strlen(flds))
return 1;
// here we convert old 3.2.8 top's more limited fields ...
strcpy(fields_dst, fields_src);
/* all other fields represent the 'on' state with a capitalized version
of a particular qwerty key. for the 2 additional suse out-of-memory
fields it makes perfect sense to do the exact opposite, doesn't it?
in any case, we must turn them 'off' temporarily ... */
if ((p1 = strchr(flds, '['))) *p1 = '{';
if ((p2 = strchr(flds, '\\'))) *p2 = '|';
for (i = 0; i < CVT_FLDMAX; i++) {
c = flds[i];
x = tolower(c) - 'a';
if (x < 0 || x >= CVT_FLDMAX)
return 1;
fields_dst[i] = fields_src[x];
if (isupper(c))
CVTon(fields_dst[i]);
}
// if we turned any suse only fields off, turn 'em back on OUR way ...
if (p1) CVTon(fields_dst[p1 - flds]);
if (p2) CVTon(fields_dst[p2 - flds]);
// next, we must adjust the old sort field enum ...
x = q->rc.sortindx;
c = null_flds[x];
q->rc.sortindx = 0;
if ((p1 = memchr(flds, c, CVT_FLDMAX))
|| ((p1 = memchr(flds, toupper(c), CVT_FLDMAX)))) {
x = p1 - flds;
q->rc.sortindx = (fields_dst[x] & 0x7f) - FLD_OFFSET;
}
// now we're in a 3.3.0 format (soon to be transformed) ...
strcpy(flds, fields_dst);
}
// lastly, let's attend to the 3.3.0 - 3.3.17 fieldcurs format ...
pn = &q->rc.fieldscur[0];
x = strlen(defs);
for (i = 0; i < x; i++) {
f = ((unsigned char)flds[i] & 0x7f);
f = f << 1;
if ((unsigned char)flds[i] & 0x80) f |= 0x01;
*(pn + i) = f;
}
return 0;
#undef CVTon
} // end: cfg_xform
/*
* A configs_file *Helper* function responsible for reading
* and validating a configuration file's 'Inspection' entries */
@ -3719,7 +3812,7 @@ end_oops:
* a configuration file (personal or system-wide default) */
static const char *configs_file (FILE *fp, const char *name, float *delay) {
char fbuf[LRGBUFSIZ];
int i, tmp_whole, tmp_fract;
int i, n, tmp_whole, tmp_fract;
const char *p = NULL;
p = fmtmk(N_fmt(RC_bad_files_fmt), name);
@ -3729,7 +3822,7 @@ static const char *configs_file (FILE *fp, const char *name, float *delay) {
, &Rc.id, &Rc.mode_altscr, &Rc.mode_irixps, &tmp_whole, &tmp_fract, &i)) {
return p;
}
if (Rc.id != RCF_VERSION_ID)
if (Rc.id < 'a' || Rc.id > RCF_VERSION_ID)
return p;
if (Rc.mode_altscr < 0 || Rc.mode_altscr > 1)
return p;
@ -3745,15 +3838,19 @@ static const char *configs_file (FILE *fp, const char *name, float *delay) {
*delay = (float)tmp_whole + (float)tmp_fract / 1000;
for (i = 0 ; i < GROUPSMAX; i++) {
int j, n, x;
static const char *def_flds[] = { DEF_FORMER, JOB_FORMER, MEM_FORMER, USR_FORMER };
int j, x;
WIN_t *w = &Winstk[i];
p = fmtmk(N_fmt(RC_bad_entry_fmt), i+1, name);
if (1 != fscanf(fp, "%3s\tfieldscur=", w->rc.winname))
return p;
for (j = 0; j < mlen(w->rc.fieldscur); j++) {
if (Rc.id < RCF_XFORMED_ID)
fscanf(fp, "%s\n", fbuf);
else {
for (j = 0; ; j++)
if (1 != fscanf(fp, "%d", &w->rc.fieldscur[j]))
return p;
break;
}
// be tolerant of missing release 3.3.10 graph modes additions
@ -3787,13 +3884,29 @@ static const char *configs_file (FILE *fp, const char *name, float *delay) {
switch (Rc.id) {
case 'a': // 3.2.8 (former procps)
// fall through
case 'f': // 3.3.0 thru 3.3.3 (ng)
SETw(w, Show_JRNUMS);
// fall through
case 'g': // from 3.3.4 thru 3.3.8
scat(fbuf, RCF_PLUS_H);
// fall through
case 'h': // this is release 3.3.9
w->rc.graph_cpus = w->rc.graph_mems = 0;
// these next 2 are really global, but best documented here
Rc.summ_mscale = Rc.task_mscale = SK_Kb;
// fall through
case 'i': // from 3.3.10 thru 3.3.16
scat(fbuf, RCF_PLUS_J);
w->rc.double_up = w->rc.combine_cpus = 0;
// fall through
case 'j': // this is release 3.3.17
if (cfg_xform(w, fbuf, def_flds[i]))
return p;
Rc.tics_scaled = 0;
// fall through
case 'k': // current RCF_VERSION_ID
// fall through
default:
if (mlen(w->rc.fieldscur) < EU_MAXPFLGS)
return p;

View File

@ -506,6 +506,13 @@ typedef struct WIN_t {
#define SYS_RCRESTRICT "/etc/toprc"
#define SYS_RCDEFAULTS "/etc/topdefaultrc"
#define RCF_EYECATCHER "Config File (Linux processes with windows)\n"
#define RCF_PLUS_H "\\]^_`abcdefghij"
#define RCF_PLUS_J "klmnopqrstuvwxyz"
// this next guy must never, ever change
// ( we transition from'char' to 'int' )
#define RCF_XFORMED_ID 'k'
// this next guy is incremented when columns change
// ( to prevent older top versions from accessing )
#define RCF_VERSION_ID 'k'
#define FLD_OFFSET ( (int)'%' )
@ -513,14 +520,27 @@ typedef struct WIN_t {
/* The default fields displayed and their order,
if nothing is specified by the loser, oops user. */
#define OLD_FIELDS { \
#ifdef ORIG_TOPDEFS
#define DEF_FORMER "¥¨³´»½ÀÄ·º¹Å&')*+,-./012568<>?ABCFGHIJKLMNOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
#else
#define DEF_FORMER "¥&K¨³´»½@·º¹56ÄFÅ')*+,-./0128<>?ABCGHIJLMNOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
#endif
/* Pre-configured windows/field groups */
#define JOB_FORMER "¥¦¹·º(³´Ä»½@<§Å)*+,-./012568>?ABCFGHIJKLMNOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
#define MEM_FORMER "¥º»<½¾¿ÀÁMBNÃD34·Å&'()*+,-./0125689FGHIJKLOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
#define USR_FORMER "¥¦§¨ª°¹·ºÄÅ)+,-./1234568;<=>?@ABCFGHIJKLMNOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
// old top fields ( 'a'-'z' ) in positions 0-25
// other suse old top fields ( '{|' ) in positions 26-27
#define CVT_FORMER "%&*'(-0346789:;<=>?@ACDEFGML)+,./125BHIJKNOPQRSTUVWXYZ[" RCF_PLUS_H RCF_PLUS_J
#define CVT_FLDMAX 26
#ifdef ORIG_TOPDEFS
#define DEF_FIELDS { \
75, 81, 103, 105, 119, 123, 129, 137, 111, 117, 115, 139, 76, 78, 82, 84, 86, 88, 90, 92, \
94, 96, 98, 100, 106, 108, 112, 120, 124, 126, 130, 132, 134, 140, 142, 144, 146, 148, 150, 152, \
154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, \
194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, \
234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272 }
#ifdef ORIG_TOPDEFS
#define DEF_FIELDS OLD_FIELDS
#else
#define DEF_FIELDS { \
75, 76, 150, 81, 103, 105, 119, 123, 128, 111, 117, 115, 106, 108, 137, 140, 139, 78, 82, 84, \
@ -681,6 +701,7 @@ typedef struct WIN_t {
//atic inline int osel_matched (const WIN_t *q, FLG_t enu, const char *str);
/*------ Startup routines ----------------------------------------------*/
//atic void before (char *me);
//atic int cfg_xform (WIN_t *q, char *flds, const char *defs);
//atic int config_insp (FILE *fp, char *buf, size_t size);
//atic int config_osel (FILE *fp, char *buf, size_t size);
//atic const char *configs_file (FILE *fp, const char *name, float *delay);