?login_element?

Subversion Repositories NedoOS

Rev

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

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