|
|
1.1 root 1: /***************************************************************************
2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
3: * is provided to you without charge, and with no warranty. You may give *
4: * away copies of JOVE, including sources, provided that this notice is *
5: * included in all the files. *
6: ***************************************************************************/
7:
8: #include "jove.h"
9: #include "io.h"
10: #include "ctype.h"
11: #include "termcap.h"
12:
13: #ifdef MAC
14: # include "mac.h"
15: #else
16: # include <sys/stat.h>
17: # ifndef MSDOS
18: # include <sys/file.h>
19: # else /* MSDOS */
20: # include <fcntl.h>
21: # include <io.h>
22: # endif /* MSDOS */
23: #endif /* MAC */
24:
25: #include <errno.h>
26:
27: #ifdef MAC
28: # undef private
29: # define private
30: #endif
31:
32: #ifdef LINT_ARGS
33: private File * f_alloc(char *, int, int, char *, int);
34: #ifdef RAINBOW
35: private int rbwrite(int, char *, int);
36: #endif
37: #else
38: private File * f_alloc();
39: #ifdef RAINBOW
40: private int rbwrite();
41: #endif
42: #endif /* LINT_ARGS */
43:
44: #ifdef MAC
45: # undef private
46: # define private static
47: #endif
48:
49: #ifndef L_SET
50: # define L_SET 0
51: #endif
52:
53: #define MAXFILES 20 /* good enough for my purposes */
54:
55: private File _openfiles[MAXFILES] = {0};
56:
57: private File *
58: f_alloc(name, flags, fd, buffer, buf_size)
59: char *name,
60: *buffer;
61: {
62: register File *fp;
63: register int i;
64:
65: for (fp = _openfiles, i = 0; i < MAXFILES; i++, fp++)
66: if (fp->f_flags == 0)
67: break;
68: if (i == MAXFILES)
69: complain("[Too many open files!]");
70: fp->f_bufsize = buf_size;
71: fp->f_cnt = 0;
72: fp->f_fd = fd;
73: fp->f_flags = flags;
74: if (buffer == 0) {
75: buffer = emalloc(buf_size);
76: fp->f_flags |= F_MYBUF;
77: }
78: fp->f_base = fp->f_ptr = buffer;
79: fp->f_name = copystr(name);
80:
81: return fp;
82: }
83:
84: void
85: gc_openfiles()
86: {
87: register File *fp;
88:
89: for (fp = _openfiles; fp < &_openfiles[MAXFILES]; fp++)
90: if (fp->f_flags != 0 && (fp->f_flags & F_LOCKED) == 0)
91: f_close(fp);
92: }
93:
94: File *
95: fd_open(name, flags, fd, buffer, bsize)
96: char *name,
97: *buffer;
98: {
99: return f_alloc(name, flags, fd, buffer, bsize);
100: }
101:
102: File *
103: f_open(name, flags, buffer, buf_size)
104: char *name,
105: *buffer;
106: {
107: register int fd;
108: int mode = F_MODE(flags);
109:
110: if (mode == F_READ)
111: fd = open(name, 0);
112: if (mode == F_APPEND) {
113: fd = open(name, 1);
114: if (fd == -1)
115: mode = F_WRITE;
116: else
117: (void) lseek(fd, 0L, 2);
118: }
119: if (mode == F_WRITE)
120: fd = creat(name, CreatMode);
121: if (fd == -1)
122: return NIL;
123: #ifdef MSDOS
124: else
125: setmode(fd, 0x8000);
126: #endif /* MSDOS */
127: return f_alloc(name, flags, fd, buffer, buf_size);
128: }
129:
130: void
131: f_close(fp)
132: File *fp;
133: {
134: flush(fp);
135: #ifdef BSD4_2
136: if (fp->f_flags & (F_WRITE|F_APPEND))
137: (void) fsync(fp->f_fd);
138: #endif
139: (void) close(fp->f_fd);
140: if (fp->f_flags & F_MYBUF)
141: free(fp->f_base);
142: free(fp->f_name);
143: fp->f_flags = 0; /* indicates that we're available */
144: }
145:
146: int
147: filbuf(fp)
148: File *fp;
149: {
150: if (fp->f_flags & (F_EOF|F_ERR))
151: return EOF;
152: fp->f_ptr = fp->f_base;
153: #ifndef MSDOS
154: do
155: #endif /* MSDOS */
156: fp->f_cnt = read(fp->f_fd, fp->f_base, fp->f_bufsize);
157: #ifndef MSDOS
158: while (fp->f_cnt == -1 && errno == EINTR);
159: #endif /* MSDOS */
160: if (fp->f_cnt == -1) {
161: printf("[Read error %d]", errno);
162: fp->f_flags |= F_ERR;
163: }
164: if (fp->f_cnt == 0) {
165: fp->f_flags |= F_EOF;
166: return EOF;
167: }
168: io_chars += fp->f_cnt;
169: return getc(fp);
170: }
171:
172: void
173: putstr(s)
174: register char *s;
175: {
176: #ifndef IBMPC
177: register int c;
178:
179: while (c = *s++)
180: putchar(c);
181: #else /* IBMPC */
182: write_emif(s);
183: #endif /* IBMPC */
184: }
185:
186: void
187: fputnchar(s, n, fp)
188: register char *s;
189: register int n;
190: register File *fp;
191: {
192: while (--n >= 0)
193: putc(*s++, fp);
194: }
195:
196: void
197: flusho()
198: {
199: #ifndef IBMPC
200: _flush(EOF, stdout);
201: #endif /* IBMPC */
202: }
203:
204: void
205: flush(fp)
206: File *fp;
207: {
208: _flush(EOF, fp);
209: }
210:
211: void
212: f_seek(fp, offset)
213: register File *fp;
214: off_t offset;
215: {
216: if (fp->f_flags & F_WRITE)
217: flush(fp);
218: fp->f_cnt = 0; /* next read will filbuf(), next write
219: will flush() with no bad effects */
220: lseek(fp->f_fd, (long) offset, L_SET);
221: }
222:
223: int /* is void - but for lints sake */
224: _flush(c, fp)
225: register File *fp;
226: {
227: register int n;
228:
229: if (fp->f_flags & (F_READ | F_STRING | F_ERR))
230: return EOF;
231: if (((n = (fp->f_ptr - fp->f_base)) > 0) &&
232: #ifndef RAINBOW
233: (write(fp->f_fd, fp->f_base, n) != n) &&
234: #else
235: (rbwrite(fp->f_fd, fp->f_base, n) != n) &&
236: #endif
237: (fp != stdout)) {
238: fp->f_flags |= F_ERR;
239: error("[I/O error(%d); file = %s, fd = %d]",
240: errno, fp->f_name, fp->f_fd);
241: }
242:
243: fp->f_cnt = fp->f_bufsize;
244: fp->f_ptr = fp->f_base;
245: if (c != EOF)
246: return putc(c, fp);
247: }
248:
249: int
250: f_gets(fp, buf, max)
251: register File *fp;
252: char *buf;
253: {
254: register char *cp = buf;
255: register int c;
256: char *endp = buf + max - 1;
257:
258: if (fp->f_flags & F_EOF)
259: return EOF;
260: while (((c = getc(fp)) != EOF) && (c != '\n')) {
261: if (c == '\0') /* possibly different from NULL */
262: break; /* sorry we don't read nulls */
263: #ifdef MSDOS
264: if (c == '\r') {
265: if ((c = getc(fp)) == '\n')
266: break;
267: else
268: *cp++ = '\r';
269: }
270: #endif /* MSDOS */
271: if (cp >= endp) {
272: add_mess(" [Line too long]");
273: rbell();
274: return EOF;
275: }
276: *cp++ = c;
277: }
278: *cp = '\0';
279: if (c == EOF) {
280: if (cp != buf)
281: add_mess(" [Incomplete last line]");
282: fp->f_flags |= F_EOF;
283: return EOF;
284: }
285: io_lines += 1;
286: return 0; /* this means okay */
287: }
288:
289: /* skip to beginning of next line, i.e., next read returns first
290: character of new line */
291:
292: void
293: f_toNL(fp)
294: register File *fp;
295: {
296: register int c;
297:
298: if (fp->f_flags & F_EOF)
299: return;
300: while (((c = getc(fp)) != EOF) && (c != '\n'))
301: ;
302: if (c == EOF)
303: fp->f_flags |= F_EOF;
304: }
305:
306: void
307: f_readn(fp, addr, n)
308: register File *fp;
309: register char *addr;
310: register int n;
311: {
312: while (--n >= 0)
313: *addr++ = getc(fp);
314: }
315:
316: int
317: f_getint(fp)
318: File *fp;
319: {
320: int n = 0,
321: c;
322:
323: while (isdigit(c = getc(fp)))
324: n = (n * 10) + c;
325: return n;
326: }
327:
328: /* Deals with output to the terminal, setting up the amount of characters
329: to be buffered depending on the output baud rate. Why it's in a
330: separate file I don't know ... */
331:
332: private char one_buf;
333:
334: int BufSize = 1;
335:
336: private File _stdout = {1, 1, 1, F_WRITE, &one_buf, &one_buf};
337: File *stdout = &_stdout;
338:
339: /* put a string with padding */
340:
341: #ifndef IBMPC
342: void
343: tputc(c)
344: {
345: putchar(c);
346: }
347:
348: #undef putchar /* for files which forget to include io.h,
349: here's a real putchar procedure. */
350: void
351: putchar(c)
352: {
353: putc(c, stdout);
354: }
355:
356: #endif /* IBMPC */
357: #ifndef MAC
358: void
359: putpad(str, lines)
360: char *str;
361: {
362: #ifndef IBMPC
363: if (str)
364: tputs(str, lines, tputc);
365: #else /* IBMPC */
366: write_emif(str);
367: #endif /* IBMPC */
368: }
369: #endif
370:
371: /* Determine the number of characters to buffer at each baud rate. The
372: lower the number, the quicker the response when new input arrives. Of
373: course the lower the number, the more prone the program is to stop in
374: output. Decide what matters most to you. This sets BufSize to the right
375: number or chars, and initiaizes `stdout'. */
376:
377: void
378: settout(ttbuf)
379: char *ttbuf;
380: {
381: #ifndef MAC
382: #ifndef MSDOS
383: static int speeds[] = {
384: 1, /* 0 */
385: 1, /* 50 */
386: 1, /* 75 */
387: 1, /* 110 */
388: 1, /* 134 */
389: 1, /* 150 */
390: 1, /* 200 */
391: 2, /* 300 */
392: 4, /* 600 */
393: 8, /* 1200 */
394: 16, /* 1800 */
395: 32, /* 2400 */
396: 128, /* 4800 */
397: 256, /* 9600 */
398: 512, /* EXTA */
399: 1024 /* EXT */
400: };
401: flusho(); /* flush the one character buffer */
402: BufSize = min(MAXTTYBUF, speeds[ospeed] * max(LI / 24, 1));
403: stdout = fd_open("/dev/tty", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
404: #else /* MSDOS */
405: #ifndef IBMPC
406: flusho(); /* flush the one character buffer */
407: BufSize = BUFSIZ;
408: stdout = fd_open("con", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
409: #endif /* IBMPC */
410: #endif /* MSDOS */
411: #endif /* MAC */
412: }
413:
414: #ifdef RAINBOW
415:
416: /*
417: * use the Rainbow's video output function
418: */
419:
420: #include <dos.h>
421:
422: private int
423: rbwrite(fd, buf, cnt)
424: char *buf;
425: {
426: union REGS vr;
427:
428: if (fd != 1) {
429: write(fd, buf, cnt);
430: } else {
431: while (cnt-- > 0) {
432: vr.x.ax = *buf++;
433: vr.x.di = 0;
434: int86(0x18, &vr, &vr);
435: }
436: }
437: }
438: #endif /* RAINBOW */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.