;/.ASM by John M. Kodis
;CP/M U.G. contrubution November 1980
;
;The "slant" program reads a command line which
;may contain several program invocations.  A $$$.SUB
;file is built with these commands.  This file is
;then executed.
;
;For example, the command line:
;
;/ asm copy; load copy; dir copy*.*; type copy.prn
;
;will build a file containing commands to assemble
;and load the file named 'copy', search the directory
;for all copy programs, and type the COPY.PRN file.
;
;Based on "/.ASM", CPMUG 40.1.  This program was
;written because the abstract for volume 40 states
;that 40.1 works only under CP/M version 1.4,
;and that the source code cannot be provided.  This
;version overcomes both of these difficulties.
;       (Note: 40.1 "1.4 only" meant "not 1.3".
;        it does work with 2.2 <Ward C.>)
;
;PROCESSOR:     ASM
;DEPENDENCIES:  NONE
;NOTES:         Set "DUP" to true, to define a version
;               which will write "/.SUB" out to disk
;               to facilitate re-executing the same commands.
;               To re-execute them, REN $$$.SUB=/.SUB
;               then ^C.  Alternatively, PIP $$$.SUB=/.SUB
;
;               You might wish to name the version of this
;               program assembled with DUP true, as ".COM
;
;               (but this will "screw up" the Master CATalog
;                system which reauires its "-name.xxx" to be
;                the first file found)
;
;       A program for quickie, use once and throw away submits.
;
;       The command syntax is:
;
;       A>/ <command line>[[;<command line>] ... ] <cr>
;
closef  equ     16
delete  equ     19
writef  equ     21
makef   equ     22
dmaf    equ     26
;
boot    equ       0     ;for a warm start
bdos    equ       5     ;cp/m entry point
chcnt   equ     080h    ;character count
cibuf   equ     081h    ;console input buffer
tpa     equ     100h    ;transient program area
;
dup     equ     0
;
       org     tpa
;
slant:  lxi     h,chcnt
       mov     a,l
       add     m
       inr     a
       mov     l,a
       mvi     m,0     ;zero the byte after the end of the command line.
;
       lxi     d,cibuf ;de is the source pointer.
       lxi     h,subbuf+1;hl is the destination pointer.
;
nxtcmd: ldax    d
       cpi     ' '
       jnz     xfer    ;skip over leading blanks.
       inx     d
       jmp     nxtcmd
;
xfer:   ldax    d
       ana     a       ;end of line?
       jz      cmdend
       cpi     ';'     ;end of command?
       jz      cmdend
       mov     m,a     ;if neither, xfer it to the output buffer,
       inx     d
       inx     h       ;bump both pointers,
       jmp     xfer    ;and try again.
;
cmdend: mvi     m,0     ;zero the byte after the end of the line.
       mov     a,l
       dcr     a
       ani     7fh     ;accumulator has character count.
       mov     b,a     ;save it.
       mov     a,l
       ani     80h
       mov     l,a     ;hl points to the character count byte.
       mov     m,b
;
       ldax    d
       ana     a       ;if we've reached the end of the input line...
       jz      fileit  ;let's "file it".
       lxi     b,129
       dad     b
       inx     d       ;point to the next character in the input.
       jmp     nxtcmd  ;loop back for the next command.
;
fileit: push    h       ;save address of last zone
       if      dup
       lxi     d,xfcb
       mvi     c,delete
       call    bdos
       endif
       lxi     d,fcb
       mvi     c,delete
       call    bdos    ;delete any existing command files.
;
       if      dup
       lxi     d,xfcb
       mvi     c,makef
       call    bdos
       endif
       lxi     d,fcb
       mvi     c,makef
       call    bdos    ;create the new command files.
;
       pop     h
wrloop: push    h
       xchg
       mvi     c,dmaf
       call    bdos
;
       if      dup
       lxi     d,xfcb
       mvi     c,writef
       call    bdos
       endif
       lxi     d,fcb
       mvi     c,writef
       call    bdos    ;write the new commands, one command per
                       ;disk sector, writing the last command first.
;
       pop     h       ;get current dma address
       lxi     d,-128
       dad     d
       lxi     d,subbuf
       mov     a,l
       sub     e
       mov     a,h
       sbb     d
       jnc     wrloop
;
       if      dup
       lxi     d,xfcb
       mvi     c,closef
       call    bdos
       endif
       lxi     d,fcb
       mvi     c,closef
       call    bdos    ;close the files after writing the last sector.
;
       rst     boot    ;back to cp/m via a warm start.
                       ;changing this to a "ret" will return
                       ;to CP/M without the warm start, and so
                       ;the command file will not be executed
                       ;until the next boot from this disk.
;
fcb:    db      1, '$$$     SUB'
       dw      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
xfcb:   db      1, '/       SUB'
       dw      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
;
       org     ($+0ffh) and 0ff00h
;
subbuf: ds      0
;
       end     slant