📄 io.c
字号:
/* io.c Larn is copyrighted 1986 by Noah Morgan. * * Below are the functions in this file: * * setupvt100() Subroutine to set up terminal in correct mode for game * clearvt100() Subroutine to clean up terminal when the game is over * getchar() Routine to read in one character from the terminal * scbr() Function to set cbreak -echo for the terminal * sncbr() Function to set -cbreak echo for the terminal * newgame() Subroutine to save the initial time and seed rnd() * * FILE OUTPUT ROUTINES * * lprintf(format,args . . .) printf to the output buffer * lprint(integer) send binary integer to output buffer * lwrite(buf,len) write a buffer to the output buffer * lprcat(str) sent string to output buffer * * FILE OUTPUT MACROS (in header.h) * * lprc(character) put the character into the output buffer * * FILE INPUT ROUTINES * * long lgetc() read one character from input buffer * long lrint() read one integer from input buffer * lrfill(address,number) put input bytes into a buffer * char *lgetw() get a whitespace ended word from input * char *lgetl() get a \n or EOF ended line from input * * FILE OPEN / CLOSE ROUTINES * * lcreat(filename) create a new file for write * lopen(filename) open a file for read * lappend(filename) open for append to an existing file * lrclose() close the input file * lwclose() close output file * lflush() flush the output buffer * * Other Routines * * cursor(x,y) position cursor at [x,y] * cursors() position cursor at [1,24] (saves memory) * cl_line(x,y) Clear line at [1,y] and leave cursor at [x,y] * cl_up(x,y) Clear screen from [x,1] to current line. * cl_dn(x,y) Clear screen from [1,y] to end of display. * standout(str) Print the string in standout mode. * set_score_output() Called when output should be literally printed. ** putchar(ch) Print one character in decoded output buffer. ** flush_buf() Flush buffer with decoded output. ** init_term() Terminal initialization -- setup termcap info ** char *tmcapcnv(sd,ss) Routine to convert VT100 \33's to termcap format * beep() Routine to emit a beep if enabled (see no-beep in .larnopts) * * Note: ** entries are available only in termcap mode. */#include "header.h"#ifdef SYSV /* system III or system V */#include <termio.h>#define sgttyb termio#define stty(_a,_b) ioctl(_a,TCSETA,_b)#define gtty(_a,_b) ioctl(_a,TCGETA,_b)static int rawflg = 0;static char saveeof,saveeol;#define doraw(_a) if(!rawflg){++rawflg;saveeof=_a.c_cc[VMIN];saveeol=_a.c_cc[VTIME];}\ _a.c_cc[VMIN]=1;_a.c_cc[VTIME]=1;_a.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL)#define unraw(_a) _a.c_cc[VMIN]=saveeof;_a.c_cc[VTIME]=saveeol;_a.c_lflag |= ICANON|ECHO|ECHOE|ECHOK|ECHONL#else not SYSV#ifndef BSD#define CBREAK RAW /* V7 has no CBREAK */#endif#define doraw(_a) (_a.sg_flags |= CBREAK,_a.sg_flags &= ~ECHO)#define unraw(_a) (_a.sg_flags &= ~CBREAK,_a.sg_flags |= ECHO)#include <sgtty.h>#endif not SYSV#ifndef NOVARARGS /* if we have varargs */#include <varargs.h>#else NOVARARGS /* if we don't have varargs */typedef char *va_list;#define va_dcl int va_alist;#define va_start(plist) plist = (char *) &va_alist#define va_end(plist)#define va_arg(plist,mode) ((mode *)(plist += sizeof(mode)))[-1]#endif NOVARARGS#define LINBUFSIZE 128 /* size of the lgetw() and lgetl() buffer */int lfd; /* output file numbers */int fd; /* input file numbers */static struct sgttyb ttx; /* storage for the tty modes */static int ipoint=MAXIBUF,iepoint=MAXIBUF; /* input buffering pointers */static char lgetwbuf[LINBUFSIZE]; /* get line (word) buffer *//* * setupvt100() Subroutine to set up terminal in correct mode for game * * Attributes off, clear screen, set scrolling region, set tty mode */setupvt100() { clear(); setscroll(); scbr(); /* system("stty cbreak -echo"); */ }/* * clearvt100() Subroutine to clean up terminal when the game is over * * Attributes off, clear screen, unset scrolling region, restore tty mode */clearvt100() { resetscroll(); clear(); sncbr(); /* system("stty -cbreak echo"); */ }/* * getchar() Routine to read in one character from the terminal */getchar() { char byt;#ifdef EXTRA c[BYTESIN]++;#endif lflush(); /* be sure output buffer is flushed */ read(0,&byt,1); /* get byte from terminal */ return(byt); }/* * scbr() Function to set cbreak -echo for the terminal * * like: system("stty cbreak -echo") */scbr() { gtty(0,&ttx); doraw(ttx); stty(0,&ttx); }/* * sncbr() Function to set -cbreak echo for the terminal * * like: system("stty -cbreak echo") */sncbr() { gtty(0,&ttx); unraw(ttx); stty(0,&ttx); }/* * newgame() Subroutine to save the initial time and seed rnd() */newgame() { register long *p,*pe; for (p=c,pe=c+100; p<pe; *p++ =0); time(&initialtime); srand(initialtime); lcreat((char*)0); /* open buffering for output to terminal */ }/* * lprintf(format,args . . .) printf to the output buffer * char *format; * ??? args . . . * * Enter with the format string in "format", as per printf() usage * and any needed arguments following it * Note: lprintf() only supports %s, %c and %d, with width modifier and left * or right justification. * No correct checking for output buffer overflow is done, but flushes * are done beforehand if needed. * Returns nothing of value. */#ifdef lint/*VARARGS*/lprintf(str) char *str; { char *str2; str2 = str; str = str2; /* to make lint happy */ }/*VARARGS*/sprintf(str) char *str; { char *str2; str2 = str; str = str2; /* to make lint happy */ }#else lint/*VARARGS*/lprintf(va_alist)va_dcl { va_list ap; /* pointer for variable argument list */ register char *fmt; register char *outb,*tmpb; register long wide,left,cont,n; /* data for lprintf */ char db[12]; /* %d buffer in lprintf */ va_start(ap); /* initialize the var args pointer */ fmt = va_arg(ap, char *); /* pointer to format string */ if (lpnt >= lpend) lflush(); outb = lpnt; for ( ; ; ) { while (*fmt != '%') if (*fmt) *outb++ = *fmt++; else { lpnt=outb; return; } wide = 0; left = 1; cont=1; while (cont) switch(*(++fmt)) { case 'd': n = va_arg(ap, long); if (n<0) { n = -n; *outb++ = '-'; if (wide) --wide; } tmpb = db+11; *tmpb = (char)(n % 10 + '0'); while (n>9) *(--tmpb) = (char)((n /= 10) % 10 + '0'); if (wide==0) while (tmpb < db+12) *outb++ = *tmpb++; else { wide -= db-tmpb+12; if (left) while (wide-- > 0) *outb++ = ' '; while (tmpb < db+12) *outb++ = *tmpb++; if (left==0) while (wide-- > 0) *outb++ = ' '; } cont=0; break; case 's': tmpb = va_arg(ap, char *); if (wide==0) { while (*outb++ = *tmpb++); --outb; } else { n = wide - strlen(tmpb); if (left) while (n-- > 0) *outb++ = ' '; while (*outb++ = *tmpb++); --outb; if (left==0) while (n-- > 0) *outb++ = ' '; } cont=0; break; case 'c': *outb++ = va_arg(ap, int); cont=0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': wide = 10*wide + *fmt - '0'; break; case '-': left = 0; break; default: *outb++ = *fmt; cont=0; break; }; fmt++; } va_end(ap); }#endif lint/* * lprint(long-integer) send binary integer to output buffer * long integer; * * +---------+---------+---------+---------+ * | high | | | low | * | order | | | order | * | byte | | | byte | * +---------+---------+---------+---------+ * 31 --- 24 23 --- 16 15 --- 8 7 --- 0 * * The save order is low order first, to high order (4 bytes total) * and is written to be system independent. * No checking for output buffer overflow is done, but flushes if needed! * Returns nothing of value. */lprint(x) register long x; { if (lpnt >= lpend) lflush(); *lpnt++ = 255 & x; *lpnt++ = 255 & (x>>8); *lpnt++ = 255 & (x>>16); *lpnt++ = 255 & (x>>24); }/* * lwrite(buf,len) write a buffer to the output buffer * char *buf; * int len; * * Enter with the address and number of bytes to write out * Returns nothing of value */lwrite(buf,len) register char *buf; int len; { register char *str; register int num2; if (len > 399) /* don't copy data if can just write it */ {#ifdef EXTRA c[BYTESOUT] += len;#endif#ifndef VT100 for (str=buf; len>0; --len) lprc(*str++);#else VT100 lflush(); write(lfd,buf,len);#endif VT100 } else while (len) { if (lpnt >= lpend) lflush(); /* if buffer is full flush it */ num2 = lpbuf+BUFBIG-lpnt; /* # bytes left in output buffer */ if (num2 > len) num2=len; str = lpnt; len -= num2; while (num2--) *str++ = *buf++; /* copy in the bytes */ lpnt = str; } }/* * long lgetc() Read one character from input buffer * * Returns 0 if EOF, otherwise the character */long lgetc() { register int i; if (ipoint != iepoint) return(inbuffer[ipoint++]); if (iepoint!=MAXIBUF) return(0); if ((i=read(fd,inbuffer,MAXIBUF))<=0) { if (i!=0) write(1,"error reading from input file\n",30); iepoint = ipoint = 0; return(0); } ipoint=1; iepoint=i; return(*inbuffer); }/* * long lrint() Read one integer from input buffer * * +---------+---------+---------+---------+ * | high | | | low | * | order | | | order | * | byte | | | byte | * +---------+---------+---------+---------+ * 31 --- 24 23 --- 16 15 --- 8 7 --- 0 * * The save order is low order first, to high order (4 bytes total) * Returns the int read */long lrint() { register unsigned long i; i = 255 & lgetc(); i |= (255 & lgetc()) << 8; i |= (255 & lgetc()) << 16; i |= (255 & lgetc()) << 24; return(i); }/* * lrfill(address,number) put input bytes into a buffer * char *address; * int number; * * Reads "number" bytes into the buffer pointed to by "address". * Returns nothing of value */lrfill(adr,num) register char *adr; int num; { register char *pnt; register int num2; while (num) { if (iepoint == ipoint) { if (num>5) /* fast way */ { if (read(fd,adr,num) != num) write(2,"error reading from input file\n",30); num=0; } else { *adr++ = lgetc(); --num; } } else { num2 = iepoint-ipoint; /* # of bytes left in the buffer */ if (num2 > num) num2=num; pnt = inbuffer+ipoint; num -= num2; ipoint += num2; while (num2--) *adr++ = *pnt++; } } }/* * char *lgetw() Get a whitespace ended word from input * * Returns pointer to a buffer that contains word. If EOF, returns a NULL */char *lgetw() { register char *lgp,cc; register int n=LINBUFSIZE,quote=0; lgp = lgetwbuf; do cc=lgetc(); while ((cc <= 32) && (cc > NULL)); /* eat whitespace */ for ( ; ; --n,cc=lgetc()) { if ((cc==NULL) && (lgp==lgetwbuf)) return(NULL); /* EOF */ if ((n<=1) || ((cc<=32) && (quote==0))) { *lgp=NULL; return(lgetwbuf); } if (cc != '"') *lgp++ = cc; else quote ^= 1; } }/* * char *lgetl() Function to read in a line ended by newline or EOF * * Returns pointer to a buffer that contains the line. If EOF, returns NULL */char *lgetl() { register int i=LINBUFSIZE,ch; register char *str=lgetwbuf; for ( ; ; --i) { if ((*str++ = ch = lgetc()) == NULL) { if (str == lgetwbuf+1) return(NULL); /* EOF */ ot: *str = NULL; return(lgetwbuf); /* line ended by EOF */ } if ((ch=='\n') || (i<=1)) goto ot; /* line ended by \n */ } }/* * lcreat(filename) Create a new file for write * char *filename; * * lcreat((char*)0); means to the terminal * Returns -1 if error, otherwise the file descriptor opened. */lcreat(str) char *str; { lpnt = lpbuf; lpend = lpbuf+BUFBIG; if (str==NULL) return(lfd=1); if ((lfd=creat(str,0644)) < 0) { lfd=1; lprintf("error creating file <%s>\n",str); lflush(); return(-1); } return(lfd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -