except.inc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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 = SizeInt(-1);
  31. {$ifdef SUPPORT_THREADVAR}
  32. ThreadVar
  33. {$else SUPPORT_THREADVAR}
  34. Var
  35. {$endif SUPPORT_THREADVAR}
  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 fpc_PushExceptAddr (Ft: Longint): PJmp_buf ;
  44. [Public, Alias : 'FPC_PUSHEXCEPTADDR'];saveregisters;
  45. {$else HAS_ADDR_STACK_ON_HEAP}
  46. Function fpc_PushExceptAddr (Ft: Longint;_buf,_newaddr : pointer): PJmp_buf ;
  47. [Public, Alias : 'FPC_PUSHEXCEPTADDR'];saveregisters; {$ifdef hascompilerproc} compilerproc; {$endif}
  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. fpc_PushExceptAddr:=Buf;
  83. end;
  84. Procedure fpc_PushExceptObj (Obj : TObject; AnAddr,AFrame : Pointer);
  85. [Public, Alias : 'FPC_PUSHEXCEPTOBJECT'];saveregisters; {$ifdef hascompilerproc} compilerproc; {$endif}
  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. {$ifdef hascompilerproc}
  108. { make it avalable for local use }
  109. Procedure fpc_PushExceptObj (Obj : TObject; AnAddr,AFrame : Pointer); [external name 'FPC_PUSHEXCEPTOBJECT'];
  110. {$endif}
  111. Procedure DoUnHandledException;
  112. begin
  113. If ExceptProc<>Nil then
  114. If ExceptObjectStack<>Nil then
  115. TExceptPRoc(ExceptProc)(ExceptObjectStack^.FObject,ExceptObjectStack^.Addr,ExceptObjectStack^.Frame);
  116. RunError(217);
  117. end;
  118. Function fpc_Raiseexception (Obj : TObject; AnAddr,AFrame : Pointer) : TObject;[Public, Alias : 'FPC_RAISEEXCEPTION']; {$ifdef hascompilerproc} compilerproc; {$endif}
  119. begin
  120. {$ifdef excdebug}
  121. writeln ('In RaiseException');
  122. {$endif}
  123. fpc_Raiseexception:=nil;
  124. fpc_PushExceptObj(Obj,AnAddr,AFrame);
  125. If ExceptAddrStack=Nil then
  126. DoUnhandledException;
  127. if (RaiseProc <> nil) and (ExceptObjectStack <> nil) then
  128. RaiseProc(Obj, AnAddr, AFrame);
  129. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  130. end;
  131. Procedure fpc_PopAddrStack;[Public, Alias : 'FPC_POPADDRSTACK']; {$ifdef hascompilerproc} compilerproc; {$endif}
  132. {$ifndef HAS_ADDR_STACK_ON_STACK}
  133. var
  134. hp : PExceptAddr;
  135. {$endif HAS_ADDR_STACK_ON_STACK}
  136. begin
  137. {$ifdef excdebug}
  138. writeln ('In Popaddrstack');
  139. {$endif}
  140. If ExceptAddrStack=nil then
  141. begin
  142. writeln ('At end of ExceptionAddresStack');
  143. halt (255);
  144. end
  145. else
  146. begin
  147. {$ifndef HAS_ADDR_STACK_ON_STACK}
  148. hp:=ExceptAddrStack;
  149. ExceptAddrStack:=ExceptAddrStack^.Next;
  150. dispose(hp^.buf);
  151. dispose(hp);
  152. {$else HAS_ADDR_STACK_ON_STACK}
  153. ExceptAddrStack:=ExceptAddrStack^.Next;
  154. {$endif HAS_ADDR_STACK_ON_STACK}
  155. end;
  156. end;
  157. function fpc_PopObjectStack : TObject;[Public, Alias : 'FPC_POPOBJECTSTACK']; {$ifdef hascompilerproc} compilerproc; {$endif}
  158. var
  159. hp : PExceptObject;
  160. begin
  161. {$ifdef excdebug}
  162. writeln ('In PopObjectstack');
  163. {$endif}
  164. If ExceptObjectStack=nil then
  165. begin
  166. writeln ('At end of ExceptionObjectStack');
  167. halt (1);
  168. end
  169. else
  170. begin
  171. { we need to return the exception object to dispose it }
  172. fpc_PopObjectStack:=ExceptObjectStack^.FObject;
  173. hp:=ExceptObjectStack;
  174. ExceptObjectStack:=ExceptObjectStack^.next;
  175. dispose(hp);
  176. end;
  177. end;
  178. { this is for popping exception objects when a second exception is risen }
  179. { in an except/on }
  180. function fpc_PopSecondObjectStack : TObject;[Public, Alias : 'FPC_POPSECONDOBJECTSTACK']; {$ifdef hascompilerproc} compilerproc; {$endif}
  181. var
  182. hp : PExceptObject;
  183. begin
  184. {$ifdef excdebug}
  185. writeln ('In PopObjectstack');
  186. {$endif}
  187. If not(assigned(ExceptObjectStack)) or
  188. not(assigned(ExceptObjectStack^.next)) then
  189. begin
  190. writeln ('At end of ExceptionObjectStack');
  191. halt (1);
  192. end
  193. else
  194. begin
  195. { we need to return the exception object to dispose it }
  196. fpc_PopSecondObjectStack:=ExceptObjectStack^.next^.FObject;
  197. hp:=ExceptObjectStack^.next;
  198. ExceptObjectStack^.next:=hp^.next;
  199. dispose(hp);
  200. end;
  201. end;
  202. Procedure fpc_ReRaise;[Public, Alias : 'FPC_RERAISE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  203. begin
  204. {$ifdef excdebug}
  205. writeln ('In reraise');
  206. {$endif}
  207. If ExceptAddrStack=Nil then
  208. DoUnHandledException;
  209. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  210. end;
  211. Function fpc_Catches(Objtype : TClass) : TObject;[Public, Alias : 'FPC_CATCHES']; {$ifdef hascompilerproc} compilerproc; {$endif}
  212. var
  213. _Objtype : TExceptObjectClass;
  214. begin
  215. If ExceptObjectStack=Nil then
  216. begin
  217. Writeln ('Internal error.');
  218. halt (255);
  219. end;
  220. _Objtype := TExceptObjectClass(Objtype);
  221. if Not ((_Objtype = TExceptObjectClass(CatchAllExceptions)) or
  222. (ExceptObjectStack^.FObject is _ObjType)) then
  223. fpc_Catches:=Nil
  224. else
  225. begin
  226. // catch !
  227. fpc_Catches:=ExceptObjectStack^.FObject;
  228. { this can't be done, because there could be a reraise (PFV)
  229. PopObjectStack;
  230. Also the PopAddrStack shouldn't be done, we do it now
  231. immediatly in the exception handler (FK)
  232. PopAddrStack; }
  233. end;
  234. end;
  235. Procedure fpc_DestroyException(o : TObject);[Public, Alias : 'FPC_DESTROYEXCEPTION']; {$ifdef hascompilerproc} compilerproc; {$endif}
  236. begin
  237. { with free we're on the really save side }
  238. o.Free;
  239. end;
  240. Procedure SysInitExceptions;
  241. {
  242. Initialize exceptionsupport
  243. }
  244. begin
  245. ExceptObjectstack:=Nil;
  246. ExceptAddrStack:=Nil;
  247. end;
  248. {
  249. $Log$
  250. Revision 1.10 2003-05-01 08:05:23 florian
  251. * started to make the rtl 64 bit save by introducing SizeInt and SizeUInt (similar to size_t of C)
  252. Revision 1.9 2002/10/14 19:39:17 peter
  253. * threads unit added for thread support
  254. Revision 1.8 2002/09/07 15:07:45 peter
  255. * old logs removed and tabs fixed
  256. }