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