MS-DOS patches to perl. Apply this patch to the standard perl source, version 4, patch level 19, using "patch -p." Do this in the root directory of the perl source distribution. You can cat all these patches together and pipe the output to patch -p. Len Reed Holos Software, Inc. ..!gatech!holos0!lbr holos0!lbr@gatech.edu -------------------------------------- *** msdos/argv.asm.old Sun Feb 23 08:48:16 1992 --- msdos/argv.asm Thu Nov 14 08:56:28 1991 *************** *** 0 **** --- 1,347 ---- + ; Invoke MKS argument handler. If succcesful, return. + ; If unsuccessful, call MS-DOS __argv to process the command line. + + ; Called by MS-DOS C startup code (crt0.obj in the C library). + + ; This code used detailed knowledge of how the Microsoft C 6.0 startup + ; code works. That source is distributed with the compiler, in + ; lib/startup and lib/startup/dos, so we're not talking about a terrible + ; guessing game here. + + ; This code contains no MKS or Microsoft copyrighted code. + + ; This program is free software; you can redistribute it and/or + ; modify it under the terms of the GNU General Public License + ; (version 1), as published by the Free Software Foundation, and + ; found in the file 'LICENSE' included with this distribution. + + ; This program is distributed in the hope that it will be useful, + ; but WITHOUT ANY WARRANTY; without even the implied warrant of + ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ; GNU General Public License for more details. + + ; You must assemble this file with masm flag + ; -dmmodel where model is one of {small, compact, medium, large} + ; + ifdef msmall + .model small + ARG equ 4 + endif + ifdef mcompact + .model compact + ARG equ 4 + endif + ifdef mmedium + .model medium + ARG equ 6 + endif + ifdef mlarge + .model large + ARG equ 6 + endif + + ;------------------------- + + ; The Microsoft startup code calls __setenvp and then __setargv. Each of + ; these can return a changed stack pointer. The routines set ___argv, + ; ___argc, and environ. + + + .DATA + + If @codesize + return_adr dd ? + Else + return_adr dw ? + Endif + + extrn __psp:word ; our PSP segment, set by startup before __setenvp + extrn ___argc:word ; pointer to argv[], used by startup in calling main + extrn _environ:word ; ptr to environment ptrs, used by startup calling main + extrn STKHQQ:word ; top of stack, defined by Microsoft C startup + extrn __osversion:word ; MS-DOS version + + gseg dw ? ; segment of buffer passed to MKS glob + + Public _com_slashc + _com_slashc db '/c', 0 ; default switch for command.com + + .CODE + extrn ___setargv:proc ; Microsoft globber, in C library + extrn __amsg_exit:proc ; Microsoft stack overflow death, in C library + + extrn _mks_init:proc ; C code to do MKS argument analysis + extrn _mks_globber:proc ; C code to run MKS glob.exe + + DONT_USE equ 400h ; stack space that must be left over after + ; processing arguments + + ; Define MIN_DOS_VER to be minimum version of DOS to support times 100, + ; using the -D assembler option. If undefined, assume 2.0. + + Ifndef MIN_DOS_VER + MIN_DOS_VER Equ 200 ; have to at least have handle I/O, in ver 2.00 + Endif + + If MIN_DOS_VER lt 300 + exec_ss dw ? ; needed to support DOS 2.xx exec system call + exec_sp dw ? + Endif + + Public __setenvp + + __setenvp Proc + pop ax + mov word ptr return_adr,ax + If @codesize + pop ax + mov word ptr return_adr + 2,ax + Endif + + mov ax,3000h ; get MS-DOS version. + int 21h + mov __osversion,ax ; Microsoft code we're replacing does this, too. + mov dx,ax + xchg dl,dh ; version from DOS is in wrong byte order! + cmp dx,MIN_DOS_VER ; Approprite DOS version + jae ver_okay + mov bx,4 ; error message number + jmp version_death + + ver_okay: + cmp al,4 ; if version 4 or beyond ignore switch char + jae ver_4 + mov ax,3700h ; get switch char, usually / or - + int 21h + mov _com_slashc,dl ; set the switch character + + ver_4: + mov ax,STKHQQ ; min SP: below this is stack overflow + add ax,DONT_USE ; retain some space, AX will be mks_init's SP + cmp sp,ax ; make sure that DONT_USE doesn't exhaust the stack + jb too_little ; sorry--expand the stack + mov dx,sp + sub dx,ax ; DX has amount of space mks_init can play with + mov sp,ax ; allocate that space for mks_init + push dx ; tell C program how much space he gets + + call _mks_init ; parse envp and args, return stack space used + ; return -1 for insufficient stack space + pop dx ; total that was available + + cmp ax,0FFFFh ; was there enough space? + je not_enough + + sub dx,ax ; subtract off amount actually used + add sp,dx ; reduce stack by amount not used + + cmp ___argc,0 ; did we find the MKS arguments? + jnz done_with_args + + sub sp,dx ; reallocate the remaining space + push dx ; tell mks_globber how big it is + call _mks_globber ; try running MKS glob program + pop dx ; total that was available + + cmp ax,0FFFFh ; was there enough space? + je not_enough + + sub dx,ax ; subtract off amount actually used + add sp,dx ; reduce stack by amount not used + + mov ax,gseg + or ax,ax + jz gspace_freed + mov es,ax + mov ah,49h ; free the memory block used by glob + int 21h + + gspace_freed: + cmp ___argc,0 ; did MKS glob program succeed? + jnz done_with_args + + ; Last chance, and it's a poor third choice, is to let Microsoft's globber run + ; It won't handle single quotes and thinks *.* matches abc and that * doesn't + ; match "abc.c". It will also change the file names to upper case. If + ; someone doesn't like that he can write a globber. + + call ___setargv + + done_with_args: + jmp return_adr + + not_enough: + add sp,dx ; recover all the space that was allocated + + too_little: + xor ax,ax ; message zero + jmp __amsg_exit ; stack overflow message and die + __setenvp Endp + + ; Resolve Microsoft C's need for the following routine + + Public __setargv + + __setargv Proc + ret ; all was done by _setenvp + __setargv Endp + + .DATA + + fcb_one db 0, 12 dup(' ') + fcb_two db 0, 12 dup(' ') + + gtt db 1, ' ', '\r', '\n' ; glob's tail is null + + genv dw ? ; segment of glob's environment + gtail dd gtt ; pointer to glob's command tail + gfcb1 dd fcb_one ; first FCB + gfcb2 dd fcb_two ; second FCB + + .CODE + + ; Subroutine to get space for running MKS glob program. + ; Can't be using malloc() this early, so we call DOS directly. + ; Return a far pointer to the allocated 8K space, 0 for failure. + + Public _get_glob_space + _get_glob_space Proc + mov ah,48h ; MS-DOS allocate memory call + mov bx,201h ; 8 Kilobytes worth of paragraphs plus one paragraph + ; the extra paragraph is used for glob's environment + int 21h + jnc got_it + sub ax,ax ; not enough memory + mov dx,ax + ret + + got_it: + mov gseg,ax ; save segment address + mov dx,ax ; return segment address + sub ax,ax ; offset is always zero + ret + _get_glob_space Endp + + ; Run the MKS glob program. + ; Arguments are standard pointer to the glob program name and far + ; pointer to the glob buffer. + + Public _spawn_mks_glob + + one_dig Proc Near ; convert to ascii and store 1 hex digit + mov ax,dx + and ax,0fh + add ax,30h + cmp ax,39h + jbe one_dec + add ax,7 ; change 3A to 41 ('A'), 3B to 'B' etc. + + one_dec: + mov es:[bx],al + dec bx + shr dx,cl + ret + one_dig Endp + + _spawn_mks_glob Proc + push bp + mov bp,sp + push si + push di + + mov ax,gseg ; segment of glob buffer + mov dx,ax ; save for making ascii string + add ax,200h ; segment of where we'll put the environment + mov genv,ax + + mov es,ax + mov cx,4 + mov bx,3 + call one_dig + call one_dig + call one_dig + call one_dig + mov es:word ptr [4],3030h ; we know glob buffer starts at para address + mov es:word ptr [6],3030h + mov es:byte ptr [8],0 ; terminate the string + + mov ax,@data ; set ES:BX pointing to spawn parameter block + mov es,ax + lea bx,genv + + If @datasize + mov ds,[bp+ARG+2] ; segment of program name + Endif + mov dx,[bp+ARG] ; offset of program name + + If MIN_DOS_VER lt 300 + ; DOS 2.x is brain-damaged and will clobber all but CS:IP + push ds + mov exec_ss,ss + mov exec_sp,sp + Endif + mov ax,4b00h ; spawn the glob program + int 21h ; we're assuming DOS 3.0+; 2.x trashes regs + If MIN_DOS_VER lt 300 + mov ss,exec_ss ; will delay interrupts til after next instr + mov sp,exec_sp ; movs and pops don't change CF + pop ds + Endif + mov ah,0ffh ; assume failure: note doesn't affect carry + jc spawn_done ; problem: return MS-DOS error code + + mov ah,4dh ; get return code of glob + int 21h + + spawn_done: ; return code in AX, if spawn failed, AH == 0FFh + mov cx,ss + mov ds,cx + + pop di + pop si + pop bp + ret + _spawn_mks_glob Endp + + ; Catastophe calling glob.exe. Print message and die + + .DATA + + gmsg0 db 'glob: not found', 13, 10 + gmsg1 db 'glob: insufficient space', 13, 10 + gmsg2 db 'glob: unknown problem', 13, 10 + gmsg3 db 'glob: arg list too long', 13, 10 + gmsg4 db 'DOS ' + db (MIN_DOS_VER shr 8) or 30h ; ascii major + db '.' + db ((MIN_DOS_VER and 0f0h) shr 4) or 30h ; ascii minor (tens) + db (MIN_DOS_VER and 0fh) or 30h ; ascii minor (units) + db ' or better required', 13, 10 + + gmsg dw gmsg0, gmsg1, gmsg2, gmsg3, gmsg4 + dw gmsg + + .CODE + + Public _glob_problem + _glob_problem Proc + push bp + mov bp,sp + mov bx,[bp+ARG] ; get message index + + version_death: + shl bx,1 ; convert to word index + mov dx,[bx].gmsg ; get offset of the message + mov cx,[bx+2].gmsg ; get offset of next message + sub cx,dx ; bytes in between + mov bx,2 ; write to stderr + mov ah,40h + int 21h + + mov ax,4c01h ; terminte with return code 1 + int 21h + ; no return + _glob_problem Endp + + + End