sysutils.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  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. { Read String Handling functions implementation }
  48. {$i sysstr.inc}
  49. { Read date & Time function implementations }
  50. {$i dati.inc}
  51. { Read pchar handling functions implementation }
  52. {$i syspch.inc}
  53. { generic internationalisation code }
  54. {$i sysint.inc}
  55. { MCBS functions }
  56. {$i sysansi.inc}
  57. { wide string functions }
  58. {$i syswide.inc}
  59. { CPU Specific code }
  60. {$i sysutilp.inc}
  61. { OS utility code }
  62. {$i osutil.inc}
  63. procedure FreeAndNil(var obj);
  64. var
  65. temp: tobject;
  66. begin
  67. temp:=tobject(obj);
  68. pointer(obj):=nil;
  69. temp.free;
  70. end;
  71. { Interfaces support }
  72. {$i sysuintf.inc}
  73. constructor Exception.Create(const msg : string);
  74. begin
  75. inherited create;
  76. fmessage:=msg;
  77. end;
  78. constructor Exception.CreateFmt(const msg : string; const args : array of const);
  79. begin
  80. inherited create;
  81. fmessage:=Format(msg,args);
  82. end;
  83. constructor Exception.CreateRes(ResString: PString);
  84. begin
  85. inherited create;
  86. fmessage:=ResString^;
  87. end;
  88. constructor Exception.CreateResFmt(ResString: PString; const Args: array of const);
  89. begin
  90. inherited create;
  91. fmessage:=Format(ResString^,args);
  92. end;
  93. constructor Exception.CreateHelp(const Msg: string; AHelpContext: Integer);
  94. begin
  95. inherited create;
  96. fmessage:=Msg;
  97. fhelpcontext:=AHelpContext;
  98. end;
  99. constructor Exception.CreateFmtHelp(const Msg: string; const Args: array of const;
  100. AHelpContext: Integer);
  101. begin
  102. inherited create;
  103. fmessage:=Format(Msg,args);
  104. fhelpcontext:=AHelpContext;
  105. end;
  106. constructor Exception.CreateResHelp(ResString: PString; AHelpContext: Integer);
  107. begin
  108. inherited create;
  109. fmessage:=ResString^;
  110. fhelpcontext:=AHelpContext;
  111. end;
  112. constructor Exception.CreateResFmtHelp(ResString: PString; const Args: array of const;
  113. AHelpContext: Integer);
  114. begin
  115. inherited create;
  116. fmessage:=Format(ResString^,args);
  117. fhelpcontext:=AHelpContext;
  118. end;
  119. procedure EHeapMemoryError.FreeInstance;
  120. begin
  121. if AllowFree then
  122. inherited FreeInstance;
  123. end;
  124. {$ifopt S+}
  125. {$define STACKCHECK_WAS_ON}
  126. {$S-}
  127. {$endif OPT S }
  128. Procedure CatchUnhandledException (Obj : TObject; Addr: Pointer; FrameCount: Longint; Frames: PPointer);[public,alias:'FPC_BREAK_UNHANDLED_EXCEPTION'];
  129. Var
  130. Message : String;
  131. i : longint;
  132. begin
  133. Writeln(stdout,'An unhandled exception occurred at $',HexStr(Ptrint(Addr),sizeof(PtrInt)*2),' :');
  134. if Obj is exception then
  135. begin
  136. Message:=Exception(Obj).ClassName+' : '+Exception(Obj).Message;
  137. Writeln(stdout,Message);
  138. end
  139. else
  140. Writeln(stdout,'Exception object ',Obj.ClassName,' is not of class Exception.');
  141. if (FrameCount>0) then
  142. begin
  143. Writeln(stdout,BackTraceStrFunc(Addr));
  144. for i:=0 to FrameCount-1 do
  145. Writeln(stdout,BackTraceStrFunc(Frames[i]));
  146. end;
  147. Halt(217);
  148. end;
  149. Var OutOfMemory : EOutOfMemory;
  150. InValidPointer : EInvalidPointer;
  151. Procedure RunErrorToExcept (ErrNo : Longint; Address,Frame : Pointer);
  152. Var E : Exception;
  153. S : String;
  154. begin
  155. Case Errno of
  156. 1,203 : E:=OutOfMemory;
  157. 204 : E:=InvalidPointer;
  158. 2,3,4,5,6,100,101,102,103,105,106 : { I/O errors }
  159. begin
  160. Case Errno of
  161. 2 : S:=SFileNotFound;
  162. 3 : S:=SInvalidFileName;
  163. 4 : S:=STooManyOpenFiles;
  164. 5 : S:=SAccessDenied;
  165. 6 : S:=SInvalidFileHandle;
  166. 15 : S:=SInvalidDrive;
  167. 100 : S:=SEndOfFile;
  168. 101 : S:=SDiskFull;
  169. 102 : S:=SFileNotAssigned;
  170. 103 : S:=SFileNotOpen;
  171. 104 : S:=SFileNotOpenForInput;
  172. 105 : S:=SFileNotOpenForOutput;
  173. 106 : S:=SInvalidInput;
  174. end;
  175. E:=EinOutError.Create (S);
  176. EInoutError(E).ErrorCode:=IOresult; // Clears InOutRes !!
  177. end;
  178. // We don't set abstracterrorhandler, but we do it here.
  179. // Unless the use sets another handler we'll get here anyway...
  180. 200 : E:=EDivByZero.Create(SDivByZero);
  181. 201 : E:=ERangeError.Create(SRangeError);
  182. 205 : E:=EOverflow.Create(SOverflow);
  183. 206 : E:=EOverflow.Create(SUnderflow);
  184. 207 : E:=EInvalidOp.Create(SInvalidOp);
  185. 211 : E:=EAbstractError.Create(SAbstractError);
  186. 215 : E:=EIntOverflow.Create(SIntOverflow);
  187. 216 : E:=EAccessViolation.Create(SAccessViolation);
  188. 217 : E:=EPrivilege.Create(SPrivilege);
  189. 218 : E:=EControlC.Create(SControlC);
  190. 219 : E:=EInvalidCast.Create(SInvalidCast);
  191. 220 : E:=EVariantError.Create(SInvalidVarCast);
  192. 221 : E:=EVariantError.Create(SInvalidVarOp);
  193. 222 : E:=EVariantError.Create(SDispatchError);
  194. 223 : E:=EVariantError.Create(SVarArrayCreate);
  195. 224 : E:=EVariantError.Create(SVarNotArray);
  196. 225 : E:=EVariantError.Create(SVarArrayBounds);
  197. 227 : E:=EAssertionFailed.Create(SAssertionFailed);
  198. 228 : E:=EExternalException.Create(SExternalException);
  199. 229 : E:=EIntfCastError.Create(SIntfCastError);
  200. 230 : E:=ESafecallException.Create(SSafecallException);
  201. 232 : E:=ENoThreadSupport.Create(SNoThreadSupport);
  202. else
  203. E:=Exception.CreateFmt (SUnKnownRunTimeError,[Errno]);
  204. end;
  205. Raise E at Address,Frame;
  206. end;
  207. {$IFDEF HAS_OSERROR}
  208. Procedure RaiseLastOSError;
  209. var
  210. ECode: Cardinal;
  211. E : EOSError;
  212. begin
  213. ECode := GetLastOSError;
  214. If (ECode<>0) then
  215. E:=EOSError.CreateFmt(SOSError, [ECode, SysErrorMessage(ECode)])
  216. else
  217. E:=EOSError.Create(SUnkOSError);
  218. E.ErrorCode:=ECode;
  219. Raise E;
  220. end;
  221. {$else}
  222. Procedure RaiseLastOSError;
  223. begin
  224. Raise Exception.Create('RaiseLastOSError not implemented on this platform.');
  225. end;
  226. {$endif}
  227. Procedure AssertErrorHandler (Const Msg,FN : ShortString;LineNo:longint; TheAddr : pointer);
  228. Var
  229. S : String;
  230. begin
  231. If Msg='' then
  232. S:=SAssertionFailed
  233. else
  234. S:=Msg;
  235. Raise EAssertionFailed.Createfmt(SAssertError,[S,Fn,LineNo]); // at Pointer(theAddr);
  236. end;
  237. {$ifdef STACKCHECK_WAS_ON}
  238. {$S+}
  239. {$endif}
  240. Procedure InitExceptions;
  241. {
  242. Must install uncaught exception handler (ExceptProc)
  243. and install exceptions for system exceptions or signals.
  244. (e.g: SIGSEGV -> ESegFault or so.)
  245. }
  246. begin
  247. ExceptProc:=@CatchUnhandledException;
  248. // Create objects that may have problems when there is no memory.
  249. OutOfMemory:=EOutOfMemory.Create(SOutOfMemory);
  250. OutOfMemory.AllowFree:=false;
  251. InvalidPointer:=EInvalidPointer.Create(SInvalidPointer);
  252. InvalidPointer.AllowFree:=false;
  253. AssertErrorProc:=@AssertErrorHandler;
  254. ErrorProc:=@RunErrorToExcept;
  255. OnShowException:=Nil;
  256. end;
  257. Procedure DoneExceptions;
  258. begin
  259. OutOfMemory.AllowFree:=true;
  260. OutOfMemory.Free;
  261. InValidPointer.AllowFree:=true;
  262. InValidPointer.Free;
  263. end;
  264. { Exception handling routines }
  265. function ExceptObject: TObject;
  266. begin
  267. If RaiseList=Nil then
  268. Result:=Nil
  269. else
  270. Result:=RaiseList^.FObject;
  271. end;
  272. function ExceptAddr: Pointer;
  273. begin
  274. If RaiseList=Nil then
  275. Result:=Nil
  276. else
  277. Result:=RaiseList^.Addr;
  278. end;
  279. function ExceptionErrorMessage(ExceptObject: TObject; ExceptAddr: Pointer;
  280. Buffer: PChar; Size: Integer): Integer;
  281. Var
  282. S : AnsiString;
  283. Len : Integer;
  284. begin
  285. S:=Format(SExceptionErrorMessage,[ExceptAddr,ExceptObject.ClassName]);
  286. If ExceptObject is Exception then
  287. S:=Format('%s:'#10'%s',[S,Exception(ExceptObject).Message]);
  288. Len:=Length(S);
  289. If S[Len]<>'.' then
  290. begin
  291. S:=S+'.';
  292. Inc(len);
  293. end;
  294. If Len>Size then
  295. Len:=Size;
  296. if Len > 0 then
  297. Move(S[1],Buffer^,Len);
  298. Result:=Len;
  299. end;
  300. procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);
  301. // use shortstring. On exception, the heap may be corrupt.
  302. Var
  303. Buf : ShortString;
  304. begin
  305. SetLength(Buf,ExceptionErrorMessage(ExceptObject,ExceptAddr,@Buf[1],255));
  306. If IsConsole Then
  307. writeln(Buf)
  308. else
  309. If Assigned(OnShowException) Then
  310. OnShowException (Buf);
  311. end;
  312. procedure Abort;
  313. begin
  314. Raise EAbort.Create(SAbortError) at Pointer(Get_Caller_addr(Get_Frame));
  315. end;
  316. procedure OutOfMemoryError;
  317. begin
  318. Raise OutOfMemory;
  319. end;
  320. { ---------------------------------------------------------------------
  321. Initialization/Finalization/exit code
  322. ---------------------------------------------------------------------}
  323. Type
  324. PPRecord = ^TPRecord;
  325. TPRecord = Record
  326. Func : TTerminateProc;
  327. NextFunc : PPRecord;
  328. end;
  329. Const
  330. TPList : PPRecord = Nil;
  331. procedure AddTerminateProc(TermProc: TTerminateProc);
  332. Var
  333. TPR : PPRecord;
  334. begin
  335. New(TPR);
  336. With TPR^ do
  337. begin
  338. NextFunc:=TPList;
  339. Func:=TermProc;
  340. end;
  341. TPList:=TPR;
  342. end;
  343. function CallTerminateProcs: Boolean;
  344. Var
  345. TPR : PPRecord;
  346. begin
  347. Result:=True;
  348. TPR:=TPList;
  349. While Result and (TPR<>Nil) do
  350. begin
  351. Result:=TPR^.Func();
  352. TPR:=TPR^.NextFunc;
  353. end;
  354. end;
  355. { ---------------------------------------------------------------------
  356. Diskh functions, OS independent.
  357. ---------------------------------------------------------------------}
  358. function ForceDirectories(Const Dir: string): Boolean;
  359. var
  360. E: EInOutError;
  361. ADir : String;
  362. begin
  363. Result:=True;
  364. ADir:=ExcludeTrailingPathDelimiter(Dir);
  365. if (ADir='') then
  366. begin
  367. E:=EInOutError.Create(SCannotCreateEmptyDir);
  368. E.ErrorCode:=3;
  369. Raise E;
  370. end;
  371. if Not DirectoryExists(ADir) then
  372. begin
  373. Result:=ForceDirectories(ExtractFilePath(ADir));
  374. If Result then
  375. CreateDir(ADir);
  376. end;
  377. end;
  378. Procedure GetRandomBytes(Var Buf; NBytes : Integer);
  379. Var
  380. I : Integer;
  381. P : PByte;
  382. begin
  383. P:=@Buf;
  384. Randomize;
  385. For I:=0 to NBytes-1 do
  386. P[i]:=Random(256);
  387. end;
  388. {$IFDEF HASCREATEGUID}
  389. Function SysCreateGUID(out GUID : TGUID) : Integer; forward;
  390. {$ENDIF}
  391. Function CreateGUID(out GUID : TGUID) : Integer;
  392. begin
  393. If Assigned(OnCreateGUID) then
  394. Result:=OnCreateGUID(GUID)
  395. else
  396. begin
  397. {$IFDEF HASCREATEGUID}
  398. Result:=SysCreateGUID(GUID);
  399. {$ELSE}
  400. GetRandomBytes(GUID,SizeOf(Guid));
  401. Result:=0;
  402. {$ENDIF}
  403. end;
  404. end;
  405. {
  406. Revision 1.1 2003/10/06 21:01:06 peter
  407. * moved classes unit to rtl
  408. Revision 1.17 2003/09/06 20:46:07 marco
  409. * 3 small VP fixes from Noah Silva. One (OutOfMemory error) failed.
  410. Revision 1.16 2003/04/06 11:06:39 michael
  411. + Added exception classname to output of unhandled exception for better identification
  412. Revision 1.15 2003/03/18 08:28:23 michael
  413. Patch from peter for Abort routine
  414. Revision 1.14 2003/03/17 15:11:51 armin
  415. + someone AssertErrorHandler, BackTraceFunc and Dump_Stack so that pointer instead of longint is needed
  416. Revision 1.13 2003/01/01 20:58:07 florian
  417. + added invalid instruction exception
  418. Revision 1.12 2002/10/07 19:43:24 florian
  419. + empty prototypes for the AnsiStr* multi byte functions added
  420. Revision 1.11 2002/09/07 16:01:22 peter
  421. * old logs removed and tabs fixed
  422. Revision 1.10 2002/07/16 13:57:39 florian
  423. * raise takes now a void pointer as at and frame address
  424. instead of a longint, fixed
  425. Revision 1.9 2002/01/25 17:42:03 peter
  426. * interface helpers
  427. Revision 1.8 2002/01/25 16:23:03 peter
  428. * merged filesearch() fix
  429. }