sysutils.inc 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  1. {%MainUnit sysutils.pp}
  2. {
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { MCBS functions }
  13. {$i sysansi.inc}
  14. {$i syscodepages.inc}
  15. {$macro on}
  16. {$define PathStr:=UnicodeString}
  17. {$define PathPChar:=PUnicodeChar}
  18. {$define SYSUTILSUNICODE}
  19. { Read filename handling functions implementation }
  20. {$i fina.inc}
  21. { Read disk function implementations }
  22. {$i disk.inc}
  23. {$undef SYSUTILSUNICODE}
  24. {$define PathStr:=RawByteString}
  25. {$define PathPChar:=PAnsiChar}
  26. { Read filename handling functions implementation }
  27. {$i fina.inc}
  28. { Read disk function implementations }
  29. {$i disk.inc}
  30. {$undef PathStr}
  31. {$undef PathPChar}
  32. { Read file utility functions implementation }
  33. {$i filutil.inc}
  34. { variant error codes }
  35. {$i varerror.inc}
  36. { Type helpers}
  37. {$i syshelp.inc}
  38. {$IFDEF FPC_HAS_FEATURE_UNICODESTRINGS}
  39. { strange Delphi thing }
  40. {$i sysmarshal.inc}
  41. {$ENDIF}
  42. {$ifndef OS_FILEISREADONLY}
  43. Function FileIsReadOnly(const FileName: RawByteString): Boolean;
  44. begin
  45. Result := (FileGetAttr(FileName) and faReadOnly) <> 0;
  46. end;
  47. Function FileIsReadOnly(const FileName: UnicodeString): Boolean;
  48. begin
  49. Result := (FileGetAttr(FileName) and faReadOnly) <> 0;
  50. end;
  51. {$endif OS_FILEISREADONLY}
  52. {$ifndef OS_FILESETDATEBYNAME}
  53. Function FileSetDate (Const FileName : RawByteString;Age : Int64) : Longint;
  54. Var
  55. fd : THandle;
  56. begin
  57. { at least windows requires fmOpenWrite here }
  58. fd:=FileOpen(FileName,fmOpenWrite);
  59. If (Fd<>feInvalidHandle) then
  60. try
  61. Result:=FileSetDate(fd,Age);
  62. finally
  63. FileClose(fd);
  64. end
  65. else
  66. {$ifdef HAS_OSERROR}
  67. Result:=GetLastOSError;
  68. {$else}
  69. Result:=-1;
  70. {$endif}
  71. end;
  72. Function FileSetDate (Const FileName : UnicodeString;Age : Int64) : Longint;
  73. Var
  74. fd : THandle;
  75. begin
  76. { at least windows requires fmOpenWrite here }
  77. fd:=FileOpen(FileName,fmOpenWrite);
  78. If (Fd<>feInvalidHandle) then
  79. try
  80. Result:=FileSetDate(fd,Age);
  81. finally
  82. FileClose(fd);
  83. end
  84. else
  85. {$ifdef HAS_OSERROR}
  86. Result:=GetLastOSError;
  87. {$else}
  88. Result:=-1;
  89. {$endif}
  90. end;
  91. {$endif}
  92. { Read String Handling functions implementation }
  93. {$i sysstr.inc}
  94. { Read date & Time function implementations }
  95. {$ifndef FPUNONE}
  96. {$i dati.inc}
  97. {$endif}
  98. {$IFNDEF HAS_GETTICKCOUNT}
  99. function GetTickCount: LongWord;
  100. begin
  101. Result := LongWord(GetTickCount64);
  102. end;
  103. {$ENDIF}
  104. {$IFNDEF HAS_GETTICKCOUNT64}
  105. function GetTickCount64: QWord;
  106. begin
  107. {$IFDEF FPU_NONE}
  108. {$IFDEF HAS_SYSTIMERTICK}
  109. Result := SysTimerTick;
  110. {$ELSE}
  111. Result := 0;
  112. {$ENDIF}
  113. {$ELSE}
  114. Result := Trunc(Now * 24 * 60 * 60 * 1000);
  115. {$ENDIF}
  116. end;
  117. {$ENDIF}
  118. { Read PAnsiChar handling functions implementation }
  119. {$i syspch.inc}
  120. { generic internationalisation code }
  121. {$i sysint.inc}
  122. { wide string functions }
  123. {$i syswide.inc}
  124. {$ifdef FPC_HAS_UNICODESTRING}
  125. { unicode string functions }
  126. {$i sysuni.inc}
  127. {$i sysencoding.inc}
  128. {$endif FPC_HAS_UNICODESTRING}
  129. { threading stuff }
  130. {$i sysuthrd.inc}
  131. { OS utility code }
  132. {$i osutil.inc}
  133. procedure FreeAndNil(var obj);
  134. var
  135. temp: tobject;
  136. begin
  137. temp:=tobject(obj);
  138. pointer(obj):=nil;
  139. temp.free;
  140. end;
  141. procedure FreeMemAndNil(var p);
  142. var
  143. temp:Pointer;
  144. begin
  145. temp := Pointer(p);
  146. Pointer(P):=nil;
  147. FreeMem(temp);
  148. end;
  149. { Interfaces support }
  150. {$i sysuintf.inc}
  151. constructor Exception.Create(const msg : string);
  152. begin
  153. inherited create;
  154. fmessage:=msg;
  155. end;
  156. constructor Exception.CreateFmt(const msg : string; const args : array of const);
  157. begin
  158. inherited create;
  159. fmessage:=Format(msg,args);
  160. end;
  161. constructor Exception.CreateRes(ResString: PResStringRec);
  162. begin
  163. inherited create;
  164. fmessage:=ResString^;
  165. end;
  166. constructor Exception.CreateResFmt(ResString: PResStringRec; const Args: array of const);
  167. begin
  168. inherited create;
  169. fmessage:=Format(ResString^,args);
  170. end;
  171. constructor Exception.CreateHelp(const Msg: string; AHelpContext: Longint);
  172. begin
  173. inherited create;
  174. fmessage:=Msg;
  175. fhelpcontext:=AHelpContext;
  176. end;
  177. constructor Exception.CreateFmtHelp(const Msg: string; const Args: array of const;
  178. AHelpContext: Longint);
  179. begin
  180. inherited create;
  181. fmessage:=Format(Msg,args);
  182. fhelpcontext:=AHelpContext;
  183. end;
  184. constructor Exception.CreateResHelp(ResString: PResStringRec; AHelpContext: Longint);
  185. begin
  186. inherited create;
  187. fmessage:=ResString^;
  188. fhelpcontext:=AHelpContext;
  189. end;
  190. constructor Exception.CreateResFmtHelp(ResString: PResStringRec; const Args: array of const;
  191. AHelpContext: Longint);
  192. begin
  193. inherited create;
  194. fmessage:=Format(ResString^,args);
  195. fhelpcontext:=AHelpContext;
  196. end;
  197. Function Exception.ToString : RTLString;
  198. begin
  199. Result:=ClassName+': '+Message;
  200. end;
  201. procedure EHeapMemoryError.FreeInstance;
  202. begin
  203. if AllowFree then
  204. inherited FreeInstance;
  205. end;
  206. function Exception.GetBaseException : Exception;
  207. var
  208. _ExceptObjectStack : PExceptObject;
  209. begin
  210. _ExceptObjectStack:=RaiseList;
  211. While Assigned(_ExceptObjectStack) do
  212. begin
  213. result:=Exception(_ExceptObjectStack^.FObject);
  214. _ExceptObjectStack:=_ExceptObjectStack^.Next;
  215. end;
  216. end;
  217. Constructor EVariantError.CreateCode (Code : longint);
  218. begin
  219. case Code of
  220. VAR_OK:
  221. Create(SNoError);
  222. VAR_PARAMNOTFOUND:
  223. Create(SVarParamNotFound);
  224. VAR_TYPEMISMATCH:
  225. Create(SInvalidVarCast);
  226. VAR_BADVARTYPE:
  227. Create(SVarBadType);
  228. VAR_OVERFLOW:
  229. Create(SVarOverflow);
  230. VAR_BADINDEX:
  231. Create(SVarArrayBounds);
  232. VAR_ARRAYISLOCKED:
  233. Create(SVarArrayLocked);
  234. VAR_NOTIMPL:
  235. Create(SVarNotImplemented);
  236. VAR_OUTOFMEMORY:
  237. Create(SVarOutOfMemory);
  238. VAR_INVALIDARG:
  239. Create(SVarInvalid);
  240. VAR_UNEXPECTED,
  241. VAR_EXCEPTION:
  242. Create(SVarUnexpected);
  243. else
  244. CreateFmt(SUnknownErrorCode,[Code]);
  245. end;
  246. ErrCode:=Code;
  247. end;
  248. constructor EInOutArgumentException.Create(const aMsg, aPath: string); overload;
  249. begin
  250. Path:=aPath;
  251. Inherited Create(aMsg);
  252. end;
  253. constructor EInOutArgumentException.CreateRes(ResStringRec: PResStringRec; const aPath: string); overload;
  254. begin
  255. Path:=aPath;
  256. Inherited CreateRes(ResStringRec);
  257. end;
  258. constructor EInOutArgumentException.CreateFmt(const fmt: string; const args : array of const; const aPath : String);
  259. begin
  260. Path:=aPath;
  261. inherited CreateFmt(fmt,args);
  262. end;
  263. {$if defined(win32) or defined(win64) or defined (wince)}
  264. function EExternal.GetExceptionRecord: PExceptionRecord;
  265. begin
  266. result:=@FExceptionRecord;
  267. end;
  268. {$endif win32 or win64 or wince}
  269. {$push}
  270. {$S-}
  271. Procedure CatchUnhandledException (Obj : TObject; Addr: CodePointer; FrameCount: Longint; Frames: PCodePointer);[public,alias:'FPC_BREAK_UNHANDLED_EXCEPTION'];
  272. Var
  273. i : longint;
  274. hstdout : ^text;
  275. begin
  276. if WriteErrorsToStdErr then
  277. hstdout:=@stderr
  278. else
  279. hstdout:=@stdout;
  280. Writeln(hstdout^,'An unhandled exception occurred at $',HexStr(Addr),':');
  281. if Obj is exception then
  282. Writeln(hstdout^,Obj.ClassName,': ',Exception(Obj).Message)
  283. else if Obj is TObject then
  284. Writeln(hstdout^,'Exception object ',Obj.ClassName,' is not of class Exception.')
  285. else
  286. Writeln(hstdout^,'Exception object is not a valid class.');
  287. {$IFDEF HAS_OSERROR}
  288. {$IFDEF DEBUG_EXCEPTIONS_LASTOSERROR}
  289. WriteLn (HStdOut^, 'Last OS error detected in the RTL: ', GetLastOSError);
  290. {$ENDIF DEBUG_EXCEPTIONS_LASTOSERROR}
  291. {$ENDIF HAS_OSERROR}
  292. Writeln(hstdout^,BackTraceStrFunc(Addr));
  293. if (FrameCount>0) then
  294. begin
  295. for i:=0 to FrameCount-1 do
  296. Writeln(hstdout^,BackTraceStrFunc(Frames[i]));
  297. end;
  298. Writeln(hstdout^,'');
  299. end;
  300. type
  301. PExceptMapEntry=^TExceptMapEntry;
  302. TExceptMapEntry=record
  303. code: byte;
  304. cls: ExceptClass;
  305. {$IFDEF FPC_HAS_FEATURE_RESOURCES} // This is necessary for 2.4.4, which does not have reasources as a separate feature
  306. msg: PResStringRec;
  307. {$else FPC_HAS_FEATURE_RESOURCES}
  308. msg: PAnsiString;
  309. {$endif FPC_HAS_FEATURE_RESOURCES}
  310. end;
  311. const
  312. exceptmap: array[0..30] of TExceptMapEntry = (
  313. (code: 200; cls: EDivByZero; msg: @SDivByZero),
  314. (code: 201; cls: ERangeError; msg: @SRangeError),
  315. (code: 202; cls: EStackOverflow; msg: @SStackOverflow),
  316. (code: 205; cls: EOverflow; msg: @SOverflow),
  317. (code: 206; cls: EUnderflow; msg: @SUnderflow),
  318. (code: 207; cls: EInvalidOp; msg: @SInvalidOp),
  319. { Delphi distinguishes reDivByZero from reZeroDivide, but maps both to code 200. }
  320. (code: 208; cls: EZeroDivide; msg: @SZeroDivide),
  321. (code: 210; cls: EObjectCheck; msg: @SObjectCheckError),
  322. (code: 211; cls: EAbstractError; msg: @SAbstractError),
  323. (code: 212; cls: EExternalException; msg: @SExternalException),
  324. (code: 214; cls: EBusError; msg: @SBusError),
  325. (code: 215; cls: EIntOverflow; msg: @SIntOverflow),
  326. (code: 216; cls: EAccessViolation; msg: @SAccessViolation),
  327. (code: 217; cls: EControlC; msg: @SControlC),
  328. (code: 218; cls: EPrivilege; msg: @SPrivilege),
  329. (code: 219; cls: EInvalidCast; msg: @SInvalidCast),
  330. (code: 220; cls: EVariantError; msg: @SInvalidVarCast),
  331. (code: 221; cls: EVariantError; msg: @SInvalidVarOp),
  332. (code: 222; cls: EVariantError; msg: @SDispatchError),
  333. (code: 223; cls: EVariantError; msg: @SVarArrayCreate),
  334. (code: 224; cls: EVariantError; msg: @SVarNotArray),
  335. (code: 225; cls: EVariantError; msg: @SVarArrayBounds),
  336. (code: 227; cls: EAssertionFailed; msg: @SAssertionFailed),
  337. (code: 228; cls: EIntfCastError; msg: @SIntfCastError),
  338. (code: 229; cls: ESafecallException; msg: @SSafecallException),
  339. (code: 231; cls: EConvertError; msg: @SiconvError),
  340. (code: 232; cls: ENoThreadSupport; msg: @SNoThreadSupport),
  341. (code: 233; cls: ESigQuit; msg: @SSigQuit),
  342. (code: 234; cls: ENoWideStringSupport; msg: @SMissingWStringManager),
  343. (code: 235; cls: ENoDynLibsSupport; msg: @SNoDynLibsSupport),
  344. (code: 236; cls: EThreadError; msg: @SThreadError)
  345. );
  346. function FindExceptMapEntry(err: longint): PExceptMapEntry;
  347. var
  348. i: longint;
  349. begin
  350. for i:=low(exceptmap) to high(exceptmap) do
  351. if err=exceptmap[i].code then
  352. begin
  353. result:=@exceptmap[i];
  354. exit;
  355. end;
  356. result:=nil;
  357. end;
  358. Var OutOfMemory : EOutOfMemory;
  359. InValidPointer : EInvalidPointer;
  360. Procedure RunErrorToExcept (ErrNo : Longint; Address : CodePointer; Frame : Pointer);
  361. var
  362. E: Exception;
  363. HS: PResStringRec;
  364. Entry: PExceptMapEntry;
  365. begin
  366. Case Errno of
  367. 1,203 : E:=OutOfMemory;
  368. 204 : E:=InvalidPointer;
  369. else
  370. Entry:=FindExceptMapEntry(ErrNo);
  371. if Assigned(Entry) then
  372. E:=Entry^.cls.CreateRes(Entry^.msg)
  373. else
  374. begin
  375. HS:=nil;
  376. Case Errno of
  377. 2 : HS:=@SFileNotFound;
  378. 3 : HS:=@SInvalidFileName;
  379. 4 : HS:=@STooManyOpenFiles;
  380. 5 : HS:=@SAccessDenied;
  381. 6 : HS:=@SInvalidFileHandle;
  382. 15 : HS:=@SInvalidDrive;
  383. 100 : HS:=@SEndOfFile;
  384. 101 : HS:=@SDiskFull;
  385. 102 : HS:=@SFileNotAssigned;
  386. 103 : HS:=@SFileNotOpen;
  387. 104 : HS:=@SFileNotOpenForInput;
  388. 105 : HS:=@SFileNotOpenForOutput;
  389. 106 : HS:=@SInvalidInput;
  390. end;
  391. if Assigned(HS) then
  392. E:=EInOutError.CreateRes(HS)
  393. else
  394. E:=EInOutError.CreateResFmt(@SUnknownRunTimeError,[errno]);
  395. // this routine can be called from FPC_IOCHECK,
  396. // which clears inoutres and then passes its
  397. // original value to HandleErrorFrame() (which calls
  398. // us). So use errno rather than IOResult, and clear
  399. // InOutRes explicitly in case we can also be called
  400. // from a place that does not clear InOutRes explicitly
  401. EInoutError(E).ErrorCode:=errno;
  402. inoutres:=0;
  403. end;
  404. end;
  405. Raise E at Address,Frame;
  406. end;
  407. {$IFDEF HAS_OSERROR}
  408. Procedure RaiseLastOSError;overload;
  409. begin
  410. RaiseLastOSError(GetLastOSError);
  411. end;
  412. Procedure RaiseLastOSError(LastError: Integer);overload;
  413. var
  414. E : EOSError;
  415. begin
  416. If (LastError<>0) then
  417. E:=EOSError.CreateFmt(SOSError, [LastError, SysErrorMessage(LastError)])
  418. else
  419. E:=EOSError.Create(SUnkOSError);
  420. E.ErrorCode:=LastError;
  421. Raise E;
  422. end;
  423. {$else}
  424. Procedure RaiseLastOSError;overload;
  425. begin
  426. Raise Exception.Create('RaiseLastOSError not implemented on this platform.');
  427. end;
  428. Procedure RaiseLastOSError(LastError: Integer);overload;
  429. begin
  430. RaiseLastOSError;
  431. end;
  432. {$endif}
  433. procedure CheckOSError(LastError: Integer);
  434. begin
  435. if LastError <> 0 then
  436. RaiseLastOSError(LastError);
  437. end;
  438. Procedure AssertErrorHandler (Const Msg,FN : ShortString;LineNo:longint; TheAddr : pointer);
  439. Var
  440. S : String;
  441. begin
  442. If Msg='' then
  443. S:=SAssertionFailed
  444. else
  445. S:=Msg;
  446. Raise EAssertionFailed.Createfmt(SAssertError,[S,Fn,LineNo]) at get_caller_addr(theAddr), get_caller_frame(theAddr);
  447. end;
  448. {$pop} //{$S-} for Error handling functions
  449. procedure RangeIndexError(aIndex, aMaxIndex: SizeInt; aListObj: TObject);
  450. begin
  451. raise ERangeError.Create(ListIndexErrorMsg(aIndex,aMaxIndex,aListObj));
  452. end;
  453. Procedure InitExceptions;
  454. {
  455. Must install uncaught exception handler (ExceptProc)
  456. and install exceptions for system exceptions or signals.
  457. (e.g: SIGSEGV -> ESegFault or so.)
  458. }
  459. begin
  460. ExceptionClass := Exception;
  461. ExceptProc:=@CatchUnhandledException;
  462. // Create objects that may have problems when there is no memory.
  463. OutOfMemory:=EOutOfMemory.Create(SOutOfMemory);
  464. OutOfMemory.AllowFree:=false;
  465. InvalidPointer:=EInvalidPointer.Create(SInvalidPointer);
  466. InvalidPointer.AllowFree:=false;
  467. AssertErrorProc:=@AssertErrorHandler;
  468. ErrorProc:=@RunErrorToExcept;
  469. OnShowException:=Nil;
  470. end;
  471. Procedure DoneExceptions;
  472. begin
  473. OutOfMemory.AllowFree:=true;
  474. OutOfMemory.Free;
  475. InValidPointer.AllowFree:=true;
  476. InValidPointer.Free;
  477. end;
  478. { Exception handling routines }
  479. function ExceptObject: TObject;
  480. begin
  481. If RaiseList=Nil then
  482. Result:=Nil
  483. else
  484. Result:=RaiseList^.FObject;
  485. end;
  486. function ExceptAddr: CodePointer;
  487. begin
  488. If RaiseList=Nil then
  489. Result:=Nil
  490. else
  491. Result:=RaiseList^.Addr;
  492. end;
  493. function ExceptFrameCount: Longint;
  494. begin
  495. If RaiseList=Nil then
  496. Result:=0
  497. else
  498. Result:=RaiseList^.Framecount;
  499. end;
  500. function ExceptFrames: PCodePointer;
  501. begin
  502. If RaiseList=Nil then
  503. Result:=Nil
  504. else
  505. Result:=RaiseList^.Frames;
  506. end;
  507. function ExceptionErrorMessage(ExceptObject: TObject; ExceptAddr: Pointer;
  508. Buffer: PAnsiChar; Size: Integer): Integer;
  509. Var
  510. S : AnsiString;
  511. Len : Integer;
  512. begin
  513. S:=Format(SExceptionErrorMessage,[ExceptAddr,ExceptObject.ClassName]);
  514. If ExceptObject is Exception then
  515. S:=Format('%s:'#10'%s',[S,Exception(ExceptObject).Message]);
  516. Len:=Length(S);
  517. If S[Len]<>'.' then
  518. begin
  519. S:=S+'.';
  520. Inc(len);
  521. end;
  522. If Len>Size then
  523. Len:=Size;
  524. if Len > 0 then
  525. Move(S[1],Buffer^,Len);
  526. Result:=Len;
  527. end;
  528. procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);
  529. // use shortstring. On exception, the heap may be corrupt.
  530. Var
  531. Buf : ShortString;
  532. begin
  533. SetLength(Buf,ExceptionErrorMessage(ExceptObject,ExceptAddr,@Buf[1],255));
  534. If IsConsole Then
  535. writeln(Buf)
  536. else
  537. If Assigned(OnShowException) Then
  538. OnShowException (Buf);
  539. end;
  540. procedure Abort;
  541. begin
  542. Raise EAbort.Create(SAbortError) at CodePointer(Get_Caller_addr(Get_Frame));
  543. end;
  544. procedure OutOfMemoryError;
  545. begin
  546. Raise OutOfMemory;
  547. end;
  548. function ListIndexErrorMsg(aIndex, aMaxIndex: SizeInt; const aListObjName: string): string; overload;
  549. begin
  550. if aMaxIndex<0 then
  551. Result:=Format(SListIndexErrorEmptyReason,[aListObjName])
  552. else
  553. Result:=Format(SListIndexErrorRangeReason,[aListObjName]);
  554. Result:=Format(SListIndexError, [aIndex])+Result;
  555. end;
  556. function ListIndexErrorMsg(AIndex, AMaxIndex: SizeInt; AListObj: TObject): string; overload;
  557. Var
  558. aName : string;
  559. begin
  560. if Assigned(aListObj) then
  561. Result:=aListObj.ClassName
  562. else
  563. Result:='<Nil>';
  564. Result:=ListIndexErrorMsg(aIndex, aMaxIndex, aName);
  565. end;
  566. procedure ListIndexError(aIndex,aMax: Integer; aObj: TObject);
  567. var
  568. aClassName : string;
  569. begin
  570. if Assigned(aObj) then
  571. aClassName:=aObj.ClassName
  572. else
  573. aClassName:='<nil>';
  574. Raise EListError.CreateFmt(SErrListIndexExt,[aIndex,aClassName,aMax])
  575. end;
  576. { ---------------------------------------------------------------------
  577. Initialization/Finalization/exit code
  578. ---------------------------------------------------------------------}
  579. Type
  580. PPRecord = ^TPRecord;
  581. TPRecord = Record
  582. Func : TTerminateProc;
  583. NextFunc : PPRecord;
  584. end;
  585. Const
  586. TPList : PPRecord = Nil;
  587. procedure AddTerminateProc(TermProc: TTerminateProc);
  588. Var
  589. TPR : PPRecord;
  590. begin
  591. New(TPR);
  592. With TPR^ do
  593. begin
  594. NextFunc:=TPList;
  595. Func:=TermProc;
  596. end;
  597. TPList:=TPR;
  598. end;
  599. function CallTerminateProcs: Boolean;
  600. Var
  601. TPR : PPRecord;
  602. begin
  603. Result:=True;
  604. TPR:=TPList;
  605. While Result and (TPR<>Nil) do
  606. begin
  607. Result:=TPR^.Func();
  608. TPR:=TPR^.NextFunc;
  609. end;
  610. end;
  611. procedure FreeTerminateProcs;
  612. var
  613. TPR1, TPR2: PPRecord;
  614. begin
  615. TPR1 := TPList;
  616. TPList := Nil;
  617. while Assigned(TPR1) do begin
  618. TPR2 := TPR1^.NextFunc;
  619. Dispose(TPR1);
  620. TPR1 := TPR2;
  621. end;
  622. end;
  623. { ---------------------------------------------------------------------
  624. Diskh functions, OS independent.
  625. ---------------------------------------------------------------------}
  626. Function GetCurrentDir: {$ifdef FPC_UNICODE_RTL}UnicodeString{$else}AnsiString{$endif};
  627. begin
  628. GetDir(0,Result);
  629. end;
  630. { ---------------------------------------------------------------------
  631. Other functions, OS independent.
  632. ---------------------------------------------------------------------}
  633. Var
  634. GUIDCalledRandomize : Boolean = False;
  635. Procedure GetRandomBytes(Var Buf; NBytes : Integer);
  636. Var
  637. I : Integer;
  638. P : PByte;
  639. begin
  640. P:=@Buf;
  641. If Not GUIDCalledRandomize then
  642. begin
  643. Randomize;
  644. GUIDCalledRandomize:=True;
  645. end;
  646. For I:=0 to NBytes-1 do
  647. P[i]:=Random(256);
  648. end;
  649. {$IFDEF HASCREATEGUID}
  650. Function SysCreateGUID(out GUID : TGUID) : Integer; forward;
  651. {$ENDIF}
  652. Function CreateGUID(out GUID : TGUID) : Integer;
  653. begin
  654. If Assigned(OnCreateGUID) then
  655. Result:=OnCreateGUID(GUID)
  656. else
  657. begin
  658. {$IFDEF HASCREATEGUID}
  659. Result:=SysCreateGUID(GUID);
  660. {$ELSE}
  661. GetRandomBytes(GUID,SizeOf(Guid));
  662. guid.clock_seq_hi_and_reserved:=(guid.clock_seq_hi_and_reserved and $3F) + 64;
  663. guid.time_hi_and_version :=(guid.time_hi_and_version and $0FFF)+ $4000;
  664. Result:=0;
  665. {$ENDIF}
  666. end;
  667. end;
  668. function SafeLoadLibrary(const FileName: AnsiString; ErrorMode: DWord = {$ifdef windows}SEM_NOOPENFILEERRORBOX{$else windows}0{$endif windows}): HMODULE;
  669. {$if defined(win64) or defined(win32)}
  670. var
  671. mode : DWord;
  672. begin
  673. mode:=SetErrorMode(ErrorMode);
  674. try
  675. Result:=System.SafeLoadLibrary(FileName);
  676. finally
  677. SetErrorMode(mode);
  678. end;
  679. end;
  680. {$else}
  681. begin
  682. {$ifdef FPC_HAS_FEATURE_DYNLIBS}
  683. Result:=System.SafeLoadLibrary(FileName);
  684. {$else}
  685. Result:=HModule(nil);
  686. {$endif not FPC_HAS_FEATURE_DYNLIBS}
  687. end;
  688. {$endif}
  689. {$if defined(win32) or defined(win64) or defined(wince)}
  690. function GetModuleName(Module: HMODULE): string;
  691. var
  692. ResultLength, BufferLength: DWORD;
  693. Buffer: UnicodeString;
  694. begin
  695. BufferLength := MAX_PATH div 2;
  696. repeat
  697. Inc(BufferLength, BufferLength);
  698. SetLength(Buffer, BufferLength);
  699. ResultLength := GetModuleFileNameW(Module, Pointer(Buffer), BufferLength);
  700. if ResultLength = 0 then
  701. Exit('');
  702. until ResultLength < BufferLength;
  703. SetLength(Buffer, ResultLength);
  704. Result := Buffer;
  705. end;
  706. {$elseif defined(win16)}
  707. function GetModuleName(Module: HMODULE): string;
  708. var
  709. ResultLength, BufferLength: DWORD;
  710. Buffer: RawByteString;
  711. begin
  712. BufferLength := MAX_PATH div 2;
  713. repeat
  714. Inc(BufferLength, BufferLength);
  715. SetLength(Buffer, BufferLength);
  716. ResultLength := GetModuleFileName(Module, FarAddr(Buffer[1]), BufferLength);
  717. if ResultLength = 0 then
  718. Exit('');
  719. until ResultLength < BufferLength;
  720. SetLength(Buffer, ResultLength);
  721. Result := Buffer;
  722. end;
  723. {$else}
  724. function GetModuleName(Module: HMODULE): string;
  725. begin
  726. Result:='';
  727. end;
  728. {$endif}
  729. { Beep support }
  730. procedure Beep;
  731. begin
  732. If Assigned(OnBeep) then
  733. OnBeep;
  734. end;
  735. // OSes that only provide 1 byte versions can enable the following define
  736. {$ifdef executeprocuni}
  737. function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
  738. begin
  739. result:=ExecuteProcess(ToSingleByteFileSystemEncodedFileName(Path),ToSingleByteFileSystemEncodedFileName(ComLine));
  740. end;
  741. function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
  742. var
  743. ComLineA : array of RawByteString;
  744. I : Integer;
  745. begin
  746. SetLength(ComLineA,high(comline)-low(comline)+1);
  747. For I:=0 to length(ComLineA)-1 Do
  748. ComLineA[i]:=ToSingleByteFileSystemEncodedFileName(ComLine[I]);
  749. result:=ExecuteProcess(ToSingleByteFileSystemEncodedFileName(Path),ComLineA);
  750. end;
  751. {$endif}
  752. // generic ifthen..
  753. {$IFNDEF VER3_0}
  754. generic function IfThen<T>(val:boolean;const iftrue:T; const iffalse:T) :T; inline; overload;
  755. begin
  756. if val then
  757. Result := ifTrue
  758. else
  759. Result:=ifFalse;
  760. end;
  761. generic function Exchange<T>(var target:T; const newvalue:T) :T;
  762. begin
  763. Result := target;
  764. target := newvalue;
  765. end;
  766. {$ENDIF}
  767. Function ArrayOfConstToStrArray(const Args: array of const) : TUTF8StringDynArray;
  768. var
  769. i: Integer;
  770. O : TObject;
  771. C : TClass;
  772. S : String;
  773. begin
  774. SetLength(Result,Length(Args));
  775. for i:=Low(Args) to High(Args) do
  776. case Args[i].VType of
  777. vtInteger: Result[i]:=IntToStr(Args[i].VInteger);
  778. vtBoolean: Result[i]:=BoolToStr(Args[i].VBoolean);
  779. vtChar: Result[i] := Args[i].VChar;
  780. {$ifndef FPUNONE}
  781. vtExtended: Result[i]:= FloatToStr(Args[i].VExtended^);
  782. {$ENDIF}
  783. vtString: Result[i] := Args[i].VString^;
  784. vtPointer: Result[i] := '0x'+HexStr(PtrInt(Args[i].VPointer),SizeOF(PtrInt));
  785. vtPChar: Result[i] := Args[i].VPChar;
  786. vtObject:
  787. begin
  788. O:=Args[i].VObject;
  789. if Assigned(O) then
  790. begin
  791. try
  792. S:=O.ClassName;
  793. except
  794. S:='<Invalid instance>';
  795. end;
  796. end
  797. else
  798. S:='';
  799. Result[I] := '<Object '+S+' 0x'+HexStr(PtrInt(O),SizeOF(PtrInt))+'>';
  800. end;
  801. vtClass:
  802. begin
  803. C:=Args[i].VClass;
  804. if Assigned(C) then
  805. begin
  806. try
  807. S:=C.ClassName;
  808. except
  809. S:='<Invalid Class>';
  810. end;
  811. end
  812. else
  813. S:='';
  814. Result[I] := '<Class '+S+' 0x'+HexStr(PtrInt(C),SizeOF(PtrInt))+'>';
  815. end;
  816. vtWideChar: Result[i] := UTF8Encode(Args[i].VWideChar);
  817. vtPWideChar: Result[i] := UTF8Encode(Args[i].VPWideChar^);
  818. vtAnsiString: Result[i] := AnsiString(Args[i].VAnsiString);
  819. vtCurrency: Result[i] := FLoatToSTr(Args[i].VCurrency^);
  820. vtVariant: Result[i] := Args[i].VVariant^;
  821. vtInterface: Result[I] := '<Interface 0x'+HexStr(PtrInt(Args[i].VInterface),SizeOF(PtrInt))+'>';
  822. vtWidestring: Result[i] := UTF8ENcode(WideString(Args[i].VWideString));
  823. vtInt64: Result[i] := IntToStr(Args[i].VInt64^);
  824. vtQWord: Result[i] := IntToStr(Args[i].VQWord^);
  825. vtUnicodeString:Result[i] := UTF8Encode(UnicodeString(Args[i].VUnicodeString));
  826. end;
  827. end;
  828. Function ArrayOfConstToStr(const Args: array of const ; aSeparator : Char = ','; aQuoteBegin : Char = '"'; aQuoteEnd : Char = '"') : UTF8String;
  829. Procedure Add(s: UTF8String);
  830. begin
  831. if aQuoteBegin<>#0 then
  832. S:=aQuoteBegin+S;
  833. if aQuoteEnd<>#0 then
  834. S:=S+aQuoteEnd;
  835. if Result<>'' then
  836. Result:=Result+aSeparator;
  837. Result:=Result+S;
  838. end;
  839. Var
  840. S : UTF8String;
  841. begin
  842. Result:='';
  843. For S in ArrayOfConstToStrArray(Args) do
  844. Add(S);
  845. end;
  846. Function GetCompiledArchitecture : TOSVersion.TArchitecture;
  847. begin
  848. Result:=arOther;
  849. {$ifdef i386}
  850. Result:=arIntelX86;
  851. {$endif i386}
  852. {$ifdef m68k}
  853. Result:=arM68k;
  854. {$endif m68k}
  855. {$ifdef powerpc}
  856. Result:=arPowerPC
  857. {$endif powerpc}
  858. {$ifdef powerpc64}
  859. Result:=arPower64
  860. {$endif powerpc64}
  861. {$ifdef arm}
  862. Result:=arARM32;
  863. {$endif arm}
  864. {$ifdef aarch64}
  865. Result:=arARM64
  866. {$endif aarch64}
  867. {$ifdef sparc}
  868. Result:=arSparc;
  869. {$endif sparc}
  870. {$ifdef sparc64}
  871. Result:=arSparc64;
  872. {$endif sparc64}
  873. {$ifdef CPUX86_64}
  874. Result:=arIntelX64;
  875. {$endif x86_64}
  876. {$ifdef mipsel}
  877. Result:=arMipsel
  878. {$else : not mipsel}
  879. {$ifdef mips}
  880. Result:=arMips;
  881. {$endif mips}
  882. {$endif not mipsel}
  883. {$ifdef riscv32}
  884. Result:=arRiscV32;
  885. {$endif riscv32}
  886. {$ifdef riscv64}
  887. Result:=arRiscV64;
  888. {$endif riscv64}
  889. {$ifdef xtensa}
  890. Result:=arXtensa;
  891. {$endif xtensa}
  892. {$ifdef wasm32}
  893. Result:=arWasm32;
  894. {$endif wasm32}
  895. {$ifdef loongarch64}
  896. Result:=arLoongArch64;
  897. {$endif loongarch64}
  898. end;
  899. Function GetCompiledPlatform : TOSVersion.TPlatform;
  900. begin
  901. Result:=pfOther;
  902. {$IFDEF WINDOWS}
  903. Result:=pfWindows;
  904. {$ENDIF}
  905. {$Ifdef darwin}
  906. Result:=pfMacOS;
  907. {$ENDIF}
  908. {$IFDEF IOS}
  909. Result:=pfiOS;
  910. {$ENDIF}
  911. {$IFDEF ANDROID}
  912. Result:=pfAndroid;
  913. {$ENDIF}
  914. {$IFDEF LINUX}
  915. Result:=pfLinux;
  916. {$ENDIF}
  917. {$IFDEF GO32V2}
  918. Result:=pfGo32v2;
  919. {$ENDIF}
  920. {$IFDEF OS2}
  921. Result:=pfOS2;
  922. {$ENDIF}
  923. {$IFDEF FREEBSD}
  924. Result:=pfFreeBSD;
  925. {$ENDIF}
  926. {$IFDEF BEOS}
  927. Result:=pfBeos;
  928. {$ENDIF}
  929. {$IFDEF NETBSD}
  930. Result:=pfNetBSD;
  931. {$ENDIF}
  932. {$IFDEF AMIGA}
  933. Result:=pfAmiga;
  934. {$ENDIF}
  935. {$IFDEF ATARI}
  936. Result:=pfAtari;
  937. {$ENDIF}
  938. {$IFDEF SUNOS}
  939. Result:=pfSolaris;
  940. {$ENDIF}
  941. {$IFDEF QNX}
  942. Result:=pfQNX;
  943. {$ENDIF}
  944. {$IFDEF Netware}
  945. Result:=pfNetware;
  946. {$ENDIF}
  947. {$IFDEF OpenBSD}
  948. Result:=pfOpenBSD;
  949. {$ENDIF}
  950. {$IFDEF WDosX}
  951. Result:=pfWDosX;
  952. {$ENDIF}
  953. {$IFDEF PALMOS}
  954. Result:=pfPalmos;
  955. {$ENDIF}
  956. {$IFDEF MacOSClassic}
  957. Result:=pfMacOSClassic;
  958. {$ENDIF}
  959. {$IFDEF DARWIN}
  960. Result:=pfDarwin;
  961. {$ENDIF}
  962. {$IFDEF EMX}
  963. Result:=pfEMX;
  964. {$ENDIF}
  965. {$IFDEF WATCOM}
  966. Result:=pfWatcom;
  967. {$ENDIF}
  968. {$IFDEF MORPHOS}
  969. Result:=pfMorphos;
  970. {$ENDIF}
  971. {$IFDEF NETWLIBC}
  972. Result:=pfNetwLibC;
  973. {$ENDIF}
  974. {$IFDEF WINCE}
  975. Result:=pfWinCE;
  976. {$ENDIF}
  977. {$IFDEF GBA}
  978. Result:=pfGBA;
  979. {$ENDIF}
  980. {$IFDEF NDS}
  981. Result:=pfNDS;
  982. {$ENDIF}
  983. {$IFDEF EMBEDDED}
  984. Result:=pfEmbedded;
  985. {$ENDIF}
  986. {$IFDEF SYMBIAN}
  987. Result:=pfSymbian;
  988. {$ENDIF}
  989. {$IFDEF HAIKU}
  990. Result:=pfHaiku;
  991. {$ENDIF}
  992. {$IFDEF IPHONESIM}
  993. Result:=pfIPhoneSim;
  994. {$ENDIF}
  995. {$IFDEF AIX}
  996. Result:=pfAIX;
  997. {$ENDIF}
  998. {$IFDEF JAVA}
  999. Result:=pfJava;
  1000. {$ENDIF}
  1001. {$IFDEF NATIVENT}
  1002. Result:=pfNativeNT;
  1003. {$ENDIF}
  1004. {$IFDEF MSDOS}
  1005. Result:=pfMSDos;
  1006. {$ENDIF}
  1007. {$IFDEF WII}
  1008. Result:=pfWII;
  1009. {$ENDIF}
  1010. {$IFDEF AROS}
  1011. Result:=pfAROS;
  1012. {$ENDIF}
  1013. {$IFDEF DRAGONFLY}
  1014. Result:=pfDragonFly;
  1015. {$ENDIF}
  1016. {$IFDEF WIN16}
  1017. Result:=pfWin16;
  1018. {$ENDIF}
  1019. {$IFDEF FREERTOS}
  1020. Result:=pfFreeRTOS;
  1021. {$ENDIF}
  1022. {$IFDEF ZXSPECTRUM}
  1023. Result:=pfZXSpectrum;
  1024. {$ENDIF}
  1025. {$IFDEF MSXDOS}
  1026. Result:=pfMSXDOS;
  1027. {$ENDIF}
  1028. {$IFDEF AMSTRADCPC}
  1029. Result:=pfAmstradCPC;
  1030. {$ENDIF}
  1031. {$IFDEF SINCLAIRQL}
  1032. Result:=pfSinclairQL;
  1033. {$ENDIF}
  1034. {$IFDEF WASI}
  1035. Result:=pfWasi;
  1036. {$ENDIF}
  1037. end;
  1038. class constructor TOSVersion.Create;
  1039. {$IFNDEF HAS_OSVERSION}
  1040. var
  1041. S : String;
  1042. {$ENDIF}
  1043. begin
  1044. FArchitecture:=GetCompiledArchitecture;
  1045. FPlatform:=GetCompiledPlatform;
  1046. FBuild:=0;
  1047. FMajor:=0;
  1048. FMinor:=0;
  1049. FServicePackMajor:=0;
  1050. FServicePackMinor:=0;
  1051. {$IFDEF HAS_OSVERSION}
  1052. InitOSVersion;
  1053. {$ELSE}
  1054. WriteStr(S,GetCompiledPlatform);
  1055. FName:=Copy(S,3);
  1056. WriteStr(S,GetCompiledArchitecture);
  1057. FFull:=Copy(S,3)+'-'+FName;
  1058. {$ENDIF}
  1059. end;
  1060. class function TOSVersion.Check(aMajor: Integer): Boolean; overload; static; inline;
  1061. begin
  1062. Result:=(Major>=aMajor);
  1063. end;
  1064. class function TOSVersion.Check(aMajor, aMinor: Integer): Boolean; overload; static; inline;
  1065. begin
  1066. Result:=(Major>aMajor)
  1067. or ((Major=aMajor) and (Minor>=aMinor))
  1068. end;
  1069. class function TOSVersion.Check(aMajor, aMinor, aServicePackMajor: Integer): Boolean; overload; static; inline;
  1070. begin
  1071. Result:=(Major>AMajor)
  1072. or ((Major=aMajor) and (Minor>aMinor))
  1073. or ((Major=aMajor) and (Minor=aMinor) and (ServicePackMajor>=aServicePackMajor));
  1074. end;
  1075. class function TOSVersion.ToString: string; static;
  1076. begin
  1077. Result:=FFull;
  1078. end;