system.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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. {$I systemh.inc}
  19. {$I osdebugh.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. AROS_ThreadLib : Pointer; public name 'AROS_THREADLIB';
  48. ASYS_heapPool : Pointer; { pointer for the OS pool for growing the heap }
  49. ASYS_fileSemaphore: Pointer; { mutex semaphore for filelist access arbitration }
  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. { Dispose the thread init/exit chains }
  93. CleanupThreadProcChain(threadInitProcList);
  94. CleanupThreadProcChain(threadExitProcList);
  95. { Closing opened files }
  96. CloseList(ASYS_fileList);
  97. { Changing back to original directory if changed }
  98. if ASYS_OrigDir <> 0 then begin
  99. oldDirLock:=CurrentDir(ASYS_origDir);
  100. { unlock our lock if its safe, so we won't leak the lock }
  101. if (oldDirLock<>0) and (oldDirLock<>ASYS_origDir) then
  102. Unlock(oldDirLock);
  103. end;
  104. if AOS_UtilityBase <> nil then
  105. CloseLibrary(AOS_UtilityBase);
  106. if ASYS_heapPool <> nil then
  107. DeletePool(ASYS_heapPool);
  108. AOS_UtilityBase := nil;
  109. ASYS_HeapPool := nil;
  110. //
  111. if AOS_DOSBase<>nil then
  112. CloseLibrary(AOS_DOSBase);
  113. AOS_DOSBase := nil;
  114. //
  115. if AOS_wbMsg <> nil then
  116. begin
  117. // forbid -> Amiga RKM Libraries Manual
  118. Forbid();
  119. // Reply WBStartupMessage
  120. ReplyMsg(AOS_wbMsg);
  121. end;
  122. //
  123. HaltProc(ExitCode);
  124. end;
  125. function GetWBArgsNum: Integer;
  126. var
  127. startup: PWBStartup;
  128. begin
  129. GetWBArgsNum := 0;
  130. Startup := nil;
  131. Startup := PWBStartup(AOS_wbMsg);
  132. if Startup <> nil then
  133. begin
  134. Result := Startup^.sm_NumArgs - 1;
  135. end;
  136. end;
  137. function GetWBArg(Idx: Integer): string;
  138. var
  139. startup: PWBStartup;
  140. wbarg: PWBArgList;
  141. Path: array[0..254] of Char;
  142. strPath: string;
  143. Len: Integer;
  144. begin
  145. GetWBArg := '';
  146. FillChar(Path[0],255,#0);
  147. Startup := PWBStartup(AOS_wbMsg);
  148. if Startup <> nil then
  149. begin
  150. //if (Idx >= 0) and (Idx < Startup^.sm_NumArgs) then
  151. begin
  152. wbarg := Startup^.sm_ArgList;
  153. if NameFromLock(wbarg^[Idx + 1].wa_Lock,@Path[0],255) then
  154. begin
  155. Len := 0;
  156. while (Path[Len] <> #0) and (Len < 254) do
  157. Inc(Len);
  158. if Len > 0 then
  159. if (Path[Len - 1] <> ':') and (Path[Len - 1] <> '/') then
  160. Path[Len] := '/';
  161. strPath := Path;
  162. end;
  163. Result := strPath + wbarg^[Idx + 1].wa_Name;
  164. end;
  165. end;
  166. end;
  167. { Generates correct argument array on startup }
  168. procedure GenerateArgs;
  169. var
  170. ArgVLen: LongInt;
  171. procedure AllocArg(Idx, Len: LongInt);
  172. var
  173. i, OldArgVLen : LongInt;
  174. begin
  175. if Idx >= ArgVLen then
  176. begin
  177. OldArgVLen := ArgVLen;
  178. ArgVLen := (Idx + 8) and (not 7);
  179. SysReAllocMem(Argv, Argvlen * SizeOf(Pointer));
  180. for i := OldArgVLen to ArgVLen - 1 do
  181. ArgV[i]:=nil;
  182. end;
  183. ArgV[Idx] := SysAllocMem(Succ(Len));
  184. end;
  185. var
  186. Count: Word;
  187. Start: Word;
  188. Ende: Word;
  189. LocalIndex: Word;
  190. i: Integer;
  191. P : PChar;
  192. {$H+}
  193. Temp : string;
  194. InQuotes: boolean;
  195. begin
  196. P := GetArgStr;
  197. ArgVLen := 0;
  198. { Set argv[0] }
  199. Temp := ParamStr(0);
  200. AllocArg(0, Length(Temp));
  201. Move(Temp[1], Argv[0]^, Length(Temp));
  202. Argv[0][Length(Temp)] := #0;
  203. { check if we're started from Workbench }
  204. if AOS_wbMsg <> nil then
  205. begin
  206. ArgC := GetWBArgsNum + 1;
  207. for i := 1 to ArgC - 1 do
  208. begin
  209. Temp := GetWBArg(i);
  210. AllocArg(i, Length(Temp));
  211. Move(Temp[1], Argv[i]^, Length(Temp));
  212. Argv[i][Length(Temp)] := #0;
  213. end;
  214. Exit;
  215. end;
  216. InQuotes := False;
  217. { Handle the other args }
  218. Count := 0;
  219. { first index is one }
  220. LocalIndex := 1;
  221. while (P[Count] <> #0) do
  222. begin
  223. while (p[count]=' ') or (p[count]=#9) or (p[count]=LineEnding) do
  224. Inc(count);
  225. if p[count] = '"' then
  226. begin
  227. inQuotes := True;
  228. Inc(Count);
  229. end;
  230. start := count;
  231. if inQuotes then
  232. begin
  233. while (p[count]<>#0) and (p[count]<>'"') and (p[count]<>LineEnding) do
  234. begin
  235. Inc(Count)
  236. end;
  237. end else
  238. begin
  239. while (p[count]<>#0) and (p[count]<>' ') and (p[count]<>#9) and (p[count]<>LineEnding) do
  240. inc(count);
  241. end;
  242. ende := count;
  243. if not inQuotes then
  244. begin
  245. while (p[start]=' ') and (Start < Ende) do
  246. Inc(Start)
  247. end;
  248. if (ende-start>0) then
  249. begin
  250. allocarg(localindex,ende-start);
  251. move(p[start],argv[localindex]^,ende-start);
  252. argv[localindex][ende-start]:=#0;
  253. if inQuotes and (argv[localindex][(ende-start) - 1] = '"') then
  254. argv[localindex][(ende-start)-1] := #0;
  255. inc(localindex);
  256. end;
  257. if inQuotes and (p[count] = '"') then
  258. Inc(Count);
  259. inQuotes := False;
  260. end;
  261. argc:=localindex;
  262. end;
  263. function GetProgDir: String;
  264. var
  265. s1 : String;
  266. alock : LongInt;
  267. counter: Byte;
  268. begin
  269. GetProgDir:='';
  270. SetLength(s1, 256);
  271. FillChar(s1,255,#0);
  272. { GetLock of program directory }
  273. alock:=GetProgramDir;
  274. if alock<>0 then begin
  275. if NameFromLock(alock,@s1[1],255) then begin
  276. counter:=1;
  277. while (s1[counter]<>#0) and (counter<>0) do Inc(counter);
  278. SetLength(s1, counter-1);
  279. GetProgDir:=s1;
  280. end;
  281. end;
  282. end;
  283. function GetProgramName: String;
  284. { Returns ONLY the program name }
  285. var
  286. s1 : String;
  287. counter: Byte;
  288. begin
  289. GetProgramName:='';
  290. SetLength(s1, 256);
  291. FillChar(s1,255,#0);
  292. if GetProgramName(@s1[1],255) then begin
  293. { now check out and assign the length of the string }
  294. counter := 1;
  295. while (s1[counter]<>#0) and (counter<>0) do Inc(counter);
  296. SetLength(s1, counter-1);
  297. { now remove any component path which should not be there }
  298. for counter:=length(s1) downto 1 do
  299. if (s1[counter] = '/') or (s1[counter] = ':') then break;
  300. { readjust counterv to point to character }
  301. if counter<>1 then Inc(counter);
  302. GetProgramName:=copy(s1,counter,length(s1));
  303. end;
  304. end;
  305. {*****************************************************************************
  306. ParamStr/Randomize
  307. *****************************************************************************}
  308. { number of args }
  309. function paramcount : longint;
  310. begin
  311. if AOS_wbMsg<>nil then
  312. paramcount:=GetWBArgsNum
  313. else
  314. paramcount:=argc-1;
  315. end;
  316. { argument number l }
  317. function paramstr(l : longint) : string;
  318. var
  319. s1: String;
  320. begin
  321. paramstr:='';
  322. if AOS_wbMsg<>nil then
  323. begin
  324. paramstr := GetWBArg(l);
  325. end else
  326. begin
  327. if l=0 then begin
  328. s1:=GetProgDir;
  329. if s1[length(s1)]=':' then paramstr:=s1+GetProgramName
  330. else paramstr:=s1+'/'+GetProgramName;
  331. end else begin
  332. if (l>0) and (l+1<=argc) then paramstr:=strpas(argv[l]);
  333. end;
  334. end;
  335. end;
  336. { set randseed to a new pseudo random value }
  337. procedure Randomize;
  338. var
  339. tmpTime: TDateStamp;
  340. begin
  341. DateStamp(@tmpTime);
  342. randseed := tmpTime.ds_tick;
  343. end;
  344. { AmigaOS specific startup }
  345. procedure SysInitAmigaOS;
  346. var
  347. self: PProcess;
  348. begin
  349. self := PProcess(FindTask(nil));
  350. if self^.pr_CLI = NIL then begin
  351. { if we're running from Ambient/Workbench, we catch its message }
  352. WaitPort(@self^.pr_MsgPort);
  353. AOS_wbMsg:=GetMsg(@self^.pr_MsgPort);
  354. end;
  355. AOS_DOSBase := OpenLibrary('dos.library', 0);
  356. if AOS_DOSBase = nil then
  357. Halt(1);
  358. AOS_UtilityBase := OpenLibrary('utility.library', 0);
  359. if AOS_UtilityBase = nil then
  360. Halt(1);
  361. { Creating the memory pool for growing heap }
  362. ASYS_heapPool := CreatePool(MEMF_ANY or MEMF_SEM_PROTECTED, growheapsize2, growheapsize1);
  363. if ASYS_heapPool = nil then
  364. Halt(1);
  365. { Initialize semaphore for filelist access arbitration }
  366. ASYS_fileSemaphore:=AllocPooled(ASYS_heapPool,sizeof(TSignalSemaphore));
  367. if ASYS_fileSemaphore = nil then
  368. Halt(1);
  369. InitSemaphore(ASYS_fileSemaphore);
  370. if AOS_wbMsg = nil then begin
  371. StdInputHandle := THandle(dosInput);
  372. StdOutputHandle := THandle(dosOutput);
  373. StdErrorHandle := THandle(DosError1);
  374. end else begin
  375. AOS_ConHandle := Open(AOS_ConName, MODE_OLDFILE);
  376. if AOS_ConHandle <> 0 then begin
  377. StdInputHandle := AOS_ConHandle;
  378. StdOutputHandle := AOS_ConHandle;
  379. StdErrorHandle := AOS_ConHandle;
  380. end else
  381. Halt(1);
  382. end;
  383. end;
  384. procedure SysInitStdIO;
  385. begin
  386. OpenStdIO(Input,fmInput,StdInputHandle);
  387. OpenStdIO(Output,fmOutput,StdOutputHandle);
  388. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  389. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  390. end;
  391. function GetProcessID: SizeUInt;
  392. begin
  393. GetProcessID := SizeUInt(FindTask(NIL));
  394. end;
  395. function CheckInitialStkLen(stklen : SizeUInt) : SizeUInt;
  396. begin
  397. result := stklen;
  398. end;
  399. begin
  400. IsConsole := TRUE;
  401. SysResetFPU;
  402. if not (IsLibrary) then
  403. SysInitFPU;
  404. StackLength := CheckInitialStkLen(InitialStkLen);
  405. StackBottom := Sptr - StackLength;
  406. { OS specific startup }
  407. AOS_wbMsg := nil;
  408. ASYS_origDir := 0;
  409. ASYS_fileList := nil;
  410. envp := nil;
  411. SysInitAmigaOS;
  412. { Set up signals handlers }
  413. //InstallSignals;
  414. { Setup heap }
  415. InitHeap;
  416. SysInitExceptions;
  417. initunicodestringmanager;
  418. { Setup stdin, stdout and stderr }
  419. SysInitStdIO;
  420. { Reset IO Error }
  421. InOutRes:=0;
  422. { Arguments }
  423. GenerateArgs;
  424. InitSystemThreads;
  425. InitSystemDynLibs;
  426. end.