except.inc 7.1 KB

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