148236Sbostic /*-
248236Sbostic * Copyright (c) 1991 The Regents of the University of California.
348236Sbostic * All rights reserved.
448236Sbostic *
548236Sbostic * %sccs.include.proprietary.c%
648236Sbostic */
748236Sbostic
814473Ssam #ifndef lint
9*60482Sbostic static char sccsid[] = "@(#)lib.c 4.11 (Berkeley) 05/26/93";
1048236Sbostic #endif /* not lint */
116671Smckusick
1258334Storek #ifdef __STDC__
1346819Sbostic #include <stdarg.h>
1458334Storek #else
1558334Storek #include <varargs.h>
1658334Storek #endif
176671Smckusick #include "stdio.h"
186671Smckusick #include "awk.def"
196671Smckusick #include "awk.h"
206671Smckusick #include "ctype.h"
216671Smckusick
2258334Storek int error __P((int, const char *, ...));
2358334Storek
2432354Sbostic extern FILE *yyin; /* lex input file */
2544021Sbostic extern char *lexprog; /* points to program argument if it exists */
266671Smckusick FILE *infile = NULL;
276671Smckusick char *file;
286671Smckusick #define RECSIZE (5 * 512)
296671Smckusick char record[RECSIZE];
306671Smckusick char fields[RECSIZE];
3110794Ssam char EMPTY[] = "";
326671Smckusick
336671Smckusick #define MAXFLD 100
346671Smckusick int donefld; /* 1 = implies rec broken into fields */
356671Smckusick int donerec; /* 1 = record is valid (no flds have changed) */
366671Smckusick int mustfld; /* 1 = NF seen, so always break*/
376671Smckusick
3810794Ssam #define FINIT {EMPTY, EMPTY, 0.0, FLD|STR}
396671Smckusick cell fldtab[MAXFLD] = { /*room for fields */
406671Smckusick { "$record", record, 0.0, STR|FLD},
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,
4431035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4531035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4631035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4731035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4831035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
4931035Sbostic FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT,
506671Smckusick };
516671Smckusick int maxfld = 0; /* last used field */
526671Smckusick
536671Smckusick
getrec()546671Smckusick getrec()
556671Smckusick {
566671Smckusick register char *rr;
576671Smckusick extern int svargc;
586671Smckusick extern char **svargv;
596671Smckusick register c, sep;
606671Smckusick
616671Smckusick dprintf("**RS=%o, **FS=%o\n", **RS, **FS, NULL);
626671Smckusick donefld = 0;
636671Smckusick donerec = 1;
646671Smckusick record[0] = 0;
656671Smckusick while (svargc > 0) {
666671Smckusick dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL);
676671Smckusick if (infile == NULL) { /* have to open a new file */
686671Smckusick if (member('=', *svargv)) { /* it's a var=value argument */
696671Smckusick setclvar(*svargv);
706671Smckusick svargv++;
716671Smckusick svargc--;
726671Smckusick continue;
736671Smckusick }
746671Smckusick *FILENAME = file = *svargv;
756671Smckusick dprintf("opening file %s\n", file, NULL, NULL);
7632354Sbostic if (*file == '-') {
7744021Sbostic if (yyin == stdin && ! lexprog)
7832354Sbostic error(FATAL, "standard input already used for reading commands");
7932354Sbostic else
8032354Sbostic infile = stdin;
8132354Sbostic }
826671Smckusick else if ((infile = fopen(file, "r")) == NULL)
836671Smckusick error(FATAL, "can't open %s", file);
846671Smckusick }
856671Smckusick if ((sep = **RS) == 0)
866671Smckusick sep = '\n';
876671Smckusick for (rr = record; ; ) {
886671Smckusick for (; (c=getc(infile)) != sep && c != EOF; *rr++ = c)
896671Smckusick ;
906671Smckusick if (**RS == sep || c == EOF)
916671Smckusick break;
926671Smckusick if ((c = getc(infile)) == '\n' || c == EOF) /* 2 in a row */
936671Smckusick break;
946671Smckusick *rr++ = '\n';
956671Smckusick *rr++ = c;
966671Smckusick }
976671Smckusick if (rr > record+RECSIZE)
986671Smckusick error(FATAL, "record `%.20s...' too long", record);
996671Smckusick *rr = 0;
1006671Smckusick if (mustfld)
1016671Smckusick fldbld();
1026671Smckusick if (c != EOF || rr > record) { /* normal record */
1036671Smckusick recloc->tval &= ~NUM;
1046671Smckusick recloc->tval |= STR;
1056671Smckusick ++nrloc->fval;
1066671Smckusick nrloc->tval &= ~STR;
1076671Smckusick nrloc->tval |= NUM;
1086671Smckusick return(1);
1096671Smckusick }
1106671Smckusick /* EOF arrived on this file; set up next */
1116671Smckusick if (infile != stdin)
1126671Smckusick fclose(infile);
1136671Smckusick infile = NULL;
1146671Smckusick svargc--;
1156671Smckusick svargv++;
1166671Smckusick }
1176671Smckusick return(0); /* true end of file */
1186671Smckusick }
1196671Smckusick
setclvar(s)1206671Smckusick setclvar(s) /* set var=value from s */
1216671Smckusick char *s;
1226671Smckusick {
1236671Smckusick char *p;
1246671Smckusick cell *q;
1256671Smckusick
1266671Smckusick for (p=s; *p != '='; p++)
1276671Smckusick ;
1286671Smckusick *p++ = 0;
1296671Smckusick q = setsymtab(s, tostring(p), 0.0, STR, symtab);
1306671Smckusick setsval(q, p);
1316671Smckusick dprintf("command line set %s to |%s|\n", s, p, NULL);
1326671Smckusick }
1336671Smckusick
fldbld()1346671Smckusick fldbld()
1356671Smckusick {
1366671Smckusick register char *r, *fr, sep;
1376671Smckusick int i, j;
1386671Smckusick
1396671Smckusick r = record;
1406671Smckusick fr = fields;
1416671Smckusick i = 0; /* number of fields accumulated here */
1426671Smckusick if ((sep = **FS) == ' ')
1436671Smckusick for (i = 0; ; ) {
1446671Smckusick while (*r == ' ' || *r == '\t' || *r == '\n')
1456671Smckusick r++;
1466671Smckusick if (*r == 0)
1476671Smckusick break;
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 do
1566671Smckusick *fr++ = *r++;
1576671Smckusick while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
1586671Smckusick *fr++ = 0;
1596671Smckusick }
1606671Smckusick else if (*r != 0) /* if 0, it's a null field */
1616671Smckusick for (;;) {
1626671Smckusick i++;
1636671Smckusick if (i >= MAXFLD)
1646671Smckusick error(FATAL, "record `%.20s...' has too many fields", record);
1656671Smckusick if (!(fldtab[i].tval&FLD))
16610794Ssam strfree(fldtab[i].sval);
1676671Smckusick fldtab[i].sval = fr;
1686671Smckusick fldtab[i].tval = FLD | STR;
1696671Smckusick while (*r != sep && *r != '\n' && *r != '\0') /* \n always a separator */
1706671Smckusick *fr++ = *r++;
1716671Smckusick *fr++ = 0;
1726671Smckusick if (*r++ == 0)
1736671Smckusick break;
1746671Smckusick }
1756671Smckusick *fr = 0;
1766671Smckusick for (j=MAXFLD-1; j>i; j--) { /* clean out junk from previous record */
1776671Smckusick if (!(fldtab[j].tval&FLD))
17810794Ssam strfree(fldtab[j].sval);
1796671Smckusick fldtab[j].tval = STR | FLD;
18010794Ssam fldtab[j].sval = EMPTY;
1816671Smckusick }
1826671Smckusick maxfld = i;
1836671Smckusick donefld = 1;
1846671Smckusick for(i=1; i<=maxfld; i++)
185*60482Sbostic if(isanumber(fldtab[i].sval)) {
1866671Smckusick fldtab[i].fval = atof(fldtab[i].sval);
1876671Smckusick fldtab[i].tval |= NUM;
1886671Smckusick }
1896671Smckusick setfval(lookup("NF", symtab, 0), (awkfloat) maxfld);
1906671Smckusick if (dbg)
1916671Smckusick for (i = 0; i <= maxfld; i++)
1926671Smckusick printf("field %d: |%s|\n", i, fldtab[i].sval);
1936671Smckusick }
1946671Smckusick
recbld()1956671Smckusick recbld()
1966671Smckusick {
1976671Smckusick int i;
1986671Smckusick register char *r, *p;
1996671Smckusick
2006671Smckusick if (donefld == 0 || donerec == 1)
2016671Smckusick return;
2026671Smckusick r = record;
2036671Smckusick for (i = 1; i <= *NF; i++) {
2046671Smckusick p = getsval(&fldtab[i]);
2056671Smckusick while (*r++ = *p++)
2066671Smckusick ;
2076671Smckusick *(r-1) = **OFS;
2086671Smckusick }
2096671Smckusick *(r-1) = '\0';
2106671Smckusick dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
2116671Smckusick recloc->tval = STR | FLD;
2126671Smckusick dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL);
2136671Smckusick if (r > record+RECSIZE)
2146671Smckusick error(FATAL, "built giant record `%.20s...'", record);
2156671Smckusick dprintf("recbld = |%s|\n", record, NULL, NULL);
2166671Smckusick }
2176671Smckusick
fieldadr(n)2186671Smckusick cell *fieldadr(n)
2196671Smckusick {
2206671Smckusick if (n >= MAXFLD)
2216671Smckusick error(FATAL, "trying to access field %d", n);
2226671Smckusick return(&fldtab[n]);
2236671Smckusick }
2246671Smckusick
2256671Smckusick int errorflag = 0;
2266671Smckusick
yyerror(s)2276671Smckusick yyerror(s) char *s; {
2286671Smckusick fprintf(stderr, "awk: %s near line %d\n", s, lineno);
2296671Smckusick errorflag = 2;
2306671Smckusick }
2316671Smckusick
23258334Storek int
23358334Storek #ifdef __STDC__
error(int isfatal,const char * fmt,...)23458334Storek error(int isfatal, const char *fmt, ...)
23558334Storek #else
23658334Storek error(isfatal, fmt, va_alist)
23746819Sbostic int isfatal;
23846819Sbostic char *fmt;
23958334Storek va_dcl
24058334Storek #endif
24146819Sbostic {
24246819Sbostic va_list ap;
24346819Sbostic
24458334Storek #ifdef __STDC__
24546819Sbostic va_start(ap, fmt);
24658334Storek #else
24758334Storek va_start(ap);
24858334Storek #endif
24946819Sbostic (void)fprintf(stderr, "awk: ");
25046819Sbostic (void)vfprintf(stderr, fmt, ap);
25146819Sbostic va_end(ap);
25246819Sbostic (void)fprintf(stderr, "\n");
25317190Sralph if (NR && *NR > 0)
25446819Sbostic (void)fprintf(stderr, " record number %g\n", *NR);
25546819Sbostic if (isfatal)
2566671Smckusick exit(2);
2576671Smckusick }
2586671Smckusick
PUTS(s)2596671Smckusick PUTS(s) char *s; {
2606671Smckusick dprintf("%s\n", s, NULL, NULL);
2616671Smckusick }
2626671Smckusick
2636671Smckusick #define MAXEXPON 38 /* maximum exponenet for fp number */
2646671Smckusick
isanumber(s)265*60482Sbostic isanumber(s)
2666671Smckusick register char *s;
2676671Smckusick {
2686671Smckusick register d1, d2;
2696671Smckusick int point;
2706671Smckusick char *es;
2716671Smckusick
27210794Ssam if (s == NULL)
27310794Ssam return (0);
2746671Smckusick d1 = d2 = point = 0;
2756671Smckusick while (*s == ' ' || *s == '\t' || *s == '\n')
2766671Smckusick s++;
2776671Smckusick if (*s == '\0')
2786671Smckusick return(0); /* empty stuff isn't number */
2796671Smckusick if (*s == '+' || *s == '-')
2806671Smckusick s++;
2816671Smckusick if (!isdigit(*s) && *s != '.')
2826671Smckusick return(0);
2836671Smckusick if (isdigit(*s)) {
2846671Smckusick do {
2856671Smckusick d1++;
2866671Smckusick s++;
2876671Smckusick } while (isdigit(*s));
2886671Smckusick }
2896671Smckusick if(d1 >= MAXEXPON)
2906671Smckusick return(0); /* too many digits to convert */
2916671Smckusick if (*s == '.') {
2926671Smckusick point++;
2936671Smckusick s++;
2946671Smckusick }
2956671Smckusick if (isdigit(*s)) {
2966671Smckusick d2++;
2976671Smckusick do {
2986671Smckusick s++;
2996671Smckusick } while (isdigit(*s));
3006671Smckusick }
3016671Smckusick if (!(d1 || point && d2))
3026671Smckusick return(0);
3036671Smckusick if (*s == 'e' || *s == 'E') {
3046671Smckusick s++;
3056671Smckusick if (*s == '+' || *s == '-')
3066671Smckusick s++;
3076671Smckusick if (!isdigit(*s))
3086671Smckusick return(0);
3096671Smckusick es = s;
3106671Smckusick do {
3116671Smckusick s++;
3126671Smckusick } while (isdigit(*s));
3136671Smckusick if (s - es > 2)
3146671Smckusick return(0);
3156671Smckusick else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON)
3166671Smckusick return(0);
3176671Smckusick }
3186671Smckusick while (*s == ' ' || *s == '\t' || *s == '\n')
3196671Smckusick s++;
3206671Smckusick if (*s == '\0')
3216671Smckusick return(1);
3226671Smckusick else
3236671Smckusick return(0);
3246671Smckusick }
3256671Smckusick /*
326*60482Sbostic isanumber(s) char *s; {return(0);}
3276671Smckusick */
328