Subversion Repositories NedoOS

Rev

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