except.inc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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. PExceptObject = ^TExceptObject;
  29. TExceptObject = record
  30. FObject : TObject;
  31. Addr,
  32. Frame : pointer;
  33. Next : PExceptObject;
  34. end;
  35. TExceptObjectClass = Class of TObject;
  36. Const
  37. CatchAllExceptions = -1;
  38. Var
  39. ExceptAddrStack : PExceptAddr;
  40. ExceptObjectStack : PExceptObject;
  41. Function PushExceptAddr (Ft: Longint): PJmp_buf ;[Public, Alias : 'FPC_PUSHEXCEPTADDR'];
  42. var
  43. Buf : PJmp_buf;
  44. NewAddr : PExceptAddr;
  45. begin
  46. {$ifdef excdebug}
  47. writeln ('In PushExceptAddr');
  48. {$endif}
  49. If ExceptAddrstack=Nil then
  50. begin
  51. New(ExceptAddrStack);
  52. ExceptAddrStack^.Next:=Nil;
  53. end
  54. else
  55. begin
  56. New(NewAddr);
  57. NewAddr^.Next:=ExceptAddrStack;
  58. ExceptAddrStack:=NewAddr;
  59. end;
  60. new(buf);
  61. ExceptAddrStack^.Buf:=Buf;
  62. ExceptAddrStack^.FrameType:=ft;
  63. PushExceptAddr:=Buf;
  64. end;
  65. Procedure PushExceptObj (Obj : TObject; AnAddr,AFrame : Pointer); [Public, Alias : 'FPC_PUSHEXCEPTOBJECT'];
  66. var
  67. Newobj : PExceptObject;
  68. begin
  69. {$ifdef excdebug}
  70. writeln ('In PushExceptObject');
  71. {$endif}
  72. If ExceptObjectStack=Nil then
  73. begin
  74. New(ExceptObjectStack);
  75. ExceptObjectStack^.Next:=Nil;
  76. end
  77. else
  78. begin
  79. New(NewObj);
  80. NewObj^.Next:=ExceptObjectStack;
  81. ExceptObjectStack:=NewObj;
  82. end;
  83. ExceptObjectStack^.FObject:=Obj;
  84. ExceptObjectStack^.Addr:=AnAddr;
  85. ExceptObjectStack^.Frame:=AFrame;
  86. end;
  87. Procedure DoUnHandledException;
  88. begin
  89. If ExceptProc<>Nil then
  90. If ExceptObjectStack<>Nil then
  91. TExceptPRoc(ExceptProc)(ExceptObjectStack^.FObject,ExceptObjectStack^.Addr,ExceptObjectStack^.Frame);
  92. RunError(217);
  93. end;
  94. Function Raiseexcept (Obj : TObject; AnAddr,AFrame : Pointer) : TObject;[Public, Alias : 'FPC_RAISEEXCEPTION'];
  95. begin
  96. {$ifdef excdebug}
  97. writeln ('In RaiseException');
  98. {$endif}
  99. Raiseexcept:=nil;
  100. PushExceptObj(Obj,AnAddr,AFrame);
  101. If ExceptAddrStack=Nil then
  102. DoUnhandledException;
  103. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  104. end;
  105. Procedure PopAddrStack;[Public, Alias : 'FPC_POPADDRSTACK'];
  106. var
  107. hp : PExceptAddr;
  108. begin
  109. {$ifdef excdebug}
  110. writeln ('In Popaddrstack');
  111. {$endif}
  112. If ExceptAddrStack=nil then
  113. begin
  114. writeln ('At end of ExceptionAddresStack');
  115. halt (255);
  116. end
  117. else
  118. begin
  119. hp:=ExceptAddrStack;
  120. ExceptAddrStack:=ExceptAddrStack^.Next;
  121. dispose(hp^.buf);
  122. dispose(hp);
  123. end;
  124. end;
  125. function PopObjectStack : TObject;[Public, Alias : 'FPC_POPOBJECTSTACK'];
  126. var
  127. hp : PExceptObject;
  128. begin
  129. {$ifdef excdebug}
  130. writeln ('In PopObjectstack');
  131. {$endif}
  132. If ExceptObjectStack=nil then
  133. begin
  134. writeln ('At end of ExceptionObjectStack');
  135. halt (1);
  136. end
  137. else
  138. begin
  139. { we need to return the exception object to dispose it }
  140. PopObjectStack:=ExceptObjectStack^.FObject;
  141. hp:=ExceptObjectStack;
  142. ExceptObjectStack:=ExceptObjectStack^.next;
  143. dispose(hp);
  144. end;
  145. end;
  146. { this is for popping exception objects when a second exception is risen }
  147. { in an except/on }
  148. function PopSecondObjectStack : TObject;[Public, Alias : 'FPC_POPSECONDOBJECTSTACK'];
  149. var
  150. hp : PExceptObject;
  151. begin
  152. {$ifdef excdebug}
  153. writeln ('In PopObjectstack');
  154. {$endif}
  155. If not(assigned(ExceptObjectStack)) or
  156. not(assigned(ExceptObjectStack^.next)) then
  157. begin
  158. writeln ('At end of ExceptionObjectStack');
  159. halt (1);
  160. end
  161. else
  162. begin
  163. { we need to return the exception object to dispose it }
  164. PopSecondObjectStack:=ExceptObjectStack^.next^.FObject;
  165. hp:=ExceptObjectStack^.next;
  166. ExceptObjectStack^.next:=hp^.next;
  167. dispose(hp);
  168. end;
  169. end;
  170. Procedure ReRaise;[Public, Alias : 'FPC_RERAISE'];
  171. begin
  172. {$ifdef excdebug}
  173. writeln ('In reraise');
  174. {$endif}
  175. If ExceptAddrStack=Nil then
  176. DoUnHandledException;
  177. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  178. end;
  179. Function Catches(Objtype : TExceptObjectClass) : TObject;[Public, Alias : 'FPC_CATCHES'];
  180. begin
  181. If ExceptObjectStack=Nil then
  182. begin
  183. Writeln ('Internal error.');
  184. halt (255);
  185. end;
  186. if Not ((Objtype = TExceptObjectClass(CatchAllExceptions)) or
  187. (ExceptObjectStack^.FObject is ObjType)) then
  188. Catches:=Nil
  189. else
  190. begin
  191. // catch !
  192. Catches:=ExceptObjectStack^.FObject;
  193. { this can't be done, because there could be a reraise (PFV)
  194. PopObjectStack;
  195. Also the PopAddrStack shouldn't be done, we do it now
  196. immediatly in the exception handler (FK)
  197. PopAddrStack; }
  198. end;
  199. end;
  200. Procedure DestroyException(o : TObject);[Public, Alias : 'FPC_DESTROYEXCEPTION'];
  201. begin
  202. { with free we're on the really save side }
  203. o.Free;
  204. end;
  205. Procedure InitExceptions;
  206. {
  207. Initialize exceptionsupport
  208. }
  209. begin
  210. ExceptObjectstack:=Nil;
  211. ExceptAddrStack:=Nil;
  212. end;
  213. {
  214. $Log$
  215. Revision 1.18 2000-04-24 11:11:50 peter
  216. * backtraces for exceptions are now only generated from the place of the
  217. exception
  218. * frame is also pushed for exceptions
  219. * raise statement enhanced with [,<frame>]
  220. Revision 1.17 2000/02/09 22:16:50 florian
  221. + popsecondobjectstack added
  222. Revision 1.16 2000/02/09 16:59:29 peter
  223. * truncated log
  224. Revision 1.15 2000/02/06 17:17:57 florian
  225. * popobjectstack is now a function
  226. Revision 1.14 2000/01/07 16:41:33 daniel
  227. * copyright 2000
  228. Revision 1.13 1999/07/27 08:14:15 florian
  229. * catch doesn't call popaddrstack anymore, this is done now by the compiler
  230. Revision 1.12 1999/07/26 12:11:28 florian
  231. * reraise doesn't call popaddrstack anymode
  232. }