home *** CD-ROM | disk | FTP | other *** search
-
- ;-----------------------------------------------------------------------
- ; Small-C Run-time Library (ASM Version) May 10, 1988
- ;
- ; V5d As of July 29, 1983 7:47am (br)
- ; Fixed GETC()/CGET() so it skips check for CR when
- ; calling GETCHAR().
- ; - Bill Randle
- ;
- ; V5c As of July 27, 1983 9:55 pm
- ; Fixed bug in initialization of RSTDIN and RSTDOUT.
- ; Fixed bug in PUTS().
- ; - Bill Randle
- ;
- ; V5b As of July 19, 1983 9:50 pm
- ; Fixed bug in FCLOSE().
- ; - Bill Randle
- ;
- ; V5a As of April 14, 1983 12:55 pm
- ; Masked parity bit in compares for EOL, LF & ^Z.
- ; - Bill Randle
- ;
- ; V5 As of April 12, 1983 12:30 am
- ; Modified to reuse package for Small-C, ver 2.
- ; Removed "QZ" in front of names.
- ; Added runtime initialization and command line
- ; processing from RUNTIM.MAC [by Bill Danielson, 3/83].
- ; Added I/O redirection for stdin and stdout.
- ; Added FPUTS(), FGETS(), DOLDDR(), DOLDIR(),
- ; UNLINK() and ABORT() functions.
- ; - Bill Randle
- ;
- ; V4d As of July 16, 1980 9:00 pm
- ; Added EXIT() function
- ; - GTF
- ;
- ; V4c As of July 9, 1980 9:15 pm
- ; Fixed bug in CPMIO which returned wrong error status.
- ; Added PUTS() function
- ; Un-hardwired I/O buffer count.
- ; Made GETCHAR() print LF after reading CR.
- ; Made GETCHAR() return -1 on EOF (=CTRL-Z)
- ; Added EOL and LF equates, instead of magic numbers
- ; - GTF
- ;
- ; V4b As of July 7, 1980 3:00 pm
- ; Changed putc() to test code returned by cput()
- ; - GTF
- ;
- ; V4 As of June 26, 1980 12:15pm
- ; Changed all @'s and ?'s to "QZ" for ASM compatibility
- ; - GTF
- ;
- ; V3b As of June 9, 1980 12pm
- ; corrected cp to chp in @gets
- ; changed lower case to hex constants in @fopen and fcb
- ; - RJ
- ;
- ;------------------------------------------------------------------
- ;
- ; May need following statement when using ASM
- ;
- ;;; ORG 100H
- ;
- ;
- ;
- JMP START
- ;
- ; Delete following extern when using ASM
- ;
- LINK EQU 1
- ;
- IF LINK
- PUBLIC CPM, PUTC, FPUTC, PUTCHAR, GETC, FGETC, GETCHAR
- PUBLIC FOPEN, UNLINK, FCLOSE, ABORT, EXIT, PUTS, FPUTS
- PUBLIC GETS, FGETS
- ;
- EXTRN MAIN, CCDSGI, CCSXT
- ENDIF ; LINK
- ;
- ; ========================================
- ; I/O subroutines for CP/M
- ; By Glen Fisher
- ; The Code Works(tm)
- ; [modified by Bill Randle]
- ; ========================================
- ;
- NULL EQU 0 ; Pointer to nothing
- FCBSIZE EQU 36 ; Size, in bytes, of an FCB
- NEXTP EQU 0 ; Offset to next-character pointer in I/O structure
- UNUSED EQU 2 ; Offset to unused-positions-count in I/O structure
- BUFFER EQU 4 ; Offset to disk sector buffer in I/O structure
- FLAG EQU 33 ; File-type flag byte (in unused part of FCB)
- FREEFLG EQU 128 ; This I/O structure is available for the taking
- EOFFLG EQU 2 ; The end of this file has been hit
- WRTFLG EQU 1 ; This file open for writing
- BUFSIZ EQU 128 ; How long the sector buffer is
- NBUFS EQU 4 ; Number of I/O buffers (change buffer declarations, too)
- ;
- ; CP/M system call codes
- ;
- CLOSE EQU 16 ; Close a file
- CPMSTR EQU 9 ; Print '$' delimited string on console
- CREATE EQU 22 ; Make a file
- DMA EQU 26 ; Set DMA (I/O address)
- DELETE EQU 19 ; Delete a file
- GETCH EQU 1 ; Read character from console
- GETSTR EQU 10 ; Read string from console
- LSTOUT EQU 5 ; Write character to list device
- OPEN EQU 15 ; Open a file
- PUTCH EQU 2 ; Write character to console
- QUERY EQU 25 ; Get logged-in drive id
- READ EQU 20 ; Read a sector
- SELECT EQU 14 ; Log-in a drive
- WRITE EQU 21 ; Write a sector
- ;
- LF EQU 10 ; Line feed
- EOL EQU 13 ; End-of-line character (=carriage return)
- CTRLZ EQU 26 ; End-of-file mark for text files
- TBUFF EQU 80H ; Address of default I/O address
- BDOS EQU 5 ; Entry point to CP/M BDOS
- CPMARG EQU 80H ; CP/M command line
- MAXARG EQU 32 ; Maximum number of args in input line
- STDIN EQU 0 ; Default for stdin
- STDOUT EQU 1 ; Default for stdout
- STDERR EQU 2 ; Default for stderr
- STDLIST EQU 4 ; Default for stdlist
- ;
- DFLTDSK:DS 1 ; Drive to use if no drive is named
- UNIT: DS 2 ; I/O structure address to act on
- IP: DS 2 ; Int *ip;
- CHP: DS 2 ; Char *chp;
- DP: DS 2 ; Char *dp;
- FILE: DS 2 ; File name
- MODE: DS 2 ; Char *mode;(read or write)
- ZCH: DS 2 ; Char ch;
- ZT: DS 2 ; Int t;
- FN: DS 2 ; Int fn; i/o function (for cpmio)
- ;
- SVCHP: DS 2 ; Char *svchp; saved character pointer
- RSTDIN: DS 2 ; Int rstdin; unit of redirected stdin
- RSTDOUT:DS 2 ; Int rstdout; unit of redirected stdout
- ;
- ; First thing, we save CPM's stack pointer and current disk and initial-
- ; ize STDIN and STDOUT. Second thing, we run through the CPM input line
- ; and modify it so that we can pass the C program the command line in
- ; the ARGC, ARGV form that it expects
- ;
- ; HL = pointer to next argv entry
- ; DE = pointer to next character in command line
- ; B = number of characters left in line
- ; C = argument count (argc)
- ;
- START: LXI H,0 ; Get CPM's stack pointer
- DAD SP
- SHLD STACK ; Save it for later
- MVI C,QUERY ; Get logged-in disk
- CALL BDOS
- INR A ; Make it so it will work in FCB
- STA DFLTDSK
- LDA BDOS+2 ; Get base of BDOS
- MOV H,A ; Save page in HL
- MVI L,0
- SPHL ; Set stack pointer
- LXI H,STDIN
- SHLD RSTDIN ; Init RSTDIN
- LXI H,STDOUT
- SHLD RSTDOUT ; Init RSTDOOUT
- MVI C,0 ; Init ATGC
- LXI H,ARGV ; Pointer to first entry of ARGV array
- ;
- ; Unfortunately, CPM does not tell us what the first word of
- ; the command line was (the name of pgm), so we fake
- ; it by pointing it to a ascii string with 'pgmname' in it
- ;
- LXI D,PGM ; Pointer to 'pgmname' string
- CALL SVARG ; Save next argument
-
- ; Ok, now for the real stuff. Set DE pair to point to CPM command line
- ; and start searching for arguments
- ;
- LXI D,CPMARG ; Pointer to CPM argument line
- LDAX D ; Load # character in line
- MOV B,A ; Save it in B
- ;
- NXTSP: INX D ; Point to next character
- DCR B ; Decrement character count
- JM ENDCMD ; End of cmd line
- LDAX D ; Load next character in line
- CPI ' ' ; Space?
- JZ NXTSP ; Yes...continue searching
- CPI '>' ; Redirect output?
- JZ RDOUT ; Yes...open the file for output
- CPI '<' ; Redirect input?
- JZ RDINP ; Yes...open the file for input
- CALL SVARG ; Nope, save starting point of this arg
- ;
- ; Loop looking for either end of line of a space
- ;
- NXTCH: INX D ; Point to next character
- DCR B ; Decrement character count
- JM ENDWRD ; End of cmd line, but need to end arg
- LDAX D ; Load next character in line
- CPI ' ' ; Space?
- JNZ NXTCH ; Nope...keep looking
- MVI A,0 ; Yes, replace it with a zero byte
- STAX D
- JMP NXTSP ; Look for start of next argument
- ;
- ENDWRD: MVI A,0
- STAX D
- ;
- ENDCMD: MVI B,0 ; Zero B (BC now is 16 bit ATGC)
- PUSH B ; First arg to main procedure
- LXI H,ARGV ; Point to argv array
- PUSH H ; Second argument to main procedure
- MVI A,2 ; Load up the argument count
- CALL MAIN ; Transfer to the C world....
- JMP EXIT ; Return to CP/M
- ;
- SVARG: MOV M,E ; Save pointer to start of string
- INX H
- MOV M,D
- INX H
- INR C ; Increment ARGC
- RET
- ;
- ARGV: DS MAXARG*2
- ;
- PGM: DB 'PGMNAME',0
- ;
- RDINP: CALL DEBLNK ; Skip leading spaces
- JM RDERR ; End of line reached
- PUSH H
- CALL CPYNAM ; Copy filename to temp buffer
- PUSH D ; Save registers
- PUSH B
- LXI H,NAMBUF ; Begining of filename
- PUSH H
- LXI H,RDOPN ; Mode
- PUSH H
- CALL FOPEN ; Open the file
- POP D
- POP D
- MOV A,H
- ORA L ; Check return status
- JZ RDERR
- SHLD RSTDIN ; Save unit for redirected input
- POP B ; Restore registers
- POP D
- POP H
- MVI A,0FFH
- CMP B ; End of command line?
- JZ ENDCMD
- JMP NXTSP ; Get next argument
- ;
- RDOUT: CALL DEBLNK ; Skip leading spaces
- JM RDERR ; End of line reached
- PUSH H
- CALL CPYNAM ; Copy filename to temp buffer
- PUSH D ; Save registers
- PUSH B
- LXI H,NAMBUF ; Begining of filename
- PUSH H
- LXI H,WROPN ; Mode
- PUSH H
- CALL FOPEN ; Open the file
- POP D
- POP D
- MOV A,H
- ORA L ; Check return status
- JZ RDERR
- SHLD RSTDOUT ; Save unit for redirected input
- POP B ; Restore registers
- POP D
- POP H
- MVI A,0FFH
- CMP B ; End of command line?
- JZ ENDCMD
- JMP NXTSP ; Get next argument
- ;
- DEBLNK: INX D ; Skip leading spaces
- DCR B
- RM ; End of line reached
- LDAX D
- CPI ' '
- JZ DEBLNK
- RET
- ;
- CPYNAM: LXI H,NAMBUF ; Copy filename to temp buffer
- PUSH B ; Save reg C
- MVI C,16 ; Maximum filename length
- ;
- CPY1: MOV M,A
- INX D
- INX H
- DCR B
- JM ENDNAM
- DCR C
- JZ RDERR
- LDAX D
- CPI ' '
- JNZ CPY1
- ;
- ENDNAM: MVI M,0
- POP H
- MOV C,L ; Restore reg C
- RET
- ;
- RDERR: LXI D,RDEMSG ; Error message
- MVI C,CPMSTR
- CALL BDOS ; Make sure it gets put on the terminal
- JMP EXIT
- ;
- RDOPN: DB 'r',0
- WROPN: DB 'w',0
- NAMBUF: DS 16
- RDEMSG: DB 'IOLIB: Unable to open < or > file$'
- ;
- ; LLDDR (source, dest, n)
- ;
- DOLDDR: INX SP ; Skip over return address
- INX SP
- POP B ; Load n
- POP D ; Load destination
- POP H ; Load source
- DB 0EDH, 0B8H ; Do LDDR instruction
- PUSH H ; Restore stack
- PUSH D
- PUSH B
- DCX SP
- DCX SP
- RET
- ;
- ; DOLDIR (source, dest, n)
- ;
- DOLDIR: INX SP ; Skip over return address
- INX SP
- POP B ; Load n
- POP D ; Load destination
- POP H ; Load source
- DB 0EDH, 0B0H ; Do LDIR instruction
- PUSH H ; Restore stack
- PUSH D
- PUSH B
- DCX SP
- DCX SP
- RET
- ;
- ; End of memory function
- ; Returns top memory location in HL
- ;
- TOPOFMEM:
- LDA BDOS+2 ; Get base of BDOS
- MOV H,A ; Save page in HL
- MVI L,0
- RET
- ;
- ; Return the first free location
- ;
- FIRSTFREE:
- LHLD MEMRY$
- RET
- ;
- MEMRY$: DW 0
- ;
- ; This assembly routine allows CP/M calls from Small C.
- ;
- ; CPM (cpmfunction#, inputparameter)
- ;
- ; Since this function returns whatever is returned in register
- ; it cannot be used to call ReturnVersionNumber, ReturnLoginVector,
- ; WriteProtectDisk, or GetAddr.
- ;
- CPM: POP H ; Pop return address
- POP D ; Pop input parameter in DE register pair
- POP B ; Pop function code into C register
- PUSH B ; Restore stack
- PUSH D
- PUSH H
- CALL BDOS ; Call CP/M
- MOV L,A ; Sign extend A into HL register pair
- RLC
- SBB A
- MOV H,A
- RET
- ;
- ; EXIT () Stop execution of the program, restore the logged-in drive
- ; and reboot CP/M
- ;
- EXIT: LHLD RSTDOUT
- MOV A,H
- ORA A ; See if STDOUT has been redirected
- JZ EXIT1
- PUSH H
- CALL FCLOSE ; If so, close the file
- POP B
- ;
- EXIT1: LDA DFLTDSK ; Grab orig. logged-in disk
- MOV E,A
- DCR E ; (cvt. back to 0-n)
- MVI C,SELECT ; And log it in again
- CALL BDOS
- LHLD STACK ; Load stack pointer
- SPHL
- JMP 0 ; Return to CP/M
- ;
- STACK: DW 0
- ;
- ; ABORT (reason)
- ;
- ABORT: POP B
- POP D
- PUSH D
- PUSH B
- PUSH D ; Error code
- LXI H,ABTMSG ; Load abort message
- PUSH H
- LXI H,STDERR
- PUSH H
- CALL FPUTS
- POP B
- POP B
- LXI H,2
- CALL CCDSGI
- PUSH H
- ;
- ; Someday this should write out the correct error code
- ;
- ; CALL OUTDEC## ; Inside C compiler
- POP B
- JMP EXIT
- ;
- ABTMSG: DB 0DH, 0DH, 'Aborted, reason = ',0
- ;
- ; GRABIO () Find an input buffer, and return its address. If there
- ; isn't one, return a NULL.
- ;
- GRABIO: MVI B,NBUFS
- LXI H,IOBUFS+FLAG
- LXI D,FCBSIZE+BUFFER+BUFSIZ
- MVI A,FREEFLG
- ;
- GRAB2: CMP M ; Flag byte == freeflg?
- JZ GRAB3 ; If so, found a free buffer
- DAD D ; On to next buffer
- DCR B
- JNZ GRAB2 ; If there is one...
- LXI H,NULL ; There ain't
- RET ; Give up
- ;
- GRAB3: MVI M,0 ; Mark buffer as taken
- LXI D,-FLAG ; Back up to buffer start
- DAD D
- RET ; And hand it back
- ;
- ; FREEIO (unit) Mmark a buffer as free
- ;
- FREEIO: POP B ; Save rtn addr
- POP H ; Get buffer address
- PUSH H ; Put the stack back together
- PUSH B
- LXI D,FLAG ; Find flag byte
- DAD D
- MVI M,FREEFLG ; Mark buffer as 'free'
- LXI H,NULL ; Return something
- RET
- ;
- IOBUFS: DS FCBSIZE-3
- DB FREEFLG,0,0
- DS BUFFER+BUFSIZ
- DS FCBSIZE-3
- DB FREEFLG,0,0
- DS BUFFER+BUFSIZ
- DS FCBSIZE-3
- DB FREEFLG,0,0
- DS BUFFER+BUFSIZ
- DS FCBSIZE-3
- DB FREEFLG,0,0
- DS BUFFER+BUFSIZ
- ;
- ; FOPEN (name,mode)
- ;
- FOPEN: POP B ; Get arguments
- POP H ; Mode
- SHLD MODE
- POP D
- XCHG
- SHLD FILE
- PUSH H
- PUSH D
- PUSH B
- CALL GRABIO ; Unit = grabio()
- SHLD UNIT
- MOV A,H ; If(unit==NULL)
- ORA ; Return(NULL)
- RZ
- LXI D,FCBSIZE ; Ip = unit+FCBSIZE
- DAD D
- SHLD IP
- LHLD IP ; Ip[NEXTP] = &ip[BUFFER]
- LXI D,BUFFER
- DAD D
- XCHG
- LHLD IP
- LXI B,NEXTP
- DAD B
- MOV M,E
- INX H
- MOV M,D
- LHLD UNIT ; Fcb(unit,name)
- PUSH H
- LHLD FILE
- PUSH H
- CALL FCB
- POP H
- POP H
- LHLD UNIT ; Cpmdisk(*unit)
- MOV L,M
- MVI H,0
- PUSH H
- CALL CPMDISK
- POP H
- LHLD MODE ; If(*mode=='r' || *mode=='R')
- MOV A,M
- CPI 72H ; 'r' ?
- JZ FOPIF0
- CPI 52H ; 'R' ?
- JNZ FOPIF1
- ;
- FOPIF0: MVI C,OPEN ; If(CPM(OPEN,unit)<0)
- LHLD UNIT
- XCHG
- CALL BDOS
- ORA A
- JP FOPIF2
- LHLD UNIT ; Freeio(unit)
- PUSH H
- CALL FREEIO
- POP H
- LXI H,NULL ; Return(NULL)
- RET
- ;
- FOPIF2: LHLD IP ; Ip[UNUSED] = 0
- LXI D,UNUSED
- DAD D
- LXI D,0
- MOV M,E
- INX H
- MOV M,D
- JMP FOPIF4
- ;
- ; Else if(*mode=='w' || *mode=='W')
- ;
- FOPIF1: LHLD MODE
- MOV A,M
- CPI 77H ; 'w'
- JZ FOPIFA
- CPI 57H ; 'W'
- JNZ FOPIF5
- ;
- FOPIFA: MVI C,DELETE ; Cpm(DELETE,unit)
- LHLD UNIT
- XCHG
- CALL BDOS
- MVI C,CREATE ; If(cpm(CREATE,unit)<0)
- LHLD UNIT
- XCHG
- CALL BDOS
- ORA A
- JP FOPIF3
- LHLD UNIT ; Freeio(unit)
- PUSH H
- CALL FREEIO
- POP H
- LXI H,NULL ; Return(NULL)
- RET
- ;
- FOPIF3: LHLD IP ; Ip[UNUSED] = BUFSIZ
- LXI D,UNUSED
- DAD D
- LXI D,BUFSIZ
- MOV M,E
- INX H
- MOV M,D
- LHLD UNIT ; Unit[FLAG] = WRITE_FL
- LXI D,FLAG
- DAD D
- MVI A,WRTFLG
- ORA M
- MOV M,A
- JMP FOPIF4
- ;
- FOPIF5: LHLD UNIT ; Else freeio(unit)
- PUSH H
- CALL FREEIO
- POP H
- LXI H,NULL ; Return(NULL)
- RET
- ;
- FOPIF4: LHLD UNIT ; Return(unit)
- RET
- ;
- ; FCLOSE (unit)
- ;
- FCLOSE: POP B
- POP H
- SHLD UNIT
- PUSH H
- PUSH B
- MOV A,H ; If (unit<256)
- ORA A ; /* assume stdin, stdout, etc. */
- MVI L,0
- RZ ; Return NULL
- LXI H,1 ; T = 1;
- SHLD ZT
- LHLD UNIT ; If(unit[FLAG] & WRITE_FL)
- LXI D,FLAG
- DAD D
- MOV A,M
- ANI WRTFLG
- JZ FCLIF1
- LXI H,CTRLZ ; Putc(CTRL_Z,unit)
- PUSH H
- LHLD UNIT
- PUSH H
- CALL PUTC
- POP H
- POP H
- LHLD UNIT ; Ip = unit + FCBSIZE
- LXI D,FCBSIZE
- DAD D
- SHLD IP
- LHLD IP ; Cp = ip[NEXTP]
- LXI D,NEXTP
- DAD D
- MOV E,M
- INX H
- MOV D,M
- XCHG
- SHLD CHP
- LHLD IP ; Dp = &ip[BUFFER]+BUFSIZ
- LXI D,BUFFER+BUFSIZ
- DAD D
- SHLD DP
- ;
- ; While(cp<dp)
- ;
- FCLWH1: LHLD CHP
- XCHG
- LHLD DP
- MOV A,D
- CMP H
- JC FCLWH2
- JNZ FCLWH3
- MOV A,E
- CMP L
- JNC FCLWH3
- ;
- ; *cp++ = CTRL_Z
- ;
- FCLWH2: LHLD CHP
- MVI M,CTRLZ
- INX H
- SHLD CHP
- JMP FCLWH1
- ;
- FCLWH3: LXI H,WRITE ; If(cpmio(WRITE,unit)<0)
- PUSH H
- LHLD UNIT
- PUSH H
- CALL CPMIO
- POP D
- POP D
- MOV A,H
- ORA A
- JP FCLIF4
- LXI H,0 ; T = 0;
- SHLD ZT
- ;
- FCLIF4:
- FCLIF3:
- FCLIF1: MVI C,CLOSE ; If(cpm(CLOSE,unit)<0)
- LHLD UNIT
- XCHG
- CALL BDOS
- ORA A
- JP FCLIF5
- LXI H,0 ; T = 0
- SHLD ZT
- ;
- FCLIF5: LHLD UNIT ; Freeio(unit)
- PUSH H
- CALL FREEIO
- POP H
- LHLD ZT ; Return(NULL+t)
- RET
- ;
- ; UNLINK(name)
- ;
- UNLINK: POP B
- POP D
- PUSH D
- PUSH B
- PUSH D ; Name
- LXI H,RDOPN ; Mode
- PUSH H
- CALL FOPEN ; Unit = fopen(name,'r')
- POP D
- POP D
- SHLD UNIT
- MVI C,DELETE ; Cpm(DELETE,unit)
- CALL BDOS
- LHLD UNIT ; Freeio(unit)
- PUSH H
- CALL FREEIO
- POP D
- RET ; Return;
- ;
- ; FCB (fp,name)
- ;
- FCB: POP H ; Get argumentss
- POP D ; Name
- POP B ; Fp
- PUSH B
- PUSH D
- PUSH H
- INX D ; If(name[1]==':')
- LDAX D
- DCX D
- CPI ':'
- JNZ FCBIF1
- LDAX D ; A = *name - '@'
- SUI 40H ; '@'
- INX D ; Name += 2
- INX D
- CPI 61H-41H ; If(A>'a'-'A') /* lower case? */
- JC FCBIF2
- SUI 61H-41H ; A -= 'a'-'A'
- JMP FCBIF2
- ;
- FCBIF1: LDA DFLTDSK ; Else A = default_drive
- ;
- FCBIF2: STAX B ; *fp++ = A
- INX B
- MVI H,' ' ; Fp = fcbfill(fp,name,' ',8
- MVI L,8
- CALL FCBFILL
- MVI L,3 ; Fp = fcbfill(fp,name,' ',3
- CALL FCBFILL
- MVI H,0 ; Fp = fcbpad(fp,0,4)
- MVI L,4
- CALL FCBPAD
- LXI H,16 ; Fp[16] = 0
- DAD B
- MVI M,0
- RET ; Return;
- ;
- ; FCBFILL (dest,name,pad,size)
- ; B D H L
- ;
- FCBFILL:MOV A,L ; While(L>0 && (A= *D)~='.' && A~=0)
- ORA A
- JZ FILL2
- LDAX D
- CPI '.'
- JZ FILL2
- CPI 0
- JZ FILL2
- CPI 61H ; If(A>='a' && A<='z')
- JC FILL1
- CPI 7AH+1 ; 'z' 9
- JNC FILL1
- SUI 61H-41H ; A = A - 'a' + 'A'
- ;
- FILL1: STAX B ; *B++ = A
- INX B
- INX D ; D++
- DCR L ; L--
- JMP FCBFILL
- ;
- FILL2: LDAX D ; While(*D~='.' && *D~=0)
- CPI '.'
- JZ FILL3
- CPI 0
- JZ FILL3
- INX D ; D++
- JMP FILL2
- ;
- FILL3: CPI '.' ; If(*D=='.')
- JNZ FILL4
- INX D ; D++
- ;
- ; FCBPAD (dest,pad,size)
- ; B H L
- ;
- FILL4:
- FCBPAD: MOV A,L ; While(L>0)
- ORA A
- JZ PAD2
- MOV A,H ; *B++ = H
- STAX B
- INX B
- DCR L ; L--
- JMP FCBPAD
- ;
- PAD2: RET ; Return
- ;
- ; GETC (unit)
- ;
- FGETC:
- GETC: POP B
- POP H ; Get arguments
- PUSH H
- PUSH B
- ;
- ; C=cget(unit)
- ;
- PUSH H
- CALL CGET
- POP D
- MOV A,L ; If(c=='\r')
- ANI 7FH ; /* mask parity in compare */
- CPI EOL
- JNZ GETCRET
- PUSH H ; Cget(unit)
- PUSH D ; /* to skip LF */
- CALL CGET
- POP H
- POP H
- ;
- GETCRET:RET
- ;
- ; CGET (unit)
- ;
- CGET: POP D
- POP H
- PUSH H
- PUSH D
- MOV A,H
- ORA A ; If(unit < 256)
- JNZ CGET1 ; /* assume stdin */
- CALL GETCHAR ; Getchar()
- POP D ; /* return to caller of getc()
- POP D ; To bypass CR check */
- RET ; Return
- ;
- CGET1: SHLD UNIT
- LXI D,FLAG ; If(unit[FLAG] & EOF_FL)
- DAD D
- MOV A,M
- ANI EOFFLG
- JZ GTCIF1
- LXI H,-1 ; Return(-1)
- RET
- ;
- GTCIF1: LHLD UNIT ; Ip = unit + FCBSIZE
- LXI D,FCBSIZE
- DAD D
- SHLD IP
- LXI D,NEXTP ; Cp = ip[NEXTP]
- DAD D
- MOV E,M
- INX H
- MOV D,M
- XCHG
- SHLD CHP
- LHLD IP ; If(ip[UNUSED]==0)
- LXI D,UNUSED
- DAD D
- MOV A,M
- INX H
- ORA M
- JNZ GTCIF2
- LXI H,READ ; If(cpmio(READ,unit)~=0)
- PUSH H
- LHLD UNIT
- PUSH H
- CALL CPMIO
- POP D
- POP D
- MOV A,H
- ORA L
- JZ GTCIF3
- LXI H,-1 ; Return(-1)
- RET
- ;
- GTCIF3: LHLD IP ; Else { ip[UNUSED] = BUFSIZ
- LXI D,UNUSED
- DAD D
- LXI D,BUFSIZ
- MOV M,E
- INX H
- MOV M,D
- LHLD IP ; Cp = &ip[BUFFER]
- LXI D,BUFFER
- DAD D
- SHLD CHP
- ;
-
- GTCIF2: LHLD IP ; Ip[UNUSED]--
- LXI D,UNUSED
- DAD D
- MOV E,M
- INX H
- MOV D,M
- DCX D
- MOV M,D
- DCX H
- MOV M,E
- LHLD CHP ; Ip[NEXTP] = cp+1
- INX H
- XCHG
- LHLD IP
- LXI B,NEXTP
- DAD B
- MOV M,E
- INX H
- MOV M,D
- LHLD CHP ; If(*cp==CTRL_Z)
- MOV A,M
- ANI 7FH ; /* mask parity in compare */
- CPI CTRLZ
- JNZ GTCIF4
- LHLD UNIT ; Unit[FLAG] |= EOF_FL
- LXI D,FLAG
- DAD D
- MOV A,M
- ORI EOFFLG
- MOV M,A
- LXI H,-1 ; Return(-1)
- RET
- ;
- GTCIF4: MOV A,M
- MOV L,A ; Return(*cp & 0377)
- MVI H,0
- RET
- ;
- ; GETCHAR ()
- ;
- GETCHAR:LHLD RSTDIN ; If(rdstdin >= 256)
- MOV A,H ; /* stdin has been redirected */
- ORA A
- JZ GETCHR1
- PUSH H
- CALL GETC ; Getc(rdstdin)
- POP B ; Return
- RET
- ;
- ; } else { /* read from console */
- ;
- GETCHR1:MVI C,GETCH ; T = cpm(GETCH,0) & 0377
- CALL BDOS
- MOV L,A
- MVI H,0
- ANI 7FH ; /* mask parity in compare */
- CPI CTRLZ ; If(t==CTRLZ)
- JNZ GET1CHAR
- LXI H,-1 ; T = -1
- ;
- GET1CHAR:
- CPI EOL ; If(t==EOL)
- JNZ GET2CHAR
- PUSH H ; Putchar('\n')
- MVI C,PUTCH
- MVI E,LF
- CALL BDOS
- POP H
- ;
- GET2CHAR: ; Return(t)
- RET
- ;
- ; GETS (buff)
- ;
- GETS: POP B
- POP H
- PUSH H
- PUSH B
- PUSH H ; Buff
- LHLD RSTDIN ; If(rstdin >= 256)
- MOV A,H
- ORA A
- JZ GETS1
- XCHG
- LXI H,80
- PUSH H ; Len
- PUSH D ; Unit
- CALL FGETS ; Return(fgets(buff, 80, rstdin))
- POP B
- POP B
- POP B
- RET
- ;
- GETS1: POP H ; } else {
- SHLD CHP
- DCX H ; Save = buff[-1]; save2 = buff[-2]
- MOV D,M ; Buff[-1] = 0; buff[-2] = 79
- MVI M,0
- DCX H
- MOV E,M
- MVI M,79
- PUSH H
- PUSH D
- XCHG ; Cpm(GETSTR,buff-2)
- MVI C,GETSTR
- CALL BDOS
- LHLD CHP ; Buff[buff[-1]] = 0; (9 Jun 80. Was cp)
- DCX H
- MOV E,M
- INX H
- MVI D,0
- DAD D
- MVI M,0
- POP D ; Buff[-1] = save; buff[-2] = save2
- POP H
- MOV M,E
- INX H
- MOV M,D
- INX H
- MVI C,PUTCH ; Putchar('\n')
- MVI E,LF
- CALL BDOS
- LHLD CHP ; Return(buff)
- RET ; }
- ;
- ; FGETS (cp,len,unit)
- ;
- FGETS: INX SP ; Skip return address
- INX SP
- POP B ; Unit
- POP D ; Length
- POP H ; Cp
- PUSH H
- PUSH D
- PUSH B
- DCX SP
- DCX SP
- MOV A,B ; If(unit < 256)
- ORA A ; /* assume stdin */
- JNZ FGETS1
- PUSH H
- CALL GETS ; Gets(cp)
- POP B ; Return (cp)
- RET ; } else {
- ;
- FGETS1: SHLD SVCHP ; Save_cp = cp
- PUSH D ; Keep stack right
- ;
- FGETS2: POP D
- DCX D ; While (--len)
- PUSH D
- MOV A,D
- ORA E
- JZ FGETS4
- PUSH H ; Save cp
- PUSH B ; Unit
- CALL GETC ; C = getc(unit)
- POP B
- MOV A,H ; If(c==EOF) /* c>255 */
- ORA A
- JZ FGETS3
- POP D ; Cp
- LHLD SVCHP ; If (cp<>save_cp)
- XCHG ; /* read something */
- MOV A,H
- CMP D
- JNZ FGETS4 ; Goto fgets4
- MOV A,L
- CMP E
- JNZ FGETS4 ; Else
- LXI H,0 ; /* no characters */
- POP D ; Fix stack
- RET ; Return (NULL)
- ;
- FGETS3: MOV A,L ; Else {
- POP H
- MOV M,A ; *cp++ = c
- INX H
- ANI 7FH ; /* mask parity in compare */
- CPI LF ; If(c=='\n')
- JNZ FGETS2
- ;
- FGETS4: MVI M,0 ; *cp='\0'
- POP D ; Fix stack
- LHLD SVCHP ; Return save cp
- RET
- ;
- ; PUTC (c,unit)
- ;
- FPUTC:
- PUTC: POP B ; Return address
- POP D ; Unit
- POP H ; C
- PUSH H
- PUSH D
- PUSH B
- MOV A,D
- ORA A ; If(unit < 256)
- JNZ PUTC4 ; /* assume stdout, stderr */
- MOV A,E ; /* or stdlist. */
- CPI STDOUT ; If(unit == stdout)
- JNZ PUTC1
- PUSH H
- CALL PUTCHAR ; Putchar(c)
- POP H
- RET ; Return
- ;
- PUTC1: CPI STDERR ; Elseif(unit == stderr)
- JNZ PUTC2
- CALL PUTCON ; Putconsole(c)
- RET ; Return
- ;
- PUTC2: CPI STDLIST ; Elseif(unit == stdlist)
- JNZ PUTC3
- PUSH H
- CALL PUTLST ; Putlist(c)
- POP H
- RET ; Return
- ;
- PUTC3: JMP PTCER1 ; Else goto putcerr
- ;
- PUTC4: PUSH H ; If(cput(c,unit)<0)
- PUSH D ; Goto putcerr
- CALL CPUT
- POP D
- MOV A,H
- ORA A
- JM PUTCERR
- MOV A,L ; If(c=='\r')
- CPI EOL
- JNZ PUTCRET
- LXI H,LF ; Cput('\n',unit)
- PUSH H
- PUSH D
- CALL CPUT
- POP D
- POP D
- MOV A,H
- ORA A
- JM PUTCERR
- ;
- PUTCRET:POP H ; Return(c)
- RET
- ;
- PUTCERR:POP B ; Return(-1)
- ;
- PTCER1: LXI H,-1
- RET
- ;
- ; PUTLIST (c)
- ;
- PUTLST: POP B
- POP D
- PUSH D
- PUSH B
- SHLD ZCH
- MVI C,LSTOUT ; Cpm(LSTOUT,c)
- CALL BDOS
- LDA ZCH
- CPI EOL ; If(c==EOL)
- JNZ PUTLS1
- MVI E,LF ; Cpm(LSTOUT,LF)
- MVI C,LSTOUT
- CALL BDOS
- ;
- PUTLS1: LHLD ZCH ; Return(c & 0377)
- MVI H,0
- RET
- ;
- ; CPUT (c,unit)
- ;
- CPUT: POP B
- POP D
- POP H
- PUSH H
- PUSH D
- PUSH B
- SHLD ZCH
- XCHG
- SHLD UNIT
- LXI D,FCBSIZE ; Ip = unit + FCBSIZE
- DAD D
- SHLD IP
- LXI D,NEXTP ; Cp = ip[NEXTP]
- DAD D
- MOV E,M
- INX H
- MOV D,M
- XCHG
- SHLD CHP
- LHLD IP ; If(ip[UNUSED]==0)
- LXI D,UNUSED
- DAD D
- MOV A,M
- INX H
- ORA M
- JNZ PTCIF1
- LXI H,WRITE ; If(cpmio(WRITE,unit)~=0)
- PUSH H
- LHLD UNIT
- PUSH H
- CALL CPMIO
- POP D
- POP D
- MOV A,H
- ORA L
- JZ PTCIF2
- LXI H,-1 ; Return(-1)
- RET
- ;
- PTCIF2: LHLD IP ; Else { ip[UNUSED] = BUFSIZ
- LXI D,UNUSED
- DAD D
- LXI D,BUFSIZ
- MOV M,E
- INX H
- MOV M,D
- LHLD IP ; Cp = &ip[BUFFER]
- LXI D,BUFFER
- DAD D
- SHLD CHP
- ;
-
- PTCIF1: LHLD IP
- LXI D,UNUSED ; Ip[UNUSED]--
- DAD D
- MOV E,M
- INX H
- MOV D,M
- DCX D
- MOV M,D
- DCX H
- MOV M,E
- LHLD CHP ; Ip[NEXTP] = cp+1
- INX H
- XCHG
- LHLD IP
- LXI B,NEXTP
- DAD B
- MOV M,E
- INX H
- MOV M,D
- LDA ZCH ; Return((*cp = c) & 0377)
- LHLD CHP
- MOV M,A
- MVI H,0
- MOV L,A
- RET
- ;
- ; PUTCHAR (c)
- ;
- PUTCHAR:POP B
- POP H
- PUSH H
- PUSH B
- PUSH H
- LHLD RSTDOUT ; If(rdstdout >= 256)
- MOV A,H ; /* stdout has been redirected */
- ORA A
- JZ PUTCHR1
- PUSH H
- CALL PUTC ; Putc(c, rdstdout)
- POP B
- POP B ; Return
- RET
- ;
- PUTCHR1:POP H
- ;
- PUTCON: SHLD ZCH ; /* send to console */
- XCHG ; Cpm(PUTCH,c)
- MVI C,PUTCH
- CALL BDOS
- LDA ZCH ; If(c==EOL)
- ANI 7FH ; /* mask parity in compare */
- CPI EOL
- JNZ PUTCHIF1
- MVI E,LF ; Cpm(PUTCH,LF)
- MVI C,PUTCH
- CALL BDOS
- ;
- PUTCHIF1:
- LHLD ZCH ; Return(c & 0377)
- MVI H,0
- RET
- ;
- ; PUTS (cp)
- ;
- PUTS: POP B ; Get arguments
- POP H
- PUSH H
- PUSH B
- PUSH H ; Cp
- LHLD RSTDOUT
- MOV A,H ; If(rstdout >= 256)
- ORA A
- JZ PUTS1
- PUSH H
- CALL FPUTS ; Return (fputs(cp, rstdout))
- POP B
- POP B
- RET
- ;
- PUTS1: POP H ; } else {
- MOV A,M ; While(*cp)
- ORA A
- JZ PUTSRET
- MOV E,M ; Putchar(*cp++)
- INX H
- PUSH H
- MVI C,PUTCH
- CALL BDOS
- JMP PUTS1
- ;
- PUTSRET:RET
- ;
- ; FPUTS (cp,unit)
- ;
- FPUTS: POP B
- POP D ; Unit
- POP H ; Cp
- PUSH H
- PUSH D
- PUSH B
- ;
- FPUTS1: MOV A,M ; While((c=*cp++) <> NULL)
- INX H
- ORA A
- JZ FPUTS3
- PUSH H
- MOV C,A
- MVI B,0
- PUSH B
- PUSH D
- CALL PUTC ; If(putc(c,unit)==EOF)
- POP D
- POP B
- MOV A,H
- ORA A
- JZ FPUTS2
- POP B
- RET ; Return(EOF)
- ;
- FPUTS2: POP H
- JMP FPUTS1
- ;
- FPUTS3: LXI H,0
- RET ; Return(NULL)
- ;
- ; CPMIO (fn,unit)
- ;
- CPMIO: POP B
- POP D
- POP H
- SHLD FN
- XCHG
- SHLD UNIT
- PUSH D
- PUSH H
- PUSH B
- LHLD UNIT ; Cpmdisk(*unit)
- MOV L,M
- MVI H,0
- PUSH H
- CALL CPMDISK
- POP H
- LHLD UNIT ; Ip = unit+FCBSIZE
- LXI D,FCBSIZE ; Cpm(DMA,&ip[BUFFER])
- DAD D
- LXI D,BUFFER
- DAD D
- XCHG
- MVI C,DMA
- CALL BDOS
- LHLD FN ; T = cpm(fn,unit)
- MOV C,L
- LHLD UNIT
- XCHG
- CALL BDOS
- CALL CCSXT
- SHLD ZT
- MVI C,DMA ; Cpm(DMA,TBUFF)
- LXI D,TBUFF
- CALL BDOS
- LHLD ZT ; If(t~=0) return(-1)
- MOV A,H ; Else return(0)
- ORA L
- JNZ CPMIF1
- LXI H,0
- JMP CPMIF2
- ;
- CPMIF1: LXI H,-1
- ;
- CPMIF2: RET
- ;
- ; CPMDISK (disk)
- ;
- CPMDISK:POP D
- POP H
- PUSH H
- PUSH D
- MOV A,L ; If(d~=0)
- ORA H
- JZ DISKIF1
- XCHG ; Cpm(SELECT,d-1)
- DCX D
- MVI C,SELECT
- CALL BDOS
- ;
- DISKIF1:RET
- ;
- ;------------------- end of small-C library ----------------------------
- ;