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