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 */