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