system.pp 11 KB

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