Subversion Repositories NedoOS

Rev

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

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