home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol122 / lrun8080.asm < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  23.1 KB  |  1,114 lines

  1. TITLE    'LRUNZ  Library Run for ZCPR2 -- a utility for .LBR files'
  2. VERSION EQU    1$0    ;82-08-06 Initial source release
  3.     PAGE    60
  4. ;
  5. ; Requires MAC for assembly.  Due to the complexity of
  6. ; the relocation macros, this program may take a while
  7. ; to assemble.    Be prepared for periods of no disk activity
  8. ; on both passes before pressing panic button.    G.P.N.
  9. ;
  10. ; Modified for 8080 operation with ZCPR8080.ASM
  11. ; Charles H. Strom, May 11, 1983.
  12.  
  13. ;--------------------------NOTICE------------------------------
  14. ;
  15. ;   (c) Copyright 1982    Gary P. Novosielski
  16. ;    All rights reserved.
  17. ;    
  18. ;   The following features courtesy of Ron Fowler:
  19. ;    1) command line reparsing and repacking (this allows
  20. ;    the former load-only program to become a load & run
  21. ;    utility).
  22. ;    2) code necessary to actually execute the loaded file
  23. ;    3) the HELP facility (LRUN with no arguments)
  24. ;    4) modified error routines to avoid warm-boot delay
  25. ;       (return to CCP directly instead)
  26. ;    
  27. ;    Permission to distribute this program in source or
  28. ;    object form without prior written aproval is granted
  29. ;    only under the following conditions.
  30. ;
  31. ;        1. No charge is imposed for the program.
  32. ;        2. Charges for incidental costs including
  33. ;           but not limited to media, postage, tele-
  34. ;           communications, and data storage do not
  35. ;           exceed those costs actually incurred.
  36. ;        3. This Notice and any copright notices in
  37. ;           the object code remain intact 
  38. ;
  39. ;            (signed)  Gary P. Novosielski
  40. ;
  41. ;--------------------------------------------------------------
  42. ;
  43. ; LRUN is intended to be used in conjunction with libraries
  44. ; created with LU.COM, a library utility based upon the
  45. ; groundwork laid by Michael Rubenstien, with some additional
  46. ; inspiration from Leor Zolman's CLIB librarian for .CRL files.
  47. ;
  48. ; The user can place the less frequently used command (.COM)
  49. ; files in a library to save space, and  still be able to run
  50. ; them when required, by typing:
  51. ;     LRUN <normal command line>.
  52. ; The name of the library can be specified, but the greatest
  53. ; utility will be achieved by placing all commands in one
  54. ; library called COMMAND.LBR, or some locally defined name,
  55. ; and always letting LRUN use that name as the default.
  56. ;
  57.  
  58. ;Syntax:
  59. ;    LRUN [-<lbrname>] <command> [<parameters>]
  60. ;
  61. ;where:
  62. ;<lbrname>    is the optional library name.  In the
  63. ;        distrubution version, this defaults to
  64. ;        COMMAND.LBR.  If the user wishes to use a
  65. ;        different name for the default, the 8-byte
  66. ;        literal at DFLTNAM below may be changed to
  67. ;        suit local requirements. The current drive
  68. ;        is searched for the .LBR file, and if not
  69. ;        found there, the A: drive is searched.
  70. ;        **Note that the leading minus sign (not a part
  71. ;        of the name) is required to indicate an
  72. ;        override library name is being entered.
  73. ;
  74. ;<command>    is the name of the .COM file in the library
  75. ;
  76. ;<line>        is the (possibly empty) set of parameters
  77. ;        which are to be passed to <command>, as in
  78. ;        normal CP/M syntax.  Notice that if the
  79. ;        library name is defaulted, the syntax is
  80. ;        simply:
  81. ;     LRUN <command line>
  82. ;        which is just the normal command line with
  83. ;        LRUN prefixed to it.
  84. ;
  85. ;
  86. @SYS    SET    0
  87. @KEY    SET    1
  88. @CON    SET    2
  89. @RDR    SET    3
  90. @PUN    SET    4
  91. @LST    SET    5
  92. @DIO    SET    6
  93. @RIO    SET    7
  94. @SIO    SET    8
  95. @MSG    SET    9
  96. @INP    SET    10
  97. @RDY    SET    11
  98. @VER    SET    12
  99. @LOG    SET    13
  100. @DSK    SET    14
  101. @OPN    SET    15
  102. @CLS    SET    16
  103. @DIR    SET    17
  104. @NXT    SET    18
  105. @DEL    SET    19
  106. @FRD    SET    20
  107. @FWR    SET    21
  108. @MAK    SET    22
  109. @REN    SET    23
  110. @CUR    SET    25
  111. @DMA    SET    26
  112. @CHG    SET    30
  113. @USR    SET    32
  114. @RRD    SET    33
  115. @RWR    SET    34
  116. @SIZ    SET    35
  117. @REC    SET    36
  118. @LOGV    SET    37    ;2.2 only
  119. @RWR0    SET    40    ;2.2 only
  120. ;
  121. CPMBASE EQU    0
  122. BOOT    SET    CPMBASE
  123. BDOS    SET    BOOT+5
  124. TFCB    EQU    BOOT+5CH
  125. TFCB1    EQU    TFCB
  126. TFCB2    EQU    TFCB+16
  127. TBUFF    EQU    BOOT+80H
  128. TPA    EQU    BOOT+100H
  129. CTRL    EQU    ' '-1        ;Ctrl char mask
  130. CR    SET    CTRL AND 'M'
  131. LF    SET    CTRL AND 'J'
  132. TAB    SET    CTRL AND 'I'
  133. FF    SET    CTRL AND 'L'
  134. BS    SET    CTRL AND 'H'
  135. FALSE    SET    0
  136. TRUE    SET    NOT FALSE
  137. ;
  138. CPM    MACRO    FUNC,OPERAND,CONDTN
  139.     LOCAL    PAST
  140.     IF    NOT NUL CONDTN
  141.     DB    ( J&CONDTN ) XOR 8
  142.     DW    PAST
  143.     ENDIF        ;;of not nul condtn
  144.     IF    NOT NUL OPERAND
  145.     LXI    D,OPERAND
  146.     ENDIF        ;;of not nul operand
  147.     IF    NOT NUL FUNC
  148.     MVI    C,@&FUNC
  149.     ENDIF
  150.     CALL    BDOS
  151. PAST:
  152.     ENDM
  153. ;
  154. BLKMOV    MACRO    DEST,SRCE,LEN,COND
  155.     LOCAL    PAST
  156.     JMP    PAST
  157. @BMVSBR:
  158.     MOV    A,B
  159.     ORA    C
  160.     RZ
  161.     DCX    B
  162.     MOV    A,M
  163.     INX    H
  164.     STAX    D
  165.     INX    D
  166.     JMP    @BMVSBR
  167. BLKMOV    MACRO    DST,SRC,LN,CC
  168.     LOCAL    PST
  169.     IF    NOT NUL CC
  170.     DB    ( J&CC ) XOR 8
  171.     DW    PST
  172.     ENDIF
  173.     IF    NOT NUL DST
  174.     LXI    D,DST
  175.     ENDIF
  176.     IF    NOT NUL SRC
  177.     LXI    H,SRC
  178.     ENDIF
  179.     IF    NOT NUL LN
  180.     LXI    B,LN
  181.     ENDIF
  182.     CALL    @BMVSBR
  183.     IF    NOT NUL CC
  184. PST:
  185.     ENDIF
  186.     ENDM
  187. PAST:    BLKMOV    DEST,SRCE,LEN,COND
  188.     ENDM
  189.  
  190. ;
  191. OVERLAY SET    0
  192. ; Macro Definitions
  193. ;
  194. RTAG    MACRO    LBL
  195. ??R&LBL EQU    $+2-@BASE
  196.     ENDM
  197. ;
  198. RGRND    MACRO    LBL
  199. ??R&LBL EQU    0FFFFH
  200.     ENDM
  201. ;
  202. R    MACRO    INST
  203. @RLBL    SET    @RLBL+1
  204.     RTAG    %@RLBL
  205.     INST-@BASE
  206.     ENDM
  207. ;
  208. NXTRLD    MACRO    NN
  209. @RLD    SET    ??R&NN
  210. @NXTRLD SET    @NXTRLD + 1
  211.     ENDM
  212. ;
  213. ;
  214. ; Enter here from Console Command Processor (CCP)
  215. ;
  216.     ORG    TPA
  217. CCPIN:
  218. ;
  219. ;  Branch to Start of Program
  220. ;
  221.     jmp    start
  222.  
  223. ;
  224. ;******************************************************************
  225. ;
  226. ;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
  227. ;
  228. ;    This data block precisely defines the data format for
  229. ; initial features of a ZCPR2 system which are required for proper
  230. ; initialization of the ZCPR2-Specific Routines in SYSLIB.
  231. ;
  232.  
  233. ;
  234. ;  EXTERNAL PATH DATA
  235. ;
  236. EPAVAIL:
  237.     DB    0FFH    ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
  238. EPADR:
  239.     DW    40H    ; ADDRESS OF EXTERNAL PATH IF AVAILABLE
  240.  
  241. ;
  242. ;  INTERNAL PATH DATA
  243. ;
  244. INTPATH:
  245.     DB    0,0    ; DISK, USER FOR FIRST PATH ELEMENT
  246.             ; DISK = 1 FOR A, '$' FOR CURRENT
  247.             ; USER = NUMBER, '$' FOR CURRENT
  248.     DB    0,0
  249.     DB    0,0
  250.     DB    0,0
  251.     DB    0,0
  252.     DB    0,0
  253.     DB    0,0
  254.     DB    0,0    ; DISK, USER FOR 8TH PATH ELEMENT
  255.     DB    0    ; END OF PATH
  256.  
  257. ;
  258. ;  MULTIPLE COMMAND LINE BUFFER DATA
  259. ;
  260. MCAVAIL:
  261.     DB    0FFH    ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
  262. MCADR:
  263.     DW    0FF00H    ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE
  264.  
  265. ;
  266. ;  DISK/USER LIMITS
  267. ;
  268. MDISK:
  269.     DB    4    ; MAXIMUM NUMBER OF DISKS
  270. MUSER:
  271.     DB    31    ; MAXIMUM USER NUMBER
  272.  
  273. ;
  274. ;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
  275. ;
  276. DOK:
  277.     DB    0FFH    ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
  278. UOK:
  279.     DB    0FFH    ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)
  280.  
  281. ;
  282. ;  PRIVILEGED USER DATA
  283. ;
  284. PUSER:
  285.     DB    10    ; BEGINNING OF PRIVILEGED USER AREAS
  286. PPASS:
  287.     DB    'chdir',0    ; PASSWORD FOR MOVING INTO PRIV USER AREAS
  288.     DS    41-($-PPASS)    ; 40 CHARS MAX IN BUFFER + 1 for ending NULL
  289.  
  290. ;
  291. ;  CURRENT USER/DISK INDICATOR
  292. ;
  293. CINDIC:
  294.     DB    '$'    ; USUAL VALUE (FOR PATH EXPRESSIONS)
  295.  
  296. ;
  297. ;  DMA ADDRESS FOR DISK TRANSFERS
  298. ;
  299. DMADR:
  300.     DW    80H    ; TBUFF AREA
  301.  
  302. ;
  303. ;  NAMED DIRECTORY INFORMATION
  304. ;
  305. NDRADR:
  306.     DW    00000H    ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
  307. NDNAMES:
  308.     DB    64    ; MAX NUMBER OF DIRECTORY NAMES
  309. DNFILE:
  310.     DB    'NAMES   '    ; NAME OF DISK NAME FILE
  311.     DB    'DIR'        ; TYPE OF DISK NAME FILE
  312.  
  313. ;
  314. ;  REQUIREMENTS FLAGS
  315. ;
  316. EPREQD:
  317.     DB    0FFH    ; EXTERNAL PATH?
  318. MCREQD:
  319.     DB    000H    ; MULTIPLE COMMAND LINE?
  320. MXREQD:
  321.     DB    000H    ; MAX USER/DISK?
  322. UDREQD:
  323.     DB    000H    ; ALLOW USER/DISK CHANGE?
  324. PUREQD:
  325.     DB    000H    ; PRIVILEGED USER?
  326. CDREQD:
  327.     DB    0FFH    ; CURRENT INDIC AND DMA?
  328. NDREQD:
  329.     DB    000H    ; NAMED DIRECTORIES?
  330. Z2CLASS:
  331.     DB    5    ; CLASS 5
  332.     DB    'ZCPR2'
  333.     DS    10    ; RESERVED
  334.  
  335. ;
  336. ;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
  337. ;
  338. ;******************************************************************
  339. ;
  340. DFLTNAM:
  341.     DB    'COMMAND ' ; <---change this if you like---
  342. LBRLIT:
  343.     DB    'LBR'
  344. ;
  345. SIGNON:
  346.     DB    'LRUNZ  8080 Version '    ;Signon message
  347.     DB    VERSION/10+'0'
  348.     DB    '.'
  349.     DB    VERSION MOD 10+'0'
  350.     DB    CR,LF
  351.     DB    '$',CTRL AND 'Z'
  352.     DB    ' Copyright (c) 1982  Gary P. Novosielski '
  353.     DB    CR,LF
  354.     DB    ' Modified for Use Under ZCPR2 by Richard Conn'
  355.     DB    '$',CTRL AND 'Z'
  356. ;
  357. ;  START OF PROGRAM
  358. ;
  359. START:
  360.     LXI    H,0        ;get the CCP entry stackpointer
  361.     DAD    SP        ;(used only if HELP request
  362.     SHLD    SPSAVE        ; is encountered)
  363.     CPM    MSG,SIGNON;    ;Display signon
  364.     CALL    SETUP        ;initialize.
  365.     LHLD    BDOS+1        ;find top of memory
  366.     MOV    A,H        ;page address
  367.                 ;Form destination...
  368.     SUI    PAGES         ;...address in
  369.     MOV    D,A        ;DE pair.
  370.     MVI    E,0
  371.     PUSH    D        ;save on stack
  372. ;
  373.     BLKMOV    ,@BASE,SEGLEN    ;Move the active segment.
  374. ;
  375. ;The segment is now moved to high memory, but not
  376. ;properly relocated.  The bit table which specifies
  377. ;which addresses need to be adjusted is located
  378. ;just after the last byte of the source segment,
  379. ;so (HL) is now pointing at it.
  380.     POP    D    ;beginning of newly moved code.
  381.     LXI    B,SEGLEN;length of segment
  382.     PUSH    H    ;save pointer to reloc info
  383.     MOV    H,D    ;offset page address
  384. ;
  385. ;Scan through the newly moved code, and adjust any
  386. ;page addresses by adding (H) to them.    The word on
  387. ;top of the stack points to the next byte of the
  388. ;relocation bit table.    Each bit in the table
  389. ;corresponds to one byte in the destination code.
  390. ;A value of 1 indicates the byte is to be adjusted.
  391. ;A value of 0 indicates the byte is to be unchanged.
  392. ;
  393. ;Thus one byte of relocation information serves to
  394. ;mark 8 bytes of object code.  The bits which have
  395. ;not been used yet are saved in L until all 8
  396. ;are used.
  397. ;
  398. FIXLOOP:
  399.     MOV    A,B
  400.     ORA    C        ;test if finished
  401.     JZ    FIXDONE
  402.     DCX    B        ;count down
  403.     MOV    A,E
  404.     ANI    07H        ;on 8-byte boundry?
  405.     JNZ    NEXTBIT
  406. ;
  407. NEXTBYT:
  408. ;Get another byte of relocation bits
  409.     XTHL
  410.     MOV    A,M
  411.     INX    H
  412.     XTHL
  413.     MOV    L,A        ;save in register L
  414. ;
  415. NEXTBIT:
  416.     MOV    A,L        ;remaining bits from L
  417.     RAL            ;next bit to CARRY
  418.     MOV    L,A        ;save the rest
  419.     JNC    NEXTADR
  420. ;
  421. ;CARRY was = 1.  Fix this byte.
  422.     LDAX    D
  423.     ADD    H        ;(H) is the page offset
  424.     STAX    D
  425. ;
  426. NEXTADR:
  427.     INX    D
  428.     JMP    FIXLOOP
  429. ;
  430. ;Finished.  Jump to the first address in the new
  431. ;segment in high memory.
  432. ;
  433. ;First adjust the stack.  One garbage word was
  434. ;left by fixloop.
  435. ;
  436. FIXDONE:
  437.     INX    SP
  438.     INX    SP
  439. ;
  440. ;(HL) still has the page address
  441. ;
  442.     MOV    L,A    ;move zero to l
  443. ;
  444. ;  Set User/Disk for Return
  445. ;
  446.     LDA    CDISK    ;Set Disk
  447.     MOV    B,A
  448.     LDA    CUSER    ;Set User
  449.     MOV    C,A
  450.     PCHL        ;Stack is valid
  451. ;
  452. ;Any one-shot initialization code goes here.
  453. ;
  454. SETUP:
  455.     LXI    H,NOLOAD
  456.     SHLD    CCPIN+1     ;Prevent reentry
  457. ;
  458.     CALL    REPARS        ;Re-parse command line
  459. ;
  460.     LXI    D,MEMBER+9    ;Check member filetype
  461.     LDAX    D
  462.     CPI    ' '        ;If blank,
  463.     BLKMOV    ,COMLIT,3,Z    ; default to COM.
  464. ;
  465.     LXI    D,LBRFIL+9    ;Check library filetype
  466.     LDAX    D
  467.     CPI    ' '        ;If blank,
  468.     BLKMOV    ,LBRLIT,3,Z    ; default to LBR
  469. ;
  470.     LXI    D,LBRFIL+1    ;Check name
  471.     LDAX    D
  472.     CPI    ' '        ;If blank,
  473.     BLKMOV    ,DFLTNAM,8,Z    ; use default name.
  474. ;
  475. ;  Set Current Disk and User and then Search Along ZCPR2 Path for
  476. ;    the Library File
  477. ;
  478.     CPM    CUR        ;Get Current Disk
  479.     STA    CDISK        ;Save It
  480.     CPM    USR,0FFH    ;Get Current User
  481.     STA    CUSER        ;Save It
  482.     CPM    OPN,LBRFIL    ;Try to Open Library File Now
  483.     INR    A        ;Zero Means Not Found
  484.     JNZ    DIROK        ;Process if Found
  485.     XRA    A        ;Set to Select Current Disk
  486.     STA    LBRFIL
  487.     LXI    H,INTPATH    ;Point to Internal Path
  488.     LDA    EPAVAIL        ;External Path Available?
  489.     ORA    A        ;Zero = No
  490.     JZ    INPATH
  491.     LHLD    EPADR        ;Get Address of External Path
  492. INPATH:
  493.     MOV    A,M        ;Get Drive
  494.     ORA    A        ;0=Command Not Found
  495.     JZ    NODIR        ;Not Found
  496.     ANI    7FH        ;Mask MSB
  497.     MOV    B,A        ;Save in B for a While
  498.     LDA    CINDIC        ;Get Current Indicator
  499.     CMP    B        ;Compare for Current
  500.     JNZ    INPATH1        ;Good Disk In B
  501.     LDA    CDISK        ;Get Current Disk
  502.     INR    A        ;Add 1 to be good
  503.     MOV    B,A        ;Disk In B
  504. INPATH1:
  505.     DCR    B        ;Disk in Range 0-15
  506.     INX    H        ;Pt to User Number
  507.     MOV    A,M        ;Get User Number
  508.     INX    H        ;Pt to Next Disk
  509.     PUSH    H        ;Save Ptr
  510.     ANI    7FH        ;Mask User Number
  511.     MOV    C,A        ;User in C for now
  512.     LDA    CINDIC        ;Compare to Current Indicator
  513.     CMP    C        ;See if Current User
  514.     JNZ    INPATH2        ;Good User In C
  515.     LDA    CUSER        ;User Current User
  516.     MOV    C,A        ;User in C
  517. INPATH2:
  518.     MOV    E,B        ;Select Disk
  519.     PUSH    B        ;Save User in C
  520.     CPM    DSK        ;Set Disk
  521.     POP    D        ;Get User in E
  522.     CPM    USR        ;Set User
  523.     CPM    DIR,LBRFIL    ;See if File Exists in this Directory
  524.     POP    H        ;Restore Path Pointer
  525.     INR    A        ;Error Code (Not Found) is Zero
  526.     JZ    INPATH        ;Continue Thru Path
  527. DIROPN:
  528.     CPM    OPN,LBRFIL    ;Open for directory read.
  529. DIROK:
  530.     CPM    DMA,TBUFF    ;Set DMA for Block Read
  531. FINDMBR:
  532.     CPM    FRD,LBRFIL    ;Read the directory
  533.     ORA    A
  534.     JNZ    FISHY        ;Empty file, Give up.
  535.     LXI    H,TBUFF
  536.     MOV    A,M
  537.     ORA    A
  538.     JNZ    FISHY        ;Directory not active??
  539.     MVI    B,8+3        ;Check for blanks
  540.     MVI    A,' '
  541. VALIDLOOP:
  542.     INX    H
  543.     CMP    M
  544.     JNZ    FISHY
  545.     DCR    B
  546.     JNZ    VALIDLOOP
  547. ;
  548.     LHLD    TBUFF+1+8+3    ;Index must be 0000
  549.     MOV    A,H
  550.     ORA    L
  551.     JNZ    FISHY
  552. ;
  553.     LHLD    TBUFF+1+8+3+2    ;Get directory size
  554.     DCX    H        ;We already read one.
  555.     PUSH    H        ;Save on stack
  556.     JMP    FINDMBRN    ;Jump into loop
  557. FINDMBRL:
  558.     POP    H        ;Read sector count from TOS
  559.     MOV    A,H
  560.     ORA    L        ;0 ?
  561.     JZ    NOMEMB        ;Member not found in library
  562.     DCX    H        ;Count down
  563.     PUSH    H        ;and put it back.
  564.     CPM    FRD,LBRFIL    ;Get next directory sector
  565.     ORA    A
  566.     JNZ    FISHY
  567.  
  568.  
  569. FINDMBRN:
  570.     LXI    H,TBUFF       ;Point to buffer.
  571.     MVI    C,128/32    ;Number of directory entries
  572. ;
  573. FINDMBR1:
  574.     CALL    COMPARE     ;Check if found yet.
  575.     JZ    GETLOC        ;Found member in .DIR
  576.     DCR    C
  577.     JZ    FINDMBRL
  578. ;
  579.     LXI    D,32        ;No match, point to next one.
  580.     DAD    D
  581.     JMP    FINDMBR1
  582. ;
  583. GETLOC:     ;The name was found now get index and length
  584.     POP    B    ;Clear stack garbage
  585.     XCHG        ;Pointer to sector address.
  586.     MOV    E,M    ;Get First
  587.     INX    H
  588.     MOV    D,M
  589.     XCHG
  590.     SHLD    INDEX    ;Save it
  591.     XCHG
  592.     INX    H    ;Get Size to DE
  593.     MOV    E,M
  594.     INX    H
  595.     MOV    D,M
  596.     XCHG        ; Size to HL
  597.     SHLD    LENX
  598.     CALL    PACKUP    ;Repack command line arguments
  599.     CPM    CON,CR    ;do <cr> only (look like CCP)
  600.     RET
  601. ;        End of setup.
  602. ;
  603. ;    Utility subroutines
  604. NEGDE:            ;DE = -DE
  605.     MOV    A,D
  606.     CMA
  607.     MOV    D,A
  608. ;
  609.     MOV    A,E
  610.     CMA
  611.     MOV    E,A
  612.     INX    D
  613.     RET
  614. ;
  615. ;    REPARSE re-parses the fcbs from the command line,
  616. ;    to allow the "-" character to prefix the library name
  617. ;
  618. REPARS:
  619.     LXI    D,MEMBER    ;first reinitialize both fcbs
  620.     CALL    NITF
  621.     LXI    D,LBRFIL
  622.     CALL    NITF
  623.     LXI    H,TBUFF     ;store a null at the end of
  624.     MOV    E,M        ; the command line (this is
  625.     MVI    D,0        ; done by CP/M usually, except
  626.     XCHG            ; in the case of a full com-
  627.     DAD    D        ; mand line
  628.     INX    H
  629.     MVI    M,0
  630.     XCHG            ;tbuff pointer back in hl
  631. SCANBK:
  632.     INX    H        ;bump to next char position
  633.     MOV    A,M        ;fetch next char
  634.     ORA    A        ;reached a null? (no arguments)
  635.     JZ    HELP        ;interpret as a call for help
  636.     CPI    ' '        ;not null, skip blanks
  637.     JZ    SCANBK
  638.     CPI    '-'        ;library name specifier?
  639.     JNZ    NOTLBR        ;skip if not
  640.     INX    H        ;it is, skip over flag character
  641.     LXI    D,LBRFIL    ;parse library name into FCB
  642.     CALL    GETFN
  643. NOTLBR:
  644.     LXI    D,MEMBER    ;now parse the command name
  645.     CALL    GETFN
  646.     LXI    D,HOLD+1    ;pnt to temp storage for rest of cmd line
  647.     MVI    B,-1        ;init a counter
  648. CLSAVE:
  649.     INR    B        ;bump up counter
  650.     MOV    A,M        ;fetch a char
  651.     STAX    D        ;move it to hold area
  652.     INX    H        ;bump pointers
  653.     INX    D
  654.     ORA    A        ;test whether char was a terminator
  655.     JNZ    CLSAVE        ;continue moving line if not
  656.     MOV    A,B        ;it was, get count
  657.     STA    HOLD        ;save it in hold area
  658.     RET
  659. ;
  660. ;    PACKUP retrieves the command line stored at
  661. ;    HOLD and moves it back to tbuff, then reparses
  662. ;    the default file control blocks so the command
  663. ;    will never know it was run from a library
  664. ;
  665. PACKUP:
  666.     LXI    H,HOLD        ;point to length byte of HOLD
  667.     MOV    C,M        ;get length in BC
  668.     MVI    B,0
  669.     INX    B        ;bump up to because length byte doesn't
  670.     INX    B        ;  include itself or null terminator
  671.     BLKMOV    TBUFF        ;moving everybody to Tbuff
  672.     LXI    H,TBUFF+1    ;point to the command tail
  673.     LXI    D,TFCB1     ;first parse out tfcb1
  674.     CALL    GETFN
  675.     LXI    D,TFCB2     ;then tfcb2
  676.     CALL    GETFN
  677.     RET
  678. ;
  679. ;    Here when HELP is requested (indicated
  680. ;    by LRUN with no arguments)
  681. ;
  682. HELP:
  683.     CPM    MSG,HLPMSG    ;print the HELP message
  684. EXIT:
  685.     LHLD    SPSAVE        ;find CCP re-entry adrs
  686.     SPHL            ;fix & return
  687.     RET
  688. ;
  689. ;    the HELP message
  690. ;
  691. HLPMSG:
  692.     DB    CR,LF,'Correct syntax is:'
  693.     DB    CR,LF
  694.     DB    LF,TAB,'LRUN [-<lbrname>] <command line>'
  695.     DB    CR,LF
  696.     DB    LF,'Where <lbrname> is the optional library name'
  697.     DB    CR,LF,'(Note the preceding "-".  ) If omitted,'
  698.     DB    CR,LF,'the default command library is used.'
  699.     DB    LF
  700.     DB    CR,LF,'<command line> is the name and parameters'
  701.     DB    CR,LF,'of the command being run from the library,'
  702.     DB    CR,LF,'just as if a separate .COM file were being run.'
  703.     DB    CR,LF,'$'
  704. ;
  705. ;
  706. COMPARE:        ;Test status, name and type of
  707.     PUSH    H        ;a directory entry.
  708.     MVI    B,1+8+3
  709.     XCHG            ;with the one we're
  710.     LXI    H,MEMBER    ;looking for.
  711. COMPAR1:
  712.     LDAX    D
  713.     CMP    M
  714.     JNZ    COMPEXIT
  715.     INX    D
  716.     INX    H
  717.     DCR    B
  718.     JNZ    COMPAR1
  719. COMPEXIT:            ;Return with DE pointing to
  720.     POP    H        ;last match + 1, and HL still
  721.     RET            ;pointing to beginning.
  722. ;
  723. ;
  724. ;    File name parsing subroutines
  725. ;
  726. ; getfn gets a file name from text pointed to by reg hl into
  727. ; an fcb pointed to by reg de.    leading delimeters are 
  728. ; ignored.
  729. ; entry hl    first character to be scanned
  730. ;    de    first byte of fcb
  731. ; exit    hl    character following file name
  732. ;
  733. ;
  734. ;
  735. GETFN:
  736.     CALL    NITF    ;init 1st half of fcb
  737.     CALL    GSTART    ;scan to first character of name
  738.     RZ        ;end of line was found - leave fcb blank
  739.     CALL    GETDRV    ;get drive spec. if present
  740.     CALL    GETPS    ;get primary and secondary name
  741.     RET
  742.  
  743.  
  744. ;
  745. ; nitf fills the fcb with dflt info - 0 in drive field
  746. ; all-blank in name field, and 0 in ex,s1,s2 and rc flds
  747. ;
  748. NITF:
  749.     PUSH    D    ;save fcb loc
  750.     XCHG        ;move it to hl
  751.     MVI    M,0    ;zap dr field
  752.     INX    H    ;bump to name field
  753.     MVI    B,11    ;zap all of name fld
  754. NITLP1:
  755.     MVI    M,' '
  756.     INX    H
  757.     DCR    B
  758.     JNZ    NITLP1
  759.     MVI    B,4    ;zero others
  760. NITLP2:
  761.     MVI    M,0
  762.     INX    H
  763.     DCR    B
  764.     JNZ    NITLP2
  765.     XCHG        ;restore hl
  766.     POP    D    ;restore fcb pointer
  767.     RET
  768. ;
  769. ; gstart advances the text pointer (reg hl) to the first
  770. ; non delimiter character (i.e. ignores blanks).  returns a
  771. ; flag if end of line (00h or ';') is found while scaning.
  772. ; exit    hl    pointing to first non delimiter
  773. ;    a    clobbered
  774. ;    zero    set if end of line was found
  775. ;
  776. GSTART:
  777.     CALL    GETCH    ;see if pointing to delim?
  778.     RNZ        ;nope - return
  779.     CPI    ';'    ;end of line?
  780.     RZ        ;yup - return w/flag
  781.     ORA    A
  782.     RZ        ;yup - return w/flag
  783.     INX    H    ;nope - move over it
  784.     JMP    GSTART    ;and try next char
  785. ;
  786. ; getdrv checks for the presence of a drive spec at the text
  787. ; pointer, and if present formats it into the fcb and
  788. ; advances the text pointer over it.
  789. ; entry hl    text pointer
  790. ;    de    pointer to first byte of fcb
  791. ; exit    hl    possibly updated text pointer
  792. ;    de    pointer to second (primary name) byte of fcb
  793. ;
  794. GETDRV:
  795.     INX    D    ;point to name if spec not found
  796.     INX    H    ;look ahead to see if ':' present
  797.     MOV    A,M
  798.     DCX    H    ;put back in case not present
  799.     CPI    ':'    ;is a drive spec present?
  800.     RNZ        ;nope - return
  801.     MOV    A,M    ;yup - get the ascii drive name
  802.     SUI    'A'-1    ;convert to fcb drive spec
  803.     DCX    D    ;point back to drive spec byte
  804.     STAX    D    ;store spec into fcb
  805.     INX    D    ;point back to name
  806.     INX    H    ;skip over drive name
  807.     INX    H    ;and over ':'
  808.     RET
  809. ;
  810. ; getps gets the primary and secondary names into the fcb.
  811. ; entry hl    text pointer
  812. ; exit    hl    character following secondary name (if present)
  813. ;
  814. GETPS:
  815.     MVI    C,8    ;max length of primary name
  816.     CALL    GETNAM    ;pack primary name into fcb
  817.     MOV    A,M    ;see if terminated by a period
  818.     CPI    '.'
  819.     RNZ        ;nope - secondary name not given
  820.             ;return default (blanks)
  821.     INX    H    ;yup - move text pointer over period
  822. FTPOINT:
  823.     MOV    A,C    ;yup - update fcb pointer to secondary
  824.     ORA    A
  825.     JZ    GETFT
  826.     INX    D
  827.     DCR    C
  828.     JMP    FTPOINT
  829. GETFT:
  830.     MVI    C,3    ;max length of secondary name
  831.     CALL    GETNAM    ;pack secondary name into fcb
  832.     RET
  833. ;
  834. ; getnam copies a name from the text pointer into the fcb for
  835. ; a given maximum length or until a delimiter is found, which
  836. ; ever occurs first.  if more than the maximum number of
  837. ; characters is present, characters are ignored until a
  838. ; a delimiter is found.
  839. ; entry hl    first character of name to be scaned
  840. ;    de    pointer into fcb name field
  841. ;    c    maximum length
  842. ; exit    hl    pointing to terminating delimiter
  843. ;    de    next empty byte in fcb name field
  844. ;    c    max length - number of characters transfered
  845. ;
  846. GETNAM:
  847.     CALL    GETCH    ;are we pointing to a delimiter yet?
  848.     RZ        ;if so, name is transfered
  849.     INX    H    ;if not, move over character
  850.     CPI    '*'    ;ambigious file reference?
  851.     JZ    AMBIG    ;if so, fill the rest of field with '?'
  852.     STAX    D    ;if not, just copy into name field
  853.     INX    D    ;increment name field pointer
  854.     DCR    C    ;if name field full?
  855.     JNZ    GETNAM    ;nope - keep filling
  856.     JMP    GETDEL    ;yup - ignore until delimiter
  857. AMBIG:
  858.     MVI    A,'?'    ;fill character for wild card match
  859. QFILL:
  860.     STAX    D    ;fill until field is full
  861.     INX    D
  862.     DCR    C
  863.     JNZ    QFILL    ;fall thru to ingore rest of name
  864. GETDEL:
  865.     CALL    GETCH    ;pointing to a delimiter?
  866.     RZ        ;yup - all done
  867.     INX    H    ;nope - ignore antoher one
  868.     JMP    GETDEL
  869. ;
  870. ; getch gets the character pointed to by the text pointer
  871. ; and sets the zero flag if it is a delimiter.
  872. ; entry hl    text pointer
  873. ; exit    hl    preserved
  874. ;    a    character at text pointer
  875. ;    z    set if a delimiter
  876. ;
  877. GETCH:
  878.     MOV    A,M    ;get the character
  879.     CPI    '.'
  880.     RZ
  881.     CPI    ','
  882.     RZ      
  883.     CPI    ';'
  884.     RZ
  885.     CPI    ' '
  886.     RZ
  887.     CPI    ':'
  888.     RZ
  889.     CPI    '='
  890.     RZ
  891.     CPI    '<'
  892.     RZ
  893.     CPI    '>'
  894.     RZ
  895.     ORA    A    ;Set zero flag on end of text
  896.     RET
  897. ;
  898. ;
  899. ; Error routines:
  900. ;
  901. NODIR:
  902.     CALL    ABEND
  903.     DB    'Library not found'
  904.     DB    '$'
  905. FISHY:
  906.     CALL    ABEND
  907.     DB    'Name after "-" isn''t a library'
  908.     DB    '$'
  909. NOMEMB:
  910.     LXI    H,MEMBER+1    ;Pt to first char of Command Name
  911.     MVI    B,8        ;Print 8 Chars
  912. NOMEMBL:
  913.     MOV    E,M        ;Print Char
  914.     INX    H        ;Pt to Next
  915.     PUSH    H        ;Save Ptr and Count
  916.     PUSH    B
  917.     CPM    CON
  918.     POP    B
  919.     POP    H
  920.     DCR    B
  921.     JNZ    NOMEMBL
  922.     CALL    ABEND1        ;No Initial New Line
  923.     DB    ' -- Command not in directory'
  924.     DB    '$'
  925. NOLOAD:
  926.     CALL    ABEND
  927.     DB    'No program in memory'
  928.     DB    '$'
  929. NOFIT:
  930.     POP    B    ;Clear Stack
  931.     CALL    ABEND
  932.     DB    'Program too large to load'
  933.     DB    '$'
  934. ;
  935. COMLIT:
  936.     DB    'COM'
  937. ;
  938. ABEND:
  939.     CPM    MSG,NEWLIN
  940. ABEND1:
  941.     POP    D
  942.     CPM    MSG
  943.     CPM    DEL,SUBFILE
  944.     CPM    MSG,ABTMSG
  945.     JMP    EXIT
  946. ABTMSG:
  947.     DB    ' -- Aborting$'
  948. NEWLIN:
  949.     DB    CR,LF,'$'
  950. CDISK:
  951.     DS    1    ;CURRENT DISK BUFFER
  952. CUSER:
  953.     DS    1    ;CURRENT USER BUFFER
  954. SPSAVE:
  955.     DS    2        ;stack pointer save
  956. ;
  957.     PAGE
  958. ;Adjust location counter to next 256-byte boundry
  959. @BASE    ORG    ($ + 0FFH) AND 0FF00H
  960. @RLBL    SET    0
  961. ;
  962. ; The segment to be relocated goes here.
  963. ; Any position dependent (3-byte) instructions
  964. ; are handled by the "R" macro.
  965. ;*************************************************
  966. ;
  967.     PUSH    B    ;Save Original User/Disk
  968.  R    <LHLD    LENX>    ;Get length of .COM member to load.
  969.     MVI    A,TPA/128
  970.     ADD    L    ;Calculate highest address
  971.     MOV    L,A    ;To see if it will fit in
  972.     ADC    H    ;available memory
  973.     SUB    L
  974.     MOV    H,A
  975.     REPT    7
  976.     DAD    H
  977.     ENDM
  978.     XCHG    
  979.     CALL    NEGDE    ;IT'S STILL IN LOW MEMORY
  980.  R    <LXI    H,PROTECT>
  981.     DAD    D
  982.     JNC    NOFIT    ;Haven't overwritten it yet.
  983. ;
  984. ; The library file is still open.  The open FCB has been
  985. ; moved up here into high memory with the loader code.
  986. ;
  987. LBROPN:
  988.  R    <LHLD    INDEX>        ;Set up for random reads
  989.  R    <SHLD    RANDOM>
  990.     XRA    A
  991.  R    <STA    RANDOM+2>
  992. ;
  993.     LXI    H,TPA
  994.  R    <SHLD    LOADDR>
  995.  
  996. ;
  997. ; This high memory address and above, including CCP, must be
  998. ; protected from being overlaid by loaded program
  999. ;
  1000. PROTECT:
  1001. ;
  1002. LOADLOOP:            ;Load that sucker.
  1003.  R    <LHLD    LENX>        ;See if done yet.
  1004.     MOV    A,L
  1005.     ORA    H
  1006.  R    <JZ    LOADED>
  1007.     DCX    H
  1008.  R    <SHLD    LENX>
  1009. ;
  1010.  R    <LHLD    LOADDR>     ;Increment for next time
  1011.     MOV    D,H
  1012.     MOV    E,L
  1013.     LXI    B,80H
  1014.     DAD    B
  1015.  R    <SHLD    LOADDR>
  1016.     CPM    DMA        ;but use old value (DE)
  1017. ;
  1018.  R    <LXI    D,LBRFIL>
  1019.     CPM    RRD        ;Read the sector
  1020.     ORA    A        ;Ok?
  1021.  R    <JNZ    ERR>        ;No, bail out.
  1022. ;
  1023.  R    <LHLD    RANDOM>     ;Increment random record field
  1024.     INX    H
  1025.  R    <SHLD    RANDOM>
  1026. ;
  1027.  R    <JMP    LOADLOOP>    ;Until done.
  1028. ;
  1029. ERR:
  1030.     MVI    A,( JMP )    ;Prevent execution of bad code
  1031.     STA    TPA
  1032.     LXI    H,BOOT
  1033.     SHLD    TPA+1
  1034. ;
  1035.  R    <LXI    D,LDMSG>
  1036.     CPM    MSG
  1037.  R    <LXI    D,SUBFILE>    ;Abort SUBMIT if in progress
  1038.     CPM    DEL
  1039. LOADED:
  1040.     CPM    DMA,TBUFF    ;Restore DMA adrs for user pgm
  1041.     CPM    CON,LF        ;Turn up a new line on console
  1042.     POP    B        ;Restore Current User/Disk
  1043.     PUSH    B        ;Save it again
  1044.     MOV    E,B        ;Restore Disk
  1045.     CPM    DSK        ;Log In Disk
  1046.     POP    D        ;E=USER
  1047.     CPM    USR        ;Log In User
  1048.     JMP    TPA
  1049. ;
  1050. LDMSG:
  1051.     DB    CR,LF,'Bad Load$'
  1052. INDEX:
  1053.     DW    0
  1054. LENX:
  1055.     DW    0
  1056. SUBFILE:
  1057.     DB    1,'$$$     SUB',0,0,0,0
  1058.     ;If used, this FCB will clobber the following one.
  1059.     ;but it's only used on a fatal error, anyway.
  1060. LBRFIL:
  1061.     DS    32        ;Name placed here at setup
  1062.     DB    0        ;Normal FCB plus...
  1063. OVERLAY SET    $        ;(Nothing past here but DS's)
  1064. RANDOM:
  1065.     DS    3        ;...Random access bytes
  1066. MAXMEM:
  1067.     DS    2
  1068. LOADDR:
  1069.     DS    2
  1070. ;*************************************************
  1071. ;End of segment to be relocated.
  1072.     IF    OVERLAY EQ 0
  1073. OVERLAY SET    $
  1074.     ENDIF
  1075. ;
  1076. PAGES    EQU    ($-@BASE+0FFH)/256+8
  1077. ;
  1078. SEGLEN    EQU    OVERLAY-@BASE
  1079.     ORG    @BASE+SEGLEN
  1080.     PAGE
  1081. ;    Build the relocation information into a
  1082. ; bit table immediately following.
  1083. ;
  1084. @X    SET    0
  1085. @BITCNT SET    0
  1086. @RLD    SET    ??R1
  1087. @NXTRLD SET    2
  1088.     RGRND    %@RLBL+1    ;define one more label
  1089. ;
  1090.     REPT    SEGLEN+8
  1091.     IF    @BITCNT>@RLD
  1092.     NXTRLD    %@NXTRLD    ;next value
  1093.     ENDIF
  1094.     IF    @BITCNT=@RLD
  1095. @X    SET    @X OR 1     ;mark a bit
  1096.     ENDIF
  1097. @BITCNT SET    @BITCNT + 1
  1098.     IF    @BITCNT MOD 8 = 0
  1099.     DB    @X
  1100. @X    SET    0    ;clear hold variable for more
  1101.     ELSE
  1102. @X    SET    @X SHL 1    ;not 8 yet. move over.
  1103.     ENDIF
  1104.     ENDM
  1105. ;
  1106.     DB    0
  1107. HOLD:
  1108.     DB    0,0        ;0 length, null terminator
  1109.     DS    128-2        ;rest of HOLD area
  1110. MEMBER:
  1111.     DS    16
  1112. ;
  1113.     END    CCPIN
  1114.