sysutils.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { Read filename handling functions implementation }
  12. {$i fina.inc}
  13. Function FileSearch (Const Name, DirList : String) : String;
  14. Var
  15. I : longint;
  16. Temp : String;
  17. begin
  18. Result:='';
  19. temp:=Dirlist;
  20. repeat
  21. While (Length(Temp)>0) and (Temp[1]=PathSeparator) do
  22. Delete(Temp,1,1);
  23. I:=pos(PathSep,Temp);
  24. If I<>0 then
  25. begin
  26. Result:=Copy (Temp,1,i-1);
  27. system.Delete(Temp,1,I);
  28. end
  29. else
  30. begin
  31. Result:=Temp;
  32. Temp:='';
  33. end;
  34. If (Length(Result)>0) and (result[length(result)]<>DirectorySeparator) then
  35. Result:=Result+DirectorySeparator;
  36. Result:=Result+name;
  37. If not FileExists(Result) Then
  38. Result:='';
  39. until (length(temp)=0) or (length(result)<>0);
  40. end;
  41. {$ifndef OS_FILEISREADONLY}
  42. Function FileIsReadOnly(const FileName: String): Boolean;
  43. begin
  44. Result := (FileGetAttr(FileName) and faReadOnly) <> 0;
  45. end;
  46. {$endif OS_FILEISREADONLY}
  47. {$ifndef OS_FILESETDATEBYNAME}
  48. Function FileSetDate (Const FileName : String;Age : Longint) : Longint;
  49. Var
  50. fd : longint;
  51. begin
  52. fd:=FileOpen(FileName,fmOpenRead);
  53. If (Fd>=0) then
  54. try
  55. Result:=FileSetDate(fd,Age);
  56. finally
  57. FileClose(fd);
  58. end
  59. else
  60. Result:=Fd;
  61. end;
  62. {$endif}
  63. { Read String Handling functions implementation }
  64. {$i sysstr.inc}
  65. { Read date & Time function implementations }
  66. {$i dati.inc}
  67. { Read pchar handling functions implementation }
  68. {$i syspch.inc}
  69. { generic internationalisation code }
  70. {$i sysint.inc}
  71. { MCBS functions }
  72. {$i sysansi.inc}
  73. { wide string functions }
  74. {$i syswide.inc}
  75. { threading stuff }
  76. {$i sysuthrd.inc}
  77. { CPU Specific code }
  78. {$i sysutilp.inc}
  79. { OS utility code }
  80. {$i osutil.inc}
  81. procedure FreeAndNil(var obj);
  82. var
  83. temp: tobject;
  84. begin
  85. temp:=tobject(obj);
  86. pointer(obj):=nil;
  87. temp.free;
  88. end;
  89. { Interfaces support }
  90. {$i sysuintf.inc}
  91. constructor Exception.Create(const msg : string);
  92. begin
  93. inherited create;
  94. fmessage:=msg;
  95. end;
  96. constructor Exception.CreateFmt(const msg : string; const args : array of const);
  97. begin
  98. inherited create;
  99. fmessage:=Format(msg,args);
  100. end;
  101. constructor Exception.CreateRes(ResString: PString);
  102. begin
  103. inherited create;
  104. fmessage:=ResString^;
  105. end;
  106. constructor Exception.CreateResFmt(ResString: PString; const Args: array of const);
  107. begin
  108. inherited create;
  109. fmessage:=Format(ResString^,args);
  110. end;
  111. constructor Exception.CreateHelp(const Msg: string; AHelpContext: Integer);
  112. begin
  113. inherited create;
  114. fmessage:=Msg;
  115. fhelpcontext:=AHelpContext;
  116. end;
  117. constructor Exception.CreateFmtHelp(const Msg: string; const Args: array of const;
  118. AHelpContext: Integer);
  119. begin
  120. inherited create;
  121. fmessage:=Format(Msg,args);
  122. fhelpcontext:=AHelpContext;
  123. end;
  124. constructor Exception.CreateResHelp(ResString: PString; AHelpContext: Integer);
  125. begin
  126. inherited create;
  127. fmessage:=ResString^;
  128. fhelpcontext:=AHelpContext;
  129. end;
  130. constructor Exception.CreateResFmtHelp(ResString: PString; const Args: array of const;
  131. AHelpContext: Integer);
  132. begin
  133. inherited create;
  134. fmessage:=Format(ResString^,args);
  135. fhelpcontext:=AHelpContext;
  136. end;
  137. procedure EHeapMemoryError.FreeInstance;
  138. begin
  139. if AllowFree then
  140. inherited FreeInstance;
  141. end;
  142. {$ifopt S+}
  143. {$define STACKCHECK_WAS_ON}
  144. {$S-}
  145. {$endif OPT S }
  146. Procedure CatchUnhandledException (Obj : TObject; Addr: Pointer; FrameCount: Longint; Frames: PPointer);[public,alias:'FPC_BREAK_UNHANDLED_EXCEPTION'];
  147. Var
  148. Message : String;
  149. i : longint;
  150. begin
  151. Writeln(stdout,'An unhandled exception occurred at $',HexStr(Ptrint(Addr),sizeof(PtrInt)*2),' :');
  152. if Obj is exception then
  153. begin
  154. Message:=Exception(Obj).ClassName+' : '+Exception(Obj).Message;
  155. Writeln(stdout,Message);
  156. end
  157. else
  158. Writeln(stdout,'Exception object ',Obj.ClassName,' is not of class Exception.');
  159. Writeln(stdout,BackTraceStrFunc(Addr));
  160. if (FrameCount>0) then
  161. begin
  162. for i:=0 to FrameCount-1 do
  163. Writeln(stdout,BackTraceStrFunc(Frames[i]));
  164. end;
  165. Halt(217);
  166. end;
  167. Var OutOfMemory : EOutOfMemory;
  168. InValidPointer : EInvalidPointer;
  169. Procedure RunErrorToExcept (ErrNo : Longint; Address,Frame : Pointer);
  170. Var E : Exception;
  171. S : String;
  172. begin
  173. Case Errno of
  174. 1,203 : E:=OutOfMemory;
  175. 204 : E:=InvalidPointer;
  176. 2,3,4,5,6,100,101,102,103,105,106 : { I/O errors }
  177. begin
  178. Case Errno of
  179. 2 : S:=SFileNotFound;
  180. 3 : S:=SInvalidFileName;
  181. 4 : S:=STooManyOpenFiles;
  182. 5 : S:=SAccessDenied;
  183. 6 : S:=SInvalidFileHandle;
  184. 15 : S:=SInvalidDrive;
  185. 100 : S:=SEndOfFile;
  186. 101 : S:=SDiskFull;
  187. 102 : S:=SFileNotAssigned;
  188. 103 : S:=SFileNotOpen;
  189. 104 : S:=SFileNotOpenForInput;
  190. 105 : S:=SFileNotOpenForOutput;
  191. 106 : S:=SInvalidInput;
  192. end;
  193. E:=EinOutError.Create (S);
  194. EInoutError(E).ErrorCode:=IOresult; // Clears InOutRes !!
  195. end;
  196. // We don't set abstracterrorhandler, but we do it here.
  197. // Unless the use sets another handler we'll get here anyway...
  198. 200 : E:=EDivByZero.Create(SDivByZero);
  199. 201 : E:=ERangeError.Create(SRangeError);
  200. 205 : E:=EOverflow.Create(SOverflow);
  201. 206 : E:=EOverflow.Create(SUnderflow);
  202. 207 : E:=EInvalidOp.Create(SInvalidOp);
  203. 211 : E:=EAbstractError.Create(SAbstractError);
  204. 214 : E:=EBusError.Create(SBusError);
  205. 215 : E:=EIntOverflow.Create(SIntOverflow);
  206. 216 : E:=EAccessViolation.Create(SAccessViolation);
  207. 217 : E:=EPrivilege.Create(SPrivilege);
  208. 218 : E:=EControlC.Create(SControlC);
  209. 219 : E:=EInvalidCast.Create(SInvalidCast);
  210. 220 : E:=EVariantError.Create(SInvalidVarCast);
  211. 221 : E:=EVariantError.Create(SInvalidVarOp);
  212. 222 : E:=EVariantError.Create(SDispatchError);
  213. 223 : E:=EVariantError.Create(SVarArrayCreate);
  214. 224 : E:=EVariantError.Create(SVarNotArray);
  215. 225 : E:=EVariantError.Create(SVarArrayBounds);
  216. 227 : E:=EAssertionFailed.Create(SAssertionFailed);
  217. 228 : E:=EExternalException.Create(SExternalException);
  218. 229 : E:=EIntfCastError.Create(SIntfCastError);
  219. 230 : E:=ESafecallException.Create(SSafecallException);
  220. 232 : E:=ENoThreadSupport.Create(SNoThreadSupport);
  221. else
  222. E:=Exception.CreateFmt (SUnKnownRunTimeError,[Errno]);
  223. end;
  224. Raise E at Address,Frame;
  225. end;
  226. {$IFDEF HAS_OSERROR}
  227. Procedure RaiseLastOSError;
  228. var
  229. ECode: Cardinal;
  230. E : EOSError;
  231. begin
  232. ECode := GetLastOSError;
  233. If (ECode<>0) then
  234. E:=EOSError.CreateFmt(SOSError, [ECode, SysErrorMessage(ECode)])
  235. else
  236. E:=EOSError.Create(SUnkOSError);
  237. E.ErrorCode:=ECode;
  238. Raise E;
  239. end;
  240. {$else}
  241. Procedure RaiseLastOSError;
  242. begin
  243. Raise Exception.Create('RaiseLastOSError not implemented on this platform.');
  244. end;
  245. {$endif}
  246. Procedure AssertErrorHandler (Const Msg,FN : ShortString;LineNo:longint; TheAddr : pointer);
  247. Var
  248. S : String;
  249. begin
  250. If Msg='' then
  251. S:=SAssertionFailed
  252. else
  253. S:=Msg;
  254. Raise EAssertionFailed.Createfmt(SAssertError,[S,Fn,LineNo]); // at Pointer(theAddr);
  255. end;
  256. {$ifdef STACKCHECK_WAS_ON}
  257. {$S+}
  258. {$endif}
  259. Procedure InitExceptions;
  260. {
  261. Must install uncaught exception handler (ExceptProc)
  262. and install exceptions for system exceptions or signals.
  263. (e.g: SIGSEGV -> ESegFault or so.)
  264. }
  265. begin
  266. ExceptProc:=@CatchUnhandledException;
  267. // Create objects that may have problems when there is no memory.
  268. OutOfMemory:=EOutOfMemory.Create(SOutOfMemory);
  269. OutOfMemory.AllowFree:=false;
  270. InvalidPointer:=EInvalidPointer.Create(SInvalidPointer);
  271. InvalidPointer.AllowFree:=false;
  272. AssertErrorProc:=@AssertErrorHandler;
  273. ErrorProc:=@RunErrorToExcept;
  274. OnShowException:=Nil;
  275. end;
  276. Procedure DoneExceptions;
  277. begin
  278. OutOfMemory.AllowFree:=true;
  279. OutOfMemory.Free;
  280. InValidPointer.AllowFree:=true;
  281. InValidPointer.Free;
  282. end;
  283. { Exception handling routines }
  284. function ExceptObject: TObject;
  285. begin
  286. If RaiseList=Nil then
  287. Result:=Nil
  288. else
  289. Result:=RaiseList^.FObject;
  290. end;
  291. function ExceptAddr: Pointer;
  292. begin
  293. If RaiseList=Nil then
  294. Result:=Nil
  295. else
  296. Result:=RaiseList^.Addr;
  297. end;
  298. function ExceptFrameCount: Longint;
  299. begin
  300. If RaiseList=Nil then
  301. Result:=0
  302. else
  303. Result:=RaiseList^.Framecount;
  304. end;
  305. function ExceptFrames: PPointer;
  306. begin
  307. If RaiseList=Nil then
  308. Result:=Nil
  309. else
  310. Result:=RaiseList^.Frames;
  311. end;
  312. function ExceptionErrorMessage(ExceptObject: TObject; ExceptAddr: Pointer;
  313. Buffer: PChar; Size: Integer): Integer;
  314. Var
  315. S : AnsiString;
  316. Len : Integer;
  317. begin
  318. S:=Format(SExceptionErrorMessage,[ExceptAddr,ExceptObject.ClassName]);
  319. If ExceptObject is Exception then
  320. S:=Format('%s:'#10'%s',[S,Exception(ExceptObject).Message]);
  321. Len:=Length(S);
  322. If S[Len]<>'.' then
  323. begin
  324. S:=S+'.';
  325. Inc(len);
  326. end;
  327. If Len>Size then
  328. Len:=Size;
  329. if Len > 0 then
  330. Move(S[1],Buffer^,Len);
  331. Result:=Len;
  332. end;
  333. procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);
  334. // use shortstring. On exception, the heap may be corrupt.
  335. Var
  336. Buf : ShortString;
  337. begin
  338. SetLength(Buf,ExceptionErrorMessage(ExceptObject,ExceptAddr,@Buf[1],255));
  339. If IsConsole Then
  340. writeln(Buf)
  341. else
  342. If Assigned(OnShowException) Then
  343. OnShowException (Buf);
  344. end;
  345. procedure Abort;
  346. begin
  347. Raise EAbort.Create(SAbortError) at Pointer(Get_Caller_addr(Get_Frame));
  348. end;
  349. procedure OutOfMemoryError;
  350. begin
  351. Raise OutOfMemory;
  352. end;
  353. { ---------------------------------------------------------------------
  354. Initialization/Finalization/exit code
  355. ---------------------------------------------------------------------}
  356. Type
  357. PPRecord = ^TPRecord;
  358. TPRecord = Record
  359. Func : TTerminateProc;
  360. NextFunc : PPRecord;
  361. end;
  362. Const
  363. TPList : PPRecord = Nil;
  364. procedure AddTerminateProc(TermProc: TTerminateProc);
  365. Var
  366. TPR : PPRecord;
  367. begin
  368. New(TPR);
  369. With TPR^ do
  370. begin
  371. NextFunc:=TPList;
  372. Func:=TermProc;
  373. end;
  374. TPList:=TPR;
  375. end;
  376. function CallTerminateProcs: Boolean;
  377. Var
  378. TPR : PPRecord;
  379. begin
  380. Result:=True;
  381. TPR:=TPList;
  382. While Result and (TPR<>Nil) do
  383. begin
  384. Result:=TPR^.Func();
  385. TPR:=TPR^.NextFunc;
  386. end;
  387. end;
  388. { ---------------------------------------------------------------------
  389. Diskh functions, OS independent.
  390. ---------------------------------------------------------------------}
  391. function ForceDirectories(Const Dir: string): Boolean;
  392. var
  393. E: EInOutError;
  394. ADir : String;
  395. begin
  396. Result:=True;
  397. ADir:=ExcludeTrailingPathDelimiter(Dir);
  398. if (ADir='') then
  399. begin
  400. E:=EInOutError.Create(SCannotCreateEmptyDir);
  401. E.ErrorCode:=3;
  402. Raise E;
  403. end;
  404. if Not DirectoryExists(ADir) then
  405. begin
  406. Result:=ForceDirectories(ExtractFilePath(ADir));
  407. If Result then
  408. CreateDir(ADir);
  409. end;
  410. end;
  411. Procedure GetRandomBytes(Var Buf; NBytes : Integer);
  412. Var
  413. I : Integer;
  414. P : PByte;
  415. begin
  416. P:=@Buf;
  417. Randomize;
  418. For I:=0 to NBytes-1 do
  419. P[i]:=Random(256);
  420. end;
  421. {$IFDEF HASCREATEGUID}
  422. Function SysCreateGUID(out GUID : TGUID) : Integer; forward;
  423. {$ENDIF}
  424. Function CreateGUID(out GUID : TGUID) : Integer;
  425. begin
  426. If Assigned(OnCreateGUID) then
  427. Result:=OnCreateGUID(GUID)
  428. else
  429. begin
  430. {$IFDEF HASCREATEGUID}
  431. Result:=SysCreateGUID(GUID);
  432. {$ELSE}
  433. GetRandomBytes(GUID,SizeOf(Guid));
  434. Result:=0;
  435. {$ENDIF}
  436. end;
  437. end;