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 / JSAGE / ZSUS / LBR / LX22.LBR / LX22.ZZ0 / LX22.Z80
Text File  |  1991-02-19  |  29KB  |  1,078 lines

  1. ;    title    'LX - RUN PROGRAM FROM COMMAND.LBR'
  2.  
  3. ;  PROGRAM: LX
  4. ;  ORIGINAL AUTHOR: RICHARD CONN
  5. ;  VERSION: 1.0
  6. ;  DATE: 10 Aug 85
  7.  
  8. VERS    EQU    22
  9. REV    EQU    ' '
  10. TYPE    EQU    4        ; ZCPR program type to assemble LX for
  11. ;TYPE is 1,3, or 4. If type 4 is elected, then the resulting REL object
  12. ;must be linked to a PRL file whose 256 byte header contains a Type 4
  13. ;Loader. See the notes for rev 2.0c by Cam Cotrill in LX.HST.
  14.  
  15. ;=========================================================
  16. ;ASSEMBLY/LINK using ZMAC assembler and ZML linker (aeh)
  17.  
  18. ;for Type equ 1
  19. ;    ZMAC LX20
  20. ;    ZML LX20,LX-1/N
  21.  
  22. ;For Type equ 3 and execution at 8000h
  23. ;    ZMAC LX20
  24. ;    ZML LX20,LX-3.COM/N /A:8000
  25.  
  26. ;for Type equ 4
  27. ;    ZMAC LX20
  28. ;    ZML LX20,LX-4.COM/N,T4LDR/P
  29. ;        (T4LDR.HDR is in current dir or ZML's alternate dir)
  30. ; T4LDR.HDR is a binary file containing the type 4 loader code
  31. ; required by ZCPR34. It is exactly 256 bytes long.
  32.  
  33. ;=========================================================
  34.  
  35. ;abbreviated LX revision history. See LX.HST for full change notes.
  36.  
  37. ; 2.2                02/20/91        Bruce Morgen
  38. ;    Fix cosmetic problem with missing newlines when LX is a
  39. ;    genuine ECP, shorten some other code.
  40.  
  41. ; 2.1                08/13/90        Howard Goldstein
  42. ;    Fix bugs in type 4 version, shorten code
  43.  
  44. ; 2.0f                08/07/90        Al Hawley (aeh)
  45. ;    Clean up source & reorganize configuration block.
  46.  
  47. ; 2.0e                08/05/90        Howard Goldstein
  48. ;    Add local stack, fix bugs. OK for type 2 programs now
  49.  
  50. ; 2.0d                07/22/90        Al Hawley (aeh)
  51. ;    Define configuration data block for ZCNFG configuration.
  52.  
  53. ; 2.0c                11/05/89        Cameron W. Cotrill
  54. ;    Revise code for ease of making proper Type 4 version of LX
  55.  
  56. ; 2.0b                            Cameron W. Cotrill
  57. ;     Implemented Howard Goldstein's corrected ECP code in CHEKWS.
  58.  
  59. ; 2.0a                            Cameron W. Cotrill
  60. ;    Massive rewrite to allow LX to run as type 1,3,4 and extract
  61. ;       and load type 1,3,4 files.
  62.  
  63. ; 1.9d                            Cameron W. Cotrill
  64. ;    Code optimization for LX running as type 3 or 4
  65.  
  66. ; 1.9a            19 Aug 89.            Harold F. Bower
  67. ;    Modified to use SARGV and Z33GMTOP routines.  Other minor optimization
  68.  
  69. ; 1.9            April 1, 1988            Bruce Morgen
  70. ;     Added type 3 safety header, restore wheel response options
  71.  
  72. ; 1.8             Howard Goldstein, November 29, 1987
  73. ;    Rewrote the ADJCML routine to adjust the command line properly
  74.  
  75. ; 1.7            Howard Goldstein, November 21, 1987
  76. ;    Changed code to parse file names via resident Z33/34 code.
  77.  
  78. ; 1.6            Bruce Morgen @23:55:56 June 4, 1987
  79. ;    Added WS and ARUNZ compatibility features. '/' syntax.
  80. ;    Errors abort to error handler.
  81.  
  82. ; 1.5            Bruce Morgen @15:03:03 April 24, 1987
  83. ;    Code revisions for WS, Z33 compatibility. Remove self modifying code.
  84.  
  85. ; 1.2            3 September 1986 - Michael Bate
  86. ;    Auto-installs ZCPR3 utilities. 
  87.  
  88. ; 1.1                27 Feb 86  jww
  89. ;    Changed ARGV to recognize '=' argument delimiter
  90.  
  91. ; 1.0 - Release version
  92.  
  93. ; LX is like the old LRUN tools in that it looks at its arguments as a command
  94. ; line to be executed.  LX locks onto a library file, searches for the command
  95. ; verb COM file in it, extracts the COM file into memory at 100H, and sets up
  96. ; the various buffers to look like the COM file was executed by the ZCPR3
  97. ; command processor.
  98.  
  99. ; Unlike the other LRUN tools I've seen and heard of (with the possible
  100. ; exception of LRUNZ), LX truly acts as the ZCPR3 command processor, parsing
  101. ; the command line as ZCPR3 itself would.  Named directory references are
  102. ; allowed, the External FCB is loaded if available, etc.  Any ZCPR3 tool
  103. ; executed by LX sees the environment as it would if ZCPR3 itself executed the
  104. ; tool.
  105.  
  106. ; For security, no directory references are allowed (they are ignored) for any
  107. ; arguments if the wheel byte is not set.
  108.  
  109.     PUBLIC    COUT        ; b/m, April 24, 1987
  110.     public    print        ; hg, 08/05/90
  111.  
  112. ; Externals
  113.  
  114.     .request z3lib        ; From Z3LIB Get...
  115.  
  116.     EXT    Z3INIT, ZPRSFN, Z3LOG, Z33CHK, Z33FNAME, GZMTOP
  117.     EXT    PUTER3, GETQUIET, GETCST, PUTCST, PFIND
  118.     EXT    GETMSG, GETEFCB, GETWHL, GETCL1
  119.     ext    prttype
  120.  
  121.     .request syslib1,syslib0; From SYSLIB Get...
  122.  
  123.      if    type ne 4
  124.     EXT    CODEND
  125.      endif
  126.     EXT    EPRINT, RETUD, PUTUD, LOGUD, GETUD, PFN2
  127.     EXT    INITFCB, F$EXIST, BOUT, CRLF
  128.     ext    LUINIT, LUOPEN, LUREAD, ARGV
  129.     ext    setdma
  130.  
  131. ; Symbol definitions
  132.  
  133. CR    EQU    0DH
  134. LF    EQU    0AH
  135. BDOSE    EQU    5
  136. FCB1    EQU    5CH
  137. FCB2    EQU    6CH
  138. TBUFF    EQU    80H
  139. TPA    EQU    100H
  140. ;LNSIZE    EQU    22        ; Number of chars allowed for library name
  141. LNSIZE    EQU    21        ; Number of chars allowed for library name
  142.  
  143. ;---------- ZCPR3x Program header -------------
  144.  
  145. ENTRY:    jr    start            ; bypass header and data
  146.                     ; must be JR for type 3 safety code
  147.     db    0            ; space filler required.
  148.  
  149. Z3ENAME: DB    'Z3ENV'
  150. Z3LTYP:     DB    TYPE            ; TYPE is 1,3, or 4
  151. Z3EADR:     DEFW    0            ; Filled in by Z33
  152.  
  153.       if    type eq 4
  154.     public    $memry
  155. $memry:     ds    2            ; Offset of top of lx+1.  Only
  156.                     ; valid prior to relocation.
  157.       else
  158.      DEFW    ENTRY            ; Intended load address
  159.       endif
  160.  
  161. ;-------------- Configuration Data ---------------
  162.  
  163.     DB    'LX22    ',0        ;CFG filename, terminator
  164.  
  165. OPTION:     DB    0FFH            ; Make zero for wheel byte
  166.                     ; control of default LBR
  167.  
  168. ;  Names of Library Files
  169.  
  170. LIBNAM1: DB    'ROOT:COMMAND.LBR'    ; Wheel's library
  171.      DS    LNSIZE-($-LIBNAM1),' '
  172.      db    0
  173.  
  174. LIBNAM2: DB    'ROOT:USERCMD.LBR'    ; Non-wheel library
  175.      DS    LNSIZE-($-LIBNAM2),' '
  176.      db    0
  177.  
  178. ; Default Filetype strings    ; moved from Data area (aeh)
  179.  
  180. LBRTYP:    DB    'LBR'        ; Default lbr file type
  181. COMTYP:    DB    'COM'        ; Default com file type
  182.  
  183. ;----------- End of Configuration Data ---------------
  184. ; Beginning of code
  185.  
  186. start:
  187.      IF    TYPE EQ 3
  188. ; TYPE 3 HEADER
  189. ; Code modified as suggested by Charles Irvine to function correctly with
  190. ; interrupts enabled.  Program will abort with an error message when not
  191. ; loaded to the correct address (attempt to run it under CP/M or Z30).
  192. ; Slightly changed by Bruce Morgen to save a byte and a level of stack
  193. ; at the final test code (Howard Goldstein's suggestion, inspired by Joe
  194. ; Wright's observation).
  195.  
  196.     LD    HL,0            ; Point to warmboot entry
  197.     LD    A,(HL)            ; Save the byte there
  198.     DI                ; Protect against interrupts
  199.     LD    (HL),0C9H        ; Replace warmboot with a return opcode
  200.     RST    0            ; Call address 0, pushing RETADDR
  201.                     ; onto stack
  202. RETADDR: LD    (HL),A            ; Restore byte at 0
  203.     DEC    SP            ; Get stack pointer to point
  204.     DEC    SP            ; To the value of RETADDR
  205.     POP    HL            ; Get it into HL and restore stack
  206.     EI                ; We can allow interrupts again
  207.     LD    DE,RETADDR        ; This is where we should be
  208.     XOR    A            ; Clear carry flag
  209.     SBC    HL,DE            ; Subtract -- we should have 0 now
  210.     JR    Z,START1        ; If addresses matched, begin real code
  211.     ADD    HL,DE            ; Restore value of RETADDR
  212.  
  213.     LD    DE,NOTZ33MSG-RETADDR    ; Offset to message
  214.     ADD    HL,DE
  215.     EX    DE,HL            ; Switch pointer to message into DE
  216.     LD    C,9
  217.     JP    BDOSE            ; Return via BDOS print string function
  218. NOTZ33MSG:
  219.     DB    'Not Z33+$'        ; Abort message if not Z33-compatible
  220. START1:
  221.      ENDIF            ;type 3
  222.  
  223.     LD    (OLDSTK),SP    ; Save system stack
  224.     LD    SP,STACK    ; Set up local stack
  225.     LD    HL,(Z3EADR)    ; Pt to zcpr3 environment
  226.     CALL    Z3INIT        ; Init zcpr3 environment
  227.     CALL    GZMTOP        ; Get base Address of CCP
  228.     LD    (TPAEND),hl    ; Set end of TPA
  229.     LD    A,10
  230.     LD    (ERRCD),A    ; Assume error code 10 (for now)
  231.     LD    HL,ARGV2    ; Usual command tail start ptr.
  232.     LD    (TAILST),HL
  233.  
  234. ; Set name of default library file
  235.  
  236.     LD    HL,LIBNAM1
  237.     LD    A,(OPTION)
  238.     OR    A
  239.     CALL    Z,GETWHL
  240.     JR    NZ,NOGWHL
  241.     LD    HL,LIBNAM2
  242. NOGWHL:    LD    (LIBNAME),HL
  243.  
  244. ; Save home directory
  245.  
  246.     CALL    PUTUD
  247.  
  248. ; First parse of command line to determine if help needed, name of library
  249.  
  250.     LD    DE,TBUFF+1    ; Pt to command line
  251.     LD    HL,ARGS        ; Pt to argument table
  252.     LD    (HL),5        ; Init. for five arguments
  253.     EX    DE,HL
  254.     XOR    A        ; Do not delimit tokens (A=0)
  255.     CALL    ARGV        ; Generate vector
  256.     LD    A,(ARGC)    ; Check count
  257.     LD    B,A        ; Save arg count in b
  258.     OR    A        ; Help if no args
  259.     JR    Z,HELP
  260.     LD    HL,(ARGV1)    ; Get ptr to first arg
  261.     LD    A,(HL)        ; Get first char of first arg
  262.     SUB    '/'        ; Test for help or forced ECP
  263.     LD    (FORCED),A    ; Save result for later
  264.     LD    A,(HL)        ; Re-get first char of first arg
  265.     JP    NZ,GO1        ; Skip help if not /
  266.     DEC    B        ; Reduce arg count by one
  267.     JP    NZ,GOECP    ; If only one arg with slash, assume help
  268.  
  269. ; Print Help Message
  270.  
  271. HELP:    CALL    GETCST
  272.     BIT    2,A        ; If someone typed "//" only
  273.     CALL    NZ,CRLF        ; We'll need an extra newline
  274.     CALL    EPRINT
  275.     DB    'LX, Version '
  276.     DB    vers/10+'0','.',(vers mod 10)+'0',REV,' ',0
  277.     LD    HL,ENTRY
  278.     LD    A,(Z3LTYP)
  279.     CALL    PRTTYPE        ; Identify what type and where we are
  280.     CALL    EPRINT
  281.     DB    cr,lf,' Syntax: LX [/] [-[dir:]library] command_line'
  282.     DB    cr,lf,' (Use "/" option when chaining from ARUNZ'
  283.     DB    ' default alias)',0
  284.     LD    SP,(OLDSTK)    ; Restore system stack
  285.     RET
  286.  
  287. ; Adjust vectors for forced-ECP mode
  288.  
  289. GOECP:    LD    DE,ARGV2
  290.     LD    HL,ARGV3
  291.     LD    (TAILST),HL
  292.     LD    HL,(ARGV2)
  293.     LD    A,(HL)
  294.     JR    GOECP1
  295.  
  296. ; Continue processing; check for and process library reference
  297.  
  298. GO1:    LD    DE,ARGV1    ; Set pointer for first token
  299. GOECP1:    CP    '-'        ; Library reference?
  300.     JR    NZ,GO2
  301.     DEC    B        ; Reduce argument count by 1
  302.     JP    Z,HELP        ; Library name by itself is not enough
  303.  
  304. ; Extract and store library reference
  305.  
  306.     PUSH    BC        ; Save arg count
  307.     LD    DE,(LIBNAME)    ; Set library name
  308.     PUSH    DE        ; Save on stack
  309.     INC    HL        ; Pt to name
  310.     LD    BC,LNSIZE    ; Size of buffer
  311.     LDIR            ; BC=00
  312.     POP    HL        ; Terminate name with zero
  313. LNSCAN:    LD    A,(HL)        ; Get next char
  314.     CP    ' '        ; Done?
  315.     JR    Z,LNSCAN1
  316.     OR    A
  317.     JR    Z,LNSCAN1
  318.     INC    HL        ; Pt to next
  319.     JR    LNSCAN
  320.  
  321. LNSCAN1: LD    (HL),B        ; B=0
  322.     LD    DE,(TAILST)    ; Set ptr to first token
  323.     POP    BC        ; Get arg count
  324.  
  325. ; DE pts to first token of command line
  326. ; Store command line (next token) into TBUFF
  327.  
  328. GO2:    PUSH    DE        ; Save ptr to first token
  329.     DJNZ    GO3        ; See if any tokens follow the command name
  330.                 ; If no more tokens, then zero gbuff
  331.     LD    HL,GBUFF    ; Store empty command line into gbuff
  332.     LD    (HL),B        ; B=0.
  333.     INC    HL
  334.     LD    (HL),B
  335.     JR    GCLINE
  336.  
  337. ; Save command line tail into GBUFF
  338.  
  339. GO3:    EX    DE,HL        ; Switch regs around
  340.     INC    HL        ; Pt to next token
  341.     INC    HL
  342.     LD    E,(HL)        ; Get address
  343.     INC    HL
  344.     LD    D,(HL)        ; DE pts to first token of command line tail
  345.     LD    HL,GBUFF+1    ; Pt to command line buffer (char after)
  346.     LD    (HL),' '    ; Store leading space
  347.     INC    HL
  348.     EX    DE,HL        ; ..restore regs position
  349.     LD    B,1        ; Set char count to 1
  350. CLTSAVE: LD    A,(HL)        ; Get next char
  351.     LD    (DE),A        ; Store it
  352.     OR    A        ; Eol?
  353.     JR    Z,CLTSDON
  354.     INC    HL        ; Pt to next
  355.     INC    DE
  356.     INC    B        ; Increment count
  357.     JR    CLTSAVE
  358.  
  359. CLTSDON: LD    A,B        ; Get count
  360.     LD    (GBUFF),A    ; Set count in local buffer.
  361. GCLINE:    CALL    RETUD        ; C=current user
  362.     LD    HL,FCB1        ; Clear fcb1
  363.     CALL    CLRFCB
  364.     LD    HL,FCB2        ; Clear fcb2
  365.     CALL    CLRFCB
  366.     POP    HL        ; Get ptr to first token
  367.     LD    A,(HL)        ; Get address
  368.     INC    HL
  369.     LD    H,(HL)
  370.     LD    L,A        ; Hl pts to first token
  371.     LD    DE,ARGS        ; Use same argument vector table
  372.     LD    A,0FFH        ; Null-terminate arguments
  373.     CALL    ARGV
  374.     LD    C,0        ; Up to 3 tokens to obtain
  375.     LD    DE,ARGV1    ; Pt to first token
  376.     LD    A,(ARGC)    ; Get argument count
  377.     CP    4        ; Range?
  378.     JR    C,GO4
  379.     LD    A,3        ; Set 3 tokens
  380. GO4:    LD    B,A        ; In c
  381.  
  382. ; There are three tokens (max) to be extracted:
  383. ;    Program name (external FCB - done below)
  384. ;    FCB 1
  385. ;    FCB 2
  386.  
  387. GO5:    PUSH    BC        ; Save counters
  388.     CALL    NAMEBLD        ; Build token
  389.     POP    BC        ; Get counters
  390.     INC    C        ; Increment token id
  391.     DJNZ    GO5
  392.  
  393. ; Extract program name and put in local FCB for lbr file open.
  394.  
  395.     LD    DE,ARGV1    ; Pt to command name string
  396.     LD    A,(DE)        ; Get address in hl
  397.     LD    L,A
  398.     INC    DE
  399.     LD    A,(DE)
  400.     LD    H,A
  401.     LD    DE,LFCB        ; Pt to fcb
  402.     CALL    PARSE        ; Parse into fcb
  403.     LD    HL,9        ; Set type of file to 'com'
  404.     ADD    HL,DE
  405.     LD    DE,COMTYP    ; File type
  406.     EX    DE,HL
  407.     LD    BC,3        ; 3 bytes
  408.     LDIR
  409.  
  410. ; Copy program name to Z3EFCB
  411.  
  412.     CALL    GETEFCB        ; Set file type to com for external fcb
  413.     JR    Z,GO6        ; No external fcb
  414.     LD    DE,LFCB
  415.     EX    DE,HL
  416.     LD    C,33        ; B= 0 from LDIR above
  417.     LDIR            ; Copy name to external fcb
  418.  
  419. ; Locate LBR file
  420.  
  421. GO6:
  422.     CALL    FINDLF
  423.     JP    NZ,CHEKWS    ; Abort if not found
  424.  
  425. ; Load Command from Library into Memory
  426.  
  427.     CALL    LOADCOM        ; Extract and load to high RAM.
  428.                 ; ..also installs z3 utils
  429.     JP    Z,CHEKWS    ; If error
  430.  
  431. ; Set up TBUFF area
  432.  
  433. INSTALL:
  434.     CALL    GETUD        ; Return to home directory
  435.     LD    HL,TBUFF    ; Default dma address to TBUFF
  436.     CALL    SETDMA        ; Let SYSLIB do it
  437.     EX    DE,HL        ; Ptr to TBUFF into DE
  438.     LD    HL,GBUFF    ; Ptr to local buffer
  439.     LD    B,D        ; 128 bytes = 80H = TBUFF
  440.     LD    C,E        ; BC = 128
  441.     LDIR            ; move new command tail into place
  442.  
  443. ; Set up to Copy member and execute
  444.  
  445.     LD    HL,(LOADAT)
  446.     LD    A,0C7H        ; is first byte rst 0?
  447.     CP    (HL)
  448.     JR    NZ,INSTA0    ; if not
  449.     LD    (HL),0C3H    ; make it a jp
  450. INSTA0:
  451.     LD    BC,CPYSIZ    ; size of cpycod routine
  452.     LD    A,(CPYFLG)
  453.     AND    A
  454.     JR    Z,INSTA3    ; If load and run address same
  455.  
  456. ; See where we can stick the cpycod routine
  457.  
  458.     INC    A        ; loaded below lx and moving up?
  459.     JR    NZ,INSTA1    ; if above lx and moving down
  460.     SBC    HL,BC        ; point below loaded module
  461.     LD    A,H
  462.     AND    A        ; legal address? (>0)
  463.     JR    NZ,INSTA2    ; if ok
  464.     LD    HL,(LOADAT)    ; try top of mem otherwise
  465.  
  466. ; Loaded above lx, moving down.  Stick cpycod above load image.
  467.  
  468. INSTA1:    LD    DE,(CPYCNT)
  469.     ADD    HL,DE        ; top of loaded code
  470.     LD    D,H
  471.     LD    E,L
  472.     ADD    HL,BC        ; add in size of copy code
  473.     EX    DE,HL
  474.     LD    A,(TPAEND+1)
  475.     CP    D        ; see if overflows tpa
  476.     JP    C,LCOMER    ; if overflow
  477.     JR    NZ,INSTA2    ; if ok to load
  478.     LD    A,(TPAEND)
  479.     CP    E
  480.     JP    C,LCOMER    ; if overflow
  481.  
  482. ; Move cpycod into place
  483.  
  484. INSTA2:    PUSH    HL        ; stack copy routine address
  485.     EX    DE,HL
  486.     LD    HL,CPYCOD
  487.     LDIR
  488.     POP    HL        ; relocated copy routine
  489.     JR    INSTA4
  490.  
  491. ; Finish the last few details and run the program
  492.  
  493. INSTA3:    LD    HL,CPYCOD
  494. INSTA4:    CALL    CRLFECP        ; Deliver a newline if required
  495.     LD    SP,(OLDSTK)    ; Restore system stack
  496.     LD    DE,(RUNAT)    ; Destination address
  497.     PUSH    DE        ; stack it
  498.     PUSH    HL        ; stack the copy routine address
  499.     LD    BC,(CPYCNT)    ; Size of program in bytes
  500.     LD    HL,(Z3EADR)
  501.     LD    A,(CPYFLG)    ; Get the copy flag back
  502.     AND    A        ; clear z flag if relocation needed
  503.     RET            ; Go to cpycod, wherever it is...
  504.  
  505. ;==========================================================
  506. ; Copy routine - this will be placed wherever needed.
  507. ;  Cpycod exits to the entry point of the loaded program.
  508. ;==========================================================
  509.  
  510. CPYCOD:    RET    Z        ; If nothing moves, run it
  511.     PUSH    HL        ; save env address
  512.     LD    HL,(LOADAT)    ; Start address
  513.     INC    A
  514.     JR    Z,COPYC1    ; if moving up
  515.  
  516. ; Moving down, standard head to tail copy ok
  517.  
  518.     LDIR            ; Do copy (in place is ok)
  519.     POP    HL        ; restore env address
  520.     RET            ; Jump to program
  521.  
  522. ; Moving up in memory, use tail to head copy
  523.  
  524. COPYC1:    DEC    BC
  525.     ADD    HL,BC        ; Point to last byte of source
  526.     EX    DE,HL
  527.     ADD    HL,BC        ; Point to last byte of destination
  528.     EX    DE,HL
  529.     INC    BC
  530.     LDDR            ; tail to head copy
  531.     POP    HL        ; restore env address
  532.     RET
  533.  
  534. CPYSIZ    EQU    $-CPYCOD
  535.  
  536. ;==========================================================
  537. ; Failed to find either library or member, so clean up
  538. ;==========================================================
  539.  
  540. CHEKWS:    LD    SP,(OLDSTK)    ; Restore system stack
  541.     LD    A,(1)        ; Test for the WordStar kludge.
  542.     CP    3
  543.     JP    NZ,GETUD    ; Reassert orig. DU and exit.
  544.     CALL    GETCL1        ; Point hl to mcl
  545.     LD    E,(HL)        ; Get address of command delimiter
  546.     INC    HL
  547.     LD    D,(HL)
  548.     INC    HL
  549.     INC    HL
  550.     INC    HL
  551.     EX    DE,HL        ; DE pts to 1st char of mcl, HL TO CHAR
  552.                 ; ...FOLLOWING command that invoked LX
  553.     XOR    A
  554.     SBC    HL,DE        ; Number of chars in mcl to this point
  555.     LD    B,H        ;  ...to BC
  556.     LD    C,L
  557.     ADD    HL,DE        ; Restore pointer
  558.     DEC    HL        ; Point to last char of LX command
  559.     LD    A,';'        ; Search back for end of previous command
  560.     CPDR            ; ...or beginning of mcl
  561.     INC    HL        ;adjust pointer
  562.     JR    NZ,PRSMCL    ; pointer now correct if no previous cmd
  563.     INC    HL        ; Adjust again, skip '2'
  564. PRSMCL:    LD    A,(FORCED)
  565.     OR    A        ; Were we forced ECP?
  566.     JR    Z,ADJMCL    ; Then adjust MCL bffr.
  567.     CALL    GETCST        ; Get Command Status Flag.
  568.     LD    B,A
  569.     BIT    2,A        ; Real ECP?
  570.     JR    NZ,ERREXT    ; Then just set CSF error bit.
  571.     CALL    Z33CHK        ; Running ZCPR 3.3?
  572.     JR    NZ,GOTER3    ; Then just set ECP, error bits.
  573.     SET    3,B        ; Otherwise external source...
  574.     LD    A,(ERRCD)    ; Get our error code
  575.     CALL    PUTER3        ; Store for error handler
  576. GOTER3:    LD    A,B        ; Get back CSF.
  577.     JR    ERREXT        ; Set ECP, error bits and stuff.
  578.  
  579. ADJMCL:    LD    DE,ARGS        ; Pt to ARGV table
  580.     XOR    A        ; Don't delimit tokens
  581.     CALL    ARGV        ; Get vector of tokens in MCL
  582.     EX    DE,HL        ; Point to cmd start, save new first token
  583.     LD    HL,(ARGV3)    ; Pt to 3rd token
  584.     LD    A,(HL)        ; Get first char
  585.     CP    '-'        ; '-' means LBR name
  586.     JR    NZ,FOUNDL    ; If not, MCL begins here
  587.     LD    HL,(ARGV4)    ; else, get next token
  588.  
  589. FOUNDL:    LD    A,(HL)
  590.     LD    (DE),A        ; copy a character
  591.     INC    HL
  592.     INC    DE        ; bump pointers
  593.     AND    A        ; end of string?
  594.     JR    NZ,FOUNDL    ; continue until null found    
  595.  
  596.     CALL    GETCST        ; Get Cmd. Status Flag
  597. ERREXT:    OR    110B        ; Set ECP and error bits.
  598.     JP    PUTCST        ; Put 'em in CSF and we're done,
  599.                 ; return via Z3LIB routine
  600.  
  601. ;==========================================================
  602. ; Clear FCB pted to by HL
  603. ; Current user area is in C
  604. ;==========================================================
  605.  
  606. CLRFCB:    LD    (HL),0        ; Current disk
  607.     INC    HL        ; Pt to name
  608.     LD    B,11        ; 11 bytes
  609.     LD    A,' '        ; Space fill
  610.     CALL    FILL
  611.     XOR    A        ; Get a Null for now and later
  612.     LD    (HL),A
  613.     INC    HL
  614.     LD    (HL),C        ; User area (byte 13)
  615.     INC    HL
  616.     LD    B,4        ; Number of bytes w/zeros (in A)
  617.             ;..fall through to FILL
  618.  
  619. ; Fill B bytes pted to by HL with A
  620.  
  621. FILL:    LD    (HL),A        ; Fill
  622.     INC    HL        ; Pt to next
  623.     DJNZ    FILL
  624.     RET
  625.  
  626. ;==========================================================
  627. ; Build name of token whose address is pted to by DE
  628. ; On input, C=flag:
  629. ;    0    Name of program
  630. ;    1    FCB 1
  631. ;    2    FCB 2
  632. ;==========================================================
  633.  
  634. NAMEBLD: LD    A,(DE)        ; Get address of token in hl
  635.     LD    L,A
  636.     INC    DE
  637.     LD    A,(DE)
  638.     LD    H,A
  639.     INC    DE
  640.     LD    A,C        ; Check flag
  641.     CP    1        ; Middle value
  642.     RET    C        ; Token 0 handled elsewhere
  643.  
  644.     PUSH    DE        ; Save ptr to next
  645.     LD    DE,FCB1        ; Assume fcb
  646.     JR    Z,NAMEB1    ; Fcb 1 if 1
  647.     LD    DE,FCB2        ; Else fcb2
  648.  
  649. ; DE pts to FCB to build into, HL pts to token
  650.  
  651. NAMEB1:    PUSH    DE        ; Save fcb ptr
  652.     LD    DE,LFCB        ; Pt to local fcb
  653.     CALL    PARSE        ; Parse into local fcb
  654.     CALL    GETWHL        ; Check wheel byte
  655.     JR    NZ,NAMEB2    ; Continue with name build if wheel
  656.  
  657. ; User is not a wheel, so force all directory references to current dir
  658.  
  659.     CALL    RETUD        ; Get current user in c
  660.     LD    HL,LFCB        ; Pt to fcb
  661.     LD    (HL),0        ; Set current disk
  662.     LD    DE,13        ; Offset to user
  663.     ADD    HL,DE
  664.     LD    (HL),C        ; Set current user into lfcb
  665.  
  666. ; Store FCB data into FCB
  667.  
  668. NAMEB2:    POP    DE        ; Get ptr to target fcb
  669.     LD    HL,LFCB        ; Pt to fcb
  670.     LD    BC,17        ; Copy 17 bytes
  671.     LDIR
  672.     POP    DE        ; Get ptr to next token
  673.     RET
  674.  
  675. ;==========================================================
  676. ; Locate Library File
  677. ; On exit, A=0 if library file found
  678. ;==========================================================
  679.  
  680. FINDLF: LD    HL,(LIBNAME)    ; Parse library file name
  681.     LD    DE,LUDFCB
  682.     CALL    PARSE
  683.     LD    DE,LUDFCB+9    ; Set library file type
  684.     LD    HL,LBRTYP    ; Default file type
  685.     LD    BC,3        ; 3 bytes
  686.     LDIR
  687.  
  688. ; Set specified directory as default
  689.  
  690.     LD    DE,LUDFCB    ; Pt to fcb
  691.     CALL    Z3LOG        ; Log into it for default
  692.  
  693. ; Look into directory pted to by user (or current if user did not spec one)
  694.  
  695.     CALL    INITFCB        ; Reset fcb
  696.     CALL    F$EXIST        ; Is file there?
  697.     JR    NZ,FLF2A
  698.  
  699. ; Look along path from current dir (not including current)
  700.  
  701.     CALL    GETUD        ; Log into original home directory
  702.     XOR    A        ; Don't search current dir also
  703.     CALL    PFIND        ; Search for file
  704.     JR    NZ,FLF2        ; File found, so process
  705.  
  706. ; File not found
  707.  
  708. flf1:    CALL    GETQUIET    ; Are we muzzled?
  709.     RET    NZ        ; Return NZ if so (A=FFh).
  710.     CALL    CRLFECP
  711.     CALL    EPRINT
  712.     DB    ' Library File ',0
  713.     LD    DE,LUDFCB+1    ; Print file name
  714.     CALL    PFN2
  715.     CALL    EPRINT
  716.     DB    ' Not Found',0
  717.     OR    0FFH        ; Error code (NZ & A=FFh)
  718.     RET
  719.  
  720.  
  721. ; File found
  722.  
  723. flf2:    CALL    LOGUD        ; Log into directory
  724. flf2a:    LD    DE,LUD        ; Pt to lud
  725.     CALL    LUINIT        ; Read to use library
  726.     JR    NZ,flf1        ; Error
  727.     RET
  728.  
  729.  
  730. ;==========================================================
  731. ; Load COM file into memory
  732. ; on exit, NZ if OK and HL = next block
  733. ;==========================================================
  734.  
  735. LOADCOM:
  736.     LD    DE,LUD        ; Pt to lud
  737.     LD    HL,LFCB+1    ; Pt to fcb (file name part)
  738.     CALL    LUOPEN        ; Open file
  739.     JP    NZ,LDCOME    ; if not found in lbr
  740.  
  741. ; Set up load and exe addresses
  742.  
  743.      IF    TYPE NE 4
  744.     CALL    CODEND
  745.     LD    (LXTOP),HL    ; Save our top address
  746.     EX    DE,HL
  747.     LD    HL,(TPAEND)
  748.     AND    A
  749.     SBC    HL,DE        ; Calculate high elbowroom
  750.     JR    NC,LOADC1
  751.      ENDIF        ; not type 4
  752.  
  753.     LD    HL,0        ; Fix underflow
  754. LOADC1:    LD    (HIGHBUF),HL    ; Save high buffer size
  755.     LD    HL,ENTRY
  756.     LD    DE,TPA
  757.     XOR    A
  758.     LD    (CPYFLG),A    ; indicate no copy needed (yet)
  759.     SBC    HL,DE
  760.     LD    (LOWBUF),HL    ; Save low buffer size
  761.  
  762.     LD    HL,TBUFF
  763.     CALL    SETDMA        ; Load first sector to TBUFF
  764.     LD    DE,LUD
  765.     CALL    LUREAD        ; First sector in tbuff
  766.  
  767. ; See if Z3 utility and install it if so
  768.  
  769.     LD    HL,TBUFF+3
  770.     LD    DE,Z3ENAME    ; DE -> "Z3ENV" in this program
  771.     LD    B,5        ; compare 5 bytes
  772. LOADC2: LD    A,(DE)        ; Compare "Z3ENV" with location in
  773.     CP    (HL)        ; the loaded program that would have it
  774.     JP    NZ,LOADC9    ; jump if no match - NOT a ZCPR3 utility
  775.     INC    DE
  776.     INC    HL        ; index through the 5 bytes
  777.     DJNZ    LOADC2
  778.     LD    A,(HL)        ; Get env type byte
  779.     CP    2
  780.     JP    Z,LOADC9    ; Type 2 - don't auto-install
  781.     CP    4
  782.     JP    NZ,LT13
  783.  
  784. ; Type 4, so we need to do some fancy footwork.  If lx is also a
  785. ;  type 4, the member will load and run immediately below lx.  If
  786. ;  lx is a type 3 high in memory, the member will load above lx if
  787. ;  there is room.  Otherwise, the member is loaded below lx.  All
  788. ;  type 4's are loaded at the address they will run.
  789.  
  790. LT4:
  791.      IF    TYPE NE 4
  792.     LD    A,(HIGHBUF+1)
  793.     AND    A        ; See if we have room above lx
  794.     LD    HL,(LXTOP)    ; Assume there is
  795.     JR    NZ,LOADC4    ; If assumption correct
  796.      ENDIF
  797.  
  798.     LD    HL,ENTRY-100H    ; Else load 2 records below lx
  799. LOADC4:    LD    B,2        ; Number of records to load
  800.     LD    (HDRADR),HL
  801. LOADC4A:
  802.     CALL    SETDMA
  803.     LD    DE,LUD
  804.     CALL    LUREAD        ; Read a record
  805.     LD    DE,128
  806.     ADD    HL,DE        ; point to next load address
  807.     DJNZ    LOADC4A        ; again until records 1 and 2 loaded
  808.     LD    DE,11-128
  809.     ADD    HL,DE        ; point to size word
  810.     LD    C,(HL)
  811.     INC    HL
  812.     LD    B,(HL)        ; Move size to bc
  813.     DEC    B
  814.     LD    A,B
  815.     OR    C        ; any reserved memory?
  816.     JR    NZ,LOADC5    ; Yes, take it into account
  817.     CALL    FSIZE
  818. LOADC5:
  819.      IF    TYPE NE 4
  820.     LD    HL,(HIGHBUF)
  821.     AND    A
  822.     SBC    HL,BC        ; enough room to load above lx?
  823.     LD    DE,(TPAEND)    ; if so, memtop is tpaend
  824.     JR    NC,LOADC6
  825.      ENDIF
  826.  
  827.     LD    HL,(LOWBUF)
  828.     AND    A
  829.     SBC    HL,BC        ; see if enough room to load low
  830.     LD    DE,ENTRY    ; if so, we load member under lx
  831.     JP    C,LCOMER    ; give mem full error if can't load
  832. LOADC6:    LD    HL,LT4X
  833.     PUSH    HL        ; vector exit thru this routine to clear z
  834.     LD    HL,(Z3EADR)    ; env address
  835.     INC    B        ; Adjust for loader
  836.     LD    A,-1
  837.     CALL    TBUFF+9        ; call loader.  Inserts return to part 2
  838.     LD    (RUNAT),HL
  839.     LD    (LOADAT),HL    ; save load and run addresses
  840.     LD    HL,(HDRADR)
  841.     LD    DE,TBUFF
  842.     LD    BC,128
  843.     LDIR            ; copy 2nd loader record to tbuff
  844.     LD    DE,(LOADAT)
  845.     LD    C,128
  846.     LDIR            ; copy first record of member to load address
  847.     PUSH    DE
  848.     LD    HL,(LOADAT)
  849.     LD    C,8
  850.     ADD    HL,BC
  851.     LD    (HL),4        ; change load type to 4
  852.     INC    HL
  853.     LD    DE,(Z3EADR)
  854.     LD    (HL),E
  855.     INC    HL
  856.     LD    (HL),D        ; install env address in util
  857.     POP    HL        ; move next load address to hl
  858.     JR    LCOM        ; load remainder of file
  859.  
  860. LT4X:    OR    0FFH        ; insure z flag clear
  861.     RET
  862.  
  863. ; Load absolute file (type 1-3, non-z).  Lx will first try to load
  864. ;  the member at the address it will run.  If it can't because lx
  865. ;  itself is in the way, lx will try and load the member above
  866. ;  itself.  Failing that, it will load the member below itself if 
  867. ;  possible.
  868.  
  869. LOADC9:    LD    DE,TPA        ; not z3 util, load in tpa
  870.     JR    LOADC3
  871.  
  872. LT13:    INC    HL
  873.     LD    DE,(Z3EADR)    ; This is a ZCPR3 utility
  874.     LD    (HL),E
  875.     INC    HL
  876.     LD    (HL),D        ; Store the environment address
  877.     LD    DE,TPA        ; assume program runs at 100h
  878.     INC    HL
  879.     CP    3        ; Check for type 3
  880.     JR    NZ,LOADC3    ; Branch if standard-TPA tool
  881.     LD    E,(HL)
  882.     INC    HL
  883.     LD    D,(HL)        ; Runtime address to de
  884. LOADC3:    LD    (RUNAT),DE    ; save run time address
  885.     CALL    FSIZE        ; return file load size in bc
  886.     LD    H,D
  887.     LD    L,E        ; copy run address to hl
  888.     ADD    HL,BC        ; top address of running program
  889.     EX    DE,HL
  890.     PUSH    HL
  891.     LD    HL,(TPAEND)
  892.     XOR    A        ; indicate no relocation
  893.     SBC    HL,DE        ; See if program will run
  894.     POP    DE
  895.     JR    C,LCOMER    ; If program would overflow memory
  896.  
  897.      IF    TYPE NE 4
  898.     LD    HL,(LXTOP)
  899.     SBC    HL,DE        ; check for base of runtime inside lx
  900.     JR    C,LD13A        ; base is above lx, ok to load
  901.      ENDIF
  902.  
  903.     LD    H,D
  904.     LD    L,E        ; copy run address to hl
  905.     ADD    HL,BC        ; top address of running program
  906.     PUSH    DE
  907.     LD    DE,ENTRY
  908.     AND    A
  909.     SBC    HL,DE        ; check for overlap on the low side
  910.     POP    DE
  911.     JR    C,LD13A        ; top of program is below lx, ok to load
  912.  
  913.      IF    TYPE NE 4
  914.     LD    HL,(HIGHBUF)
  915.     LD    A,1        ; flag for load above lx
  916.     SBC    HL,BC
  917.     LD    DE,(LXTOP)
  918.     JR    NC,LD13A    ; if ok to load above lx
  919.      ENDIF
  920.  
  921.     LD    HL,(LOWBUF)
  922.     OR    -1        ; flag for load below lx and clear cy
  923.     SBC    HL,BC
  924.     JR    C,LCOMER    ; if can't load beneath lx either
  925.     LD    HL,ENTRY
  926.     SBC    HL,BC        ; calculate load address
  927.     EX    DE,HL        ; and place in de
  928. LD13A:    LD    (CPYFLG),A    ; indicate if load and run addresses differ
  929.     LD    (LOADAT),DE
  930.     LD    HL,TBUFF
  931.     LD    BC,128
  932.     LDIR            ; move first record into place
  933.     EX    DE,HL        ; next load address in hl
  934.  
  935. LCOM:    CALL    SETDMA        ; Set dma address
  936.     LD    DE,LUD        ; Pt to lud
  937.     CALL    LUREAD        ; Read block
  938.     RET    NZ
  939.     LD    DE,128        ; Pt to next block
  940.     ADD    HL,DE
  941.     JR    LCOM
  942.  
  943. ; Memory full error
  944.  
  945. LCOMER:    CALL    GETQUIET
  946.     JR    NZ,QLCOM
  947.     CALL    CRLFECP
  948.     CALL    EPRINT
  949.     DB    ' Memory Full',0
  950. QLCOM:    LD    A,12
  951.     LD    (ERRCD),A
  952.     XOR    A        ; Error code
  953.     RET
  954.  
  955. ; LBR member not found error
  956.  
  957. ldcome:    CALL    GETQUIET    ; Muzzled?
  958.     JR    NZ,NOPRNT    ; Skip msg. if so
  959.     CALL    CRLFECP
  960.     CALL    EPRINT        ; Otherwise fall through
  961.     DB    ' File ',0
  962.     LD    DE,LFCB+1    ; Pt to FBC's file name ASCII.
  963.     CALL    PFN2
  964.     CALL    EPRINT
  965.     DB    ' Not Found in Library ',0
  966.     LD    DE,LUDFCB+1    ; Pt to library file name
  967.     CALL    PFN2
  968. NOPRNT:    XOR    A        ; Error
  969.     RET
  970.  
  971.  
  972. ; Calculate file size after loading first record
  973.  
  974. FSIZE:    XOR    A
  975.     LD    BC,(LUDBLR)    ; Get size in records -1 of member
  976.     INC    BC
  977.     SRL    B        ; assume no file larger than 65k
  978.     RR    C        ; r1-r8
  979.     RRA            ; shift r0 into a
  980.     LD    B,C
  981.     LD    C,A        ; file size in bytes
  982.     LD    (CPYCNT),BC    ; save for copy routine
  983.     RET
  984.  
  985. ;==========================================================
  986. ; Console character output "routine".  Unlike SYSLIB's COUT, this one
  987. ; will work under WordStar's "R" option.    b/m, June 3, 1987
  988. ;==========================================================
  989.  
  990. COUT:    JP    BOUT        ; PUBLIC label for EPRINT, etc.
  991.  
  992.  
  993. ;==========================================================
  994. ; Insure that all references to PRINT in syslib routines actually call
  995. ; EPRINT
  996. ;==========================================================
  997.  
  998. PRINT:    JP    EPRINT
  999.  
  1000.  
  1001. ;==========================================================
  1002. ; Parses token pointed to by HL into FCB pointed to
  1003. ; by DE.  If Z33 running, uses resident CPR code, otherwise
  1004. ; uses ZPRSFN.    This ensures full ZCPR33 compatibility.
  1005. ;==========================================================
  1006.  
  1007. PARSE:    CALL    Z33CHK
  1008.     JP    Z,Z33FNAME
  1009.     XOR    A        ; DIR first for ZPRSFN
  1010.     JP    ZPRSFN
  1011.  
  1012. ;==========================================================
  1013. ; Delivers a newline via SYSLIB's CRLF routine if:
  1014. ; 1. A ZCPR 3.3 or later CPR is present in memory
  1015. ; 2. LX isn't a "forced ECP" chained from ARUNZ or equiv.
  1016. ; 3. The ECP bit in the Command Status Flag is set
  1017. ;==========================================================
  1018.  
  1019. CRLFECP:
  1020.     CALL    Z33CHK        ; If we're under BGii, Z30, etc.
  1021.     RET    NZ        ; then don't mess with newlines
  1022.     LD    A,(FORCED)
  1023.     OR    A
  1024.     RET    Z        ; Likewise if we're a forced ECP
  1025.     CALL    GETCST
  1026.     BIT    2,A
  1027.     RET    Z        ; Or not an ECP of any kind (Z)
  1028.     JP    CRLF        ; OK -- NOW deliver the newline!
  1029.  
  1030. ;==========================================================
  1031. ; Data Area
  1032. ;==========================================================
  1033.  
  1034.     DSEG            ; To minimize COMfile size
  1035.  
  1036. ; ARGV argument table
  1037.  
  1038. ARGS:    DS    1        ; Will init. to allow up to 5
  1039. ARGC:    DS    1        ; Argument count
  1040. ARGV1:    DS    2        ; First argument
  1041. ARGV2:    DS    2        ; Second argument
  1042. ARGV3:    DS    2        ; Third argument
  1043. ARGV4:    DS    2*3        ; 3 more arguments
  1044.  
  1045. TAILST:    DS    2        ; Start of actual command tail
  1046.  
  1047. ;data structure for calls to LUOPEN
  1048. LUD:    DS    4        ; Dummy used by LU* routines
  1049. LUDBLR:    DS    2        ; Blocks remaining in member file
  1050.     DS    11        ; scratch area for LUOPEN, etc.
  1051. LUDFCB:    DS    36        ; Fcb containing library file data
  1052.  
  1053. ; General-purpose LX Buffers & Pointers.
  1054.  
  1055. TPAEND:    DS    2        ; Top of TPA
  1056. GBUFF:    DS    128        ; Command line save area
  1057. LFCB:    DS    36        ; Local FCB
  1058. LXTOP:    DS    2        ; First free address after lx
  1059. HIGHBUF: DS    2        ; Size of buffer above lx and below memtop
  1060. LOWBUF:    DS    2        ; Size of buffer below lx
  1061. HDRADR:    DS    2        ; Address of second and third records of t4
  1062. LOADAT:    DS    2        ; Load address for lbr member
  1063. LIBNAME: DS    2        ; Pointer to lbr name string
  1064. CPYFLG:    DS    1        ; NZ if loaded member needs copying
  1065. ERRCD:    DS    1        ; Error code storage
  1066. FORCED:    DS    1        ; Will be zero if forced ECP mode
  1067.  
  1068. ; For relocated CPYCOD routine
  1069.  
  1070. RUNAT:    DS    2        ; COMfile runtime origin
  1071. CPYCNT:    DS    2        ; COMfile length in bytes
  1072.  
  1073. OLDSTK:    DS    2        ; Save system stack pointer here
  1074.     DS    64        ; Room for 32-level stack
  1075. STACK    EQU    $
  1076.  
  1077.     END
  1078.