1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)lib.c 4.11 (Berkeley) 05/26/93"; 10 #endif /* not lint */ 11 12 #ifdef __STDC__ 13 #include <stdarg.h> 14 #else 15 #include <varargs.h> 16 #endif 17 #include "stdio.h" 18 #include "awk.def" 19 #include "awk.h" 20 #include "ctype.h" 21 22 int error __P((int, const char *, ...)); 23 24 extern FILE *yyin; /* lex input file */ 25 extern char *lexprog; /* points to program argument if it exists */ 26 FILE *infile = NULL; 27 char *file; 28 #define RECSIZE (5 * 512) 29 char record[RECSIZE]; 30 char fields[RECSIZE]; 31 char EMPTY[] = ""; 32 33 #define MAXFLD 100 34 int donefld; /* 1 = implies rec broken into fields */ 35 int donerec; /* 1 = record is valid (no flds have changed) */ 36 int mustfld; /* 1 = NF seen, so always break*/ 37 38 #define FINIT {EMPTY, EMPTY, 0.0, FLD|STR} 39 cell fldtab[MAXFLD] = { /*room for fields */ 40 { "$record", record, 0.0, STR|FLD}, 41 FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 42 FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 43 FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 44 FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 45 FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 46 FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 47 FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 48 FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 49 FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, 50 }; 51 int maxfld = 0; /* last used field */ 52 53 54 getrec() 55 { 56 register char *rr; 57 extern int svargc; 58 extern char **svargv; 59 register c, sep; 60 61 dprintf("**RS=%o, **FS=%o\n", **RS, **FS, NULL); 62 donefld = 0; 63 donerec = 1; 64 record[0] = 0; 65 while (svargc > 0) { 66 dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL); 67 if (infile == NULL) { /* have to open a new file */ 68 if (member('=', *svargv)) { /* it's a var=value argument */ 69 setclvar(*svargv); 70 svargv++; 71 svargc--; 72 continue; 73 } 74 *FILENAME = file = *svargv; 75 dprintf("opening file %s\n", file, NULL, NULL); 76 if (*file == '-') { 77 if (yyin == stdin && ! lexprog) 78 error(FATAL, "standard input already used for reading commands"); 79 else 80 infile = stdin; 81 } 82 else if ((infile = fopen(file, "r")) == NULL) 83 error(FATAL, "can't open %s", file); 84 } 85 if ((sep = **RS) == 0) 86 sep = '\n'; 87 for (rr = record; ; ) { 88 for (; (c=getc(infile)) != sep && c != EOF; *rr++ = c) 89 ; 90 if (**RS == sep || c == EOF) 91 break; 92 if ((c = getc(infile)) == '\n' || c == EOF) /* 2 in a row */ 93 break; 94 *rr++ = '\n'; 95 *rr++ = c; 96 } 97 if (rr > record+RECSIZE) 98 error(FATAL, "record `%.20s...' too long", record); 99 *rr = 0; 100 if (mustfld) 101 fldbld(); 102 if (c != EOF || rr > record) { /* normal record */ 103 recloc->tval &= ~NUM; 104 recloc->tval |= STR; 105 ++nrloc->fval; 106 nrloc->tval &= ~STR; 107 nrloc->tval |= NUM; 108 return(1); 109 } 110 /* EOF arrived on this file; set up next */ 111 if (infile != stdin) 112 fclose(infile); 113 infile = NULL; 114 svargc--; 115 svargv++; 116 } 117 return(0); /* true end of file */ 118 } 119 120 setclvar(s) /* set var=value from s */ 121 char *s; 122 { 123 char *p; 124 cell *q; 125 126 for (p=s; *p != '='; p++) 127 ; 128 *p++ = 0; 129 q = setsymtab(s, tostring(p), 0.0, STR, symtab); 130 setsval(q, p); 131 dprintf("command line set %s to |%s|\n", s, p, NULL); 132 } 133 134 fldbld() 135 { 136 register char *r, *fr, sep; 137 int i, j; 138 139 r = record; 140 fr = fields; 141 i = 0; /* number of fields accumulated here */ 142 if ((sep = **FS) == ' ') 143 for (i = 0; ; ) { 144 while (*r == ' ' || *r == '\t' || *r == '\n') 145 r++; 146 if (*r == 0) 147 break; 148 i++; 149 if (i >= MAXFLD) 150 error(FATAL, "record `%.20s...' has too many fields", record); 151 if (!(fldtab[i].tval&FLD)) 152 strfree(fldtab[i].sval); 153 fldtab[i].sval = fr; 154 fldtab[i].tval = FLD | STR; 155 do 156 *fr++ = *r++; 157 while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); 158 *fr++ = 0; 159 } 160 else if (*r != 0) /* if 0, it's a null field */ 161 for (;;) { 162 i++; 163 if (i >= MAXFLD) 164 error(FATAL, "record `%.20s...' has too many fields", record); 165 if (!(fldtab[i].tval&FLD)) 166 strfree(fldtab[i].sval); 167 fldtab[i].sval = fr; 168 fldtab[i].tval = FLD | STR; 169 while (*r != sep && *r != '\n' && *r != '\0') /* \n always a separator */ 170 *fr++ = *r++; 171 *fr++ = 0; 172 if (*r++ == 0) 173 break; 174 } 175 *fr = 0; 176 for (j=MAXFLD-1; j>i; j--) { /* clean out junk from previous record */ 177 if (!(fldtab[j].tval&FLD)) 178 strfree(fldtab[j].sval); 179 fldtab[j].tval = STR | FLD; 180 fldtab[j].sval = EMPTY; 181 } 182 maxfld = i; 183 donefld = 1; 184 for(i=1; i<=maxfld; i++) 185 if(isanumber(fldtab[i].sval)) { 186 fldtab[i].fval = atof(fldtab[i].sval); 187 fldtab[i].tval |= NUM; 188 } 189 setfval(lookup("NF", symtab, 0), (awkfloat) maxfld); 190 if (dbg) 191 for (i = 0; i <= maxfld; i++) 192 printf("field %d: |%s|\n", i, fldtab[i].sval); 193 } 194 195 recbld() 196 { 197 int i; 198 register char *r, *p; 199 200 if (donefld == 0 || donerec == 1) 201 return; 202 r = record; 203 for (i = 1; i <= *NF; i++) { 204 p = getsval(&fldtab[i]); 205 while (*r++ = *p++) 206 ; 207 *(r-1) = **OFS; 208 } 209 *(r-1) = '\0'; 210 dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL); 211 recloc->tval = STR | FLD; 212 dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL); 213 if (r > record+RECSIZE) 214 error(FATAL, "built giant record `%.20s...'", record); 215 dprintf("recbld = |%s|\n", record, NULL, NULL); 216 } 217 218 cell *fieldadr(n) 219 { 220 if (n >= MAXFLD) 221 error(FATAL, "trying to access field %d", n); 222 return(&fldtab[n]); 223 } 224 225 int errorflag = 0; 226 227 yyerror(s) char *s; { 228 fprintf(stderr, "awk: %s near line %d\n", s, lineno); 229 errorflag = 2; 230 } 231 232 int 233 #ifdef __STDC__ 234 error(int isfatal, const char *fmt, ...) 235 #else 236 error(isfatal, fmt, va_alist) 237 int isfatal; 238 char *fmt; 239 va_dcl 240 #endif 241 { 242 va_list ap; 243 244 #ifdef __STDC__ 245 va_start(ap, fmt); 246 #else 247 va_start(ap); 248 #endif 249 (void)fprintf(stderr, "awk: "); 250 (void)vfprintf(stderr, fmt, ap); 251 va_end(ap); 252 (void)fprintf(stderr, "\n"); 253 if (NR && *NR > 0) 254 (void)fprintf(stderr, " record number %g\n", *NR); 255 if (isfatal) 256 exit(2); 257 } 258 259 PUTS(s) char *s; { 260 dprintf("%s\n", s, NULL, NULL); 261 } 262 263 #define MAXEXPON 38 /* maximum exponenet for fp number */ 264 265 isanumber(s) 266 register char *s; 267 { 268 register d1, d2; 269 int point; 270 char *es; 271 272 if (s == NULL) 273 return (0); 274 d1 = d2 = point = 0; 275 while (*s == ' ' || *s == '\t' || *s == '\n') 276 s++; 277 if (*s == '\0') 278 return(0); /* empty stuff isn't number */ 279 if (*s == '+' || *s == '-') 280 s++; 281 if (!isdigit(*s) && *s != '.') 282 return(0); 283 if (isdigit(*s)) { 284 do { 285 d1++; 286 s++; 287 } while (isdigit(*s)); 288 } 289 if(d1 >= MAXEXPON) 290 return(0); /* too many digits to convert */ 291 if (*s == '.') { 292 point++; 293 s++; 294 } 295 if (isdigit(*s)) { 296 d2++; 297 do { 298 s++; 299 } while (isdigit(*s)); 300 } 301 if (!(d1 || point && d2)) 302 return(0); 303 if (*s == 'e' || *s == 'E') { 304 s++; 305 if (*s == '+' || *s == '-') 306 s++; 307 if (!isdigit(*s)) 308 return(0); 309 es = s; 310 do { 311 s++; 312 } while (isdigit(*s)); 313 if (s - es > 2) 314 return(0); 315 else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON) 316 return(0); 317 } 318 while (*s == ' ' || *s == '\t' || *s == '\n') 319 s++; 320 if (*s == '\0') 321 return(1); 322 else 323 return(0); 324 } 325 /* 326 isanumber(s) char *s; {return(0);} 327 */ 328