except.inc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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. {$ifndef HAS_ADDR_STACK_ON_STACK}
  39. Function PushExceptAddr (Ft: Longint): PJmp_buf ;
  40. [Public, Alias : 'FPC_PUSHEXCEPTADDR'];saveregisters;
  41. {$else ADDR_STACK_ON_HEAP}
  42. Function PushExceptAddr (Ft: Longint;_buf,_newaddr : pointer): PJmp_buf ;
  43. [Public, Alias : 'FPC_PUSHEXCEPTADDR'];saveregisters;
  44. {$endif HAS_ADDR_STACK_ON_STACK}
  45. var
  46. Buf : PJmp_buf;
  47. NewAddr : PExceptAddr;
  48. begin
  49. {$ifdef excdebug}
  50. writeln ('In PushExceptAddr');
  51. {$endif}
  52. If ExceptAddrstack=Nil then
  53. begin
  54. {$ifndef HAS_ADDR_STACK_ON_STACK}
  55. New(ExceptAddrStack);
  56. {$else HAS_ADDR_STACK_ON_STACK}
  57. ExceptAddrStack:=PExceptAddr(_newaddr);
  58. {$endif HAS_ADDR_STACK_ON_STACK}
  59. ExceptAddrStack^.Next:=Nil;
  60. end
  61. else
  62. begin
  63. {$ifndef HAS_ADDR_STACK_ON_STACK}
  64. New(NewAddr);
  65. {$else HAS_ADDR_STACK_ON_STACK}
  66. NewAddr:=PExceptAddr(_newaddr);
  67. {$endif HAS_ADDR_STACK_ON_STACK}
  68. NewAddr^.Next:=ExceptAddrStack;
  69. ExceptAddrStack:=NewAddr;
  70. end;
  71. {$ifndef HAS_ADDR_STACK_ON_STACK}
  72. new(buf);
  73. {$else HAS_ADDR_STACK_ON_STACK}
  74. buf:=PJmp_Buf(_buf);
  75. {$endif HAS_ADDR_STACK_ON_STACK}
  76. ExceptAddrStack^.Buf:=Buf;
  77. ExceptAddrStack^.FrameType:=ft;
  78. PushExceptAddr:=Buf;
  79. end;
  80. Procedure PushExceptObj (Obj : TObject; AnAddr,AFrame : Pointer);
  81. [Public, Alias : 'FPC_PUSHEXCEPTOBJECT'];saveregisters;
  82. var
  83. Newobj : PExceptObject;
  84. begin
  85. {$ifdef excdebug}
  86. writeln ('In PushExceptObject');
  87. {$endif}
  88. If ExceptObjectStack=Nil then
  89. begin
  90. New(ExceptObjectStack);
  91. ExceptObjectStack^.Next:=Nil;
  92. end
  93. else
  94. begin
  95. New(NewObj);
  96. NewObj^.Next:=ExceptObjectStack;
  97. ExceptObjectStack:=NewObj;
  98. end;
  99. ExceptObjectStack^.FObject:=Obj;
  100. ExceptObjectStack^.Addr:=AnAddr;
  101. ExceptObjectStack^.Frame:=AFrame;
  102. end;
  103. Procedure DoUnHandledException;
  104. begin
  105. If ExceptProc<>Nil then
  106. If ExceptObjectStack<>Nil then
  107. TExceptPRoc(ExceptProc)(ExceptObjectStack^.FObject,ExceptObjectStack^.Addr,ExceptObjectStack^.Frame);
  108. RunError(217);
  109. end;
  110. Function Raiseexcept (Obj : TObject; AnAddr,AFrame : Pointer) : TObject;[Public, Alias : 'FPC_RAISEEXCEPTION'];
  111. begin
  112. {$ifdef excdebug}
  113. writeln ('In RaiseException');
  114. {$endif}
  115. Raiseexcept:=nil;
  116. PushExceptObj(Obj,AnAddr,AFrame);
  117. If ExceptAddrStack=Nil then
  118. DoUnhandledException;
  119. if (RaiseProc <> nil) and (ExceptObjectStack <> nil) then
  120. RaiseProc(Obj, AnAddr, AFrame);
  121. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  122. end;
  123. Procedure PopAddrStack;[Public, Alias : 'FPC_POPADDRSTACK'];
  124. var
  125. hp : PExceptAddr;
  126. begin
  127. {$ifdef excdebug}
  128. writeln ('In Popaddrstack');
  129. {$endif}
  130. If ExceptAddrStack=nil then
  131. begin
  132. writeln ('At end of ExceptionAddresStack');
  133. halt (255);
  134. end
  135. else
  136. begin
  137. hp:=ExceptAddrStack;
  138. ExceptAddrStack:=ExceptAddrStack^.Next;
  139. {$ifndef HAS_ADDR_STACK_ON_STACK}
  140. dispose(hp^.buf);
  141. dispose(hp);
  142. {$endif HAS_ADDR_STACK_ON_STACK}
  143. end;
  144. end;
  145. function PopObjectStack : TObject;[Public, Alias : 'FPC_POPOBJECTSTACK'];
  146. var
  147. hp : PExceptObject;
  148. begin
  149. {$ifdef excdebug}
  150. writeln ('In PopObjectstack');
  151. {$endif}
  152. If ExceptObjectStack=nil then
  153. begin
  154. writeln ('At end of ExceptionObjectStack');
  155. halt (1);
  156. end
  157. else
  158. begin
  159. { we need to return the exception object to dispose it }
  160. PopObjectStack:=ExceptObjectStack^.FObject;
  161. hp:=ExceptObjectStack;
  162. ExceptObjectStack:=ExceptObjectStack^.next;
  163. dispose(hp);
  164. end;
  165. end;
  166. { this is for popping exception objects when a second exception is risen }
  167. { in an except/on }
  168. function PopSecondObjectStack : TObject;[Public, Alias : 'FPC_POPSECONDOBJECTSTACK'];
  169. var
  170. hp : PExceptObject;
  171. begin
  172. {$ifdef excdebug}
  173. writeln ('In PopObjectstack');
  174. {$endif}
  175. If not(assigned(ExceptObjectStack)) or
  176. not(assigned(ExceptObjectStack^.next)) then
  177. begin
  178. writeln ('At end of ExceptionObjectStack');
  179. halt (1);
  180. end
  181. else
  182. begin
  183. { we need to return the exception object to dispose it }
  184. PopSecondObjectStack:=ExceptObjectStack^.next^.FObject;
  185. hp:=ExceptObjectStack^.next;
  186. ExceptObjectStack^.next:=hp^.next;
  187. dispose(hp);
  188. end;
  189. end;
  190. Procedure ReRaise;[Public, Alias : 'FPC_RERAISE'];
  191. begin
  192. {$ifdef excdebug}
  193. writeln ('In reraise');
  194. {$endif}
  195. If ExceptAddrStack=Nil then
  196. DoUnHandledException;
  197. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  198. end;
  199. Function Catches(Objtype : TExceptObjectClass) : TObject;[Public, Alias : 'FPC_CATCHES'];
  200. begin
  201. If ExceptObjectStack=Nil then
  202. begin
  203. Writeln ('Internal error.');
  204. halt (255);
  205. end;
  206. if Not ((Objtype = TExceptObjectClass(CatchAllExceptions)) or
  207. (ExceptObjectStack^.FObject is ObjType)) then
  208. Catches:=Nil
  209. else
  210. begin
  211. // catch !
  212. Catches:=ExceptObjectStack^.FObject;
  213. { this can't be done, because there could be a reraise (PFV)
  214. PopObjectStack;
  215. Also the PopAddrStack shouldn't be done, we do it now
  216. immediatly in the exception handler (FK)
  217. PopAddrStack; }
  218. end;
  219. end;
  220. Procedure DestroyException(o : TObject);[Public, Alias : 'FPC_DESTROYEXCEPTION'];
  221. begin
  222. { with free we're on the really save side }
  223. o.Free;
  224. end;
  225. Procedure InitExceptions;
  226. {
  227. Initialize exceptionsupport
  228. }
  229. begin
  230. ExceptObjectstack:=Nil;
  231. ExceptAddrStack:=Nil;
  232. end;
  233. {
  234. $Log$
  235. Revision 1.4 2001-01-05 17:35:50 florian
  236. * the info about exception frames is stored now on the stack
  237. instead on the heap
  238. Revision 1.3 2000/09/30 07:38:07 sg
  239. * Added 'RaiseProc': A user-definable callback procedure which gets
  240. called whenever an exception is being raised
  241. Revision 1.2 2000/07/13 11:33:42 michael
  242. + removed logs
  243. }