--- ray/src/cal/rcalc.c 2004/06/09 16:00:13 1.13 +++ ray/src/cal/rcalc.c 2016/08/18 00:52:47 1.27 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rcalc.c,v 1.13 2004/06/09 16:00:13 greg Exp $"; +static const char RCSid[] = "$Id: rcalc.c,v 1.27 2016/08/18 00:52:47 greg Exp $"; #endif /* * rcalc.c - record calculator program. @@ -8,9 +8,6 @@ static const char RCSid[] = "$Id: rcalc.c,v 1.13 2004/ */ #include -#include -#include -#include #include #include @@ -25,7 +22,7 @@ static const char RCSid[] = "$Id: rcalc.c,v 1.13 2004/ #define isblnk(c) (igneol ? isspace(c) : (c)==' '||(c)=='\t') -#define INBSIZ 4096 /* longest record */ +#define INBSIZ 16384 /* longest record */ #define MAXCOL 32 /* number of columns recorded */ /* field type specifications */ @@ -76,13 +73,17 @@ struct field *inpfmt = NULL; /* input record format struct field *outfmt = NULL; /* output record structure */ struct strvar *svhead = NULL; /* string variables */ +long incnt = 0; /* limit number of input records? */ +long outcnt = 0; /* limit number of output records? */ + int blnkeq = 1; /* blanks compare equal? */ int igneol = 0; /* ignore end of line? */ int passive = 0; /* passive mode (transmit unmatched input) */ char sepchar = '\t'; /* input/output separator */ int noinput = 0; /* no input records? */ +int itype = 'a'; /* input type (a/f/F/d/D) */ int nbicols = 0; /* number of binary input columns */ -int bocols = 0; /* produce binary output columns */ +int otype = 'a'; /* output format (a/f/F/d/D) */ char inpbuf[INBSIZ]; /* input buffer */ double colval[MAXCOL]; /* input column values */ unsigned long colflg = 0; /* column retrieved flags */ @@ -106,6 +107,7 @@ int argc, char *argv[] ) { + char *fpath; int i; esupport |= E_VARIABLE|E_FUNCTION|E_INCHAN|E_OUTCHAN|E_RCONST; @@ -135,7 +137,15 @@ char *argv[] svpreset(argv[++i]); break; case 'f': - fcompile(argv[++i]); + fpath = getpath(argv[++i], getrlibpath(), 0); + if (fpath == NULL) { + eputs(argv[0]); + eputs(": cannot find file '"); + eputs(argv[i]); + eputs("'\n"); + quit(1); + } + fcompile(fpath); break; case 'e': scompile(argv[++i], NULL, 0); @@ -146,13 +156,20 @@ char *argv[] case 'i': switch (argv[i][2]) { case '\0': + itype = 'a'; nbicols = 0; readfmt(argv[++i], 0); break; + case 'n': + incnt = atol(argv[++i]); + break; case 'a': + itype = 'a'; nbicols = 0; break; case 'd': + case 'D': + itype = argv[i][2]; if (isdigit(argv[i][3])) nbicols = atoi(argv[i]+3); else @@ -164,11 +181,13 @@ char *argv[] } break; case 'f': + case 'F': + itype = argv[i][2]; if (isdigit(argv[i][3])) - nbicols = -atoi(argv[i]+3); + nbicols = atoi(argv[i]+3); else - nbicols = -1; - if (-nbicols*sizeof(float) > INBSIZ) { + nbicols = 1; + if (nbicols*sizeof(float) > INBSIZ) { eputs(argv[0]); eputs(": too many input columns\n"); quit(1); @@ -181,18 +200,23 @@ char *argv[] case 'o': switch (argv[i][2]) { case '\0': - bocols = 0; + otype = 'a'; readfmt(argv[++i], 1); break; + case 'n': + outcnt = atol(argv[++i]); + break; case 'a': - bocols = 0; + otype = 'a'; break; case 'd': - bocols = 1; - break; + case 'D': case 'f': - bocols = -1; + case 'F': + otype = argv[i][2]; break; + default: + goto userr; } break; case 'w': @@ -208,13 +232,21 @@ char *argv[] eputs(" [-b][-l][-n][-p][-w][-u][-tS][-s svar=sval][-e expr][-f source][-i infmt][-o outfmt] [file]\n"); quit(1); } - + if (otype != 'a') + SET_FILE_BINARY(stdout); +#ifdef getc_unlocked /* avoid lock/unlock overhead */ + flockfile(stdout); +#endif if (noinput) { /* produce a single output record */ + if (i < argc) { + eputs(argv[0]); + eputs(": file argument(s) incompatible with -n\n"); + quit(1); + } eclock++; putout(); quit(0); } - if (blnkeq) /* for efficiency */ nbsynch(); @@ -248,12 +280,20 @@ FILE *fp { if (inpfmt != NULL) return(getrec()); - if (nbicols > 0) - return(fread(inpbuf, sizeof(double), - nbicols, fp) == nbicols); - if (nbicols < 0) - return(fread(inpbuf, sizeof(float), - -nbicols, fp) == -nbicols); + if (tolower(itype) == 'd') { + if (getbinary(inpbuf, sizeof(double), nbicols, fp) != nbicols) + return(0); + if (itype == 'D') + swap64(inpbuf, nbicols); + return(1); + } + if (tolower(itype) == 'f') { + if (getbinary(inpbuf, sizeof(float), nbicols, fp) != nbicols) + return(0); + if (itype == 'F') + swap32(inpbuf, nbicols); + return(1); + } return(fgets(inpbuf, INBSIZ, fp) != NULL); } @@ -275,17 +315,27 @@ char *file eputs(": cannot open\n"); quit(1); } + if (itype != 'a') + SET_FILE_BINARY(fp); +#ifdef getc_unlocked /* avoid lock/unlock overhead */ + flockfile(fp); +#endif if (inpfmt != NULL) initinp(fp); while (getinputrec(fp)) { varset("recno", '=', (double)++nrecs); + varset("outno", '=', (double)(nout+1)); colflg = 0; eclock++; if (!conditional || varvalue("cond") > 0.0) { - varset("outno", '=', (double)++nout); putout(); + ++nout; } + if (incnt && nrecs >= incnt) + break; + if (outcnt && nout >= outcnt) + break; } fclose(fp); } @@ -298,11 +348,11 @@ putout(void) /* produce an output recor colpos = 0; if (outfmt != NULL) putrec(); - else if (bocols) - chanout(bchanset); - else + else if (otype == 'a') chanout(chanset); - if (colpos && !bocols) + else + chanout(bchanset); + if (colpos && otype == 'a') putchar('\n'); if (unbuff) fflush(stdout); @@ -313,7 +363,7 @@ static double l_in(char *funame) /* function call for $channel */ { int n; - register char *cp; + char *cp; /* get argument as integer */ n = (int)(argument(1) + .5); if (n != 0) /* return channel value */ @@ -321,10 +371,8 @@ l_in(char *funame) /* function call for $channel */ /* determine number of channels */ if (noinput || inpfmt != NULL) return(0); - if (nbicols > 0) + if (nbicols) return(nbicols); - if (nbicols < 0) - return(-nbicols); cp = inpbuf; /* need to count */ for (n = 0; *cp; ) if (blnkeq && isspace(sepchar)) { @@ -347,7 +395,7 @@ int n ) { int i; - register char *cp; + char *cp; if (noinput || inpfmt != NULL) { eputs("no column input\n"); @@ -357,15 +405,13 @@ int n eputs("illegal channel number\n"); quit(1); } - if (nbicols > 0) { + if (nbicols) { if (n > nbicols) return(0.0); - cp = inpbuf + (n-1)*sizeof(double); - return(*(double *)cp); - } - if (nbicols < 0) { - if (n > -nbicols) - return(0.0); + if (tolower(itype) == 'd') { + cp = inpbuf + (n-1)*sizeof(double); + return(*(double *)cp); + } cp = inpbuf + (n-1)*sizeof(float); return(*(float *)cp); } @@ -417,16 +463,25 @@ double v ) { static char zerobuf[sizeof(double)]; + float fval = v; while (++colpos < n) - fwrite(zerobuf, - bocols>0 ? sizeof(double) : sizeof(float), + putbinary(zerobuf, + tolower(otype)=='d' ? sizeof(double) : sizeof(float), 1, stdout); - if (bocols > 0) - fwrite(&v, sizeof(double), 1, stdout); - else { - float fval = v; - fwrite(&fval, sizeof(float), 1, stdout); + switch (otype) { + case 'D': + swap64((char *)&v, 1); + /* fall through */ + case 'd': + putbinary(&v, sizeof(double), 1, stdout); + break; + case 'F': + swap32((char *)&fval, 1); + /* fall through */ + case 'f': + putbinary(&fval, sizeof(float), 1, stdout); + break; } } @@ -441,7 +496,7 @@ int output char *inptr; struct field fmt; int res; - register struct field *f; + struct field *f; /* check for inline format */ for (inptr = spec; *inptr; inptr++) if (*inptr == '$') @@ -454,7 +509,7 @@ int output eputs(": cannot open\n"); quit(1); } - res = read(fd, inpbuf+1, INBSIZ-1); + res = read(fd, inpbuf+2, INBSIZ-2); if (res <= 0 || res >= INBSIZ-1) { eputs(spec); if (res < 0) @@ -466,7 +521,7 @@ int output quit(1); } close(fd); - (inptr=inpbuf+1)[res] = '\0'; + (inptr=inpbuf+2)[res] = '\0'; } f = &fmt; /* get fields */ while ((res = readfield(&inptr)) != F_NUL) { @@ -501,12 +556,12 @@ int output static int readfield( /* get next field in format */ -register char **pp +char **pp ) { int type = F_NUL; int width = 0; - register char *cp; + char *cp; cp = inpbuf; while (cp < &inpbuf[INBSIZ-1] && **pp != '\0') { @@ -571,7 +626,7 @@ getsvar( /* get string variabl char *svname ) { - register struct strvar *sv; + struct strvar *sv; for (sv = svhead; sv != NULL; sv = sv->next) if (!strcmp(sv->name, svname)) @@ -590,8 +645,8 @@ svpreset( /* preset a string variab char *eqn ) { - register struct strvar *sv; - register char *val; + struct strvar *sv; + char *val; for (val = eqn; *val != '='; val++) if (!*val) @@ -610,7 +665,7 @@ char *eqn static void clearrec(void) /* clear input record variables */ { - register struct field *f; + struct field *f; for (f = inpfmt; f != NULL; f = f->next) switch (f->type & F_TYP) { @@ -631,13 +686,16 @@ static int getrec(void) /* get next record from file */ { int eatline; - register struct field *f; - + struct field *f; + while (ipb.chr != EOF) { - eatline = !igneol && ipb.chr != '\n'; - if (blnkeq) /* beware of nbsynch() */ + if (blnkeq) { /* beware of nbsynch() */ while (isblnk(ipb.chr)) resetinp(); + if (ipb.chr == EOF) + return(0); + } + eatline = (!igneol && ipb.chr != '\n'); clearrec(); /* start with fresh record */ for (f = inpfmt; f != NULL; f = f->next) if (getfield(f) == -1) @@ -662,14 +720,14 @@ getrec(void) /* get next record from file */ static int getfield( /* get next field */ -register struct field *f +struct field *f ) { static char buf[RMAXWORD+1]; /* no recursion! */ int delim, inword; double d; char *np; - register char *cp; + char *cp; switch (f->type & F_TYP) { case T_LIT: @@ -756,10 +814,11 @@ register struct field *f static void putrec(void) /* output a record */ { - char fmt[32]; - register int n; - register struct field *f; + char fmt[32], typ[16]; + int n; + struct field *f; int adlast, adnext; + double dv, av; adlast = 0; for (f = outfmt; f != NULL; f = f->next) { @@ -790,13 +849,24 @@ putrec(void) /* output break; case T_NUM: n = f->type & F_WID; + dv = evalue(f->f.ne); + av = fabs(dv); + if (n <= 9) + strcpy(typ, "g"); + else + sprintf(typ, ".%de", n-5); + if (av < 1L<<31) { + long iv = (int)(av + .5); + if (iv && fabs(av-iv) <= av*1e-14) + strcpy(typ, ".0f"); + } if (adlast && adnext) - strcpy(fmt, "%g"); + sprintf(fmt, "%%%s", typ); else if (adlast) - sprintf(fmt, "%%-%dg", n); + sprintf(fmt, "%%-%d%s", n, typ); else - sprintf(fmt, "%%%dg", n); - printf(fmt, evalue(f->f.ne)); + sprintf(fmt, "%%%d%s", n, typ); + printf(fmt, dv); adlast = 1; break; }