home *** CD-ROM | disk | FTP | other *** search
- TITLE Control Character converter
- ;++
- ; CTRLCVT
- ; Control character sequence converter
- ;
- ; V1.1 - CRA 26-MAY-1990
- ; Linked with V4LIB versions and converted source to SLR format.
- ;
- ;--
- ASEG
- IF Z33 ; Z3BASE not needed in this setup
- TRUE EQU 0FFFFH
- FALSE EQU 0000H
- ELSE
- .XLIST
- MACLIB Z3BASE
- .LIST
- ENDIF ; Z33
- .XLIST
- MACLIB CTRLCVT ; get rest of equates
- .LIST
- ;+
- ; Link with Z3LIB and SYSLIB, and possibly Z33LIB.
- ;-
- IF Z33
- .REQUEST Z33LIB,Z3LIB,SYSLIB
- ELSE
- .REQUEST Z3LIB,SYSLIB
- ENDIF
- ;+
- ; Mark some public symbols for debugging when requested.
- ; (SLR180 eliminates this need!)
- ;-
- SUBTTL Establish Environment
- PAGE
- ;+
- ; ZCPR3 Program Header for use with Z3INS or the auto-install feature
- ; of ZCPR33.
- ;-
- CSEG
- IF Z3ENV NE 0 OR Z33
- ;+
- ; Set up the headers for an external environment descriptor.
- ; Taking advantage of SLRNK's ability to load code at 103H, we leave
- ; room for the leading jump to the entry point START, declared as
- ; such in the END statement.
- ;-
- DEFB 'Z3ENV' ; This is a zcpr3 utility
- DEFB 1 ; type 1 image (external environment)
- IF Z33
- Z3EADR: DEFW 0 ; will be filled in by ZCPR33
- ELSE
- Z3EADR: DEFW Z3ENV ; place environment descriptor here
- ENDIF ; Z33
- ELSE
- ;+
- ; Prepare the internal environment descriptor, even though this will
- ; take more memory.
- ;-
- MACLIB SYSENV ; construct type 2 image
- Z3EADR: SYSENV
- ENDIF ; Z3ENV > 0 | Z33
- SUBTTL Initialize
- PAGE
- ;+
- ; Call the initialization routine.
- ; How we obtain the descriptor depends on the type of environment
- ; we have.
- ;-
- START:: IF DEBUG ; setup a dummy command line if debugging
- LD BC,CMDLNE-CMDLNB; place length
- LD DE,DMA ; target
- LD HL,CMDLNB ; command line dummy
- LDIR ; place it
- ENDIF ; DEBUG
- IF Z3ENV NE 0
- LD HL,(Z3EADR) ; obtain environment descriptor
- ELSE
- LD HL,Z3EADR ; obtain descriptor from inline
- ENDIF ; Z3ENV switch
- CALL Z3INIT## ; tell library about it
- ;+
- ; Check on the validity of the ZCPR33 environment.
- ;-
- IF Z33
- CALL Z33CHK## ; find out if this is Z33able
- JR Z,Z33IS ; yup
- LD A,0FFH ; nope
- Z33SV: LD (Z33FLAG),A ; save this
- JR HEAP
- Z33IS: XOR A ; clear A
- JR Z33SV ; fall around
- ENDIF ; Z33
- ;+
- ; Initialize allocation routines.
- ;-
- HEAP: LD A,1 ; indicate that we are providing bottom of heap
- LD HL,HEAPSTART ; load bottom of heap
- CALL IALLOC## ; establish allocation
- ;+
- ; Print signon message if the QUIET flag is off.
- ;-
- LD HL,SIGNON
- CALL QPSTR##
- CALL QCRLF##
- SUBTTL Parse command line
- PAGE
- ;+
- ; See to it that we do not have a zero length argument string
- ; (meaning that the user only typed in the command).
- ;-
- LD A,(DMA) ; pick up length of string
- CP 0 ; and check
- JR NZ,COPY1 ; we appear to have no arguments
- LD HL,NOARGS1 ; get 'No arguments' string
- CALL PSTR## ; and print it
- LD A,8 ; set error #8
- JP ERROR ; no more
- ;+
- ; Change the command line from a counted string to a null terminated
- ; string.
- ;-
- COPY1: LD C,A ; BC = A
- LD B,0 ; zero MS byte
- LD HL,DMA+1 ; our source
- ADD HL,BC ; make a new pointer
- XOR A ; A = 0
- LD (HL),A ; null terminate string
- ;+
- ; Conduct ARGV-style token parsing on the command line.
- ; The copied target line will be modified.
- ;-
- LD HL,DMA+1 ; obtain our now null-terminated string
- LD DE,TOKENP ; set up token start
- LD A,0FFH ; we want null-terminated tokens
- CALL ARGV##
- JR Z,ARGCHK ; at least we have <= 2 arguments
- LD HL,ARGG1
- CALL PSTR## ; too many arguments
- LD A,5 ; set error #5
- JP ERROR
- ;+
- ; Begin to look at the arguments presented.
- ; See if a '//' was passed, signifying a request for information.
- ;-
- ARGCHK: LD HL,(TOKEN1) ; pointer to first char in first arg
- LD A,'/' ; get the help character
- CP (HL) ; so far so good?
- JR NZ,TOKENS ; nope, see about argument count
- INC HL ; look at next spot
- CP (HL) ; did we get two?
- JR NZ,TOKENS ; nope
- ;+
- ; Display relevant description information.
- ;-
- IF VERBOSE
- IRPC LB,12345
- CALL CRLF## ;; flush a line first
- LD HL,DESCN&LB ;; first line
- CALL PSTR##
- ENDM
- ELSE
- IRPC LB,12
- CALL CRLF## ;; flush a line first
- LD HL,DESCN&LB ;; first line
- CALL PSTR##
- ENDM
- ENDIF
- RET ; that's it, we done
- ;+
- ; Look at the number of arguments passed.
- ;-
- TOKENS: LD A,(TOKENP+1) ; get number of args found
- CP 2 ; check against magic number
- JR Z,SEARCH ; this is 2 args
- LD HL,ARGL1
- CALL PSTR## ; too few arguments
- LD A,8 ; and set error 8
- JP ERROR
- SUBTTL Determine names of files
- PAGE
- ;+
- ; Parse the input file name first.
- ;-
- SEARCH: LD HL,(TOKEN1) ; set to input token
- LD DE,IFCB ; set to input FCB
- LD A,1 ; search DU before DIR
- CALL ZPRSFN## ; parse name
- LD A,BUFSIZE/128 ; set up the buffer size
- LD (ICBPAGES),A ; and save it
- LD DE,BUFSIZE ; set up buffer size
- CALL ALLOC## ; request dynamic memory
- LD (ICBBUFA),HL ; and save the returned address
- ;+
- ; Now parse the output file name.
- ;-
- LD HL,(TOKEN2) ; set to output token
- LD DE,OFCB ; set to output FCB
- LD A,1 ; search DU before DIR
- CALL ZPRSFN## ; parse this name
- LD A,BUFSIZE/128 ; set up the buffer size
- LD (OCBPAGES),A ; and save it
- LD DE,BUFSIZE ; set up buffer size
- CALL ALLOC## ; request dynamic memory
- LD (OCBBUFA),HL ; and save the returned address
- ;+
- ; At this point, we use FXI$OPEN to open the input file with the
- ; 'multiblock' capability to ease disk accesses.
- ;-
- LD DE,IFCB ; reestablish input file
- CALL Z3LOG## ; and log it in
- IF VERBOSE ; only necessary for verbosity
- CALL RETUD## ; obtain this DU
- LD (IDU),BC ; and save
- ENDIF ; VERBOSE
- LD DE,ICB ; now establish extended IOCB
- CALL FXI$OPEN## ; open input file for reading
- JR NZ,OPENED ; file is open
- ;+
- ; This means that the file wasn't opened. Build up the messages
- ; and return abnormally.
- ;-
- LD HL,ERRF1 ; first part
- CALL PSTR##
- LD HL,(TOKEN1) ; file name
- CALL PSTR##
- LD HL,ERRF2 ; second part
- CALL PSTR##
- LD A,10 ; set error #10
- JP ERROR
- ;+
- ; We opened the input file. Now we must get ready to create the
- ; output file if it doesn't exist.
- ;-
- OPENED: LD DE,OFCB ; reestablish output file context
- CALL Z3LOG## ; log in this DU
- IF VERBOSE ; only necessary for verbosity
- CALL RETUD## ; obtain this DU
- LD (ODU),BC ; and save
- ENDIF ; VERBOSE
- LD DE,OCB ; now establish extended IOCB
- CALL FXO$OPEN## ; open output file for writing
- JR NZ,CONVERT ; if file is open, begin converting
- ;+
- ; This file didn't get opened, either.
- ;-
- LD HL,ERRX1 ; first part
- CALL PSTR##
- LD HL,(TOKEN2) ; file name
- CALL PSTR##
- LD HL,ERRX2 ; second part
- CALL PSTR##
- LD A,12 ; set error #12 (can't write)
- JP ERROR
- SUBTTL Conversion Main Loop
- PAGE
- ;+
- ; Conversion initialization.
- ;-
- CONVERT:IF VERBOSE ; this stuff only necessary if verbose
- CALL GETQUIET## ; actions here contingent on quiet flag
- JR NZ,LOOP ; we are quiet, skip initialization
- ;+
- ; Initialize the counter for the number of characters converted.
- ;-
- LD HL,0 ; clear the counters
- LD (CONV),HL ; clear 'converted' count
- ;+
- ; Indicate what files we are converting.
- ;-
- LD HL,CNVM1 ; first message part
- CALL PSTR## ; display it
- LD BC,(IDU) ; get DU for input file
- CALL PDU ; display the DU form
- LD A,':' ; separator
- CALL COUT## ; display this
- LD DE,IFCB ; get input FCB
- CALL PFN ; display file name in FCB
- LD HL,CNVM2 ; second message part
- CALL PSTR## ; display it
- LD BC,(ODU) ; get DU for output file
- CALL PDU ; display the DU form
- LD A,':' ; separator
- CALL COUT## ; display this
- LD DE,OFCB ; get output FCB
- CALL PFN ; display file name in FCB
- CALL CRLF## ; end of line. (TRON quote, can't help it)
- ENDIF ; VERBOSE
- ;+
- ; Main loop of the conversion code.
- ;-
- LOOP: LD DE,ICB
- CALL FX$GET## ; obtain next character
- JR Z,COUNT ; we are at end of file, so we will count
- CP CTRLFLAG ; is character the control flag?
- JR NZ,WRITE ; most characters fall through
- ;+
- ; But this one does not fall through.
- ; We'll have to get another character from the stream.
- ;-
- CALL FX$GET## ; get another character
- JR Z,COUNT ; hit end of file
- CP CTRLFLAG ; if it's the same character, we wanted one
- JR Z,WRITE ; treat the two identical char's as one
- ;+
- ; Mask out the non-control characters.
- ;-
- AND CTRLMASK ; our mask to pass these characters through
- ;+
- ; Maintain our count of characters converted if verbose.
- ;-
- IF VERBOSE ; only necessary when verbose (gasp)
- LD HL,CONV ; get the point to increment
- INC (HL)
- JR NZ,WRITE ; no carry
- INC HL ; adjust pointer
- INC (HL) ; and increment this
- ENDIF ; VERBOSE
- ;+
- ; This character is processed.
- ; Write it out to the stream.
- ;-
- WRITE: LD DE,OCB
- CALL FX$PUT## ; write converted character
- JR NZ,LOOP ; no error, resume processing in loop
- ;+
- ; A write error has occured (such as a full disk).
- ; Indicate this is an error, close files, and exit.
- ;-
- LD HL,ERRW1
- CALL PSTR## ; display error
- CALL DONE ; close the files
- LD A,12 ; error code 12
- JR ERROR ; and handle the errors
- ;+
- ; Display the number of characters converted.
- ;-
- COUNT:
- IF VERBOSE ; compile if verbose
- CALL GETQUIET## ; get quiet state
- JR NZ,DONE ; don't do this if quiet flag on
- LD A,' ' ; we like a space following all messages
- CALL COUT## ; so we print one
- LD HL,(CONV) ; get the count
- CALL PHLFDC## ; display count in unjustified decimal
- LD HL,SUMM1 ; point to rest of message
- CALL PSTR## ; and display it
- ENDIF ; VERBOSE
- ;+
- ; Close files.
- ;-
- DONE: LD DE,ICB
- CALL FXI$CLOSE## ; close input file
- LD DE,OCB
- CALL FXO$CLOSE## ; close output file
- ;+
- ; Normal return. (and return point for calling DONE!)
- ;-
- RET ; we done normally
- SUBTTL Error Handling
- PAGE
- ;+
- ; Here is where error handling is performed. For Z33, we can use
- ; the special error codes for advanced error handling features.
- ;-
- ERROR: PUSH AF ; save the error code
- LD A,0FFH ; set up usual error stuff
- CALL PUTER2## ; set the usual flag
- POP AF
- IF Z33 ; get into advanced stuff
- LD B,A ; move error code into B
- LD A,0FFH ; indicate external program error
- CALL INVERROR## ; invoke error handler
- JP NZ,0 ; warm boot if Z33 isn't available
- ENDIF ; Z33
- RET ; otherwise make a clean exit
- SUBTTL Print the Disk and User Number
- PAGE
- ;++
- ; PDU
- ; Display the Disk and User Number
- ;
- ; Inputs:
- ; BC - disk and user in a form returned from RETUD and GETUD, i.e.,
- ; B = 0 for disk A, and C = user number
- ;
- ; Outputs:
- ; None.
- ;
- ; Implicit Inputs:
- ; None.
- ;
- ; Inplicit Outputs:
- ; Up to three characters are written to the console.
- ;
- ; Side Effects:
- ; Stack is affected.
- ;
- ; Calls:
- ; COUT, PAFDC
- ;--
- PAGE
- PDU:: PUSH AF ; save flags and A
- ;+
- ; Modify the count in B to make it a reasonable disk letter.
- ;-
- LD A,B
- ADD A,'A' ; this is the offset
- CALL COUT## ; display it
- ;+
- ; Display the user number as decimal.
- ;-
- LD A,C
- CALL PAFDC## ; display as decimal
- ;+
- ; We done.
- ;-
- POP AF ; restore A and flags
- RET
- ;
- SUBTTL Print the file name and type
- PAGE
- ;++
- ; PFN
- ; Display the File Name and Type
- ;
- ; Inputs:
- ; DE - FCB for file to display
- ;
- ; Outputs:
- ; None.
- ;
- ; Implicit Inputs:
- ; None.
- ;
- ; Inplicit Outputs:
- ; Up to 12 characters are written to the console, 8 for the file name
- ; (blank padded), a period, and 3 for the file type (blank padded).
- ; Bit 7 is cleared in all characters to prevent funny characters
- ; from falling through.
- ;
- ; Side Effects:
- ; Stack is affected.
- ;
- ; Calls:
- ; COUT
- ;--
- PAGE
- PFN:: PUSH AF ; save flags and A
- PUSH BC ; and especially B
- PUSH HL ; to save from clobbering
- ;+
- ; Point the FCB to the first character in the file name and start
- ; printing it to the screen.
- ;-
- LD H,D ; move DE to HL
- LD L,E
- INC HL ; position to first char in file name
- LD B,8 ; want 8 characters
- PN1: LD A,(HL) ; get character
- RES 7,A ; clear bit 7
- CALL COUT## ; print it
- INC HL ; point to next
- DJNZ PN1 ; do exactly 8
- ;+
- ; Now display the period.
- ;-
- LD A,'.'
- CALL COUT## ; print the period
- ;+
- ; Print the three characters in the file type.
- ;-
- LD B,3 ; want 3 characters
- PN2: LD A,(HL) ; get character
- RES 7,A ; clear bit 7
- CALL COUT## ; print it
- INC HL ; poin to next
- DJNZ PN2 ; do exactly 3
- ;+
- ; We done.
- ;-
- POP HL ; restore what was used
- POP BC
- POP AF
- RET ; we done
- SUBTTL Read only Storage Areas
- PAGE
- ;+
- ; Signon message.
- ;-
- SIGNON: DEFB 'CTRLCVT, Version '
- DEFB [VERSION / 10] + '0'
- DEFB '.'
- DEFB [VERSION MOD 10] + '0'
- DEFB '-'
- DEFB [MODF / 100] + '0'
- DEFB [MODF / 10 MOD 10] + '0'
- DEFB [MODF MOD 10] + '0'
- DEFB 0
- ;+
- ; Informational message pointers are kept here.
- ;-
- IF VERBOSE ; only compile if requested
- CNVM1: DEFZ ' Converting '
- CNVM2: DEFZ ' to '
- SUMM1: DEFZ ' characters were converted'
- ENDIF ; VERBOSE
- DESCN1: DEFZ 'Usage:'
- DESCN2: DEFZ ' CTRLCVT [du:]filename.typ [du:]filename.typ'
- IF VERBOSE ; additional help only if requested
- DESCN3: DEFZ 'where the first file specification is the input file to be'
- DESCN4: DEFZ 'converted, and the second file specification is the output'
- DESCN5: DEFZ 'file to which the converted output is written.'
- ENDIF ; VERBOSE
- ;+
- ; Error message pointers are kept here.
- ;-
- NOARGS1:DEFZ ' No arguments on command line'
- ARGL1: DEFZ ' Too few arguments'
- ARGG1: DEFZ ' Too many arguments'
- ERRF1: DEFZ ' File '
- ERRF2: DEFZ ' NOT Found'
- ERRX1: DEFZ ' Can not open file '
- ERRX2: DEFZ ' for processing'
- ERRW1: DEFZ ' Write error'
- ;+
- ; Command line for debugging.
- ; We build a counted ASCII string (VAX/VMS terminology: .ASCIC)
- ;-
- IF DEBUG
- CMDLNB: DEFB CMDLNE-CMDLIN ; length
- CMDLIN: DEFB ' TEST.TXT TEST.001'
- CMDLNE:
- ENDIF ; DEBUG
- SUBTTL Read/Write Storage Areas
- PAGE
- DSEG
- ;+
- ; Token pointer storage area.
- ;-
- TOKENP: DEFB 2 ; maximum of three tokens
- DEFS 1 ; number we really found
- TOKEN1: DEFS 2 ; first token pointer
- TOKEN2: DEFS 2 ; second token pointer
- ;+
- ; Input and output extended FCB's.
- ;-
- ICB:
- ICBPAGES:
- DEFS 1 ; number of 128 byte pages to set up
- DEFS 5 ; filled in by callee
- ICBBUFA:DEFW 1 ; address of input buffer
- IFCB: DEFS 36
- ;
- OCB:
- OCBPAGES:
- DEFS 1 ; number of 128 byte pages to set up
- DEFS 5 ; filled in by callee
- OCBBUFA:DEFW 1 ; address of input buffer
- OFCB: DEFS 36
- ;+
- ; Counter storage area.
- ;-
- IF VERBOSE ; also only compile if requested
- CONV: DEFS 2 ; word for the converted total
- ;+
- ; DU storage areas.
- ;-
- IDU: DEFS 2 ; places to keep the two DU's
- ODU: DEFS 2 ; where we can get at them
- ENDIF ; VERBOSE
- ;+
- ; Z33 or greater enabled flag.
- ;-
- IF Z33
- Z33FLAG:DEFS 1 ; flag: 0 if Z33 enabled, nonzero if not
- ENDIF ; Z33
- ;+
- ; End of data area.
- ;-
- END START ; identify entry point for module
- rd for the converted total
- ;+
- ; DU storage areas.
- ;-
-