1*48236Sbostic /*- 2*48236Sbostic * Copyright (c) 1991 The Regents of the University of California. 3*48236Sbostic * All rights reserved. 4*48236Sbostic * 5*48236Sbostic * %sccs.include.proprietary.c% 6*48236Sbostic */ 7*48236Sbostic 814473Ssam #ifndef lint 9*48236Sbostic static char sccsid[] = "@(#)lib.c 4.9 (Berkeley) 04/17/91"; 10*48236Sbostic #endif /* not lint */ 116671Smckusick 1246819Sbostic #include <stdarg.h> 136671Smckusick #include "stdio.h" 146671Smckusick #include "awk.def" 156671Smckusick #include "awk.h" 166671Smckusick #include "ctype.h" 176671Smckusick 1832354Sbostic extern FILE *yyin; /* lex input file */ 1944021Sbostic extern char *lexprog; /* points to program argument if it exists */ 206671Smckusick FILE *infile = NULL; 216671Smckusick char *file; 226671Smckusick #define RECSIZE (5 * 512) 236671Smckusick char record[RECSIZE]; 246671Smckusick char fields[RECSIZE]; 2510794Ssam char EMPTY[] = ""; 266671Smckusick 276671Smckusick #define MAXFLD 100 286671Smckusick int donefld; /* 1 = implies rec broken into fields */ 296671Smckusick int donerec; /* 1 = record is valid (no flds have changed) */ 306671Smckusick int mustfld; /* 1 = NF seen, so always break*/ 316671Smckusick 3210794Ssam #define FINIT {EMPTY, EMPTY, 0.0, FLD|STR} 336671Smckusick cell fldtab[MAXFLD] = { /*room for fields */ 346671Smckusick { "$record", record, 0.0, STR|FLD}, 3531035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 3631035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 3731035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 3831035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 3931035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 4031035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 4131035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 4231035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 4331035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 446671Smckusick }; 456671Smckusick int maxfld = 0; /* last used field */ 466671Smckusick 476671Smckusick 486671Smckusick getrec() 496671Smckusick { 506671Smckusick register char *rr; 516671Smckusick extern int svargc; 526671Smckusick extern char **svargv; 536671Smckusick register c, sep; 546671Smckusick 556671Smckusick dprintf("**RS=%o, **FS=%o\n", **RS, **FS, NULL); 566671Smckusick donefld = 0; 576671Smckusick donerec = 1; 586671Smckusick record[0] = 0; 596671Smckusick while (svargc > 0) { 606671Smckusick dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL); 616671Smckusick if (infile == NULL) { /* have to open a new file */ 626671Smckusick if (member('=', *svargv)) { /* it's a var=value argument */ 636671Smckusick setclvar(*svargv); 646671Smckusick svargv++; 656671Smckusick svargc--; 666671Smckusick continue; 676671Smckusick } 686671Smckusick *FILENAME = file = *svargv; 696671Smckusick dprintf("opening file %s\n", file, NULL, NULL); 7032354Sbostic if (*file == '-') { 7144021Sbostic if (yyin == stdin && ! lexprog) 7232354Sbostic error(FATAL, "standard input already used for reading commands"); 7332354Sbostic else 7432354Sbostic infile = stdin; 7532354Sbostic } 766671Smckusick else if ((infile = fopen(file, "r")) == NULL) 776671Smckusick error(FATAL, "can't open %s", file); 786671Smckusick } 796671Smckusick if ((sep = **RS) == 0) 806671Smckusick sep = '\n'; 816671Smckusick for (rr = record; ; ) { 826671Smckusick for (; (c=getc(infile)) != sep && c != EOF; *rr++ = c) 836671Smckusick ; 846671Smckusick if (**RS == sep || c == EOF) 856671Smckusick break; 866671Smckusick if ((c = getc(infile)) == '\n' || c == EOF) /* 2 in a row */ 876671Smckusick break; 886671Smckusick *rr++ = '\n'; 896671Smckusick *rr++ = c; 906671Smckusick } 916671Smckusick if (rr > record+RECSIZE) 926671Smckusick error(FATAL, "record `%.20s...' too long", record); 936671Smckusick *rr = 0; 946671Smckusick if (mustfld) 956671Smckusick fldbld(); 966671Smckusick if (c != EOF || rr > record) { /* normal record */ 976671Smckusick recloc->tval &= ~NUM; 986671Smckusick recloc->tval |= STR; 996671Smckusick ++nrloc->fval; 1006671Smckusick nrloc->tval &= ~STR; 1016671Smckusick nrloc->tval |= NUM; 1026671Smckusick return(1); 1036671Smckusick } 1046671Smckusick /* EOF arrived on this file; set up next */ 1056671Smckusick if (infile != stdin) 1066671Smckusick fclose(infile); 1076671Smckusick infile = NULL; 1086671Smckusick svargc--; 1096671Smckusick svargv++; 1106671Smckusick } 1116671Smckusick return(0); /* true end of file */ 1126671Smckusick } 1136671Smckusick 1146671Smckusick setclvar(s) /* set var=value from s */ 1156671Smckusick char *s; 1166671Smckusick { 1176671Smckusick char *p; 1186671Smckusick cell *q; 1196671Smckusick 1206671Smckusick for (p=s; *p != '='; p++) 1216671Smckusick ; 1226671Smckusick *p++ = 0; 1236671Smckusick q = setsymtab(s, tostring(p), 0.0, STR, symtab); 1246671Smckusick setsval(q, p); 1256671Smckusick dprintf("command line set %s to |%s|\n", s, p, NULL); 1266671Smckusick } 1276671Smckusick 1286671Smckusick fldbld() 1296671Smckusick { 1306671Smckusick register char *r, *fr, sep; 1316671Smckusick int i, j; 1326671Smckusick 1336671Smckusick r = record; 1346671Smckusick fr = fields; 1356671Smckusick i = 0; /* number of fields accumulated here */ 1366671Smckusick if ((sep = **FS) == ' ') 1376671Smckusick for (i = 0; ; ) { 1386671Smckusick while (*r == ' ' || *r == '\t' || *r == '\n') 1396671Smckusick r++; 1406671Smckusick if (*r == 0) 1416671Smckusick break; 1426671Smckusick i++; 1436671Smckusick if (i >= MAXFLD) 1446671Smckusick error(FATAL, "record `%.20s...' has too many fields", record); 1456671Smckusick if (!(fldtab[i].tval&FLD)) 14610794Ssam strfree(fldtab[i].sval); 1476671Smckusick fldtab[i].sval = fr; 1486671Smckusick fldtab[i].tval = FLD | STR; 1496671Smckusick do 1506671Smckusick *fr++ = *r++; 1516671Smckusick while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); 1526671Smckusick *fr++ = 0; 1536671Smckusick } 1546671Smckusick else if (*r != 0) /* if 0, it's a null field */ 1556671Smckusick for (;;) { 1566671Smckusick i++; 1576671Smckusick if (i >= MAXFLD) 1586671Smckusick error(FATAL, "record `%.20s...' has too many fields", record); 1596671Smckusick if (!(fldtab[i].tval&FLD)) 16010794Ssam strfree(fldtab[i].sval); 1616671Smckusick fldtab[i].sval = fr; 1626671Smckusick fldtab[i].tval = FLD | STR; 1636671Smckusick while (*r != sep && *r != '\n' && *r != '\0') /* \n always a separator */ 1646671Smckusick *fr++ = *r++; 1656671Smckusick *fr++ = 0; 1666671Smckusick if (*r++ == 0) 1676671Smckusick break; 1686671Smckusick } 1696671Smckusick *fr = 0; 1706671Smckusick for (j=MAXFLD-1; j>i; j--) { /* clean out junk from previous record */ 1716671Smckusick if (!(fldtab[j].tval&FLD)) 17210794Ssam strfree(fldtab[j].sval); 1736671Smckusick fldtab[j].tval = STR | FLD; 17410794Ssam fldtab[j].sval = EMPTY; 1756671Smckusick } 1766671Smckusick maxfld = i; 1776671Smckusick donefld = 1; 1786671Smckusick for(i=1; i<=maxfld; i++) 1796671Smckusick if(isnumber(fldtab[i].sval)) { 1806671Smckusick fldtab[i].fval = atof(fldtab[i].sval); 1816671Smckusick fldtab[i].tval |= NUM; 1826671Smckusick } 1836671Smckusick setfval(lookup("NF", symtab, 0), (awkfloat) maxfld); 1846671Smckusick if (dbg) 1856671Smckusick for (i = 0; i <= maxfld; i++) 1866671Smckusick printf("field %d: |%s|\n", i, fldtab[i].sval); 1876671Smckusick } 1886671Smckusick 1896671Smckusick recbld() 1906671Smckusick { 1916671Smckusick int i; 1926671Smckusick register char *r, *p; 1936671Smckusick 1946671Smckusick if (donefld == 0 || donerec == 1) 1956671Smckusick return; 1966671Smckusick r = record; 1976671Smckusick for (i = 1; i <= *NF; i++) { 1986671Smckusick p = getsval(&fldtab[i]); 1996671Smckusick while (*r++ = *p++) 2006671Smckusick ; 2016671Smckusick *(r-1) = **OFS; 2026671Smckusick } 2036671Smckusick *(r-1) = '\0'; 2046671Smckusick dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL); 2056671Smckusick recloc->tval = STR | FLD; 2066671Smckusick dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL); 2076671Smckusick if (r > record+RECSIZE) 2086671Smckusick error(FATAL, "built giant record `%.20s...'", record); 2096671Smckusick dprintf("recbld = |%s|\n", record, NULL, NULL); 2106671Smckusick } 2116671Smckusick 2126671Smckusick cell *fieldadr(n) 2136671Smckusick { 2146671Smckusick if (n >= MAXFLD) 2156671Smckusick error(FATAL, "trying to access field %d", n); 2166671Smckusick return(&fldtab[n]); 2176671Smckusick } 2186671Smckusick 2196671Smckusick int errorflag = 0; 2206671Smckusick 2216671Smckusick yyerror(s) char *s; { 2226671Smckusick fprintf(stderr, "awk: %s near line %d\n", s, lineno); 2236671Smckusick errorflag = 2; 2246671Smckusick } 2256671Smckusick 22646819Sbostic error(isfatal, fmt) 22746819Sbostic int isfatal; 22846819Sbostic char *fmt; 22946819Sbostic { 23046819Sbostic va_list ap; 23146819Sbostic 23246819Sbostic va_start(ap, fmt); 23346819Sbostic (void)fprintf(stderr, "awk: "); 23446819Sbostic (void)vfprintf(stderr, fmt, ap); 23546819Sbostic va_end(ap); 23646819Sbostic (void)fprintf(stderr, "\n"); 23717190Sralph if (NR && *NR > 0) 23846819Sbostic (void)fprintf(stderr, " record number %g\n", *NR); 23946819Sbostic if (isfatal) 2406671Smckusick exit(2); 2416671Smckusick } 2426671Smckusick 2436671Smckusick PUTS(s) char *s; { 2446671Smckusick dprintf("%s\n", s, NULL, NULL); 2456671Smckusick } 2466671Smckusick 2476671Smckusick #define MAXEXPON 38 /* maximum exponenet for fp number */ 2486671Smckusick 2496671Smckusick isnumber(s) 2506671Smckusick register char *s; 2516671Smckusick { 2526671Smckusick register d1, d2; 2536671Smckusick int point; 2546671Smckusick char *es; 2556671Smckusick 25610794Ssam if (s == NULL) 25710794Ssam return (0); 2586671Smckusick d1 = d2 = point = 0; 2596671Smckusick while (*s == ' ' || *s == '\t' || *s == '\n') 2606671Smckusick s++; 2616671Smckusick if (*s == '\0') 2626671Smckusick return(0); /* empty stuff isn't number */ 2636671Smckusick if (*s == '+' || *s == '-') 2646671Smckusick s++; 2656671Smckusick if (!isdigit(*s) && *s != '.') 2666671Smckusick return(0); 2676671Smckusick if (isdigit(*s)) { 2686671Smckusick do { 2696671Smckusick d1++; 2706671Smckusick s++; 2716671Smckusick } while (isdigit(*s)); 2726671Smckusick } 2736671Smckusick if(d1 >= MAXEXPON) 2746671Smckusick return(0); /* too many digits to convert */ 2756671Smckusick if (*s == '.') { 2766671Smckusick point++; 2776671Smckusick s++; 2786671Smckusick } 2796671Smckusick if (isdigit(*s)) { 2806671Smckusick d2++; 2816671Smckusick do { 2826671Smckusick s++; 2836671Smckusick } while (isdigit(*s)); 2846671Smckusick } 2856671Smckusick if (!(d1 || point && d2)) 2866671Smckusick return(0); 2876671Smckusick if (*s == 'e' || *s == 'E') { 2886671Smckusick s++; 2896671Smckusick if (*s == '+' || *s == '-') 2906671Smckusick s++; 2916671Smckusick if (!isdigit(*s)) 2926671Smckusick return(0); 2936671Smckusick es = s; 2946671Smckusick do { 2956671Smckusick s++; 2966671Smckusick } while (isdigit(*s)); 2976671Smckusick if (s - es > 2) 2986671Smckusick return(0); 2996671Smckusick else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON) 3006671Smckusick return(0); 3016671Smckusick } 3026671Smckusick while (*s == ' ' || *s == '\t' || *s == '\n') 3036671Smckusick s++; 3046671Smckusick if (*s == '\0') 3056671Smckusick return(1); 3066671Smckusick else 3076671Smckusick return(0); 3086671Smckusick } 3096671Smckusick /* 3106671Smckusick isnumber(s) char *s; {return(0);} 3116671Smckusick */ 312