sysutils.inc 13 KB

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