home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
MBUG
/
MBUG150.ARC
/
TXT2ASM.AQM
/
TXT2ASM.ASM
Wrap
Assembly Source File
|
1979-12-31
|
13KB
|
593 lines
TITLE 'FILTER TEXT TO .ASM DB FORMAT'
; Author Thomas Hill
; 200 Oklahoma St.
; Anchorage, Ak. 99504
; (907) 337-1984
; Modifications & updates (in reverse order):
;
; 10/09/82 Version 1.1
; Cleaned up code
; 09/30/82 Version 1.0
; This program accepts as input a text file created by any of the
; CP/M text editors. It outputs a file formatted as "DB" statements
; suitable for inclusion in .ASM and .MAC assembly files.
; Carriage return, linefeed sequences are translated into the
; label sequence "CR,LF". Tabs are passed unaltered and form feed
; control codes are translated into the label "FF".
; In deference to the MAC assembler, which dislikes quoted text lines
; longer than 64 characters, input lines longer than 60 characters
; are broken into two or more output lines.
; Note that theis version assumes that the input text will fit
; in available TPA.
; SYSTEM EQUATES
CPM EQU 0
BDOS EQU CPM+0005H ; BDOS ENTRY POINT
FCB1 EQU CPM+005CH ; CP/M FILE CONTROL BLOCK
FCB2 EQU CPM+006CH ; SECOND FILE CONTROL BLOCK
CBUF EQU CPM+0080H ; DEFAULT COMMAND BUFFER
TPA EQU CPM+0100H ; user program area
; NON-DISK I/O FUNCTIONS
CONIN EQU 1 ; CONSOLE INPUT
CONOUT EQU 2 ; CONSOLE OUTPUT
LSTOUT EQU 5 ; LIST DEVICE OUTPUT
PRTBUF EQU 9 ; SEND A STRING TO THE CONSOLE
RDBUF EQU 10 ; GET A STRING FROM THE CONSOLE
CONSTAT EQU 11 ; CONSOLE STATUS
VERS EQU 12 ; RETURN CP/M (MP/M) VERSION NUMBER
; DISK I/O FUNCTIONS
SELDSK EQU 14 ; SELECT DISK
OPENF EQU 15 ; OPEN FILE
CLOSEF EQU 16 ; CLOSE A FILE
DELETF EQU 19 ; DELETE A FILE
READF EQU 20 ; READ A RECORD
WRITEF EQU 21 ; WRITE A RECORD
MAKEF EQU 22 ; CREATE A FILE
SETDMA EQU 26 ; SET DISK DMA ADDRESS
SIZEF EQU 35 ; COMPUTE FILE SIZE
; THOSE FUNCTIONS REQUIRING A BYTE ARGUMENT WILL EXPECT THAT BYTE
; TO BE IN THE E REGISTER. ADDRESS ARGUMENTS ARE PASSED IN THE
; DE REGISTER. RETURN CODES ARE PASSED IN THE ACC. IN GENERAL,
; A RETURN OF ZERO INDICATES SUCCESS, WHILE A OFFH INDICATES FAILURE.
; character equates
CR EQU 0DH ; carriage return
LF EQU 0AH ; line feed
ESC EQU 1BH ; escape code
EOF EQU 1AH ; end-of-file, control-z
BELL EQU 07H ; terminal bell
BS EQU 08H ; backspace
TAB EQU 09H ; tab char
APOS EQU '''' ; apostrophe
FORMF EQU 0CH ; form feed
;
FALSE EQU 00H
TRUE EQU 0FFH
;
MAX$LEN EQU 60 ; maximum length for output lines
MACLIB Z80
ORG TPA
TXT2ASM:
JMP FILTER ; over copyright notice
SIGNON: DB 'Text to .ASM Formatting Program',cr,lf
DB 'Copyright October, 1982 by '
DB 'Thomas N. Hill',cr,lf,LF,'$',eof
FILTER: LXI D,SIGNON
CALL PMESS
LDA FCB1+1 ; check for input file
CPI ' '
JZ USAGE ; tell how to use.
; check for second file name as output
LDA FCB2+1
CPI ' '
CZ USE$SAME ; use the same file as output
LXI H,FCB2
LXI D,OUT$FCB ; move to output FCB
MVI B,12
LDIR ; move it
MVI B,24
LP1: MVI M,0 ; fill rest of FCB with zeros
INX H
DJNZ LP1
; input and output FCBs are set. Now open input file and fill buffer
LXI D,FCB1
MVI C,OPENF
CALL BDOS ; try to open the input
INR A
LXI D,NO$OPEN
JZ ERROR ; nothing there to open.
LXI D,OUT$FCB
MVI C,DELETF ; remove any existing output file
CALL BDOS
XRA A
LXI D,OUT$FCB$EX
MVI B,24
ZERO: STAX D
INX D
DJNZ ZERO ; re zero fcb
LXI D,OUT$FCB
MVI C,MAKEF ; and re-create it
CALL BDOS
INR A
LXI D,NO$MAKE
JZ ERROR ; can't make file, no room
; both files open, set up counters and pointers
LXI H,0
SHLD I$LN$CNT ; input lines
SHLD O$LN$CNT ; output line count
LXI H,IN$BUF
SHLD IN$PTR ; input buffer pointer
LXI H,OUT$LINE
SHLD OUT$PTR ; output line buffer
LXI H,OUT$BUF
SHLD OUT$DSK ; disk output buffer
; pointers & counters set, begin filtering operation
CALL FILL$BUF ; fill the input buffer
LP2: CALL SET$LINE ; set up the output line
CALL MAKE$LINE ; and make one
CALL WRT$LINE ; write the line to disk
LDA EOF$FLG ; was there an EOF during input?
ORA A
JRZ LP2 ; nope, continue
CALL FLUSH ; yes, flush remaining output
LHLD I$LN$CNT
CALL HL2DEC ; print number of input lines
LXI D,IN$MSG
CALL PMESS
LHLD O$LN$CNT ; output lines
CALL HL2DEC
LXI D,OUT$MSG
CALL PMESS
LXI D,OUT$FCB
MVI C,CLOSEF
CALL BDOS ; shut things down
INR A
LXI D,NO$CLOSE
JZ ERROR ; oh,oh ... can't close file!
JMP CPM ; return to operating system
; fill the input buffer. set EOF flag if we bump into end of file.
FILL$BUF:
LXI H,IN$BUF
FILL1: SHLD IN$PTR
XCHG
MVI C,SETDMA
CALL BDOS ; tell BDOS where to go
LXI D,FCB1
MVI C,READF
CALL BDOS ; read something
ORA A
JRNZ FILL4 ; got EOF, set flag
LHLD IN$PTR
LXI D,80H
DAD D ; next sector
LDA BDOS+2 ; check for no room in memory
CMP H
JRNC FILL1
LXI D,NO$MEM
JMP ERROR
FILL4: LXI D,FCB1
MVI C,CLOSEF
CALL BDOS ; done with that file
LXI H,IN$BUF
SHLD IN$PTR ; set pointer to start of buffer
RET
; set up the output line buffer.
; preload the initial tab, DB, and tab
SET$LINE:
LXI D,OUT$LINE
LXI H,LN$MSK
LXI B,MSK$LEN
LDIR ; put the line begining in place
SDED OUT$PTR ; save current location in output line
XRA A
STA NUM$OUT ; reset output character count
STA FIRST
STA IN$QUOTE ; and flags for comma control
RET
; here we do the work.
; Get characters form the input buffer, translating CR,LF, and FF
; controls to proper labels. Place quotes around text strings,
; making sure to double imbedded quotes. Watch placement of
; commas and length of output line.
MAKE$LINE:
LHLD IN$PTR ; current buffer pointer
LDED OUT$PTR ; output line pointer
MAKE0: MOV A,M ; get char from input
CPI EOF ; end of input?
JZ END$IT
CPI CR
JZ PUT$CR ; mark newline
CPI LF
JZ PUT$LF ; some lines don't have CRs
CPI FORMF
JZ PUT$FF ; and form feeds
CPI APOS ; imbedded quote?
JNZ MAKE1
CALL PUT$APOS ; put in two apostrophes
CALL PUT$APOS
INX H
JR MAKE0
; if we got here, then plain character
MAKE1: MVI A,TRUE
STA FIRST ; not first char anymore
LDA IN$QUOTE ; are we inside quoted string?
ORA A
JRNZ MAKE2 ; yes, don't place apos
CALL PUT$APOS ; no, mark start of text line
MVI A,TRUE
STA IN$QUOTE ; we are now.
MAKE2: MOV A,M ; recover character
MAKE3: INX H
STAX D ; place character in output line
INX D
CALL OUT$CNT ; count output chars
CPI MAX$LEN ; reached end?
JNZ MAKE0
LDA IN$QUOTE
ORA A ; inside quoted line?
JRZ MAKE4 ; nope.
CALL PUT$APOS ; end of quoted text
MAKE4: MVI A,CR
STAX D ; real end of line
INX D
MVI A,LF
STAX D
SHLD IN$PTR ; save current buffer pointer
RET
END$IT: LDA IN$QUOTE
ORA A ; inside quoted string?
JRZ ENDIT1
MVI A,FALSE
STA IN$QUOTE
CALL PUT$APOS ; yes, mark end
ENDIT1: LDA FIRST
ORA A ; first position in line?
JRZ ENDIT2
CALL PUT$COMMA ; nope, need a comma here
ENDIT2: CALL PUT$APOS
MVI A,'$' ; mark end of text
STAX D
INX D
CALL PUT$APOS ; with CP/M EOM marker
MVI A,TRUE
STA EOF$FLG
JMP MAKE4 ; and end line
; here are the various "PUT" subroutines
PUT$CR: PUSH H
LHLD I$LN$CNT
INX H
SHLD I$LN$CNT ; count input lines
POP H
LDA IN$QUOTE
ORA A ; inside quoted string?
JRZ PUT$C1
CALL PUT$APOS ; close it first
MVI A,FALSE
STA IN$QUOTE ; reset flag
PUT$C1: LDA FIRST
ORA A ; beginning of line?
JRZ PUT$C2 ; yep, no comma
CALL PUT$COMMA
PUT$C2: MVI A,TRUE
STA FIRST ; not beginning anymore
MVI A,'C'
STAX D ; put "CR" label in place
INX D
MVI A,'R'
STAX D
INX D
PUT$C3: INX H
MOV A,M ; take care of LF
CPI LF
JNZ MAKE4
PUT$LF: LDA IN$QUOTE
ORA A
JRZ PUT$L1
CALL PUT$APOS
MVI A,FALSE
STA IN$QUOTE
PUT$L1: LDA FIRST
ORA A
JRZ PUT$L2
CALL PUT$COMMA
MVI A,TRUE
STA FIRST
PUT$L2: MVI A,'L'
STAX D ; put "LF" label in place
INX D
MVI A,'F'
STAX D
INX D
JR PUT$C3 ; look for some more
PUT$APOS:
MVI A,APOS
STAX D
INX D ; put an apostrophe in output line
RET
PUT$COMMA:
MVI A,','
STAX D
INX D
RET
PUT$FF: MVI A,'F'
STAX D
INX D
STAX D
INX D
RET
; count output chars, return count in A
OUT$CNT:
LDA NUM$OUT
INR A
STA NUM$OUT
RET
; write output line to buffer. When buffer fills, write it to disk.
WRT$LINE:
PUSH H
PUSH D
LDED OUT$DSK
LXI H,OUT$LINE
WRT1: MOV A,M
STAX D ; move line till see a LF
LXI B,O$BUF$TOP ; buffer top
MOV A,B
CMP D
JNZ WRT4
MOV A,C
CMP E
JNZ WRT4
; buffer full, write it out
PUSH H ; save current line pointer
MVI A,BUF$SIZE
CALL WRT$BUF
LXI H,OUT$BUF
SHLD OUT$PTR
POP H ; output line pointer
JMP WRT1 ; continue with move, if any left
WRT4: MOV A,M ; get char again
INX H
INX D
CPI LF ; end of line?
JNZ WRT1
SDED OUT$DSK ; save current location in buffer
LHLD O$LN$CNT
INX H
SHLD O$LN$CNT
POP D
POP H
RET
; flush rest of output buffer to disk
FLUSH: LHLD OUT$DSK ; fill rest of buffer with EOFs
FLUSH1: MVI M,EOF
INX H
MOV A,L ; till next page break
ORA A
JRNZ FLUSH1
LXI D,-OUT$BUF
DAD D ; calc. number of sectors to write
MOV A,H ; pages
ADD A ; double for sectors
INR A ; plus one for safety
WRT$BUF:
LXI H,OUT$BUF
WRT2: PUSH PSW
SHLD OUT$DSK
XCHG
MVI C,SETDMA
CALL BDOS
LXI D,OUT$FCB
MVI C,WRITEF
CALL BDOS
ORA A
LXI D,NO$WRITE
JNZ ERROR ; got a write error
POP PSW
DCR A
RZ
LHLD OUT$DSK
LXI D,80H
DAD D
JR WRT2
; double precision convert HL to decimal
HL2DEC: LXI B,-10000
CALL CNVRT ; 10,000s digit
MOV A,E
ORA A ; skip leading zeros
JRZ HLD1
CALL DIGOUT
HLD1: LXI B,-1000
CALL CNVRT ; 1,000s digit
MOV A,E
ORA A
JRZ HLD2
CALL DIGOUT
HLD2: LXI B,-100
CALL CNVRT
MOV E,A
ORA A
JRZ HLD3
CALL DIGOUT
HLD3: LXI B,-10
CALL CNVRT
MOV A,E
ORA A
JRZ HLD4
CALL DIGOUT
HLD4: MOV A,L ; print last digit, even a zero
CALL DIGOUT
RET
CNVRT: MVI E,-1
CNV1: INR E
DAD B
MOV A,H
ORA A
JP CNV1
MOV A,B
CMA
MOV B,A
MOV A,C
CMA
MOV C,A
INX B
DAD B
RET
DIGOUT: ADI '0'
COUT: PUSH H
PUSH D
PUSH B
MOV E,A
MVI C,CONOUT
CALL BDOS
POP B
POP D
POP H
RET
; no input file, tell user what to do
USAGE: LXI D,USE$MSG
CALL PMESS
JMP CPM
; error routine, print message at (DE) and abort to CP/M
ERROR: CALL PMESS
JMP CPM
CRLF: LXI D,CRLF$MSG ; save some code here
PMESS: MVI C,PRTBUF
JMP BDOS
; useing same input file name for output. keep name, make type
; = .DB
USE$SAME:
LXI H,FCB1
LXI D,FCB2
LXI B,9
LDIR ; move the name
XCHG
MVI M,'D'
INX H
MVI M,'B' ; set type
INX H
MVI M,' '
RET
; messages
USE$MSG:
DB CR,LF
DB 'Usage: TXT2ASM <infile> [<outfile>]',CR,LF
DB ' Converts standard text input file to DB format for '
DB 'assembly',CR,LF
DB ' programs. <infile> is input text, optional '
DB '<outfile> is the',CR,LF
DB ' output file. If no output file is specified, '
DB 'output is sent',CR,LF
DB ' to <infile name>.DB '
DB '[Oct. 9, 1982 V1.1]',CR,LF,CR,LF
DB '$'
NO$OPEN:DB bell,'Cannot open input file, check directory and spelling.'
DB CR,LF,'$'
NO$MAKE:DB bell,'Cannot create output file, check space remaining.'
CRLF$MSG:
DB CR,LF,'$'
NO$CLOSE:
DB bell,'Cannot close output file, definite problem here.'
DB CR,LF,'$'
NO$WRITE:
DB bell,'Cannot complete write to output file. Disk probably full'
DB CR,LF,'$'
NO$MEM: DB bell,'Insufficient memory for input file.',cr,lf,'$'
IN$MSG: DB ' lines input.',cr,lf,'$'
OUT$MSG:DB ' lines output.',cr,lf,'$'
LN$MSK: DB TAB,'DB',TAB
MSK$LEN EQU $ - LN$MSK
; byte and address storage
EOF$FLG:DB 0
FIRST: DB 0
IN$QUOTE:
DB 0
IN$PTR: DW IN$BUF
OUT$PTR:DW OUT$LINE
OUT$DSK:DW OUT$BUF
NUM$OUT:DB 0
I$LN$CNT:
DW 0
O$LN$CNT:
DW 0
; file control block
OUT$FCB:DB 0 ; drive
DB ' ' ; name
DB ' ' ; type
OUT$FCB$EX:
DS 30 ; the rest
; buffers
BUF$SIZE EQU 16 ; 16 sectors for buffer
OUT$LINE:
DS 80
OUT$BUF:DS 128 * BUF$SIZE
O$BUF$TOP EQU $
IN$BUF EQU $
END