2 /********************************************
4 copyright 1991, 1992. Michael D. Brennan
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
14 * Revision 1.10 1995/12/24 22:23:22 mike
15 * remove errmsg() from inside FINopen
17 * Revision 1.9 1995/06/06 00:18:29 mike
18 * change mawk_exit(1) to mawk_exit(2)
20 * Revision 1.8 1994/12/13 00:26:35 mike
21 * rt_nr and rt_fnr for run-time error messages
23 * Revision 1.7 1994/12/11 23:25:05 mike
26 * Revision 1.6 1994/12/11 22:14:15 mike
27 * remove THINK_C #defines. Not a political statement, just no indication
28 * that anyone ever used it.
30 * Revision 1.5 1994/10/08 19:15:42 mike
33 * Revision 1.4 1993/07/17 13:22:55 mike
34 * indent and general code cleanup
36 * Revision 1.3 1993/07/15 13:26:55 mike
39 * Revision 1.2 1993/07/04 12:51:57 mike
40 * start on autoconfig changes
42 * Revision 1.1.1.1 1993/07/03 18:58:13 mike
45 * Revision 5.7 1993/01/01 21:30:48 mike
46 * split new_STRING() into new_STRING and new_STRING0
48 * Revision 5.6 1992/12/17 02:48:01 mike
49 * 1.1.2d changes for DOS
51 * Revision 5.5 1992/07/28 15:11:30 brennan
52 * minor change in finding eol, needed for MsDOS
54 * Revision 5.4 1992/07/10 16:17:10 brennan
55 * MsDOS: remove NO_BINMODE macro
57 * Revision 5.3 1992/07/08 16:14:27 brennan
58 * FILENAME and FNR retain last values in the
61 * Revision 5.2 1992/02/21 13:30:08 brennan
62 * fixed bug that free'd FILENAME twice if
63 * command line was var=value only
65 * Revision 5.1 91/12/05 07:56:02 brennan
84 /* This file handles input files. Opening, closing,
85 buffering and (most important) splitting files into
89 int PROTO(isatty, (int)) ;
91 static FIN *PROTO(next_main, (int)) ;
92 static char *PROTO(enlarge_fin_buffer, (FIN *)) ;
93 static void PROTO(set_main_to_stdin, (void)) ;
94 int PROTO(is_cmdline_assign, (char *)) ; /* also used by init */
96 /* convert file-descriptor to FIN*.
97 It's the main stream if main_flag is set
100 FINdopen(fd, main_flag)
103 register FIN *fin = ZMALLOC(FIN) ;
106 fin->flags = main_flag ? (MAIN_FLAG | START_FLAG) : START_FLAG ;
107 fin->buffp = fin->buff = (char *) zmalloc(BUFFSZ + 1) ;
111 if ((isatty(fd) && rs_shadow.type == SEP_CHAR && rs_shadow.c == '\n')
112 || (interactive_flag && fd == 0) )
114 /* interactive, i.e., line buffer this file */
115 if (fd == 0) fin->fp = stdin ;
116 else if (!(fin->fp = fdopen(fd, "r")))
118 errmsg(errno, "fdopen failed") ; mawk_exit(2) ;
121 else fin->fp = (FILE *) 0 ;
126 /* open a FIN* by filename.
127 It's the main stream if main_flag is set.
128 Recognizes "-" as stdin.
132 FINopen(filename, main_flag)
137 int oflag = O_RDONLY ;
140 int bm = binmode() & 1 ;
141 if (bm) oflag |= O_BINARY ;
144 if (filename[0] == '-' && filename[1] == 0)
147 if (bm) setmode(0, O_BINARY) ;
149 return FINdopen(0, main_flag) ;
152 if ((fd = open(filename, oflag, 0)) == -1)
155 return FINdopen(fd, main_flag) ;
158 /* frees the buffer and fd, but leaves FIN structure until
159 the user calls close() */
165 static char dead = 0 ;
167 if (fin->buff != &dead)
169 zfree(fin->buff, fin->nbuffs * BUFFSZ + 1) ;
173 if (fin->fp) fclose(fin->fp) ;
174 else close(fin->fd) ;
177 fin->buff = fin->buffp = &dead ; /* marks it semi_closed */
179 /* else was already semi_closed */
182 /* user called close() on input file */
191 /* return one input record as determined by RS,
192 from input file (FIN) fin
200 register char *p, *q ;
206 if (!(p = fin->buffp)[0]) /* need a refill */
208 if (fin->flags & EOF_FLAG)
210 if (fin->flags & MAIN_FLAG)
212 fin = next_main(0) ; goto restart ;
216 *len_p = 0 ; return (char *) 0 ;
223 if (!fgets(fin->buff, BUFFSZ + 1, fin->fp))
225 fin->flags |= EOF_FLAG ;
227 fin->buffp = fin->buff ;
228 goto restart ; /* might be main_fin */
230 else /* return this line */
234 while (*p != '\n' && *p != 0) p++ ;
236 *p = 0 ; *len_p = p - fin->buff ;
243 /* block buffering */
244 r = fillbuff(fin->fd, fin->buff, fin->nbuffs * BUFFSZ) ;
247 fin->flags |= EOF_FLAG ;
248 fin->buffp = fin->buff ;
249 goto restart ; /* might be main */
251 else if (r < fin->nbuffs * BUFFSZ)
253 fin->flags |= EOF_FLAG ;
256 p = fin->buffp = fin->buff ;
258 if (fin->flags & START_FLAG)
260 fin->flags &= ~START_FLAG ;
261 if (rs_shadow.type == SEP_MLR)
263 /* trim blank lines from front of file */
264 while (*p == '\n') p++ ;
266 if (*p == 0) goto restart ;
274 switch (rs_shadow.type)
277 q = strchr(p, rs_shadow.c) ;
282 q = str_str(p, ((STRING *) rs_shadow.ptr)->str,
283 match_len = ((STRING *) rs_shadow.ptr)->len) ;
288 q = re_pos_match(p, rs_shadow.ptr, &match_len) ;
289 /* if the match is at the end, there might still be
290 more to match in the file */
291 if (q && q[match_len] == 0 && !(fin->flags & EOF_FLAG))
296 bozo("type of rs_shadow") ;
301 /* the easy and normal case */
302 *q = 0 ; *len_p = q - p ;
303 fin->buffp = q + match_len ;
307 if (fin->flags & EOF_FLAG)
309 /* last line without a record terminator */
310 *len_p = r = strlen(p) ; fin->buffp = p+r ;
312 if (rs_shadow.type == SEP_MLR && fin->buffp[-1] == '\n'
323 /* current record is too big for the input buffer, grow buffer */
324 p = enlarge_fin_buffer(fin) ;
328 /* move a partial line to front of buffer and try again */
331 p = (char *) memcpy(fin->buff, p, r = strlen(p)) ;
332 q = p+r ; rr = fin->nbuffs*BUFFSZ - r ;
334 if ((r = fillbuff(fin->fd, q, rr)) < rr)
335 fin->flags |= EOF_FLAG ;
341 enlarge_fin_buffer(fin)
345 unsigned oldsize = fin->nbuffs * BUFFSZ + 1 ;
348 /* I'm not sure this can really happen:
349 avoid "16bit wrap" */
350 if (fin->nbuffs == MAX_BUFFS)
352 errmsg(0, "out of input buffer space") ;
358 fin->buff = (char *) zrealloc(fin->buff, oldsize, oldsize + BUFFSZ) ;
361 r = fillbuff(fin->fd, fin->buff + (oldsize - 1), BUFFSZ) ;
362 if (r < BUFFSZ) fin->flags |= EOF_FLAG ;
368 target is big enough to hold size + 1 chars
369 on exit the back of the target is zero terminated
372 fillbuff(fd, target, size)
374 register char *target ;
378 unsigned entry_size = size ;
381 switch (r = read(fd, target, size))
384 errmsg(errno, "read error") ;
391 target += r ; size -= r ;
397 return entry_size - size ;
400 /* main_fin is a handle to the main input stream
401 == 0 never been opened */
404 ARRAY Argv ; /* to the user this is ARGV */
405 static double argi = 1.0 ; /* index of next ARGV[argi] to try to open */
411 cell_destroy(FILENAME) ;
412 FILENAME->type = C_STRING ;
413 FILENAME->ptr = (PTR) new_STRING("-") ;
415 FNR->type = C_DOUBLE ;
416 FNR->dval = 0.0 ; rt_fnr = 0 ;
417 main_fin = FINdopen(0, 1) ;
421 /* this gets called once to get the input stream going.
422 It is called after the execution of the BEGIN block
423 unless there is a getline inside BEGIN {}
433 if (k & 1) setmode(0, O_BINARY) ;
434 if ( k & 2 ) { setmode(1,O_BINARY) ; setmode(2,O_BINARY) ; }
437 cellcpy(&argc, ARGC) ;
438 if (argc.type != C_DOUBLE) cast1_to_d(&argc) ;
440 if (argc.dval == 1.0) set_main_to_stdin() ;
444 /* get the next command line file open */
447 int open_flag ; /* called by open_main() if on */
450 CELL argc ; /* copy of ARGC */
451 CELL c_argi ; /* cell copy of argi */
452 CELL argval ; /* copy of ARGV[c_argi] */
455 argval.type = C_NOINIT ;
456 c_argi.type = C_DOUBLE ;
458 if (main_fin) FINclose(main_fin) ;
459 /* FILENAME and FNR don't change unless we really open
462 /* make a copy of ARGC to avoid side effect */
463 if (cellcpy(&argc, ARGC)->type != C_DOUBLE) cast1_to_d(&argc) ;
465 while (argi < argc.dval)
470 if (!(cp = array_find(Argv, &c_argi, NO_CREATE)))
471 continue ; /* its deleted */
473 /* make a copy so we can cast w/o side effect */
474 cell_destroy(&argval) ;
475 cp = cellcpy(&argval, cp) ;
476 if (cp->type < C_STRING) cast1_to_s(cp) ;
477 if (string(cp)->len == 0) continue ;
478 /* file argument is "" */
480 /* it might be a command line assignment */
481 if (is_cmdline_assign(string(cp)->str)) continue ;
483 /* try to open it -- we used to continue on failure,
484 but posix says we should quit */
485 if (!(main_fin = FINopen(string(cp)->str, 1)))
487 errmsg(errno, "cannot open %s", string(cp)->str) ;
491 /* success -- set FILENAME and FNR */
492 cell_destroy(FILENAME) ;
493 cellcpy(FILENAME, cp) ;
494 free_STRING(string(cp)) ;
496 FNR->type = C_DOUBLE ;
497 FNR->dval = 0.0 ; rt_fnr = 0 ;
502 cell_destroy(&argval) ;
506 /* all arguments were null or assignment */
507 set_main_to_stdin() ;
513 /* this is how we mark EOF on main_fin */
514 static char dead_buff = 0 ;
515 static FIN dead_main =
516 {0, (FILE *) 0, &dead_buff, &dead_buff,
519 return main_fin = &dead_main ;
520 /* since MAIN_FLAG is not set, FINgets won't call next_main() */
534 CELL cell ; /* used if command line assign to pseudo field */
535 CELL *fp = (CELL *) 0 ; /* ditto */
537 if (scan_code[*(unsigned char *) s] != SC_IDCHAR) return 0 ;
540 while ((c = scan_code[*(unsigned char *) p]) == SC_IDCHAR
544 if (*p != '=') return 0 ;
553 stp->stval.cp = cp = ZMALLOC(CELL) ;
557 case ST_NR: /* !! no one will do this */
563 /* must be pseudo field */
570 "cannot command line assign to %s\n\ttype clash or keyword"
574 /* we need to keep ARGV[i] intact */
576 len = strlen(p) + 1 ;
577 /* posix says escape sequences are on from command line */
578 p = rm_escape(strcpy((char *) zmalloc(len), p)) ;
579 cp->ptr = (PTR) new_STRING(p) ;
581 check_strnum(cp) ; /* sets cp->type */
582 if (fp) /* move it from cell to pfield[] */
584 field_assign(fp, cp) ;
585 free_STRING(string(cp)) ;