syspara.inc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2016 by Marcus Sackrow and Karoly Balogh
  4. members of the Free Pascal development team.
  5. Command line parameter handling for Atari
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. (* define this symbol to get ARGV argument passing that's strictly
  13. * compatible with the Atari standard. If it's not defined, then
  14. * the startup code won't validate the ARGV= variable by checking
  15. * the command byte for 127. Note that there are still some
  16. * applications (gulam is a notable example) that implement only
  17. * part of the standard and don't set the command byte to 127.
  18. *)
  19. {$IF 0}
  20. {$DEFINE STRICTLY_COMPATIBLE_WITH_STANDARD }
  21. {$ENDIF}
  22. var execpathstr : shortstring;
  23. { Generates correct argument array on startup }
  24. procedure GenerateArgs;
  25. var
  26. ArgVLen: LongInt;
  27. LocalIndex: Word;
  28. len: Integer;
  29. procedure AllocArg(Idx, Len: LongInt);
  30. var
  31. i, OldArgVLen : LongInt;
  32. begin
  33. if Idx >= ArgVLen then
  34. begin
  35. OldArgVLen := ArgVLen;
  36. ArgVLen := (Idx + 8) and (not 7);
  37. SysReAllocMem(Argv, Argvlen * SizeOf(Pointer));
  38. for i := OldArgVLen to ArgVLen - 1 do
  39. ArgV[i]:=nil;
  40. end;
  41. ArgV[Idx] := SysAllocMem(Succ(Len));
  42. end;
  43. function scan_argv : boolean;
  44. var
  45. hp, start : PAnsiChar;
  46. len: integer;
  47. begin
  48. hp:=basepage^.p_env;
  49. result:=false;
  50. if (hp=nil) then
  51. exit;
  52. LocalIndex := 0;
  53. while hp^<>#0 do
  54. begin
  55. if (hp[0] = 'A') and (hp[1] = 'R') and (hp[2] = 'G') and (hp[3] = 'V') and (hp[4] = '=') then
  56. begin
  57. { in any case, terminate environment here }
  58. hp[0] := #0;
  59. hp[1] := #0;
  60. { skip ARGV= string }
  61. hp := hp + 5;
  62. if (hp[0] = 'N') and (hp[1] = 'U') and (hp[2] = 'L') and (hp[3] = 'L') and (hp[4] = ':') then
  63. begin
  64. { TODO: handle NULL arguments }
  65. end;
  66. {$ifdef STRICTLY_COMPATIBLE_WITH_STANDARD}
  67. if (len <> 127) then
  68. exit;
  69. {$endif}
  70. { skip ARGV= value }
  71. while hp^<>#0 do
  72. inc(hp);
  73. inc(hp);
  74. { get arguments }
  75. while hp^<>#0 do
  76. begin
  77. start := hp;
  78. while hp^<>#0 do
  79. inc(hp);
  80. len := hp - start;
  81. allocarg(localindex,len);
  82. move(start^,argv[localindex]^,len);
  83. argv[localindex][len]:=#0;
  84. inc(localindex);
  85. inc(hp);
  86. end;
  87. argc:=localindex;
  88. result := true;
  89. exit;
  90. end;
  91. hp := hp + strlen(hp) + 1;
  92. end;
  93. end;
  94. var
  95. Count: Word;
  96. Start: Word;
  97. Ende: Word;
  98. i: Integer;
  99. P : PAnsiChar;
  100. begin
  101. P := Args;
  102. ArgVLen := 0;
  103. { check ARGV usage indicator }
  104. len := ord(P[0]);
  105. if scan_argv then
  106. exit;
  107. { Set argv[0] }
  108. AllocArg(0, 0);
  109. Argv[0][0] := #0;
  110. { just in case; commandline cannot be longer }
  111. if len > 127 then
  112. begin
  113. argc := 1;
  114. exit;
  115. end;
  116. { Handle the other args }
  117. p[len + 1] := #0;
  118. Count := 1;
  119. { first index is one }
  120. LocalIndex := 1;
  121. while (P[Count] <> #0) do
  122. begin
  123. while (P[Count] <> #0) and (p[count]<=#32) do
  124. Inc(count);
  125. if p[count] = '"' then
  126. begin
  127. Inc(Count);
  128. start := count;
  129. while (p[count]<>#0) and (p[count]<>'"') and (p[count]>=#32) do
  130. Inc(Count);
  131. ende := count;
  132. if (p[count] = '"') then
  133. Inc(Count);
  134. end else
  135. begin
  136. start := count;
  137. while (p[count]<>#0) and (p[count]>#32) do
  138. inc(count);
  139. ende := count;
  140. end;
  141. if (ende>start) then
  142. begin
  143. allocarg(localindex,ende-start);
  144. move(p[start],argv[localindex]^,ende-start);
  145. argv[localindex][ende-start]:=#0;
  146. inc(localindex);
  147. end;
  148. end;
  149. argc:=localindex;
  150. end;
  151. Function FSearch(const path:RawByteString;dirlist:RawByteString):RawByteString;
  152. {
  153. Searches for a file 'path' in the list of direcories in 'dirlist'.
  154. returns an empty string if not found. Wildcards are NOT allowed.
  155. If dirlist is empty, it is set to '.'
  156. This function tries to make FSearch use ansistrings, and decrease
  157. stringhandling overhead at the same time.
  158. }
  159. Var
  160. mypath,
  161. mydir,NewDir : RawByteString;
  162. p1 : longint;
  163. olddta : PDTA;
  164. dta : TDTA;
  165. i,j : longint;
  166. p : PAnsiChar;
  167. tmpPath: RawByteString;
  168. Begin
  169. {Check for WildCards}
  170. If (Pos('?',Path) <> 0) or (Pos('*',Path) <> 0) Then
  171. FSearch:='' {No wildcards allowed in these things.}
  172. Else
  173. Begin
  174. { allow slash as backslash }
  175. tmpPath:=Path+#0;
  176. DoDirSeparators(tmpPath);
  177. DoDirSeparators(dirlist);
  178. {Replace ';' with #0}
  179. for p1:=1 to length(dirlist) do
  180. if (dirlist[p1]=';') or (dirlist[p1]=',') then
  181. dirlist[p1]:=#0;
  182. mypath:=ToSingleByteFileSystemEncodedFileName(tmppath);
  183. olddta := gemdos_getdta;
  184. gemdos_setdta(@dta);
  185. p:=PAnsiChar(dirlist);
  186. i:=length(dirlist);
  187. j:=1;
  188. Repeat
  189. mydir:=RawByteString(p);
  190. if (length(mydir)>0) and (mydir[length(mydir)]<>DirectorySeparator) then
  191. begin
  192. { concatenate character without influencing code page }
  193. setlength(mydir,length(mydir)+1);
  194. mydir[length(mydir)]:=DirectorySeparator;
  195. end;
  196. NewDir:=mydir+mypath;
  197. if (gemdos_fsfirst(PAnsiChar(NewDir),$07)>=0) and
  198. ((dta.d_attrib and ATTRIB_DIRECTORY)=0) then
  199. Begin
  200. {DOS strips off an initial .\}
  201. If Pos('.\',NewDir)=1 Then
  202. Delete(NewDir,1,2);
  203. End
  204. Else
  205. NewDir:='';
  206. while (j<=i) and (p^<>#0) do begin inc(j); inc(p); end;
  207. if p^=#0 then inc(p);
  208. Until (j>=i) or (Length(NewDir) > 0);
  209. gemdos_setdta(olddta);
  210. FSearch:=NewDir;
  211. End;
  212. End;
  213. {*****************************************************************************
  214. ParamStr
  215. *****************************************************************************}
  216. { number of args }
  217. function ParamCount: LongInt;
  218. begin
  219. ParamCount := argc - 1;
  220. end;
  221. function fpGetEnvAtari(const envvar : ShortString): RawByteString; external name '_fpc_atari_getenv';
  222. { argument number l }
  223. function ParamStr(l: LongInt): shortstring;
  224. var
  225. s1: shortstring;
  226. begin
  227. if l=0 then
  228. begin
  229. if (execpathstr='') and (argv[0][0]<>#0) then
  230. begin
  231. execpathstr := fsearch(argv[0],fpgetenvAtari('PATH'));
  232. if execpathstr='' then
  233. execpathstr := argv[0];
  234. end;
  235. paramstr := execpathstr;
  236. end
  237. else if (l > 0) and (l < argc) then
  238. ParamStr := StrPas(argv[l])
  239. else
  240. ParamStr := '';
  241. end;