;
;  PROGRAM:  DEV3
;  AUTHOR:  RICHARD CONN
;  VERSION:  1.0
;  DATE:  4 Apr 84
;  PREVIOUS VERSION:  None
;  DERIVATION:  DEVICE2 of ZCPR2
;
VERS    EQU     10
z3env   SET     0f400h

;
;       DEV is a program which enables the user to manipulate the
; extended ZCPR3 redirectable device drivers.  It allows the user to
; perform the following functions:
;
;               o Display the Names of the Current Devices
;               o Set One or More of the Current Devices
;               o Ask for Help
;
;       The format of the DEV command is:
;
;               DEV or DEV //                   <-- Ask for Help
;               DEV command,command,command ... <-- Issue Commands
;
; where "command" may take the following forms:
;
;               DISPLAY ALL     <-- Display Names of All Devices
;               DISPLAY CON     <-- Display Names of Consoles
;               DISPLAY LST     <-- Display Names of Printers
;               DISPLAY RDR     <-- Display Names of Readers
;               DISPLAY PUN     <-- Display Names of Punches
;
;               CON:=name       <-- Select Console
;               LST:=name       <-- Select Printer
;               RDR:=name       <-- Select Reader
;               PUN:=name       <-- Select Punch
;

;
;  Constants
;
tbuff   equ     80h
cr      equ     0dh
lf      equ     0ah

;
;  SYSLIB Routines
;
       ext     z3init,getiop
       ext     cin,cout,epstr,eprint,cline,crlf

;
; Environment Definition
;
       if      z3env ne 0
;
; External ZCPR3 Environment Descriptor
;
       jmp     start
       db      'Z3ENV' ;This is a ZCPR3 Utility
       db      1       ;External Environment Descriptor
z3eadr:
       dw      z3env
start:
       lhld    z3eadr  ;pt to ZCPR3 environment
;
       else
;
; Internal ZCPR3 Environment Descriptor
;
       MACLIB  Z3BASE.LIB
       MACLIB  SYSENV.LIB
z3eadr:
       jmp     start
       SYSENV
start:
       lxi     h,z3eadr        ;pt to ZCPR3 environment
       endif

;
; Start of Program -- Initialize ZCPR3 Environment
;
       call    z3init  ;initialize the ZCPR3 Env and the VLIB Env

;
;  Start of Program
;

       call    getiop  ;check for initialization
       mov     a,h
       ora     l       ;must NOT be zero
       jnz     start0
       call    banner
       call    eprint
       db      cr,lf,'DEV NOT Initialized with I/O Base',0
abort:
       call    eprint
       db      ' -- Aborting',0
       ret

start0:
       call    status  ;check for drivers
       jnz     start1
       call    banner
       call    eprint
       db      cr,lf,'Redirection Not Supported',0
       jmp     abort

start1:
       lxi     h,tbuff ;pt to input buffer
       call    cline   ;extract and save command line
       call    sblank  ;skip to non-blank
       ora     a       ;EOL?
       jz      help    ;select help
       cpi     '/'     ;help?
       jnz     docmd   ;run command subroutine

;
;  Print Help Message
;
help:
       call    banner
       call    eprint
       db      cr,lf,'DEV - Quick Redirectable I/O Device Selector'
       db      cr,lf,'Syntax:'
       db      cr,lf,'   DEV or DEV //             '
       db      '<-- Ask for Help'
       db      cr,lf,'   DEV Command,Command, ...  '
       db      '<-- Issue Commands'
       db      cr,lf,'where "command" may take the following forms:'
       db      cr,lf,'  DISPLAY=ALL    '
       db      '<-- Display All Devices'
       db      cr,lf,'  DISPLAY=CON    '
       db      '<-- Display Consoles'
       db      cr,lf,'  DISPLAY=LST    '
       db      '<-- Display Printers'
       db      cr,lf,'  DISPLAY=RDR    '
       db      '<-- Display Readers'
       db      cr,lf,'  DISPLAY=PUN    '
       db      '<-- Display Punches'
       db      cr,lf
       db      cr,lf,'  CON:=name  <-- Select Console'
       db      cr,lf,'  LST:=name  <-- Select Printer'
       db      cr,lf,'  RDR:=name  <-- Select Reader'
       db      cr,lf,'  PUN:=name  <-- Select Punch'
       db      0
       ret
