system.pp 12 KB

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