|
|
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.