;
; Print Banner
;
banner:
       call    eprint
       db      'DEV, Version '
       db      (vers/10)+'0','.',(vers mod 10)+'0',0
       ret
;
;  Skip to Non-Blank Routine
;
sblank:
       mov     a,m     ;get char
       inx     h       ;pt to next
       cpi     ' '     ;blank?
       jz      sblank  ;continue if so
       dcx     h       ;pt to non-blank
       ret

;
;  Skip until a delimiter encountered
;
sdelm:
       mov     a,m     ;get char
       inx     h       ;pt to next
       cpi     ' '+1   ;<SP> or less?
       rc
       cpi     '='
       rz
       cpi     ','
       rz
       jmp     sdelm

;
;  DOCMD -- This subroutine processes the command line pted to by HL.
;    It is the Main Line if a DEVICE command line is given, it is just
;    a subroutine if the user is in interactive mode.
;
docmd:
       call    docmd1  ;do first command
       call    sdelm   ;skip to delim
       cpi     ','     ;another command?
       jz      docmd
       ret
docmd1:
       mov     a,m     ;get command letter
       cpi     'C'     ;console assignment?
       jz      docon
       cpi     'D'     ;display?
       jz      dodisp
       cpi     'L'     ;LST:?
       jz      dolst
       cpi     'P'     ;PUN:?
       jz      dopun
       cpi     'R'     ;RDR:?
       jz      dordr
cerr:
       call    eprint
       db      cr,lf,'Error at -- ',0
       call    epstr   ;print rest
       ret

;
;  Do LST: Assignment
;
dolst:
       call    eprint
       db      ' LST:',0
       mvi     a,3     ;select LST:
       jmp     assign

;
;  Do PUN: Assignment
;
dopun:
       call    eprint
       db      ' PUN:',0
       mvi     a,2     ;select PUN:
       jmp     assign

;
;  Do RDR: Assignment
;
dordr:
       call    eprint
       db      ' RDR:',0
       mvi     a,1     ;select RDR:
       jmp     assign

;
;  Do CON: Assignment
;
docon:
       call    eprint
       db      ' CON:',0
       mvi     a,0     ;select console
;
;  Do Assignment in General
;
assign:
       mov     b,a     ;save A in B
       push    b       ;save BC
       call    sdelm   ;skip to delimiter
       pop     b       ;get BC
       cpi     ' '
       jz      asgn0
       cpi     '='
       jnz     cerr
asgn0:
       mov     a,b     ;get A back
       sta     logical ;save logical device number
       shld    name    ;save ptr to mnemonic
       mov     b,a     ;number in B
       inr     b       ;add 1 for offset
       call    status  ;get device status
       dcx     h       ;pt to previous
       dcx     h
asgn1:
       inx     h       ;pt to next
       inx     h
       dcr     b       ;count down
       jnz     asgn1
       mov     c,m     ;get number of devices in C
       mov     a,c     ;check for value of zero
       ora     a
       jnz     asgn2
       lhld    name    ;pt to error name
       jmp     cerr
asgn2:
       lda     logical ;get logical device number
       mov     b,a     ;... in B
       push    b       ;save device count
       dcr     c       ;pt to previous
       call    namer   ;get name
       xchg            ;name pted to by DE
       lhld    name    ;user's name pted to by HL
asgn3:
       ldax    d       ;get name of device
       cpi     ' '+1   ;done?
       jc      asgn3a
       cmp     m       ;compare to user
       jnz     asgn4
       inx     h       ;pt to next
       inx     d
       jmp     asgn3
asgn3a:
       mov     a,m     ;get user
       cpi     ' '+1   ;done?
       jc      asgn3b
       cpi     ','     ;done?
       jnz     asgn4
asgn3b:
       pop     b       ;match -- C-1 is selected device
       dcr     c       ;decrement
       call    select  ;select device
       lda     logical ;get logical device in A
       call    current ;print name of device selected
       lhld    name    ;pt to name for scan continuation
       ret
asgn4:
       pop     b       ;count down
       dcr     c       ;count down
       jnz     asgn2   ;continue
       lhld    name    ;pt to invalid name
       call    eprint
       db      cr,lf,' Invalid Name at -- ',0
       call    epstr
       lhld    name    ;pt to name for scan continuation
       ret

