except.inc 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. {$IFNDEF VIRTUALPASCAL}
  39. Function RaiseList : PExceptObject;
  40. begin
  41. RaiseList:=ExceptObjectStack;
  42. end;
  43. {$ENDIF}
  44. {$ifndef HAS_ADDR_STACK_ON_STACK}
  45. Function fpc_PushExceptAddr (Ft: Longint): PJmp_buf ;
  46. [Public, Alias : 'FPC_PUSHEXCEPTADDR'];saveregisters;
  47. {$else HAS_ADDR_STACK_ON_HEAP}
  48. Function fpc_PushExceptAddr (Ft: Longint;_buf,_newaddr : pointer): PJmp_buf ;
  49. [Public, Alias : 'FPC_PUSHEXCEPTADDR'];saveregisters; {$ifdef hascompilerproc} compilerproc; {$endif}
  50. {$endif HAS_ADDR_STACK_ON_STACK}
  51. var
  52. Buf : PJmp_buf;
  53. NewAddr : PExceptAddr;
  54. begin
  55. {$ifdef excdebug}
  56. writeln ('In PushExceptAddr');
  57. {$endif}
  58. If ExceptAddrstack=Nil then
  59. begin
  60. {$ifndef HAS_ADDR_STACK_ON_STACK}
  61. New(ExceptAddrStack);
  62. {$else HAS_ADDR_STACK_ON_STACK}
  63. ExceptAddrStack:=PExceptAddr(_newaddr);
  64. {$endif HAS_ADDR_STACK_ON_STACK}
  65. ExceptAddrStack^.Next:=Nil;
  66. end
  67. else
  68. begin
  69. {$ifndef HAS_ADDR_STACK_ON_STACK}
  70. New(NewAddr);
  71. {$else HAS_ADDR_STACK_ON_STACK}
  72. NewAddr:=PExceptAddr(_newaddr);
  73. {$endif HAS_ADDR_STACK_ON_STACK}
  74. NewAddr^.Next:=ExceptAddrStack;
  75. ExceptAddrStack:=NewAddr;
  76. end;
  77. {$ifndef HAS_ADDR_STACK_ON_STACK}
  78. new(buf);
  79. {$else HAS_ADDR_STACK_ON_STACK}
  80. buf:=PJmp_Buf(_buf);
  81. {$endif HAS_ADDR_STACK_ON_STACK}
  82. ExceptAddrStack^.Buf:=Buf;
  83. ExceptAddrStack^.FrameType:=ft;
  84. fpc_PushExceptAddr:=Buf;
  85. end;
  86. Procedure fpc_PushExceptObj (Obj : TObject; AnAddr,AFrame : Pointer);
  87. [Public, Alias : 'FPC_PUSHEXCEPTOBJECT'];saveregisters; {$ifdef hascompilerproc} compilerproc; {$endif}
  88. var
  89. Newobj : PExceptObject;
  90. begin
  91. {$ifdef excdebug}
  92. writeln ('In PushExceptObject');
  93. {$endif}
  94. If ExceptObjectStack=Nil then
  95. begin
  96. New(ExceptObjectStack);
  97. ExceptObjectStack^.Next:=Nil;
  98. end
  99. else
  100. begin
  101. New(NewObj);
  102. NewObj^.Next:=ExceptObjectStack;
  103. ExceptObjectStack:=NewObj;
  104. end;
  105. ExceptObjectStack^.FObject:=Obj;
  106. ExceptObjectStack^.Addr:=AnAddr;
  107. ExceptObjectStack^.Frame:=AFrame;
  108. end;
  109. {$ifdef hascompilerproc}
  110. { make it avalable for local use }
  111. Procedure fpc_PushExceptObj (Obj : TObject; AnAddr,AFrame : Pointer); [external name 'FPC_PUSHEXCEPTOBJECT'];
  112. {$endif}
  113. Procedure DoUnHandledException;
  114. begin
  115. If ExceptProc<>Nil then
  116. If ExceptObjectStack<>Nil then
  117. TExceptPRoc(ExceptProc)(ExceptObjectStack^.FObject,ExceptObjectStack^.Addr,ExceptObjectStack^.Frame);
  118. RunError(217);
  119. end;
  120. Function fpc_Raiseexception (Obj : TObject; AnAddr,AFrame : Pointer) : TObject;[Public, Alias : 'FPC_RAISEEXCEPTION']; {$ifdef hascompilerproc} compilerproc; {$endif}
  121. begin
  122. {$ifdef excdebug}
  123. writeln ('In RaiseException');
  124. {$endif}
  125. fpc_Raiseexception:=nil;
  126. fpc_PushExceptObj(Obj,AnAddr,AFrame);
  127. If ExceptAddrStack=Nil then
  128. DoUnhandledException;
  129. if (RaiseProc <> nil) and (ExceptObjectStack <> nil) then
  130. RaiseProc(Obj, AnAddr, AFrame);
  131. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  132. end;
  133. Procedure fpc_PopAddrStack;[Public, Alias : 'FPC_POPADDRSTACK']; {$ifdef hascompilerproc} compilerproc; {$endif}
  134. {$ifndef HAS_ADDR_STACK_ON_STACK}
  135. var
  136. hp : PExceptAddr;
  137. {$endif HAS_ADDR_STACK_ON_STACK}
  138. begin
  139. {$ifdef excdebug}
  140. writeln ('In Popaddrstack');
  141. {$endif}
  142. If ExceptAddrStack=nil then
  143. begin
  144. writeln ('At end of ExceptionAddresStack');
  145. halt (255);
  146. end
  147. else
  148. begin
  149. {$ifndef HAS_ADDR_STACK_ON_STACK}
  150. hp:=ExceptAddrStack;
  151. ExceptAddrStack:=ExceptAddrStack^.Next;
  152. dispose(hp^.buf);
  153. dispose(hp);
  154. {$else HAS_ADDR_STACK_ON_STACK}
  155. ExceptAddrStack:=ExceptAddrStack^.Next;
  156. {$endif HAS_ADDR_STACK_ON_STACK}
  157. end;
  158. end;
  159. function fpc_PopObjectStack : TObject;[Public, Alias : 'FPC_POPOBJECTSTACK']; {$ifdef hascompilerproc} compilerproc; {$endif}
  160. var
  161. hp : PExceptObject;
  162. begin
  163. {$ifdef excdebug}
  164. writeln ('In PopObjectstack');
  165. {$endif}
  166. If ExceptObjectStack=nil then
  167. begin
  168. writeln ('At end of ExceptionObjectStack');
  169. halt (1);
  170. end
  171. else
  172. begin
  173. { we need to return the exception object to dispose it }
  174. fpc_PopObjectStack:=ExceptObjectStack^.FObject;
  175. hp:=ExceptObjectStack;
  176. ExceptObjectStack:=ExceptObjectStack^.next;
  177. dispose(hp);
  178. end;
  179. end;
  180. { this is for popping exception objects when a second exception is risen }
  181. { in an except/on }
  182. function fpc_PopSecondObjectStack : TObject;[Public, Alias : 'FPC_POPSECONDOBJECTSTACK']; {$ifdef hascompilerproc} compilerproc; {$endif}
  183. var
  184. hp : PExceptObject;
  185. begin
  186. {$ifdef excdebug}
  187. writeln ('In PopObjectstack');
  188. {$endif}
  189. If not(assigned(ExceptObjectStack)) or
  190. not(assigned(ExceptObjectStack^.next)) then
  191. begin
  192. writeln ('At end of ExceptionObjectStack');
  193. halt (1);
  194. end
  195. else
  196. begin
  197. { we need to return the exception object to dispose it }
  198. fpc_PopSecondObjectStack:=ExceptObjectStack^.next^.FObject;
  199. hp:=ExceptObjectStack^.next;
  200. ExceptObjectStack^.next:=hp^.next;
  201. dispose(hp);
  202. end;
  203. end;
  204. Procedure fpc_ReRaise;[Public, Alias : 'FPC_RERAISE']; {$ifdef hascompilerproc} compilerproc; {$endif}
  205. begin
  206. {$ifdef excdebug}
  207. writeln ('In reraise');
  208. {$endif}
  209. If ExceptAddrStack=Nil then
  210. DoUnHandledException;
  211. longjmp(ExceptAddrStack^.Buf^,FPC_Exception);
  212. end;
  213. Function fpc_Catches(Objtype : TClass) : TObject;[Public, Alias : 'FPC_CATCHES']; {$ifdef hascompilerproc} compilerproc; {$endif}
  214. var
  215. _Objtype : TExceptObjectClass;
  216. begin
  217. If ExceptObjectStack=Nil then
  218. begin
  219. Writeln ('Internal error.');
  220. halt (255);
  221. end;
  222. _Objtype := TExceptObjectClass(Objtype);
  223. if Not ((_Objtype = TExceptObjectClass(CatchAllExceptions)) or
  224. (ExceptObjectStack^.FObject is _ObjType)) then
  225. fpc_Catches:=Nil
  226. else
  227. begin
  228. // catch !
  229. fpc_Catches:=ExceptObjectStack^.FObject;
  230. { this can't be done, because there could be a reraise (PFV)
  231. PopObjectStack;
  232. Also the PopAddrStack shouldn't be done, we do it now
  233. immediatly in the exception handler (FK)
  234. PopAddrStack; }
  235. end;
  236. end;
  237. Procedure fpc_DestroyException(o : TObject);[Public, Alias : 'FPC_DESTROYEXCEPTION']; {$ifdef hascompilerproc} compilerproc; {$endif}
  238. begin
  239. { with free we're on the really save side }
  240. o.Free;
  241. end;
  242. Procedure SysInitExceptions;
  243. {
  244. Initialize exceptionsupport
  245. }
  246. begin
  247. ExceptObjectstack:=Nil;
  248. ExceptAddrStack:=Nil;
  249. end;
  250. {
  251. $Log$
  252. Revision 1.11 2003-09-06 21:56:29 marco
  253. * one VIRTUALPASCAL
  254. Revision 1.10 2003/05/01 08:05:23 florian
  255. * started to make the rtl 64 bit save by introducing SizeInt and SizeUInt (similar to size_t of C)
  256. Revision 1.9 2002/10/14 19:39:17 peter
  257. * threads unit added for thread support
  258. Revision 1.8 2002/09/07 15:07:45 peter
  259. * old logs removed and tabs fixed
  260. }