system.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2004-2006 by Karoly Balogh
  4. AROS conversion
  5. Copyright (c) 2011 by Marcus Sackrow
  6. System unit for AROS
  7. Uses parts of the Free Pascal 1.0.x for Commodore Amiga/68k port
  8. by Carl Eric Codere and Nils Sjoholm
  9. See the file COPYING.FPC, included in this distribution,
  10. for details about the copyright.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. **********************************************************************}
  15. unit System;
  16. interface
  17. {$define FPC_IS_SYSTEM}
  18. {.$define DISABLE_NO_THREAD_MANAGER}
  19. {$I systemh.inc}
  20. const
  21. LineEnding = #10;
  22. LFNSupport = True;
  23. DirectorySeparator = '/';
  24. DriveSeparator = ':';
  25. ExtensionSeparator = '.';
  26. PathSeparator = ';';
  27. AllowDirectorySeparators : set of char = ['\','/'];
  28. AllowDriveSeparators : set of char = [':'];
  29. maxExitCode = 255;
  30. MaxPathLen = 256;
  31. AllFilesMask = '#?';
  32. const
  33. UnusedHandle : THandle = 0;
  34. StdInputHandle : THandle = 0;
  35. StdOutputHandle : THandle = 0;
  36. StdErrorHandle : THandle = 0;
  37. FileNameCaseSensitive : Boolean = False;
  38. FileNameCasePreserving: boolean = True;
  39. CtrlZMarksEOF: Boolean = false; (* #26 not considered as end of file *)
  40. sLineBreak = LineEnding;
  41. DefaultTextLineBreakStyle : TTextLineBreakStyle = tlbsLF;
  42. BreakOn : Boolean = True;
  43. var
  44. AOS_ExecBase : Pointer; external name '_ExecBase';
  45. AOS_DOSBase : Pointer;
  46. AOS_UtilityBase: Pointer;
  47. ASYS_heapPool : Pointer; { pointer for the OS pool for growing the heap }
  48. ASYS_origDir : LongInt; { original directory on startup }
  49. AOS_wbMsg : Pointer;
  50. AOS_ConName : PChar ='CON:10/30/620/100/FPC Console Output/AUTO/CLOSE/WAIT';
  51. AOS_ConHandle: THandle;
  52. AOS_ThreadBase: Pointer;
  53. argc: LongInt;
  54. argv: PPChar;
  55. envp: PPChar;
  56. killed : Boolean = False;
  57. function GetLibAdress(Base: Pointer; Offset: LongInt): Pointer;
  58. procedure Debug(s: string);
  59. procedure Debugln(s: string);
  60. implementation
  61. {$I system.inc}
  62. type
  63. PWBArg = ^TWBArg;
  64. TWBArg = record
  65. wa_Lock : LongInt; { a lock descriptor }
  66. wa_Name : PChar; { a string relative to that lock }
  67. end;
  68. WBArgList = array[1..100] of TWBArg; { Only 1..smNumArgs are valid }
  69. PWBArgList = ^WBArgList;
  70. PWBStartup = ^TWBStartup;
  71. TWBStartup = record
  72. sm_Message : TMessage; { a standard message structure }
  73. sm_Process : Pointer; { the process descriptor for you }
  74. sm_Segment : Pointer; { a descriptor for your code }
  75. sm_NumArgs : Longint; { the number of elements in ArgList }
  76. sm_ToolWindow : Pointer; { description of window }
  77. sm_ArgList : PWBArgList; { the arguments themselves }
  78. end;
  79. {*****************************************************************************
  80. Misc. System Dependent Functions
  81. *****************************************************************************}
  82. procedure haltproc(e:longint); cdecl; external name '_haltproc';
  83. procedure System_exit;
  84. var
  85. oldDirLock: LongInt;
  86. begin
  87. if Killed then
  88. Exit;
  89. Killed := True;
  90. { Closing opened files }
  91. CloseList(ASYS_fileList);
  92. //
  93. if AOS_wbMsg <> nil then
  94. ReplyMsg(AOS_wbMsg);
  95. { Changing back to original directory if changed }
  96. if ASYS_OrigDir <> 0 then begin
  97. oldDirLock:=CurrentDir(ASYS_origDir);
  98. { unlock our lock if its safe, so we won't leak the lock }
  99. if (oldDirLock<>0) and (oldDirLock<>ASYS_origDir) then
  100. Unlock(oldDirLock);
  101. end;
  102. if AOS_UtilityBase <> nil then
  103. CloseLibrary(AOS_UtilityBase);
  104. if ASYS_heapPool <> nil then
  105. DeletePool(ASYS_heapPool);
  106. AOS_UtilityBase := nil;
  107. ASYS_HeapPool := nil;
  108. //
  109. if AOS_DOSBase<>nil then
  110. CloseLibrary(AOS_DOSBase);
  111. AOS_DOSBase := nil;
  112. if AOS_ThreadBase <> nil then
  113. CloseLibrary(AOS_ThreadBase);
  114. AOS_ThreadBase := nil;
  115. //
  116. HaltProc(ExitCode);
  117. end;
  118. { Generates correct argument array on startup }
  119. procedure GenerateArgs;
  120. var
  121. ArgVLen: LongInt;
  122. procedure AllocArg(Idx, Len: LongInt);
  123. var
  124. i, OldArgVLen : LongInt;
  125. begin
  126. if Idx >= ArgVLen then
  127. begin
  128. OldArgVLen := ArgVLen;
  129. ArgVLen := (Idx + 8) and (not 7);
  130. SysReAllocMem(Argv, Argvlen * SizeOf(Pointer));
  131. for i := OldArgVLen to ArgVLen - 1 do
  132. ArgV[i]:=nil;
  133. end;
  134. ArgV[Idx] := SysAllocMem(Succ(Len));
  135. end;
  136. var
  137. Count: Word;
  138. Start: Word;
  139. Ende: Word;
  140. LocalIndex: Word;
  141. P : PChar;
  142. {$H+}
  143. Temp : string;
  144. InQuotes: boolean;
  145. begin
  146. P := GetArgStr;
  147. ArgVLen := 0;
  148. { Set argv[0] }
  149. Temp := ParamStr(0);
  150. AllocArg(0, Length(Temp));
  151. Move(Temp[1], Argv[0]^, Length(Temp));
  152. Argv[0][Length(Temp)] := #0;
  153. { check if we're started from Workbench }
  154. if AOS_wbMsg <> nil then
  155. begin
  156. ArgC := 0;
  157. Exit;
  158. end;
  159. InQuotes := False;
  160. { Handle the other args }
  161. Count := 0;
  162. { first index is one }
  163. LocalIndex := 1;
  164. while (P[Count] <> #0) do
  165. begin
  166. while (p[count]=' ') or (p[count]=#9) or (p[count]=LineEnding) do
  167. Inc(count);
  168. if p[count] = '"' then
  169. begin
  170. inQuotes := True;
  171. Inc(Count);
  172. end;
  173. start := count;
  174. if inQuotes then
  175. begin
  176. while (p[count]<>#0) and (p[count]<>'"') and (p[count]<>LineEnding) do
  177. begin
  178. Inc(Count)
  179. end;
  180. end else
  181. begin
  182. while (p[count]<>#0) and (p[count]<>' ') and (p[count]<>#9) and (p[count]<>LineEnding) do
  183. inc(count);
  184. end;
  185. ende := count;
  186. if not inQuotes then
  187. begin
  188. while (p[start]=' ') and (Start < Ende) do
  189. Inc(Start)
  190. end;
  191. if (ende-start>0) then
  192. begin
  193. allocarg(localindex,ende-start);
  194. move(p[start],argv[localindex]^,ende-start);
  195. argv[localindex][ende-start]:=#0;
  196. if inQuotes and (argv[localindex][(ende-start) - 1] = '"') then
  197. argv[localindex][(ende-start)-1] := #0;
  198. inc(localindex);
  199. end;
  200. if inQuotes and (p[count] = '"') then
  201. Inc(Count);
  202. inQuotes := False;
  203. end;
  204. argc:=localindex;
  205. end;
  206. function GetProgDir: String;
  207. var
  208. s1 : String;
  209. alock : LongInt;
  210. counter: Byte;
  211. begin
  212. GetProgDir:='';
  213. SetLength(s1, 256);
  214. FillChar(s1,255,#0);
  215. { GetLock of program directory }
  216. alock:=GetProgramDir;
  217. if alock<>0 then begin
  218. if NameFromLock(alock,@s1[1],255) then begin
  219. counter:=1;
  220. while (s1[counter]<>#0) and (counter<>0) do Inc(counter);
  221. SetLength(s1, counter-1);
  222. GetProgDir:=s1;
  223. end;
  224. end;
  225. end;
  226. function GetProgramName: String;
  227. { Returns ONLY the program name }
  228. var
  229. s1 : String;
  230. counter: Byte;
  231. begin
  232. GetProgramName:='';
  233. SetLength(s1, 256);
  234. FillChar(s1,255,#0);
  235. if GetProgramName(@s1[1],255) then begin
  236. { now check out and assign the length of the string }
  237. counter := 1;
  238. while (s1[counter]<>#0) and (counter<>0) do Inc(counter);
  239. SetLength(s1, counter-1);
  240. { now remove any component path which should not be there }
  241. for counter:=length(s1) downto 1 do
  242. if (s1[counter] = '/') or (s1[counter] = ':') then break;
  243. { readjust counterv to point to character }
  244. if counter<>1 then Inc(counter);
  245. GetProgramName:=copy(s1,counter,length(s1));
  246. end;
  247. end;
  248. {*****************************************************************************
  249. ParamStr/Randomize
  250. *****************************************************************************}
  251. function GetWBArgsNum: Integer;
  252. var
  253. startup: PWBStartup;
  254. begin
  255. GetWBArgsNum := 0;
  256. Startup := nil;
  257. Startup := PWBStartup(AOS_wbMsg);
  258. if Startup <> nil then
  259. begin
  260. Result := Startup^.sm_NumArgs - 1;
  261. end;
  262. end;
  263. function GetWBArg(Idx: Integer): string;
  264. var
  265. startup: PWBStartup;
  266. wbarg: PWBArgList;
  267. Path: array[0..254] of Char;
  268. strPath: string;
  269. Len: Integer;
  270. begin
  271. GetWBArg := '';
  272. FillChar(Path[0],255,#0);
  273. Startup := PWBStartup(AOS_wbMsg);
  274. if Startup <> nil then
  275. begin
  276. //if (Idx >= 0) and (Idx < Startup^.sm_NumArgs) then
  277. begin
  278. wbarg := Startup^.sm_ArgList;
  279. if NameFromLock(wbarg^[Idx + 1].wa_Lock,@Path[0],255) then
  280. begin
  281. Len := 0;
  282. while (Path[Len] <> #0) and (Len < 254) do
  283. Inc(Len);
  284. if Len > 0 then
  285. if (Path[Len - 1] <> ':') and (Path[Len - 1] <> '/') then
  286. Path[Len] := '/';
  287. strPath := Path;
  288. end;
  289. Result := strPath + wbarg^[Idx + 1].wa_Name;
  290. end;
  291. end;
  292. end;
  293. { number of args }
  294. function paramcount : longint;
  295. begin
  296. if AOS_wbMsg<>nil then
  297. paramcount:=GetWBArgsNum
  298. else
  299. paramcount:=argc-1;
  300. end;
  301. { argument number l }
  302. function paramstr(l : longint) : string;
  303. var
  304. s1: String;
  305. begin
  306. paramstr:='';
  307. if AOS_wbMsg<>nil then
  308. begin
  309. paramstr := GetWBArg(l);
  310. end else
  311. begin
  312. if l=0 then begin
  313. s1:=GetProgDir;
  314. if s1[length(s1)]=':' then paramstr:=s1+GetProgramName
  315. else paramstr:=s1+'/'+GetProgramName;
  316. end else begin
  317. if (l>0) and (l+1<=argc) then paramstr:=strpas(argv[l]);
  318. end;
  319. end;
  320. end;
  321. { set randseed to a new pseudo random value }
  322. procedure Randomize;
  323. var
  324. tmpTime: TDateStamp;
  325. begin
  326. DateStamp(@tmpTime);
  327. randseed := tmpTime.ds_tick;
  328. end;
  329. { AmigaOS specific startup }
  330. procedure SysInitAmigaOS;
  331. var
  332. self: PProcess;
  333. begin
  334. self := PProcess(FindTask(nil));
  335. if self^.pr_CLI = NIL then begin
  336. { if we're running from Ambient/Workbench, we catch its message }
  337. WaitPort(@self^.pr_MsgPort);
  338. AOS_wbMsg:=GetMsg(@self^.pr_MsgPort);
  339. end;
  340. AOS_DOSBase := OpenLibrary('dos.library', 0);
  341. if AOS_DOSBase = nil then
  342. Halt(1);
  343. AOS_UtilityBase := OpenLibrary('utility.library', 0);
  344. if AOS_UtilityBase = nil then
  345. Halt(1);
  346. if AOS_ThreadBase = nil then
  347. AOS_ThreadBase := OpenLibrary('thread.library', 0);
  348. { Creating the memory pool for growing heap }
  349. ASYS_heapPool := CreatePool(MEMF_ANY or MEMF_SEM_PROTECTED, growheapsize2, growheapsize1);
  350. if ASYS_heapPool = nil then
  351. Halt(1);
  352. if AOS_wbMsg = nil then begin
  353. StdInputHandle := THandle(dosInput);
  354. StdOutputHandle := THandle(dosOutput);
  355. StdErrorHandle := THandle(DosError1);
  356. end else begin
  357. AOS_ConHandle := Open(AOS_ConName, MODE_OLDFILE);
  358. if AOS_ConHandle <> 0 then begin
  359. StdInputHandle := AOS_ConHandle;
  360. StdOutputHandle := AOS_ConHandle;
  361. StdErrorHandle := AOS_ConHandle;
  362. end else
  363. Halt(1);
  364. end;
  365. end;
  366. procedure SysInitStdIO;
  367. begin
  368. OpenStdIO(Input,fmInput,StdInputHandle);
  369. OpenStdIO(Output,fmOutput,StdOutputHandle);
  370. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  371. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  372. end;
  373. function GetProcessID: SizeUInt;
  374. begin
  375. GetProcessID := SizeUInt(FindTask(NIL));
  376. end;
  377. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  378. begin
  379. result := stklen;
  380. end;
  381. begin
  382. IsConsole := TRUE;
  383. SysResetFPU;
  384. if not (IsLibrary) then
  385. SysInitFPU;
  386. StackLength := CheckInitialStkLen(InitialStkLen);
  387. StackBottom := Sptr - StackLength;
  388. { OS specific startup }
  389. AOS_wbMsg := nil;
  390. ASYS_origDir := 0;
  391. ASYS_fileList := nil;
  392. envp := nil;
  393. SysInitAmigaOS;
  394. { Set up signals handlers }
  395. //InstallSignals;
  396. { Setup heap }
  397. InitHeap;
  398. SysInitExceptions;
  399. initunicodestringmanager;
  400. { Setup stdin, stdout and stderr }
  401. SysInitStdIO;
  402. { Reset IO Error }
  403. InOutRes:=0;
  404. { Arguments }
  405. GenerateArgs;
  406. InitSystemThreads;
  407. initvariantmanager;
  408. end.