* same argument parsing -"abc" becomes -abc. This is compatible with

delphi and with unix shells (merged)
This commit is contained in:
peter 2001-06-01 22:23:21 +00:00
parent 9ac5af24c1
commit 6db9db184b
2 changed files with 1802 additions and 1569 deletions

View File

@ -151,7 +151,6 @@ type
end; end;
var var
doscmd : string[128]; { Dos commandline copied from PSP, max is 128 chars }
old_int00 : tseginfo;cvar; old_int00 : tseginfo;cvar;
old_int75 : tseginfo;cvar; old_int75 : tseginfo;cvar;
@ -294,6 +293,23 @@ var
procedure setup_arguments; procedure setup_arguments;
type
arrayword = array [0..255] of word;
var
psp : word;
proxy_s : string[50];
proxy_argc,proxy_seg,proxy_ofs,lin : longint;
rm_argv : ^arrayword;
argv0len : longint;
useproxy : boolean;
hp : ppchar;
doscmd : string[129]; { Dos commandline copied from PSP, max is 128 chars +1 for terminating zero }
arglen,
count : longint;
argstart,
pc,arg : pchar;
quote : char;
argvlen : longint;
function atohex(s : pchar) : longint; function atohex(s : pchar) : longint;
var var
@ -313,80 +329,176 @@ procedure setup_arguments;
atohex:=rv; atohex:=rv;
end; end;
type procedure allocarg(idx,len:longint);
arrayword = array [0..255] of word;
var
psp : word;
i,j : longint;
quote : char;
proxy_s : string[50];
al,proxy_argc,proxy_seg,proxy_ofs,lin : longint;
largs : array[0..127] of pchar;
rm_argv : ^arrayword;
argv0len : longint;
useproxy : boolean;
hp : ppchar;
begin begin
fillchar(largs,sizeof(largs),0); if idx>=argvlen then
psp:=stub_info^.psp_selector; begin
largs[0]:=dos_argv0; argvlen:=(idx+8) and (not 7);
sysreallocmem(argv,argvlen*sizeof(pointer));
end;
{ use realloc to reuse already existing memory }
if len<>0 then
sysreallocmem(argv[idx],len+1);
end;
begin
count:=0;
argc:=1; argc:=1;
argv:=nil;
argvlen:=0;
{ load commandline from psp }
psp:=stub_info^.psp_selector;
sysseg_move(psp, 128, get_ds, longint(@doscmd), 128); sysseg_move(psp, 128, get_ds, longint(@doscmd), 128);
doscmd[length(doscmd)+1]:=#0;
{$IfDef SYSTEM_DEBUG_STARTUP} {$IfDef SYSTEM_DEBUG_STARTUP}
Writeln(stderr,'Dos command line is #',doscmd,'# size = ',length(doscmd)); Writeln(stderr,'Dos command line is #',doscmd,'# size = ',length(doscmd));
{$EndIf } {$EndIf }
{ create argv[0] }
{ setup cmdline variable }
argv0len:=strlen(dos_argv0); argv0len:=strlen(dos_argv0);
cmdline:=sysgetmem(argv0len+length(doscmd)+1); allocarg(count,argv0len);
move(dos_argv0^,argv[count]^,argv0len);
inc(count);
{ setup cmdline variable }
cmdline:=Getmem(argv0len+length(doscmd)+2);
move(dos_argv0^,cmdline^,argv0len); move(dos_argv0^,cmdline^,argv0len);
cmdline[argv0len]:=' ';
inc(argv0len);
move(doscmd[1],cmdline[argv0len],length(doscmd)); move(doscmd[1],cmdline[argv0len],length(doscmd));
cmdline[argv0len+length(doscmd)]:=#0; cmdline[argv0len+length(doscmd)+1]:=#0;
{ parse dos commandline }
j := 1; pc:=@doscmd[1];
quote := #0; while pc^<>#0 do
for i:=1 to length(doscmd) do
Begin
if doscmd[i] = quote then
begin begin
quote := #0; { skip leading spaces }
if (i>1) and ((doscmd[i-1]='''') or (doscmd[i-1]='"')) then while pc^ in [#1..#32] do
inc(pc);
{ calc argument length }
quote:=' ';
argstart:=pc;
arglen:=0;
while (pc^<>#0) do
begin begin
j := i+1; case pc^ of
doscmd[i] := #0; #1..#32 :
continue; begin
if quote<>' ' then
inc(arglen)
else
break;
end; end;
doscmd[i] := #0; '"' :
largs[argc]:=@doscmd[j]; begin
inc(argc); if quote<>'''' then
j := i+1; begin
if pchar(pc+1)^<>'"' then
begin
if quote='"' then
quote:=' '
else
quote:='"';
end end
else else
if (quote = #0) and ((doscmd[i] = '''') or (doscmd[i]='"')) then inc(pc);
end
else
inc(arglen);
end;
'''' :
begin begin
quote := doscmd[i]; if quote<>'"' then
j := i + 1;
end else
if (quote = #0) and ((doscmd[i] = ' ')
or (doscmd[i] = #9) or (doscmd[i] = #10) or
(doscmd[i] = #12) or (doscmd[i] = #9)) then
begin begin
doscmd[i]:=#0; if pchar(pc+1)^<>'''' then
if j<i then
begin begin
largs[argc]:=@doscmd[j]; if quote='''' then
inc(argc); quote:=' '
j := i+1; else
end else inc(j); quote:='''';
end else end
if (i = length(doscmd)) then else
inc(pc);
end
else
inc(arglen);
end;
else
inc(arglen);
end;
inc(pc);
end;
{ copy argument }
allocarg(count,arglen);
quote:=' ';
pc:=argstart;
arg:=argv[count];
while (pc^<>#0) do
begin begin
doscmd[i+1]:=#0; case pc^ of
largs[argc]:=@doscmd[j]; #1..#32 :
inc(argc); begin
if quote<>' ' then
begin
arg^:=pc^;
inc(arg);
end
else
break;
end;
'"' :
begin
if quote<>'''' then
begin
if pchar(pc+1)^<>'"' then
begin
if quote='"' then
quote:=' '
else
quote:='"';
end
else
inc(pc);
end
else
begin
arg^:=pc^;
inc(arg);
end; end;
end; end;
'''' :
begin
if quote<>'"' then
begin
if pchar(pc+1)^<>'''' then
begin
if quote='''' then
quote:=' '
else
quote:='''';
end
else
inc(pc);
end
else
begin
arg^:=pc^;
inc(arg);
end;
end;
else
begin
arg^:=pc^;
inc(arg);
end;
end;
inc(pc);
end;
arg^:=#0;
{$IfDef SYSTEM_DEBUG_STARTUP}
Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
{$EndIf SYSTEM_DEBUG_STARTUP}
inc(count);
end;
argc:=count;
{ check for !proxy for long commandlines passed using environment }
hp:=envp; hp:=envp;
useproxy:=false; useproxy:=false;
while assigned(hp^) do while assigned(hp^) do
@ -399,54 +511,53 @@ begin
proxy_s[13]:=#0; proxy_s[13]:=#0;
proxy_s[18]:=#0; proxy_s[18]:=#0;
proxy_s[23]:=#0; proxy_s[23]:=#0;
largs[2]:=@proxy_s[9]; argv[2]:=@proxy_s[9];
largs[3]:=@proxy_s[14]; argv[3]:=@proxy_s[14];
largs[4]:=@proxy_s[19]; argv[4]:=@proxy_s[19];
useproxy:=true; useproxy:=true;
break; break;
end; end;
end; end;
inc(hp); inc(hp);
end; end;
{ check for !proxy for long commandlines passed using commandline }
if (not useproxy) and if (not useproxy) and
(argc > 1) and (far_strlen(get_ds,longint(largs[1])) = 6) then (argc > 1) and (far_strlen(get_ds,longint(argv[1])) = 6) then
begin begin
move(largs[1]^,proxy_s[1],6); move(argv[1]^,proxy_s[1],6);
proxy_s[0] := #6; proxy_s[0] := #6;
if (proxy_s = '!proxy') then if (proxy_s = '!proxy') then
useproxy:=true; useproxy:=true;
end; end;
{ use proxy when found }
if useproxy then if useproxy then
begin begin
proxy_argc := atohex(largs[2]); proxy_argc:=atohex(argv[2]);
proxy_seg := atohex(largs[3]); proxy_seg:=atohex(argv[3]);
proxy_ofs := atohex(largs[4]); proxy_ofs:=atohex(argv[4]);
{$IfDef SYSTEM_DEBUG_STARTUP} {$IfDef SYSTEM_DEBUG_STARTUP}
Writeln(stderr,'proxy command line found'); Writeln(stderr,'proxy command line found');
writeln(stderr,'argc: ',proxy_argc,' seg: ',proxy_seg,' ofs: ',proxy_ofs); writeln(stderr,'argc: ',proxy_argc,' seg: ',proxy_seg,' ofs: ',proxy_ofs);
{$EndIf SYSTEM_DEBUG_STARTUP} {$EndIf SYSTEM_DEBUG_STARTUP}
if proxy_argc>128 then rm_argv:=SysGetmem(proxy_argc*sizeof(word));
proxy_argc:=128;
rm_argv := sysgetmem(proxy_argc*sizeof(word));
sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word)); sysseg_move(dos_selector,proxy_seg*16+proxy_ofs, get_ds,longint(rm_argv),proxy_argc*sizeof(word));
for i:=0 to proxy_argc - 1 do for count:=0 to proxy_argc - 1 do
begin begin
lin := proxy_seg*16 + rm_argv^[i]; lin:=proxy_seg*16+rm_argv^[count];
al :=far_strlen(dos_selector, lin); arglen:=far_strlen(dos_selector,lin);
largs[i] := sysgetmem(al+1); allocarg(count,arglen);
sysseg_move(dos_selector, lin, get_ds,longint(largs[i]), al+1); sysseg_move(dos_selector,lin,get_ds,longint(argv[count]),arglen+1);
{$IfDef SYSTEM_DEBUG_STARTUP} {$IfDef SYSTEM_DEBUG_STARTUP}
Writeln(stderr,'arg ',i,' #',rm_argv^[i],'#',al,'#',largs[i],'#'); Writeln(stderr,'arg ',count,' #',rm_argv^[count],'#',arglen,'#',argv[count],'#');
{$EndIf SYSTEM_DEBUG_STARTUP} {$EndIf SYSTEM_DEBUG_STARTUP}
end; end;
sysfreemem(rm_argv); SysFreemem(rm_argv);
argc:=proxy_argc; argc:=proxy_argc;
end; end;
argv := sysgetmem(argc shl 2); { create an nil entry }
for i := 0 to argc-1 do allocarg(argc,0);
argv[i]:=largs[i]; { free unused memory }
sysreallocmem(argv,(argc+1)*sizeof(pointer));
_args:=argv; _args:=argv;
end; end;
@ -1420,7 +1531,11 @@ Begin
End. End.
{ {
$Log$ $Log$
Revision 1.7 2001-03-21 23:29:40 florian Revision 1.8 2001-06-01 22:23:21 peter
* same argument parsing -"abc" becomes -abc. This is compatible with
delphi and with unix shells (merged)
Revision 1.7 2001/03/21 23:29:40 florian
+ sLineBreak and misc. stuff for Kylix compatiblity + sLineBreak and misc. stuff for Kylix compatiblity
Revision 1.6 2001/03/21 21:08:20 hajny Revision 1.6 2001/03/21 21:08:20 hajny

View File

@ -718,67 +718,181 @@ var
arglen, arglen,
count : longint; count : longint;
argstart, argstart,
pc : pchar; pc,arg : pchar;
quote : set of char; quote : char;
argsbuf : array[0..127] of pchar; argvlen : longint;
procedure allocarg(idx,len:longint);
begin
if idx>=argvlen then
begin
argvlen:=(idx+8) and (not 7);
sysreallocmem(argv,argvlen*sizeof(pointer));
end;
{ use realloc to reuse already existing memory }
if len<>0 then
sysreallocmem(argv[idx],len+1);
end;
begin begin
{ create commandline, it starts with the executed filename which is argv[0] } { create commandline, it starts with the executed filename which is argv[0] }
{ Win32 passes the command NOT via the args, but via getmodulefilename} { Win32 passes the command NOT via the args, but via getmodulefilename}
count:=0; count:=0;
argv:=nil;
argvlen:=0;
pc:=getcommandfile; pc:=getcommandfile;
Arglen:=0; Arglen:=0;
repeat repeat
Inc(Arglen); Inc(Arglen);
until (pc[Arglen]=#0); until (pc[Arglen]=#0);
getmem(argsbuf[count],arglen+1); allocarg(count,arglen);
move(pc^,argsbuf[count]^,arglen); move(pc^,argv[count]^,arglen);
{ Now skip the first one } { Setup cmdline variable }
pc:=GetCommandLine; cmdline:=GetCommandLine;
repeat { process arguments }
pc:=cmdline;
{$IfDef SYSTEM_DEBUG_STARTUP}
Writeln(stderr,'Win32 GetCommandLine is #',pc,'#');
{$EndIf }
while pc^<>#0 do
begin
{ skip leading spaces } { skip leading spaces }
while pc^ in [' ',#9,#13] do while pc^ in [#1..#32] do
inc(pc); inc(pc);
{ calc argument length }
quote:=' ';
argstart:=pc;
arglen:=0;
while (pc^<>#0) do
begin
case pc^ of case pc^ of
#0 : break; #1..#32 :
'"' : begin begin
quote:=['"']; if quote<>' ' then
inc(pc); inc(arglen)
else
break;
end; end;
'''' : begin '"' :
quote:=['''']; begin
if quote<>'''' then
begin
if pchar(pc+1)^<>'"' then
begin
if quote='"' then
quote:=' '
else
quote:='"';
end
else
inc(pc); inc(pc);
end
else
inc(arglen);
end;
'''' :
begin
if quote<>'"' then
begin
if pchar(pc+1)^<>'''' then
begin
if quote='''' then
quote:=' '
else
quote:='''';
end
else
inc(pc);
end
else
inc(arglen);
end; end;
else else
quote:=[' ',#9,#13]; inc(arglen);
end; end;
{ scan until the end of the argument }
argstart:=pc;
while (pc^<>#0) and not(pc^ in quote) do
inc(pc); inc(pc);
end;
{ copy argument }
{ Don't copy the first one, it is already there.} { Don't copy the first one, it is already there.}
If Count<>0 then If Count<>0 then
begin begin
{ reserve some memory } allocarg(count,arglen);
arglen:=pc-argstart; quote:=' ';
getmem(argsbuf[count],arglen+1); pc:=argstart;
move(argstart^,argsbuf[count]^,arglen); arg:=argv[count];
argsbuf[count][arglen]:=#0; while (pc^<>#0) do
begin
case pc^ of
#1..#32 :
begin
if quote<>' ' then
begin
arg^:=pc^;
inc(arg);
end
else
break;
end; end;
{ skip quote } '"' :
if pc^ in quote then begin
if quote<>'''' then
begin
if pchar(pc+1)^<>'"' then
begin
if quote='"' then
quote:=' '
else
quote:='"';
end
else
inc(pc); inc(pc);
end
else
begin
arg^:=pc^;
inc(arg);
end;
end;
'''' :
begin
if quote<>'"' then
begin
if pchar(pc+1)^<>'''' then
begin
if quote='''' then
quote:=' '
else
quote:='''';
end
else
inc(pc);
end
else
begin
arg^:=pc^;
inc(arg);
end;
end;
else
begin
arg^:=pc^;
inc(arg);
end;
end;
inc(pc);
end;
arg^:=#0;
end;
{$IfDef SYSTEM_DEBUG_STARTUP}
Writeln(stderr,'dos arg ',count,' #',arglen,'#',argv[count],'#');
{$EndIf SYSTEM_DEBUG_STARTUP}
inc(count); inc(count);
until false; end;
{ create argc } { get argc and create an nil entry }
argc:=count; argc:=count;
{ create an nil entry } allocarg(argc,0);
argsbuf[count]:=nil; { free unused memory }
inc(count); sysreallocmem(argv,(argc+1)*sizeof(pointer));
{ create the argv }
getmem(argv,count shl 2);
move(argsbuf,argv^,count shl 2);
{ Setup cmdline variable }
cmdline:=GetCommandLine;
end; end;
@ -1434,7 +1548,11 @@ end.
{ {
$Log$ $Log$
Revision 1.9 2001-03-21 23:29:40 florian Revision 1.10 2001-06-01 22:23:21 peter
* same argument parsing -"abc" becomes -abc. This is compatible with
delphi and with unix shells (merged)
Revision 1.9 2001/03/21 23:29:40 florian
+ sLineBreak and misc. stuff for Kylix compatiblity + sLineBreak and misc. stuff for Kylix compatiblity
Revision 1.8 2001/03/21 21:08:20 hajny Revision 1.8 2001/03/21 21:08:20 hajny