--- ray/src/cal/rcalc.c 2003/05/25 05:27:16 1.4 +++ ray/src/cal/rcalc.c 2014/03/09 20:07:27 1.23 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rcalc.c,v 1.4 2003/05/25 05:27:16 greg Exp $"; +static const char RCSid[] = "$Id: rcalc.c,v 1.23 2014/03/09 20:07:27 greg Exp $"; #endif /* * rcalc.c - record calculator program. @@ -7,26 +7,22 @@ static const char RCSid[] = "$Id: rcalc.c,v 1.4 2003/0 * 9/11/87 */ -#include - #include - #include - #include +#include "platform.h" +#include "rterror.h" +#include "rtmisc.h" +#include "rtio.h" #include "calcomp.h" -#ifdef CPM -#define getc agetc /* text files only, right? */ -#endif - #define isnum(c) (isdigit(c) || (c)=='-' || (c)=='.' \ || (c)=='+' || (c)=='e' || (c)=='E') #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 */ @@ -58,8 +54,20 @@ struct field { /* record format struc #define savqstr(s) strcpy(emalloc(strlen(s)+1),s) #define freqstr(s) efree(s) -extern char *strcpy(), *emalloc(), *savestr(); -struct strvar *getsvar(); +static int getinputrec(FILE *fp); +static void scaninp(void), advinp(void), resetinp(void); +static void putrec(void), putout(void), nbsynch(void); +static int getrec(void); +static void execute(char *file); +static void initinp(FILE *fp); +static void svpreset(char *eqn); +static void readfmt(char *spec, int output); +static int readfield(char **pp); +static int getfield(struct field *f); +static void chanset(int n, double v); +static void bchanset(int n, double v); +static struct strvar* getsvar(char *svname); +static double l_in(char *); struct field *inpfmt = NULL; /* input record format */ struct field *outfmt = NULL; /* output record structure */ @@ -67,10 +75,12 @@ struct strvar *svhead = NULL; /* string variables */ 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 */ @@ -88,10 +98,13 @@ struct { } ipb; /* circular lookahead buffer */ -main(argc, argv) -int argc; -char *argv[]; +int +main( +int argc, +char *argv[] +) { + char *fpath; int i; esupport |= E_VARIABLE|E_FUNCTION|E_INCHAN|E_OUTCHAN|E_RCONST; @@ -101,6 +114,7 @@ char *argv[]; biggerlib(); #endif varset("PI", ':', 3.14159265358979323846); + funset("in", 1, '=', &l_in); for (i = 1; i < argc && argv[i][0] == '-'; i++) switch (argv[i][1]) { @@ -110,6 +124,9 @@ char *argv[]; case 'l': igneol = !igneol; break; + case 'p': + passive = !passive; + break; case 't': sepchar = argv[i][2]; break; @@ -117,7 +134,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); @@ -128,23 +153,39 @@ char *argv[]; case 'i': switch (argv[i][2]) { case '\0': + itype = 'a'; nbicols = 0; readfmt(argv[++i], 0); 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 nbicols = 1; + if (nbicols*sizeof(double) > INBSIZ) { + eputs(argv[0]); + eputs(": too many input columns\n"); + quit(1); + } 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; + nbicols = 1; + if (nbicols*sizeof(float) > INBSIZ) { + eputs(argv[0]); + eputs(": too many input columns\n"); + quit(1); + } break; default: goto userr; @@ -153,18 +194,20 @@ char *argv[]; case 'o': switch (argv[i][2]) { case '\0': - bocols = 0; + otype = 'a'; readfmt(argv[++i], 1); 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': @@ -177,16 +220,24 @@ char *argv[]; userr: eputs("Usage: "); eputs(argv[0]); -eputs(" [-b][-l][-n][-w][-u][-tS][-s svar=sval][-e expr][-f source][-i infmt][-o outfmt] [file]\n"); +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(); @@ -197,10 +248,12 @@ eputs(" [-b][-l][-n][-w][-u][-tS][-s svar=sval][-e exp execute(argv[i]); quit(0); + return 0; /* pro forma return */ } -nbsynch() /* non-blank starting synch character */ +static void +nbsynch(void) /* non-blank starting synch character */ { if (inpfmt == NULL || (inpfmt->type & F_TYP) != T_LIT) return; @@ -211,24 +264,35 @@ nbsynch() /* non-blank starting synch ch } -int -getinputrec(fp) /* get next input record */ -FILE *fp; +static int +getinputrec( /* get next input record */ +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 (fread(inpbuf, sizeof(double), nbicols, fp) != nbicols) + return(0); + if (itype == 'D') + swap64(inpbuf, nbicols); + return(1); + } + if (tolower(itype) == 'f') { + if (fread(inpbuf, sizeof(float), nbicols, fp) != nbicols) + return(0); + if (itype == 'F') + swap32(inpbuf, nbicols); + return(1); + } return(fgets(inpbuf, INBSIZ, fp) != NULL); } -execute(file) /* process a file */ -char *file; +static void +execute( /* process a file */ +char *file +) { int conditional = vardefined("cond"); long nrecs = 0; @@ -242,46 +306,83 @@ 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; } } fclose(fp); } -putout() /* produce an output record */ +static void +putout(void) /* produce an output record */ { - extern void chanset(), bchanset(); 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); } +static double +l_in(char *funame) /* function call for $channel */ +{ + int n; + char *cp; + /* get argument as integer */ + n = (int)(argument(1) + .5); + if (n != 0) /* return channel value */ + return(chanvalue(n)); + /* determine number of channels */ + if (noinput || inpfmt != NULL) + return(0); + if (nbicols) + return(nbicols); + cp = inpbuf; /* need to count */ + for (n = 0; *cp; ) + if (blnkeq && isspace(sepchar)) { + while (isspace(*cp)) + cp++; + n += *cp != '\0'; + while (*cp && !isspace(*cp)) + cp++; + } else { + n += *cp != '\n'; + while (*cp && *cp++ != sepchar) + ; + } + return(n); +} + double -chanvalue(n) /* return value for column n */ -int n; +chanvalue( /* return value for column n */ +int n +) { int i; - register char *cp; + char *cp; if (noinput || inpfmt != NULL) { eputs("no column input\n"); @@ -291,15 +392,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); } @@ -329,9 +428,10 @@ int n; void -chanset(n, v) /* output column n */ -int n; -double v; +chanset( /* output column n */ +int n, +double v +) { if (colpos == 0) /* no leading separator */ colpos = 1; @@ -344,34 +444,46 @@ double v; void -bchanset(n, v) /* output binary channel n */ -int n; -double v; +bchanset( /* output binary channel n */ +int n, +double v +) { static char zerobuf[sizeof(double)]; + float fval = v; while (++colpos < n) fwrite(zerobuf, - bocols>0 ? sizeof(double) : sizeof(float), + tolower(otype)=='d' ? sizeof(double) : sizeof(float), 1, stdout); - if (bocols > 0) + switch (otype) { + case 'D': + swap64((char *)&v, 1); + /* fall through */ + case 'd': fwrite(&v, sizeof(double), 1, stdout); - else { - float fval = v; + break; + case 'F': + swap32((char *)&fval, 1); + /* fall through */ + case 'f': fwrite(&fval, sizeof(float), 1, stdout); + break; } } -readfmt(spec, output) /* read record format */ -char *spec; -int output; +static void +readfmt( /* read record format */ +char *spec, +int output +) { int fd; 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 == '$') @@ -384,7 +496,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) @@ -396,7 +508,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) { @@ -429,13 +541,14 @@ int output; } -int -readfield(pp) /* get next field in format */ -register char **pp; +static int +readfield( /* get next field in format */ +char **pp +) { int type = F_NUL; int width = 0; - register char *cp; + char *cp; cp = inpbuf; while (cp < &inpbuf[INBSIZ-1] && **pp != '\0') { @@ -496,10 +609,11 @@ register char **pp; struct strvar * -getsvar(svname) /* get string variable */ -char *svname; +getsvar( /* get string variable */ +char *svname +) { - register struct strvar *sv; + struct strvar *sv; for (sv = svhead; sv != NULL; sv = sv->next) if (!strcmp(sv->name, svname)) @@ -513,11 +627,13 @@ char *svname; } -svpreset(eqn) /* preset a string variable */ -char *eqn; +static void +svpreset( /* preset a string variable */ +char *eqn +) { - register struct strvar *sv; - register char *val; + struct strvar *sv; + char *val; for (val = eqn; *val != '='; val++) if (!*val) @@ -533,9 +649,10 @@ char *eqn; } -clearrec() /* clear input record variables */ +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) { @@ -552,47 +669,52 @@ clearrec() /* clear input record variables */ } -getrec() /* get next record from file */ +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)) - scaninp(); + 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) break; if (f == NULL) { - advinp(); + advinp(); /* got one! */ return(1); } - resetinp(); + resetinp(); /* eat false start */ if (eatline) { /* eat rest of line */ while (ipb.chr != '\n') { if (ipb.chr == EOF) return(0); - scaninp(); + resetinp(); } - scaninp(); - advinp(); + resetinp(); } } return(0); } -getfield(f) /* get next field */ -register struct field *f; +static int +getfield( /* get next field */ +struct field *f +) { - static char buf[MAXWORD+1]; /* no recursion! */ + 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: @@ -621,7 +743,7 @@ register struct field *f; delim = f->next->f.sl[0]; cp = buf; do { - if (ipb.chr == EOF) + if (ipb.chr == EOF || ipb.chr == '\n') inword = 0; else if (blnkeq && delim != EOF) inword = isblnk(delim) ? @@ -633,7 +755,7 @@ register struct field *f; *cp++ = ipb.chr; scaninp(); } - } while (inword && cp < &buf[MAXWORD]); + } while (inword && cp < &buf[RMAXWORD]); *cp = '\0'; if (f->f.sv->val == NULL) f->f.sv->val = savqstr(buf); /* first setting */ @@ -662,7 +784,7 @@ register struct field *f; *cp++ = ipb.chr; scaninp(); } - } while (inword && cp < &buf[MAXWORD]); + } while (inword && cp < &buf[RMAXWORD]); *cp = '\0'; d = np==NULL ? 0. : atof(np); if (!vardefined(f->f.nv)) @@ -672,14 +794,16 @@ register struct field *f; return(-1); /* doesn't match! */ return(0); } + return -1; /* pro forma return */ } -putrec() /* output a record */ +static void +putrec(void) /* output a record */ { char fmt[32]; - register int n; - register struct field *f; + int n; + struct field *f; int adlast, adnext; adlast = 0; @@ -725,8 +849,9 @@ putrec() /* output a re } -initinp(fp) /* prepare lookahead buffer */ -FILE *fp; +static void +initinp(FILE *fp) /* prepare lookahead buffer */ + { ipb.fin = fp; ipb.beg = ipb.end = inpbuf; @@ -736,7 +861,8 @@ FILE *fp; } -scaninp() /* scan next character */ +static void +scaninp(void) /* scan next character */ { if (ipb.chr == EOF) return; @@ -755,18 +881,22 @@ scaninp() /* scan next character } -advinp() /* move home to current position */ +static void +advinp(void) /* move home to current position */ { ipb.beg = ipb.pos; } -resetinp() /* rewind position and advance 1 */ +static void +resetinp(void) /* rewind position and advance 1 */ { if (ipb.beg == NULL) /* full */ ipb.beg = ipb.end; ipb.pos = ipb.beg; ipb.chr = *ipb.pos; + if (passive) /* transmit unmatched character? */ + fputc(ipb.chr, stdout); if (++ipb.beg >= &inpbuf[INBSIZ]) ipb.beg = inpbuf; scaninp(); @@ -774,16 +904,14 @@ resetinp() /* rewind position and void -eputs(msg) -char *msg; +eputs(char *msg) { fputs(msg, stderr); } void -wputs(msg) -char *msg; +wputs(char *msg) { if (!nowarn) eputs(msg); @@ -791,8 +919,7 @@ char *msg; void -quit(code) -int code; +quit(int code) { exit(code); }