except.inc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  103. end;
  104. Procedure PopAddrStack;[Public, Alias : 'FPC_POPADDRSTACK'];
  105. var
  106. hp : PExceptAddr;
  107. begin
  108. {$ifdef excdebug}
  109. writeln ('In Popaddrstack');
  110. {$endif}
  111. If ExceptAddrStack=nil then
  112. begin
  113. writeln ('At end of ExceptionAddresStack');
  114. halt (255);
  115. end
  116. else
  117. begin
  118. hp:=ExceptAddrStack;
  119. ExceptAddrStack:=ExceptAddrStack^.Next;
  120. dispose(hp^.buf);
  121. dispose(hp);
  122. end;
  123. end;
  124. function PopObjectStack : TObject;[Public, Alias : 'FPC_POPOBJECTSTACK'];
  125. var
  126. hp : PExceptObject;
  127. begin
  128. {$ifdef excdebug}
  129. writeln ('In PopObjectstack');
  130. {$endif}
  131. If ExceptObjectStack=nil then
  132. begin
  133. writeln ('At end of ExceptionObjectStack');
  134. halt (1);
  135. end
  136. else
  137. begin
  138. { we need to return the exception object to dispose it }
  139. PopObjectStack:=ExceptObjectStack^.FObject;
  140. hp:=ExceptObjectStack;
  141. ExceptObjectStack:=ExceptObjectStack^.next;
  142. dispose(hp);
  143. end;
  144. end;
  145. { this is for popping exception objects when a second exception is risen }
  146. { in an except/on }
  147. function PopSecondObjectStack : TObject;[Public, Alias : 'FPC_POPSECONDOBJECTSTACK'];
  148. var
  149. hp : PExceptObject;
  150. begin
  151. {$ifdef excdebug}
  152. writeln ('In PopObjectstack');
  153. {$endif}
  154. If not(assigned(ExceptObjectStack)) or
  155. not(assigned(ExceptObjectStack^.next)) then
  156. begin
  157. writeln ('At end of ExceptionObjectStack');
  158. halt (1);
  159. end
  160. else
  161. begin
  162. { we need to return the exception object to dispose it }
  163. PopSecondObjectStack:=ExceptObjectStack^.next^.FObject;
  164. hp:=ExceptObjectStack^.next;
  165. ExceptObjectStack^.next:=hp^.next;
  166. dispose(hp);
  167. end;
  168. end;
  169. Procedure ReRaise;[Public, Alias : 'FPC_RERAISE'];
  170. begin
  171. {$ifdef excdebug}
  172. writeln ('In reraise');
  173. {$endif}
  174. If ExceptAddrStack=Nil then
  175. DoUnHandledException;
  176. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  177. end;
  178. Function Catches(Objtype : TExceptObjectClass) : TObject;[Public, Alias : 'FPC_CATCHES'];
  179. begin
  180. If ExceptObjectStack=Nil then
  181. begin
  182. Writeln ('Internal error.');
  183. halt (255);
  184. end;
  185. if Not ((Objtype = TExceptObjectClass(CatchAllExceptions)) or
  186. (ExceptObjectStack^.FObject is ObjType)) then
  187. Catches:=Nil
  188. else
  189. begin
  190. // catch !
  191. Catches:=ExceptObjectStack^.FObject;
  192. { this can't be done, because there could be a reraise (PFV)
  193. PopObjectStack;
  194. Also the PopAddrStack shouldn't be done, we do it now
  195. immediatly in the exception handler (FK)
  196. PopAddrStack; }
  197. end;
  198. end;
  199. Procedure DestroyException(o : TObject);[Public, Alias : 'FPC_DESTROYEXCEPTION'];
  200. begin
  201. { with free we're on the really save side }
  202. o.Free;
  203. end;
  204. Procedure InitExceptions;
  205. {
  206. Initialize exceptionsupport
  207. }
  208. begin
  209. ExceptObjectstack:=Nil;
  210. ExceptAddrStack:=Nil;
  211. end;
  212. {
  213. $Log$
  214. Revision 1.20 2000-06-22 18:05:56 michael
  215. + Modifications for exception support in sysutils. Mainly added
  216. RaiseList function.
  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. }