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