title miscellaneous include asm.inc public abort_if_cf ; public move_file_pointer ; public read_from_file public strcmpi .data extw psp .const ertx_aborting db 'Aborting',0 ;ertx_disk_full db 'Disk full',0 .data? argc dw ? argv dd ? .code extn get_strerror,set_strerror,perror extn ms_dos_strerror,malloc ;; abort_if_cf ; abort_if_cf proc jnc aic2 call get_strerror jz aic1 movx si,NULL_POINTER call perror aic1: lea ax,ertx_aborting call set_strerror call perror call exit_with_error aic2: ret abort_if_cf endp ;; close file ; ; entry BX handle ; exit Cf 0 ; uses AX ; close_file proc mov ah,3Eh jmp ms_dos_strerror close_file endp ;; err disk full ; ; exit Cf 1 ; uses AX ; ;err_disk_full proc ; lea ax,ertx_disk_full ; jmp set_strerror ;err_disk_full endp ;; exit program ; exit_program proc mov ax,4C00h jmp ms_dos exit_program endp ;; exit with error ; exit_with_error proc mov ax,4C01h jmp ms_dos exit_with_error endp ;; get vector ; ; entry AL vector # ; exit DS:SI selected vector ; Zf if null vector ; uses AX ; get_vector proc mov ah,0 add ax,ax add ax,ax xchg ax,si xor ax,ax mov ds,ax lds si,[si] mov ax,ds or ax,si ret get_vector endp ;; input file size ; ; entry BX file handle ; exit DX AX size ; input_file_size proc pushm cx,di,si mov ax,4201h ; get current position movx cx,0 movx dx,0 call ms_dos_strerror jc ifs1 mov si,dx ; into SI DI mov di,ax mov ax,4202h ; move to end of file movx dx,0 call ms_dos_strerror jc ifs1 pushm ax,dx mov ax,4200h ; restore file position mov cx,si mov dx,di call ms_dos_strerror popm dx,ax ifs1: popm si,di,cx ret input_file_size endp ;; move file pointer ; ; entry BX file handle ; DX AX file position ; exit Cf if error ; uses AX ; ;move_file_pointer proc ; push cx ; mov cx,dx ; mov dx,ax ; mov ax,4200h ; call ms_dos_dialog ; pop cx ; ret ;move_file_pointer endp ;; ms dos ; ms_dos proc int 21h ret ms_dos endp ;; open input file ; ; entry DS:SI string ; exit AX,BX handle ; Cf if error, error text set ; calls offset_dos_error, ms_dos ; open_input_file proc mov ax,3D00h ; (use 3D20 for shared access read) xchg dx,si call ms_dos_strerror xchg dx,si mov bx,ax ret open_input_file endp ;; read command line ; ; exit DS:SI program command line ; read_command_line proc mov ds,psp[bp] mov si,81h ret read_command_line endp ;; read environment ; ; exit DS:SI environment ; read_environment proc xor si,si mov ds,psp[bp] mov ds,[si+2Ch] ret read_environment endp ;; read from file ; ; entry BX file handle ; CX byte count ; ES:DI destination ; exit AX number of bytes read ; Cf if error ; ;read_from_file proc ; push ds ; mov ah,3Fh ; push es ; pop ds ; xchg dx,di ; call ms_dos_dialog ; xchg di,dx ; pop ds ; ret ;read_from_file endp ;; remove ; ; entry DS:SI filename to delete ; exit Cf if error ; uses AX ; remove proc mov ah,41h ; delete file xchg dx,si call ms_dos_strerror xchg dx,si ret remove endp even ;; restore most ; ; note never call this routine ; restore_most proc popm bp,es,ds,si,di,dx,cx,bx ret restore_most endp even ;; save most ; ; note saves all registers except AX and BP. however, the current ; version also saves BP because the code works out that way. ; the registers are automatically restored. this routine is ; called with a return address as the top of stack. ; save_most proc ; +16 inner ret adr, +18 outer ret adr push cx ; +14 push dx ; +12 push di ; +10 push si ; +8 push ds ; +6 push es ; +4 push bp ; +2 lea bp,restore_most ; after execution of inner push bp ; +0 routine, return to restore_most mov bp,sp xchg bx,[bp+16] ; bx above cx push bx ; -2 setup return to inner routine mov bx,[bp+16] ; restore original BX and BP mov bp,[bp+2] ret save_most endp ;; set argc argv ; ; exit Cf if no memory ; uses AX,CX,DI,SI,ES,DS ; set_argc_argv proc mov cx,256 call malloc jc saa9 ; if no memory mov argc[bp],1 mov wptr argv[bp],di mov wptr argv[bp+2],es mov ah,30h call ms_dos cmp al,3 jb saa10 ; if prior to DOS version 3.x call read_environment ; skip environment saa1: call strskp lodsb cmp al,NULL_CHAR jne saa1 lodsw ; (skip 1) call strcpy ; copy program name which appears inc di ; after environment saa2: call read_command_line saa3: call strskp_white cmp al,CR_CHAR je saa7 ; if no more arguments inc argc[bp] jmp saa5 saa4: stosb saa5: lodsb cmp al,SPACE_CHAR jbe saa6 cmp al,',' je saa6 cmp al,'~' jbe saa4 saa6: cmp al,CR_CHAR mov al,NULL_CHAR stosb jne saa3 saa7: inc di ; word align table and di,-2 lds si,argv[bp] ; get ptr to first argument mov wptr argv[bp],di ; set pointer list offset mov cx,argc[bp] ; get list count (cannot==0) saa8: mov ax,si ; build pointer list stosw call strskp loop saa8 clc saa9: ret saa10: mov ax,'C' stosw jmp saa2 set_argc_argv endp ;; stosb tmp path ; ; entry ES:DI destination ; exit DI updated ; uses AX ; stosb_tmp_path proc mov al,NULL_CHAR stosb dec di ret stosb_tmp_path endp ;; strcmpi ; ; entry DS:SI string1 ; ES:DI string2 ; exit Zf if string1==string2 ; uses AX ; strcmpi proc pushm di,si sci1: mov ah,es:[di] lodsb or ax,ax jz sci2 ; if same strings inc di call tolower xchg al,ah call tolower cmp ah,al je sci1 ; if strings match so far sci2: popm si,di ret strcmpi endp ;; strcpy ; ; entry DS:SI source ptr ; ES:DI destination ptr ; exit SI updated past NULL ; DI updated, points to NULL ; uses AX ; strcpy proc lodsb stosb cmp al,NULL_CHAR jne strcpy dec di ret strcpy endp ;; strcpy limit ; ; entry DS:SI source pointer ; ES:DI destination pointer ; DX destination limit ; exit DI updated to last character in destination ; uses AX ; strcpy_limit proc push si scl1: cmp di,dx jae scl2 ; if at destination limit lodsb ; else copy one character stosb cmp al,0 jne scl1 dec di scl2: pop si ret strcpy_limit endp ;; strlen ; ; entry DS:SI string ; exit CX byte count excluding NULL ; uses AX ; strlen proc mov cx,si sln1: lodsb cmp al,NULL_CHAR jne sln1 xchg cx,si sub cx,si dec cx ret strlen endp ;; strskp ; ; entry DS:SI asciiz string ptr ; exit SI updated past null ; uses AX ; strskp proc lodsb cmp al,NULL_CHAR jne strskp ret strskp endp ;; strskp white ; ; entry DS:SI text ptr ; exit SI updated past spaces and tabs ; AL non-white character ; strskp_white proc lodsb cmp al,SPACE_CHAR je strskp_white cmp al,TAB_CHAR je strskp_white dec si ret strskp_white endp ;; tolower ; ; entry AL char ; exit AL lower cased AL ; tolower proc cmp al,'A' jb tol1 cmp al,'Z' ja tol1 or al,20h tol1: ret tolower endp public ms_dos,read_command_line,read_environment,set_argc_argv,strcpy public argv,argc,exit_program,exit_with_error,get_vector,tolower public close_file,open_input_file,input_file_size public remove,save_most,strlen,strcpy_limit,strskp end