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