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