?login_element?

Subversion Repositories NedoOS

Rev

Rev 1299 | Rev 1506 | 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;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.         SETPG32KHIGH
  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.         SETPG32KHIGH
  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.         SETPG32KHIGH
  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.         SETPG32KHIGH
  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+2)
  960.         exx
  961.         ld hl,(filinfo+FILINFO_FSIZE)
  962.         call prdword
  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.         SETPG32KHIGH
  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_cd
  1811.         db "cd",0
  1812.         dw cmd_copy
  1813.         db "copy",0
  1814.         dw cmd_copy
  1815.         db "cp",0
  1816.         dw cmd_rem
  1817.         db "rem",0
  1818.         dw cmd_md
  1819.         db "md",0
  1820.         dw cmd_md
  1821.         db "mkdir",0
  1822.         dw cmd_ren
  1823.         db "ren",0
  1824.         dw cmd_ren
  1825.         db "mv",0
  1826.         dw cmd_mem
  1827.         db "mem",0
  1828.         dw cmd_mem
  1829.         db "free",0
  1830.         dw cmd_proc
  1831.         db "proc",0
  1832.         dw cmd_proc
  1833.         db "ps",0
  1834.         dw cmd_tee
  1835.         db "tee",0
  1836.         dw cmd_drop
  1837.         db "drop",0
  1838.         dw cmd_drop
  1839.         db "kill",0
  1840.         dw cmd_date
  1841.         db "date",0
  1842.         dw cmd_start
  1843.         db "start",0
  1844.         dw cmd_copydir
  1845.         db "copydir",0
  1846.         dw cmd_type
  1847.         db "type",0
  1848.         dw cmd_type
  1849.         db "cat",0
  1850.         dw cmd_echo
  1851.         db "echo",0
  1852.         dw cmd_pause
  1853.         db "pause",0
  1854.         dw cmd_cls
  1855.         db "cls",0
  1856.        
  1857.         dw -1 ;конец таблицы команд
  1858.  
  1859. tunknowncommand
  1860.         db "Unknown command",0
  1861. tdrivenotfound
  1862.         db "Drive not found",0
  1863. tnopars
  1864.         db "No parameters",0
  1865. tnotenoughpars
  1866.         db "Not enough parameters",0
  1867. tcantcopy
  1868.         db "Can't copy",0
  1869. tcantwrite
  1870.         db "Can't write",0
  1871. twrongpath
  1872.         db "Wrong path",0
  1873. twrongfile
  1874.         db "Wrong file",0
  1875. tcantmakedir
  1876.         db "Can't make the directory",0
  1877. tcantrename
  1878.         db "Can't rename",0
  1879. t_files_crlf
  1880.         db " files",0x0d,0x0a,0
  1881. tfree
  1882.         db "free pages=",0
  1883. twrongid
  1884.         db "Wrong ID",0
  1885.        
  1886. ;oldtimer
  1887. ;        dw 0
  1888.        
  1889.         db 0 ;для запарывания на случай отсутствия пути
  1890. wordbuf
  1891.         ds MAXCMDSZ+1
  1892. wordbuf2
  1893.         ds MAXCMDSZ+1
  1894. filenamebuf
  1895.         ds MAXCMDSZ+1
  1896. filenamebuf2
  1897.         ds MAXCMDSZ+1
  1898.  
  1899. fcb
  1900.         ds FCB_sz
  1901. fcb_filename=fcb+FCB_FNAME        
  1902.  
  1903. fcbmask
  1904.         db 0
  1905.         db "???????????"
  1906.         ds FCB_sz-11-1
  1907. fcbmask_filename=fcbmask+FCB_FNAME
  1908.  
  1909. fcb2
  1910.         ds FCB_sz
  1911. fcb2_filename=fcb2+FCB_FNAME        
  1912.  
  1913. fcb_bat
  1914.         ds FCB_sz
  1915. fcb_bat_filename=fcb_bat+FCB_FNAME        
  1916.  
  1917. oldpath ;TODO убрать (когда будет loadapp через OPENHANDLE)
  1918.         ds MAXPATH_sz;MAXCMDSZ+1
  1919.  
  1920. sysdir
  1921.         ds MAXPATH_sz
  1922.        
  1923. oldcmd
  1924.         ds MAXCMDSZ+1
  1925.        
  1926. copybuf
  1927.         ds 4096;128 ;можно сколько угодно
  1928. copybuf_sz=$-copybuf
  1929.  
  1930. params
  1931.         ds MAXCMDSZ+1
  1932.  
  1933. filinfo
  1934.         ds FILINFO_sz
  1935.  
  1936. emptypath
  1937.         db 0
  1938.  
  1939.         align 256
  1940. file_buf
  1941.         ds 128 ;buf for reading .bat
  1942. file_buf_end=$-1
  1943.  
  1944.         if DEBUG
  1945. printcurdir
  1946.         ld de,curdir__
  1947.         push de
  1948.         OS_GETPATH
  1949.         pop hl
  1950.         ld c,0
  1951.         call prtext
  1952.         call prcrlf
  1953.         ret
  1954. curdir__
  1955.         ds 256
  1956.         endif
  1957.  
  1958.         include "prdword.asm"
  1959.         include "cmdpr.asm"
  1960.         include "../_sdk/stdio.asm"
  1961.  
  1962. cmd_cls=clearterm ;print 25 lines of spaces except one
  1963.  
  1964. cmd_end
  1965.  
  1966.         ;display "cmd size ",/d,cmd_end-cmd_begin," bytes"
  1967.  
  1968.         savebin "cmd.com",cmd_begin,cmd_end-cmd_begin
  1969.        
  1970.         LABELSLIST "..\..\us\user.l"
  1971.