home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_200
/
223_02
/
filelib.mac
< prev
next >
Wrap
Text File
|
1989-02-23
|
10KB
|
541 lines
; filelib.mac
;
; Small-C File Library Version 2.0
;
; by
;
; Fred A. Scacchitti
; 25 Glenview Lane
; Roch., NY 14609
;
; 3 - 22 - 86
;
; This module is a derivative of RUNTIME.MAC by Glen Fisher
; and Bill Randle. It contains the constructs necessary for
; handling file i/o for C programs compiled by Version 2.70
; (and later) of the Small-C compiler.
;
; This module contains the following routines:
;
; fopen(name,mode)
;
; fclose(name)
;
; fcb()
;
; fcbpad()
;
; fcbsize()
;
;
; Now then here's the file i/o code
;
CBDOS EQU 5 ;/* bdos entry point */
CPMARG EQU 128 ;/* CP/M command line */
MAXARG EQU 32 ;/* Maximum number of input args */
STDIN EQU 0
STDOUT EQU 1
STDERR EQU 2
STDLST EQU 4
CTRLZ EQU 26 ;control z
NULL EQU 0 ;pointer to nothing
FCBSIZE EQU 36 ;size, in bytes, of an FCB
NEXTP EQU 0 ;offset to next-char. pointer in I/O struct.
UNUSED EQU 2 ;offset to unused-pos.-count in I/O struct.
BUFFER EQU 6 ;offset to disk sector buf. in I/O struct.
UNGOT EQU 5 ;offset to char ungotten by ungetc()
FLAG EQU 33 ;file-type flag byte (in unused part of FCB)
FREEFLG EQU 128 ;This I/O structure is available
EOF EQU 0FFH
EOFFLG EQU 2 ;The end of this file has been hit
WRTFLG EQU 1 ;This file open for writing
BUFSIZ EQU 1024 ;how long the sector buffer is
NBUFS EQU 8 ;number of I/O buffers
TBUFF EQU 128 ;default cpm buffer
LF EQU 10
EOL EQU 13
;
; CP/M BDOS CALLS
;
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
;
;
; File i/o storage varibles found in ZZFIO.MAC
;
;
EXTRN ZZUNIT
EXTRN ZZIP
EXTRN ZZCHP
EXTRN ZZDP
EXTRN ZZFILE
EXTRN ZZMODE
EXTRN ZZCH
EXTRN ZZT
EXTRN ZZFN
EXTRN ZZNUBU
EXTRN ZZMXSC
EXTRN ZZSVCH
;
;
;
; Characteristics variable storage found in ulink()
;
;
EXTRN ZZDFLT
EXTRN ZZSTAK
EXTRN ZZMEM
EXTRN ZZTEMP
;
; Start of file buffers found at end of program
;
EXTRN GRABIO
EXTRN FREEIO
EXTRN CPMIO
EXTRN CPMDISK
;
; Required to set buffer in append mode
;
EXTRN PUTC
;
; Default disk I/O buffer
;
EXTRN ZZBUF
;
; Storage variables used by append mode
;
CURREC: DB 0
CUREXT: DB 0
OLDREC: DB 0
OLDEXT: DB 0
;
; fopen(name,mode)
;
FOPEN::
;
POP B ;get args
POP H ;mode
SHLD ZZMODE
POP D
XCHG
SHLD ZZFILE
PUSH H
PUSH D
PUSH B
CALL GRABIO ; unit = grabio();
SHLD ZZUNIT
MOV A,H ; if(unit==NULL)
ORA L ; return(NULL);
RZ
LXI D,FCBSIZE ; ZZIP = unit+FCBSIZE;
DAD D
SHLD ZZIP
;
LXI D,UNGOT ;# OFFSET TO UNGOTTEN CHAR
DAD D
MVI M,0FFH ;# EOF TO AVOID EXTRA CHAR
;
DCX H ;# POINT TO ERROR BYTE
MVI M,0 ;# CLEAR IT
;
LHLD ZZIP ;ZZIP[NEXTP]=&ZZIP[BUFFER];
LXI D,BUFFER
DAD D
XCHG
LHLD ZZIP
LXI B,NEXTP
DAD B
MOV M,E
INX H
MOV M,D
LHLD ZZUNIT ; fcb(unit,name);
PUSH H
LHLD ZZFILE
PUSH H
CALL FCB
POP H
POP H
LHLD ZZUNIT ; cpmdisk(*unit);
MOV L,M
MVI H,0
PUSH H
CALL CPMDISK
POP H
LHLD ZZMODE ;if(*mode=='R'||*mode=='A'){
MOV A,M
;
ANI 5FH ;# CONVERT TO UPPERCASE
CPI 'R' ;# MODE = R ?
JNZ FOPIF1
;
FOPIF0:
MVI C,OPEN ; if(cpm(OPEN,unit)<0){
LHLD ZZUNIT
XCHG
CALL CBDOS ; (mod toÇcbdos (fas))
ORA A
JP FOPIF2
LHLD ZZUNIT ; freeio(unit);
PUSH H
CALL FREEIO
POP H
LXI H,NULL ; return(NULL);
RET
; }
FOPIF2:
LHLD ZZIP ; ZZIP[UNUSED] = 0;
LXI D,UNUSED
DAD D
LXI D,0
MOV M,E
INX H
MOV M,D
; }
JMP FOPIFX
FOPIF1: ; else if(*mode=='W'){
LHLD ZZMODE
MOV A,M
ANI 5FH
CPI 'W' ;# WRITE MODE ?
JZ FOPIFA ;# YES - GO DO IT
CPI 'A' ;# APPEND MODE ?
JNZ FOPIF5 ;# NO - BACK TO CALLER OF FOPEN
; ;# NO MODES LEFT TO TRY
;
MVI C,OPEN ;# FIRST LET'S SEE IF IT'S THERE
LHLD ZZUNIT
XCHG
CALL CBDOS
ORA A
JP FOPIF3 ;# YES - SET IT UP FOR USE
;
;# NO - LET'S MAKE ONE
LHLD ZZMODE ;# SET MODE TO 'W' ON NEW FILE
MVI M,'W' ;# TO AVOID WASTING TIME AND CODE
;# SEARCHING AN EMPTY FILE
;
FOPIFA:
MVI C,DELETE ; cpm(DELETE,unit);
LHLD ZZUNIT
XCHG
CALL CBDOS ; (mod to cbdos(fas))
MVI C,CREATE ; if(cpm(CREATE,unit)<0){
LHLD ZZUNIT
XCHG
CALL CBDOS ; (mod to cbdos(fas))
ORA A
JP FOPIF3
LHLD ZZUNIT ; freeio(unit);
PUSH H
CALL FREEIO
POP H
LXI H,NULL ; return(NULL);
RET
; }
FOPIF3:
LHLD ZZIP ; ZZIP[UNUSED] = BUFSIZ;
LXI D,UNUSED
DAD D
LXI D,BUFSIZ
MOV M,E
INX H
MOV M,D
LHLD ZZUNIT ; unit[FLAG] = WRITE_FL;
LXI D,FLAG
DAD D
MVI A,WRTFLG
ORA M
MOV M,A
JMP FOPIF4
; }
FOPIF5:
LHLD ZZUNIT ; else{ freeio(unit);
PUSH H
CALL FREEIO
POP H
LXI H,NULL ; return(NULL);
RET
;
; }
FOPIF4:
;
LHLD ZZMODE ;#
MOV A,M ;# GET MODE
ANI 5FH
CPI 'A' ;# APPEND MODE ?
JNZ FOPIFX ;# NO - RETURN NORMALLY
;
AMSCRD:
;
LDA CUREXT ;# SAVE EXTENT AND RECORD NUMBERS
STA OLDEXT ;# TWO DEEP
LDA CURREC
STA OLDREC
LHLD ZZUNIT
LXI D,12
DAD D
MOV A,M ;# GET CURRENT EXTENT #
STA CUREXT
LXI D,20
DAD D
MOV A,M ;# GET CURRENT RECORD #
STA CURREC
;
LHLD ZZUNIT ;# YES - LET'S READ TO THE END
XCHG ;# DE --> FCB
MVI C,READ
CALL CBDOS ;# READ A SECTOR
ORA A
JZ AMSCRD ;# READ TO PHYSICAL END OF FILE
;
LHLD ZZUNIT
LXI D,12
DAD D
LDA OLDEXT
MOV M,A ;# RESTORE LAST EXTENT #
LXI D,20
DAD D
LDA OLDREC
MOV M,A ;# RESTORE LAST RECORD #
;
LXI H,ZZBUF
SHLD ZZTEMP ;# SAVE THE BUFF. WE'RE READING FROM
;
XRA A
STA OLDREC ;# use oldrec for a counter
AMCHRD:
LHLD ZZTEMP ;# HL --> TEMPORARY BUFFER
MOV A,M
;
CPI 0AH ;# LINE FEED CHECK
JNZ NOTLF
INX H ;# INCREMENT POINTER
SHLD ZZTEMP ;# AND GO ON TO NEXT CHARACTER
JMP AMCHRD
;
NOTLF: CPI 1AH ;# END OF FILE MARKER ?
JZ FOPIFX ;# YES - EXIT GRACEFULLY
MOV C,A
MVI B,0 ;# BC CONTAINS THE CHARACTER
INX H
SHLD ZZTEMP ;# SAVE UPDATED POINTER
LHLD ZZUNIT
PUSH B
PUSH H
CALL PUTC ;# PUTC(CHAR,ZZUNIT)
POP B
POP B
;
LDA OLDREC ;# get the counter
INR A ;# add a count
STA OLDREC ;# store it
;
JNZ AMCHRD ;# keep going (max 128 bytes)
;
FOPIFX:
LHLD ZZUNIT ; return(unit);
RET
;
FCLOSE::
POP B
POP H
SHLD ZZUNIT
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 ZZT
LHLD ZZUNIT ; 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 ZZUNIT
PUSH H
CALL PUTC
POP H
POP H
LHLD ZZUNIT ; ZZIP = unit + FCBSIZE;
LXI D,FCBSIZE
DAD D
SHLD ZZIP
LHLD ZZIP ; cp = ZZIP[NEXTP];
LXI D,NEXTP
DAD D
MOV E,M
INX H
MOV D,M
XCHG
SHLD ZZCHP
LHLD ZZIP ; ZZDP = &ZZIP[BUFFER]+BUFSIZ;
LXI D,BUFFER+BUFSIZ
DAD D
SHLD ZZDP
FCLWH1: ; while(cp<ZZDP)
LHLD ZZCHP
XCHG
LHLD ZZDP
MOV A,D
CMP H
JC FCLWH2
JNZ FCLWH3
MOV A,E
CMP L
JNC FCLWH3
FCLWH2: ; *cp++ = CTRL_Z;
LHLD ZZCHP
MVI M,CTRLZ
INX H
SHLD ZZCHP
JMP FCLWH1
FCLWH3:
LXI H,WRITE ; if(cpmio(WRITE,unit)<0)
PUSH H
LHLD ZZUNIT
PUSH H
CALL CPMIO
POP D
POP D
MOV A,H
ORA A
JP FCLIF4
LXI H,0 ; t = 0;
SHLD ZZT
FCLIF4:
; }
FCLIF3:
; }
FCLIF1:
MVI C,CLOSE ; if(cpm(CLOSE,unit)<0)
LHLD ZZUNIT
XCHG
CALL CBDOS ; (mod tocbdos(fas))
ORA A
JP FCLIF5
LXI H,0 ; t = 0;
SHLD ZZT
FCLIF5:
LHLD ZZUNIT ; freeio(unit);
PUSH H
CALL FREEIO
POP H
LHLD ZZT ; return(NULL+t);
RET
;
; fcb(fp,name)
;
FCB::
POP H ;get args
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 ; '@' 9 Jun 80 rj
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 ZZDFLT ; 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 Jun 80 rj
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++;
FILL4:
; fall into...
;
; fcbpad(dest,pad,size)
; B H L
;
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;
;
;
END