+#include "stdio.h"
+#include "awk.def"
+#include "awk.h"
+#include "ctype.h"
+
+FILE *infile = NULL;
+char *file;
+#define RECSIZE 512
+char record[RECSIZE];
+char fields[RECSIZE];
+
+#define MAXFLD 50
+int donefld; /* 1 = implies rec broken into fields */
+int donerec; /* 1 = record is valid (no flds have changed) */
+int mustfld; /* 1 = NF seen, so always break*/
+
+#define FINIT {0, NULL, 0.0, FLD|STR}
+cell fldtab[MAXFLD] = { /*room for fields */
+ { "$record", record, 0.0, STR|FLD},
+ FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
+ FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
+ FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
+ FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
+ FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
+ FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
+ FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT
+};
+int maxfld = 0; /* last used field */
+
+
+getrec()
+{
+ register char *rr;
+ extern int svargc;
+ extern char **svargv;
+ register c, sep;
+
+ dprintf("**RS=%o, **FS=%o\n", **RS, **FS, NULL);
+ donefld = 0;
+ donerec = 1;
+ record[0] = 0;
+ while (svargc > 0) {
+ dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL);
+ if (infile == NULL) { /* have to open a new file */
+ if (member('=', *svargv)) { /* it's a var=value argument */
+ setclvar(*svargv);
+ svargv++;
+ svargc--;
+ continue;
+ }
+ *FILENAME = file = *svargv;
+ dprintf("opening file %s\n", file, NULL, NULL);
+ if (*file == '-')
+ infile = stdin;
+ else if ((infile = fopen(file, "r")) == NULL)
+ error(FATAL, "can't open %s", file);
+ }
+ if ((sep = **RS) == 0)
+ sep = '\n';
+ for (rr = record; ; ) {
+ for (; (c=getc(infile)) != sep && c != EOF; *rr++ = c)
+ ;
+ if (**RS == sep || c == EOF)
+ break;
+ if ((c = getc(infile)) == '\n' || c == EOF) /* 2 in a row */
+ break;
+ *rr++ = '\n';
+ *rr++ = c;
+ }
+ if (rr > record+RECSIZE)
+ error(FATAL, "record `%.20s...' too long", record);
+ *rr = 0;
+ if (mustfld)
+ fldbld();
+ if (c != EOF) /* normal record */
+ return(1);
+ /* EOF arrived on this file; set up next */
+ if (infile != stdin)
+ fclose(infile);
+ infile = NULL;
+ svargc--;
+ svargv++;
+ }
+ return(0); /* true end of file */
+}
+
+setclvar(s) /* set var=value from s */
+char *s;
+{
+ char *p;
+ cell *q;
+
+ for (p=s; *p != '='; p++)
+ ;
+ *p++ = 0;
+ q = setsymtab(s, tostring(p), 0.0, STR, symtab);
+ setsval(q, p);
+ dprintf("command line set %s to |%s|\n", s, p, NULL);
+}
+
+fldbld()
+{
+ register char *r, *fr, sep;
+ int i, j;
+
+ r = record;
+ fr = fields;
+ if ((sep = **FS) == ' ')
+ for (i = 0; ; ) {
+ while (*r == ' ' || *r == '\t' || *r == '\n')
+ r++;
+ if (*r == 0)
+ break;
+ i++;
+ if (i >= MAXFLD)
+ error(FATAL, "record `%.20s...' has too many fields", record);
+ if (!(fldtab[i].tval&FLD))
+ xfree(fldtab[i].sval);
+ fldtab[i].sval = fr;
+ fldtab[i].tval = FLD | STR;
+ do
+ *fr++ = *r++;
+ while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
+ *fr++ = 0;
+ }
+ else
+ for (i = 0; ; ) {
+ i++;
+ if (i >= MAXFLD)
+ error(FATAL, "record `%.20s...' has too many fields", record);
+ if (!(fldtab[i].tval&FLD))
+ xfree(fldtab[i].sval);
+ fldtab[i].sval = fr;
+ fldtab[i].tval = FLD | STR;
+ while (*r != sep && *r != '\n' && *r != '\0') /* \n always a separator */
+ *fr++ = *r++;
+ *fr++ = '\0';
+ if (*r == 0) break;
+ r++;
+ }
+ *fr = 0;
+ for (j=maxfld; j>i; j--) { /* clean out junk from previous record */
+ if (!(fldtab[j].tval&FLD))
+ xfree(fldtab[j].sval);
+ fldtab[j].tval = STR | FLD;
+ fldtab[j].sval = NULL;
+ }
+ maxfld = i;
+ donefld = 1;
+ for(i=1; i<=maxfld; i++)
+ if(isnumber(fldtab[i].sval))
+ { fldtab[i].fval = atof(fldtab[i].sval);
+ fldtab[i].tval |= NUM;
+ }
+ setfval(lookup("NF", symtab), (awkfloat) maxfld);
+ if (dbg)
+ for (i = 0; i <= maxfld; i++)
+ printf("field %d: |%s|\n", i, fldtab[i].sval);
+}
+
+recbld()
+{
+ int i;
+ register char *r, *p;
+
+ if (donefld == 0 || donerec == 1)
+ return;
+ r = record;
+ for (i = 1; i <= *NF; i++) {
+ p = getsval(&fldtab[i]);
+ while (*r++ = *p++)
+ ;
+ *(r-1) = **OFS;
+ }
+ *(r-1) = '\0';
+ dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
+ recloc->tval = STR | FLD;
+ dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
+ if (r > record+RECSIZE)
+ error(FATAL, "built giant record `%.20s...'", record);
+ dprintf("recbld = |%s|\n", record, NULL, NULL);
+}
+
+cell *fieldadr(n)
+{
+ if (n >= MAXFLD)
+ error(FATAL, "trying to access field %d", n);
+ return(&fldtab[n]);
+}
+
+int errorflag = 0;
+
+yyerror(s) char *s; {
+ fprintf(stderr, "awk: %s near line %d\n", s, lineno);
+ errorflag = 2;
+}
+
+error(f, s, a1, a2, a3, a4, a5, a6, a7) {
+ fprintf(stderr, "awk: ");
+ fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
+ fprintf(stderr, "\n");
+ if (*NR > 0)
+ fprintf(stderr, " record number %g\n", *NR);
+ if (f)
+ exit(2);
+}
+
+PUTS(s) char *s; {
+ dprintf("%s\n", s, NULL, NULL);
+}
+
+#define MAXEXPON 38 /* maximum exponenet for fp number */
+
+isnumber(s)
+register char *s;
+{
+ register d1, d2;
+ int point;
+ char *es;
+
+ d1 = d2 = point = 0;
+ while (*s == ' ' || *s == '\t' || *s == '\n')
+ s++;
+ if (*s == '\0')
+ return(0); /* empty stuff isn't number */
+ if (*s == '+' || *s == '-')
+ s++;
+ if (!isdigit(*s) && *s != '.')
+ return(0);
+ if (isdigit(*s)) {
+ d1++;
+ do {
+ s++;
+ } while (isdigit(*s));
+ }
+ if (*s == '.') {
+ point++;
+ s++;
+ }
+ if (d1 == 0 && point == 0)
+ return(0);
+ if (isdigit(*s)) {
+ d2++;
+ do {
+ s++;
+ } while (isdigit(*s));
+ }
+ if (!(d1 || point && d2))
+ return(0);
+ if (*s == 'e' || *s == 'E') {
+ s++;
+ if (*s == '+' || *s == '-')
+ s++;
+ if (!isdigit(*s))
+ return(0);
+ es = s;
+ do {
+ s++;
+ } while (isdigit(*s));
+ if (s - es > 2)
+ return(0);
+ else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON)
+ return(0);
+ }
+ while (*s == ' ' || *s == '\t' || *s == '\n')
+ s++;
+ if (*s == '\0')
+ return(1);
+ else
+ return(0);
+}
+/*
+isnumber(s) char *s; {return(0);}
+*/