?login_element?

Subversion Repositories NedoOS

Rev

Rev 1863 | Blame | Compare with Previous | Last modification | View Log | Download

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