; Обработка BAT-файлов ; ;fhandle BAT_FM: db 0 ; дескр. bat-файла ;count: db 0 ; число прочит. байт из файла ; флаг echo-режима echo_mode: db true ; 1/0 on/off ; буфер bat-файла ;T98B9: ds 256 ; IF 0 ; CALL RUN_BAT ; CALL BATCH ; CALL MAKE_BATCH_PRM_ARRAY ; CALL NEWLINE ; CALL CMDMODE ; CALL EVALCMD ; CALL RUN_BAT ; ENDIF ;------------------------------------------------- ; Запуск bat-файла ; вход: hl=имя файла ;------------------------------------------------- RUN_BAT: call BATCH jp c,A83DD ; ошибка откр. файла (cpp.asm) ret ;------------------------------------------------- ; вход: b=число слов "ZERO".."NINE" MAKE_BATCH_PRM_ARRAY: dec hl .loop: inc hl ld a,(hl) or a ret z cp " " jr z,.loop cp 9 ; Tab jr z,.loop ex de,hl ld (hl),e inc hl ld (hl),d inc hl ex de,hl .B_FIND_SPACE: inc hl ld a,(hl) cp " "+1 jr nc,.B_FIND_SPACE ld (hl),0 or a ret z djnz .loop ret ;------------------------------------------------- ; Загрузка и выполнение BAT-файла ; вход: hl=имя файла ; выход: "CF" - ошибка откр. файла ;------------------------------------------------- BATCH: ; [ ] 11/12/23 вложенные bat ld a,(BAT_FM) or a jr nz,.new_process ; push hl ; сохр. имя bat-файла ld de,work_buffer ; 512 местный буфер call copy_string ; скопир. строку (с нулем) ld hl,work_buffer ; 512 местный буфер ld de,BAT_PRM_ARRAY ; таблица указат. на "ZERO".."NINE" ld b,BAT_PRM_ARRAY.TOTAL ; число слов "ZERO".."NINE" call MAKE_BATCH_PRM_ARRAY jr nz,.B_ALL_P ld hl,NULL ; ds 2*10 ex de,hl .B_CLR_P: ld (hl),e inc hl ld (hl),d inc hl djnz .B_CLR_P ex de,hl .B_ALL_P:;- pop hl ; восст. имя bat-файла ld a,Dss.Open.R ; на чтение ld c,Dss.Open ; открыть файл RST ToDSS ;push af ; сохр. код ошибки ;call c,restore_disk_path ; восст. тек. диск и путь ;R10 ;CALL Restore_Screen ;R10 ;pop af ret c ld (BAT_FM),a ; дескр. bat-файла ; выполн. команд bat-файла call NEWLINE ;!TODO вложенные bat. передавать ошибку обратно в вызывающий bat ;R10 push af CALL Restore_Screen pop af ;R10 xor a ;!FIXIT ret ; [ ] 11/12/23 вложенные bat .new_process: ld de,work_buffer2 call copy_string ; ld hl,.shell ld de,struct_input_line+5 call copy_string ; ld hl,work_buffer2 ld de,struct_input_line+5 + .shell.size - 1 call copy_string ; ; ld c,Dss.CurDisk ; rst ToDSS ; add a,'A' ; ld (.shell),a ; ld hl,struct_input_line+5 ld bc,Dss.Exec RST ToDSS ;!TODO вложенные bat. передавать ошибку обратно в вызывающий bat xor a ret ; ;rst ToDSS ; ; ret nc ; CP DSS_Error.sys.FILE_NOT_FOUND ; ret nz ; jp z,A83DD ; ошибка откр. файла (cpp.asm) ; ret ;.shell: DB '?:\SYSTEM.EXE /C ',0 .shell: DB 'SYSTEM.EXE /C ',0 .shell.size EQU $ - .shell ;!TODO .ErrorEnv: DB 'ERRORLEVEL=' .ErrorEnv.Code: DB 'xxx',0 .ErrorEnv.Size EQU $ - .ErrorEnv ; ;--------------------------------------------------- ; Выполнение команд BAT-файла ;--------------------------------------------------- NEWLINE: LD (cmd_break.sp),SP ; [ ] 11/12/23 cmd_break ; ld de,struct_input_line+5 ;!HARDCODE .ADDBAT: push de call READBAT ; прочитать 128 байт из файла в "work_buffer1" pop de ;!TODO доделать тут нормальную проверку на облом с чтением файла, выводить ошибку jp c,cmd_break.exit or a ; a=число прочит. байт jr nz,.BATLINE ; ex de,hl ld de,struct_input_line+5 sbc hl,de jp z,cmd_break.exit; ;[x] убран баг с незакрытым BAT-файлом ld a,l ld (struct_input_line+4),a ; длина строки call CMDMODE ; тест на bat-команды ; ^^^^^^^ ;!TODO вложенные bat. передавать ошибку обратно в вызывающий bat JP cmd_break.exit ; .exit: ld a,(BAT_FM) ; дескр. bat-файла ; ld c,Dss.Close ; закрыть файл ; ;!TODO вложенные bat. передавать ошибку обратно в вызывающий bat ; RST ToDSS ; xor a ; ld (BAT_FM),a ; ret ; .BATLINE: ld hl,work_buffer1 .loop: call MOVWORD ; скопир. work_buffer1 -> struct_input_line+5 jr c,.ADDBAT ld a,b ld (MOVWORD.count),a ; осталось пропарсить прочитанных байтов push hl ex de,hl ld de,struct_input_line+5 sbc hl,de ld a,l ld (struct_input_line+4),a ; длина строки call CMDMODE ; тест на bat-команды ; ^^^^^^^ ;!TODO вложенные bat. передавать ошибку обратно в вызывающий bat ld de,struct_input_line+5 pop hl jr .loop ;------------------------------------------------- ; Чтение данных (hl) -> (de), при необходимости ; подкачка из файла. ; ; вход: hl=откуда ; de=куда ;------------------------------------------------- MOVWORD: .count+1: ld a,0 ; число прочит. байт из файла ; [ ] 15/12/23 exit if 0 OR A SCF RET Z ; ld b,a .loop: ld a,(hl) ld (de),a cp " " jr c,.loop_ inc hl inc de djnz .loop scf ret ; прочитать доп. блок из файла .loop2: ld a,(hl) cp " " ret nc .loop_: inc hl djnz .loop2 push de call READBAT ; прочитать 128 байт из файла pop de ;!TODO доделать тут нормальную проверку на облом с чтением файла, выводить ошибку RET C ;ld hl,BATBUFF ; 128 буфер (ccp.asm) "work_buffer1" ld hl,work_buffer1 ld b,a ; число прочит. байт or a jr nz,.loop2 scf ret ; прочитать 128 байт из файла READBAT: ;ld hl,T99B9 ; 128 буфер под данные (ccp.asm) "work_buffer1" ld hl,work_buffer1 ld de,128 ; сколько ld a,(BAT_FM) ; дескр. bat-файла ld c,Dss.Read ; чтение файла RST ToDSS ld a,e ; [x] 28/09/23 JR NC,1F ;!TODO доделать тут нормальную проверку на облом с чтением файла, сохранять ошибку LD A,0 ; сохраняем флаг CF ; 1: ld (MOVWORD.count),a ; число прочит. байт из файла ret ; Тест на bat-команды ; должен соблюдаться баланс стека для cmd_break CMDMODE: ;xor a ;ld (D96A6),a ; (inline.asm) call EVALCMD ; (batch.asm) ;ld ix,T96AC ; нужно?? закоментарил (inline.asm) ;ld hl,T96AE ;;256 буфер (inline.asm) ld hl,struct_input_line+5 ld a,(hl) cp "@" ; 40h jr nz,.A8240 dec hl ;ld hl,struct_input_line+4;; dec (hl) jr z,.A825B ld c,(hl) ; длина строки inc hl ld b,0 ;ld hl,work_buffer+256;; ld d,h ld e,l inc hl ldir jr .A825B ; .A8240: ld a,(echo_mode) ; флаг echo-режима or a jr z,.A825B ; off ; вывести сист. путь и строку содержимого bat-файла ;ld de,T96AE ;;256 буфер (inline.asm) ;ld de,struct_input_line+5 ;call A95DE ; вывод экран. пути с ">" (inline.asm) ; вывести экран. путь и введ. команду ld c,BIOS.LP_GET_PLACE ; узнать полож. курсора RST ToBIOS ld (YXpos),de ; Y/X начало ком-строки ld (cursor_position),de ; Y/X позиция курсора call print_compath ; вывести путь + новая ширина поля ввода ld de,(YXpos) ; Y/X начало ком-строки ld c,Dss.Locate ; уст. полож. курсора RST ToDSS ;ld hl,work_buffer+256;; ld hl,struct_input_line+4 ; длина строки ld a,(hl) ld b,a inc hl ;+5 push bc ld c,BIOS.LP_PRINT_LINE2 ; вывод строки без атрибутов RST ToBIOS pop bc ; b=длина строки ld a,(width_inpline) ; ширина поля ввода (76..48) sub b ;ei ret z ; правый край экрана jr c,.A8250; ; строка больше ширины экрана ; заполнить строку до конца экрана dec a ; чтобы не сработал скроллинг экрана ;!FIXIT scroll ld b,a ; число вывод. символов ld a," " ; символ ld c,BIOS.LP_PRINT_SYM ; вывод символа без атрибута RST ToBIOS ;ei ;!TEST .A8250: call newline ; ; ;ld a,(D96AD) ;; длина строки (inline.asm) ;ld a,(struct_input_line+4);- ;or a ;ret z ;call newline ;jr A8264 ; .A825B: ;ld a,(D96AD) ;; длина строки (inline.asm) ld a,(struct_input_line+4) or a ret z ;A8264: ld hl,T96AE ;;256 буфер (inline.asm) ;ld hl,struct_input_line+5 ;dec hl ; убрать концевые пробелы строки ld hl,struct_input_line+4 ld c,(hl) ; hl=длина строки (inline.asm) ld b,0 inc hl ;ld hl,work_buffer+256;; .A826C: ld a,(hl) cp " " jr nz,.A8276 inc hl dec c jr nz,.A826C ret ; .A8276: ld d,h ld e,l add hl,bc ld (hl),b ; 0 в конец строки (первого конц. пробела) sbc hl,bc ld a,c ex af,af' ld a," " cpir jr nz,.A8286 inc c .A8286: ex af,af' sub c ld c,a ; длина слова или строки ? ld hl,BATLIST ; команды bat + dos-команды ; ; de=struct_input_line+5, c=длина строки (без конц. пробелов) ; выполн. команду или запустить файл jp COMP.start ; должна убрать конц. пробелы и уст. длину строки, если урезалась EVALCMD: xor a ld hl,struct_input_line+4 ;!HARDCODE ld c,(hl) ld b,a inc hl add hl,bc ld (hl),a ; 0 в конец строки sbc hl,bc ld de,work_buffer2 ; 256 буфер call EVALSTR ld hl,work_buffer2 ;work_buffer+256 ld de,struct_input_line+5 ; куда ld bc,255 .loop: ld a,(hl) ldi inc b or a jr nz,.loop dec b ld a,b ld (struct_input_line+4),a ; длина строки (edline.asm) and a ret ; HL - STRING WITH %VAR% EVALSTR: ld a,(hl) cp "%" jr z,.TVARIABLE .VARL1: ldi or a jr nz,EVALSTR ; A=0 ld b,a ld c,a ld (.TVAR_PNT),bc ret ; .TVARIABLE: .TVAR_PNT+1: ld bc,0 ld a,b or c ld a,"%" ld (.TVAR_PNT),de jr nz,.TVAR1 inc hl ld a,(hl) ;!FIXIT я в console.asm исправлял баг с параметром %A например. Тут мои правки или Василя? cp "9"+1 jr c,.TVAR0 .TVAR2: ld a,"%" ; > "9" dec hl jp .VARL1 .TVAR0: cp "0" jr c,.TVAR2 ; < "0" ; BATCH PARAM %0, %1, %2 ... inc hl push hl ld (.TVAR_PNT),bc sub "0" add a,a ld c,a ld hl,BAT_PRM_ARRAY ; таблица указат. на "ZERO".."NINE" add hl,bc ld a,(hl) inc hl ld h,(hl) ld l,a or h jr z,.NOBTP ; NO BATCH PARM call copy_string ; скопир. строку (с нулем) dec de .NOBTP: pop hl jp EVALSTR ; .TVAR1: push hl ld h,d ld l,e dec hl and a sbc hl,bc jr z,.TNOVAR ld a,"=" ld (de),a inc de xor a ld (de),a ld d,b ; de=буфер значения перем. ld e,c ld h,b ; hl=имя перем. ld l,c inc hl ld bc,Dss.Environ.Get ; получить перем. окружения RST ToDSS .TNOVAR: pop hl inc hl ld bc,0 ld (.TVAR_PNT),bc jp EVALSTR ; !! Не делать одну команду > 256 символов)) !! ; ; BAT-команды (не отделять от дос-команд) BATLIST: DZ 'PAUSE' : DW cmd_pause ;CPAUSE DZ 'REM' : DW cmd_rem ;CREM DZ 'EXIT' : DW cmd_break ;break ; ; DSS-команды CMDLIST: DZ 'CD' : DW cmd_chdir ;CCHDIR DZ 'DIR' : DW cmd_dir ;DIR DZ 'ECHO' : DW cmd_echo ;CECHO DZ 'ECHO.' : DW cmd_echoLN DZ 'PATH' : DW cmd_path ;CPATH DZ 'MD' : DW cmd_mkdir ;CMKDIR DZ 'REN' : DW cmd_rename ;CRENAM DZ 'DEL' : DW cmd_del ;CDELET DZ 'RD' : DW cmd_rmdir ;CRMDIR DZ 'SET' : DW cmd_set ;CSET DZ 'TIME' : DW cmd_time ;CTIME DZ 'DATE' : DW cmd_date ;CDATE DZ 'VER' : DW cmd_version ;VERS DZ 'CLS' : DW cmd_cls ;CLS DZ 'CHDIR' : DW cmd_chdir ;CCHDIR DZ 'MKDIR' : DW cmd_mkdir ;CMKDIR DZ 'RENAME' : DW cmd_rename ;CRENAM DZ 'ERASE' : DW cmd_del ;CDELET DZ 'RMDIR' : DW cmd_rmdir ;CRMDIR DZ 'HELP' : DW cmd_help ;HELP DZ 'VERSION' : DW cmd_version ;VERS DZ 'EXIT' : DW cmd_exit ;CEXIT DZ 'REBOOT' : DW cmd_reboot ;REBOOT DB #00 IZERO DB "ZERO",0 IONE DB "ONE",0 ITWO DB "TWO",0 ITHREE DB "THREE",0 IFOUR DB "FOUR",0 IFIVE DB "FIVE",0 ISIX DB "SIX",0 ISEVEN DB "SEVEN",0 IEIGHT DB "EIGHT",0 ININE DB "NINE",0 BAT_PRM_ARRAY: DW IZERO, IONE, ITWO, ITHREE, IFOUR, IFIVE, ISIX, ISEVEN, IEIGHT, ININE DW 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 10 число слов "ZERO".."NINE" .TOTAL EQU ($-BAT_PRM_ARRAY)/4 DISPLAY "First compilation test: 10 = ",/D, BAT_PRM_ARRAY.TOTAL ASSERT BAT_PRM_ARRAY.TOTAL = 10, "BAT_PRM_ARRAY.TOTAL" NULL: DB 0 ;TVAR_PNT: DW 0