aboutsummaryrefslogtreecommitdiff
path: root/sys/fio/filbuf.x
blob: 55878cad5ebc82c5646859ed980f387cbd11ab9f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<syserr.h>
include	<config.h>
include	<fio.h>

# FILBUF -- Fill the file buffer.  Called by GETC, GETLINE, and READ when the
# i/o pointer no longer points into the file buffer.  This happens when
# (1) there is no file buffer yet, (2) all the data in the buffer has been
# read, or (3) a SEEK has occurred.

int procedure filbuf (fd)

int	fd			#I input file

pointer	bp, pb_sp
int	maxch, nchars_read

int	ffault()
errchk	fmkbfs, ffault, filerr, syserr
include	<fio.com>
define	again_ 91

begin
	fp = fiodes[fd]
	if (fd <= 0 || fp == NULL)			# verification
	    call syserr (SYS_FILENOTOPEN)
again_
	if (and (FF_READ+FF_PUSHBACK, fflags[fd]) == 0) {
	    if (FTYPE(fp) == STRING_FILE || FTYPE(fp) == SPOOL_FILE)
		return (EOF)
	    else
		call filerr (FNAME(fp), SYS_FNOREADPERM)
	}

	# If filbuf was called at the end of a pushed back block of data,
	# pop the old i/o pointers off the pushback stack and resume i/o
	# at the point at which it was interrupted.

	if (and (fflags[fd], FF_PUSHBACK) != 0) {
	    repeat {
		pb_sp = FPBSP(fp)

		iop[fd]    = Memi[pb_sp];	pb_sp = pb_sp + 1
		itop[fd]   = Memi[pb_sp];	pb_sp = pb_sp + 1
		bufptr[fd] = Memi[pb_sp];	pb_sp = pb_sp + 1
		FPBIOP(fp) = Memi[pb_sp];	pb_sp = pb_sp + 1

		FPBSP(fp) = pb_sp

		# When the pb stack pointer reaches the top of the pushback
		# buffer, all pushed back data has been read.  Note that the
		# stack pointer is a pointer to int while FPBTOP is a pointer
		# to char.

		if (pb_sp >= (FPBTOP(fp) - 1) / SZ_INT + 1)
		    fflags[fd] = fflags[fd] - FF_PUSHBACK

		# If there was no data left when pushback occurred, then we
		# aren't done yet.

		nchars_read = itop[fd] - iop[fd]
		if (nchars_read > 0)
		    return (nchars_read)

	    } until (and (fflags[fd], FF_PUSHBACK) == 0)
	    goto again_
	}

	# If we do not have a file buffer yet, allocate one.
	bp = bufptr[fd]
	if (bp == NULL) {
	    call fmkbfs (fd)
	    bp = bufptr[fd]
	}

	if (FTYPE(fp) == TEXT_FILE) {
	    # Get next line from text file, initialize pointers.  In raw mode
	    # we only read one character at a time.

	    if (and (FF_RAW, fflags[fd]) == 0)
		maxch = FBUFSIZE(fp)
	    else
		maxch = 1
	    call zcall4 (ZGETTX(fp), FCHAN(fp), Memc[bp], maxch, nchars_read)

	    iop[fd] = bp
	    itop[fd] = max (bp, bp + nchars_read)
	    otop[fd] = bp

	} else if (FNCHARS(fp) < 0) {
	    # Validate data in buffer without performing a physical read (used
	    # to attempt error recovery following a read error - see fseti).

	    nchars_read = -FNCHARS(fp)
	    iop[fd] = bp
	    itop[fd] = bp + nchars_read
	    otop[fd] = bp

	} else {
	    # Fill buffer from binary file.
	    nchars_read = ffault (fd, LNOTE(fd), 0, FF_READ)
	}

	switch (nchars_read) {
	case ERR:
	    call filerr (FNAME(fp), SYS_FREAD)
	case 0:
	    return (EOF)
	default:
	    return (nchars_read)			# (or ERR)
	}
end