home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / cpm3 / chn31.lbr / CHN31.MZC / CHN31.MAC
Text File  |  1988-01-06  |  15KB  |  510 lines

  1. ;
  2. ; CHN.MAC  --  Version 3.1  --  For CP/M Plus (3.0) Only
  3. ;
  4. ; Creates a command file (alias) for a group of chained
  5. ; commands.
  6. ;
  7. ; Note: This program requires CP/M 3.0 and a Z80 CPU.
  8. ;
  9. ;     Usage: CHN {{d:}fn {[command{\command{...}}}}
  10. ;
  11. ; The filename is name of the output (command) file for CHN to
  12. ; create or edit.  If a filename is not given, it will be requested:
  13. ;
  14. ;        Name of Command File: {d:}fn
  15. ;
  16. ; Enter the name.  If a drive specification is included, the new
  17. ; file will be created on that drive, otherwise the default drive
  18. ; will be used.  The file created will be a .COM file, so it is
  19. ; not necessary to enter the filetype (any filetype entered will
  20. ; be ignored).
  21. ;
  22. ; If an output filename is included in the command tail then a
  23. ; command line for inclusion in the command file may also be
  24. ; included in the tail following a left bracket ([).  You have
  25. ; slightly less command line space for your command file this way
  26. ; because the CCP will not accept more than 128 characters from
  27. ; the system prompt, including "CHN", the output filename, and the
  28. ; necessary delimiting spaces.  In addition, exclamation points
  29. ; cannot be included in a CP/M Plus command tail, so a backslash
  30. ; (\) should be used to separate multiple commands.  These will
  31. ; be converted by CHN to exclamation points.  Backslashes are
  32. ; seldom used in commands, but if you need to enter one then omit
  33. ; the command line from the command tail.
  34. ;
  35. ; CHN will then request the command line from you:
  36. ;
  37. ;    COMMAND LINE:
  38. ;
  39. ;    >
  40. ;
  41. ; Enter the command line.  It may include parameters like SUBMIT
  42. ; files of the form $n where n is a single digit 1-9.  Parameter
  43. ; 0 cannot be used (it becomes the command name).  Entering two
  44. ; $$ in the command line enters a real $ (like SUBMIT).  Parameters
  45. ; may be up to 14 characters each.  The command line is limited
  46. ; to 128 characters total, including space for entering parameters.
  47. ;*Multiple chained commands separated by ! are permitted, as are
  48. ; conditional commands using a colon (:).
  49. ;
  50. ; CHN's .COM files do not support program input.  (SUBMIT allows
  51. ; that using the "<" marker.)
  52. ;
  53. ; If a .COM with the same name exists, you will be asked if you want
  54. ; to modify it.  If you answer "Y" and you enter a command line in
  55. ; the command tail, the old file will immediately be overwritten.  If
  56. ; you didn't enter a command tail, CHN will attempt to read the file.
  57. ; (If it is not a CHN file, CHN will complain and abort.)
  58. ;
  59. ; After the old file is read, the old command line will be displayed
  60. ; for editing.  You may use all the CP/M Plus line editing facilities,
  61. ; some of which will be displayed on the screen to remind you.  Once
  62. ; you press <return>, a new file containing the edited line will be 
  63. ; created.
  64. ;
  65. ; VERSIONS:
  66. ;    0.1    Gordon Wilk -- original version.
  67. ;    1.0    Gordon Wilk -- first public domain release.
  68. ;    2.0    Gordon Wilk, 9/86 -- FOG release -- Osborne
  69. ;            Executive specific; program named SYN for
  70. ;            SYNonym.
  71. ;    3.0    Gene Pizzetta, 5/20/87 -- Machine specific code
  72. ;            (which was unnecessary) changed; command
  73. ;            line filename and drive specification added
  74. ;            for output file; changed parameter marker
  75. ;            to '$' (was '&') to be consistent with SUBMIT
  76. ;            (nothing new to remember); changed program
  77. ;            name to CHN from SYN; now sends "failed"
  78. ;            code to BDOS if aborted (to work with
  79. ;            conditional CHN and SUBMIT files); code
  80. ;            cleaned up; Z80 macros removed, Z80.LIB now
  81. ;            required.  Should now run on all CP/M Plus
  82. ;            machines.
  83. ;    3.1    Gene Pizzetta, 6/15/87 -- Added ability to read
  84. ;            command line contents from command tail;
  85. ;            fixed bug that caused program not to abort
  86. ;            after command line editing mode if ^X was
  87. ;            used to erase the entire command line (an
  88. ;            empty command line was written to disk).
  89. ;
  90. ; COPYRIGHT:  Original code copyright 1986 by    Gordon Wilk
  91. ;                        6707 Springpark Ave.
  92. ;                        Los Angeles CA 90056
  93. ;
  94. ; Released for private non-commercial uses without fee.
  95. ;
  96. ; Please report any bugs or suggestions concerning this version to:
  97. ;    Gene Pizzetta        CompuServe 72060,505
  98. ;    481 Revere Street    FOG #29 (617) 288-4667
  99. ;    Revere, MA  02151    Voice (617) 284-0891
  100. ;
  101. ; Developed with SLRMAC.  May be assembled with MAC by changing the
  102. ; filetype to .ASM.  Z80.LIB is required.  Note: the line above
  103. ; marked with an * will generate an error, but it is harmless.
  104. ; The code is not affected.
  105. ;
  106. ;    
  107. WBoot    equ    00h        ; warm boot
  108. Bdos    equ    05h        ; BDOS entry
  109. MemTop  equ    Bdos+1        ; top of memory
  110. Fail    equ    0FF00h        ; failure code
  111. CpmFcb    equ    05Ch        ; default FCB 
  112. FcbExt    equ    CpmFcb+9    ; default filetype
  113. FcbCr    equ    CpmFcb+32
  114. DBuff    equ    080h        ; default DMA buffer 
  115. ;
  116. ; BDOS functions
  117. ;
  118. ConIn    equ    01h
  119. FOpen    equ    0Fh
  120. FClose    equ    10h
  121. FRead    equ    14h
  122. FWrite    equ    15h
  123. FMake    equ    16h
  124. MultSec    equ    2Ch
  125. Chain    equ    2Fh
  126. BdosRet    equ    6Ch
  127. FParse    equ    98h
  128. ;
  129. ; character codes
  130. ;
  131. LF    equ    0Ah        ; linefeed
  132. CR    equ    0Dh        ; carriage return
  133. BELL    equ    07h        ; BEL
  134. ESC    equ    1Bh        ; escape
  135. ;
  136. ; The following equates may be changed and the program re-assembled
  137. ;
  138. ArgMark    equ    '$'        ; parameter argument marking character
  139. CmdDelm    equ    '\'        ; command tail multiple command delimiter
  140. ;
  141.     MACLIB    Z80
  142. ;
  143. PRINT    MACRO    MSG        ; print the string at MSG
  144.     lxi    d,MSG
  145.     call    PSTR
  146.     ENDM
  147. ;
  148. REPLY    MACRO    BUFFR,LENGTH    ; get string from console
  149.     lxi    h,BUFFR
  150.     mvi    m,LENGTH
  151.     xchg
  152.     call    GETS
  153.      ENDM
  154. ;
  155. FILE    MACRO    FUNC,POINTER    ; BDOS file related calls
  156.   IF NOT NUL POINTER
  157.     lxi    d,POINTER
  158.   ENDIF
  159.     mvi    c,FUNC
  160.     call    Bdos
  161.     ENDM
  162. ;
  163. SETSEC    MACRO   NUMBER        ; set multi-sector count
  164.     push    b
  165.     push    d
  166.     push    h
  167.     mvi    c,MultSec
  168.     mvi    e,NUMBER
  169.     call    Bdos
  170.     pop    h
  171.     pop    d
  172.     pop    b
  173.     ENDM
  174. ;
  175. BLKMOVE MACRO    FROM,TO,LENGTH    ; move a block of memory
  176.     lxi    h,FROM
  177.     lxi    d,TO
  178.     lxi    b,LENGTH
  179.     LDIR
  180.     ENDM
  181. ;
  182.     org    100h
  183.     jmp    MAIN
  184. ;
  185. ; strings for dim and normal video must end with $
  186. ;
  187. DIM:    db    '$',0,0,0,0,0,0,0    ; string for dim video
  188. NORMAL:    db    '$',0,0,0,0,0,0,0    ; string for normal video
  189. ;
  190. ; messages ...
  191. ;
  192. SIGNON:    db    CR,LF,'CHN  for CP/M Plus    Version 3.1$'
  193. ASKFIL:    db    'Name of Command File: $'
  194. EDHLP:    db    '<--   -->   DEL   Del/BS   BOL/EOL   Redsply   DONE    ',CR,LF
  195.     db    '^A    ^F    ^G      ^H       ^B        ^R      <CR>    $'
  196. SHWOLD:    db    'EDITING COMMAND LINE:$'
  197. CRLF:    db    CR,LF,LF,'$'
  198. ASKCOM:    db    'COMMAND LINE:$'
  199. PROMPT:    db    '>$'
  200. ASKMOD:    db    'This Command File Exists.   Modify it? (Y/N): $'
  201. NOTCHN:    db    ' * *  Not a Command File  * *$'
  202. ABORT:    db    'ABORTED',BELL,'$'
  203. DONE:    db    'DONE$'
  204. QCOM:    db    '.COM',0
  205. QCHN:    db    'CHN',0
  206. PFCB:    dw    DBuff+2        ; parse block: name starts at 2nd byte
  207.     dw    CpmFcb
  208. ;
  209. MAIN:    lhld    MemTop        ; stack at top of memory
  210.     dcx    H
  211.     sphl
  212.     PRINT    SIGNON        ; sign on
  213.     lda    CpmFcb+1    ; check for command tail
  214.     cpi    '#'
  215.     cc    GETFN        ; (no tail, ask)
  216.     BLKMOVE    QCOM+1,FcbExt,3    ; move .COM to FCB
  217. ;
  218.     lxi    h,DBuff+1
  219.     lxi    d,COMNC
  220.     call    BRACKET        ; check for command line in tail
  221. ;
  222. ISFILE:    BLKMOVE CpmFcb+1,PARMS,8  ; and place in parameter 0
  223.     FILE    FOpen,CpmFcb    ; see if file already exists
  224.     inr    a        ; if it does then ask
  225.     JRNZ    FILEX        ; ..about modification
  226.     lda    COMNC        ; see if command line already exists
  227.     cpi    0
  228.     JRNZ    FLMAKE        ; (yes, don't ask for one)
  229.     PRINT    CRLF
  230.     PRINT    ASKCOM        ; otherwise, ask for command line and
  231.     PRINT    CRLF
  232.     PRINT    PROMPT
  233.     REPLY    COMMX,128    ; ..put into buffer space of new program
  234.     jz    EREXIT        ; (no command line: abort)
  235. FLMAKE:    FILE    FMake,CpmFcb    ; ..create it and
  236.     jmp    DO$WR        ; ..write the new file
  237. ;
  238. ; FILEX -- the command file exists; do you want to modify it?
  239. ;
  240. FILEX:    PRINT    CRLF
  241.     PRINT    ASKMOD        ; Modify it?
  242.     call    YESNO
  243.     jrz    YESMOD
  244.     call    GETFN        ; (no, get new filename)
  245.     jr    ISFILE
  246. ;
  247. YESMOD:    lda    COMNC        ; see if a new cmd line already exists
  248.     cpi    0
  249.     jnz    DO$WR        ; if so just write it
  250.     call    RD$COM        ; get command line from file,
  251.     sub    a        ; ..set cr to first
  252.     sta    FcbCr        ; ..record for re-write
  253. ;
  254. ; show the old line and accept edit to COMLIN 
  255. ;
  256.     PRINT    CRLF
  257.     PRINT    DIM        ; dim video
  258.     PRINT    EDHLP        ; editing help message
  259.     PRINT    NORMAL        ; normal video
  260.     PRINT    CRLF
  261.     PRINT    SHWOLD        ; editing message
  262.     PRINT    CRLF
  263.     PRINT    PROMPT
  264.     lxi    D,COMMX
  265.     call    GETEDIT        ; edit command line
  266. ;
  267. ; DO$WR -- write program code and command line data to new file
  268. ;    (512 bytes, 4 logical sectors)
  269. ;
  270. DO$WR:    lda    COMNC        ; is command line null?
  271.     cpi    0
  272.     JRZ    EREXIT        ; (yes, abort)
  273.     lxi    d,NEWPRO    ; set buffer to new program area
  274.     call    SETBUFF
  275.     SETSEC    4        ; set multi-sector count
  276.     FILE    FWrite,CpmFcb    ; ..write
  277.     FILE    FClose,CpmFcb    ; ..close
  278. ;
  279. ; FINISH -- normal end of program
  280. ;
  281. FINISH:    PRINT    CRLF
  282.     PRINT    DONE        ; say we're through
  283.     jmp    WBoot        ; ..and terminate
  284. ;
  285. ; EREXIT -- aborted program exit
  286. ;
  287. EREXIT:    PRINT    CRLF
  288.     PRINT    ABORT        ; let us know
  289.     lxi    d,Fail        ; kill any conditional
  290.     mvi    c,BdosRet    ; ..batch file
  291.     call    Bdos
  292.     jmp    WBoot        ; ..and terminate
  293. ;
  294. ;================================================================
  295. ;    SUBROUTINES
  296. ;================================================================
  297. ;
  298. BRACKET:
  299.     mvi    b,'['        ; look for [ in command tail
  300.     mvi    c,0        ; ..or a null
  301.     call    SCAN
  302.     cmp    b        ; was it a [
  303.     rnz            ; (no, return)
  304.     mvi    a,0        ; yes, move it
  305.     sta    COMNC        ; initialize buffer to 0
  306. LOOP:    inx    d
  307.     inx    h        ; increment pointers
  308.     mov    a,m        ; get byte from command tail
  309.     cpi    CmdDelm        ; is it a backslash?
  310.     JRNZ    NOSLSH        ; (no, skip conversion)
  311.     mvi    a,'!'        ; make it an exclamation
  312. NOSLSH:    stax    d        ; store in command line
  313.     cpi    0        ; was it a null?
  314.     rz            ; (yes, end of tail)
  315.     lda    COMNC        ; no, increment command length
  316.     inr    a
  317.     sta    COMNC
  318.     jr    LOOP
  319. ;
  320. SCAN:    mov    a,m        ; get byte
  321.     cmp    b        ; is it a [
  322.     rz            ; (yes, return)
  323.     cmp    c        ; a null then?
  324.     rz            ; (yes, return)
  325.     inx    h        ; increment pointer
  326.     jr    SCAN        ; ..and keep looking
  327. ;
  328. GETFN:    PRINT    CRLF
  329.     PRINT    ASKFIL        ; ask for filename
  330.     REPLY    DBuff,10    ; get reply, put in DMA buffer
  331.     jz    EREXIT        ; (no entry: abort)
  332.     lxi    b,5        ; move 5 chars from ".COM"
  333.     xchg            ; ..to 1st byte after name
  334.     lxi    h,QCOM
  335.     LDIR
  336.     FILE    FParse,PFCB    ; parse filename into CpmFcb
  337.     ret
  338. ;
  339. ; RD$COM -- Read an existing file and verify it is a CHN file
  340. ;
  341. RD$COM:    lxi    d,NEWPRO    ; overlay the NEWPRO code
  342.     call    SETBUFF        ; with a file read
  343.     SETSEC    4        ; set multi-sector count
  344.     FILE    FRead,CpmFcb    ; ..read it
  345. ;
  346. ; parmeter 0 must be filename, but only the first char is checked 
  347. ;
  348.     lda    PARMS        ; 1st char of parm0
  349.     lxi    h,CpmFcb+1    ; --> 1st char of filename
  350.     cmp    m
  351.     rz            ; if it matches, return
  352.     PRINT    CRLF
  353.     PRINT    NOTCHN        ; otherwise, complain
  354.     jmp    EREXIT        ; ..and abort
  355. ;
  356. ; GETEDIT -- edits string at (DE)
  357. ;    return: DE = A = length and flags set
  358. ;        HL -> EOS null termination
  359. ;
  360. GETEDIT:
  361.     push    d        ; save buffer address
  362.     call    SETBUFF        ; set DMA address there
  363.     mov    d,a        ; set DE=0 for edit
  364.     mov    e,a
  365.     jmp    GETS$2
  366. ;
  367. ; GETS -- gets string to (DE)
  368. ;
  369. GETS:    push    d        ; save buffer address
  370. GETS$2:    mvi    c,10        ; get string (DE)
  371.     call    Bdos
  372.     pop    h        ; HL --> buffer
  373.     inx    h        ; HL --> count
  374.     mov    a,m        ; A = length
  375.     mov    e,a
  376.     mvi    d,0        ; DE = length
  377.     dad    d        ; HL --> last char in string
  378.     inx    h        ; HL --> EOS
  379.     mov    m,d        ; NULL terminate
  380.     ora    a        ; and set flags
  381.     ret
  382. ;
  383. ; YESNO -- return with Z flag set if reply = Y ; reset otherwise
  384. ;
  385. YESNO:    mvi    C,ConIn
  386.     call    Bdos
  387.     ani    05Fh        ;upper case
  388.     cpi    'Y'
  389.     ret
  390. ;
  391. ; * * The routines below return directly from BDOS * *
  392. ;
  393. ; PSTR -- Console display string
  394. ;
  395. PSTR:    mvi    c,09        ; display string pointed 
  396.     jmp    Bdos        ; ..to by DE
  397. ;
  398. ; SETBUFF -- set buffer address
  399. ;
  400. SETBUFF:
  401.     mvi    c,26        ; set DMA buffer
  402.     jmp    Bdos        ; ..to (DE)   
  403. ;
  404. ;
  405. ; * * below is the new command file to be created * *
  406. ;
  407. ; Move the command line data from COMLIN to the default DMA buffer
  408. ; and chain to it.  OFFSET adjusts addresses to their runtime
  409. ; locations because MAC does not have .phase/.dephase
  410. ;    
  411. NEWPRO    equ    $
  412. OFFSET    equ    $-100H
  413.     lhld    MemTop        ; set up stack
  414.     dcx    h
  415.     sphl
  416. ;
  417.     call    GETARG        ; get args into parm list
  418.     lxi    h,COMLIN-OFFSET    ; move the command line
  419.     lxi    d,DBuff        ; ..to DMA buffer
  420.     call    MOVE
  421.     stax    d        ; terminate with 0
  422.     mvi    c,Chain        ; chain to command line
  423.     jmp    Bdos
  424. ;
  425. ; * * SUBROUTINES * *
  426. ;
  427. ; GETARG -- moves arguments from the command line to the 
  428. ;         appropriate PARM slots
  429. ;
  430. GETARG    equ    $-OFFSET
  431.     lxi    d,DBuff+1    ; source
  432.     lxi    h,PARMS-OFFSET+16 ; destination step over parm0
  433.     lxi    b,16        ; parm increment
  434. FNDARG    equ    $-OFFSET    ; find an argument
  435.     ldax    d
  436.     inx    d
  437.     cpi    ' '        ; if it's a space 
  438.     jz    FNDARG        ; ..keep looking
  439.     rc            ; (if < space, quit; otherwise
  440.                 ; ..we've found an argument
  441.     push    h        ; save address of parm slot
  442. ARGLOOP    equ    $-OFFSET    ; move chars until end of argument
  443.     mov    m,a        ; move char to parms
  444.     inx    h        ; increment destination
  445.     ldax    d        ; get next char
  446.     inx    d        ; increment source
  447.     cpi    ' '+1        ; (if it's > space then
  448.     jnc    ARGLOOP        ; ..there's more to copy)
  449.     pop    h        ; else restore HL --> parm slot
  450.     ora    a        ; (if it's null
  451.     rz            ; ..then quit)
  452.     dad    b        ; otherwise HL = HL+16, next slot
  453.     jmp    FNDARG
  454. ;
  455. ; MOVE -- a recursive macro processor
  456. ;    HL --> source string
  457. ;    DE --> destination in the command line buffer
  458. ; Characters are moved (HL) to (DE).  If an ArgMark is encountered,
  459. ; HL is saved, the address of the stored argument placed in HL
  460. ; and MOVE is called recursively to move from the stored argument.
  461. ; Stops at a NULL byte in source.
  462. ;    Return: A = 0
  463. ;        DE --> EOS
  464. ;
  465. MOVE    equ    $-OFFSET
  466.        mov    a,m        ; A = char
  467.     inx    h        ; point to next char
  468.      ora    a        ; if 0 then
  469.      rz            ; ..end of string
  470.     cpi    ArgMark        ; if not an argument marker then
  471.     jnz    MOVE2        ; ..move the character
  472.     mov    a,m        ; otherwise get next char
  473.     inx    h        ; ..and point to one after that
  474.     cpi    '0'        ; if it's < '0' it's not an arg number
  475.     jc    MOVE2        ; ..so move it
  476.     cpi    '9'+1        ; if it's > '9' it's not an arg number
  477.     jnc    MOVE2        ; ..so move it
  478.                 ; otherwise its an ASCII digit
  479.     sui    '0'        ; ..so make it binary
  480. ;
  481. ; A = argument number which, multiplied by 16, is list index.
  482. ; Save HL and replace it with the argument address.
  483. ;
  484.     add    a
  485.     add    a
  486.     add    a
  487.     add    a        ; times 16 for length of arg
  488.     push    h        ; save address of next char
  489.     mvi    b,0
  490.     mov    c,a        ; BC = address of list offset
  491.     lxi    h,PARMS-OFFSET    ; HL = base of arg list
  492.     dad    b        ; HL = address in arg list
  493.     call    MOVE        ; move recursively from arg list
  494.     pop    h        ; restore source address
  495.     jmp    MOVE        ; ..and start over
  496. ;
  497. MOVE2    equ    $-OFFSET
  498.     stax    d        ; move to destination
  499.     inx    d        ; point to next char in dest
  500.     jmp    MOVE        ; get next char
  501. ;
  502. ; data for NEWPRO
  503. ;
  504. PARMS:    ds    10*16        ; parameter space
  505. COMMX:    db    128        ; maximum chars accepted
  506. COMNC:    db    0        ; number of chars entered
  507. COMLIN:    ds    128        ; command line buffer
  508. ;
  509.     end    100h
  510.