Subversion Repositories NedoOS

Rev

Rev 656 | Rev 816 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download

  1. ;TODO в батнике %0 (параметры запуска), %1 ...
  2. ;TODO %~dp0 (драйв и путь запуска)
  3. ;TODO %~t1 (дата-время 1-го параметра)
  4. ;TODO goto и метки :label
  5. ;TODO if ???==??? goto
  6. ;TODO for
  7. ;TODO PATH (где хранить? должна подгружаться при старте новой копии cmd)
  8.  
  9.         DEVICE ZXSPECTRUM128
  10.         include "../_sdk/sys_h.asm"
  11. MAXCMDSZ=COMMANDLINE_sz-1;127 ;не считая терминатора
  12. txtscrhgt=25
  13. txtscrwid=80
  14. CMDLINEY=24
  15.  
  16. _COLOR=0x0007;7
  17. _ERRORCOLOR=0x0009;0x42
  18.  
  19.         org PROGSTART
  20. cmd_begin
  21.         ld sp,0x4000 ;не должен опускаться ниже 0x3b00! иначе возможна порча OS        
  22.         call initstdio
  23.  
  24.         OS_GETSTDINOUT ;e=stdin, d=stdout, h=stderr
  25.         ld a,d
  26.         ld (stdouthandle_wasatstart),a
  27.         ld a,e
  28.         ld (stdinhandle_wasatstart),a
  29.  
  30.         OS_GETMAINPAGES
  31. ;dehl=номера страниц в 0000,4000,8000,c000
  32.         push hl
  33.         OS_DELPAGE
  34.         pop hl
  35.         push hl
  36.         ld e,h
  37.         OS_DELPAGE
  38.         pop hl
  39.         ld e,l
  40.         OS_DELPAGE
  41.  
  42.         ld hl,COMMANDLINE ;command line
  43.         push hl
  44.         ld de,params
  45.         call strcopy
  46.        
  47.         pop hl ;ld hl,COMMANDLINE ;command line
  48.         ld de,wordbuf
  49.         call getword
  50.         call skipspaces
  51.         ld (cmdlineword2),hl
  52.         ld a,(hl)
  53.         or a
  54.         jr z,cmd_interactive
  55. ;command line = "cmd <command to run>"
  56.         ld de,cmdbuf
  57.         call strcopy
  58.        
  59.         call makeprompt ;иначе запустится из неправильной директории
  60.        
  61.         call execcmd_maybepipes ;can show errors ;a!=0: no such internal command
  62.         ;or a
  63.         ;call nz,callcmd;strcpexec_tryrun ;запускает по фону
  64.         YIELD ;чтобы запущенная задача успела захватить фокус ;???
  65. ;если командная строка была со словом autoexec.bat в параметре, то это начальный запуск autoexec.bat, из него надо входить в интерактивный режим
  66.         ld hl,tautoexecbat
  67. cmdlineword2=$+1
  68.         ld de,0
  69.         call strcp ;z=yes
  70.         jr z,cmd_interactive
  71. cmd_exit
  72.         QUIT
  73.        
  74. tautoexecbat
  75.         db "autoexec.bat",0
  76.  
  77. cmd_interactive
  78.        
  79. cmdmainloop
  80.         call makeprompt
  81.         call editcmd
  82.         call prcrlf
  83.        
  84.         ld hl,cmdbuf
  85.         ld de,oldcmd
  86.         ld bc,MAXCMDSZ+1
  87.         ldir
  88.  
  89.         call execcmd_maybepipes
  90.         ;or a
  91.         ;call nz,callcmd;strcpexec_tryrun ;запускает по фону
  92.         ld hl,cmdbuf
  93.         ld (hl),0
  94.         jp cmdmainloop
  95.  
  96. execcmd_maybepipes
  97. ;out:a!=0: no such internal command
  98. ;если command pars >file, то create file, перенаправить вывод в него, execcmd, close file, перенаправить вывод обратно
  99.         ld hl,cmdbuf
  100.         ld a,'|'
  101.         ld bc,MAXCMDSZ
  102.         cpir
  103.         jr z,execcmd_pipe
  104.  
  105.         ld hl,cmdbuf
  106.         ld a,'<'
  107.         ld bc,MAXCMDSZ
  108.         cpir
  109.         jr z,execcmd_changestdin ;jr nz,cmd_noexeccmdtofile
  110.  
  111.         ld hl,cmdbuf
  112.         ld a,'>'
  113.         ld bc,MAXCMDSZ
  114.         cpir
  115.         jp nz,execcmd_or_runprog ;jr nz,cmd_noexeccmdtofile
  116. ;change stdout
  117.         dec hl
  118.         ld (hl),0
  119.         inc hl
  120.          call skipspaces
  121.         ex de,hl ;de=filename
  122.         OS_CREATEHANDLE
  123.         ld a,b
  124.         ld (execcmdtofile_handle),a
  125.         call setstdouthandle
  126. ;changestdin_stdout_execcmd
  127.         call execcmd ;can show errors ;a!=0: no such internal command
  128.          or a
  129.          call nz,callcmd
  130.         ;push af
  131. ;команда выполнилась в блокирующем режиме и вышла
  132. execcmdtofile_handle=$+1
  133.         ld b,0
  134.         OS_CLOSEHANDLE ;закрыли выходной файл
  135. stdouthandle_wasatstart=$+1
  136.         ld a,0
  137.         call setstdouthandle
  138. ;stdinhandle_wasatstart=$+1
  139. ;        ld a,0
  140. ;        call setstdinhandle
  141.  
  142.         ;pop af
  143.         ret
  144.         ;jr cmd_noexeccmdtofileq
  145. ;cmd_noexeccmdtofile
  146. ;        jp execcmd ;a!=0: no such internal command
  147. ;cmd_noexeccmdtofileq
  148. ;        ret
  149.  
  150. execcmd_changestdin
  151.         dec hl
  152.         ld (hl),0
  153.         inc hl
  154.          call skipspaces
  155.         ex de,hl ;de=filename
  156.         OS_OPENHANDLE
  157.         ld a,b
  158.         ;ld (execcmdtofile_changestdin_handle),a
  159.         call setstdinhandle
  160.         call setstdinout
  161.         ;jr changestdin_stdout_execcmd
  162.         call execcmd ;can show errors ;a!=0: no such internal command
  163.          or a
  164.          call nz,callcmd
  165.         ;push af
  166. ;команда выполнилась в блокирующем режиме и вышла (или запустилась программа по фону)
  167.  
  168. ;execcmdtofile_changestdin_handle=$+1
  169. ;        ld b,0
  170. ;        OS_CLOSEHANDLE ;закрыли входной файл программы
  171. ;stdouthandle_wasatstart=$+1
  172. ;        ld a,0
  173. ;        call setstdouthandle
  174. stdinhandle_wasatstart=$+1
  175.         ld a,0
  176.         call setstdinhandle
  177.         call setstdinout
  178.  
  179.         ;pop af
  180.         ret
  181.         ;jr cmd_noexeccmdtofileq
  182.  
  183. execcmd_pipe
  184. ;cmd |app
  185.         dec hl
  186.         ld (hl),0
  187.         inc hl
  188.          call skipspaces
  189.         ex de,hl ;de=app filename
  190.  
  191.         OS_OPENHANDLE
  192.         or a
  193.         jr nz,execcmd_pipe_error
  194.  
  195.         push bc
  196.         ld de,tpipename
  197.         OS_CREATEHANDLE
  198.         ld a,b
  199.         ld (pipehandle),a
  200.         call setstdouthandle
  201.         pop bc
  202.        
  203.         call readapp ;делает CLOSE ;TODO через loadapp, чтобы дописывать .com и грузить из /bin
  204.        
  205.         if 1==1
  206.         push af
  207.         ld b,a
  208.         ;ld a,(stdinhandle)
  209.         ;ld d,a
  210. pipehandle=$+1
  211.         ld d,0
  212.         ld a,(stdouthandle)
  213.         ld e,a
  214.         ld h,0xff ;rnd
  215. ;b=id, e=stdin, d=stdout, h=stderr        
  216.         OS_SETSTDINOUT
  217.         endif
  218.        
  219.         pop af ;id
  220.  
  221.         ld e,a ;id
  222.         ;ld (waitpid_id),a
  223.         push de
  224.         OS_RUNAPP
  225.        
  226.         call execcmd ;can show errors ;a!=0: no such internal command
  227.          or a
  228.          call nz,callcmd
  229.         pop de
  230.         ;push af ;a=error
  231.         push de
  232.         ld a,(pipehandle)
  233.         ld b,a
  234.         OS_CLOSEHANDLE ;закрыли источник данных
  235.         pop de
  236.         WAITPID
  237.  
  238.         ld a,(stdouthandle_wasatstart)
  239.         call setstdouthandle
  240. ;закрыть входной файл правой программы
  241.         ;ld a,(pipehandle)
  242.         ;ld b,a
  243.         ;OS_CLOSEHANDLE
  244.  
  245.         ;pop af ;a=error
  246. execcmd_pipe_error
  247.         ret
  248.  
  249. tpipename
  250.         db "z:",0
  251.  
  252. ;;;;;;;;;;;;;;;;;;
  253.        
  254. editcmd_up
  255.         ld de,cmdbuf
  256.         ld hl,oldcmd
  257.         ld bc,MAXCMDSZ+1
  258.         ldir
  259.         ;jp editcmd
  260.  
  261. editcmd
  262.         ld hl,cmdbuf
  263.         call strlen
  264.         ld a,l
  265.         ld (curcmdx),a
  266. editcmd0
  267.         call fixscroll_prcmd
  268.         call cmdcalccurxy
  269.         SETX_;SETXY_
  270.         ;ld e,CURSORCOLOR;0x38
  271.         ;OS_PRATTR ;нарисовать курсор
  272.         call yieldgetkeyloop ;YIELDGETKEYLOOP
  273.          ;ld a,c ;keynolang
  274.         ;push af
  275.         ;call cmdcalccurxy
  276.         ;SETXY_
  277.         ;ld e,COLOR;7
  278.         ;OS_PRATTR ;стереть курсор
  279.         ;pop af
  280.         cp key_enter
  281.         ret z
  282.         cp key_up
  283.         jr z,editcmd_up
  284.          ld hl,editcmd0
  285.          push hl
  286.         ;ld hl,cmdbuf
  287.         cp key_backspace
  288.         jr z,editcmd_backspace
  289.         cp key_left
  290.         jr z,editcmd_left
  291.         cp key_right
  292.         jr z,editcmd_right
  293.         cp key_home
  294.         jr z,editcmd_home
  295.         cp key_end
  296.         jr z,editcmd_end
  297.         cp key_del
  298.         jr z,editcmd_del
  299.         cp 0x20
  300.         ret c ;jr c,editcmdok ;прочие системные кнопки не нужны
  301. ;type in
  302. editcmdtypein
  303.         ld e,a
  304.         ld hl,cmdbuf
  305.         call strlen ;hl=length
  306.         ld bc,MAXCMDSZ
  307.         or a
  308.         sbc hl,bc
  309.         ret nc ;jr nc,editcmdok ;некуда вводить
  310.         call cmdcalctextaddr ;hl=addr, a=curcmdx
  311.         inc a
  312.         ld (curcmdx),a
  313.         jp strinsch ;e=ch
  314.        
  315. editcmd_backspace
  316.         call cmdcalctextaddr ;hl=addr, a=curcmdx
  317.         or a
  318.         ret z ;jr z,editcmdok ;нечего удалять
  319.         dec a
  320.         ld (curcmdx),a
  321.         jp strdelch ;удаляет предыдущий символ
  322.      
  323. editcmd_del
  324.         call cmdcalctextaddr ;hl=addr, a=curcmdx
  325.         inc hl
  326.         jp strdelch ;удаляет предыдущий символ
  327.      
  328. editcmd_left
  329.         ld a,(curcmdx)
  330.         or a
  331.         ret z ;jr z,editcmdok ;некуда влево
  332.         dec a
  333. editcmd_leftq
  334.         ld (curcmdx),a
  335.         ret
  336. editcmd_home
  337.         xor a
  338.         jr editcmd_leftq
  339. editcmd_end
  340.         ld hl,cmdbuf
  341.         call strlen ;hl=length
  342.         ld a,l
  343.         jr editcmd_leftq
  344.  
  345. editcmd_right
  346.         call cmdcalctextaddr ;hl=addr, a=curcmdx
  347.         inc (hl)
  348.         dec (hl)
  349.         ret z ;jr z,editcmdok ;некуда право, стоим на терминаторе
  350.         inc a
  351.         ld (curcmdx),a
  352.         ret
  353.  
  354. getword
  355. ;hl=string
  356. ;de=wordbuf
  357. ;out: hl=terminator/space addr
  358. getword0
  359.         ld a,(hl)
  360.         or a
  361.         jr z,getwordq
  362.         sub ' '
  363.         jr z,getwordq
  364.         ldi
  365.         jp getword0
  366. getwordq
  367.         ;xor a
  368.         ld (de),a
  369.         ret
  370.  
  371. execcmd_or_runprog
  372.         call execcmd
  373.         or a
  374.         ret z
  375.         jp callcmd;strcpexec_tryrun ;запускает по фону
  376.  
  377. execcmd
  378. ;a=0: command executed
  379. ;a!=0: no such internal command
  380.         ld hl,cmdbuf
  381.         ld a,(hl)
  382.         or a
  383.         ret z
  384.                 ;display $
  385.                 ;display wordbuf
  386.         ld de,wordbuf
  387.         call getword ;hl=terminator/space addr
  388.         call skipspaces
  389.         ld (execcmd_pars),hl
  390.                 inc hl
  391.                 ld a,(wordbuf+1)
  392.                 cp ':'
  393.                 jp nz,execcmd0
  394.                 ld a,(wordbuf+2)
  395.                 or a
  396.                 jp z,cmd_t0
  397. execcmd0
  398.         ld hl,commandslist ;list of internal commands
  399. strcpexec0
  400.         ld c,(hl)
  401.         inc hl
  402.         ld b,(hl)
  403.         inc hl
  404.         ld a,b
  405.         cp -1
  406.         ret z ;jr z,strcpexec_tryrun ;a!=0: no such internal command
  407.         ld de,wordbuf
  408.         push hl
  409.         call strcp
  410.         pop hl
  411.         jr nz,strcpexec_fail
  412.         ld h,b
  413.         ld l,c
  414.         call jphl ;execute command
  415.         xor a
  416.         ret ;a=0: command executed
  417. jphl
  418.         jp (hl) ;run internal command
  419. strcpexec_fail
  420.         ld b,-1 ;чтобы точно найти терминатор
  421.         xor a
  422.         cpir ;найдём обязательно
  423.         jr strcpexec0
  424.  
  425. cmd_start
  426. ;выполнить командную строку по фону (нужно из .bat)
  427.         ld hl,cmdbuf
  428.         ld a,(hl)
  429.         or a
  430.         ret z
  431.         ld de,wordbuf
  432.         call getword ;hl=terminator/space addr
  433.         call skipspaces
  434.         ld de,cmdbuf
  435.         ld bc,MAXCMDSZ+1
  436.         ldir
  437.         call strcpexec_tryrun ;выполнить файл с именем cmdbuf или SYSDIR/cmdbuf и параметрами там, e=id, nz=error, cy=end of .bat
  438.         ret z
  439. execcmd_error
  440.         ld hl,tunknowncommand
  441.         jp cmderror
  442.        
  443. strcpexec_tryrun
  444. ;выполнить файл с именем cmdbuf или SYSDIR/cmdbuf и параметрами там, e=id, nz=error, cy=end of .bat
  445.         call loadapp ;загрузить файл с именем cmdbuf, e=id, nz=error, cy=end of .bat
  446.         ret c ;cy=end of .bat        
  447.         jr nz,execcmd_tryrunerror
  448. execcmd_tryrunok
  449.         ret c ;cy=end of .bat
  450.         push de
  451.         OS_RUNAPP ;e=id
  452.         pop de
  453.          xor a ;z
  454.         ret
  455.  
  456. execcmd_tryrunerror
  457. ;выполнить файл с именем SYSDIR/cmdbuf и параметрами там
  458.         call loadapp_keeppath
  459.         OS_SETSYSDRV
  460.         ld de,sysdir
  461.         push de
  462.         OS_GETPATH
  463.         call loadapp_setoldpath ;TODO из prompt
  464.          ;OS_SETSYSDRV
  465.          ;ld de,wordbuf2
  466.          ;OS_GETPATH
  467.         ;ld de,cmdprompt
  468.         ;OS_CHDIR
  469.         ;call makeprompt
  470.         ;ld de,cmdprompt
  471.         ;OS_CHDIR
  472.         pop hl
  473.         push hl
  474. ;если в конце нет слеша, то добавим:
  475.         ;ld bc,0 ;чтобы точно найти терминатор
  476.         xor a
  477.         ld b,a
  478.         ld c,a;0
  479.         cpir ;найдём обязательно, если длина=0, то bc=-1 и т.д.
  480.         dec hl ;на терминаторе
  481.         dec hl ;перед терминатором
  482.         ld a,'/'
  483.         cp (hl)
  484.         jr z,$+2+5
  485.          inc hl
  486.          ld (hl),a
  487.          inc hl
  488.          ld (hl),0
  489.         pop hl ;sysdir
  490.         call strlen
  491.         ld b,h
  492.         ld c,l ;bc=SYSDIR_size
  493.          push bc ;SYSDIR_size
  494.         ld hl,MAXCMDSZ+1
  495.         or a
  496.         sbc hl,bc
  497.         push hl ;MAXCMDSZ+1-SYSDIR_size
  498. ;bc=SYSDIR_size
  499.         ld hl,cmdbuf+MAXCMDSZ;+1
  500.         or a
  501.         sbc hl,bc
  502.         ld de,cmdbuf+MAXCMDSZ;+1
  503.         pop bc ;MAXCMDSZ+1-SYSDIR_size
  504.         lddr
  505.         ld hl,sysdir
  506.         ld de,cmdbuf
  507.          pop bc ;SYSDIR_size
  508.         ldir ;нельзя strcopy, т.к. не нужен терминатор
  509.          ;ld hl,sysdir
  510.          ;ld de,oldpath
  511.          ;ld bc,MAXPATH_sz;MAXCMDSZ+1
  512.          ;ldir ;TODO рекурсивно (для .bat)
  513.          ;jr $
  514.         call loadapp ;загрузить файл с именем cmdbuf, e=id, nz=error, cy=end of .bat
  515.         jr z,execcmd_tryrunok
  516.         ret ;nz=error
  517.        
  518. callcmd
  519. ;call command (cmdbuf) with waiting
  520. ;TODO open %0 (progname), %1...
  521.         ld hl,cmdbuf
  522.         call strlen
  523.         ld b,h
  524.         ld c,l ;bc=len (without terminator)
  525.         ld hl,cmdbuf
  526.         add hl,bc ;at terminator
  527.         ld de,cmdbuf+MAXCMDSZ ;at last byte of buffer
  528.         inc bc ;bc=len (with terminator)
  529.         lddr
  530.         ex de,hl
  531.         inc hl
  532.         ld de,cmdbuf
  533. chgparams0
  534.         ld a,(hl)
  535.         ld (de),a
  536.         or a
  537.         jr z,chgparams0q
  538.         inc hl
  539.         cp '%'
  540.         jr nz,chgparams0skip
  541.         ld a,(hl)
  542.         ld (de),a
  543.         or a
  544.         jr z,chgparams0q
  545.         inc hl
  546.         sub '0' ;a=param
  547.         cp 10
  548.         jr nc,chgparams0skip ;%%
  549.         push hl
  550.         ld hl,params
  551.         inc a
  552.         ld b,a
  553. chgparams1
  554.         call skipword ;doesn't move at terminator
  555.         call skipspaces ;doesn't move at terminator
  556.         djnz chgparams1
  557. ;hl=param text (end=space or terminator)        
  558. chgparams2
  559.         ld a,(hl)
  560.         or a
  561.         jr z,chgparams2q
  562.         cp ' '
  563.         jr z,chgparams2q
  564.         ld (de),a
  565.         inc hl
  566.         inc de
  567.         djnz chgparams2
  568. chgparams2q
  569.         pop hl
  570.         dec de
  571. chgparams0skip
  572.         inc de
  573.         jr chgparams0
  574. chgparams0q
  575.  
  576.         call execcmd ;a!=0: no such internal command
  577.         or a
  578.         ret z ;command executed
  579.         ;call loadapp ;загрузить файл с именем cmdbuf, e=id
  580.         call strcpexec_tryrun ;загрузить файл с именем cmdbuf или SYSDIR/cmdbuf, e=id, nz=error, CY=end of .bat
  581.         ret c
  582.         jp nz,execcmd_error
  583.         ;push de
  584.         ;OS_RUNAPP
  585.         ;pop de
  586.         WAITPID ;не должно быть, если команда была .bat!
  587.         ret
  588.  
  589. loadapp_keeppath
  590.         ld hl,cmdprompt
  591.         ld de,oldpath
  592.         ld bc,MAXPATH_sz;MAXCMDSZ+1
  593.         ldir ;TODO рекурсивно (для .bat)
  594.         ret
  595.  
  596. loadapp_setoldpath
  597.         push de
  598.         ld de,oldpath ;TODO рекурсивно (для .bat)
  599.         OS_CHDIR
  600.         pop de
  601.         xor a
  602.         ret ;Z
  603.        
  604. loadapp
  605. ;out: nz=error, cy=end of .bat, or else e=id
  606.         ld hl,cmdbuf
  607.         ld de,wordbuf
  608.         call getword
  609. ;учесть путь в имени (TODO использовать OS_OPENHANDLE)
  610.         ld hl,wordbuf
  611.         push hl
  612.         call findlastslash. ;de=after last slash or beginning of path
  613.         pop hl
  614.  
  615.         ;push hl
  616. ;ищем точку, проверяем, что после неё стоит .com или .bat
  617. loadapp_finddot0
  618.         ld a,(hl)
  619.         or a
  620.         jr z,loadapp_nodot
  621.         cp '.'
  622.         inc hl
  623.         jr nz,loadapp_finddot0
  624. ;проверяем, что после неё стоит .com или .bat
  625.         ld a,(hl)
  626.         or 0x20
  627.         cp 'b'
  628. ; TODO где проверка на остальные буквы?
  629.         jp z,strcpexec_tryrun_bat
  630. ;считаем, что написано .com (в принципе расширение безразлично - просто запускаем)
  631.         jr loadapp_finddotok
  632. loadapp_nodot
  633. ;a=0
  634.         ld (hl),'.'
  635.         inc hl
  636.         ld (hl),'c'
  637.         inc hl
  638.         ld (hl),'o'
  639.         inc hl
  640.         ld (hl),'m'
  641.         inc hl
  642.         ld (hl),a ;0        
  643. loadapp_finddotok
  644.         ld de,wordbuf ;pop de
  645.         OS_OPENHANDLE
  646.         or a
  647.          push af
  648.         ld a,b
  649.         ld (curhandle),a
  650.          call loadapp_setoldpath
  651.          pop af
  652.         ret nz ;jr nz,execcmd_error ;NC!
  653.         OS_NEWAPP ;на момент создания должна быть включена текущая директория!!!
  654.         or a
  655.         ret nz ;error ;NC!
  656. ;dehl=номера страниц в 0000,4000,8000,c000 нового приложения, b=id, a=error
  657.         push bc ;b=id
  658.         ld a,d
  659.         SETPG32KHIGH
  660.         push de
  661.         push hl
  662.         ld hl,cmdbuf
  663.         ld de,0xc000+COMMANDLINE
  664.         ld bc,COMMANDLINE_sz
  665.         ldir ;command line
  666.         pop hl
  667.         pop de
  668.         call readfile_pages_dehl
  669.  
  670.         ld a,(curhandle)
  671.         ld b,a
  672.         OS_CLOSEHANDLE
  673.         pop de
  674.         ld e,d ;e=id
  675.         xor a
  676.         ret ;Z
  677.      
  678. readapp
  679.         ld a,b
  680.         ld (curhandle),a
  681.        
  682.         OS_NEWAPP ;для первой создаваемой задачи будут созданы первые два пайпа и подключены
  683. ;dehl=номера страниц в 0000,4000,8000,c000 нового приложения, b=id, a=error
  684.         push bc ;b=id
  685.  
  686.         ld a,d
  687.         SETPG32KHIGH
  688.         push de
  689.         push hl
  690.         ld hl,COMMANDLINE ;command line
  691.         call skipword
  692.         call skipspaces ;пропустили первое слово (там было term.com, а дальше, например, cmd.com autoexec.bat)
  693.         ld de,0xc080
  694.         ld bc,128  
  695.         ldir ;command line
  696.         pop hl
  697.         pop de
  698.  
  699.         call readfile_pages_dehl
  700.  
  701.         ld a,(curhandle)
  702.         ld b,a
  703.         OS_CLOSEHANDLE
  704.  
  705.         pop af ;id
  706.         ret
  707.  
  708. skipword
  709. ;hl=string
  710. ;out: hl=terminator/space addr
  711. skipword0
  712.         ld a,(hl)
  713.         or a
  714.         ret z ;jr z,skipwordq
  715.         sub ' '
  716.         ret z ;jr z,skipwordq
  717.         inc hl ;ldi
  718.         jr skipword0
  719.  
  720. readfile_pages_dehl
  721.         ld a,d
  722.         SETPG32KHIGH
  723.         ld a,0xc100/256
  724.         call cmd_loadpage
  725.         ret nz
  726.         ld a,e
  727.         call cmd_loadfullpage
  728.         ret nz
  729.         ld a,h
  730.         call cmd_loadfullpage
  731.         ret nz
  732.         ld a,l
  733. cmd_loadfullpage
  734.         SETPG32KHIGH
  735.         ld a,0xc000/256
  736. cmd_loadpage
  737. ;out: a=error
  738. ;keeps hl,de
  739.         push de
  740.         push hl
  741.         ld d,a
  742.         xor a
  743.         ld l,a
  744.         ld e,a
  745.         sub d
  746.         ld h,a ;de=buffer, hl=size
  747. curhandle=$+1
  748.         ld b,0
  749.         OS_READHANDLE
  750.         pop hl
  751.         pop de
  752.         or a
  753.         ret
  754.      
  755. strcpexec_tryrun_bat
  756.         ;display "strcpexec_tryrun_bat",strcpexec_tryrun_bat
  757. ;out: nz=error, cy=end of .bat
  758. ;open .bat
  759. ;filename in wordbuf
  760.         ld de,wordbuf ;pop de
  761.         OS_OPENHANDLE
  762.         or a
  763.         ld a,b
  764.         ld (curbathandle),a    
  765.         ret nz ;jp nz,execcmd_error ;NC!
  766.        
  767.          ld a,0x3c ;"inc a"
  768.          ld (readbyte_readbuf_last),a
  769.         ld iy,file_buf_end
  770. strcpexec_tryrun_bat0
  771. ;load line to cmdbuf
  772.         ld hl,cmdbuf
  773.         LD (hl),0
  774.         call readstr ;nz=EOF
  775.         push af ;jr nz,strcpexec_tryrun_batq ;чтобы последнюю строку всё-таки выполнить
  776.  
  777.         push iy
  778.         ld hl,cmdbuf
  779.         call prtext
  780.         call prcrlf
  781.         pop iy
  782.        
  783. ;call command in cmdbuf
  784.         push iy
  785.         call callcmd
  786.         pop iy
  787.        
  788.         pop af
  789.         jr z,strcpexec_tryrun_bat0 ;nz=EOF
  790. strcpexec_tryrun_batq
  791. ;close .bat
  792.         ld a,(curbathandle)
  793.         ld b,a
  794.         OS_CLOSEHANDLE
  795.         xor a
  796.          scf ;чтобы на выходе не делать RUNAPP
  797.         ret ;Z
  798.  
  799.         macro READBYTE_A
  800. ;out: z=EOF
  801.         inc ly
  802.         call m,readbyte_readbuf
  803.         ld a,(iy)
  804.         endm
  805.  
  806. readstr
  807. ;out: nz=EOF
  808. ;skips empty lines!
  809.         READBYTE_A ;z=EOF
  810.         jr z,readstrEOF
  811.         cp 0x0d
  812.         jr z,readstr ;empty string - retry
  813.         cp 0x0a
  814.         jr z,readstr ;empty string - retry
  815.         ld b,MAXCMDSZ
  816.         jr readstr0go
  817. readstr0
  818.         READBYTE_A ;z=EOF
  819.         jr z,readstrEOF ;возвращает NZ
  820.         ;jr z,readstrq ;возвращает Z
  821.         cp 0x0d
  822.         jr z,readstrq
  823.         cp 0x0a
  824.         jr z,readstrq
  825. readstr0go
  826.         ld (hl),a
  827.         inc hl
  828.         djnz readstr0
  829. readstrq
  830.         xor a ;Z
  831.         ld (hl),a
  832.         inc hl
  833.         ret ;Z
  834. readstrEOF
  835.         xor a
  836.         ld (hl),a
  837.         inc hl
  838.         dec a
  839.         ret ;NZ
  840.  
  841. readbyte_readbuf
  842. ;out: z=EOF
  843.         push bc
  844.         push de
  845.         push hl
  846.         push ix
  847.          ;jr $
  848.         xor a
  849. readbyte_readbuf_last=$ ;TODO keep if recursive!
  850.         inc a ;/nop(z)=last, inc a(nz)=not last
  851.         jr z,readbyte_readbufq
  852.  
  853.         if 1==1
  854. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  855. curbathandle=$+1
  856.         ld b,0
  857.         ld de,file_buf
  858.         push de
  859.         ld hl,128
  860.         OS_READHANDLE
  861.         pop iy
  862. ;HL = Number of bytes actually read, A=error
  863.         ;sub 1
  864.         ;sbc a,a ;error=0 => a=255, else a=0 (Z)
  865.         ;jr z,readbyte_readbufq ;error (=>EOF)
  866.          ;jr $
  867.         ld a,l
  868.         or a
  869.         jr z,readbyte_readbufq ;0 bytes (=>EOF)
  870.         jp m,readbyte_readbufq ;128 bytes (NZ no EOF) (not last block)
  871.        
  872.         else ;CP/M-like
  873.        
  874.         ld de,file_buf
  875.         push de
  876.         OS_SETDTA ;set disk transfer address = de
  877.         ld de,fcb_bat
  878.         OS_FREAD
  879.         pop iy
  880.         xor 128 ;a = bytes read
  881.         jr z,readbyte_readbufq
  882.         jp m,readbyte_readbufq ;full block = not last block
  883.        
  884.         endif
  885.        
  886. ;last block: shift data to the end of buf, mark last
  887.         ld c,a ;1..128
  888.         ld b,0 ;nz!
  889.         ld a,b
  890.         ld (readbyte_readbuf_last),a ;last block
  891.         ld hl,file_buf
  892.         add hl,bc
  893.         dec hl ;end of data
  894.         ld de,file_buf+127
  895.         lddr
  896.         inc de
  897.         push de
  898.         pop iy
  899.         ;nz!
  900. readbyte_readbufq
  901. ;iy=addr
  902. ;z=EOF
  903.         pop ix
  904.         pop hl
  905.         pop de
  906.         pop bc
  907.         ret
  908.  
  909. cmd_dir
  910.         ld de,(execcmd_pars)
  911.         ;ld de,emptypath
  912.         OS_OPENDIR
  913.         or a
  914.         ld bc,0 ;nfiles
  915.         jp nz,loaddir2_error
  916. cmd_dir2_0
  917.        push bc
  918.         ld de,filinfo
  919.         OS_READDIR
  920.        pop bc
  921.         or a
  922.         jr nz,loaddir2q
  923.         ld a,(filinfo+FILINFO_FNAME)
  924.         or a
  925.         jr z,loaddir2q
  926.        push bc
  927.         ld ix,(filinfo+FILINFO_FDATE)
  928.         ld hl,(filinfo+FILINFO_FTIME)
  929.         call prdate_time
  930.  
  931.         ld a,' '
  932.         PRCHAR_
  933.  
  934.         ld hl,(filinfo+FILINFO_FSIZE+2)
  935.         exx
  936.         ld hl,(filinfo+FILINFO_FSIZE)
  937.         call prdword
  938.         ld a,' '
  939.         PRCHAR_
  940.  
  941.         ld hl,filinfo+FILINFO_LNAME
  942.         ld a,(hl)
  943.         or a
  944.         jr nz,$+5
  945.         ld hl,filinfo+FILINFO_FNAME
  946.         ;ld c,0 ;c=x
  947.         call prtext
  948. ;c=x
  949.        
  950.         call prcrlf
  951.        pop bc ;nfiles
  952.         inc bc ;nfiles
  953.         or a
  954.         jr cmd_dir2_0
  955. loaddir2_error
  956. loaddir2q
  957. ;bc=nfiles
  958.         ld h,b
  959.         ld l,c
  960.         call prword
  961.         ld hl,t_files_crlf
  962.         jp prtext
  963.  
  964. prdate_time
  965. ;ix=date, hl=time
  966.         ld de,datetimebuf
  967.        push de
  968.        push hl ;time
  969.         ;push ix ;date
  970.         ld a,hx
  971.         srl a
  972.         sub 20
  973.         jr nc,$+4
  974.         add a,100 ;XX century
  975.         call prNNcmd ;year
  976.         ;ld a,'-'
  977.         ;PRCHAR_
  978.          inc de
  979.         ;pop hl
  980.         ld a,lx
  981.         push af
  982.         add ix,ix
  983.         add ix,ix
  984.         add ix,ix
  985.         ld a,hx
  986.         and 0x0f
  987.         call prNNcmd ;month
  988.         ;ld a,'-'
  989.         ;PRCHAR_
  990.          inc de
  991.         pop af
  992.         and 0x1f
  993.         call prNNcmd ;day
  994.  
  995.         ;ld a,' '
  996.         ;PRCHAR_
  997.          inc de
  998.        pop hl ;time
  999.         push hl
  1000.         ld a,h
  1001.         rra
  1002.         rra
  1003.         rra
  1004.         and 0x1f
  1005.         call prNNcmd ;hour
  1006.         ;ld a,':'
  1007.         ;PRCHAR_
  1008.          inc de
  1009.         pop hl
  1010.         ld a,l
  1011.         push af
  1012.         add hl,hl
  1013.         add hl,hl
  1014.         add hl,hl
  1015.         ld a,h
  1016.         and 0x3f
  1017.         call prNNcmd ;minute
  1018.         ;ld a,':'
  1019.         ;PRCHAR_
  1020.          inc de
  1021.         pop af
  1022.         add a,a
  1023.         and 0x3f
  1024.         call prNNcmd ;second
  1025.        pop hl
  1026.         ld de,8+1+8
  1027.         jp cmdprNchars
  1028.  
  1029. prNNcmd
  1030. ;a=NN
  1031. ;de=buf
  1032.         ld bc,10+(256*('0'-1))
  1033.         sub c
  1034.         inc b
  1035.         jr nc,$-2
  1036.          ex de,hl
  1037.          ld (hl),b
  1038.          ex de,hl
  1039.          inc de
  1040.         add a,'0'+10
  1041.          ld (de),a
  1042.          inc de
  1043.         ret
  1044.  
  1045. datetimebuf
  1046.         db "00-00-00 00:00:00"
  1047.        
  1048. skipspaces
  1049. ;hl=string
  1050. ;out: hl=after last space
  1051.         ld a,(hl)
  1052.         cp ' '
  1053.         ret nz
  1054.         inc hl
  1055.         jr skipspaces
  1056.  
  1057. strcopy
  1058. ;hl->de
  1059. strcopy0
  1060.         ld a,(hl)
  1061.         ldi
  1062.         or a
  1063.         jr nz,strcopy0
  1064.         ret
  1065.  
  1066. cmd_cd
  1067. execcmd_pars=$+1
  1068.         ld hl,0
  1069.         ld a,(hl)
  1070.         or a
  1071.         jr z,cmd_error_nopars
  1072.         ex de,hl ;de=path
  1073.         OS_CHDIR
  1074.         or a
  1075.         ret z
  1076.         ld hl,twrongpath
  1077.         jp cmderror
  1078.        
  1079. cmd_error_nopars
  1080.         ld hl,tnopars
  1081.         jp cmderror
  1082. cmd_error_notenoughpars
  1083.         ld hl,tnotenoughpars
  1084.         jp cmderror
  1085.  
  1086. cmd_md
  1087.         ld hl,(execcmd_pars)
  1088.         ld a,(hl)
  1089.         or a
  1090.         jr z,cmd_error_nopars
  1091.         ex de,hl ;de=dirname
  1092.         OS_MKDIR
  1093.         or a
  1094.         ret z
  1095. cmd_error_cantmakedir
  1096.         ld hl,tcantmakedir
  1097.         jp cmderror
  1098.        
  1099. cmd_del
  1100.         ld hl,(execcmd_pars)
  1101.         ld a,(hl)
  1102.         or a
  1103.         jr z,cmd_error_nopars
  1104.         ex de,hl
  1105.         OS_DELETE
  1106.         or a
  1107.         ret z
  1108. cmd_error_wrongfile
  1109.         ld hl,twrongfile
  1110.         jp cmderror
  1111.        
  1112. cmd_ren
  1113.         ld hl,(execcmd_pars)
  1114.         ld a,(hl)
  1115.         or a
  1116.         jr z,cmd_error_nopars
  1117.         ld de,wordbuf
  1118.         call getword ;hl=terminator/space addr
  1119.         call skipspaces
  1120.         ld a,(hl)
  1121.         or a
  1122.         jr z,cmd_error_notenoughpars
  1123.         ld de,wordbuf2
  1124.         call getword ;hl=terminator/space addr
  1125.         ld de,wordbuf
  1126.         ld hl,wordbuf2
  1127.         OS_RENAME
  1128.         or a
  1129.         ret z
  1130.         ld hl,tcantrename
  1131.         jp cmderror
  1132.        
  1133. cmd_copy
  1134.         ld hl,(execcmd_pars)
  1135.         ld a,(hl)
  1136.         or a
  1137.         jr z,cmd_error_nopars
  1138.         ld de,filenamebuf;wordbuf
  1139.         call getword ;hl=terminator/space addr
  1140.         call skipspaces
  1141.         ld a,(hl)
  1142.         or a
  1143.         jr z,cmd_error_notenoughpars
  1144.         ld de,filenamebuf2;wordbuf2
  1145.         call getword ;hl=terminator/space addr
  1146.  
  1147.         ld de,filenamebuf;wordbuf ;de=drive/path/file
  1148.         OS_OPENHANDLE
  1149.         or a
  1150.         jp nz,cmd_error_wrongfile
  1151.         ld a,b
  1152.         ld (close_file1_handle),a
  1153.         ld hl,close_file1
  1154.         push hl
  1155.        
  1156.         ld de,filenamebuf2;wordbuf2 ;de=drive/path/file
  1157.         OS_CREATEHANDLE
  1158.         or a
  1159.         jp nz,cmd_error_cant_copy
  1160.         ld a,b
  1161.         ld (cmd_copy_close_file2_handle),a
  1162.         ld hl,cmd_copy_close_file2
  1163.         push hl
  1164. cmd_copy0
  1165.         ld hl,copybuf_sz
  1166.         ld de,copybuf
  1167.         ld a,(close_file1_handle)
  1168.         ld b,a
  1169. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  1170.         push de
  1171.         OS_READHANDLE
  1172. ;HL = Number of bytes actually read, A=error
  1173.         pop de
  1174.         ld a,h
  1175.         or l
  1176.         ret z ;0 bytes remain
  1177.         ld a,(cmd_copy_close_file2_handle)
  1178.         ld b,a
  1179. ;B = file handle, DE = Buffer address, HL = Number of bytes to write
  1180.         OS_WRITEHANDLE
  1181.         jr cmd_copy0
  1182.        
  1183. close_file1
  1184. close_file1_handle=$+1
  1185.         ld b,0
  1186.         OS_CLOSEHANDLE
  1187.         ret
  1188.        
  1189. cmd_copy_close_file2
  1190. cmd_copy_close_file2_handle=$+1
  1191.         ld b,0
  1192.         OS_CLOSEHANDLE
  1193.         ld de,filenamebuf;wordbuf;filenametext
  1194.         OS_GETFILETIME ;ix=date, hl=time
  1195.         ld de,filenamebuf2;wordbuf2
  1196.         OS_SETFILETIME
  1197.         ret      
  1198.        
  1199. cmd_error_cant_copy
  1200.         ld hl,tcantcopy
  1201.         jp cmderror
  1202.  
  1203. cmd_rem
  1204.         ret
  1205.        
  1206. cmd_mem
  1207.         ld hl,tfree
  1208.         call prtext
  1209.         ld b,0
  1210. cmd_mem0
  1211.         push bc
  1212.         OS_NEWPAGE
  1213.         pop bc
  1214.         or a
  1215.         jr nz,cmd_mem_del
  1216.         inc b
  1217.         push de
  1218.         jr cmd_mem0
  1219. cmd_mem_del
  1220.         ld c,b
  1221.         inc b
  1222.         dec b
  1223.         jr z,cmd_mem_q
  1224. cmd_mem_del0
  1225.         pop de
  1226.         push bc
  1227.         OS_DELPAGE
  1228.         pop bc
  1229.         djnz cmd_mem_del0
  1230. cmd_mem_q
  1231. ;c=free pages
  1232.         ld l,c
  1233.         ld h,0
  1234.         call prword
  1235.         jp prcrlf
  1236.  
  1237. cmd_drop
  1238.         ld hl,(execcmd_pars)
  1239.         ld a,(hl)
  1240.         or a
  1241.         jp z,cmd_error_nopars
  1242.         xor a
  1243.         ld d,a
  1244. cmd_drop_par0
  1245.         add a,d
  1246.         ld e,a ;id
  1247.         add a,a
  1248.         add a,a
  1249.         add a,e
  1250.         add a,a
  1251.         ld d,a ;d=e*10
  1252.         ld a,(hl)
  1253.         inc hl
  1254.         sub '0'
  1255.         cp 10
  1256.         jr c,cmd_drop_par0
  1257.         ;e=id
  1258.         OS_DROPAPP
  1259.         or a
  1260.         ret z
  1261.         ld hl,twrongid
  1262.         jp cmderror
  1263.        
  1264. cmd_proc
  1265.         ld e,1 ;no id 0
  1266. cmd_proc0
  1267.         push de
  1268.         OS_GETAPPMAINPAGES ;d,e,h,l=pages in 0000,4000,8000,c000, c=flags
  1269.         or a
  1270.         jr nz,cmd_proc_skip
  1271.         ld a,d
  1272.         pop de
  1273.         push de
  1274.          push bc
  1275.         push af
  1276.         ex de,hl
  1277.         ld h,0
  1278.         call prword
  1279.         ld a,' '
  1280.         PRCHAR_
  1281.         pop af ;main page
  1282.         SETPG32KHIGH
  1283.          pop bc ;c=flags
  1284.          push bc
  1285.          bit factive,c
  1286.          ld a,'-'
  1287.          jr z,$+4
  1288.          ld a,'+'
  1289.          PRCHAR_
  1290.          pop bc
  1291.          push bc
  1292.          bit fgfx,c
  1293.          ld a,' '
  1294.          jr z,$+4
  1295.          ld a,'g'
  1296.          PRCHAR_
  1297.          pop bc
  1298.           bit fwaiting,c
  1299.           ld a,' '
  1300.           jr z,$+4
  1301.           ld a,'w'
  1302.           PRCHAR_
  1303.          ld a,' '
  1304.          PRCHAR_
  1305.         ld hl,0xc000+COMMANDLINE
  1306.         call prtext
  1307.         call prcrlf
  1308. cmd_proc_skip
  1309.         pop de
  1310.         inc e
  1311.         ld a,e
  1312.         inc a ;no id 0xff
  1313.         jr nz,cmd_proc0
  1314.         ret
  1315.  
  1316. cmd_date
  1317.         OS_GETTIME ;ix=date, hl=time
  1318.         call prdate_time
  1319.         jp prcrlf
  1320.        
  1321. cmd_t0
  1322.         ld a,(wordbuf)
  1323.         and 0xdf
  1324.         sub 'A'
  1325.         call cmdsetdrive
  1326.         or a
  1327.         ret z
  1328.         ld hl,tdrivenotfound
  1329.         jp cmderror
  1330.        
  1331. cmderror
  1332.         push hl
  1333.         ld de,_ERRORCOLOR
  1334.         SETCOLOR_
  1335.         pop hl
  1336.         call prtext
  1337.         ld de,_COLOR
  1338.         SETCOLOR_
  1339. prcrlf
  1340.         ;ld a,0x0d
  1341.         ;PRCHAR_
  1342.         ;ld a,0x0a
  1343.         ;PRCHAR_
  1344.         ld hl,crlfbuf
  1345.         ld de,2
  1346.         jp cmdprNchars
  1347. crlfbuf
  1348.         db 0x0d,0x0a
  1349.        
  1350. cmdsetdrive
  1351.         ld e,a
  1352.         OS_SETDRV
  1353.         ret
  1354.  
  1355. cmd_type
  1356.         ld hl,(execcmd_pars)
  1357.         ld a,(hl)
  1358.         or a
  1359.         jp z,cmd_error_nopars
  1360.         ld de,wordbuf
  1361.         call getword ;hl=terminator/space addr
  1362.  
  1363.         ld de,wordbuf ;de=drive/path/file
  1364.         OS_OPENHANDLE
  1365.         or a
  1366.         jp nz,cmd_error_wrongfile
  1367.         ld a,b
  1368.         ld (close_file1_handle),a
  1369.         ld hl,close_file1
  1370.         push hl
  1371.        
  1372. cmd_type0
  1373. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  1374.         push bc
  1375.         ld de,cmd_type_buf
  1376.         ld hl,1
  1377.         OS_READHANDLE
  1378. ;HL = Number of bytes actually read, A=error
  1379.         pop bc
  1380.         ld a,h
  1381.         or l
  1382.         ret z ;0 bytes remain
  1383.         push bc
  1384. cmd_type_buf=$+1
  1385.         ld a,0
  1386.         PRCHAR_
  1387.         pop bc
  1388.         jr cmd_type0
  1389.        
  1390. cmd_tee
  1391. ;tee filename
  1392. ;copy sdtin to filename and to stdout
  1393.         ld hl,(execcmd_pars)
  1394.         ld a,(hl)
  1395.         or a
  1396.         jp z,cmd_error_nopars
  1397.         ld de,wordbuf
  1398.         call getword ;hl=terminator/space addr
  1399.  
  1400.         ld de,wordbuf ;de=drive/path/file
  1401.         OS_CREATEHANDLE
  1402.         or a
  1403.         jp nz,cmd_error_wrongfile
  1404.         ld a,b
  1405.         ld (close_file1_handle),a
  1406.         ld hl,close_file1
  1407.         push hl
  1408.        
  1409. cmd_tee0
  1410.         push bc
  1411.         GETKEY_
  1412.         ld (cmd_type_buf),a
  1413.         pop bc
  1414.         ret c ;input pipe closed
  1415.         ld a,(cmd_type_buf)
  1416.         PRCHAR_
  1417. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  1418.         push bc
  1419.         ld de,cmd_type_buf
  1420.         ld hl,1 ;TODO набивать буфер, потом писать много
  1421.         OS_WRITEHANDLE
  1422. ;HL = Number of bytes actually written, A=error?
  1423.         pop bc
  1424.         jr cmd_tee0
  1425.        
  1426. cmd_echo
  1427.         ld hl,(execcmd_pars)
  1428.         call prtext
  1429.         jp prcrlf
  1430.        
  1431. cmd_pause
  1432.         call yieldgetkeyloop ;YIELDGETKEYLOOP
  1433.          cp key_redraw
  1434.          jr z,cmd_pause
  1435.         ret
  1436.  
  1437. cmd_copydir
  1438.         ld hl,(execcmd_pars)
  1439.         ld a,(hl)
  1440.         or a
  1441.         jp z,cmd_error_nopars
  1442.         ld de,wordbuf
  1443.         call getword ;hl=terminator/space addr
  1444.         call skipspaces
  1445.         ld a,(hl)
  1446.         or a
  1447.         jp z,cmd_error_notenoughpars
  1448.         ld de,wordbuf2
  1449.         call getword ;hl=terminator/space addr
  1450.  
  1451. cmd_copydir_go
  1452.         ld hl,wordbuf
  1453.         call prtext
  1454.         ld a,'>'
  1455.         PRCHAR_
  1456.         ld hl,wordbuf2
  1457.         call prtext
  1458.         call prcrlf
  1459.        
  1460.         ld de,wordbuf2
  1461.         OS_MKDIR
  1462.  
  1463.         ld bc,0 ;номер файла в директории
  1464. cmd_copydir0
  1465.         push bc
  1466.         ld de,cmdprompt
  1467.         OS_CHDIR
  1468.         ld de,wordbuf
  1469.         OS_CHDIR
  1470.         pop bc
  1471.         push bc
  1472.         call getdirfcb_bc
  1473.         pop bc
  1474.         ret nz ;jr nz,cmd_copydirq
  1475.  
  1476.         ld a,(fcb_filename)
  1477.         cp '.'
  1478.         jr z,cmd_copydir0_skip
  1479.         ld a,(fcb+FCB_FATTRIB)
  1480.         and FATTRIB_DIR
  1481.         jr nz,cmd_copydir0_recursive
  1482.        
  1483.         push bc
  1484.         ld hl,fcb_filename
  1485.         ld de,filenamebuf
  1486.         call cpmname_to_dotname
  1487.         call open_setdir2_create_copy
  1488.         pop bc
  1489. cmd_copydir0_skip
  1490.         inc bc
  1491.         jr cmd_copydir0
  1492.  
  1493.         macro STRPUSH
  1494. ;hl=string addr
  1495.         xor a
  1496.         push af
  1497.          ld a,(hl)
  1498.          inc hl
  1499.          or a
  1500.          push af
  1501.         jr nz,$-4
  1502.         pop af
  1503. ;в стеке лежит \0, текст (без терминатора)
  1504.         endm
  1505.        
  1506.         macro STRPOP
  1507. ;hl=string addr
  1508.         ld d,h
  1509.         ld e,l
  1510.          pop af
  1511.          ld (hl),a
  1512.          inc hl
  1513.          or a
  1514.         jr nz,$-4
  1515.         ex de,hl
  1516.         call strmirror
  1517.         endm
  1518.        
  1519. strmirror
  1520. ;hl=string addr
  1521.         ld d,h
  1522.         ld e,l
  1523.         call strlen
  1524.         ld b,h
  1525.         ld c,l
  1526.          ld a,b
  1527.          or c
  1528.          ret z
  1529. ;de=начало, bc=hl=длина
  1530.         ;ld h,b
  1531.         ;ld l,c
  1532.         add hl,de ;hl=конец+1
  1533.         srl b
  1534.         rr c ;bc=wid/2
  1535. mirrorbytes0
  1536.         dec hl
  1537.         ld a,(de)
  1538.         ldi
  1539.         dec hl
  1540.         ld (hl),a
  1541.         jp pe,mirrorbytes0
  1542.         ret
  1543.        
  1544. cmd_copydir0_recursive
  1545. ;recursive copydir <wordbuf>/<filename> <wordbuf2>/<filename>
  1546.         push bc
  1547.         ld hl,wordbuf
  1548.         STRPUSH
  1549.         ld hl,wordbuf2
  1550.         STRPUSH
  1551.         ;ld hl,cmdprompt
  1552.         ;STRPUSH
  1553.  
  1554.         ld hl,wordbuf
  1555.         ld bc,0
  1556.         xor a
  1557.         cpir
  1558.         dec hl ;hl=terminator addr
  1559.         ld (hl),'/'
  1560.         inc hl
  1561.         ex de,hl
  1562.         ld hl,fcb_filename
  1563.         ;ld de,filenamebuf
  1564.         call cpmname_to_dotname
  1565.        
  1566.         ld hl,wordbuf2
  1567.         ld bc,0
  1568.         xor a
  1569.         cpir
  1570.         dec hl ;hl=terminator addr
  1571.         ld (hl),'/'
  1572.         inc hl
  1573.         ex de,hl
  1574.         ld hl,fcb_filename
  1575.         ;ld de,filenamebuf
  1576.         call cpmname_to_dotname
  1577.        
  1578.         call cmd_copydir_go
  1579.  
  1580. ;restore dirnames, file #
  1581.         ;ld hl,cmdprompt
  1582.         ;STRPOP
  1583.         ld hl,wordbuf2
  1584.         STRPOP
  1585.         ld hl,wordbuf
  1586.         STRPOP
  1587.         pop bc
  1588.         jp cmd_copydir0_skip
  1589.        
  1590. open_setdir2_create_copy
  1591.         ;open....
  1592.         ld de,filenamebuf;wordbuf ;de=drive/path/file
  1593.         OS_OPENHANDLE
  1594.         or a
  1595.         jp nz,cmd_error_wrongfile
  1596.         ld a,b
  1597.         ld (close_file1_handle),a
  1598.         ld hl,close_file1
  1599.         push hl
  1600.  
  1601.         ;set dir2...
  1602.         ld de,cmdprompt
  1603.         OS_CHDIR
  1604.         ld de,wordbuf2
  1605.         OS_CHDIR
  1606.  
  1607.         ;create....
  1608.         ld de,filenamebuf;2;wordbuf2 ;de=drive/path/file
  1609.         OS_CREATEHANDLE
  1610.         or a
  1611.         jp nz,cmd_error_cant_copy
  1612.         ld a,b
  1613.         ld (cmd_copy_close_file2_handle),a
  1614.         ld hl,cmd_copy_close_file2
  1615.         push hl
  1616.  
  1617.         ;copy....
  1618.         jp cmd_copy0
  1619.        
  1620.        
  1621. getdirfcb_bc
  1622. ;bc=file number in current dir to read to fcb
  1623. ;nz=error
  1624.         push bc
  1625.         ld de,fcb
  1626.         OS_SETDTA
  1627.         ld de,fcbmask
  1628.         OS_FSEARCHFIRST ;de = pointer to unopened FCB (filename with ????????), read matching FCB to DTA
  1629.         pop bc
  1630.         or a
  1631.         ret nz
  1632.        
  1633. getdirfcb_bc0
  1634.         ld a,b
  1635.         or c
  1636.         ret z
  1637.         dec bc
  1638.         push bc
  1639.         ld de,fcb
  1640.         OS_SETDTA
  1641.         ld de,fcbmask
  1642.         OS_FSEARCHNEXT ;(NOT CP/M!!!)de = pointer to unopened FCB (filename with ????????), read matching FCB to DTA
  1643.         pop bc
  1644.         or a
  1645.         jr z,getdirfcb_bc0
  1646.         ret        
  1647.        
  1648. ;hl = poi to filename in string
  1649. findlastslash.
  1650. nfopenfnslash.
  1651.         ld d,h
  1652.         ld e,l ;de = after last slash
  1653. ;find last slash
  1654. nfopenfnslash0.
  1655.         ld a,[hl]
  1656.         inc hl
  1657.         or a
  1658.         jr z,nfopenfnslashq.
  1659.         cp '/'
  1660.         jr nz,nfopenfnslash0.
  1661.         jr nfopenfnslash.
  1662. nfopenfnslashq.
  1663. ;de = after last slash
  1664.         ret
  1665.  
  1666. commandslist
  1667.         dw cmd_dir
  1668.         db "ls",0
  1669.         dw cmd_dir
  1670.         db "dir",0
  1671.         dw cmd_del
  1672.         db "del",0
  1673.         dw cmd_del
  1674.         db "rm",0
  1675.         dw cmd_exit
  1676.         db "exit",0
  1677.         dw cmd_cd
  1678.         db "cd",0
  1679.         dw cmd_copy
  1680.         db "copy",0
  1681.         dw cmd_copy
  1682.         db "cp",0
  1683.         dw cmd_rem
  1684.         db "rem",0
  1685.         dw cmd_md
  1686.         db "md",0
  1687.         dw cmd_md
  1688.         db "mkdir",0
  1689.         dw cmd_ren
  1690.         db "ren",0
  1691.         dw cmd_ren
  1692.         db "mv",0
  1693.         dw cmd_mem
  1694.         db "mem",0
  1695.         dw cmd_mem
  1696.         db "free",0
  1697.         dw cmd_proc
  1698.         db "proc",0
  1699.         dw cmd_proc
  1700.         db "ps",0
  1701.         dw cmd_tee
  1702.         db "tee",0
  1703.         dw cmd_drop
  1704.         db "drop",0
  1705.         dw cmd_drop
  1706.         db "kill",0
  1707.         dw cmd_date
  1708.         db "date",0
  1709.         dw cmd_start
  1710.         db "start",0
  1711.         dw cmd_copydir
  1712.         db "copydir",0
  1713.         dw cmd_type
  1714.         db "type",0
  1715.         dw cmd_type
  1716.         db "cat",0
  1717.         dw cmd_echo
  1718.         db "echo",0
  1719.         dw cmd_pause
  1720.         db "pause",0
  1721.        
  1722.         dw -1 ;конец таблицы команд
  1723.  
  1724. tunknowncommand
  1725.         db "Unknown command",0
  1726. tdrivenotfound
  1727.         db "Drive not found",0
  1728. tnopars
  1729.         db "No parameters",0
  1730. tnotenoughpars
  1731.         db "Not enough parameters",0
  1732. tcantcopy
  1733.         db "Can't copy",0
  1734. tcantwrite
  1735.         db "Can't write",0
  1736. twrongpath
  1737.         db "Wrong path",0
  1738. twrongfile
  1739.         db "Wrong file",0
  1740. tcantmakedir
  1741.         db "Can't make the directory",0
  1742. tcantrename
  1743.         db "Can't rename",0
  1744. t_files_crlf
  1745.         db " files",0x0d,0x0a,0
  1746. tfree
  1747.         db "free pages=",0
  1748. twrongid
  1749.         db "Wrong ID",0
  1750.        
  1751. ;oldtimer
  1752. ;        dw 0
  1753.        
  1754.         db 0 ;для запарывания на случай отсутствия пути
  1755. wordbuf
  1756.         ds MAXCMDSZ+1
  1757. wordbuf2
  1758.         ds MAXCMDSZ+1
  1759. filenamebuf
  1760.         ds MAXCMDSZ+1
  1761. filenamebuf2
  1762.         ds MAXCMDSZ+1
  1763.  
  1764. fcb
  1765.         ds FCB_sz
  1766. fcb_filename=fcb+FCB_FNAME        
  1767.  
  1768. fcbmask
  1769.         db 0
  1770.         db "???????????"
  1771.         ds FCB_sz-11-1
  1772. fcbmask_filename=fcbmask+FCB_FNAME
  1773.  
  1774. fcb2
  1775.         ds FCB_sz
  1776. fcb2_filename=fcb2+FCB_FNAME        
  1777.  
  1778. fcb_bat
  1779.         ds FCB_sz
  1780. fcb_bat_filename=fcb_bat+FCB_FNAME        
  1781.  
  1782. oldpath ;TODO убрать (когда будет loadapp через OPENHANDLE)
  1783.         ds MAXPATH_sz;MAXCMDSZ+1
  1784.  
  1785. sysdir
  1786.         ds MAXPATH_sz
  1787.        
  1788. oldcmd
  1789.         ds MAXCMDSZ+1
  1790.        
  1791. copybuf
  1792.         ds 128 ;можно сколько угодно
  1793. copybuf_sz=$-copybuf
  1794.  
  1795. params
  1796.         ds MAXCMDSZ+1
  1797.  
  1798. filinfo
  1799.         ds FILINFO_sz
  1800.  
  1801. emptypath
  1802.         db 0
  1803.  
  1804.         align 256
  1805. file_buf
  1806.         ds 128 ;buf for reading .bat
  1807. file_buf_end=$-1
  1808.  
  1809.         include "prdword.asm"
  1810.         include "cmdpr.asm"
  1811.         include "../_sdk/stdio.asm"
  1812.  
  1813. cmd_end
  1814.  
  1815.         ;display "cmd size ",/d,cmd_end-cmd_begin," bytes"
  1816.  
  1817.         savebin "cmd.com",cmd_begin,cmd_end-cmd_begin
  1818.        
  1819.         LABELSLIST "..\..\us\user.l"
  1820.