except.inc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Michael Van Canneyt
  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. {****************************************************************************
  13. Exception support
  14. ****************************************************************************}
  15. Const
  16. { Type of exception. Currently only one. }
  17. FPC_EXCEPTION = 1;
  18. { types of frames for the exception address stack }
  19. cExceptionFrame = 1;
  20. cFinalizeFrame = 2;
  21. Type
  22. PExceptAddr = ^TExceptAddr;
  23. TExceptAddr = record
  24. buf : pjmp_buf;
  25. frametype : Longint;
  26. next : PExceptAddr;
  27. end;
  28. TExceptObjectClass = Class of TObject;
  29. Const
  30. CatchAllExceptions = -1;
  31. Var
  32. ExceptAddrStack : PExceptAddr;
  33. ExceptObjectStack : PExceptObject;
  34. Function RaiseList : PExceptObject;
  35. begin
  36. RaiseList:=ExceptObjectStack;
  37. end;
  38. Function PushExceptAddr (Ft: Longint): PJmp_buf ;
  39. [Public, Alias : 'FPC_PUSHEXCEPTADDR'];saveregisters;
  40. var
  41. Buf : PJmp_buf;
  42. NewAddr : PExceptAddr;
  43. begin
  44. {$ifdef excdebug}
  45. writeln ('In PushExceptAddr');
  46. {$endif}
  47. If ExceptAddrstack=Nil then
  48. begin
  49. New(ExceptAddrStack);
  50. ExceptAddrStack^.Next:=Nil;
  51. end
  52. else
  53. begin
  54. New(NewAddr);
  55. NewAddr^.Next:=ExceptAddrStack;
  56. ExceptAddrStack:=NewAddr;
  57. end;
  58. new(buf);
  59. ExceptAddrStack^.Buf:=Buf;
  60. ExceptAddrStack^.FrameType:=ft;
  61. PushExceptAddr:=Buf;
  62. end;
  63. Procedure PushExceptObj (Obj : TObject; AnAddr,AFrame : Pointer);
  64. [Public, Alias : 'FPC_PUSHEXCEPTOBJECT'];saveregisters;
  65. var
  66. Newobj : PExceptObject;
  67. begin
  68. {$ifdef excdebug}
  69. writeln ('In PushExceptObject');
  70. {$endif}
  71. If ExceptObjectStack=Nil then
  72. begin
  73. New(ExceptObjectStack);
  74. ExceptObjectStack^.Next:=Nil;
  75. end
  76. else
  77. begin
  78. New(NewObj);
  79. NewObj^.Next:=ExceptObjectStack;
  80. ExceptObjectStack:=NewObj;
  81. end;
  82. ExceptObjectStack^.FObject:=Obj;
  83. ExceptObjectStack^.Addr:=AnAddr;
  84. ExceptObjectStack^.Frame:=AFrame;
  85. end;
  86. Procedure DoUnHandledException;
  87. begin
  88. If ExceptProc<>Nil then
  89. If ExceptObjectStack<>Nil then
  90. TExceptPRoc(ExceptProc)(ExceptObjectStack^.FObject,ExceptObjectStack^.Addr,ExceptObjectStack^.Frame);
  91. RunError(217);
  92. end;
  93. Function Raiseexcept (Obj : TObject; AnAddr,AFrame : Pointer) : TObject;[Public, Alias : 'FPC_RAISEEXCEPTION'];
  94. begin
  95. {$ifdef excdebug}
  96. writeln ('In RaiseException');
  97. {$endif}
  98. Raiseexcept:=nil;
  99. PushExceptObj(Obj,AnAddr,AFrame);
  100. If ExceptAddrStack=Nil then
  101. DoUnhandledException;
  102. if (RaiseProc <> nil) and (ExceptObjectStack <> nil) then
  103. RaiseProc(Obj, AnAddr, AFrame);
  104. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  105. end;
  106. Procedure PopAddrStack;[Public, Alias : 'FPC_POPADDRSTACK'];
  107. var
  108. hp : PExceptAddr;
  109. begin
  110. {$ifdef excdebug}
  111. writeln ('In Popaddrstack');
  112. {$endif}
  113. If ExceptAddrStack=nil then
  114. begin
  115. writeln ('At end of ExceptionAddresStack');
  116. halt (255);
  117. end
  118. else
  119. begin
  120. hp:=ExceptAddrStack;
  121. ExceptAddrStack:=ExceptAddrStack^.Next;
  122. dispose(hp^.buf);
  123. dispose(hp);
  124. end;
  125. end;
  126. function PopObjectStack : TObject;[Public, Alias : 'FPC_POPOBJECTSTACK'];
  127. var
  128. hp : PExceptObject;
  129. begin
  130. {$ifdef excdebug}
  131. writeln ('In PopObjectstack');
  132. {$endif}
  133. If ExceptObjectStack=nil then
  134. begin
  135. writeln ('At end of ExceptionObjectStack');
  136. halt (1);
  137. end
  138. else
  139. begin
  140. { we need to return the exception object to dispose it }
  141. PopObjectStack:=ExceptObjectStack^.FObject;
  142. hp:=ExceptObjectStack;
  143. ExceptObjectStack:=ExceptObjectStack^.next;
  144. dispose(hp);
  145. end;
  146. end;
  147. { this is for popping exception objects when a second exception is risen }
  148. { in an except/on }
  149. function PopSecondObjectStack : TObject;[Public, Alias : 'FPC_POPSECONDOBJECTSTACK'];
  150. var
  151. hp : PExceptObject;
  152. begin
  153. {$ifdef excdebug}
  154. writeln ('In PopObjectstack');
  155. {$endif}
  156. If not(assigned(ExceptObjectStack)) or
  157. not(assigned(ExceptObjectStack^.next)) then
  158. begin
  159. writeln ('At end of ExceptionObjectStack');
  160. halt (1);
  161. end
  162. else
  163. begin
  164. { we need to return the exception object to dispose it }
  165. PopSecondObjectStack:=ExceptObjectStack^.next^.FObject;
  166. hp:=ExceptObjectStack^.next;
  167. ExceptObjectStack^.next:=hp^.next;
  168. dispose(hp);
  169. end;
  170. end;
  171. Procedure ReRaise;[Public, Alias : 'FPC_RERAISE'];
  172. begin
  173. {$ifdef excdebug}
  174. writeln ('In reraise');
  175. {$endif}
  176. If ExceptAddrStack=Nil then
  177. DoUnHandledException;
  178. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  179. end;
  180. Function Catches(Objtype : TExceptObjectClass) : TObject;[Public, Alias : 'FPC_CATCHES'];
  181. begin
  182. If ExceptObjectStack=Nil then
  183. begin
  184. Writeln ('Internal error.');
  185. halt (255);
  186. end;
  187. if Not ((Objtype = TExceptObjectClass(CatchAllExceptions)) or
  188. (ExceptObjectStack^.FObject is ObjType)) then
  189. Catches:=Nil
  190. else
  191. begin
  192. // catch !
  193. Catches:=ExceptObjectStack^.FObject;
  194. { this can't be done, because there could be a reraise (PFV)
  195. PopObjectStack;
  196. Also the PopAddrStack shouldn't be done, we do it now
  197. immediatly in the exception handler (FK)
  198. PopAddrStack; }
  199. end;
  200. end;
  201. Procedure DestroyException(o : TObject);[Public, Alias : 'FPC_DESTROYEXCEPTION'];
  202. begin
  203. { with free we're on the really save side }
  204. o.Free;
  205. end;
  206. Procedure InitExceptions;
  207. {
  208. Initialize exceptionsupport
  209. }
  210. begin
  211. ExceptObjectstack:=Nil;
  212. ExceptAddrStack:=Nil;
  213. end;
  214. {
  215. $Log$
  216. Revision 1.3 2000-09-30 07:38:07 sg
  217. * Added 'RaiseProc': A user-definable callback procedure which gets
  218. called whenever an exception is being raised
  219. Revision 1.2 2000/07/13 11:33:42 michael
  220. + removed logs
  221. }