497 lines
9.5 KiB
C
497 lines
9.5 KiB
C
/* Copyright (c) 1984 AT&T */
|
|
/* All Rights Reserved */
|
|
|
|
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
|
|
/* The copyright notice above does not evidence any */
|
|
/* actual or intended publication of such source code. */
|
|
|
|
/* #ident "@(#)sa:sagb.c 1.5" */
|
|
#ident "$Header: /proj/irix6.5.7m/isms/eoe/cmd/sa/RCS/sagb.c,v 1.3 1986/09/17 22:29:17 scott Exp $"
|
|
/* sagb.c 1.5 of 5/13/85 */
|
|
#include "saghdr.h"
|
|
|
|
combine(p, pn)
|
|
struct p *p;
|
|
int pn;
|
|
|
|
{
|
|
int a, b, c;
|
|
int i;
|
|
int qi = 0;
|
|
float vala, valb;
|
|
struct array *ara, *arb, *arc;
|
|
struct array *popar();
|
|
char *strcpy();
|
|
|
|
ara = p->c[pn].dptr;
|
|
arb = p->c[pn+1].dptr;
|
|
arc = popar();
|
|
if(DEBUG){fprintf(stderr, "combine p->c[%d].name:%s & p->c[%d].name:%s\n",
|
|
pn, p->c[pn].name, pn+1, p->c[pn+1].name);
|
|
fprintf(stderr, " alias ara->hname:%s arb->hname:%s\n",
|
|
ara->hname, arb->hname);
|
|
}
|
|
|
|
for(a=b=c=0; a<NPTS && b<NPTS && c<NPTS; )
|
|
{
|
|
if((ara->ent[a].hr == 0) || (arb->ent[b].hr == 0))
|
|
{ /* End of file */
|
|
arc->ent[c].hr = 0;
|
|
break;
|
|
}
|
|
|
|
if((ara->ent[0].hr < 0) || (arb->ent[0].hr < 0))
|
|
{ /* One or both is a constant */
|
|
if((ara->ent[a].val <= -1000) || (arb->ent[b].val <= -1000))
|
|
arc->ent[c].val = -1000;
|
|
else
|
|
switch (p->c[pn].op)
|
|
{
|
|
case '+':
|
|
arc->ent[c].val = ara->ent[a].val + arb->ent[b].val;
|
|
break;
|
|
case '-':
|
|
arc->ent[c].val = ara->ent[a].val - arb->ent[b].val;
|
|
break;
|
|
case '*':
|
|
arc->ent[c].val = ara->ent[a].val * arb->ent[b].val;
|
|
break;
|
|
case '/':
|
|
if(arb->ent[b].val != 0)
|
|
arc->ent[c].val = ara->ent[a].val / arb->ent[b].val;
|
|
else
|
|
arc->ent[c].val = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if(ara->ent[0].hr >= 0)
|
|
{ /* a is variable */
|
|
strcpy(arc->ent[c].tm, ara->ent[a].tm);
|
|
strcpy(arc->ent[c].qfld, ara->ent[a].qfld);
|
|
arc->ent[c].hr = ara->ent[a].hr;
|
|
a++;
|
|
}
|
|
else if(arb->ent[0].hr >= 0)
|
|
{ /* b is variable */
|
|
strcpy(arc->ent[c].tm, arb->ent[b].tm);
|
|
strcpy(arc->ent[c].qfld, arb->ent[b].qfld);
|
|
arc->ent[c].hr = arb->ent[b].hr;
|
|
b++;
|
|
}
|
|
else
|
|
{ /* Both are constant */
|
|
strcpy(arc->ent[c].tm, ara->ent[a].tm);
|
|
strcpy(arc->ent[c].qfld, ara->ent[a].qfld);
|
|
arc->ent[c].hr = ara->ent[a].hr;
|
|
a++;
|
|
b++;
|
|
}
|
|
c++;
|
|
continue;
|
|
}
|
|
|
|
if(ara->ent[a].hr < arb->ent[b].hr)
|
|
{ /* b missing */
|
|
arc->ent[c].hr = ara->ent[a].hr;
|
|
strcpy(arc->ent[c].tm, ara->ent[a].tm);
|
|
strcpy(arc->ent[c].qfld, ara->ent[a].qfld);
|
|
vala = ara->ent[a].val;
|
|
valb = 0.;
|
|
a++;
|
|
}
|
|
else if(ara->ent[a].hr > arb->ent[b].hr)
|
|
{ /* a missing */
|
|
arc->ent[c].hr = arb->ent[b].hr;
|
|
strcpy(arc->ent[c].tm, arb->ent[b].tm);
|
|
strcpy(arc->ent[c].qfld, arb->ent[b].qfld);
|
|
valb = arb->ent[b].val;
|
|
vala = 0.;
|
|
b++;
|
|
}
|
|
else
|
|
{ /* a & b hrs equal */
|
|
arc->ent[c].hr = ara->ent[a].hr;
|
|
strcpy(arc->ent[c].tm, ara->ent[a].tm);
|
|
vala = ara->ent[a].val;
|
|
valb = arb->ent[b].val;
|
|
/*
|
|
** Test which index can be incremented without
|
|
** incurring a change in ..hr
|
|
*/
|
|
if((ara->ent[a+1].hr == ara->ent[a].hr)
|
|
&& (arb->ent[b+1].hr != arb->ent[b].hr))
|
|
{ /* a free, b constrained */
|
|
strcpy(arc->ent[c].qfld, ara->ent[a].qfld);
|
|
qi = 0;
|
|
a++;
|
|
}
|
|
else if((ara->ent[a+1].hr != ara->ent[a].hr)
|
|
&& (arb->ent[b+1].hr == arb->ent[b].hr))
|
|
{ /* a constrained, b free */
|
|
strcpy(arc->ent[c].qfld, arb->ent[b].qfld);
|
|
qi = 1;
|
|
b++;
|
|
}
|
|
else
|
|
{ /* Both free or both constrained */
|
|
if(qi == 1)
|
|
strcpy(arc->ent[c].qfld, arb->ent[b].qfld);
|
|
else
|
|
strcpy(arc->ent[c].qfld, ara->ent[a].qfld);
|
|
a++;
|
|
b++;
|
|
}
|
|
}
|
|
if((vala <= -1000) || (valb <= -1000))
|
|
arc->ent[c].val = -1000;
|
|
else
|
|
switch (p->c[pn].op)
|
|
{
|
|
case '+':
|
|
arc->ent[c].val = vala + valb;
|
|
break;
|
|
case '-':
|
|
arc->ent[c].val = vala - valb;
|
|
break;
|
|
case '*':
|
|
arc->ent[c].val = vala * valb;
|
|
break;
|
|
case '/':
|
|
if(valb != 0)
|
|
arc->ent[c].val = vala / valb;
|
|
else
|
|
arc->ent[c].val = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
c++;
|
|
}
|
|
|
|
sprintf(arc->hname, "%s %c %s", ara->hname, p->c[pn].op, arb->hname);
|
|
if(DEBUG){printar(ara);
|
|
printar(arb);
|
|
printar(arc);
|
|
}
|
|
pushar(ara);
|
|
pushar(arb);
|
|
p->c[pn].op = p->c[pn+1].op;
|
|
p->c[pn].dptr = arc;
|
|
for(i=pn+1; i<4; i++)
|
|
{
|
|
strcpy(p->c[i].name, p->c[i+1].name);
|
|
p->c[i].op = p->c[i+1].op;
|
|
p->c[i].dptr = p->c[i+1].dptr;
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
|
|
getdata(name, array)
|
|
char *name;
|
|
struct array *array;
|
|
/*
|
|
** Extracts data from sarc[] array and puts into
|
|
** array entries. Hunts for name string among column
|
|
** headers in sarc, and copies following data items
|
|
** from corresponding field up to next "Average" line.
|
|
** Special treatment when name string contains an integer
|
|
** or "time".
|
|
*/
|
|
|
|
{
|
|
extern char fld[NFLD][FLDCH];
|
|
extern FILE *sard;
|
|
extern long sardoff;
|
|
int fnum;
|
|
char nm[18], ql[8];
|
|
int nparts;
|
|
int i, j;
|
|
int timeflg;
|
|
int hr, min, sec;
|
|
int nmloc;
|
|
double atof();
|
|
float hour;
|
|
char *strcpy();
|
|
char *strtok();
|
|
char *tok;
|
|
|
|
if(DEBUG) fprintf(stderr, "getdata-> name:%s\n", name);
|
|
if(sscanf(name,"%f", &array->ent[0].val) == 1) /* name contains a constant */
|
|
{ /* no sar data is required */
|
|
strcpy(array->ent[0].tm, "***");
|
|
strcpy(array->hname, name);
|
|
array->ent[0].hr = -1;
|
|
array->ent[0].qfld[0] = '\0';
|
|
array->ent[1].hr = 0;
|
|
return(0);
|
|
}
|
|
|
|
if(strmatch("time", name) >= 0) /* Pick up time values from */
|
|
{ /* 1st sar group - %usr */
|
|
if(DEBUG) fprintf(stderr, "name matches time\n");
|
|
strcpy(nm, "%usr");
|
|
strcpy(ql, "");
|
|
nparts = 1;
|
|
timeflg = 1;
|
|
}
|
|
else
|
|
{
|
|
nparts = 0;
|
|
timeflg = 0;
|
|
if((tok = strtok(name, "[]")) != NULL)
|
|
{
|
|
nparts = 1;
|
|
strcpy(nm, tok);
|
|
}
|
|
if((tok = strtok(0, "[]")) != NULL)
|
|
{
|
|
nparts++;
|
|
strcpy(ql, tok);
|
|
}
|
|
else
|
|
strcpy(ql, "");
|
|
}
|
|
/* fprintf(stderr, "nparts:%d nm:%s ql:%s\n", nparts, nm, ql);
|
|
*/
|
|
|
|
fseek(sard, sardoff, 0); /* seek to line 2 of sard */
|
|
while((fnum = getfld()) != EOF)
|
|
{
|
|
for(i=0; i<fnum; i++)
|
|
if(strmatch(nm, fld[i]) >= 0)
|
|
{
|
|
if(timeflg == 1)
|
|
{
|
|
nmloc = 0;
|
|
strcpy(array->hname, "time");
|
|
}
|
|
else
|
|
{
|
|
nmloc = i ;
|
|
if(nparts < 2)
|
|
strcpy(array->hname, fld[i]);
|
|
else
|
|
sprintf(array->hname, "%s[%s]",
|
|
fld[i], ql);
|
|
}
|
|
goto readin;
|
|
}
|
|
}
|
|
fprintf(stderr, "\"%s\" data not found\n", nm);
|
|
return(-1);
|
|
|
|
readin:
|
|
for(i=0; i<NPTS; )
|
|
{
|
|
if(((fnum = getfld()) == EOF)
|
|
|| (strmatch(":", fld[0]) < 0))
|
|
{
|
|
array->ent[i].hr = 0;
|
|
return(0);
|
|
}
|
|
if(DEBUG>1) {
|
|
for (j=0; j<fnum; j++)
|
|
fprintf(stderr, " %s", fld[j]);
|
|
fputc('\n', stderr);
|
|
}
|
|
sscanf(fld[0], "%d:%d:%d", &hr, &min, &sec);
|
|
hour = (float)hr + (float)min/60 + (float)sec/3600;
|
|
if(timeflg == 1)
|
|
{
|
|
strcpy(array->ent[i].tm, fld[0]);
|
|
array->ent[i].hr = hour;
|
|
array->ent[i].val = hour;
|
|
strcpy(array->ent[i].qfld, "");
|
|
i++;
|
|
continue;
|
|
}
|
|
if(strmatch("unix", fld[1]) >= 0)
|
|
{
|
|
strcpy(array->ent[i].tm, fld[0]);
|
|
array->ent[i].hr = hour;
|
|
array->ent[i].val = -1000.;
|
|
strcpy(array->ent[i].qfld, "");
|
|
i++;
|
|
continue;
|
|
}
|
|
if((nparts > 1) && (strmatch(ql, fld[1]) < 0))
|
|
continue;
|
|
|
|
strcpy(array->ent[i].tm, fld[0]);
|
|
array->ent[i].hr = hour;
|
|
array->ent[i].val = atof(fld[nmloc]);
|
|
strcpy(array->ent[i].qfld, fld[1]);
|
|
|
|
if(DEBUG>1)
|
|
fprintf(stderr, " .val:%.3f\n", array->ent[i].val);
|
|
i++;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
|
|
getfld()
|
|
/*
|
|
** Scans characters pointed to by cp;
|
|
** puts non-blank strings into fld[NFLD][FLDCH]
|
|
** up to first newline or EOF.
|
|
** Returns number of fld's filled (or EOF),
|
|
** with cp updated to next readable char.
|
|
*/
|
|
{
|
|
extern char fld[NFLD][FLDCH];
|
|
extern FILE *sard;
|
|
int fnum=0, i=0;
|
|
int c;
|
|
|
|
while((c = getc(sard)) != EOF)
|
|
switch((char)c){
|
|
case ' ':
|
|
fld[fnum][i] = '\0';
|
|
i = 0;
|
|
if(++fnum >= 9) return(fnum);
|
|
break;
|
|
case '\n':
|
|
fld[fnum][i] = '\0';
|
|
return(++fnum);
|
|
break;
|
|
default:
|
|
fld[fnum][i++] = c;
|
|
break;
|
|
}
|
|
|
|
fld[fnum][i] = '\0';
|
|
if((i == 0) && (fnum == 0)) return(EOF);
|
|
else return(++fnum);
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
|
|
static struct array stack[10];
|
|
static struct array *sp[] = {
|
|
&stack[0],
|
|
&stack[1],
|
|
&stack[2],
|
|
&stack[3],
|
|
&stack[4],
|
|
&stack[5],
|
|
&stack[6],
|
|
&stack[7],
|
|
&stack[8],
|
|
&stack[9]};
|
|
static int spn = 10;
|
|
|
|
|
|
|
|
struct array *popar()
|
|
{
|
|
if(spn > 0)
|
|
return(sp[--spn]);
|
|
else
|
|
{
|
|
fprintf(stderr, "Stack empty\n");
|
|
exit();
|
|
}
|
|
}
|
|
|
|
|
|
pushar(par)
|
|
struct array *par;
|
|
|
|
{
|
|
if(spn < 10)
|
|
{
|
|
sp[spn++] = par;
|
|
return(1);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "Stack full\n");
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
|
|
stribl(s)
|
|
char *s;
|
|
/*
|
|
** Strips leading and trailing blanks from string
|
|
** by moving string pointer to first non-blank character,
|
|
** and replacing trailing blanks with '\0'.
|
|
** Returns number of remaining characters.
|
|
*/
|
|
|
|
{
|
|
char *a, *b;
|
|
|
|
a = b = s;
|
|
while (*b == ' ') b++;
|
|
while ((*a++ = *b++) != '\0');
|
|
a--;
|
|
while (a-- > s)
|
|
if (*a != ' ') break;
|
|
else *a = '\0';
|
|
return (int)(a-s+1);
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
|
|
int strmatch (pat, targ)
|
|
char *pat, *targ;
|
|
|
|
/*
|
|
** strmatch looks for an occurrence of string pat
|
|
** inside string targ. It returns the number of
|
|
** the first starting character position (zero is valid),
|
|
** or -1 for no match.
|
|
*/
|
|
|
|
{
|
|
int i, c, ifirst;
|
|
|
|
for (ifirst=0; ; ifirst++)
|
|
{
|
|
i=0;
|
|
do
|
|
{
|
|
if(pat[i] == '\0')
|
|
return(ifirst);
|
|
if (targ[ifirst + i] == '\0')
|
|
return(-1);
|
|
c=i++;
|
|
}
|
|
while (pat[c] == targ[ifirst + c]);
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
|
|
|
|
float yrange(ff)
|
|
float ff;
|
|
{
|
|
static float ylimit[] = {1.0, 1.5, 2.5, 5.0, 10.0};
|
|
float div = 1;
|
|
int i = 0;
|
|
if (ff <= 0.) return(0);
|
|
while (ff/div > 10.) div *= 10.;
|
|
while (ff/div < 1.) div /= 10.;
|
|
while ((ff/div) > ylimit[i]) i++;
|
|
return (ylimit[i] * div);
|
|
}
|