;
;  Display Devices and Assignments
;
dodisp:
       call    sdelm   ;skip to delimiter
       ora     a       ;none=all
       jz      dispall
       mov     a,m     ;get char after delimiter
       cpi     'A'     ;all?
       jz      dispall
       cpi     'C'     ;CON:
       jz      dispcon
       cpi     'L'     ;LST:
       jz      displst
       cpi     'P'     ;PUN:
       jz      disppun
       cpi     'R'     ;RDR:
       jz      disprdr
       jmp     cerr
dispall:
       call    dispcon ;successive displays
       call    disprdr
       call    eprint
       db      cr,lf,'Strike Any Key -- ',0
       call    cin
       call    disppun
       jmp     displst
dispcon:
       call    eprint
       db      cr,lf,'CON:',0
       mvi     a,0     ;select CON:
       call    disp
       jmp     curr
displst:
       call    eprint
       db      cr,lf,'LST:',0
       mvi     a,3     ;select LST:
       call    disp
       jmp     curr
disprdr:
       call    eprint
       db      cr,lf,'RDR:',0
       mvi     a,1     ;select RDR:
       call    disp
       jmp     curr
disppun:
       call    eprint
       db      cr,lf,'PUN:',0
       mvi     a,2     ;select PUN:
       call    disp
;
;  Print Name of Current Device
;
curr:
       call    crlf    ;new line
current:
       push    h       ;save ptr
       mov     b,a     ;save number in B
       push    b       ;save B
       call    eprint
       db      ' Assignment is ',0
       push    b       ;save B
       call    status  ;get status
       pop     b       ;get B
       inr     b       ;add 1 for offset
       dcx     h       ;back up
curr1:
       inx     h       ;pt to next
       inx     h
       dcr     b       ;count down
       jnz     curr1
       pop     b       ;get logical number in B
       mov     c,m     ;get physical number in C
       call    pname0  ;print first part of name only
       pop     h       ;get ptr
       ret
;
;  Print Names of All Physical Devices for a Logical Device
;
disp:
       push    h       ;save char ptr
       push    psw     ;save device number
       call    eprint
       db      ' Devices --',0
       mov     b,a     ;logical device in B
       push    b       ;save for later
       push    b       ;save it
       call    status  ;get status report
       pop     b       ;get logical device number
       inr     b       ;add 1 for offset
       dcx     h       ;back up
       dcx     h
disp1:
       inx     h       ;pt to next
       inx     h
       dcr     b       ;count down
       jnz     disp1
       pop     b       ;get B back
       mov     c,m     ;get count of devices
       mov     a,c     ;check for none
       ora     a
       jz      disp3
disp2:
       push    b       ;save values
       dcr     c       ;pt to next name
       call    eprint
       db      cr,lf,'    ',0
       call    pnamer  ;print name (B=logical, C=physical)
       pop     b       ;get count
       dcr     c       ;count down
       jnz     disp2
disp3:
       pop     psw
       pop     h
       ret
;
;  Routine to Print Name of Selected Device
;       B=logical number, C=physical number
;
pnamer:
       push    b       ;save BC
       call    pname0  ;print first part of name
       call    eprint  ;print separator
       db      ' - ',0
       call    epstr   ;print rest as string
       pop     b       ;restore BC
       ret
;
;  Print first part of selected device name
;
pname0:
       call    namer   ;get ptr to string
       mvi     b,8     ;at most 8 chars
pname1:
       mov     a,m     ;get char
       inx     h       ;pt to next char
       cpi     ' '     ;end of name?
       jz      pname2
       call    cout    ;print char
       dcr     b       ;count down
       jnz     pname1
       ret
pname2:
       mvi     a,' '   ;print spaces
       call    cout
       dcr     b       ;count down
       jnz     pname2
       ret

;
;  Basic Interface Routines
;
status:
       lxi     d,0     ;Offset 0
runit:
       call    getiop  ;device driver base
       dad     d
       pchl
select:
       lxi     d,3     ;Offset 3
       jmp     runit
namer:
       lxi     d,6     ;Offset 6
       jmp     runit

;
;  Buffers
;
logical:
       ds      1       ;Logical Device Number
name:
       ds      2       ;Pointer to User-Supplied Name

       end