except.inc 6.6 KB

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