sysutils.inc 12 KB

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