ABS C ATOI C ATOIB C \AUXBUF C "AVAIL C 2CALL MAC5KitCALLOC C (CLEARERRC UCLIB DEF]CSEEK C CTELL C TDTOI C EXIT C ,FEOF C FERROR C FGETC C yFGETS C @FOPEN C ~FPRINTF C ]FPUTC C FPUTS C oFREAD C FREE C YOFREOPEN C FSCANF C ZwFWRITE C GETARG C BGETCHAR C ISALNUM C  ISALPHA C aISASCII C ISATTY C )ISCNTRL C ISCONS C !SISDIGIT C #ISGRAPH C $ISLOWER C &P ISPRINT C 'dISPUNCT C ) ISSPACE C +.KISUPPER C -ISXDIGITC /(ITOA C 1ITOAB C 5MITOD C 923ITOO C ?PITOU C DITOX C JzwLEFT C O[ILEXCMP C Q LEXORDERC \ U MALLOC C e_OTOI C hIPAD C lPOLL C n[PUTCHAR C q PUTS C slRENAME C uSREVERSE C zREWIND C |ASIGN C }#STDIO H =STRCAT C gSTRCHR C STRCMP C ޠSTRCPY C  ySTRLEN C '@STRNCAT C STRNCMP C PSTRNCPY C STRRCHR C TOASCII C TOLOWER C TOUPPER C 1UNGETC C UNLINK C QUUTOI C 0XTOI C FCLOSE C FFLUSH C }CSYSLIB CQ 8^8 /* ** abs -- returns absolute value of nbr */ abs(nbr) int nbr; { if(nbr < 0) return (-nbr); return (nbr); }  #define NOCCARGC /*no argument count passing*/ /* ** atoi(s) -- convert s to integer. */ atoi(s) char *s; { int sign, n; while(isspace(*s)) ++s; sign = 1; switch(*s) { case '-': sign = -1; case '+': ++s; } n = 0; while(isdigit(*s)) n = 10 * n + s++ - '0'; return (sign * n); }  #define NOCCARGC /* ** atoib(s,b) - convert s to "unsigned" integer in base b. ** Note: this is a non-standard function. */ atoib(s, b) char *s; int b; { int n, digit; n = 0; while(isspace(*s)) ++s; while((digit = (127 & s++)) >= '0') { if(digit >= 'a') digit -= 87; else if(digit >= 'A') digit -= 55; else digit -= '0'; if(digit >= b) break; n = b * n + digit; } return (n); }  #define NOCCARG #include stdio.h #include clib.def extern int *_auxsz, *_auxef, _auxrd, _auxwt, _auxfl, _status[]; /* ** Loaded only if auxbuf() is called. Longer explanation in DDJ. */ int _xsize[MAXFILES], /*size of buffer*/ _xaddr[MAXFILES], /*aux buffer address*/ _xnext[MAXFILES], /*address of next byte in buffer*/ _xend[MAXFILES], /*address of end-of-data in buffer*/ _xeof[MAXFILES]; /*true if current buffer ends file*/ /* ** auxbuf(fd, size) -- allocate an auxiliary buffer of size size for ** fd fd. Longer explanation in DDJ. */ auxbuf(fd, size) int fd; char *size; { /*fake unsigned*/ if(!_mode(fd) || size || avail(NO) < size || _xsize[fd]) return (ERR); _xaddr[fd] = _xnext[fd] = _xend[fd] = malloc(size); _auxef = _xeof; /*pass locations to i/o routines*/ _auxrd = _xread; _auxwt = _xwrite; _auxsz = _xsize; _auxfl = _xflush; _xsize[fd] = size; return (NULL); } /* ** Fill buffer if necessary, and return next byte. */ _xread(fd) int fd; { char *ptr; while(YES) { ptr = _xnext[fd]; if(ptr < _xend[fd]) {++_xnext[fd]; return (*ptr);} if(_xeof[fd]) {_seteof(fd); return (EOF);} _auxsz = NULL; /*avoid recursive loop*/ _xend[fd] = _xaddr[fd] + read(fd, _xnext[fd]=_xaddr[fd], _xsize[fd]); _auxsz = _xsize; /*restore _auxsz*/ if(feof(fd)) {_xeof[fd] = YES; _clreof(fd);} } } /* ** Empty buffer if necessary, and store ch in buffer. */ _xwrite(ch, fd) int ch, fd; { char *ptr; while(YES) { ptr = _xnext[fd]; if(ptr < (_xaddr[fd] + _xsize[fd])) {*ptr = ch; ++_xnext[fd]; return (ch);} if(_xflush(fd)) return (EOF); } } /* ** Flush aux buffer to file. */ _xflush(fd) int fd; { int i, j; i = _xnext[fd] - _xaddr[fd]; _auxsz = NULL; /*avoid recursive loop*/ j = write(fd, _xnext[fd]=_xaddr[fd], i); _auxsz = _xsize; /*restore _auxsz*/ if(i != j) return (EOF); return (NULL); }  #define NOCCARGC extern char *_memptr; /* ** Return the number of bytes of available memory and if abort, ** abort with S if there aren't any */ avail(abort) int abort; { char x; if(&x < _memptr) { if(abort) exit ('M'); return (0); } return (&x - _memptr); } ; ;----- call.asm: Small-C ver. 2 arithmetic and logical library ; (ASM Version 7-28-83, Bill Randle) ; (Global symbols added 02-07-84, Dennis Quinn) ; (.8080 added 10 Jan 85, Earl Boebert) ; (Updated to version in the Handbook 4 Feb 85, Earl Boebert) ; .8080 _call:: EXT _END ; CCDCAL:: PCHL ; CCDDGC:: DAD D JMP CCGCHAR ; CCDSGC:: INX H INX H DAD SP ; ;FETCH A SINGLE BYTE FROM THE ADDRESS IN HL AND ;SIGN EXTEND INTO HL ; CCGCHAR:: MOV A,M ; ;PUT THE ACCUM INTO HL AND SIGN EXTEND THROUGH H. ; CCARGC:: CCSXT:: MOV L,A RLC SBB A MOV H,A RET ; CCDDGI:: DAD D JMP CCGINT ; CCDSGI:: INX H INX H DAD SP ; ;FETCH A FULL 16-BIT INTEGER FROM THE ADDRESS IN HL ;INTO HL ; CCGINT:: MOV A,M INX H MOV H,M MOV L,A RET ; CCDECC:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR DCX H MOV A,L STAX D RET ; CCINCC:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR INX H MOV A,L STAX D RET ; ; CCDDPC:: DAD D CCPDPC:: POP B ;;RET ADDR POP D PUSH B ; ;STORE A SINGLE BYTE FROM HL AT THE ADDRESS IN DE ; CCPCHAR:: PCHAR:: MOV A,L STAX D RET ; CCDECI:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT DCX H JMP CCPINT ; CCINCI:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT INX H JMP CCPINT ; ; CCDDPI:: DAD D CCPDPI:: POP B ;;RET ADDR POP D PUSH B ; ;STORE A 16-BIT INTEGER IN HL AT THE ADDRESS IN DE ; CCPINT:: PINT:: MOV A,L STAX D INX D MOV A,H STAX D RET ; ;INCLUSIVE "OR" HL AND DE INTO HL ; CCOR:: MOV A,L ORA E MOV L,A MOV A,H ORA D MOV H,A RET ; ;EXCLUSIVE "OR" HL AND DE INTO HL ; CCXOR:: MOV A,L XRA E MOV L,A MOV A,H XRA D MOV H,A RET ; ;"AND" HL AND DE INTO HL ; CCAND:: MOV A,L ANA E MOV L,A MOV A,H ANA D MOV H,A RET ; ;IN ALL THE FOLLOWING COMPARE ROUTINES, HL IS SET TO 1 IF THE ;CONDITION IS TRUE, OTHERWISE IT IS SET TO 0 (ZERO). ; ;TEST IF HL = DE ; CCEQ:: CALL CCCMP RZ DCX H RET ; ;TEST IF DE <> HL ; CCNE:: CALL CCCMP RNZ DCX H RET ; ;TEST IF DE > HL (SIGNED) ; CCGT:: XCHG CALL CCCMP RC DCX H RET ; ;TEST IF DE <= HL (SIGNED) ; CCLE:: CALL CCCMP RZ RC DCX H RET ; ;TEST IF DE >= HL (SIGNED) ; CCGE:: CALL CCCMP RNC DCX H RET ; ;TEST IF DE < HL (SIGNED) ; CCLT:: CALL CCCMP RC DCX H RET ; ;COMMON ROUTINE TO PERFORM A SIGNED COMPARE ; OF DE AND HL ;THIS ROUTINE PERFORMS DE - HL AND SETS THE CONDITIONS: ; CARRY REFLECTS SIGN OF DIFFERENCE (SET MEANS DE < HL) ; ZERO/NON-ZERO SET ACCORDING TO EQUALITY. ; CCCMP:: MOV A,H ;;INVERT SIGN OF HL XRI 80H MOV H,A MOV A,D ;;INVERT SIGN OF DE XRI 80H CMP H ;;COMPARE MSBS JNZ CCCMP1 ;;DONE IF NEQ MOV A,E ;;COMPARE LSBS CMP L CCCMP1: LXI H,1 ;;PRESET TRUE COND RET ; ;TEST IF DE >= HL (UNSIGNED) ; CCUGE:: CALL CCUCMP RNC DCX H RET ; ;TEST IF DE < HL (UNSIGNED) ; CCULT:: CALL CCUCMP RC DCX H RET ; ;TEST IF DE > HL (UNSIGNED) ; CCUGT:: XCHG CALL CCUCMP RC DCX H RET ; ;TEST IF DE <= HL (UNSIGNED) ; CCULE:: CALL CCUCMP RZ RC DCX H RET ; ;COMMON ROUTINE TO PERFORM UNSIGNED COMPARE ;CARRY SET IF DE < HL ;ZERO/NONZERO SET ACCORDINGLY ; CCUCMP:: MOV A,D CMP H JNZ CCUCP1 MOV A,E CMP L CCUCP1: LXI H,1 RET ; ;SHIFT DE ARITHMETICALLY RIGHT BY HL AND RETURN IN HL ; CCASR:: XCHG DCR E RM MOV A,H RAL MOV A,H RAR MOV H,A MOV A,L RAR MOV L,A JMP CCASR+1 ; ;SHIFT DE ARITHMETICALLY LEFT BY HL AND RETURN IN HL ; CCASL:: XCHG DCR E RM DAD H JMP CCASL+1 ; ;SUBTRACT HL FROM DE AND RETURN IN HL ; CCSUB:: MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A RET ; ;FORM THE TWO'S COMPLEMENT OF HL ; CCNEG:: CALL CCCOM INX H RET ; ;FORM THE ONE'S COMPLEMENT OF HL ; CCCOM:: MOV A,H CMA MOV H,A MOV A,L CMA MOV L,A RET ; ;MULTIPLY DE BY HL AND RETURN IN HL ;(SIGNED MULTIPLY) ; CCMULT:: MULT:: MOV B,H MOV C,L LXI H,0 CCMLT1: MOV A,C RRC JNC CCMLT2 DAD D CCMLT2: XRA A MOV A,B RAR MOV B,A MOV A,C RAR MOV C,A ORA B RZ XRA A MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RZ JMP CCMLT1 ; ;DIVIDE DE BY HL AND RETURN QUOTIENT IN HL, REMAINDER IN DE ;(SIGNED DIVIDE) ; CCDIV:: DIV:: MOV B,H MOV C,L MOV A,D XRA B PUSH PSW MOV A,D ORA A CM CCDENEG MOV A,B ORA A CM CCBCNEG MVI A,16 PUSH PSW XCHG LXI D,0 CCDIV1: DAD H CALL CCRDEL JZ CCDIV2 CALL CCCMPBCDE JM CCDIV2 MOV A,L ORI 1 MOV L,A MOV A,E SUB C MOV E,A MOV A,D SBB B MOV D,A CCDIV2: POP PSW DCR A JZ CCDIV3 PUSH PSW JMP CCDIV1 CCDIV3: POP PSW RP CALL CCDENEG XCHG CALL CCDENEG XCHG RET ; ;NEGATE THE INTEGER IN DE ;(INTERNAL ROUTINE) ; CCDENEG: MOV A,D CMA MOV D,A MOV A,E CMA MOV E,A INX D RET ; ;NEGATE THE INTEGER IN BC ;(INTERNAL ROUTINE) ; CCBCNEG: MOV A,B CMA MOV B,A MOV A,C CMA MOV C,A INX B RET ; ;ROTATE DE LEFT ONE BIT ;(INTERNAL ROUTINE) ; CCRDEL: MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RET ; ;COMPARE BC TO DE ;(INTERNAL ROUTINE) ; CCCMPBCDE: MOV A,E SUB C MOV A,D SBB B RET ; ; LOGICAL NEGATION ; CCLNEG:: MOV A,H ORA L JNZ $+6 MVI L,1 RET LXI H,0 RET ; ; EXECUTE "SWITCH" STATEMENT ; ; HL = SWITCH VALUE ; (SP) -> SWITCH TABLE ; DW ADDR1, VALUE1 ; DW ADDR2, VALUE2 ; ... ; DW 0 ; [JMP default] ; continuation ; CCSWITCH:: XCHG ;;DE = SWITCH VALUE POP H ;;HL -> SWITCH TABLE SWLOOP: MOV C,M INX H MOV B,M ;;BC -> CASE ADDR, ELSE 0 INX H MOV A,B ORA C JZ SWEND ;;DEFAULT OR CONTINUATION CODE MOV A,M INX H CMP E MOV A,M INX H JNZ SWLOOP CMP D JNZ SWLOOP MOV H,B ;;CASE MATCHED MOV L,C SWEND: PCHL ; ;(code added from DDJ) ; _end: LHLD 6 ;get bdos address SPHL ;use for base of stack LXI H, _end ;get start of free memory SHLD _memptr## ;use for memory allocation JMP _main## ;parse command line, execut program END _end  ; HL = SWITCH VALUE ; (SP #define NOCCARGC #include stdio.h /* ** Cleared-memory allocation of n items of size bytes. ** Returns address or NULL. */ calloc(n, size) char *n, *size; { return(_alloc(n*size, YES)); }  #define NOCCARGC #include stdio.h #include clib.def extern int _status[]; /* ** Clear error status for fd. */ clearerr(fd) int fd; { if(_mode(fd)) _status[fd] &= ~ERRBIT; }  /* ** CLIB.DEF -- Definitions for Small-C library functions ** ** For other credits and references, see DDJ, May 1984 */ /* ** Definition of CP/M FCB and additional parameters */ #define FCBSIZE 36 /*size of file control block*/ #define DRIVE 0 /*CP/M drive designator offset*/ #define NAMEOFF 1 /*CP/M file name offset*/ #define NAMEOFF2 16 /*CP/M 2nd file name offset*/ #define NAMESIZE 8 /*CP/M file name size*/ #define TYPEOFF 9 /*CP/M file type offset*/ #define TYPESIZE 3 /*CP/M file type size*/ #define NTSIZE 11 /*CP/M file name and type size*/ #define RRNOFF 33 /*CP/M random record number offset*/ #define CPMEOF 26 /*CP/M end-of-file byte*/ #define BUFSIZE 128 /*size of I/O buffer*/ #define MAXFILES 10 /*maximum open files*/ /* ** CP/M function calls */ #define CLOFIL 16 /*close file*/ #define DCONIO 6 /*direct console i/o*/ #define DELFIL 19 /*delete file*/ #define FNDFIL 17 /*find first occurence of file*/ #define FNDNXT 18 /*find next occurence of file*/ #define GETPOS 36 /*get number of current sector*/ #define GOCPM 00 /*go to CP/M*/ #define LSTOUT 05 /*list output*/ #define MAKFIL 22 /*make file*/ #define OPNFIL 15 /*open file*/ #define POSEND 35 /*position file to end*/ #define PUNOUT 04 /*punch output*/ #define RENAME 23 /*rename file*/ #define RDRND 33 /*read sector randomly*/ #define RDRINP 03 /*reader input*/ #define SETDMA 26 /*set dma*/ #define WRTRND 40 /*write sector randomly*/ /* ** Device codes */ #define CPMCON DCONIO /*console*/ #define CPMRDR RDRINP /*reader*/ #define CPMPUN PUNOUT /*punch*/ #define CPMLST LSTOUT /*list*/ /* ** File status bits */ #define RDBIT 1 /*open for read*/ #define WRTBIT 2 /*open for write*/ #define EOFBIT 4 /*eof condition*/ #define ERRBIT 8 /*error condition*/ /* ** ASCII characters */ #define ABORT 3 #define RUB 8 #define PAUSE 19 #define WIPE 24 #define DEL 127  #define NOCCARGC #include stdio.h #include clib.def extern int _fcbptr[], _chrpos[], _nextc[]; /* ** Position fd to 128-byte record indicated by ** "offset" relative to the point indicated by "base." ** ** BASE OFFSET-RELATIVE-TO ** 0 first record ** 1 current record ** 2 end of file (last record + 1) ** ** Returns NULL on success, else EOF. */ cseek(fd, offset, base) int fd, offset, base; { int oldrrn, *rrn; if(!_mode(fd) || isatty(fd) || fflush(fd)) return EOF; rrn = _fcbptr[fd] + RRNOFF; oldrrn = *rrn; switch (base) { case 2: _bdos(POSEND, _fcbptr[fd]); case 1: *rrn += offset; break; case 0: *rrn = offset; break; default: return (EOF); } if(_sector(fd, RDRND)) { *rrn = oldrrn; return EOF; } _chrpos[fd] = 0; _nextc[fd] = EOF; _clreof(fd); return (NULL); }  #define NOCCARGC #include stdio.h #include clib.def extern int _fcbptr[], _chrpos[]; /* ** Return offset to current 128-byte record */ ctell(fd) int fd; { int *rrn; if(!_mode(fd) || isatty(fd)) return (-1); rrn=_fcbptr[fd]+RRNOFF; return (*rrn); } /* ** Return offset to next character in current buffer. */ ctellc(fd) int fd; { return (_chrpos[fd]); }  #define NOCCARGC #include stdio.h /* ** dtoi -- convert signed decimal string to integer nbr ** returns field length, else ERR on error */ dtoi(decstr, nbr) char *decstr; int *nbr; { int len, s; if((*decstr)=='-') {s=1; ++decstr;} else s=0; if((len=utoi(decstr, nbr))<0) return (ERR); if(*nbr<0) return (ERR); if(s) {*nbr = -*nbr; return (++len);} else return (len); }  #define NOCCARGC #include stdio.h #include clib.def /* ** Close all open files and exit to CP/M. ** Entry: errcode = Character to be sent to stderr. ** Returns to CP/M rather than caller. */ exit(errcode) char errcode; { int fd; if(errcode) _conout(errcode); for(fd=0; fd < MAXFILES; fclose(fd++)); _bdos(GOCPM, NULL); } #asm abort equ exit entry abort #endasm  #define NOCCARGC #include clib.def extern int _status[]; /* ** Test for end-of-file status. ** Entry: fd = file descriptor ** Returns non-zero if fd is at eof, else zero. */ feof(fd) int fd; { return (_status[fd] & EOFBIT); }  #define NOCCARGC #include stdio.h #include clib.def /* ** Write buffer for fd if it has changes. */ extern int _status[]; /*error in DDJ*/ ferror(fd) int fd; { return(_status[fd] & ERRBIT); }  #include stdio.h #include clib.def extern int _chrpos[]; /* ** Character-stream input of one character from fd. ** Entry: fd = File descriptor of pertinent file ** Returns the next character on success, else EOF. */ fgetc(fd) int fd; { int ch; while(1) { switch(ch = _read(fd)) { default: return (ch); case CPMEOF: switch(_chrpos[fd]) { default: --_chrpos[fd]; case 0: case BUFSIZE: } _seteof(fd); return(EOF); case CR: return('\n'); case LF: /* NOTE: _conin() maps LF -> CR*/ } } } #asm getc equ fgetc entry getc #endasm  #define NOCCARGC #include stdio.h #include clib.def /* ** Gets an entire string (including its newline ** terminator) or size-1 characters, whichever comes ** first. The input is terminated by a null character. ** Entry: str = Pointer to the destination buffer. ** size = Size of the destination buffer. ** fd = File descriptor of pertinent file. ** Returns str on success, else NULL. */ fgets(str, size, fd) char *str; int size, fd; { return (_gets(str, size, fd, 1)); } /* ** Gets an entire string fron stdin (excluding its newline ** terminator) or size - 1 characters, whichever comes ** first. The input is terminated by a null character. ** The user buffer must be large enough to hold the data. ** Entry: str = Pointer to destination buffer. ** Returns str on success, else NULL. */ gets(str) char *str; { return (_gets(str, 32767, stdin, 0)); } _gets(str, size, fd, nl) char *str; int size, fd, nl; { int backup; char *next; next = str; while(--size > 0) { switch (*next = fgetc(fd)) { case EOF: *next = NULL; if (next == str) return (NULL); return (str); case '\n': *(next + nl) = NULL; return (str); case RUB: if(next > str) backup = 1; else backup = 0; goto backout; case WIPE: backup = next - str; backout: if(iscons(fd)) { fputs("\b \b\b \b", stderr); ++size; while(backup--) { fputs("\b \b", stderr); if(*--next < 32) fputs("\b \b", stderr); ++size; } continue: } default: ++next; } } *next = NULL; return (str); }  #define NOCCARGC #include stdio.h #include clib.def /* ** Open file indicated by fn. ** Entry: fn = Null-terminated CP/M file name. ** May be prefixed with letter of drive. ** mode = "a" -append ** "r" -read ** "w" -write ** "a+" -append update ** "r+" -read update ** "w+" -write update ** Returns a file descriptor on success, else NULL. */ fopen(fn, mode) char *fn, *mode; { int fd; fd = 0; /*skip stdin (= error return) */ while(++fd < MAXFILES) { if(_mode(fd) == NULL) { if(_open(fn, mode, fd)!=ERR) return (fd); break; } } return (NULL); }  #define NOCCARGC /* ** Yes, it's right. These function do not call ones which need arg counts. */ #include stdio.h /* ** fprintf(fd, ctlstring, arg, arg, ....) - Formatted print. ** Operates as described by Kernighan and Ritchie. ** b, c, d, o, s, u, and x specifications are supported. ** Note: b (binary) is a non-standard extension. */ fprintf(argc) int argc; { int *nxtarg; nxtarg = CCARGC() + &argc; return(_print(*(--nxtarg), --nxtarg)); } /* ** printf(ctlstring, arg, arg, ...) - Formatted print. ** See note to fprintf. */ printf(argc) int argc; { return(_print(stdout, CCARGC() + &argc - 1)); } /* ** _print(fd, ctlstring, arg, arg, ...) ** Called by fprintf() and printf(). */ _print(fd, nxtarg) int fd, *nxtarg; { int arg, left, pad, cc, len, maxchr, width; char *ctl, *sptr, str[17]; cc = 0; ctl = *nxtarg--; while(*ctl) { if(*ctl!='%') {fputc(*ctl++, fd); ++cc; continue;} else ++ctl; if(*ctl=='%') {fputc(*ctl++, fd); ++cc; continue;} if(*ctl=='-') {left = 1; ++ctl;} else left = 0; if(*ctl=='0') pad = '0'; else pad = ' '; if(isdigit(*ctl)) { width = atoi(ctl++); while(isdigit(*ctl)) ++ctl; } else width = 0; if(*ctl=='.') { maxchr = atoi(++ctl); while(isdigit(*ctl)) ++ctl; } else maxchr = 0; arg = *nxtarg--; sptr = str; switch(*ctl++) { case 'c': str[0] = arg; str[1] = NULL; break; case 's': sptr = arg; break; case 'd': itoa(arg,str); break; case 'b': itoab(arg,str,2); break; case 'o': itoab(arg,str,8); break; case 'u': itoab(arg,str,10); break; case 'x': itoab(arg,str,16); break; default: return (cc); } len = strlen(sptr); if(maxchr && maxchrlen) width = width - len; else width = 0; if(!left) while(width--) {fputc(pad, fd); ++cc;} while(len--) {fputc(*sptr++,fd); ++cc;} if(left) while(width--) {fputc(pad,fd); ++cc;} } return(cc); }  #define NOCCARGC #include stdio.h #include clib.def extern int _status[]; /* ** Character-stream output of a character to fd. ** Entry: ch = Character to write ** fd = File descriptor of pertinent file. ** Returns character written on success, else EOF. */ fputc(ch, fd) int ch, fd; { switch(ch) { case EOF: _write(CPMEOF, fd); break; case '\n': _write(CR, fd); _write(LF, fd); break; default: _write(ch, fd); } if(_status[fd] & ERRBIT) return (EOF); return (ch); } #asm putc equ fputc entry putc #endasm  #define NOCCARGC #include stdio.h #include clib.def /* ** Write a string to fd. ** Entry: string = Pointer to null-terminated string ** fd = File descriptor of pertinent file. */ fputs(string,fd) char *string; int fd; { while(*string) fputc(*string++,fd); }  #define NOCCARGC #include clib.def extern int _status[]; /* ** Item-stream read from fd. ** Entry: buf = address of target buffer ** sz = size of items in bytes ** n = number of items to read ** fd = file descriptor ** Returns a count of items actually read. ** Use feof() and ferror() to determine file status. */ fread(buf, sz, n, fd) char *buf; int sz, n, fd; { return(read(fd, buf, n*sz)); } /* ** Binary-stream read from fd. ** Entry: fd = file descriptor ** buf = address of target buffer ** n = number of bytes to read ** Returns a count of items actually read ** Use feof() and ferror() to determine file status. */ read(fd, buf, n) int fd, n; char *buf; { char *cnt; /*fake unsigned*/ cnt = 0; while(n--) { *buf++ = _read(fd); if(_status[fd] & (ERRBIT | EOFBIT)) break; ++cnt; } return (cnt); }  #define NOCCARGC extern char *_memptr; /* ** free(ptr) - free previously allocated memory block. ** Memory must be freed in the reverse order fromw which ** it was allocated. ** ptr = value returned from calloc() or malloc(). ** Returns ptr if successful or NULL otherwise. */ free(ptr) char *ptr; { return(_memptr = ptr); } #asm cfree equ free entry cfree #endasm  #define NOCCARGC #include stdio.h /* ** Close previously opened fd and reopen it. ** Entry: fn = Null-terminated CP/M file name. ** May be prefixed with letter of drive. ** May be just CON:, RDR:, PUN:, or LST: ** mode = "a" -append ** "r" -read ** "w" -write ** "a+" -append update ** "r+" -read update ** "w+" -write update ** Returns the original fd on success, else NULL. */ freopen(fn, mode, fd) char *fn, *mode; int fd; { if(fclose(fd)) return (NULL); if(_open(fn, mode, fd)==ERR) return (NULL); return (fd); }  #define NOCCARGC /* ** Yes, it's right. These function do not call ones which need arg counts. */ #include stdio.h /* ** fscanf(fd, ctlstring, arg, arg, ....) - Formatted read. ** Operates as described by Kernighan and Ritchie. ** b, c, d, o, s, u, and x specifications are supported. ** Note: b (binary) is a non-standard extension. */ fscanf(argc) int argc; { int *nxtarg; nxtarg = CCARGC() + &argc; return (_scan(*(--nxtarg), --nxtarg)); } /* ** scanf(ctlstring, arg, arg, ....) - Formatted read. ** Operates as described by Kernighan and Ritchie. ** b, c, d, o, s, u, and x specifications are supported. ** Note: b (binary) is a non-standard extension. */ scanf(argc) int argc; { return (_scan(stdin, CCARGC() + &argc -1)); } /* ** _scan(fd, ctlstring, arg, arg, ....) - Formatted read. ** Called by fscanf() and scanf()l */ _scan(fd,nxtarg) int fd, *nxtarg; { char *carg, *ctl, *unsigned; int *narg, wast, ac, width, ch, cnv, base, ovfl, sign; ac = 0; ctl = *nxtarg--; while(*ctl) { if(isspace(*ctl)) {++ctl; continue;} if(*ctl++ != '%') continue; if(*ctl == '*') {narg = carg = &wast; ++ctl;} else narg = carg = *nxtarg--; ctl += utoi(ctl, &width); if(!width) width = 32767; if(!(cnv = *ctl++)) break; while(isspace(ch = fgetc(fd))); if(ch == EOF) {if(ac) break; else return (EOF);} ungetc(ch,fd); switch(cnv) { case 'c': *carg = fgetc(fd); break; case 's': while(width--) { if((*carg = fgetc(fd)) == EOF) break; if(isspace(*carg)) break; if(carg != &wast) ++carg; } *carg = 0; break; default: switch(cnv) { case 'b': base = 2; sign = 1; ovfl = 32767; break; case 'd': base = 10; sign = 0; ovfl = 3276; break; case 'o': base = 8; sign = 1; ovfl = 8191; break; case 'u': base = 10; sign = 1; ovfl = 6553; break; case 'x': base = 16; sign = 1; ovfl = 4095; break; default: return (ac); } *narg = unsigned = 0; while(width-- && !isspace(ch=fgetc(fd)) && ch!=EOF) { if(!sign) if(ch == '-') {sign = -1; continue;} else sign = 1; if(ch < '0') return (ac); if(ch > 'a') ch -= 87; else if(ch >= 'A') ch -= 55; else ch -= '0'; if(ch >= base || unsigned > ovfl) return (ac); unsigned = unsigned * base + ch; } *narg = sign * unsigned; } ++ac; } return (ac); }  #define NOCCARGC #include clib.def extern int _status[]; /* ** Item-stream write to fd. ** Entry: buf = address of target buffer ** sz = size of items in bytes ** n = number of items to read ** fd = file descriptor ** Returns a count of items actually read ** or zero if an error occured. ** Use ferror() to determine file status. */ fwrite(buf, sz, n, fd) char *buf; int sz, n, fd; { int cnt; if((cnt = write(fd, buf, n*sz)) == -1) return (0); return (cnt); } /* ** Binary-stream write to fd. ** Entry: buf = address of target buffer ** n = number of items to read ** fd = file descriptor ** Returns a count of items actually read ** or -1 if an error occured. ** Use ferror() to determine file status. */ write(fd, buf, n) int fd, n; char *buf; { char *cnt; /*fake unsigned*/ cnt = 0; while(n--) { _write(*buf++, fd); if(_status[fd] & ERRBIT) return (-1); ++cnt; } return (cnt); }  #define NOCCARGC #include stdio.h /* ** Get command line argument. ** Entry: n = Number of the argument. ** s = Destination string pointer. ** size = Size of the destination string. ** argc = Argument count from main(). ** argv = Argument vector(s) from main(). ** Returns number of characters moved on success, ** else EOF. */ getarg(n,s,size,argc,argv) int n; char *s; int size, argc, argv[]; { char *str; int i; if(n < 0 | n >= argc) { *s = NULL; return (EOF); } i = 0; str=argv[n]; while(i='a') || (c<='Z' && c>='A') || (c<='9' && c>='0')); }  /* ** Return "true" if c is alphabetic */ isalpha(c) int c; { return ((c<='z' && c>='a') || (c<='Z' && c>='A')); }  /* ** Return "true" if c is an ASCII character (0-127) */ isascii(c) char *c; { /* c is simulated unsigned integer */ return (c <= 127); }  extern int _device[]; /* ** Return "true" if fd is a device, else "false" */ isatty(fd) int fd; { return (_device[fd]); }  /* ** Return "true" if c is a control character ** (0 - 31 or 127) */ iscntrl(c) char *c; { /* c is simulated unsigned integer */ return ((c <= 31) || (c == 127)); }  #include stdio.h #include clib.def extern int _device[]; /* ** Determine if fd is the console */ iscons(fd) int fd; { return(_device[fd] == CPMCON); }  /* ** return "true" if c is a decimal digit */ isdigit(c) int c; { return (c<='9' && c>='0'); }  /* ** return "true" if c is a graphic character ** (33 - 126) */ isgraph(c) int c; { return (c>=33 && c<=126); }  /* ** return "true" if c is lower-case alphabetic */ islower(c) int c; { return (c<='z' && c>='a'); }  /* ** return "true" if c is a printable character ** (32 - 126) */ isprint(c) int c; { return (c>=32 && c<=126); }  #define NOCCARGC /* ** return "true" if c is a punctuation character ** (all but control and alphanumeric) */ ispunct(c) int c; { return (!isalnum(c) && !iscntrl(c)); }  /* ** return "true" if c is a white-space character */ isspace(c) int c; { /*first check gives quick exit in most cases*/ return (c<=' ' && (c==' ' || (c<=13 && c>=9))); }  /* ** return "true" if c is upper-case alphabetic */ isupper(c) int c; { return (c <= 'Z' && c >= 'A'); }  /* ** return "true" if c is a hexadecimal digit ** (0-9, A-F, a-f) */ isxdigit(c) int c; { return ((c<= 'f' && c >= 'a') || (c<= 'F' && c >= 'A') || (c<= '9' && c >= '0')); }  #define NOCCARGC /* ** itoa(n,s) - Convert n to characters in s */ itoa(n,s) char *s; int n; { int sign; char *ptr; ptr = s; if ((sign = n) < 0) /*record sign*/ n = -n; /*make positive*/ do { /* generate digits in reverse order */ *ptr++ = n % 10 + '0'; /*get next digit*/ } while ((n = n / 10) > 0); /*delete it*/ if (sign < 0) *ptr++ = '-'; *ptr = '\0'; reverse(s); }  #define NOCCARGC /* ** itoab(n,s,b) - Convert "unsigned" n to characters in s ** using base b ** Note: this is a nonstandard function. */ itoab(n, s, b) int n; char *s; int b; { char *ptr; int lowbit; ptr = s; b >>= 1; do { lowbit = n & 1; n = (n >> 1) & 32767; *ptr = ((n % b) << 1) + lowbit; if(*ptr < 10) *ptr += '0'; else *ptr += 55; ++ptr; } while (n /= b); *ptr = 0; reverse(s); }  #include stdio.h /* ** itod -- convert nbr to signed decimal string of width ** right adjusted, blank filled; returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itod(nbr, str, sz) int nbr; char str[]; int sz; { char sgn; if(nbr<0) {nbr = -nbr; sgn='-';} else sgn=' '; if(sz>0) str[--sz]=NULL; else if(sz<0) sz = -sz; else while(str[sz]!=NULL) ++sz; while(sz) { str[--sz]=(nbr%10+'0'); if((nbr=nbr/10)==0) break; } if(sz) str[--sz]=sgn; while(sz>0) str[--sz]=' '; return str; } e feof() and ferror() to determine file status. */ read(fd, buf, n) int fd, n; char *buf; { char *cnt; /*fake unsigned* #include stdio.h /* ** itoo -- convert nbr to octal string of length sz ** right adjusted, blank filled; returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itoo(nbr, str, sz) int nbr; char str[]; int sz; { int digit; if(sz>0) str[--sz]=0; else if(sz<0) sz = -sz; else while(str[sz]!=0) ++sz; while(sz) { digit=nbr&7; nbr=(nbr>>3)&8191; str[--sz]=digit+48; if(nbr==0) break; } while(sz) str[--sz]=' '; return str; } -sz]=sgn; while(sz>0) str[--sz]=' '; return str; } #include stdio.h /* ** itou -- convert nbr to unsigned decimal string of length sz ** right adjusted, blank filled; returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itou(nbr, str, sz) int nbr; char str[]; int sz; { int lowbit; if(sz>0) str[--sz]=NULL; else if(sz<0) sz = -sz; else while(str[sz]!=NULL) ++sz; while(sz) { lowbit=nbr&1; nbr=(nbr>>1)&32767; /*divide by 2*/ str[--sz]=((nbr%5<<1)+lowbit+'0'); if((nbr=nbr/5)==0) break; } while(sz) str[--sz]=' '; return str; } 029, 030,031,032,033,034,035,036,037,038,039, 040,041,042,043,044,045,046,047, /**** 0 to 9 ****/ 065,066, #include stdio.h /* ** itox -- convert nbr to hex string of length sz ** right adjusted, blank filled; returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itox(nbr, str, sz) int nbr; char str[]; int sz; { int digit, offset; if(sz>0) str[--sz]=0; else if(sz<0) sz = -sz; else while(str[sz]!=0) ++sz; while(sz) { digit=nbr&15; nbr=(nbr>>4)&4095; if(digit<10) offset=48; else offset=55; str[--sz]=digit+offset; if(nbr==0) break; } while(sz) str[--sz]=' '; return str; } ternal /* ** left -- left adjust and terminate a string */ left(str) char *str; { char *str2; str2=str; while(*str2==' ') ++str2; while(*str++ = str2++); } byte ** if sz = 0 find end of string ** if sz < 0 use last byte for #define NOCCARGC /* ** lexcmp(s, t) - Return a number <0, 0, or >0 ** as s is <, =, or > t. */ lexcmp(s, t) char *s, *t; { while(*s == *t) { if(*s == 0) return (0); ++s; ++t; } return (lexorder(*s, *t)); } /* ** lexorder(c1, c2) - Return a number <0, 0, or >0 ** as c1 is <, =, or > c2, based on ** based on lexicographical (dictionary) ** collating sequence. */ char _lex[128] = { /**** NUL to / ****/ 000,001,002,003,004,005,006,007,008,009, 010,011,012,013,014,015,016,017,018,019, 020,021,022,023,024,025,026,027,028,029, 030,031,032,033,034,035,036,037,038,039, 040,041,042,043,044,045,046,047, /**** 0 to 9 ****/ 065,066,067,068,069,070,071,072,073,074, /**** : ; < = > ? @ ****/ 048,049,050,051,052,053,054, /**** A to Z ****/ 075,076,077,078,079,080,081,082,083,084,085,086,087, 088,089,090,091,092,093,094,095,096,097,098,099,100, /**** [ \ ^ _ ` ****/ 055,056,057,058,059,060, /**** a to z ****/ 075,076,077,078,079,080,081,082,083,084,085,086,087, 088,089,090,091,092,093,094,095,096,097,098,099,100, /**** { | } ~ ****/ 061,062,063,064, /**** DEL ****/ 101 }; lexorder(c1, c2) char c1, c2; { return(_lex[c1] - _lex[c2]); } =, or > c2, based on ** ba /* ** lexorder(c1, c2) - Return a number <0, 0, or >0 ** as c1 is <, =, or > c2, based on ** based on lexicographical (dictionary) ** collating sequence. */ char _lex[128] = { /**** NUL to / ****/ 000,001,002,003,004,005,006,007,008,009, 010,011,012,013,014,015,016,017,018,019, 020,021,022,023,024,025,026,027,028,029, 030,031,032,033,034,035,036,037,038,039, 040,041,042,043,044,045,046,047, /**** 0 to 9 ****/ 065,066,067,068,069,070,071,072,073,074, /**** : ; < = > ? @ ****/ 048,049,050,051,052,053,054, /**** A to Z ****/ 075,076,077,078,079,080,081,082,083,084,085,086,087, 088,089,090,091,092,093,094,095,096,097,098,099,100, /**** [ \ ^ _ ` ****/ 055,056,057,058,059,060, /**** a to z ****/ 075,076,077,078,079,080,081,082,083,084,085,086,087, 088,089,090,091,092,093,094,095,096,097,098,099,100, /**** { | } ~ ****/ 061,062,063,064, /**** DEL ****/ 101 }; lexorder(c1, c2) char c1, c2; { return(_lex[c1] - _lex[c2]); } =, or > c2, based on ** #define NOCCARGC #include stdio.h /* ** Memory allocation of size bytes. ** size = Size of the block in bytes. ** returns the address of the allocated block, ** else NULL for failure. */ malloc(size) char *size; { return (_alloc(size, NO)); } ,001,002,003,004,005,006,007,008,009, 010,011,012,013,014,015,016,017,018,019, 020,021,022,023,024,025,026,027, #include stdio.h /* ** otoi -- convert unsigned octal string to integer nbr ** returns field size, else ERR on error */ otoi(octstr, nbr) char *octstr; int *nbr; { int d, t; d=0; *nbr=0; while((*octstr>'0')&(*octstr<='7')) { t=*nbr; t=(t<<3) +(*octstr++ - '0'); if ((t>=0)&(*nbr<0)) return ERR; d++; *nbr=t; } return d; } 8,029, 030,031,032,033,034,035,036,037,038,039, 040,041,042,043,044,045,046,047, /**** 0 to 9 ****/ 065,06 #define NOCCARGC /* ** Place n occurences of ch at dest. */ pad(dest, ch, n) char *dest, *n; int ch; { /*n is a fake unsigned integer*/ while(n--) *dest++ = ch; }  d, t; d=0; *nbr=0; while((*octstr>'0')&(*octstr<='7')) { t #define NOCCARGC #include stdio.h #include clib.def /* ** Poll for console input or interruption */ poll(pause) int pause; { int i; i = _bdos(DCONIO, 255); if(pause) { if(i == PAUSE) { while(!(i = _bdos(DCONIO, 255))) ; if(i == ABORT) exit(0); return (0); } if(i == ABORT) exit(0); } return(i); }  if(d #define NOCCARGC #include stdio.h /* ** Write character to standard output */ putchar(ch) int ch; { return(fputc(ch, stdout)); } 093,094,095,096,097,098,099,100, /**** { | } ~ ****/ 061,062,063,064, /**** DEL ****/ 101 #define NOCCARGC #include stdio.h /* ** Write string to standard output */ puts(string) char *string; { fputs(string, stdout); fputc('\n', stdout); } 100, /**** { | } ~ ****/ 061,062,063,064, /**** DEL ****/ 101 #define NOCCARGC #include stdio.h #include clib.def /* ** Rename a file. ** from = address of old filename. ** to = address of new filename. ** Returns NULL on success, else ERR. */ rename(from, to) char *from, *to; { char fcb[FCBSIZE]; pad(fcb, NULL, FCBSIZE); if(!_newfcb(to, fcb) || _bdos(OPNFIL, fcb) != 255) { _bdos(CLOFIL, fcb); return (ERR); } if(_newfcb(from, fcb) && _newfcb(to, fcb+NAMEOFF2) && _bdos(RENAME, fcb) != 255) return (NULL); return (ERR); } ,005,006,007,008,009, 010,011,012,013,014,015,016,017,018,019, 020,021,022,023,024,025,026,027,02 #define NOCCARGC /* ** Reverse a string in place. */ reverse(s) char *s; { char *j; int c; j = s + strlen(s) -1; while(s < j) { c = *s; *s++ = *j; *j-- = c; } } CCDECI, CCINCI, CCDDPI, CCPDPI, CCPINT, PINT #define NOCCARGC /* ** Rewind file to beginning. */ rewind(fd) int fd; { return(cseek(fd, 0, 0)); } rlen(s) -1; /* ** sign -- return -1, 0, +1 depending on the sign of nbr */ sign(nbr) int nbr; { if(nbr>0) return 1; if(nbr==0) return 0; return -1; }  *s++ = *j; *j-- = c; } } CCDECI, CCINCI, CCDDPI, CCPDPI, CCPINT, PINT /* ** STDIO.H -- Standard Small-C Definitions ** ** Copyright 1984 L. E. Payne and J. E. Hendrix ** ** Keyed in from DDJ by Earl Boebert */ #define stdin 0 #define stdout 1 #define stderr 2 #define ERR (-2) #define EOF (-1) #define YES 1 #define NO 0 #define NULL 0 #define CR 13 #define LF 10 #define BELL 7 #define SPACE ' ' #define NEWLINE CR /*make consistent with Small C*/  /* ** Concatenate to end of s. ** s must be long enough. */ strcat(s, t) char *s, *t; { char *d; d = s; --s; while(*++s) ; while(*s++ = *t++) ; return(d); } ; } } CCDECI, CCINCI, CCDDPI, CCPDPI, CCPINT, PINT /* ** return pointer to 1st occurence of c in str, else 0 */ strchr(str, c) char *str, c; { while(*str) { if(*str == c) return (str); ++str; } return (0); } ; } } CCDECI, CCINCI, CCDDPI, CCPDPI, CCPINT, PINT /* ** return <0, 0, >0 according to ** st */ strcmp(s, t) char *s, *t; { while(*s == *t) { if(*s == 0) return (0); ++s; ++t; } return (*s - *t); }  CCDECI, CCINCI, CCDDPI, CCPDPI, CCPINT, PINT /* ** copy t to s */ strcpy(s, t) char *s, *t; { char *d; d = s; while (*s++ = *t++) ; return (d); } if /* ** return length of s */ strlen(s) char *s; { char *t; t = s - 1; while (*++t) ; return (t - s); } if /* ** concatenate n bytes max from t to end of s ** s must be large enough */ strncat(s, t, n) char *s, *t; int n; { char *d; d = s; --s; while(*++s) ; while(n--) { if(*s++ = *t++) continue; return (d); } *s = 0; return (d); } CCAND, CCEQ, CCNE, CCGT, CCLE, CCGE, CCLT, CCCMP external CCUGE, CCULT, CCUGT, CCULE, CCUCMP, CCASR, CCAS /* ** strncmp(s,t,n) - Compares two strings for at most n ** characters and returns an integer ** >0, =0, <0 as s is >t, =t, or 0) { if(*d++ = *sour++) continue; while(n-- > 0) *d++ = 0; } *d = 0; return (dest); }  */ itou(nbr, str, sz) int nbr; char str[]; int sz; { int lowbit; if(sz>0) str[--sz]=NULL; else if( /* ** strrchr(s,c) - Search for rightmost occurence of c. ** s = pointer to string being searched ** c = character to search for ** Returns pointer to rightmost c or NULL. */ strrchr(s, c) char *s, c; { char *ptr; ptr = 0; while(*s) { if(*s==c) ptr = s; ++s; } return (ptr); }  return (0); } T, CCUGT, CCULE, CCUCMP, CCASR, CCAS /* ** return ASCII equivalent of c. */ toascii(c) int c; { return(c); } g searched ** c = character to searc /* ** return lower-case of c if upper-case, else c */ tolower(c) int c; { if(c<='Z' && c>='A') return (c+32); return (c); } pointer to rightmost c or NULL. */ strrchr(s, c) char *s, c; { char *ptr; ptr = 0; while(*s) { /* ** return upper-case of c if lower-case, else c */ toupper(c) int c; { if(c<='z' && c>='a') return (c-32); return (c); } pointer to rightmost c or NULL. */ strrchr(s, c) char *s, c; { char *ptr; ptr = 0; while(*s) { #define NOCCARGC #include stdio.h extern _nextc[]; /* ** Put c back in file fd. ** Entry: c = character to put back ** fd = file descriptor ** Returns c if successful, else EOF */ ungetc(c, fd) int c, fd; { if(!_mode(fd) || _nextc[fd]!=EOF || c==EOF) return (EOF); return (_nextc[fd]=c); } return (0); } T, CCUGT, CCULE, CCUCMP, CCASR, CCAS #define NOCCARGC #include stdio.h #include clib.def /* ** Unlink (delete) the named file. ** Entry: fn = Null-terminated CP/M file name. ** May be prefixed by letter of drive. ** Returns NULL if successful, else ERR. */ unlink(fn) char *fn; { char fcb[FCBSIZE]; pad(fcb, NULL, FCBSIZE); if(_newfcb(fn, fcb) && _bdos(DELFIL, fcb) != 255) return (NULL); return (ERR); } #asm delete equ unlink entry delete #endasm  /**** 0 to 9 ****/ 065,06 #include stdio.h /* ** utoi -- convert unsigned decimal string to integer nbr ** Returns field size if successful, else ERR. */ utoi(decstr, nbr) char *decstr; int *nbr; { int d, t; d=0; *nbr = 0; while((*decstr>='0')&(*decstr<='9')) { t=*nbr; t=(10*t) + (*decstr++ - '0'); if ((t>=0)&(*nbr<0)) return ERR; d++; *nbr=t; } return d; } NU #include stdio.h /* ** xtoi -- convert hex string to integer nbr ** Returns field size if successful, else ERR. */ xtoi(hexstr, nbr) char *hexstr; int *nbr; { int d, t; d=0; *nbr = 0; while(1) { if((*hexstr>='0')&(*hexstr<='9')) t=48; else if((*hexstr>='A')&(*hexstr<='F')) t=55; else if((*hexstr>='a')&(*hexstr<='f')) t=55; else break; if(d<4) ++d; else return ERR; *nbr=*nbr<<4; *nbr=*nbr+(*hexstr++)-t; } return d; } 0 to 9 ****/ 065,06 #define NOCCARGC #include stdio.h #include clib.def /* ** Close fd. ** Entry: fd = File descriptor for file to be closed. ** Returns NULL for success, otherwise ERR. ** Modified to guarantee that an EOF character appears ** after the last data character in the file. */ extern int _fcbptr[], _status[], _device[]; fclose(fd) int fd; { if(!_mode(fd)) return (ERR); if(!isatty(fd)) { fputc('\32',fd); /*make sure there is an EOF (DDJ anomaly)*/ if(fflush(fd) || _bdos(CLOFIL,_fcbptr[fd])==255) return (ERR); } return (_status[fd]=_device[fd]=NULL); } er C). ** de = CP/M parameter (re #define NOCCARGC #include stdio.h #include clib.def extern int _status[], _dirty[]; /*error in DDJ*/ /* ** Flush records to disk. ** Entry: fd = File descriptor of pertinent file. ** Returns NULL on success, otherwise ERR. ** References to auxbuf() deleted. */ fflush(fd) int fd; { if(!_mode(fd)) return (ERR); if(!isatty(fd) && _dirty[fd] && _sector(fd, WRTRND)) { _seterr(fd); return (ERR); } return (NULL); } UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUvCSYSLIB.Ci ! "#$%&'()o*,+-.0/123547698:;<=>@?ABCDEFGHIJLKMNPOQRSTUVXWYZ[]^_a\`ecgdbfhHA2i!ы:<ЁÅӺWd-W#dL"\pW m>wUb͇V_w @2ɘG+MK )" '^$cċ[C>u fdd$Wv@2^*B''_P>6*1)c xnf4Y_FA `+"@x##!!:<O0f֗HFFB~#[,A6V%FHm`fMY"[Xm&:72Ro% _۫3y{uXzμJ%_^DgͿ=V`62R8mSsD!k{~B'_B'_B'_g^ǁ?:{?od6b+\,QH^K˹K˹Keo,P$VG)rod6He% _ϭl,Ћo"f`1{٦bBs+Әo  pMMV6jx[m^64HmڑX,l5T57v=)22 5^d 7nѴ;XFFj{}oksV6 ^ߚHHA2sȺ7t lp-WY  I6HTGK(B`p{W|n>qs7s]!NSHFFB 7O6H s Ws HA2J w1^߬B}OV U&@jVB~NSUb0iLWoxj nUbZXӥiρ{yG^I*19M] MyR6 ^ߴ滑Cs_H [k⽞99^G?7jxD<^D㽪5XbxsH3RoG>:O]E/ TӪwU{Uk؁j^9~?N9:gύ`~vbρ9#%~thAzwu5IO+V@cxsF^${㽞RR$"/{s=Ub0Ӂ& E22Rz:_s|+~M֯+ȁyrHHmNNׁ~ -}㽞 I6H4,VvWۉq#)XbxsvO^5^皁p|Hޫ&MZsr6ޫZvos DM܁p|ݣip) =Rxz$$ S9# 1{$##!ɘ^ $Ʌ")17s=U{$GM'RIt {zs@8~.}s [ْWkr ^jɟC/"?&'Rl (%gנS˯=Z8"*|uXz]&HH-HᅲopG$=D [Ŷtb*>oKή3/ң|sRM}WG$=D [Ŷtbj[rv"*=xM9:g?Z/5!҈Iz98m5Zz4ߖ]:,J.}{7SIlٟƷ{:u9Z?RD}:Uk)˖Zz-Ћ毟֯+Rg,opS-9{7 ^\\Gϝ6<մ~]@Γ||8HHm|78)˖\Truz9#m٫5plےWk+-9{J:2qjf4" ۫iՋ44y5{5_W + ldvoRs@ ZQ@꜍o&u>XGsQ@bc^o6IjEIT[qM&TWs6PߖZ/XRl (%gVW% 9:g{m٫5yH|s )c&362R қk9wR7sR=.7?R[ _3~"uΪ-F$Hopr/',Q9SM5].}s u }%gpETz u ~V[7sÙifiҁysV?W/^#y789񿖯LKrNYӥipr3KrNHj9$Hopr% 9'uz4͚.]Oqp9:OےWkrJ:,JΓwHRYV6wwFF< ˉ/KrNh5]~[T-7H'{m٫5yH'қܹ:ϵH'so[=jKd{-9{/-Qҋ@<9Ԃw 4M/Gi{-9{%k g^DK/]&Hl)t y \%^ *%M{H4hZB'&s=~n^A2ħȞB)0ͫ"-`šHtΐԩZ'WbEoMb:!O5S(1 Xyu!7S(Ϲ:ɟޫ&sMRHޫ&xo&uth/uz9Z^&ߜiՋ{OYԩZkӫ݁9|W&ߜZ;:g?Zn^՚Ԃ$UM=.9㽪5:5_ӧ˹{5}*$UM^Ӝ kzx@jKMԜJ_Z,&utډuz9Z^|{\s |iρ~ !ɘB MۻZ0p&s=`$##]q;C"4}46s/DUϝ~qFCJzYu\%ssV? b/]Jx1~sV?73,VkŁ98##:gAzհU= bܯ^{Jx1W sJw9#n~9:gxU@@j?ddL| Ym4P$##xO$Ar #u"u΂b[r%Ɓj`62RI5W)>{󹆽;:O'':/͜~~k!Γ }=j NNo (%g?7HeK<մZӥ'R ϛEz{q9:g@<8m٫@<WW7ݪiN_Bޜ~M_Z,ρyrG\ps5}*?:Ow7_yWkpS-9{szqr?:OS\y2wVgep]"4H3VмS%~䣲9 |33%fd)VH3ԗuGj ;:g@<oK^: Nc%g?:O.}_?R$;*hHH-H}S&<]~]>R&H-HobɝÙ'Rl|78)˖\Truz9:g7&H|߯@@jq毟@B 1ՙ3{9xHFFB 1^:^|*"Ux)rshrHFF r/Us{ OV Us,ԁVþ@8~{~"u:N?o^M9x_ZsV?"*@UϽ:,J%3/YuܫҋTrrF uΪ^^D󗖋Tr8"*@@j`8mٟ~"u&ޮPj\W\ .]±:gsS˯.o~yYu\ĕYu\Zb[rs9:_iҁ98##:Ojbے_EbZwikg&<]/-ρy4&Xj Nc%goN5\msrΓ4&XjUdڑ:m@@jqjHl)T_\5׭6qE22R~)jx NNo&+zy>RxU@j?ddL^`sXݢɅ")z{ nrG?Zޔ=Oq_ρ7@j۽iL^B's/Xρ.}_?R$$ctfݿSk^V@1ddL;+bg E22Rp;+~{ nrG?ZwZ@j$u%goNK@jsr^6PߖZ%HldLYm/CXorѫ&wn:ku ɉK3eKH-%V''7^$u%g689yis[ s kGڒW.}y-@B 1:U[̽$##!ɘy79"f߁p|.? dd` =U{$wMujz.($toKH=. Hl5HǿI&;$c`n@= laXfdd"=~7Hm{-9{%k_Z.@B 1|HǿI&dd@Ez{ nrG?[rN5d/-Q~ !ɘ^.%V}oɅ")yZorOM'RoK^ZETz HHA2FghbEv: uo zwEߊ z{[ P$##7 szGU0'R:Z^_z[~_?O?:gAzz <: rYxj <::g⽚H|_x@@jq_W @j?ddΜtBjo^Vdd$$ \<4z=.P$c{EFTE:!O5^m |pw7o^>HtZT{޼.ͫdLü!:!Ou.ͫӟP$##''W?~W'R?@B!qg ]q-bw:K8`qB'䩦ѫ o|{R ;K8upvNSMW_?N:g9{,Xosx{H3?vpt߷ sup笮upONH3 @g óH3 Ug ,ѱxw yX2f~ !;^#/HU0 o` E}"f߁p|.? dd` =U{$wMujz.($toKH=. Hl5HǿI&;$c`n@=