home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / assembly / abzshell / abzshell.s
Text File  |  1990-08-01  |  81KB  |  2,239 lines

  1.  
  2. * ABZ command shell, by Alain Birtz, feb. 89 
  3. * These program and assembler source are public domain, can be copied freely
  4. * If your use part of this source, it will be fair to mention the author
  5. * in your header program. You can contact me via Compuserve [72467,2770]
  6. * or write to: 650 Grand St-Charles, St-Paul d'Abbotsford,
  7. * P.Q., Canada J0H-1A0
  8.  
  9. * ------------------------------------------------------------------------ *
  10.  
  11. BIOS    equ     13
  12. XBIOS   equ     14
  13. GEMDOS  equ     1
  14. TAB     equ     9
  15. LF      equ     10
  16. CR      equ     13
  17. SPACE   equ     32
  18.  
  19. NO_MEM  equ     -39
  20. NO_PRT  equ     -993
  21. NO_REN  equ     -994
  22. NO_BAT  equ     -995
  23. UNKNOW  equ     -996
  24. VAR     equ     -997
  25. FULL    equ     -998
  26. MISS    equ     -999
  27.  
  28.  
  29. * ------------------------------------------------------------------------ *
  30.  
  31. * release free memory.
  32.  
  33.         move.l  a7,a5                   ; save stack pointer
  34.         lea     ustk,a7                 ; set local stack (ext data)
  35.         move.l  (4,a5),a5               ; basepage address
  36.         move.l  ($C,a5),d0              ; prg length
  37.         add.l   ($14,a5),d0             ; data area length
  38.         add.l   ($1C,a5),d0             ; bss area length
  39.         add.l   #$100,d0                ; reserve $100 long base page 
  40.         move.l  d0,-(sp)                ; length of memory to free
  41.         move.l  a5,-(sp)                ; start address of this memory
  42.         move    d0,-(sp)                ; junk word
  43.         move    #$4A,-(sp)              ; function number 'Mshrink'
  44.         trap    #GEMDOS
  45.         adda.w  #12,sp                  ; update stack
  46.  
  47.         lea     def_p,a0                ; save current directory
  48.         bsr.w   get_path
  49.         lea     title,a0                ; print title
  50.         bsr.w   prt_str
  51.         lea     boot,a0                 ; execute 'BOOT.BAT'
  52.         bsr.w   split_arg
  53.         bsr.w   do_file
  54.         bra.w   shell                   ; enter in the main shell loop
  55.  
  56. * ------------------------------------------------------------------------ *
  57.  
  58. shell:
  59.  
  60. * display the prompt symbol, get some command and execute this command
  61.  
  62.         tst.w   err_no                  ; some error ?
  63.         beq.s   shell0
  64.         bsr.w   show_error              ; yes -> display error type
  65.  
  66. shell0: lea     wait_1,a0
  67.         bsr.w   prt_str                 ; print default pathname
  68.         lea     def_p,a0
  69.         bsr.w   prt_str
  70.         lea     wait_2,a0
  71.         bsr.w   prt_str
  72.         lea     cmd,a0
  73.         moveq   #80-3,d0                ; 80-3 char max
  74.         bsr.w   get_str                 ; get user command
  75.         tst.w   d0
  76.         beq.s   shell                   ; at least one char
  77.         bsr.w   upper                   ; make command upper case only
  78.         bsr.w   split_arg               ; split command and argument
  79.         bsr.w   do_keyword
  80.         tst.w   d0                      ; it a keyword ?
  81.         bne.s   shell                   ; yes -> do it, wait next command
  82.         bsr.w   do_drive
  83.         tst.w   d0                      ; it a drive letter ? (type 'B:')
  84.         bne.s   shell                   ; yes -> change, wait next command
  85.         bsr.w   do_file                 ; it is a filename ?
  86.         tst.w   d0                      ; it a file ?
  87.         bne.s   shell                   ; yes -> exec. it, wait next command
  88.         move.w  #UNKNOW,err_no          ; no -> error
  89.         bra.s   shell                   ; wait for next command
  90.  
  91. * ------------------------------------------------------------------------ *
  92.  
  93. do_keyword:
  94.  
  95. * search command in the keyword list. if the keyword is found, execute the
  96. * routine for the keyword and return with d0 set. else return d0 clear
  97.  
  98.         moveq   #0,d2                   ; keyword counter
  99.         lea     key_w,a0                ; list of keyword
  100.  
  101. search: movea.l arg1,a1                 ; user command (first argument)
  102.         bsr.w   compare                 ; same as current keyword ?
  103.         tst.w   d0
  104.         bne.s   doKEYw                  ; yes -> execute this command
  105.         tst.b   (a0)                    ; no -> try next keyword
  106.         beq.s   noKEYw                  ; until end of list
  107.         addq.w  #1,d2
  108.         bra.s   search
  109.  
  110. doKEYw: lea     call,a0                 ; routine address table
  111.         lsl.w   #2,d2                   ; multiply d2 by 4 -> table offset
  112.         movea.l 0(a0,d2.w),a0           ; our routine address
  113.         jsr     (a0)                    ; execute this routine
  114.         moveq   #-1,d0
  115. noKEYw: rts
  116.  
  117. * ------------------------------------------------------------------------ *
  118.  
  119. do_drive:
  120.  
  121. * if the command is of type 'A:', 'B', ... then set the default drive
  122. * and return with d0 set. else return d0 clear
  123.  
  124.         moveq   #0,d0
  125.         movea.l arg1,a0                 ; user command
  126.         tst.b   2(a0)                   ; null char ?
  127.         bne.s   do_noD                  ; yes -> execute this command
  128.         cmpi.b  #':',1(a0)              ; colon ?
  129.         bne.s   do_noD                  ; yes -> execute this command
  130.  
  131.         lea     def_p,a0
  132.         clr.b   3(a0)                   ; keep only A:\
  133.         bsr.w   set_path                ; to reset (old) drive pathname
  134.         movea.l arg1,a0
  135.         bsr.w   set_path                ; do it
  136.         lea     def_p,a0                ; get complete new pathname
  137.         bsr.w   get_path
  138.         moveq   #-1,d0
  139.  
  140. do_noD: rts
  141.  
  142. * ------------------------------------------------------------------------ *
  143.  
  144. do_file:
  145.  
  146. * search command on the directory. if the filename is found, execute the
  147. * program and return with d0 set. else return d0 clear
  148.  
  149.         movea.l arg1,a0                 ; user command (first argument)
  150.         lea     work,a1                 ; work buffer
  151.         bsr.w   str_copy                ; copy the command
  152.  
  153. * next we must check for a valid filename extension so get a dot.
  154. * if there is no dot in the filename, get any file in the directory
  155. * with valid extension
  156.  
  157.         movea.l a1,a2                   ; save end of filename (the copy)
  158.  
  159. getDOT: move.b  -(a1),d0
  160.         cmpi.b  #'\',d0                 ; folder symbol ?
  161.         beq.s   no_dot
  162.         cmpi.b  #':',d0                 ; disk symbol ?
  163.         beq.s   no_dot
  164.         cmpi.b  #'.',d0                 ; dot ?
  165.         beq.s   is_dot
  166.         cmpa.l  #work,a1
  167.         bhi.s   getDOT                  ; until start of command
  168.  
  169. no_dot: move.b  #'.',(a2)+              ; put a dot at the end of filename
  170.         movea.l a2,a4                   ; the extention start there
  171.         move.b  #'*',(a2)+              ; and a wildcard in extention area
  172.         clr.b   (a2)                    ; null terminated string
  173.         bra.s   getONE
  174.  
  175. is_dot: lea     1(a1),a4                ; the extention start there
  176.  
  177. * now get one filename in the directory. first get dta buffer address
  178.  
  179. getONE: move.w  #$2F,-(sp)              ; function number: Fgetdta
  180.         trap    #GEMDOS                 ; get disk transfert address
  181.         addq.l  #2,sp                   ; update stack
  182.         move.l  d0,dta                  ; save dta address
  183.  
  184. * second search for the first matching file in the directory
  185.  
  186.         move.w  #1,-(sp)                ; file affribute: normal + protect
  187.         pea     work                    ; copy of user command
  188.         move.w  #$4E,-(sp)              ; function number: Fsfirst
  189.         trap    #GEMDOS
  190.         addq.l  #8,sp                   ; update stack
  191.         tst.w   d0                      ; file exist ?
  192.         bne.w   nofind                  ; no -> exit
  193.  
  194. * a matching filename exist. we must check for a valid extension.
  195.  
  196. valid0: movea.l dta,a3
  197.         lea     30(a3),a3               ; filemame in dta
  198.  
  199. valid1: move.b  (a3)+,d0
  200.         beq.s   next                    ; no dot -> try next file
  201.         cmpi.b  #'.',d0
  202.         bne.s   valid1
  203.         lea     ext,a0                  ; valid extension list
  204.  
  205. valid2: movea.l a0,a2                   ; current extention in the list
  206.         movea.l a3,a1                   ; extention in dta filename
  207.         bsr.w   compare                 ; same as current extension ?
  208.         tst.w   d0
  209.         bne.s   repl                    ; yes -> replace extension
  210.         tst.b   (a0)                    ; no -> try next list extention
  211.         bne.s   valid2                  ; until end of list
  212.  
  213. * no valid extention match, then get next filename
  214.  
  215. next:   move.w  #$4F,-(sp)              ; function number: Fsnext
  216.         trap    #GEMDOS
  217.         addq.l  #2,sp                   ; update stack
  218.         tst.w   d0                      ; file exist ?
  219.         beq.s   valid0                  ; yes -> check for valid extension
  220.  
  221. nofind: moveq   #0,d0                   ; file not found
  222.         rts
  223.  
  224. repl:   movea.l a2,a0                   ; current extention in the list
  225.         movea.l a4,a1                   ; start of extention in filename
  226.         bsr.w   str_copy                ; copy the valid extention
  227.         tst.b   1(a0)                   ; point now to the next list ext.
  228.         beq.w   batch                   ; last extention is BAT (batch file)
  229.         bne.w   program                 ; other is program file
  230.  
  231. * ------------------------------------------------------------------------ *
  232.  
  233. program:
  234.  
  235. * execute program of filename holding in 'work' and command tail pointed
  236. * by 'arg2'. upon return d0 is set
  237.  
  238.         lea     blank,a0
  239.         bsr.w   prt_str                 ; some blank
  240.  
  241.         movea.l arg2,a0                 ; second argument = command tail
  242.         movea.l a0,a1
  243.  
  244. length: tst.b   (a1)+                   ; compute argument length
  245.         bne.s   length
  246.  
  247.         move.l  a1,d0
  248.         sub.l   a0,d0                   ; the length (including the null)
  249.         subq.l  #1,a0
  250.         move.b  d0,(a0)                 ; length in the string leading byte
  251.  
  252.         clr.l   -(sp)                   ; no enviroment string
  253.         move.l  a0,-(sp)                ; command tail
  254.         pea     work                    ; pathname and/or filename
  255.         clr.w   -(sp)                   ; load-and-go
  256.         move.w  #$4B,-(sp)              ; 'Pexec' function
  257.         trap    #GEMDOS
  258.         adda.w  #16,sp
  259.         lea     def_p,a0
  260.         bsr.w   set_path                ; reset default pathname
  261.         moveq   #-1,d0
  262.         rts
  263.  
  264. * ------------------------------------------------------------------------ *
  265.  
  266. batch:
  267.  
  268. * load and execute batch file  of filename holding in 'work' and command
  269. * tail pointed by 'arg2'. dta buffer is pointed by 'dta'
  270. * upon return do is set
  271.  
  272.         tst.b   exeBAT                  ; already executing batch file now ?
  273.         beq.s   bat_0
  274.         move.w  #NO_BAT,err_no          ; yes -> error
  275.         moveq   #-1,d0
  276.         rts
  277.  
  278. bat_0:  lea     work,a0                 ; filemame in dta
  279.         bsr.w   open                    ; open source file      
  280.         tst.w   err_no
  281.         bpl.s   bat_r                   ; (read)
  282.         moveq   #-1,d0
  283.         rts                             ; error -> exit
  284.  
  285. bat_r:  moveq   #-1,d0                  ; get free memory
  286.         bsr.w   Malloc
  287.         subq.l  #1,d0
  288.         move.l  d0,d1
  289.  
  290.         move.l  dta,a0
  291.         move.l  26(a0),d3               ; file size
  292.         move.l  d3,d0
  293.         addi.l  #3*80,d0                ; (for lines buffer)
  294.         addq.l  #1,d0                   ; to null terminate the file
  295.         cmp.l   d1,d0                   ; file to big ?
  296.         bcc.w   bat_m                   ; (memory problem)
  297.         bsr.w   Malloc                  ; reserve memory
  298.         move.l  d0,batBUF               ; store start address
  299.  
  300.         movea.l d0,a0
  301.         move.l  d3,d0
  302.         bsr.w   read                    ; read the file
  303.         move.l  d0,d3                   ; file size
  304.         tst.w   err_no
  305.         bmi.s   bat_er                  ; close the file
  306.         bsr.w   close
  307.  
  308.         move.l  batBUF,a0               ; start of batch file buffer
  309.         move.l  a0,batPTR               ; current line pointer
  310.         adda.l  d3,a0
  311.         clr.b   (a0)+                   ; null terminated file
  312.  
  313.         move.l  a0,param                ; argument parameter (%1, %2, ...)
  314.         adda.l  #80,a0
  315.         move.l  a0,bat_LN               ; one line batch file
  316.         bsr.w   get_param               ; get parameter address (%1, %2 ...)
  317.         tst.w   err_no
  318.         bmi.s   bat_x
  319.         st      exeBAT                  ; 'executing batch file now' flag
  320.  
  321. bat_lp: move.l  batPTR,batPRV           ; save current line pointer
  322.         bsr.w   set_line                ; set one batch line
  323.         tst.w   err_no
  324.         bmi.s   bat_x   
  325.  
  326.         bsr.w   do_line                 ; execute this line of command
  327.         tst.w   err_no
  328.         bmi.s   bat_x   
  329.  
  330.         tst.b   exeBAT                  ; STOP command ?
  331.         beq.s   bat_x
  332.  
  333.         movea.l batPTR,a0
  334.         tst.b   (a0)                    ; last line ?
  335.         bne.s   bat_lp                  ; no -> try next
  336.  
  337.         bra.s   bat_x
  338.  
  339. bat_m:  move.w  #NO_MEM,err_no          ; insuficient memory
  340. bat_er: bsr.w   close                   ; close the file
  341. bat_x:  movea.l batBUF,a0
  342.         bsr.w   Mfree                   ; release used memory
  343.         moveq   #-1,d0
  344.         clr.b   exeBAT                  ; 'executing batch file now' flag
  345.         rts
  346.  
  347. * ------------------------------------------------------------------------ *
  348.  
  349. get_param:
  350.  
  351. * get parameter address (of %1, %2, ...) in 'parPTR' table
  352.  
  353.         movea.l arg2,a0
  354.         movea.l param,a1                ; copy comand line argument
  355.         bsr.w   str_copy
  356.  
  357.         movea.l param,a0                ; parameter is there
  358.         lea     parPTR,a1               ; pointer to parameter in 'param'
  359.         moveq   #3,d1                   ; dbra parameter counter
  360.  
  361. g_p_lp: bsr.w   split_arg               ; split argument (pointed by a0)
  362.         move.l  arg1,(a1)+              ; save pointer
  363.         move.l  arg2,a0                 ; try the remaining
  364.         dbra    d1,g_p_lp
  365.  
  366.         move.l  arg2,(a1)               ; fifth parameter
  367.         rts
  368.  
  369. * ------------------------------------------------------------------------ *
  370.  
  371. set_line:
  372.  
  373. * replace variable by parameter in the batch line pointed by 'batPTR'
  374.  
  375.         movea.l bat_LN,a1               ; one batch file line buffer
  376.         movea.l batPTR,a2               ; current line pointer
  377.         clr.b   cmd_ch                  ; 'is command char' flag
  378.  
  379. sLN_lp: move.b  (a2)+,d0                ; get one char
  380.         beq.s   sLNeof                  ; exit at end of file
  381.         cmpi.b  #'%',d0                 ; variable ?
  382.         beq.s   sLNvar
  383.         cmpi.b  #CR,d0
  384.         beq.s   sLN_lp                  ; ignore carriage return
  385.         cmpi.b  #LF,d0
  386.         beq.s   sLNeol                  ; exit at end of line
  387.         cmpi.b  #$20,d0                 ; control char ?
  388.         bls.s   sLN_20
  389.         st      cmd_ch                  ; set 'is command char' flag
  390. sLN_20: move.b  d0,(a1)+                ; fill the batch line
  391.         bra.s   sLN_lp
  392.  
  393. sLNvar: moveq   #0,d0
  394.         move.b  (a2)+,d0                ; get variable no.
  395.         sub.w   #'1',d0
  396.         bmi.s   sLN_er
  397.         cmpi.w  #4,d0                   ; %1 to %5 only
  398.         bhi.s   sLN_er
  399.         lea     parPTR,a0               ; parameter pointer table
  400.         lsl.w   #2,d0                   ; offset in table
  401.         movea.l 0(a0,d0.w),a0           ; the parameter address in 'param'
  402.         tst.b   (a0)                    ; parameter exist?
  403.         beq.s   sLN_er                  ; no -> error
  404.         bsr.w   str_copy                ; copy a0 to a1 (replacing %_ by
  405.         bra.s   sLN_lp                  ; its value)
  406.  
  407. sLNeof: subq.l  #1,a2
  408. sLNeol: clr.b   (a1)                    ; null terminated string
  409.         move.l  a2,batPTR               ; set pointer for next batch line
  410.         rts
  411.  
  412. sLN_er: move.w  #VAR,err_no             ; 'undefined variable'
  413.         rts
  414.  
  415. * ------------------------------------------------------------------------ *
  416.  
  417.  
  418. do_line:
  419.  
  420. * execute the batch line pointed by 'bat_LN'
  421.  
  422.         tst.b   cmd_ch                  ; reach one command char ?
  423.         beq.s   doLN_x                  ; no -> exit
  424.         lea     one_ln,a0
  425.         bsr.w   prt_str                 ; one line
  426.  
  427.         movea.l bat_LN,a0               ; the batch file line buffer
  428.         bsr.w   prt_str
  429.         bsr.w   upper                   ; make command upper case only
  430.         bsr.w   split_arg               ; split command and argument
  431.         bsr.w   do_keyword
  432.         tst.w   d0                      ; it a keyword ?
  433.         bne.s   doLN_x                  ; yes -> do it, wait next command
  434.         bsr.w   do_drive
  435.         tst.w   d0                      ; it a drive letter ? (type 'B:')
  436.         bne.s   doLN_x                  ; yes -> change, wait next command
  437.         bsr.w   do_file                 ; it is a filename ?
  438.         bne.s   doLN_x                  ; yes -> exec. it, wait next command
  439.         move.w  #UNKNOW,err_no          ; no -> error
  440.  
  441. doLN_x: rts
  442.  
  443. * ------------------------------------------------------------------------ *
  444.  
  445. show_error:
  446.  
  447. * display error type to the screen
  448.  
  449.         move.w  err_no,d4               ; error no
  450.         moveq   #0,d0
  451.         move.w  d4,d0
  452.         neg.w   d0                      ; make it positive
  453.         moveq   #10,d1                  ; base 10
  454.         moveq   #2,d2                   ; display 2 char
  455.         lea     io_no,a0                ; there
  456.         moveq   #SPACE,d3               ; replace leading zero by blank
  457.         bsr.w   l_to_a
  458.         lea     io_err,a0               ; display error no.
  459.         bsr.w   prt_str
  460.  
  461.         lea     error,a0                ; error table
  462.         subq.l  #6,a0
  463. err_lp: addq.l  #6,a0                   ; room for error no + error type adr.
  464.         move.w  (a0),d0                 ; error no. in the table
  465.         beq.s   err_x                   ; not in table -> exit
  466.         cmp.w   d0,d4                   ; our error ?
  467.         bne.s   err_lp                  ; no -> try next
  468.  
  469.         movea.l 2(a0),a0                ; error type address
  470.         bsr.w   prt_str                 ; show it
  471.  
  472. err_x:  clr.w   err_no
  473.         rts
  474.  
  475. * ------------------------------------------------------------------------ *
  476. * ----------------------- Keyword Command -------------------------------- *
  477. * ------------------------------------------------------------------------ *
  478.  
  479. * ---------------------- QUIT -------------------------------------------- *
  480.  
  481. do_quit:
  482.  
  483.         clr.w   -(sp)                   ; Pterm0
  484.         trap    #GEMDOS
  485.  
  486. * ---------------------- MFREE ------------------------------------------- *
  487.  
  488. do_mem_free:
  489.  
  490. * display number of bytes free
  491.  
  492.         moveq   #-1,d0
  493.         bsr.w   Malloc                  ; get number of free bytes in d0
  494.  
  495.         moveq   #10,d1                  ; base 10
  496.         moveq   #8,d2                   ; display 8 char
  497.         lea     free_s+2,a0             ; there
  498.         moveq   #SPACE,d3               ; replace leading zero by blank
  499.         bsr.w   l_to_a
  500.  
  501.         lea     free_s,a0
  502.         bra.w   prt_str                 ; show it
  503.  
  504. * ---------------------- DFREE ------------------------------------------- *
  505.  
  506. do_disk_free:
  507.  
  508. * display number of bytes free in the disk
  509.  
  510.         movea.l arg2,a0
  511.         moveq   #0,d0
  512.         move.b  (a0),d0                 ; drive letter
  513.         beq.s   do_D_c                  ; no argument -> current drive
  514.         subi.b  #'A'-1,d0               ; A -> 1, B -> 2...
  515. do_D_c: bsr.w   disk_free               ; get free space
  516.         tst.w   err_no                  ; error ?
  517.         beq.s   do_D_0
  518.         rts
  519.  
  520. do_D_0: moveq   #10,d1                  ; base 10
  521.         moveq   #8,d2                   ; display 8 char
  522.         lea     free_s+2,a0             ; there
  523.         moveq   #SPACE,d3               ; replace leading zero by blank
  524.         bsr.w   l_to_a
  525.  
  526.         lea     free_s,a0
  527.         bra.w   prt_str                 ; show it
  528.  
  529. * ------------------------------------------------------------------------ *
  530.  
  531. disk_free:
  532.  
  533. * get disk free space for drive d0.w. upon return d0.l hold free space.
  534.  
  535.         move.w  d0,-(sp)                ; drive no.
  536.         pea     d_free                  ; info about disk
  537.         move.w  #$36,-(sp)              ; function number: Dfree
  538.         trap    #GEMDOS
  539.         addq.l  #8,sp                   ; update stack
  540.         tst.l   d0                      ; error ?
  541.         bpl.s   d_f_0
  542.         move.w  d0,err_no
  543.         rts
  544.  
  545. d_f_0:  lea     d_free,a0
  546.         move.l  8(a0),d0                ; sector size (in bytes)
  547.         move.l  12(a0),d1               ; cluster size (in sector)
  548.         mulu    d1,d0
  549.         move.l  (a0),d1                 ; free cluster
  550.         mulu    d1,d0                   ; free space in bytes
  551.         rts
  552.  
  553. * ---------------------- DIR --------------------------------------------- *
  554.  
  555. do_dir:
  556.  
  557. * build directory and display directory to the screen
  558.  
  559.         movea.l arg2,a0
  560.         tst.b   (a0)                    ; pathname in command string ?
  561.         bne.s   doD_0
  562.         lea     def_p,a0                ; no -> use default pathname
  563.  
  564. doD_0:  lea     work,a1                 ; copy pathname
  565.         bsr.w   str_copy
  566.         cmpi.b  #'\',-1(a1)             ; ended by backslash ?
  567.         beq.s   doD_do
  568.         move.b  #'\',(a1)+              ; no -> add backslash
  569.         clr.b   (a1)
  570.  
  571. doD_do: lea     dir_of,a0               ; 'Directory of '
  572.         bsr.w   prt_str
  573.         lea     work,a0                 ; pathname -> default or in argument
  574.         bsr.w   prt_str
  575.  
  576.         lea     any,a0
  577.         bsr.w   str_copy                ; add "*.*"
  578.  
  579.         lea     two_ln,a0               ; 2 new line
  580.         bsr.w   prt_str
  581.         bra.w   directory               ; no -> display directory
  582.  
  583. * ------------------------------------------------------------------------ *
  584.  
  585. directory:
  586.  
  587. * display directory info to the screen. pathname hold in 'work'
  588. * register not affected
  589.  
  590.         movem.l d0-d4/a0-a4,-(sp)
  591.  
  592. * first get dta buffer address
  593.  
  594.         move.w  #$2F,-(sp)              ; function number: Fgetdta
  595.         trap    #GEMDOS                 ; get disk transfert address
  596.         addq.l  #2,sp                   ; update stack
  597.         move.l  d0,a3                   ; save dta address
  598.  
  599. * second search for the first file in the directory
  600.  
  601.         move.w  #-1,-(sp)               ; file affribute: any kind
  602.         pea     work                    ; filemame
  603.         move.w  #$4E,-(sp)              ; function number: Fsfirst
  604.         trap    #GEMDOS
  605.         addq.l  #8,sp                   ; update stack
  606.         tst.w   d0                      ; file exist ?
  607.         bne.w   dir_x1                  ; no -> exit
  608.  
  609.         lea     work,a4                 ; one directory entry buffer
  610.         bsr.w   get_dir                 ; get first name, size, date, time
  611.  
  612. dir_lp: move.b  #CR,(a4)+               ; end of line
  613.         move.b  #LF,(a4)+
  614.         clr.b   (a4)
  615.  
  616.         lea     work,a4                 ; reset a4
  617.         movea.l a4,a0
  618.         bsr.w   prt_str                 ; print this line
  619.  
  620. * now try an other entry in the directory
  621.  
  622.         lea     30(a3),a0               ; filemame in dta
  623.         moveq   #12-1,d1                ; 12 bytes in the filename
  624. dirERA: clr.b   (a0)+                   ; erase old filename
  625.         dbra    d1,dirERA
  626.  
  627.         move.w  #$4F,-(sp)              ; function number: Fsnext
  628.         trap    #GEMDOS
  629.         addq.l  #2,sp                   ; update stack
  630.         tst.w   d0                      ; file exist ?
  631.         bne.w   dir_x2                  ; no -> exit
  632.         bsr.w   get_dir                 ; get next name, size, date, time
  633.         bra.s   dir_lp                  ; loop while end of directory
  634.  
  635. dir_x1: cmpi.w  #-33,d0                 ; -33 mean 'file not found'
  636.         bne.s   dirERR                  ; other value is error
  637.         lea     nofile,a0               ; 'No file in this directory'
  638. dir_NO: move.b  (a0)+,(a4)+             ; copy
  639.         bne.s   dir_NO
  640.         subq.l  #1,a4
  641.         movem.l (sp)+,d0-d4/a0-a4
  642.         rts
  643.  
  644. dir_x2: cmpi.w  #-49,d0                 ; -49 mean 'no more files'
  645.         bne.s   dirERR                  ; other value is error
  646.         movem.l (sp)+,d0-d4/a0-a4
  647.         rts
  648.  
  649. dirERR: move.w  d0,err_no               ; display error message
  650.         movem.l (sp)+,d0-d4/a0-a4
  651.         rts
  652.  
  653. * ------------------------------------------------------------------------ *
  654.  
  655. get_dir:
  656.  
  657. * get filename, size, date and time, and put info into the string pointed
  658. * by a4. upon return a4 point to the last char of info plus one.
  659. * need 44 bytes by file. register affected d0-d4/a0/a4
  660.  
  661. * file name -------------------------------------------------------------- *
  662.  
  663.         lea     30(a3),a0               ; filemame in dta
  664.         moveq   #12-1,d1                ; 12 bytes in the filename
  665.  
  666. g_name: move.b  (a0)+,d0                ; copy filename
  667.         beq.s   g_null                  ; if null char -> replace by blank
  668.         cmpi.b  #'.',d0                 ; dot ?
  669.         beq.s   g_dot                   ; yes -> special case
  670.         move.b  d0,(a4)+                ; else -> just copy the char
  671. gname2: dbra    d1,g_name
  672.         bra.s   g_dir2
  673.  
  674. g_null: move.b  #SPACE,(a4)+            ; replace by blank char
  675.         dbra    d1,g_name
  676.         bra.s   g_dir2
  677.  
  678. g_dot:  move.b  #SPACE,(a4)+            ; replace dot by blank char and
  679.         cmpi.w  #3,d1                   ; fill will black up to the 3 last
  680.         bls.s   gname2                  ; char of the filename
  681.         dbra    d1,g_dot
  682.  
  683.  
  684. g_dir2: move.b  #SPACE,(a4)+            ; two blanck space
  685.         move.b  #SPACE,(a4)+
  686.  
  687. * file size or file type (for subdirectory or volume label) -------------- *
  688.  
  689.         btst    #3,21(a3)               ; volume label ?
  690.         bne.s   g_vol
  691.  
  692.         btst    #4,21(a3)               ; subdirectory ?
  693.         bne.s   g_sub
  694.  
  695.         move.l  26(a3),d0               ; file size
  696.         moveq   #10,d1                  ; base 10
  697.         moveq   #8,d2                   ; display 8 char
  698.         movea.l a4,a0                   ; there
  699.         moveq   #SPACE,d3               ; replace leading zero by blank
  700.         bsr.w   l_to_a
  701.         addq.l  #8,a4
  702.         move.b  #SPACE,(a4)+            ; two more blanck space
  703.         move.b  #SPACE,(a4)+
  704.         bra.s   g_date
  705.  
  706. g_vol:  lea     volume,a0
  707. g_vol1: move.b  (a0)+,(a4)+             ; copy '<<VOL>> '
  708.         bne.s   g_vol1
  709.         subq.l  #1,a4
  710.         move.b  #SPACE,(a4)+            ; two more blanck space
  711.         move.b  #SPACE,(a4)+
  712.         bra.s   g_date
  713.  
  714. g_sub:  lea     subdir,a0
  715. g_sub1: move.b  (a0)+,(a4)+             ; copy '<<DIR>> '
  716.         bne.s   g_sub1
  717.         subq.l  #1,a4
  718.         move.b  #SPACE,(a4)+            ; two more blanck space
  719.         move.b  #SPACE,(a4)+
  720.  
  721. * file date -------------------------------------------------------------- *
  722.  
  723. g_date: move.w  24(a3),d4               ; date stamp
  724.         moveq   #0,d0
  725.         move.w  d4,d0
  726.         lsr.w   #5,d0                   ; month -> bits 5-8
  727.         and.w   #%1111,d0               ; 4 bits only
  728.         moveq   #10,d1                  ; base 10
  729.         moveq   #2,d2                   ; display 2 char
  730.         movea.l a4,a0                   ; there
  731.         moveq   #'0',d3                 ; replace leading zero by zero!
  732.         bsr.w   l_to_a
  733.         addq.l  #2,a4
  734.         move.b  #'-',(a4)+              ; one dash
  735.  
  736.         moveq   #0,d0
  737.         move.w  d4,d0                   ; day -> bits 0-4
  738.         and.w   #%11111,d0              ; 5 bits only
  739.         moveq   #10,d1                  ; base 10
  740.         moveq   #2,d2                   ; display 2 char
  741.         movea.l a4,a0                   ; there
  742.         moveq   #'0',d3                 ; replace leading zero by zero!
  743.         bsr.w   l_to_a
  744.         addq.l  #2,a4
  745.         move.b  #'-',(a4)+              ; one dash
  746.  
  747.         moveq   #0,d0
  748.         move.w  d4,d0
  749.         moveq   #9,d1
  750.         lsr.w   d1,d0                   ; year -> bits 9-15
  751.         and.w   #%1111111,d0            ; 7 bits only
  752.         addi.w  #1980,d0                ; plus base year
  753.         moveq   #10,d1                  ; base 10
  754.         moveq   #4,d2                   ; display 4 char
  755.         movea.l a4,a0                   ; there
  756.         moveq   #'0',d3                 ; replace leading zero by zero!
  757.         bsr.w   l_to_a
  758.         addq.l  #4,a4
  759.         move.b  #SPACE,(a4)+            ; two more blanck space
  760.         move.b  #SPACE,(a4)+
  761.  
  762. * file time -------------------------------------------------------------- *
  763.  
  764.         moveq   #0,d4
  765.         move.w  22(a3),d4               ; time stamp
  766.  
  767.         moveq   #0,d0
  768.         move.w  d4,d0
  769.         moveq   #11,d1
  770.         lsr.w   d1,d0                   ; hour -> bits 11-15
  771.         and.w   #%11111,d0              ; 5 bits only
  772.         cmpi.w  #12,d0                  ; AM or PM ?
  773.         bls.s   g_hour
  774.         subi.w  #12,d0                  ; here PM
  775.         bset    #31,d4                  ; PM flag
  776. g_hour: moveq   #10,d1                  ; base 10
  777.         moveq   #2,d2                   ; display 2 char
  778.         movea.l a4,a0                   ; there
  779.         moveq   #'0',d3                 ; replace leading zero by zero!
  780.         bsr.w   l_to_a
  781.         addq.l  #2,a4
  782.         move.b  #':',(a4)+              ; one colon
  783.  
  784.         moveq   #0,d0
  785.         move.w  d4,d0                   ; minute -> bits 5-10
  786.         lsr.w   #5,d0
  787.         and.w   #%111111,d0             ; 5 bits only
  788.         moveq   #10,d1                  ; base 10
  789.         moveq   #2,d2                   ; display 2 char
  790.         movea.l a4,a0                   ; there
  791.         moveq   #'0',d3                 ; replace leading zero by zero!
  792.         bsr.w   l_to_a
  793.         addq.l  #2,a4
  794.         move.b  #SPACE,(a4)+            ; one more space
  795.  
  796.         moveq   #'A',d0
  797.         btst    #31,d4                  ; AM or PM ?
  798.         beq.s   g_AMPM
  799.         moveq   #'P',d0
  800. g_AMPM: move.b  d0,(a4)+                ; fill with AM or PM
  801.         move.b  #'M',(a4)+
  802.         rts
  803.  
  804. *----------------------- COPY ---------------------------------------------*
  805.  
  806. do_copy:
  807.  
  808. * copy file (source pointed 'arg2' to destination pointed bu 'arg3')
  809.  
  810.         movea.l arg2,a0
  811.         bsr.w   split_arg               ; split argument in 2 parts
  812.  
  813.         movea.l arg1,a0
  814.         tst.b   (a0)                    ; pathname in first argument ?
  815.         bne.s   doC_1
  816.         move.w  #MISS,err_no
  817.         bra.w   doC_er                  ; no -> error -> exit
  818.  
  819. doC_1:  lea     work,a1                 ; copy first argument
  820.         bsr.w   str_copy
  821.  
  822. * next get last colon/backslack symbol to set the source pathname 
  823.  
  824. doC_p:  move.b  -(a1),d0
  825.         cmpi.b  #'\',d0                 ; folder symbol ?
  826.         beq.s   doC_s
  827.         cmpi.b  #':',d0                 ; disk symbol ?
  828.         beq.s   doC_s
  829.         cmpa.l  #work,a1
  830.         bhi.s   doC_p                   ; until start of first argument
  831.  
  832.         bra.s   doC_2                   ; no source pathname -> use default
  833.  
  834. doC_s:  addq.l  #1,a1
  835.         clr.b   (a1)
  836.         lea     work,a0                 ; pathname
  837.         suba.l  a0,a1
  838.         move.l  a1,d0
  839.         add.l   d0,arg1                 ; keep only filename for future use
  840.         bsr.w   set_path                ; set source pathname
  841.         tst.w   err_no                  ; error ?
  842.         bne.s   doC_er                  ; yes -> exit right now
  843.  
  844. * if second argument is empty use default pathname
  845. * else if the drive is not specified use default drive
  846.  
  847. doC_2:  lea     work,a1                 ; destination to copy second arg.
  848.         movea.l arg2,a0
  849.         movea.l a0,a2
  850.         tst.b   (a0)                    ; empty ?
  851.         beq.s   doC_e
  852.         cmpi.b  #':',1(a0)              ; drive specified ?
  853.         beq.s   doC_ok
  854.         move.b  def_p,(a1)+             ; default drive letter
  855.         move.b  #':',(a1)+              ; plus colon
  856.         bra.s   doC_ok
  857.  
  858. doC_e:  lea     def_p,a0                ; default pathname
  859.  
  860. doC_ok: bsr.w   str_copy
  861.  
  862.         moveq   #0,d4                   ; 'need add filename to dest.' flag
  863.         movea.l a1,a4                   ; save end of argument
  864.         move.b  -1(a1),d0
  865.         cmpi.b  #'\',d0                 ; last char is folder symbol ?
  866.         beq.s   doCadd                  ; yes -> need add filename to dest.
  867.         cmpi.b  #':',d0                 ; last char is disk symbol ?
  868.         bne.s   doC_3                   ; no -> no need add anything
  869.  
  870. doCadd: moveq   #-1,d4                  ; need add filename to dest.
  871.  
  872. doC_3:  lea     one_ln,a0               ; 1 new line
  873.         bsr.w   prt_str
  874.         bsr.w   copy                    ; copy and display copied file
  875.         tst.w   err_no                  ; error ?
  876.         bne.s   doC_er
  877.         lea     one_ln,a0               ; 1 new line
  878.         bsr.w   prt_str
  879.  
  880. doC_er: lea     def_p,a0                ; restore old current directory
  881.         bra.w   set_path                ; set current path
  882.  
  883. *--------------------------------------------------------------------------*
  884.  
  885. copy:   bsr.w   mem_all                 ; reserve all free memory
  886.  
  887. * first get dta buffer address
  888.  
  889.         move.w  #$2F,-(sp)              ; function number: Fgetdta
  890.         trap    #GEMDOS                 ; get disk transfert address
  891.         addq.l  #2,sp                   ; update stack
  892.         move.l  d0,a3                   ; save dta address
  893.  
  894. * now get a first file in the source directory
  895.  
  896.         movea.l arg1,a0                 ; if no filename i.e. type A:
  897.         tst.b   (a0)                    ; or A:\NNN\ then get any file
  898.         bne.s   c_1st
  899.         move.l  #any,arg1
  900.  
  901. c_1st:  clr.w   -(sp)                   ; file affribute: normal
  902.         move.l  arg1,-(sp)              ; source filemame
  903.         move.w  #$4E,-(sp)              ; function number: Fsfirst
  904.         trap    #GEMDOS
  905.         addq.l  #8,sp                   ; update stack
  906.         tst.w   d0                      ; file exist ?
  907.         bne.s   c_x1                    ; no -> error
  908.  
  909. * next search for another file in the source directory
  910.  
  911. c_next: bsr.w   copy_file               ; copy previous one
  912.         tst.w   err_no                  ; error ?
  913.         bne.s   c_x3                    ; yes -> release used memory, exit
  914.  
  915.         move.w  #$4F,-(sp)              ; function number: Fsnext
  916.         trap    #GEMDOS
  917.         addq.l  #2,sp                   ; update stack
  918.         tst.w   d0                      ; file exist ?
  919.         bne.w   c_x2                    ; no -> exit
  920.         bra.s   c_next                  ; loop while end of directory
  921.  
  922. c_x1:   move.w  d0,err_no
  923.         movea.l m_free,a0
  924.         bra.w   Mfree                   ; release used memory
  925.  
  926. c_x2:   cmpi.w  #-49,d0                 ; -49 mean 'no more files'
  927.         bne.s   c_x1                    ; other value is error
  928. c_x3:   movea.l m_free,a0
  929.         bra.w   Mfree                   ; release used memory
  930.  
  931. *--------------------------------------------------------------------------*
  932.  
  933. copy_file:
  934.  
  935. * copy one file from source in dta (pointed by a3) to destination
  936. * (pointed arg2).
  937.  
  938.         lea     copy_s,a0
  939.         bsr.w   prt_str
  940.         lea     30(a3),a0               ; filemame in dta
  941.         bsr.w   prt_str                 ; display filename
  942.  
  943.         bsr.w   open                    ; open source file      
  944.         tst.w   err_no
  945.         bpl.s   c_f_r                   ; (read)
  946.         rts                             ; error -> exit
  947.  
  948. c_f_r:  move.l  26(a3),d0               ; file size
  949.         cmp.l   amount,d0               ; file to big ?
  950.         bcc.w   c_f_m                   ; (memory problem)
  951.         movea.l m_free,a0               ; buffer
  952.         bsr.w   read                    ; read the file
  953.         move.l  d0,d6                   ; save file size
  954.         tst.w   err_no
  955.         bmi.s   c_f_x
  956.  
  957.         bsr.w   close                   ; close the file
  958.         tst.w   err_no
  959.         bpl.s   c_f_d                   ; (destination)
  960.         rts
  961.  
  962. c_f_d:  tst.w   d4                      ; need add filename to dest. ?
  963.         beq.s   c_f_c                   ; no -> just create
  964.         lea     30(a3),a0               ; filemame in dta
  965.         movea.l a4,a1                   ; add filename there
  966.         bsr.w   str_copy
  967.  
  968. c_f_c:  lea     work,a0
  969.         bsr.w   create                  ; create destination file
  970.         tst.w   err_no
  971.         bpl.s   c_f_w                   ; (write)
  972.         rts
  973.  
  974. c_f_w:  move.l  d6,d0                   ; file size
  975.         movea.l m_free,a0               ; buffer
  976.         bsr.w   write                   ; write the file
  977.         cmp.l   d0,d6                   ; room for the file ?
  978.         beq.w   close                   ; yes -> close the file and exit
  979.  
  980.         move.w  #FULL,err_no            ; no -> disk full
  981.         rts
  982. c_f_m:  move.w  #NO_MEM,err_no
  983. c_f_x:  bra.w   close                   ; close the file and exit
  984.  
  985. * ---------------------- DEL --------------------------------------------- *
  986.  
  987. do_del:
  988.  
  989. * delete file
  990.  
  991.         movea.l arg2,a0
  992.         tst.b   (a0)                    ; pathname in command string ?
  993.         bne.s   do_D_1
  994. do_D_m: move.w  #MISS,err_no            ; no -> error -> exit
  995.         rts
  996.  
  997. do_D_1: movea.l arg2,a0
  998.         lea     work,a1                 ; copy first argument
  999.         bsr.w   str_copy
  1000.  
  1001. * get last colon/backslack symbol
  1002.  
  1003. do_D_p: move.b  -(a1),d0
  1004.         cmpi.b  #'\',d0                 ; folder symbol ?
  1005.         beq.s   do_D_s
  1006.         cmpi.b  #':',d0                 ; disk symbol ?
  1007.         beq.s   do_D_s
  1008.         cmpa.l  #work,a1
  1009.         bhi.s   do_D_p                  ; until start of first argument
  1010.  
  1011.         bra.s   do_D_2                  ; no source pathname -> use default
  1012.  
  1013. do_D_s: addq.l  #1,a1
  1014.         clr.b   (a1)
  1015.         lea     work,a0                 ; pathname
  1016.         suba.l  a0,a1
  1017.         move.l  a1,d0
  1018.         add.l   d0,arg2                 ; keep only filename for future use
  1019.         movea.l arg2,a1
  1020.         tst.b   (a1)                    ; nothing in filename ?
  1021.         beq.s   do_D_m
  1022.  
  1023.         bsr.w   set_path                ; set pathname
  1024.         tst.w   err_no                  ; error ?
  1025.         bne.s   do_Der                  ; yes -> exit right now
  1026.  
  1027. do_D_2: bsr.w   del_file                ; delete files
  1028.  
  1029. do_Der: lea     def_p,a0                ; restore old current directory
  1030.         bra.w   set_path                ; set current path
  1031.  
  1032. * ------------------------------------------------------------------------ *
  1033.  
  1034. del_file:
  1035.  
  1036. * delete file
  1037.  
  1038.         clr.b   alldel                  ; clear 'delete all flag'
  1039.         clr.b   cancel                  ; clear 'cancel delete' flag
  1040.  
  1041. * first get dta buffer address
  1042.  
  1043.         move.w  #$2F,-(sp)              ; function number: Fgetdta
  1044.         trap    #GEMDOS                 ; get disk transfert address
  1045.         addq.l  #2,sp                   ; update stack
  1046.         move.l  d0,a3                   ; save dta address
  1047.  
  1048. * second search for the first file in the directory
  1049.  
  1050.         clr.w   -(sp)                   ; file affribute: normal
  1051.         move.l  arg2,-(sp)              ; filename
  1052.         move.w  #$4E,-(sp)              ; function number: Fsfirst
  1053.         trap    #GEMDOS
  1054.         addq.l  #8,sp                   ; update stack
  1055.         tst.w   d0                      ; file exist ?
  1056.         bne.s   delERR                  ; no -> exit
  1057.         bsr.w   one_delete              ; delete one file
  1058.         tst.w   err_no                  ; error ?
  1059.         bne.s   delERR
  1060.         tst.b   cancel                  ; cancel ?
  1061.         bne.s   del_c
  1062.  
  1063. * now try an other entry in the directory
  1064.  
  1065. del_lp: move.w  #$4F,-(sp)              ; function number: Fsnext
  1066.         trap    #GEMDOS
  1067.         addq.l  #2,sp                   ; update stack
  1068.         tst.w   d0                      ; file exist ?
  1069.         bne.w   del_x                   ; no -> exit
  1070.         bsr.w   one_delete              ; get next name, size, date, time
  1071.         tst.w   err_no                  ; error ?
  1072.         bne.s   delERR
  1073.         tst.b   cancel                  ; cancel ?
  1074.         bne.s   del_c
  1075.         bra.s   del_lp                  ; loop while end of directory
  1076.  
  1077. del_x:  cmpi.w  #-49,d0                 ; -49 mean 'no more files'
  1078.         bne.s   delERR                  ; other value is error
  1079.         rts
  1080.  
  1081. delERR: move.w  d0,err_no               ; display error message
  1082. del_c:  rts
  1083.  
  1084. *--------------------------------------------------------------------------*
  1085.  
  1086. one_delete:
  1087.  
  1088. * ask to delete the file in dta (pointed by a3) and delete all file,
  1089. * the current file or exit according to the answer
  1090.  
  1091.         lea     del_s1,a0               ; 'Delete '
  1092.         bsr.w   prt_str
  1093.         lea     30(a3),a0               ; filemame in dta
  1094.         bsr.w   prt_str
  1095.         tst.b   alldel                  ; delete all file ?
  1096.         bne.w   delete                  ; yes -> skip question and answer
  1097.         tst.b   exeBAT                  ; executing batch file
  1098.         bne.w   delete                  ; yes -> skip too
  1099.  
  1100.         lea     del_s2,a0               ; ' ? (Yes, No, All, Cancel) '
  1101.         bsr.w   prt_str
  1102.         bsr.w   chr_in                  ; get answer
  1103.         cmpi.b  #'a',d0
  1104.         bcs.s   oneD_u
  1105.         sub.b   #'a'-'A',d0             ; make it upper case
  1106.  
  1107. oneD_u: cmpi.b  #'Y',d0
  1108.         beq.w   oneD_Y
  1109.         cmpi.b  #'N',d0
  1110.         beq.s   oneD_N
  1111.         cmpi.b  #'A',d0
  1112.         beq.s   oneD_A
  1113.         cmpi.b  #'C',d0
  1114.         beq.s   oneD_C
  1115.         bra.s   one_delete              ; get one clear answer
  1116.  
  1117. oneD_A: st      alldel                  ; set 'delete all flag'
  1118. oneD_Y: lea     30(a3),a0               ; filemame in dta
  1119.         bra.w   delete
  1120.  
  1121. oneD_C: st      cancel                  ; set 'cancel delete' flag
  1122. oneD_N: rts
  1123.  
  1124. * ---------------------- REN --------------------------------------------- *
  1125.  
  1126. do_ren:
  1127.  
  1128. * rename file
  1129.  
  1130.         movea.l arg2,a0
  1131.         bsr.w   split_arg               ; split argument in 2 parts
  1132.  
  1133.         movea.l arg1,a0
  1134.         tst.b   (a0)                    ; first argument must be a filename
  1135.         beq.s   doRer1
  1136.         movea.l arg2,a1
  1137.         tst.b   (a1)                    ; secong argument also
  1138.         beq.s   doRer1
  1139.  
  1140.         move.l  a1,-(sp)                ; new filename
  1141.         move.l  a0,-(sp)                ; filename to rename
  1142.         clr.w   -(sp)                   ; dummy
  1143.         move.w  #$56,-(sp)              ; 'Frename' function
  1144.         trap    #GEMDOS
  1145.         adda.w  #12,sp
  1146.         tst.w   d0                      ; error ?
  1147.         bne.s   doRer2
  1148.         rts
  1149.  
  1150. doRer1: move.w  #MISS,err_no            ; missing argument
  1151.         rts
  1152.  
  1153. doRer2: move.w  #NO_REN,err_no          ; cannot rename
  1154.         rts
  1155.  
  1156. * ---------------------- PATH -------------------------------------------- *
  1157.  
  1158. do_path:
  1159.  
  1160. * set current pathname
  1161.  
  1162.         movea.l arg2,a0
  1163.         tst.b   (a0)                    ; pathname in command string ?
  1164.         bne.s   do_P_1
  1165.         move.w  #MISS,err_no            ; no -> error -> exit
  1166.         rts
  1167.  
  1168. do_P_1: lea     def_p,a0
  1169.         clr.b   3(a0)                   ; keep only A:\
  1170.         bsr.w   set_path                ; to reset (old) drive pathname
  1171.         movea.l arg2,a0
  1172.         bsr.w   set_path                ; do it
  1173.         lea     def_p,a0                ; get complete pathname
  1174.         bra.w   get_path
  1175.  
  1176. * ---------------------- STOP -------------------------------------------- *
  1177.  
  1178. do_stop:
  1179.  
  1180. * stop batch file execution
  1181.  
  1182.         clr.b   exeBAT                  ; 'executing batch file now' flag
  1183.         rts
  1184.  
  1185. * ---------------------- WRITE ------------------------------------------- *
  1186.  
  1187. do_write:
  1188.  
  1189. * display message to the screen
  1190.  
  1191.         movea.l arg2,a0
  1192.         tst.b   (a0)                    ; pathname in command string ?
  1193.         bne.s   doW_1
  1194.         move.w  #MISS,err_no            ; no -> error -> exit
  1195.         rts
  1196.  
  1197. doW_1:  lea     one_ln,a0
  1198.         bsr.w   prt_str
  1199.         lea     revON,a0
  1200.         bsr.w   prt_str
  1201.         movea.l arg2,a0
  1202.         bsr.w   prt_str                 ; do it
  1203.         lea     revOFF,a0
  1204.         bra.w   prt_str
  1205.  
  1206. * ---------------------- SHOW/PRINT -------------------------------------- *
  1207.  
  1208. * output the file to the screen or printer
  1209. * key 'Q', 'q' or UNDO to stop and exit, other key to do a pause
  1210.  
  1211. do_print:
  1212.         move.w  #0,d4                   ; printer
  1213.         bsr.w   status                  ; printer ready ?
  1214.         tst.w   err_no
  1215.         beq.s   doSP_0
  1216.         rts                             ; no -> exit
  1217.  
  1218. do_show:
  1219.         move.w  #2,d4                   ; screen
  1220.  
  1221. doSP_0: moveq   #0,d5                   ; hold byte to show/print
  1222.         moveq   #0,d6                   ; logical column
  1223.  
  1224.         movea.l arg2,a0
  1225.         tst.b   (a0)                    ; pathname in command string ?
  1226.         bne.s   doSP_o
  1227.         move.w  #MISS,err_no            ; no -> error -> exit
  1228.         rts
  1229.  
  1230. doSP_o: bsr.w   open                    ; open source file      
  1231.         tst.w   err_no
  1232.         bpl.s   doSP_r                  ; (read)
  1233.         rts                             ; error -> exit
  1234.  
  1235. doSP_r: moveq   #80,d0                  ; read max. 80 bytes
  1236.         lea     work,a0                 ; in the work buffer
  1237.         bsr.w   read                    ; read the file
  1238.         tst.w   err_no                  ; error ?
  1239.         bmi.w   close                   ; yes -> close the file and exit
  1240.         tst.l   d0                      ; no byte read ?
  1241.         beq.w   close                   ; yes -> close the file and exit
  1242.  
  1243.         lea     work,a3                 ; hold the read file segment
  1244.         move.l  d0,d3                   ; number of bytes read
  1245.         subq.l  #1,d3
  1246.  
  1247. doSPlp: move.b  (a3)+,d5                ; byte read
  1248.         cmpi.b  #CR,d5                  ; carriage return ?
  1249.         beq.s   doSPcr
  1250.         cmpi.b  #LF,d5                  ; line feed ?
  1251.         beq.s   doSPlf
  1252.         cmpi.b  #TAB,d5                 ; TAB ?
  1253.         beq.s   doSPtb
  1254.  
  1255. doSP_n: bsr.w   output                  ; show/print
  1256.         tst.w   err_no                  ; error ?
  1257.         bne.w   close                   ; yes -> close the file and exit
  1258.  
  1259. doSP_u: addq.l  #1,d6                   ; update logical column
  1260.         dbra    d3,doSPlp
  1261.         bra.s   doSP_r                  ; loop while end of file
  1262.  
  1263. doSPtb: divu    #8,d6                   ; logical column/8
  1264.         swap    d6                      ; remaining in d6
  1265.         moveq   #8,d0
  1266.         sub.w   d6,d0                   ; number of blank to output
  1267.         subq.w  #1,d0
  1268.         move.w  d0,d6
  1269.  
  1270. doSPsp: moveq   #SPACE,d5
  1271.         bsr.w   output                  ; output the blank
  1272.         tst.w   err_no                  ; error ?
  1273.         bne.w   close                   ; yes -> close the file and exit
  1274.         bsr.w   pause                   ; get some input from user
  1275.         tst.w   d0                      ; exit ?
  1276.         bne.w   close                   ; yes -> close the file and exit
  1277.         dbra    d6,doSPsp
  1278.         moveq   #-1,d6                  ; reset logical column
  1279.         bra.s   doSP_u
  1280.  
  1281. doSPcr: moveq   #-1,d6                  ; reset logical column
  1282.         cmpi.b  #LF,(a3)                ; next is line feed ?
  1283.         beq.s   doSP_n                  ; yes -> normal show/print
  1284.         bsr.w   output                  ; else -> output the CR
  1285.         tst.w   err_no                  ; error ?
  1286.         bne.w   close                   ; yes -> close the file and exit
  1287.         moveq   #LF,d5
  1288.         bra.s   doSP_n                  ; and output LF too
  1289.  
  1290. doSPlf: moveq   #-1,d6                  ; reset logical column
  1291.         cmpi.b  #CR,-2(a3)              ; previous is carriage return ?
  1292.         beq.s   doSP_n                  ; yes -> normal show/print
  1293.         moveq   #CR,d5
  1294.         bsr.w   output                  ; else -> output the CR
  1295.         tst.w   err_no                  ; error ?
  1296.         bne.w   close                   ; yes -> close the file and exit
  1297.         moveq   #LF,d5
  1298.         bra.s   doSP_n                  ; and output LF too
  1299.  
  1300. *--------------------------------------------------------------------------*
  1301.  
  1302. output:
  1303.  
  1304. * output char in d5.w to the device no. d4.w
  1305.  
  1306.         move.w  d5,-(sp)                ; byte read
  1307.         move.w  d4,-(sp)                ; device
  1308.         move.w  #3,-(sp)                ; 'Bconout' functiom
  1309.         trap    #BIOS
  1310.         addq.l  #6,sp
  1311.         rts
  1312.  
  1313. *--------------------------------------------------------------------------*
  1314.  
  1315. status:
  1316.  
  1317. * check printer status.
  1318.  
  1319.         move.w  d4,-(sp)                ; device
  1320.         move.w  #8,-(sp)                ; 'Bcostat' functiom
  1321.         trap    #BIOS
  1322.         addq.l  #4,sp
  1323.         tst.w   d0                      ; printer ready ?
  1324.         bne.w   stat_x
  1325.         move.w  #NO_PRT,err_no          ; no -> error
  1326. stat_x: rts
  1327.  
  1328. *--------------------------------------------------------------------------*
  1329.  
  1330. pause:
  1331.  
  1332. * if a user keyboard input is available, then exit for 'Q', 'q' or Undo
  1333. * key and wait next iput for other key. In the first case exit with d0.w set
  1334. * else d0.w is clear. if no input is available then exit immediately
  1335. * with d0.w clear
  1336.  
  1337.         move.w  #$B,-(sp)               ; 'Cconis' function
  1338.         trap    #GEMDOS
  1339.         addq.l  #2,sp                   ; update stack
  1340.         tst.w   d0
  1341.         beq.s   pauseX                  ; no char available -> exit
  1342.  
  1343.         bsr.w   do_wait                 ; get input
  1344.         cmpi.b  #'Q',d0                 ; 'Q' ?
  1345.         beq.s   pauseQ
  1346.         cmpi.b  #'q',d0                 ; 'q' ?
  1347.         beq.s   pauseQ
  1348.         swap    d0
  1349.         cmpi.b  #$61,d0                 ; UNDO ?
  1350.         beq.s   pauseQ
  1351.  
  1352.         bsr.w   do_wait                 ; wait until a next input
  1353.         moveq   #0,d0
  1354.         rts
  1355.  
  1356. pauseQ: moveq   #-1,d0
  1357. pauseX: rts
  1358.  
  1359. * ---------------------- WAIT -------------------------------------------- *
  1360.  
  1361. do_wait:
  1362.  
  1363. * wait for next keyboard input in d0.l
  1364.  
  1365.         move.w  #7,-(sp)                ; 'Crawcin' function
  1366.         trap    #GEMDOS                 ; read the char
  1367.         addq.l  #2,sp                   ; update stack
  1368.         rts
  1369.  
  1370. * ---------------------- IF_EXIST and IF_NOT_EXIST ----------------------- *
  1371.  
  1372. * execute the next command only if file exist/not_exist and only when
  1373. * executing a batch file
  1374.  
  1375. do_if:  moveq   #0,d4
  1376.         bra.s   doI_0
  1377.  
  1378. do_if_not:
  1379.  
  1380.         moveq   #-1,d4
  1381.  
  1382. doI_0:  tst.b   exeBAT                  ; executing batch file ?
  1383.         bne.s   doI_1
  1384.         rts                             ; no -> exit
  1385.  
  1386. doI_1:  movea.l arg2,a0
  1387.         bsr.w   split_arg               ; split argument in 2 parts
  1388.  
  1389.         movea.l arg1,a0
  1390.         tst.b   (a0)                    ; first argument must be a filename
  1391.         beq.s   doI_er
  1392.         movea.l arg2,a1
  1393.         tst.b   (a1)                    ; secong argument must be command
  1394.         beq.s   doI_er
  1395.  
  1396.         move.w  #-1,-(sp)               ; file affribute: all kind
  1397.         move.l  a0,-(sp)                ; filemame
  1398.         move.w  #$4E,-(sp)              ; function number: Fsfirst
  1399.         trap    #GEMDOS
  1400.         addq.l  #8,sp                   ; update stack
  1401.         tst.w   d0                      ; file exist ?
  1402.         bne.s   doI_no                  ; no -> if 'do_if_not' -> ok
  1403.  
  1404.         tst.b   d4                      ; yes -> if 'do_if' -> ok
  1405.         beq.s   doI_x
  1406.         rts                             ; else -> do nothing
  1407.  
  1408. doI_no: tst.b   d4                      ; if 'do_if_not' -> ok
  1409.         bne.s   doI_x
  1410.         rts                             ; else -> do nothing
  1411.  
  1412. * here we must execute the command following the filename
  1413. * to do this we must reset the 'batPTR' pointer, actualy pointing to
  1414. * the next batch line. 'batPRV' is the pointer the start of the line
  1415. * holding the command to be executing
  1416.  
  1417. doI_x:  movea.l batPRV,a0               ; our batch line
  1418.         bsr.w   split_arg               ; split in 2 arguments
  1419.         movea.l arg2,a0                 ; skip first command
  1420.         bsr.w   split_arg               ; split again, skip filename
  1421.         move.l  arg2,batPTR             ; our command begin there
  1422.         rts
  1423.  
  1424. doI_er: move.w  #MISS,err_no
  1425.         rts
  1426.  
  1427. * ---------------------- CLS -------------------------------------------- *
  1428.  
  1429. do_cls:
  1430.  
  1431. * clear screen
  1432.  
  1433.         lea     cls_s,a0
  1434.         bra.w   prt_str
  1435.  
  1436. * ---------------------- ? (question mark -> help) ---------------------- *
  1437.  
  1438. do_inf:
  1439.  
  1440. * display the list of keyword
  1441.  
  1442.         lea     key_w,a1                ; the list
  1443.  
  1444.         moveq   #4,d2                   ; 5 keywords by line
  1445.         lea     one_ln,a0               ; one line
  1446.         bsr.w   prt_str
  1447.  
  1448. do_Ilp: tst.b   (a1)                    ; end of list ?
  1449.         beq.s   do_I_x                  ; yes -> exit
  1450.  
  1451.         movea.l a1,a0
  1452.         bsr.w   prt_str                 ; show the keyword
  1453.  
  1454. do_I_c: tst.b   (a1)+                   ; how many char
  1455.         bne.s   do_I_c
  1456.         move.l  a1,d0
  1457.         sub.l   a0,d0                   ; number of char including the null
  1458.  
  1459.         moveq   #20,d1
  1460.         sub.w   d0,d1
  1461.         moveq   #SPACE,d0               ; use room of 20 char
  1462. do_Isp: bsr.w   ch_out                  ; remainning of room with blank
  1463.         dbra    d1,do_Isp
  1464.  
  1465.         bra.s   do_Ilp                  ; while end of list
  1466.  
  1467. do_I_x: lea     one_ln,a0               ; one line
  1468.         bra.w   prt_str
  1469.  
  1470. *--------------------------------------------------------------------------*
  1471. *--------------------------- I/O routine ----------------------------------*
  1472. *--------------------------------------------------------------------------*
  1473.  
  1474. close:
  1475.  
  1476. * close file of handle d7.w
  1477. * register affected d0-d2/a0-a2
  1478.  
  1479.         move.w  d7,-(sp)        ; file handle
  1480.         move.w  #$3E,-(sp)      ; function number 'Fclose'
  1481.         trap    #GEMDOS
  1482.         addq.l  #4,sp           ; update stack
  1483.         tst.l   d0              ; error ?
  1484.         bmi.s   clo_er
  1485.         rts
  1486.  
  1487. clo_er: move.w  d0,err_no       ; d0 < 0 is error
  1488.         rts
  1489.  
  1490. *--------------------------------------------------------------------------*
  1491.  
  1492. read:
  1493.  
  1494. * read d0.l bytes into the buffer pointed by a0 from the of the file
  1495. * of handle d7.w upon return d0.l hold the number of bytes read.
  1496. * register affected d0-d2/a0-a2
  1497.  
  1498.         move.l  a0,-(sp)        ; buffer
  1499.         move.l  d0,-(sp)        ; length of buffer
  1500.         move.w  d7,-(sp)        ; file handle
  1501.         move.w  #$3F,-(sp)      ; function number 'Fread'
  1502.         trap    #GEMDOS
  1503.         adda.w  #12,sp          ; update stack
  1504.         tst.l   d0              ; error ?
  1505.         bmi.s   rd_er
  1506.         rts
  1507.  
  1508. rd_er:  move.w  d0,err_no       ; d0 < 0 is error
  1509.         rts
  1510.  
  1511. *--------------------------------------------------------------------------*
  1512.  
  1513. write:
  1514.  
  1515. * write on file printer. a0 is the pointer to the text buffer
  1516. * d0.l the length of the text buffer and d7.w the file handle
  1517. * upon return d0.l hold the number of bytes written.
  1518. * register affected d0-d2/a0-a2
  1519.  
  1520.         move.l  a0,-(sp)        ; buffer
  1521.         move.l  d0,-(sp)        ; length of buffer
  1522.         move.w  d7,-(sp)        ; file handle
  1523.         move.w  #$40,-(sp)      ; function number 'Fwrite'
  1524.         trap    #GEMDOS
  1525.         adda.w  #12,sp          ; update stack
  1526.         tst.l   d0              ; error ?
  1527.         bmi.s   wr_er
  1528.         rts
  1529.  
  1530. wr_er:  move.w  d0,err_no       ; d0 < 0 is error
  1531.         rts
  1532.  
  1533. *--------------------------------------------------------------------------*
  1534.  
  1535. create:
  1536.  
  1537. * create (and open) a file on disk, nul terminated filename is pointed by a0
  1538. * upon return file handle hold on d7.w
  1539. * register affected d0-d2/d7/a0-a2
  1540.  
  1541.         clr.w   -(sp)           ; R/W status
  1542.         move.l  a0,-(sp)        ; address of pathname or filename
  1543.         move.w  #$3C,-(sp)      ; function number 'Fcreate'
  1544.         trap    #GEMDOS
  1545.         addq.l  #8,sp           ; update stack
  1546.         tst.l   d0              ; error ?
  1547.         bmi.s   cr_er
  1548.         move.w  d0,d7
  1549.         rts
  1550.  
  1551. cr_er:  move.w  d0,err_no       ; d0 < 0 is error
  1552.         rts
  1553.  
  1554. *--------------------------------------------------------------------------*
  1555.  
  1556. open:
  1557.  
  1558. * open a file on disk. read or write. upon return d7.w hold the file
  1559. * handle. a0 is the pointer to the null terminated filename string
  1560. * register affected d0-d2/d7/a0-a2
  1561.  
  1562.         move.w  #2,-(sp)        ; can be read or write
  1563.         move.l  a0,-(sp)        ; address of pathname or filename
  1564.         move.w  #$3D,-(sp)      ; function number 'Fopen'
  1565.         trap    #GEMDOS
  1566.         addq.l  #8,sp           ; update stack
  1567.         tst.l   d0              ; error ?
  1568.         bmi.s   opn_er
  1569.         move.w  d0,d7
  1570.         rts
  1571.  
  1572. opn_er: move.w  d0,err_no       ; d0 < 0 is error
  1573.         rts
  1574.  
  1575. *--------------------------------------------------------------------------*
  1576.  
  1577. delete:
  1578.  
  1579. * delete the file of filename pointed by a0 a null terminated string
  1580. * register affected d0-d2/a0-a2
  1581.  
  1582.         move.l  a0,-(sp)        ; address of pathname or filename
  1583.         move.w  #$41,-(sp)      ; function number 'Fdelete'
  1584.         trap    #GEMDOS
  1585.         addq.l  #6,sp           ; update stack
  1586.         tst.l   d0              ; error ?
  1587.         bne.s   del_er
  1588.         rts
  1589.  
  1590. del_er: move.w  d0,err_no       ; d0 <> 0 is error
  1591.         rts
  1592.  
  1593. *--------------------------------------------------------------------------*
  1594.  
  1595. chr_in:
  1596.  
  1597. * read char from keyboard without echo to screen.
  1598. * upon return d0 (long) hold the value returned by the keyboard:
  1599. * scan code in high word, ascii code in low byte.
  1600. * register other than d0 not affected
  1601.  
  1602.         movem.l d1-d2/a0-a2,-(sp)       ; save register
  1603.  
  1604.         move.w  #1,-(sp)                ; 'Cconin' function
  1605.         trap    #GEMDOS                 ; read the char
  1606.         addq.l  #2,sp                   ; update stack
  1607.  
  1608.         movem.l (sp)+,d1-d2/a0-a2       ; restore register
  1609.         rts
  1610.  
  1611. *--------------------------------------------------------------------------*
  1612.  
  1613. ch_out:
  1614.  
  1615. * print char in d0.w to screen.
  1616. * register other than d0 not affected
  1617.  
  1618.         movem.l d0-d2/a0-a2,-(sp)       ; save register
  1619.  
  1620.         move.w  d0,-(sp)                ; the char
  1621.         move.w  #2,-(sp)                ; 'Cconout' function
  1622.         trap    #GEMDOS                 ; print the char
  1623.         addq.l  #4,sp                   ; update stack
  1624.  
  1625.         movem.l (sp)+,d0-d2/a0-a2       ; restore register
  1626.         rts
  1627.  
  1628. *--------------------------------------------------------------------------*
  1629.  
  1630. prt_str:
  1631.  
  1632. * print null terminated string pointed by a0
  1633. * register not affected
  1634.  
  1635.         movem.l d0-d2/a0-a2,-(sp)       ; save register
  1636.  
  1637.         move.l  a0,-(sp)                ; string address
  1638.         move.w  #9,-(sp)                ; Cconws
  1639.         trap    #GEMDOS                 ; print
  1640.         addq.l  #6,sp                   ; update stack
  1641.  
  1642.         movem.l (sp)+,d0-d2/a0-a2       ; restore register
  1643.         rts
  1644.  
  1645. * ------------------------------------------------------------------------ *
  1646.  
  1647. get_str:
  1648.  
  1649. * read a string of max length d0 (d0<256). a0 must point to the string.
  1650. * the readed string will be null terminated. a room of d0 + 3 bytes must be
  1651. * allowed for a string of length d0. upon return d0 is the number of char
  1652. * read and the cursor stay at the end of the string.
  1653. * other register not affected.
  1654.  
  1655.         movem.l d1-d2/a0-a3,-(sp)
  1656.         move.l  a0,a3                   ; save buffer address
  1657.         move.b  d0,(a3)                 ; put the max in the first byte
  1658.  
  1659.         pea     curSAV                  ; save cursor position
  1660.         move.w  #9,-(sp)                ; Cconws
  1661.         trap    #GEMDOS                 ; print
  1662.         addq.l  #6,sp                   ; update stack
  1663.  
  1664.  
  1665.         move.l  a3,-(sp)                ; get string
  1666.         move.w  #$A,-(sp)
  1667.         trap    #GEMDOS                 ; 'Cconrs' function
  1668.         addq.l  #6,sp
  1669.  
  1670.         pea     curRES                  ; restore cursor position
  1671.         move.w  #9,-(sp)                ; Cconws
  1672.         trap    #GEMDOS                 ; print
  1673.         addq.l  #6,sp                   ; update stack
  1674.  
  1675.         moveq   #0,d0
  1676.         move.b  1(a3),d0                ; number of char actually read
  1677.         beq.s   nil
  1678.         lea     2(a3),a1
  1679.         lea     rgt_s,a0                ; move one char right
  1680.         move.w  d0,d1
  1681.         subq.w  #1,d1
  1682. mov_lf: move.b  (a1)+,(a3)+             ; move read string 2 char left
  1683.         bsr.w   prt_str                 ; move cursor one char right
  1684.         dbra    d1,mov_lf
  1685. nil:    clr.b   (a3)                    ; the null
  1686.         movem.l (sp)+,d1-d2/a0-a3
  1687.         rts
  1688.  
  1689. *--------------------------------------------------------------------------*
  1690.  
  1691. Malloc:
  1692.  
  1693. * if d0.l = -1, return free memory in d0.l
  1694. * else reserve d0.l bytes space, upon return d0.l hold start address
  1695.  
  1696.         move.l  d0,-(sp)                ; reserve space
  1697.         move.w  #$48,-(sp)              ; function number 'Malloc'
  1698.         trap    #GEMDOS
  1699.         addq.l  #6,sp                   ; update stack
  1700.         tst.l   d0                      ; <= 0 is error
  1701.         bpl.s   Mal_x
  1702.         move.w  #NO_MEM,err_no
  1703. Mal_x:  rts
  1704.  
  1705. *--------------------------------------------------------------------------*
  1706.  
  1707. Mfree:
  1708.  
  1709. * relase memory reserved by Malloc at address a0
  1710.  
  1711.         move.l  a0,-(sp)                ; address of reserved memory
  1712.         move.w  #$49,-(sp)              ; function number 'Mfree'
  1713.         trap    #GEMDOS
  1714.         addq.l  #6,sp                   ; update stack
  1715.         tst.w   d0                      ; error ?
  1716.         beq.s   MfreeX
  1717.         move.w  d0,err_no
  1718. MfreeX: rts
  1719.  
  1720. *--------------------------------------------------------------------------*
  1721.  
  1722. set_drv:
  1723.  
  1724. * set drive d0.w to be current drive
  1725.  
  1726.         move.w  d0,-(sp)
  1727.         move.w  #$E,-(sp)               ; function number: Dsetdrv
  1728.         trap    #GEMDOS
  1729.         addq.l  #4,sp                   ; update stack
  1730.         rts
  1731.  
  1732. * ------------------------------------------------------------------------ *
  1733. * ------------------------------------------------------------------------ *
  1734.  
  1735. set_path:
  1736.  
  1737. * set current drive and subdirectory according the null terminated string
  1738. * pointed by a0. WARNING a0 string can be modified
  1739.  
  1740.  
  1741.         movea.l a0,a3                   ; save pointer
  1742. s_p_0:  tst.b   (a0)+
  1743.         bne.s   s_p_0                   ; get end of string
  1744.         cmpi.b  #'\',-2(a0)             ; string terminate by backslash
  1745.         beq.s   s_p_s
  1746.         move.b  #'\',-1(a0)             ; no -> add a backslash
  1747.         clr.b   (a0)
  1748.  
  1749. s_p_s:  movea.l a3,a0                   ; restore pointer
  1750.         cmpi.b  #':',1(a0)              ; drive specified ?
  1751.         bne.s   s_p_1
  1752.  
  1753.         moveq   #0,d0
  1754.         move.b  (a0),d0                 ; drive letter
  1755.         subi.b  #'A',d0                 ; A -> 0, B -> 1...
  1756.         move.b  d0,d3                   ; save it
  1757.         move.w  d0,-(sp)
  1758.         move.w  #$E,-(sp)               ; function number: Dsetdrv
  1759.         trap    #GEMDOS
  1760.         addq.l  #4,sp                   ; update stack
  1761.         btst    d3,d0                   ; bit set in drive map ?
  1762.         beq.s   s_pE1                   ; no -> error
  1763.         addq.l  #2,a3                   ; skip drive letter and colon
  1764.  
  1765. s_p_1:  pea     top                     ; reset pathname
  1766.         move.w  #$3B,-(sp)              ; function number: Dsetpath
  1767.         trap    #GEMDOS
  1768.         addq.l  #6,sp                   ; update stack
  1769.         tst.l   d0                      ; error ?
  1770.         bmi.s   s_pE2
  1771.  
  1772.         move.l  a3,-(sp)                ; pathname
  1773.         move.w  #$3B,-(sp)              ; function number: Dsetpath
  1774.         trap    #GEMDOS
  1775.         addq.l  #6,sp                   ; update stack
  1776.         tst.l   d0                      ; error ?
  1777.         bmi.s   s_pE2
  1778.         rts
  1779.  
  1780. s_pE1:  move.w  #-46,err_no             ; invalid drive specification
  1781.         rts
  1782.  
  1783. s_pE2:  move.w  d0,err_no               ; display error message
  1784.         rts
  1785.  
  1786. * ------------------------------------------------------------------------ *
  1787.  
  1788. get_path:
  1789.  
  1790. * get current drive and subdirectory in the buffer pointed by a0
  1791.  
  1792.         move.l  a0,-(sp)                ; save pointer
  1793.  
  1794.         move.w  #$19,-(sp)              ; function number: Dgetdrv
  1795.         trap    #GEMDOS
  1796.         addq.l  #2,sp                   ; update stack
  1797.         movea.l (sp),a0                 ; restore buffer pointer
  1798.         addi.b  #'A',d0                 ; A -> 0, B -> 1...
  1799.         move.b  d0,(a0)+                ; put drive letter in the buffer
  1800.         move.b  #':',(a0)+              ; add a colon
  1801.  
  1802.         clr.w   -(sp)                   ; current drive
  1803.         move.l  a0,-(sp)                ; buffer
  1804.         move.w  #$47,-(sp)              ; function number: Dgetpath
  1805.         trap    #GEMDOS
  1806.         addq.l  #8,sp                   ; update stack
  1807.  
  1808.         movea.l (sp)+,a0                ; restore buffer pointer
  1809. g_p_0:  tst.b   (a0)+
  1810.         bne.s   g_p_0                   ; get end of string
  1811.         cmpi.b  #'\',-2(a0)             ; string terminate by backslash
  1812.         beq.s   g_p_s
  1813.         move.b  #'\',-1(a0)             ; no -> add a backslash
  1814.         clr.b   (a0)
  1815. g_p_s:  rts
  1816.  
  1817. *--------------------------------------------------------------------------*
  1818.  
  1819. mem_all:
  1820.  
  1821. * reserve all free memory. return amount of free memory in 'amount'
  1822. * and start of free in 'm_free'  (always even address)
  1823. * or exit with error message
  1824.  
  1825.         moveq   #-1,d0                  ; get free memory
  1826.         bsr.w   Malloc
  1827.         subq.l  #1,d0
  1828.         move.l  d0,amount               ; amount of free memory
  1829.         bsr.w   Malloc                  ; reserve all free memory
  1830.         move.l  d0,m_free               ; store...
  1831.         rts
  1832.  
  1833. * ------------------------------------------------------------------------ *
  1834. * -------------------------- SOME TOOLS ---------------------------------- *
  1835. * ------------------------------------------------------------------------ *
  1836.  
  1837. str_copy:
  1838.  
  1839. * copy null terminated string pointed by a0 at the address a1.
  1840. * null is also copied. upon return both a0, a1 point to the null char.
  1841. * register affected d0/a0-a1.
  1842.  
  1843. str_c0: move.b  (a0)+,d0
  1844.         beq.s   str_cx
  1845.         move.b  d0,(a1)+                ; copy while not null
  1846.         bra.s   str_c0
  1847.  
  1848. str_cx: subq.l  #1,a0                   ; to the null
  1849.         clr.b   (a1)                    ; copy the null
  1850.         rts
  1851.  
  1852. * ------------------------------------------------------------------------ *
  1853.  
  1854. upper:
  1855.  
  1856. * make the null terminated string pointed by a0 upper case only
  1857. * register not affected
  1858.  
  1859.         movem.l d0/a0,-(sp)
  1860.  
  1861. up_lp:  move.b  (a0)+,d0
  1862.         beq.s   up_x                    ; exit at last char
  1863.         cmpi.b  #'a',d0
  1864.         bcs.s   up_lp                   ; forget char lower than 'a'
  1865.         cmpi.b  #'z',d0
  1866.         bhi.s   up_lp                   ; and char higher than 'z' too
  1867.         subi.b  #'a'-'A',-1(a0)         ; make char upper case
  1868.         bra.s   up_lp
  1869.  
  1870. up_x:   movem.l (sp)+,d0/a0
  1871.         rts
  1872.  
  1873. * ------------------------------------------------------------------------ *
  1874.  
  1875. compare:
  1876.  
  1877. * compare null terminated string pointed by a0 and a1.
  1878. * upon return a0 is set to the char after the null char of the string a0
  1879. * and d0 is set if the two string are same and clear otherwise.
  1880. * register affected d0/a0-a1
  1881.  
  1882.         move.b  (a0)+,d0
  1883.         beq.s   cmpNUL                  ; exit loop at last char of a0 str
  1884.         cmp.b   (a1)+,d0
  1885.         beq.s   compare                 ; loop while non-null char are same
  1886.  
  1887. cmp_0:  tst.b   (a0)+                   ; get end of a0 string
  1888.         bne.s   cmp_0
  1889.  
  1890. cmp_no: moveq   #0,d0                   ; string are not same
  1891.         rts
  1892.  
  1893. cmpNUL: tst.b   (a1)                    ; last char of a1 str is null too ?
  1894.         bne.s   cmp_no                  ; no -> not same
  1895.  
  1896.         moveq   #-1,d0                  ; yes -> string are same
  1897.         rts
  1898.  
  1899. * ------------------------------------------------------------------------ *
  1900.  
  1901. split_arg:
  1902.  
  1903. * split argument string (pointed by a0 and null terminated) up to 2 parts
  1904. * WARNING: each argument must be separate by a blank char, tab or white
  1905. * space and must be not contain null char between argument.
  1906. * upon return arg1, arg2 hold the pointer for each argument or a pointer
  1907. * to a null char if there is no argument. Each argument will be null
  1908. * terminated. register affected d0/a0
  1909.  
  1910.         sub.l   #1,a0
  1911.  
  1912. sA_1st: addq.l  #1,a0                   ; update string pointer
  1913.         move.b  (a0),d0                 ; get first char of first argument
  1914.         beq.s   sA_No1
  1915.         cmpi.b  #SPACE,d0               ; skip leading blank space
  1916.         beq.s   sA_1st
  1917.         cmpi.b  #TAB,d0
  1918.         beq.s   sA_1st
  1919.         move.l  a0,arg1                 ; fill arg1
  1920.  
  1921. sAlast: addq.l  #1,a0                   ; get last char of argument
  1922.         move.b  (a0),d0
  1923.         beq.s   sA_No2
  1924.         cmpi.b  #SPACE,d0
  1925.         beq.s   sAnext                  ; ready for next argument
  1926.         cmpi.b  #TAB,d0
  1927.         bne.s   sAlast
  1928.  
  1929. sAnext: clr.b   (a0)                    ; null terminated argument
  1930.  
  1931. sA_sec: addq.l  #1,a0                   ; update string pointer
  1932.         move.b  (a0),d0                 ; get first char of second argument
  1933.         beq.s   sA_No2
  1934.         cmpi.b  #SPACE,d0               ; skip leading blank space
  1935.         beq.s   sA_sec
  1936.         cmpi.b  #TAB,d0
  1937.         beq.s   sA_sec
  1938.         move.l  a0,arg2                 ; fill arg1
  1939.         rts
  1940.  
  1941. sA_No1: move.l  a0,arg1                 ; pointer to a null (no argument)
  1942. sA_No2: move.l  a0,arg2
  1943.         rts
  1944.  
  1945. *--------------------------------------------------------------------------*
  1946.  
  1947. l_to_a:
  1948.  
  1949. * long in d0 is converted to ascii in base d1.l at address a0 up to d2 char
  1950. * base in d1.l must be <= 16. leading zero are replace by char in d3
  1951. * for d3.l negative, a rotation is do such that the first char is non zero
  1952. * and leading zero (d3.b) are pushed right (to the end of the string)
  1953. * register not affected
  1954.  
  1955.         movem.l d0-d5/a0-a1,-(sp)
  1956.         lea     digit(pc),a1            ; digit ascii string
  1957.         adda.w  d2,a0
  1958.         subq.w  #1,d2                   ; char counter
  1959.         move.w  d2,d5
  1960.         move.l  d1,d4
  1961.         move.l  d0,d1
  1962.  
  1963. ltoa_l: move.l  d4,d0                   ; restore base
  1964.         bsr.w   div32                   ; division by base
  1965.         move.b  (0,a1,d0.w),-(a0)       ; digit to ascii
  1966.         tst.l   d1                      ; exit for leading zero
  1967.         beq.s   ltoa_j
  1968.         dbra    d2,ltoa_l               ; up to d2 char
  1969.         movem.l (sp)+,d0-d5/a0-a1
  1970.         rts
  1971.  
  1972. ltoa_j: tst.l   d3                      ; left justify ?
  1973.         bmi.s   ltoa_2
  1974.         bra.s   ltoa_0
  1975.  
  1976. ltoa_1: move.b  d3,-(a0)                ; replace leading 0 by char in d3
  1977. ltoa_0: dbra    d2,ltoa_1               ; up to d2 char
  1978.         movem.l (sp)+,d0-d5/a0-a1
  1979.         rts
  1980.  
  1981. ltoa_2: tst.w   d2
  1982.         beq.s   ltoa_x                  ; no other char to fill -> exit
  1983.         sub.w   d2,d5                   ; number of char -1 to move left
  1984.         movea.l a0,a1                   ; last digit address
  1985.         suba.w  d2,a0                   ; beginning of the string to fill
  1986. ltoa_3: move.b  (a1)+,(a0)+             ; move digit left
  1987.         dbra    d5,ltoa_3
  1988.         subq.w  #1,d2
  1989. ltoa_4: move.b  d3,(a0)+                ; fill remainning of string by d3.b
  1990.         dbra    d2,ltoa_4
  1991. ltoa_x: movem.l (sp)+,d0-d5/a0-a1
  1992.         rts
  1993.  
  1994. digit:  dc.b    "0123456789ABCDEF"
  1995.  
  1996. *--------------------------------------------------------------------------*
  1997.  
  1998. div32:
  1999.  
  2000. * (unsigned) divide long in d1 by long in d0. quotient is long in d1.
  2001. * remainder is long in d0. other register not affected.
  2002.  
  2003.         tst.l   d0
  2004.         beq.s   d32_er          ; division by zero
  2005.  
  2006.         cmp.l   d0,d1           ; d1 < d0 ?
  2007.         bcs.s   d32_NO
  2008.  
  2009.         cmpi.l  #$FFFF,d0       ; if d0 < $FFFF, need only word division
  2010.         bhi.s   l_div           ; otherwise long division
  2011.  
  2012. * here word division ------------------------------------------------------*
  2013.  
  2014.         movem.l d2-d3,-(sp)
  2015.         moveq   #0,d3
  2016.         divu    d0,d1           ; let d1 = $FFFF*y + x, d0 = x   here y.z/x
  2017.         bvc.s   w_d_ok          ; simple division d1 = r2.q2; q2 quotient
  2018.         move.l  d1,d2           ; d2 = y.z (if overflow d1 = y.z again)
  2019.         clr.w   d1              ; d1 = y.0
  2020.         swap    d1              ; d1 = 0.y
  2021.         divu    d0,d1           ; d1 = y/x = r1.q1; r1 remainder q1 quotient
  2022.         move.w  d1,d3           ; d3 = 0.q1
  2023.         move.w  d2,d1           ; d1 = r1.z
  2024.         divu    d0,d1           ; d1 = r1.z/x = r0.q0 ; q1 quotient
  2025. w_d_ok: move.l  d1,d0           ; d0 = r2.q2 or r0.q0
  2026.         swap    d1              ; d0 = q2.r2 or q0.r0
  2027.         move.w  d3,d1           ; d1 = q2.0 or q0.q1
  2028.         swap    d1              ; d1 = 0.q2 or q1.q0 real quotient
  2029.         clr.w   d0              ; d0 = r2.0 or 0.0
  2030.         swap    d0              ; d0 = 0.r2 or 0.r0 real remainder
  2031.         movem.l (sp)+,d2-d3
  2032.         rts
  2033.  
  2034. * here long division ------------------------------------------------------*
  2035.  
  2036. l_div:  movem.l d2-d4,-(sp)
  2037.         moveq   #0,d2           ; d2 hold quotient
  2038.         moveq   #0,d3           ; shift and bit number
  2039.         move.l  d0,d4           ; d4 is unmodified divisor
  2040.         bmi.s   l_d             ; if bit 31 is set skip next (note d1 >= d0)
  2041.  
  2042. l_d_1:  addq.b  #1,d3           ; else shift left d0 while bit 31 is not set
  2043.         lsl.l   #1,d0           ; (and update quotient bit no.)
  2044.         bpl.s   l_d_1
  2045.         cmp.l   d0,d1           ; if d1 >= d0 skip next
  2046.         bcc.s   l_d
  2047.  
  2048. l_d_2:  lsr.l   #1,d0           ; divide d0 by 2 while d0 > d1
  2049.         subq.b  #1,d3           ; update quotient bit no.
  2050.         cmp.l   d0,d1
  2051.         bcs.s   l_d_2
  2052.  
  2053. l_d:    bset    d3,d2           ; set bit no. in the quotient
  2054.         sub.l   d0,d1           ; new dividend
  2055.         cmp.l   d4,d1           ; loop while dividend >= divisor
  2056.         bcc.s   l_d_2
  2057.  
  2058.         move.l  d1,d0           ; remainder
  2059.         move.l  d2,d1           ; quotient
  2060.         movem.l (sp)+,d2-d4
  2061.         rts
  2062.  
  2063. d32_NO: move.l  d1,d0           ; remainder d1 when d0 > d1
  2064.         moveq   #0,d1           ; quotient = 0
  2065. d32_er: rts
  2066.  
  2067. * ------------------------------------------------------------------------ *
  2068. * ----------------------------- DATA and BSS ----------------------------- *
  2069. * ------------------------------------------------------------------------ *
  2070.  
  2071.         data
  2072.  
  2073. call:   dc.l    do_mem_free
  2074.         dc.l    do_disk_free
  2075.         dc.l    do_quit
  2076.         dc.l    do_dir
  2077.         dc.l    do_copy
  2078.         dc.l    do_del
  2079.         dc.l    do_ren
  2080.         dc.l    do_path
  2081.         dc.l    do_stop
  2082.         dc.l    do_write
  2083.         dc.l    do_show
  2084.         dc.l    do_print
  2085.         dc.l    do_wait
  2086.         dc.l    do_if
  2087.         dc.l    do_if_not
  2088.         dc.l    do_cls
  2089.         dc.l    do_inf
  2090.  
  2091. error:  dc.w    -2
  2092.         dc.l    readyN
  2093.         dc.w    -6
  2094.         dc.l    seekER
  2095.         dc.w    -8
  2096.         dc.l    sec_nf
  2097.         dc.w    -10
  2098.         dc.l    writeE
  2099.         dc.w    -11
  2100.         dc.l    readE
  2101.         dc.w    -13
  2102.         dc.l    protec
  2103.         dc.w    -16
  2104.         dc.l    secBAD
  2105.         dc.w    -17
  2106.         dc.l    insert
  2107.         dc.w    -32
  2108.         dc.l    funcNB
  2109.         dc.w    -33
  2110.         dc.l    f_n_f
  2111.         dc.w    -34
  2112.         dc.l    p_n_f
  2113.         dc.w    -35
  2114.         dc.l    access
  2115.         dc.w    -39
  2116.         dc.l    insuf
  2117.         dc.w    -46
  2118.         dc.l    driveI
  2119.         dc.w    -66
  2120.         dc.l    format
  2121.         dc.w    -993
  2122.         dc.l    prt_er
  2123.         dc.w    -994
  2124.         dc.l    ren_er
  2125.         dc.w    -995
  2126.         dc.l    noBAT
  2127.         dc.w    -996
  2128.         dc.l    unk_er
  2129.         dc.w    -997
  2130.         dc.l    var_er
  2131.         dc.w    -998
  2132.         dc.l    dkfull
  2133.         dc.w    -999
  2134.         dc.l    missng
  2135.         dc.w    0
  2136.  
  2137. title:  dc.b    13,10,"ABZ command shell, by Alain Birtz, feb. 89",10,0
  2138. wait_1: dc.b    27,'v',27,'e',13,10,27,'p',0
  2139. wait_2: dc.b    27,"q ",0
  2140. boot:   dc.b    "BOOT.BAT",0
  2141. free_s: dc.b    13,10,"________ bytes free",0
  2142. dir_of: dc.b    13,10,10,"Directory of ",0
  2143. nofile: dc.b    "No file in this directory",0
  2144. volume: dc.b    "<<VOL>> ",0
  2145. subdir: dc.b    "<<DIR>> ",0
  2146. any:    dc.b    "*.*",0
  2147. top:    dc.b    "\",0
  2148. two_ln: dc.b    10
  2149. one_ln: dc.b    13,10,0
  2150. revON:  dc.b    27,'p',0
  2151. revOFF: dc.b    27,'q',0
  2152. curSAV: dc.b    27,'j',0
  2153. curRES: dc.b    27,'k',0
  2154. cls_s:  dc.b    27,'E',0
  2155. rgt_s:  dc.b    27,'C',0
  2156. blank:  dc.b    9,9,9,0
  2157. copy_s: dc.b    13,10,"Copying ",0
  2158. del_s1: dc.b    13,10,"Delete ",0
  2159. del_s2: dc.b    " ? (Yes, No, All, Cancel) ",0
  2160.  
  2161. io_err: dc.b    13,10,10,"I/O error no "
  2162. io_no:  dc.b    "--  ",0
  2163. readyN: dc.b    "Drive not ready",0
  2164. seekER: dc.b    "Seek error, track not found",0
  2165. sec_nf: dc.b    "Sector not found",0
  2166. writeE: dc.b    "Write error",0
  2167. readE:  dc.b    "Read error",0
  2168. protec: dc.b    "Disquette write protected",0
  2169. secBAD: dc.b    "Bad sector",0
  2170. insert: dc.b    "Disquette not inserted",0
  2171. funcNB: dc.b    "Invalid function number",0
  2172. f_n_f:  dc.b    "File not found",0
  2173. p_n_f:  dc.b    "Path not found",0
  2174. access: dc.b    "Acces denied",0
  2175. insuf:  dc.b    "Insufficient memory",0
  2176. driveI: dc.b    "Invalid drive specification",0
  2177. format: dc.b    "Invalid file format",0
  2178. noBAT:  dc.b    "No embedded batch file",0
  2179. unk_er: dc.b    "Unknow command",0
  2180. var_er: dc.b    "Undefined variable (type %1, %2, ...)",0
  2181. dkfull: dc.b    "Probably disk full",0
  2182. missng: dc.b    "Missing argument",0
  2183. ren_er: dc.b    "Cannot rename file",0
  2184. prt_er: dc.b    "Printer not ready",0
  2185.  
  2186. key_w:  dc.b    "MFREE",0
  2187.         dc.b    "DFREE",0
  2188.         dc.b    "QUIT",0
  2189.         dc.b    "DIR",0
  2190.         dc.b    "COPY",0
  2191.         dc.b    "DEL",0
  2192.         dc.b    "REN",0
  2193.         dc.b    "PATH",0
  2194.         dc.b    "STOP",0
  2195.         dc.b    "WRITE",0
  2196.         dc.b    "SHOW",0
  2197.         dc.b    "PRINT",0
  2198.         dc.b    "WAIT",0
  2199.         dc.b    "IF_EXIST",0
  2200.         dc.b    "IF_NOT_EXIST",0
  2201.         dc.b    "CLS",0
  2202.         dc.b    "?",0
  2203.         dc.b    0
  2204.  
  2205. ext:    dc.b    "PRG",0
  2206.         dc.b    "TOS",0
  2207.         dc.b    "TTP",0
  2208.         dc.b    "IMG",0
  2209.         dc.b    "BAT",0
  2210.         dc.b    0
  2211.  
  2212.         even
  2213.  
  2214.         bss
  2215.  
  2216. bpcl:   ds.l    1                       ; base page command line pointer
  2217.         ds.l    100
  2218. ustk:   ds.l    1
  2219. amount: ds.l    1                       ; how much free memory
  2220. m_free: ds.l    1                       ; start of free memory
  2221. d_free: ds.l    4                       ; used in disk free calculation
  2222. dta:    ds.l    1                       ; disk transfert address
  2223. arg1:   ds.l    1                       ; argument pointer
  2224. arg2:   ds.l    1
  2225. parPTR: ds.l    5                       ; parameter pointer table
  2226. batBUF: ds.l    1                       ; start of batch file buffer
  2227. batPTR: ds.l    1                       ; pointer to current line in batch
  2228. batPRV: ds.l    1                       ; pointer to previous line in batch
  2229. bat_LN  ds.l    1                       ; one batch line
  2230. param:  ds.l    1                       ; parameter buffer
  2231. err_no: ds.w    1                       ; error no.
  2232. cancel: ds.b    1                       ; 'Cancel' flag
  2233. alldel: ds.b    1                       ; 'delete all file' flag
  2234. cmd_ch: ds.b    1                       ; 'is command char' flag
  2235. exeBAT: ds.b    1                       ; 'executing batch file now' flag
  2236. def_p:  ds.b    80                      ; pathname buffer
  2237. cmd:    ds.b    80                      ; user command buffer
  2238. work:   ds.b    80                      ; general purpose work buffer
  2239.