except.inc 8.7 KB

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