?login_element?

Subversion Repositories NedoOS

Rev

Rev 979 | Rev 1298 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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