callspec.pas 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. {
  2. $Id$
  3. This unit provides compiler-independent mechanisms to call special
  4. functions, i.e. local functions/procedures, constructors, methods,
  5. destructors, etc. As there are no procedural variables for these
  6. special functions, there is no Pascal way to call them directly.
  7. Copyright (c) 1997 Matthias K"oppe <[email protected]>
  8. This library is free software; you can redistribute it and/or
  9. modify it under the terms of the GNU Library General Public
  10. License as published by the Free Software Foundation; either
  11. version 2 of the License, or (at your option) any later version.
  12. This library is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. Library General Public License for more details.
  16. You should have received a copy of the GNU Library General Public
  17. License along with this library; if not, write to the Free
  18. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ****************************************************************************}
  20. unit CallSpec;
  21. {
  22. As of this version, the following compilers are supported. Please
  23. port CallSpec to other compilers (including earlier versions) and
  24. send your code to the above address.
  25. Compiler Comments
  26. --------------------------- -------------------------------------
  27. Turbo Pascal 6.0
  28. Borland/Turbo Pascal 7.0
  29. FPC Pascal 0.99.8
  30. }
  31. interface
  32. {$i platform.inc}
  33. {
  34. The frame pointer points to the local variables of a procedure.
  35. Use CurrentFramePointer to address the locals of the current procedure;
  36. use PreviousFramePointer to addess the locals of the calling procedure.
  37. }
  38. type
  39. {$ifdef BIT_16}
  40. FramePointer = Word;
  41. {$endif}
  42. {$ifdef BIT_32}
  43. FramePointer = pointer;
  44. {$endif}
  45. function CurrentFramePointer: FramePointer;
  46. function PreviousFramePointer: FramePointer;
  47. { This version of CallSpec supports four classes of special functions.
  48. (Please write if you need other classes.)
  49. For each, two types of argument lists are allowed:
  50. `Void' indicates special functions with no explicit arguments.
  51. Sample: constructor T.Init;
  52. `Pointer' indicates special functions with one explicit pointer argument.
  53. Sample: constructor T.Load(var S: TStream);
  54. }
  55. { Constructor calls.
  56. Ctor Pointer to the constructor.
  57. Obj Pointer to the instance. NIL if new instance to be allocated.
  58. VMT Pointer to the VMT (obtained by TypeOf()).
  59. returns Pointer to the instance.
  60. }
  61. function CallVoidConstructor(Ctor: pointer; Obj: pointer; VMT: pointer): pointer;
  62. function CallPointerConstructor(Ctor: pointer; Obj: pointer; VMT: pointer; Param1: pointer): pointer;
  63. { Method calls.
  64. Method Pointer to the method.
  65. Obj Pointer to the instance. NIL if new instance to be allocated.
  66. returns Pointer to the instance.
  67. }
  68. function CallVoidMethod(Method: pointer; Obj: pointer): pointer;
  69. function CallPointerMethod(Method: pointer; Obj: pointer; Param1: pointer): pointer;
  70. { Local-function/procedure calls.
  71. Func Pointer to the local function (which must be far-coded).
  72. Frame Frame pointer of the wrapping function.
  73. }
  74. function CallVoidLocal(Func: pointer; Frame: FramePointer): pointer;
  75. function CallPointerLocal(Func: pointer; Frame: FramePointer; Param1: pointer): pointer;
  76. { Calls of functions/procedures local to methods.
  77. Func Pointer to the local function (which must be far-coded).
  78. Frame Frame pointer of the wrapping method.
  79. Obj Pointer to the object that the method belongs to.
  80. }
  81. function CallVoidMethodLocal(Func: pointer; Frame: FramePointer; Obj: pointer): pointer;
  82. function CallPointerMethodLocal(Func: pointer; Frame: FramePointer; Obj: pointer; Param1: pointer): pointer;
  83. implementation
  84. {$ifdef PPC_FPC}
  85. {$ifdef CPUI386}
  86. {$ASMMODE ATT}
  87. {$endif CPUI386}
  88. { This indicates an FPC version which uses the same call scheme for
  89. method-local and procedure-local procedures, but which expects the
  90. ESI register be loaded with the Self pointer in method-local procs. }
  91. type
  92. VoidLocal = function(_EBP: FramePointer): pointer;
  93. PointerLocal = function(_EBP: FramePointer; Param1: pointer): pointer;
  94. VoidMethodLocal = function(_EBP: FRAMEPOINTER): pointer;
  95. PointerMethodLocal = function(_EBP: FRAMEPOINTER; Param1: pointer): pointer;
  96. VoidConstructor = function(VMT: pointer; Obj: pointer): pointer;
  97. PointerConstructor = function(VMT: pointer; Obj: pointer; Param1: pointer): pointer;
  98. VoidMethod = function(Obj: pointer): pointer;
  99. PointerMethod = function(Obj: pointer; Param1: pointer): pointer;
  100. function CallVoidConstructor(Ctor: pointer; Obj: pointer; VMT: pointer): pointer;
  101. begin
  102. { load the object pointer }
  103. {$ifdef CPUI386}
  104. asm
  105. movl Obj, %esi
  106. end;
  107. {$endif CPUI386}
  108. {$ifdef CPU68K}
  109. asm
  110. move.l Obj, a5
  111. end;
  112. {$endif CPU68K}
  113. CallVoidConstructor := VoidConstructor(Ctor)(VMT, Obj)
  114. end;
  115. function CallPointerConstructor(Ctor: pointer; Obj: pointer; VMT: pointer; Param1: pointer): pointer;
  116. begin
  117. { load the object pointer }
  118. {$ifdef CPUI386}
  119. asm
  120. movl Obj, %esi
  121. end;
  122. {$endif CPUI386}
  123. {$ifdef CPU68K}
  124. asm
  125. move.l Obj, a5
  126. end;
  127. {$endif CPU68K}
  128. CallPointerConstructor := PointerConstructor(Ctor)(VMT, Obj, Param1)
  129. end;
  130. function CallVoidMethod(Method: pointer; Obj: pointer): pointer;
  131. begin
  132. { load the object pointer }
  133. {$ifdef CPUI386}
  134. asm
  135. movl Obj, %esi
  136. end;
  137. {$endif CPUI386}
  138. {$ifdef CPU68K}
  139. asm
  140. move.l Obj, a5
  141. end;
  142. {$endif CPU68K}
  143. CallVoidMethod := VoidMethod(Method)(Obj)
  144. end;
  145. function CallPointerMethod(Method: pointer; Obj: pointer; Param1: pointer): pointer;
  146. begin
  147. { load the object pointer }
  148. {$ifdef CPUI386}
  149. asm
  150. movl Obj, %esi
  151. end;
  152. {$endif CPUI386}
  153. {$ifdef CPU68K}
  154. asm
  155. move.l Obj, a5
  156. end;
  157. {$endif CPU68K}
  158. CallPointerMethod := PointerMethod(Method)(Obj, Param1)
  159. end;
  160. function CallVoidLocal(Func: pointer; Frame: FramePointer): pointer;
  161. begin
  162. CallVoidLocal := VoidLocal(Func)(Frame)
  163. end;
  164. function CallPointerLocal(Func: pointer; Frame: FramePointer; Param1: pointer): pointer;
  165. begin
  166. CallPointerLocal := PointerLocal(Func)(Frame, Param1)
  167. end;
  168. function CallVoidMethodLocal(Func: pointer; Frame: FramePointer; Obj: pointer): pointer;
  169. begin
  170. { load the object pointer }
  171. {$ifdef CPUI386}
  172. asm
  173. movl Obj, %esi
  174. end;
  175. {$endif CPUI386}
  176. {$ifdef CPU68K}
  177. asm
  178. move.l Obj, a5
  179. end;
  180. {$endif CPU68K}
  181. CallVoidMethodLocal := VoidMethodLocal(Func)(Frame)
  182. end;
  183. function CallPointerMethodLocal(Func: pointer; Frame: FramePointer; Obj: pointer; Param1: pointer): pointer;
  184. begin
  185. { load the object pointer }
  186. {$ifdef CPUI386}
  187. asm
  188. movl Obj, %esi
  189. end;
  190. {$endif CPUI386}
  191. {$ifdef CPU68K}
  192. asm
  193. move.l Obj, a5
  194. end;
  195. {$endif CPU68K}
  196. CallPointerMethodLocal := PointerMethodLocal(Func)(Frame, Param1)
  197. end;
  198. function CurrentFramePointer: FramePointer;assembler;
  199. {$ifdef CPUI386}
  200. asm
  201. movl %ebp,%eax
  202. end ['EAX'];
  203. {$endif CPUI386}
  204. {$ifdef CPU68K}
  205. asm
  206. move.l a6, d0
  207. end['D0'];
  208. {$endif CPU68K}
  209. function PreviousFramePointer: FramePointer;assembler;
  210. {$ifdef CPUI386}
  211. asm
  212. movl (%ebp),%eax
  213. end ['EAX'];
  214. {$endif CPUI386}
  215. {$ifdef CPU68K}
  216. asm
  217. move.l (a6), d0
  218. end['D0'];
  219. {$endif CPU68K}
  220. {$endif PPC_FPC}
  221. {$ifdef PPC_BP}
  222. type
  223. VoidConstructor = function(VmtOfs: Word; Obj: pointer): pointer;
  224. PointerConstructor = function(Param1: pointer; VmtOfs: Word; Obj: pointer): pointer;
  225. VoidMethod = function(Obj: pointer): pointer;
  226. PointerMethod = function(Param1: pointer; Obj: pointer): pointer;
  227. function CallVoidConstructor(Ctor: pointer; Obj: pointer; VMT: pointer): pointer;
  228. begin
  229. CallVoidConstructor := VoidConstructor(Ctor)(Ofs(VMT^), Obj)
  230. end;
  231. function CallPointerConstructor(Ctor: pointer; Obj: pointer; VMT: pointer; Param1: pointer): pointer;
  232. begin
  233. CallPointerConstructor := PointerConstructor(Ctor)(Param1, Ofs(VMT^), Obj)
  234. end;
  235. function CallVoidMethod(Method: pointer; Obj: pointer): pointer;
  236. begin
  237. CallVoidMethod := VoidMethod(Method)(Obj)
  238. end;
  239. function CallPointerMethod(Method: pointer; Obj: pointer; Param1: pointer): pointer;
  240. begin
  241. CallPointerMethod := PointerMethod(Method)(Param1, Obj)
  242. end;
  243. function CallVoidLocal(Func: pointer; Frame: FramePointer): pointer; assembler;
  244. asm
  245. {$IFDEF Windows}
  246. MOV AX,[Frame]
  247. AND AL,0FEH
  248. PUSH AX
  249. {$ELSE}
  250. push [Frame]
  251. {$ENDIF}
  252. call dword ptr Func
  253. end;
  254. function CallPointerLocal(Func: pointer; Frame: FramePointer; Param1: pointer): pointer; assembler;
  255. asm
  256. mov ax, word ptr Param1
  257. mov dx, word ptr Param1+2
  258. push dx
  259. push ax
  260. {$IFDEF Windows}
  261. MOV AX,[Frame]
  262. AND AL,0FEH
  263. PUSH AX
  264. {$ELSE}
  265. push [Frame]
  266. {$ENDIF}
  267. call dword ptr Func
  268. end;
  269. function CallVoidMethodLocal(Func: pointer; Frame: FramePointer; Obj: pointer): pointer; assembler;
  270. asm
  271. {$IFDEF Windows}
  272. MOV AX,[Frame]
  273. AND AL,0FEH
  274. PUSH AX
  275. {$ELSE}
  276. push [Frame]
  277. {$ENDIF}
  278. call dword ptr Func
  279. end;
  280. function CallPointerMethodLocal(Func: pointer; Frame: FramePointer; Obj: pointer; Param1: pointer): pointer; assembler;
  281. asm
  282. mov ax, word ptr Param1
  283. mov dx, word ptr Param1+2
  284. push dx
  285. push ax
  286. {$IFDEF Windows}
  287. MOV AX,[Frame]
  288. AND AL,0FEH
  289. PUSH AX
  290. {$ELSE}
  291. push [Frame]
  292. {$ENDIF}
  293. call dword ptr Func
  294. end;
  295. function CurrentFramePointer: FramePointer; assembler;
  296. asm
  297. mov ax, bp
  298. end;
  299. function PreviousFramePointer: FramePointer; assembler;
  300. asm
  301. mov ax, ss:[bp]
  302. end;
  303. {$endif PPC_BP}
  304. end.
  305. {
  306. $Log$
  307. Revision 1.2 2002-09-07 15:06:36 peter
  308. * old logs removed and tabs fixed
  309. }