?login_element?

Subversion Repositories NedoOS

Rev

Rev 1518 | Rev 1674 | 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. 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
  608.         ;jp prword_hl_crlf
  609.  
  610. loadapp_keeppath
  611.         ld hl,cmdprompt
  612.         ld de,oldpath
  613.         ld bc,MAXPATH_sz;MAXCMDSZ+1
  614.         ldir ;TODO рекурсивно (для .bat)
  615.         ret
  616.  
  617. loadapp_setoldpath
  618.         push de
  619.         ld de,oldpath ;TODO рекурсивно (для .bat)
  620.         OS_CHDIR
  621.         pop de
  622.         xor a
  623.         ret ;Z
  624.        
  625. loadapp
  626. ;out: nz=error, cy=end of .bat, or else e=id
  627.         ld hl,cmdbuf
  628.         ld de,wordbuf
  629.         call getword
  630. ;учесть путь в имени (TODO использовать OS_OPENHANDLE)
  631.         ld hl,wordbuf
  632.         push hl
  633.         call findlastslash. ;de=after last slash or beginning of path
  634.         pop hl
  635.  
  636.         ;push hl
  637. ;ищем точку, проверяем, что после неё стоит .com или .bat
  638. loadapp_finddot0
  639.         ld a,(hl)
  640.         or a
  641.         jr z,loadapp_nodot
  642.         cp '.'
  643.         inc hl
  644.         jr nz,loadapp_finddot0
  645. ;проверяем, что после неё стоит .com или .bat
  646.         ld a,(hl)
  647.         or 0x20
  648.         cp 'b'
  649. ; TODO где проверка на остальные буквы?
  650.         jp z,strcpexec_tryrun_bat
  651. ;считаем, что написано .com (в принципе расширение безразлично - просто запускаем)
  652.         jr loadapp_finddotok
  653. loadapp_nodot
  654. ;a=0
  655.         ld (hl),'.'
  656.         inc hl
  657.         ld (hl),'c'
  658.         inc hl
  659.         ld (hl),'o'
  660.         inc hl
  661.         ld (hl),'m'
  662.         inc hl
  663.         ld (hl),a ;0        
  664. loadapp_finddotok
  665.         ld de,wordbuf ;pop de
  666.         OS_OPENHANDLE
  667.         or a
  668.          push af
  669.         ld a,b
  670.         ld (curhandle),a
  671.          ;call loadapp_setoldpath
  672.        if DEBUG
  673.          call printcurdir
  674.          ;call yieldgetkeyloop
  675.        endif
  676.          pop af
  677.         ret nz ;jr nz,execcmd_error ;NC!
  678.         OS_NEWAPP ;на момент создания должна быть включена текущая директория!!!
  679.         or a
  680.         ret nz ;error ;NC!
  681. ;dehl=номера страниц в 0000,4000,8000,c000 нового приложения, b=id, a=error
  682.         push bc ;b=id
  683.         ld a,d
  684.         SETPGC000
  685.         push de
  686.         push hl
  687.         ld hl,cmdbuf
  688.         ld de,0xc000+COMMANDLINE
  689.         ld bc,COMMANDLINE_sz
  690.         ldir ;command line
  691.         pop hl
  692.         pop de
  693.         call readfile_pages_dehl
  694.  
  695.         ld a,(curhandle)
  696.         ld b,a
  697.         OS_CLOSEHANDLE
  698.         pop de
  699.         ld e,d ;e=id
  700.         xor a
  701.         ret ;Z
  702.      
  703. readapp
  704.         ld a,b
  705.         ld (curhandle),a
  706.        
  707.         OS_NEWAPP ;для первой создаваемой задачи будут созданы первые два пайпа и подключены
  708. ;dehl=номера страниц в 0000,4000,8000,c000 нового приложения, b=id, a=error
  709.         push bc ;b=id
  710.  
  711.         ld a,d
  712.         SETPGC000
  713.         push de
  714.         push hl
  715.         ld hl,COMMANDLINE ;command line
  716.         call skipword
  717.         call skipspaces ;пропустили первое слово (там было term.com, а дальше, например, cmd.com autoexec.bat)
  718.         ld de,0xc080
  719.         ld bc,128  
  720.         ldir ;command line
  721.         pop hl
  722.         pop de
  723.  
  724.         call readfile_pages_dehl
  725.  
  726.         ld a,(curhandle)
  727.         ld b,a
  728.         OS_CLOSEHANDLE
  729.  
  730.         pop af ;id
  731.         ret
  732.  
  733. skipword
  734. ;hl=string
  735. ;out: hl=terminator/space addr
  736. skipword0
  737.         ld a,(hl)
  738.         or a
  739.         ret z ;jr z,skipwordq
  740.         sub ' '
  741.         ret z ;jr z,skipwordq
  742.         inc hl ;ldi
  743.         jr skipword0
  744.  
  745. readfile_pages_dehl
  746.         ld a,d
  747.         SETPGC000
  748.         ld a,0xc100/256
  749.         call cmd_loadpage
  750.         ret nz
  751.         ld a,e
  752.         call cmd_loadfullpage
  753.         ret nz
  754.         ld a,h
  755.         call cmd_loadfullpage
  756.         ret nz
  757.         ld a,l
  758. cmd_loadfullpage
  759.         SETPGC000
  760.         ld a,0xc000/256
  761. cmd_loadpage
  762. ;out: a=error
  763. ;keeps hl,de
  764.         push de
  765.         push hl
  766.         ld d,a
  767.         xor a
  768.         ld l,a
  769.         ld e,a
  770.         sub d
  771.         ld h,a ;de=buffer, hl=size
  772. curhandle=$+1
  773.         ld b,0
  774.         OS_READHANDLE
  775.         pop hl
  776.         pop de
  777.         or a
  778.         ret
  779.      
  780. strcpexec_tryrun_bat
  781.         ;display "strcpexec_tryrun_bat",strcpexec_tryrun_bat
  782. ;out: nz=error, cy=end of .bat
  783. ;open .bat
  784. ;filename in wordbuf
  785.         ld de,wordbuf ;pop de
  786.         OS_OPENHANDLE
  787.         or a
  788.         ld a,b
  789.         ld (curbathandle),a    
  790.         ret nz ;jp nz,execcmd_error ;NC!
  791.        
  792.          ld a,0x3c ;"inc a"
  793.          ld (readbyte_readbuf_last),a
  794.         ld iy,file_buf_end
  795. strcpexec_tryrun_bat0
  796. ;load line to cmdbuf
  797.         ld hl,cmdbuf
  798.         LD (hl),0
  799.         call readstr ;nz=EOF
  800.         push af ;jr nz,strcpexec_tryrun_batq ;чтобы последнюю строку всё-таки выполнить
  801.  
  802.         push iy
  803.         ld hl,cmdbuf
  804.         call prtext
  805.         call prcrlf
  806.         pop iy
  807.        
  808. ;call command in cmdbuf
  809.         push iy
  810.         call openparams
  811.         call execcmd_maybepipes ;callcmd
  812.         pop iy
  813.        
  814.         pop af
  815.         jr z,strcpexec_tryrun_bat0 ;nz=EOF
  816. strcpexec_tryrun_batq
  817. ;close .bat
  818.         ld a,(curbathandle)
  819.         ld b,a
  820.         OS_CLOSEHANDLE
  821.         xor a
  822.          scf ;чтобы на выходе не делать RUNAPP
  823.         ret ;Z
  824.  
  825.         macro READBYTE_A
  826. ;out: z=EOF
  827.         inc ly
  828.         call m,readbyte_readbuf
  829.         ld a,(iy)
  830.         endm
  831.  
  832. readstr
  833. ;out: nz=EOF
  834. ;skips empty lines!
  835.         READBYTE_A ;z=EOF
  836.         jr z,readstrEOF
  837.         cp 0x0d
  838.         jr z,readstr ;empty string - retry
  839.         cp 0x0a
  840.         jr z,readstr ;empty string - retry
  841.         ld b,MAXCMDSZ
  842.         jr readstr0go
  843. readstr0
  844.         READBYTE_A ;z=EOF
  845.         jr z,readstrEOF ;возвращает NZ
  846.         ;jr z,readstrq ;возвращает Z
  847.         cp 0x0d
  848.         jr z,readstrq
  849.         cp 0x0a
  850.         jr z,readstrq
  851. readstr0go
  852.         ld (hl),a
  853.         inc hl
  854.         djnz readstr0
  855. readstrq
  856.         xor a ;Z
  857.         ld (hl),a
  858.         inc hl
  859.         ret ;Z
  860. readstrEOF
  861.         xor a
  862.         ld (hl),a
  863.         inc hl
  864.         dec a
  865.         ret ;NZ
  866.  
  867. readbyte_readbuf
  868. ;out: z=EOF
  869.         push bc
  870.         push de
  871.         push hl
  872.         push ix
  873.          ;jr $
  874.         xor a
  875. readbyte_readbuf_last=$ ;TODO keep if recursive!
  876.         inc a ;/nop(z)=last, inc a(nz)=not last
  877.         jr z,readbyte_readbufq
  878.  
  879.         if 1==1
  880. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  881. curbathandle=$+1
  882.         ld b,0
  883.         ld de,file_buf
  884.         push de
  885.         ld hl,128
  886.         OS_READHANDLE
  887.         pop iy
  888. ;HL = Number of bytes actually read, A=error
  889.         ;sub 1
  890.         ;sbc a,a ;error=0 => a=255, else a=0 (Z)
  891.         ;jr z,readbyte_readbufq ;error (=>EOF)
  892.          ;jr $
  893.         ld a,l
  894.         or a
  895.         jr z,readbyte_readbufq ;0 bytes (=>EOF)
  896.         jp m,readbyte_readbufq ;128 bytes (NZ no EOF) (not last block)
  897.        
  898.         else ;CP/M-like
  899.        
  900.         ld de,file_buf
  901.         push de
  902.         OS_SETDTA ;set disk transfer address = de
  903.         ld de,fcb_bat
  904.         OS_FREAD
  905.         pop iy
  906.         xor 128 ;a = bytes read
  907.         jr z,readbyte_readbufq
  908.         jp m,readbyte_readbufq ;full block = not last block
  909.        
  910.         endif
  911.        
  912. ;last block: shift data to the end of buf, mark last
  913.         ld c,a ;1..128
  914.         ld b,0 ;nz!
  915.         ld a,b
  916.         ld (readbyte_readbuf_last),a ;last block
  917.         ld hl,file_buf
  918.         add hl,bc
  919.         dec hl ;end of data
  920.         ld de,file_buf+127
  921.         lddr
  922.         inc de
  923.         push de
  924.         pop iy
  925.         ;nz!
  926. readbyte_readbufq
  927. ;iy=addr
  928. ;z=EOF
  929.         pop ix
  930.         pop hl
  931.         pop de
  932.         pop bc
  933.         ret
  934.  
  935. cmd_dir
  936.         ld de,(execcmd_pars)
  937.         ;ld de,emptypath
  938.         OS_OPENDIR
  939.         or a
  940.         ld bc,0 ;nfiles
  941.         jp nz,loaddir2_error
  942. cmd_dir2_0
  943.        push bc
  944.         ld de,filinfo
  945.         OS_READDIR
  946.        pop bc
  947.         or a
  948.         jr nz,loaddir2q
  949.         ld a,(filinfo+FILINFO_FNAME)
  950.         or a
  951.         jr z,loaddir2q
  952.        push bc
  953.         ld ix,(filinfo+FILINFO_FDATE)
  954.         ld hl,(filinfo+FILINFO_FTIME)
  955.         call prdate_time
  956.  
  957.         ld a,' '
  958.         PRCHAR_
  959.  
  960.         ld hl,(filinfo+FILINFO_FSIZE)
  961.         ld de,(filinfo+FILINFO_FSIZE+2)
  962.         call prdword_dehl
  963.         ld a,' '
  964.         PRCHAR_
  965.  
  966.         ld hl,filinfo+FILINFO_LNAME
  967.         ld a,(hl)
  968.         or a
  969.         jr nz,$+5
  970.         ld hl,filinfo+FILINFO_FNAME
  971.         ;ld c,0 ;c=x
  972.         call prtext
  973. ;c=x
  974.        
  975.         call prcrlf
  976.        pop bc ;nfiles
  977.         inc bc ;nfiles
  978.         or a
  979.         jr cmd_dir2_0
  980. loaddir2_error
  981. loaddir2q
  982. ;bc=nfiles
  983.         ld h,b
  984.         ld l,c
  985.         call prword
  986.         ld hl,t_files_crlf
  987.         jp prtext
  988.  
  989. prdate_time
  990. ;ix=date, hl=time
  991.         ld de,datetimebuf
  992.        push de
  993.        push hl ;time
  994.         ;push ix ;date
  995.         ld a,hx
  996.         srl a
  997.         sub 20
  998.         jr nc,$+4
  999.         add a,100 ;XX century
  1000.         call prNNcmd ;year
  1001.         ;ld a,'-'
  1002.         ;PRCHAR_
  1003.          inc de
  1004.         ;pop hl
  1005.         ld a,lx
  1006.         push af
  1007.         add ix,ix
  1008.         add ix,ix
  1009.         add ix,ix
  1010.         ld a,hx
  1011.         and 0x0f
  1012.         call prNNcmd ;month
  1013.         ;ld a,'-'
  1014.         ;PRCHAR_
  1015.          inc de
  1016.         pop af
  1017.         and 0x1f
  1018.         call prNNcmd ;day
  1019.  
  1020.         ;ld a,' '
  1021.         ;PRCHAR_
  1022.          inc de
  1023.        pop hl ;time
  1024.         push hl
  1025.         ld a,h
  1026.         rra
  1027.         rra
  1028.         rra
  1029.         and 0x1f
  1030.         call prNNcmd ;hour
  1031.         ;ld a,':'
  1032.         ;PRCHAR_
  1033.          inc de
  1034.         pop hl
  1035.         ld a,l
  1036.         push af
  1037.         add hl,hl
  1038.         add hl,hl
  1039.         add hl,hl
  1040.         ld a,h
  1041.         and 0x3f
  1042.         call prNNcmd ;minute
  1043.         ;ld a,':'
  1044.         ;PRCHAR_
  1045.          inc de
  1046.         pop af
  1047.         add a,a
  1048.         and 0x3f
  1049.         call prNNcmd ;second
  1050.        pop hl
  1051.         ld de,8+1+8
  1052.         jp cmdprNchars
  1053.  
  1054. prNNcmd
  1055. ;a=NN
  1056. ;de=buf
  1057.         ld bc,10+(256*('0'-1))
  1058.         sub c
  1059.         inc b
  1060.         jr nc,$-2
  1061.          ex de,hl
  1062.          ld (hl),b
  1063.          ex de,hl
  1064.          inc de
  1065.         add a,'0'+10
  1066.          ld (de),a
  1067.          inc de
  1068.         ret
  1069.  
  1070. datetimebuf
  1071.         db "00-00-00 00:00:00"
  1072.        
  1073. skipspaces
  1074. ;hl=string
  1075. ;out: hl=after last space
  1076.         ld a,(hl)
  1077.         cp ' '
  1078.         ret nz
  1079.         inc hl
  1080.         jr skipspaces
  1081.  
  1082. strcopy
  1083. ;hl->de
  1084. strcopy0
  1085.         ld a,(hl)
  1086.         ldi
  1087.         or a
  1088.         jr nz,strcopy0
  1089.         ret
  1090.  
  1091. cmd_cd
  1092. execcmd_pars=$+1
  1093.         ld hl,0
  1094.         ld a,(hl)
  1095.         or a
  1096.         jr z,cmd_error_nopars
  1097.         ex de,hl ;de=path
  1098.         OS_CHDIR
  1099.         or a
  1100.         ret z
  1101.         ld hl,twrongpath
  1102.         jp cmderror
  1103.        
  1104. cmd_error_nopars
  1105.         ld hl,tnopars
  1106.         jp cmderror
  1107. cmd_error_notenoughpars
  1108.         ld hl,tnotenoughpars
  1109.         jp cmderror
  1110.  
  1111. cmd_md
  1112.         ld hl,(execcmd_pars)
  1113.         ld a,(hl)
  1114.         or a
  1115.         jr z,cmd_error_nopars
  1116.         ex de,hl ;de=dirname
  1117.         OS_MKDIR
  1118.         or a
  1119.         ret z
  1120. cmd_error_cantmakedir
  1121.         ld hl,tcantmakedir
  1122.         jp cmderror
  1123.        
  1124. cmd_del
  1125.         ld hl,(execcmd_pars)
  1126.         ld a,(hl)
  1127.         or a
  1128.         jr z,cmd_error_nopars
  1129.         ex de,hl
  1130.         OS_DELETE
  1131.         or a
  1132.         ret z
  1133. cmd_error_wrongfile
  1134.         ld hl,twrongfile
  1135.         jp cmderror
  1136.        
  1137. cmd_ren
  1138.         ld hl,(execcmd_pars)
  1139.         ld a,(hl)
  1140.         or a
  1141.         jr z,cmd_error_nopars
  1142.         ld de,wordbuf
  1143.         call getword ;hl=terminator/space addr
  1144.         call skipspaces
  1145.         ld a,(hl)
  1146.         or a
  1147.         jr z,cmd_error_notenoughpars
  1148.         ld de,wordbuf2
  1149.         call getword ;hl=terminator/space addr
  1150.         ld de,wordbuf
  1151.         ld hl,wordbuf2
  1152.        ld a,(de)
  1153.        cp '*'
  1154.        jr z,cmd_ren_star
  1155.         OS_RENAME
  1156.         or a
  1157.         ret z
  1158. cmd_ren_star_error
  1159.         ld hl,tcantrename
  1160.         jp cmderror
  1161. cmd_ren_star
  1162.        cp (hl)
  1163.        jr nz,cmd_ren_star_error
  1164. ;поддерживаем только переименование вида ren *.ext1 *.ext2
  1165.         inc hl
  1166.         inc de
  1167.         ld a,(de)
  1168.        cp '.'
  1169.        jr nz,cmd_ren_star_error
  1170.        cp (hl)
  1171.        jr nz,cmd_ren_star_error
  1172.         inc hl
  1173.         inc de
  1174. ;de,hl указывают на ext1, ext2
  1175.         ld (cmd_ren_star_ext1),de
  1176.         ld (cmd_ren_star_ext2),hl
  1177.         ld de,emptypath
  1178.         OS_OPENDIR
  1179. ;проверяем все файлы в текущей директории на соответствие filename.ext1
  1180. ;если совпало, то переименовываем в filename.ext2
  1181. cmd_ren_star0
  1182.         ld de,filinfo
  1183. ;de=buf for FILINFO (if no LNAME, use FNAME), 0x00 in FILINFO_FNAME = end dir
  1184.         OS_READDIR
  1185. ;out in A=error(0 - no error, 4 - no more files, other - critical error)
  1186.         or a
  1187.         ret nz ;todo show N files renamed
  1188.         ld hl,filinfo+FILINFO_LNAME ;длинного имени может не быть
  1189.         ld a,(hl)
  1190.         or a
  1191.         jr nz,$+5
  1192.          ld hl,filinfo+FILINFO_FNAME
  1193.        push hl ;from name
  1194.         call findlastdot
  1195. ;de=after last dot
  1196. cmd_ren_star_ext1=$+1
  1197.         ld hl,0
  1198.         call strcp ;z=yes
  1199.        pop hl ;from name
  1200.         jr nz,cmd_ren_star0
  1201.  
  1202.         ;ld hl,filinfo+FILINFO_LNAME
  1203.        push hl ;from name
  1204.         ld de,filenamebuf
  1205.        push de
  1206.         call strcopy
  1207.        pop hl ;to name
  1208.        push hl
  1209.         call findlastdot
  1210. ;de=after last dot in toname
  1211. cmd_ren_star_ext2=$+1
  1212.         ld hl,0
  1213.         call strcopy ;z=yes ;возможное переполнение уходит в filenamebuf2
  1214.        pop hl ;to name
  1215.        pop de ;from name
  1216.         ;ld hl,filenamebuf2 ;to name
  1217.         OS_RENAME
  1218. ;TODO inc count
  1219.         jr cmd_ren_star0
  1220.  
  1221. cmd_copy
  1222.         ld hl,(execcmd_pars)
  1223.         ld a,(hl)
  1224.         or a
  1225.         jp z,cmd_error_nopars
  1226.         ld de,filenamebuf;wordbuf
  1227.         call getword ;hl=terminator/space addr
  1228.         call skipspaces
  1229.         ld a,(hl)
  1230.         or a
  1231.         jp z,cmd_error_notenoughpars
  1232.         ld de,filenamebuf2;wordbuf2
  1233.         call getword ;hl=terminator/space addr
  1234.  
  1235.         ld de,filenamebuf;wordbuf ;de=drive/path/file
  1236.         OS_OPENHANDLE
  1237.         or a
  1238.         jp nz,cmd_error_wrongfile
  1239.         ld a,b
  1240.         ld (close_file1_handle),a
  1241.         ld hl,close_file1
  1242.         push hl
  1243.        
  1244.         ld de,filenamebuf2;wordbuf2 ;de=drive/path/file
  1245.         OS_CREATEHANDLE
  1246.         or a
  1247.         jp nz,cmd_error_cant_copy
  1248.         ld a,b
  1249.         ld (cmd_copy_close_file2_handle),a
  1250.         ld hl,cmd_copy_close_file2
  1251.         push hl
  1252. cmd_copy0
  1253.         ld hl,copybuf_sz
  1254.         ld de,copybuf
  1255.         ld a,(close_file1_handle)
  1256.         ld b,a
  1257. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  1258.         push de
  1259.         OS_READHANDLE
  1260. ;HL = Number of bytes actually read, A=error
  1261.         pop de
  1262.         ld a,h
  1263.         or l
  1264.         ret z ;0 bytes remain
  1265.         ld a,(cmd_copy_close_file2_handle)
  1266.         ld b,a
  1267. ;B = file handle, DE = Buffer address, HL = Number of bytes to write
  1268.         OS_WRITEHANDLE
  1269.         jr cmd_copy0
  1270.        
  1271. close_file1
  1272. close_file1_handle=$+1
  1273.         ld b,0
  1274.         OS_CLOSEHANDLE
  1275.         ret
  1276.        
  1277. cmd_copy_close_file2
  1278. cmd_copy_close_file2_handle=$+1
  1279.         ld b,0
  1280.         OS_CLOSEHANDLE
  1281.         ld de,filenamebuf;wordbuf;filenametext
  1282.         OS_GETFILETIME ;ix=date, hl=time
  1283.         ld de,filenamebuf2;wordbuf2
  1284.         OS_SETFILETIME
  1285.         ret      
  1286.        
  1287. cmd_error_cant_copy
  1288.         ld hl,tcantcopy
  1289.         jp cmderror
  1290.  
  1291. cmd_rem
  1292.         ret
  1293.        
  1294. cmd_mem
  1295.         ld hl,tfree
  1296.         call prtext
  1297.         ld b,0
  1298. cmd_mem0
  1299.         push bc
  1300.         OS_NEWPAGE
  1301.         pop bc
  1302.         or a
  1303.         jr nz,cmd_mem_del
  1304.         inc b
  1305.         push de
  1306.         jr cmd_mem0
  1307. cmd_mem_del
  1308.         ld c,b
  1309.         inc b
  1310.         dec b
  1311.         jr z,cmd_mem_q
  1312. cmd_mem_del0
  1313.         pop de
  1314.         push bc
  1315.         OS_DELPAGE
  1316.         pop bc
  1317.         djnz cmd_mem_del0
  1318. cmd_mem_q
  1319. ;c=free pages
  1320.         ld l,c
  1321.         ld h,0
  1322. prword_hl_crlf
  1323.         call prword
  1324.         jp prcrlf
  1325.  
  1326. cmd_drop
  1327.         ld hl,(execcmd_pars)
  1328.         ld a,(hl)
  1329.         or a
  1330.         jp z,cmd_error_nopars
  1331.         xor a
  1332.         ld d,a
  1333. cmd_drop_par0
  1334.         add a,d
  1335.         ld e,a ;id
  1336.         add a,a
  1337.         add a,a
  1338.         add a,e
  1339.         add a,a
  1340.         ld d,a ;d=e*10
  1341.         ld a,(hl)
  1342.         inc hl
  1343.         sub '0'
  1344.         cp 10
  1345.         jr c,cmd_drop_par0
  1346.         ;e=id
  1347.         OS_DROPAPP
  1348.         or a
  1349.         ret z
  1350.         ld hl,twrongid
  1351.         jp cmderror
  1352.        
  1353. cmd_proc
  1354.         ld e,1 ;no id 0
  1355. cmd_proc0
  1356.        ld a,e
  1357.        ld (cmd_proc_id),a
  1358.         push de
  1359.         OS_GETAPPMAINPAGES ;d,e,h,l=pages in 0000,4000,8000,c000, c=flags
  1360.         or a
  1361.         jr nz,cmd_proc_skip
  1362.         ld a,d
  1363.         pop de ;e=id
  1364.         push de ;e=id
  1365.          push bc
  1366.         push af ;main page
  1367.         ex de,hl ;l=id
  1368.         ld h,0
  1369.         call prword
  1370.         ld a,' '
  1371.         PRCHAR_
  1372.         pop af ;main page
  1373.         SETPGC000
  1374.          pop bc ;c=flags
  1375.          push bc
  1376.          bit factive,c
  1377.          ld a,'-'
  1378.          jr z,$+4
  1379.          ld a,'+'
  1380.          PRCHAR_
  1381.          pop bc
  1382.          push bc
  1383.          bit fgfx,c
  1384.          ld a,' '
  1385.          jr z,$+4
  1386.          ld a,'g'
  1387.          PRCHAR_
  1388.          pop bc
  1389.           bit fwaiting,c
  1390.           ld a,' '
  1391.           jr z,$+4
  1392.           ld a,'w'
  1393.           PRCHAR_
  1394.          ld a,' '
  1395.          PRCHAR_
  1396.  
  1397.         ld de,0 ;e=page, d=number of pages for this id
  1398. cmd_proc_countmem0
  1399.        push de
  1400.         OS_GETPAGEOWNER
  1401.         ld a,e
  1402.        pop de
  1403. cmd_proc_id=$+1
  1404.         cp 0
  1405.         jr nz,$+3
  1406.          inc d
  1407.         inc e
  1408.         jr nz,cmd_proc_countmem0
  1409.         ld l,d ;print number of used pages
  1410.         ld h,0
  1411.         call prword
  1412.  
  1413.          ld a,' '
  1414.          PRCHAR_
  1415.          
  1416.         ld hl,0xc000+COMMANDLINE
  1417.         call prtext
  1418.         call prcrlf
  1419. cmd_proc_skip
  1420.         pop de
  1421.         inc e
  1422.         ld a,e
  1423.         inc a ;no id 0xff
  1424.         jr nz,cmd_proc0
  1425.         ret
  1426.  
  1427. cmd_date
  1428.         OS_GETTIME ;ix=date, hl=time
  1429.         call prdate_time
  1430.         jp prcrlf
  1431.        
  1432. cmd_t0
  1433.         ld a,(wordbuf)
  1434.         and 0xdf
  1435.         sub 'A'
  1436.         call cmdsetdrive
  1437.         or a
  1438.         ret z
  1439.         ld hl,tdrivenotfound
  1440.         jp cmderror
  1441.        
  1442. cmderror
  1443.         push hl
  1444.         ld de,_ERRORCOLOR
  1445.         SETCOLOR_
  1446.         pop hl
  1447.         call prtext
  1448.         ld de,_COLOR
  1449.         SETCOLOR_
  1450. prcrlf
  1451.         ;ld a,0x0d
  1452.         ;PRCHAR_
  1453.         ;ld a,0x0a
  1454.         ;PRCHAR_
  1455.         ld hl,crlfbuf
  1456.         ld de,2
  1457.         jp cmdprNchars
  1458. crlfbuf
  1459.         db 0x0d,0x0a
  1460.        
  1461. cmdsetdrive
  1462.         ld e,a
  1463.         OS_SETDRV
  1464.         ret
  1465.  
  1466. cmd_type
  1467.         ld hl,(execcmd_pars)
  1468.         ld a,(hl)
  1469.         or a
  1470.         jp z,cmd_error_nopars
  1471.         ld de,wordbuf
  1472.         call getword ;hl=terminator/space addr
  1473.  
  1474.        if DEBUG
  1475.         ld hl,wordbuf
  1476.         ld c,0
  1477.         call prtext
  1478.         call prcrlf
  1479.        endif
  1480.  
  1481.         ld de,wordbuf ;de=drive/path/file
  1482.         OS_OPENHANDLE
  1483.         or a
  1484.         jp nz,cmd_error_wrongfile
  1485.         ld a,b
  1486.         ld (close_file1_handle),a
  1487.         ld hl,close_file1
  1488.         push hl
  1489.        
  1490. cmd_type0
  1491. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  1492.         push bc
  1493.         ld de,cmd_type_buf
  1494.         ld hl,1
  1495.         OS_READHANDLE
  1496. ;HL = Number of bytes actually read, A=error
  1497.         pop bc
  1498.         ld a,h
  1499.         or l
  1500.         ret z ;0 bytes remain
  1501.         push bc
  1502. cmd_type_buf=$+1
  1503.         ld a,0
  1504.         PRCHAR_
  1505.         pop bc
  1506.         jr cmd_type0
  1507.        
  1508. cmd_tee
  1509. ;tee filename
  1510. ;copy sdtin to filename and to stdout
  1511.         ld hl,(execcmd_pars)
  1512.         ld a,(hl)
  1513.         or a
  1514.         jp z,cmd_error_nopars
  1515.         ld de,wordbuf
  1516.         call getword ;hl=terminator/space addr
  1517.  
  1518.         ld de,wordbuf ;de=drive/path/file
  1519.         OS_CREATEHANDLE
  1520.         or a
  1521.         jp nz,cmd_error_wrongfile
  1522.         ld a,b
  1523.         ld (close_file1_handle),a
  1524.         ld hl,close_file1
  1525.         push hl
  1526.        
  1527. cmd_tee0
  1528.         push bc
  1529.         GETKEY_
  1530.         ld (cmd_type_buf),a
  1531.         pop bc
  1532.         ret c ;input pipe closed
  1533.         ld a,(cmd_type_buf)
  1534.         PRCHAR_
  1535. ;B = file handle, DE = Buffer address, HL = Number of bytes to read
  1536.         push bc
  1537.         ld de,cmd_type_buf
  1538.         ld hl,1 ;TODO набивать буфер, потом писать много
  1539.         OS_WRITEHANDLE
  1540. ;HL = Number of bytes actually written, A=error?
  1541.         pop bc
  1542.         jr cmd_tee0
  1543.        
  1544. cmd_echo
  1545.         ld hl,(execcmd_pars)
  1546.         call prtext
  1547.         jp prcrlf
  1548.        
  1549. cmd_pause
  1550.         call yieldgetkeyloop ;YIELDGETKEYLOOP
  1551.          cp key_redraw
  1552.          jr z,cmd_pause
  1553.         ret
  1554.  
  1555. cmd_copydir
  1556.         ld hl,(execcmd_pars)
  1557.         ld a,(hl)
  1558.         or a
  1559.         jp z,cmd_error_nopars
  1560.         ld de,wordbuf
  1561.         call getword ;hl=terminator/space addr
  1562.         call skipspaces
  1563.         ld a,(hl)
  1564.         or a
  1565.         jp z,cmd_error_notenoughpars
  1566.         ld de,wordbuf2
  1567.         call getword ;hl=terminator/space addr
  1568.  
  1569. cmd_copydir_go
  1570.         ld hl,wordbuf
  1571.         call prtext
  1572.         ld a,'>'
  1573.         PRCHAR_
  1574.         ld hl,wordbuf2
  1575.         call prtext
  1576.         call prcrlf
  1577.        
  1578.         ld de,wordbuf2
  1579.         OS_MKDIR
  1580.  
  1581.         ld bc,0 ;номер файла в директории
  1582. cmd_copydir0
  1583.         push bc
  1584.         ld de,cmdprompt
  1585.         OS_CHDIR
  1586.         ld de,wordbuf
  1587.         OS_CHDIR
  1588.         pop bc
  1589.         push bc
  1590.         call getdirfcb_bc
  1591.         pop bc
  1592.         ret nz ;jr nz,cmd_copydirq
  1593.  
  1594.         ld a,(fcb_filename)
  1595.         cp '.'
  1596.         jr z,cmd_copydir0_skip
  1597.         ld a,(fcb+FCB_FATTRIB)
  1598.         and FATTRIB_DIR
  1599.         jr nz,cmd_copydir0_recursive
  1600.        
  1601.         push bc
  1602.         ld hl,fcb_filename
  1603.         ld de,filenamebuf
  1604.         call cpmname_to_dotname
  1605.         call open_setdir2_create_copy
  1606.         pop bc
  1607. cmd_copydir0_skip
  1608.         inc bc
  1609.         jr cmd_copydir0
  1610.  
  1611.         macro STRPUSH
  1612. ;hl=string addr
  1613.         xor a
  1614.         push af
  1615.          ld a,(hl)
  1616.          inc hl
  1617.          or a
  1618.          push af
  1619.         jr nz,$-4
  1620.         pop af
  1621. ;в стеке лежит \0, текст (без терминатора)
  1622.         endm
  1623.        
  1624.         macro STRPOP
  1625. ;hl=string addr
  1626.         ld d,h
  1627.         ld e,l
  1628.          pop af
  1629.          ld (hl),a
  1630.          inc hl
  1631.          or a
  1632.         jr nz,$-4
  1633.         ex de,hl
  1634.         call strmirror
  1635.         endm
  1636.        
  1637. strmirror
  1638. ;hl=string addr
  1639.         ld d,h
  1640.         ld e,l
  1641.         call strlen
  1642.         ld b,h
  1643.         ld c,l
  1644.          ld a,b
  1645.          or c
  1646.          ret z
  1647. ;de=начало, bc=hl=длина
  1648.         ;ld h,b
  1649.         ;ld l,c
  1650.         add hl,de ;hl=конец+1
  1651.         srl b
  1652.         rr c ;bc=wid/2
  1653. mirrorbytes0
  1654.         dec hl
  1655.         ld a,(de)
  1656.         ldi
  1657.         dec hl
  1658.         ld (hl),a
  1659.         jp pe,mirrorbytes0
  1660.         ret
  1661.        
  1662. cmd_copydir0_recursive
  1663. ;recursive copydir <wordbuf>/<filename> <wordbuf2>/<filename>
  1664.         push bc
  1665.         ld hl,wordbuf
  1666.         STRPUSH
  1667.         ld hl,wordbuf2
  1668.         STRPUSH
  1669.         ;ld hl,cmdprompt
  1670.         ;STRPUSH
  1671.  
  1672.         ld hl,wordbuf
  1673.         ld bc,0
  1674.         xor a
  1675.         cpir
  1676.         dec hl ;hl=terminator addr
  1677.         ld (hl),'/'
  1678.         inc hl
  1679.         ex de,hl
  1680.         ld hl,fcb_filename
  1681.         ;ld de,filenamebuf
  1682.         call cpmname_to_dotname
  1683.        
  1684.         ld hl,wordbuf2
  1685.         ld bc,0
  1686.         xor a
  1687.         cpir
  1688.         dec hl ;hl=terminator addr
  1689.         ld (hl),'/'
  1690.         inc hl
  1691.         ex de,hl
  1692.         ld hl,fcb_filename
  1693.         ;ld de,filenamebuf
  1694.         call cpmname_to_dotname
  1695.        
  1696.         call cmd_copydir_go
  1697.  
  1698. ;restore dirnames, file #
  1699.         ;ld hl,cmdprompt
  1700.         ;STRPOP
  1701.         ld hl,wordbuf2
  1702.         STRPOP
  1703.         ld hl,wordbuf
  1704.         STRPOP
  1705.         pop bc
  1706.         jp cmd_copydir0_skip
  1707.        
  1708. open_setdir2_create_copy
  1709.         ;open....
  1710.         ld de,filenamebuf;wordbuf ;de=drive/path/file
  1711.         OS_OPENHANDLE
  1712.         or a
  1713.         jp nz,cmd_error_wrongfile
  1714.         ld a,b
  1715.         ld (close_file1_handle),a
  1716.         ld hl,close_file1
  1717.         push hl
  1718.  
  1719.         ;set dir2...
  1720.         ld de,cmdprompt
  1721.         OS_CHDIR
  1722.         ld de,wordbuf2
  1723.         OS_CHDIR
  1724.  
  1725.         ;create....
  1726.         ld de,filenamebuf;2;wordbuf2 ;de=drive/path/file
  1727.         OS_CREATEHANDLE
  1728.         or a
  1729.         jp nz,cmd_error_cant_copy
  1730.         ld a,b
  1731.         ld (cmd_copy_close_file2_handle),a
  1732.         ld hl,cmd_copy_close_file2
  1733.         push hl
  1734.  
  1735.         ;copy....
  1736.         jp cmd_copy0
  1737.        
  1738.        
  1739. getdirfcb_bc
  1740. ;bc=file number in current dir to read to fcb
  1741. ;nz=error
  1742.         push bc
  1743.         ld de,fcb
  1744.         OS_SETDTA
  1745.         ld de,fcbmask
  1746.         OS_FSEARCHFIRST ;de = pointer to unopened FCB (filename with ????????), read matching FCB to DTA
  1747.         pop bc
  1748.         or a
  1749.         ret nz
  1750.        
  1751. getdirfcb_bc0
  1752.         ld a,b
  1753.         or c
  1754.         ret z
  1755.         dec bc
  1756.         push bc
  1757.         ld de,fcb
  1758.         OS_SETDTA
  1759.         ld de,fcbmask
  1760.         OS_FSEARCHNEXT ;(NOT CP/M!!!)de = pointer to unopened FCB (filename with ????????), read matching FCB to DTA
  1761.         pop bc
  1762.         or a
  1763.         jr z,getdirfcb_bc0
  1764.         ret        
  1765.        
  1766. ;hl = poi to filename in string
  1767. ;out: ;de = after last slash
  1768. findlastslash.
  1769. nfopenfnslash.
  1770.         ld d,h
  1771.         ld e,l ;de = after last slash
  1772. nfopenfnslash0.
  1773.         ld a,[hl]
  1774.         inc hl
  1775.         or a
  1776.         ret z ;jr z,nfopenfnslashq.
  1777.         cp '/'
  1778.         jr nz,nfopenfnslash0.
  1779.         jr nfopenfnslash.
  1780. ;nfopenfnslashq.
  1781. ;de = after last slash
  1782.         ;ret
  1783.  
  1784. ;hl = poi to filename in string
  1785. ;out: ;de = after last slash
  1786. findlastdot
  1787. nfopenfndot.
  1788.         ld d,h
  1789.         ld e,l ;de = after last dot
  1790. nfopenfndot0.
  1791.         ld a,[hl]
  1792.         inc hl
  1793.         or a
  1794.         ret z
  1795.         cp '.'
  1796.         jr nz,nfopenfndot0.
  1797.         jr nfopenfndot.
  1798.  
  1799. commandslist
  1800.         dw cmd_dir
  1801.         db "ls",0
  1802.         dw cmd_dir
  1803.         db "dir",0
  1804.         dw cmd_del
  1805.         db "del",0
  1806.         dw cmd_del
  1807.         db "rm",0
  1808.         dw cmd_exit
  1809.         db "exit",0
  1810.         dw cmd_exit
  1811.         db "quit",0
  1812.         dw cmd_cd
  1813.         db "cd",0
  1814.         dw cmd_copy
  1815.         db "copy",0
  1816.         dw cmd_copy
  1817.         db "cp",0
  1818.         dw cmd_rem
  1819.         db "rem",0
  1820.         dw cmd_md
  1821.         db "md",0
  1822.         dw cmd_md
  1823.         db "mkdir",0
  1824.         dw cmd_ren
  1825.         db "ren",0
  1826.         dw cmd_ren
  1827.         db "mv",0
  1828.         dw cmd_mem
  1829.         db "mem",0
  1830.         dw cmd_mem
  1831.         db "free",0
  1832.         dw cmd_proc
  1833.         db "proc",0
  1834.         dw cmd_proc
  1835.         db "ps",0
  1836.         dw cmd_tee
  1837.         db "tee",0
  1838.         dw cmd_drop
  1839.         db "drop",0
  1840.         dw cmd_drop
  1841.         db "kill",0
  1842.         dw cmd_date
  1843.         db "date",0
  1844.         dw cmd_start
  1845.         db "start",0
  1846.         dw cmd_copydir
  1847.         db "copydir",0
  1848.         dw cmd_type
  1849.         db "type",0
  1850.         dw cmd_type
  1851.         db "cat",0
  1852.         dw cmd_echo
  1853.         db "echo",0
  1854.         dw cmd_pause
  1855.         db "pause",0
  1856.         dw cmd_cls
  1857.         db "cls",0
  1858.        
  1859.         dw -1 ;конец таблицы команд
  1860.  
  1861. tunknowncommand
  1862.         db "Unknown command",0
  1863. tdrivenotfound
  1864.         db "Drive not found",0
  1865. tnopars
  1866.         db "No parameters",0
  1867. tnotenoughpars
  1868.         db "Not enough parameters",0
  1869. tcantcopy
  1870.         db "Can't copy",0
  1871. tcantwrite
  1872.         db "Can't write",0
  1873. twrongpath
  1874.         db "Wrong path",0
  1875. twrongfile
  1876.         db "Wrong file",0
  1877. tcantmakedir
  1878.         db "Can't make the directory",0
  1879. tcantrename
  1880.         db "Can't rename",0
  1881. t_files_crlf
  1882.         db " files",0x0d,0x0a,0
  1883. tfree
  1884.         db "free pages=",0
  1885. twrongid
  1886.         db "Wrong ID",0
  1887.        
  1888. ;oldtimer
  1889. ;        dw 0
  1890.        
  1891.         db 0 ;для запарывания на случай отсутствия пути
  1892. wordbuf
  1893.         ds MAXCMDSZ+1
  1894. wordbuf2
  1895.         ds MAXCMDSZ+1
  1896. filenamebuf
  1897.         ds MAXCMDSZ+1
  1898. filenamebuf2
  1899.         ds MAXCMDSZ+1
  1900.  
  1901. fcb
  1902.         ds FCB_sz
  1903. fcb_filename=fcb+FCB_FNAME        
  1904.  
  1905. fcbmask
  1906.         db 0
  1907.         db "???????????"
  1908.         ds FCB_sz-11-1
  1909. fcbmask_filename=fcbmask+FCB_FNAME
  1910.  
  1911. fcb2
  1912.         ds FCB_sz
  1913. fcb2_filename=fcb2+FCB_FNAME        
  1914.  
  1915. fcb_bat
  1916.         ds FCB_sz
  1917. fcb_bat_filename=fcb_bat+FCB_FNAME        
  1918.  
  1919. oldpath ;TODO убрать (когда будет loadapp через OPENHANDLE)
  1920.         ds MAXPATH_sz;MAXCMDSZ+1
  1921.  
  1922. sysdir
  1923.         ds MAXPATH_sz
  1924.        
  1925. oldcmd
  1926.         ds MAXCMDSZ+1
  1927.        
  1928. copybuf
  1929.         ds 4096;128 ;можно сколько угодно
  1930. copybuf_sz=$-copybuf
  1931.  
  1932. params
  1933.         ds MAXCMDSZ+1
  1934.  
  1935. filinfo
  1936.         ds FILINFO_sz
  1937.  
  1938. emptypath
  1939.         db 0
  1940.  
  1941.         align 256
  1942. file_buf
  1943.         ds 128 ;buf for reading .bat
  1944. file_buf_end=$-1
  1945.  
  1946.         if DEBUG
  1947. printcurdir
  1948.         ld de,curdir__
  1949.         push de
  1950.         OS_GETPATH
  1951.         pop hl
  1952.         ld c,0
  1953.         call prtext
  1954.         call prcrlf
  1955.         ret
  1956. curdir__
  1957.         ds 256
  1958.         endif
  1959.  
  1960. prword
  1961.         ld de,0
  1962.         jp prdword_dehl
  1963.  
  1964.         include "../_sdk/prdword.asm"
  1965.         include "cmdpr.asm"
  1966.         include "../_sdk/stdio.asm"
  1967.  
  1968. cmd_cls=clearterm ;print 25 lines of spaces except one
  1969.  
  1970. cmd_end
  1971.  
  1972.         ;display "cmd size ",/d,cmd_end-cmd_begin," bytes"
  1973.  
  1974.         savebin "cmd.com",cmd_begin,cmd_end-cmd_begin
  1975.        
  1976.         LABELSLIST "../../us/user.l",1
  1977.