1*10794Ssam /* lib.c 4.2 83/02/09 */ 26671Smckusick 36671Smckusick #include "stdio.h" 46671Smckusick #include "awk.def" 56671Smckusick #include "awk.h" 66671Smckusick #include "ctype.h" 76671Smckusick 86671Smckusick FILE *infile = NULL; 96671Smckusick char *file; 106671Smckusick #define RECSIZE (5 * 512) 116671Smckusick char record[RECSIZE]; 126671Smckusick char fields[RECSIZE]; 13*10794Ssam char EMPTY[] = ""; 146671Smckusick 156671Smckusick #define MAXFLD 100 166671Smckusick int donefld; /* 1 = implies rec broken into fields */ 176671Smckusick int donerec; /* 1 = record is valid (no flds have changed) */ 186671Smckusick int mustfld; /* 1 = NF seen, so always break*/ 196671Smckusick 20*10794Ssam #define FINIT {EMPTY, EMPTY, 0.0, FLD|STR} 216671Smckusick cell fldtab[MAXFLD] = { /*room for fields */ 226671Smckusick { "$record", record, 0.0, STR|FLD}, 236671Smckusick FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 246671Smckusick FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 256671Smckusick FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 266671Smckusick FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 276671Smckusick FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 286671Smckusick FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 296671Smckusick FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT 306671Smckusick }; 316671Smckusick int maxfld = 0; /* last used field */ 326671Smckusick 336671Smckusick 346671Smckusick getrec() 356671Smckusick { 366671Smckusick register char *rr; 376671Smckusick extern int svargc; 386671Smckusick extern char **svargv; 396671Smckusick register c, sep; 406671Smckusick 416671Smckusick dprintf("**RS=%o, **FS=%o\n", **RS, **FS, NULL); 426671Smckusick donefld = 0; 436671Smckusick donerec = 1; 446671Smckusick record[0] = 0; 456671Smckusick while (svargc > 0) { 466671Smckusick dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL); 476671Smckusick if (infile == NULL) { /* have to open a new file */ 486671Smckusick if (member('=', *svargv)) { /* it's a var=value argument */ 496671Smckusick setclvar(*svargv); 506671Smckusick svargv++; 516671Smckusick svargc--; 526671Smckusick continue; 536671Smckusick } 546671Smckusick *FILENAME = file = *svargv; 556671Smckusick dprintf("opening file %s\n", file, NULL, NULL); 566671Smckusick if (*file == '-') 576671Smckusick infile = stdin; 586671Smckusick else if ((infile = fopen(file, "r")) == NULL) 596671Smckusick error(FATAL, "can't open %s", file); 606671Smckusick } 616671Smckusick if ((sep = **RS) == 0) 626671Smckusick sep = '\n'; 636671Smckusick for (rr = record; ; ) { 646671Smckusick for (; (c=getc(infile)) != sep && c != EOF; *rr++ = c) 656671Smckusick ; 666671Smckusick if (**RS == sep || c == EOF) 676671Smckusick break; 686671Smckusick if ((c = getc(infile)) == '\n' || c == EOF) /* 2 in a row */ 696671Smckusick break; 706671Smckusick *rr++ = '\n'; 716671Smckusick *rr++ = c; 726671Smckusick } 736671Smckusick if (rr > record+RECSIZE) 746671Smckusick error(FATAL, "record `%.20s...' too long", record); 756671Smckusick *rr = 0; 766671Smckusick if (mustfld) 776671Smckusick fldbld(); 786671Smckusick if (c != EOF || rr > record) { /* normal record */ 796671Smckusick recloc->tval &= ~NUM; 806671Smckusick recloc->tval |= STR; 816671Smckusick ++nrloc->fval; 826671Smckusick nrloc->tval &= ~STR; 836671Smckusick nrloc->tval |= NUM; 846671Smckusick return(1); 856671Smckusick } 866671Smckusick /* EOF arrived on this file; set up next */ 876671Smckusick if (infile != stdin) 886671Smckusick fclose(infile); 896671Smckusick infile = NULL; 906671Smckusick svargc--; 916671Smckusick svargv++; 926671Smckusick } 936671Smckusick return(0); /* true end of file */ 946671Smckusick } 956671Smckusick 966671Smckusick setclvar(s) /* set var=value from s */ 976671Smckusick char *s; 986671Smckusick { 996671Smckusick char *p; 1006671Smckusick cell *q; 1016671Smckusick 1026671Smckusick for (p=s; *p != '='; p++) 1036671Smckusick ; 1046671Smckusick *p++ = 0; 1056671Smckusick q = setsymtab(s, tostring(p), 0.0, STR, symtab); 1066671Smckusick setsval(q, p); 1076671Smckusick dprintf("command line set %s to |%s|\n", s, p, NULL); 1086671Smckusick } 1096671Smckusick 1106671Smckusick fldbld() 1116671Smckusick { 1126671Smckusick register char *r, *fr, sep; 1136671Smckusick int i, j; 1146671Smckusick 1156671Smckusick r = record; 1166671Smckusick fr = fields; 1176671Smckusick i = 0; /* number of fields accumulated here */ 1186671Smckusick if ((sep = **FS) == ' ') 1196671Smckusick for (i = 0; ; ) { 1206671Smckusick while (*r == ' ' || *r == '\t' || *r == '\n') 1216671Smckusick r++; 1226671Smckusick if (*r == 0) 1236671Smckusick break; 1246671Smckusick i++; 1256671Smckusick if (i >= MAXFLD) 1266671Smckusick error(FATAL, "record `%.20s...' has too many fields", record); 1276671Smckusick if (!(fldtab[i].tval&FLD)) 128*10794Ssam strfree(fldtab[i].sval); 1296671Smckusick fldtab[i].sval = fr; 1306671Smckusick fldtab[i].tval = FLD | STR; 1316671Smckusick do 1326671Smckusick *fr++ = *r++; 1336671Smckusick while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); 1346671Smckusick *fr++ = 0; 1356671Smckusick } 1366671Smckusick else if (*r != 0) /* if 0, it's a null field */ 1376671Smckusick for (;;) { 1386671Smckusick i++; 1396671Smckusick if (i >= MAXFLD) 1406671Smckusick error(FATAL, "record `%.20s...' has too many fields", record); 1416671Smckusick if (!(fldtab[i].tval&FLD)) 142*10794Ssam strfree(fldtab[i].sval); 1436671Smckusick fldtab[i].sval = fr; 1446671Smckusick fldtab[i].tval = FLD | STR; 1456671Smckusick while (*r != sep && *r != '\n' && *r != '\0') /* \n always a separator */ 1466671Smckusick *fr++ = *r++; 1476671Smckusick *fr++ = 0; 1486671Smckusick if (*r++ == 0) 1496671Smckusick break; 1506671Smckusick } 1516671Smckusick *fr = 0; 1526671Smckusick for (j=MAXFLD-1; j>i; j--) { /* clean out junk from previous record */ 1536671Smckusick if (!(fldtab[j].tval&FLD)) 154*10794Ssam strfree(fldtab[j].sval); 1556671Smckusick fldtab[j].tval = STR | FLD; 156*10794Ssam fldtab[j].sval = EMPTY; 1576671Smckusick } 1586671Smckusick maxfld = i; 1596671Smckusick donefld = 1; 1606671Smckusick for(i=1; i<=maxfld; i++) 1616671Smckusick if(isnumber(fldtab[i].sval)) { 1626671Smckusick fldtab[i].fval = atof(fldtab[i].sval); 1636671Smckusick fldtab[i].tval |= NUM; 1646671Smckusick } 1656671Smckusick setfval(lookup("NF", symtab, 0), (awkfloat) maxfld); 1666671Smckusick if (dbg) 1676671Smckusick for (i = 0; i <= maxfld; i++) 1686671Smckusick printf("field %d: |%s|\n", i, fldtab[i].sval); 1696671Smckusick } 1706671Smckusick 1716671Smckusick recbld() 1726671Smckusick { 1736671Smckusick int i; 1746671Smckusick register char *r, *p; 1756671Smckusick 1766671Smckusick if (donefld == 0 || donerec == 1) 1776671Smckusick return; 1786671Smckusick r = record; 1796671Smckusick for (i = 1; i <= *NF; i++) { 1806671Smckusick p = getsval(&fldtab[i]); 1816671Smckusick while (*r++ = *p++) 1826671Smckusick ; 1836671Smckusick *(r-1) = **OFS; 1846671Smckusick } 1856671Smckusick *(r-1) = '\0'; 1866671Smckusick dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL); 1876671Smckusick recloc->tval = STR | FLD; 1886671Smckusick dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL); 1896671Smckusick if (r > record+RECSIZE) 1906671Smckusick error(FATAL, "built giant record `%.20s...'", record); 1916671Smckusick dprintf("recbld = |%s|\n", record, NULL, NULL); 1926671Smckusick } 1936671Smckusick 1946671Smckusick cell *fieldadr(n) 1956671Smckusick { 1966671Smckusick if (n >= MAXFLD) 1976671Smckusick error(FATAL, "trying to access field %d", n); 1986671Smckusick return(&fldtab[n]); 1996671Smckusick } 2006671Smckusick 2016671Smckusick int errorflag = 0; 2026671Smckusick 2036671Smckusick yyerror(s) char *s; { 2046671Smckusick fprintf(stderr, "awk: %s near line %d\n", s, lineno); 2056671Smckusick errorflag = 2; 2066671Smckusick } 2076671Smckusick 2086671Smckusick error(f, s, a1, a2, a3, a4, a5, a6, a7) { 2096671Smckusick fprintf(stderr, "awk: "); 2106671Smckusick fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7); 2116671Smckusick fprintf(stderr, "\n"); 2126671Smckusick if (*NR > 0) 2136671Smckusick fprintf(stderr, " record number %g\n", *NR); 2146671Smckusick if (f) 2156671Smckusick exit(2); 2166671Smckusick } 2176671Smckusick 2186671Smckusick PUTS(s) char *s; { 2196671Smckusick dprintf("%s\n", s, NULL, NULL); 2206671Smckusick } 2216671Smckusick 2226671Smckusick #define MAXEXPON 38 /* maximum exponenet for fp number */ 2236671Smckusick 2246671Smckusick isnumber(s) 2256671Smckusick register char *s; 2266671Smckusick { 2276671Smckusick register d1, d2; 2286671Smckusick int point; 2296671Smckusick char *es; 2306671Smckusick 231*10794Ssam if (s == NULL) 232*10794Ssam return (0); 2336671Smckusick d1 = d2 = point = 0; 2346671Smckusick while (*s == ' ' || *s == '\t' || *s == '\n') 2356671Smckusick s++; 2366671Smckusick if (*s == '\0') 2376671Smckusick return(0); /* empty stuff isn't number */ 2386671Smckusick if (*s == '+' || *s == '-') 2396671Smckusick s++; 2406671Smckusick if (!isdigit(*s) && *s != '.') 2416671Smckusick return(0); 2426671Smckusick if (isdigit(*s)) { 2436671Smckusick do { 2446671Smckusick d1++; 2456671Smckusick s++; 2466671Smckusick } while (isdigit(*s)); 2476671Smckusick } 2486671Smckusick if(d1 >= MAXEXPON) 2496671Smckusick return(0); /* too many digits to convert */ 2506671Smckusick if (*s == '.') { 2516671Smckusick point++; 2526671Smckusick s++; 2536671Smckusick } 2546671Smckusick if (isdigit(*s)) { 2556671Smckusick d2++; 2566671Smckusick do { 2576671Smckusick s++; 2586671Smckusick } while (isdigit(*s)); 2596671Smckusick } 2606671Smckusick if (!(d1 || point && d2)) 2616671Smckusick return(0); 2626671Smckusick if (*s == 'e' || *s == 'E') { 2636671Smckusick s++; 2646671Smckusick if (*s == '+' || *s == '-') 2656671Smckusick s++; 2666671Smckusick if (!isdigit(*s)) 2676671Smckusick return(0); 2686671Smckusick es = s; 2696671Smckusick do { 2706671Smckusick s++; 2716671Smckusick } while (isdigit(*s)); 2726671Smckusick if (s - es > 2) 2736671Smckusick return(0); 2746671Smckusick else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON) 2756671Smckusick return(0); 2766671Smckusick } 2776671Smckusick while (*s == ' ' || *s == '\t' || *s == '\n') 2786671Smckusick s++; 2796671Smckusick if (*s == '\0') 2806671Smckusick return(1); 2816671Smckusick else 2826671Smckusick return(0); 2836671Smckusick } 2846671Smckusick /* 2856671Smckusick isnumber(s) char *s; {return(0);} 2866671Smckusick */ 287