/fth/c_struct.fth

https://github.com/philburk/pforth · Forth · 250 lines · 227 code · 23 blank · 0 comment · 10 complexity · 7e962a2d05f6fdd92ed29eab3f51aba7 MD5 · raw file

  1. \ @(#) c_struct.fth 98/01/26 1.2
  2. \ STRUCTUREs are for interfacing with 'C' programs.
  3. \ Structures are created using :STRUCT and ;STRUCT
  4. \
  5. \ This file must be loaded before loading any .J files.
  6. \
  7. \ Author: Phil Burk
  8. \ Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom
  9. \
  10. \ Permission to use, copy, modify, and/or distribute this
  11. \ software for any purpose with or without fee is hereby granted.
  12. \
  13. \ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  14. \ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  15. \ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
  16. \ THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
  17. \ CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  18. \ FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  19. \ CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  20. \ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21. \
  22. \ MOD: PLB 1/16/87 Use abort" instead of er.report
  23. \ MDH 4/14/87 Added sign-extend words to ..@
  24. \ MOD: PLB 9/1/87 Add pointer to last member for debug.
  25. \ MOD: MDH 4/30/88 Use fast addressing for ..@ and ..!
  26. \ MOD: PLB/MDH 9/30/88 Fixed offsets for 16@+long and 8@+long
  27. \ fixed OB.COMPILE.+@/! for 0 offset
  28. \ MOD: PLB 1/11/89 Added EVEN-UP in case of last member BYTE
  29. \ MOD: RDG 9/19/90 Added floating point member support
  30. \ MOD: PLB 12/21/90 Optimized ..@ and ..!
  31. \ 00001 PLB 11/20/91 Make structures IMMEDIATE with ALITERAL for speed
  32. \ Don't need MOVEQ.L #0,D0 for 16@+WORD and 8@+WORD
  33. \ 00002 PLB 8/3/92 Added S@ and S!, and support for RPTR
  34. \ 951112 PLB Added FS@ and FS!
  35. \ This version for the pForth system.
  36. ANEW TASK-C_STRUCT
  37. decimal
  38. \ STRUCT ======================================================
  39. : <:STRUCT> ( pfa -- , run time action for a structure)
  40. [COMPILE] CREATE
  41. @ even-up here swap dup ( -- here # # )
  42. allot ( make room for ivars )
  43. 0 fill ( initialize to zero )
  44. \ immediate \ 00001
  45. \ DOES> [compile] aliteral \ 00001
  46. ;
  47. \ Contents of a structure definition.
  48. \ CELL 0 = size of instantiated structures
  49. \ CELL 1 = #bytes to last member name in dictionary.
  50. \ this is relative so it will work with structure
  51. \ relocation schemes like MODULE
  52. : :STRUCT ( -- , Create a 'C' structure )
  53. \ Check pairs
  54. ob-state @
  55. warning" :STRUCT - Previous :STRUCT or :CLASS unfinished!"
  56. ob_def_struct ob-state ! ( set pair flags )
  57. \
  58. \ Create new struct defining word.
  59. CREATE
  60. here ob-current-class ! ( set current )
  61. 0 , ( initial ivar offset )
  62. 0 , ( location for #byte to last )
  63. DOES> <:STRUCT>
  64. ;
  65. : ;STRUCT ( -- , terminate structure )
  66. ob-state @ ob_def_struct = NOT
  67. abort" ;STRUCT - Missing :STRUCT above!"
  68. false ob-state !
  69. \ Point to last member.
  70. latest ob-current-class @ body> >name - ( byte difference of NFAs )
  71. ob-current-class @ cell+ !
  72. \
  73. \ Even up byte offset in case last member was BYTE.
  74. ob-current-class @ dup @ even-up swap !
  75. ;
  76. \ Member reference words.
  77. : .. ( object <member> -- member_address , calc addr of member )
  78. ob.stats? drop state @
  79. IF ?dup
  80. IF [compile] literal compile +
  81. THEN
  82. ELSE +
  83. THEN
  84. ; immediate
  85. : (S+C!) ( val addr offset -- ) + c! ;
  86. : (S+W!) ( val addr offset -- ) + w! ;
  87. : (S+!) ( val addr offset -- ) + ! ;
  88. : (S+REL!) ( ptr addr offset -- ) + >r if.use->rel r> ! ;
  89. : compile+!bytes ( offset size -- )
  90. \ ." compile+!bytes ( " over . dup . ." )" cr
  91. swap [compile] literal \ compile offset into word
  92. CASE
  93. cell OF compile (s+!) ENDOF
  94. 2 OF compile (s+w!) ENDOF
  95. 1 OF compile (s+c!) ENDOF
  96. -cell OF compile (s+rel!) ENDOF \ 00002
  97. -2 OF compile (s+w!) ENDOF
  98. -1 OF compile (s+c!) ENDOF
  99. true abort" s! - illegal size!"
  100. ENDCASE
  101. ;
  102. : !BYTES ( value address size -- )
  103. CASE
  104. cell OF ! ENDOF
  105. -cell OF ( aptr addr ) swap if.use->rel swap ! ENDOF \ 00002
  106. ABS
  107. 2 OF w! ENDOF
  108. 1 OF c! ENDOF
  109. true abort" s! - illegal size!"
  110. ENDCASE
  111. ;
  112. \ These provide ways of setting and reading members values
  113. \ without knowing their size in bytes.
  114. : (S!) ( offset size -- , compile proper fetch )
  115. state @
  116. IF compile+!bytes
  117. ELSE ( -- value addr off size )
  118. >r + r> !bytes
  119. THEN
  120. ;
  121. : S! ( value object <member> -- , store value in member )
  122. ob.stats?
  123. (s!)
  124. ; immediate
  125. : @BYTES ( addr +/-size -- value )
  126. CASE
  127. cell OF @ ENDOF
  128. 2 OF w@ ENDOF
  129. 1 OF c@ ENDOF
  130. -cell OF @ if.rel->use ENDOF \ 00002
  131. -2 OF w@ w->s ENDOF
  132. -1 OF c@ b->s ENDOF
  133. true abort" s@ - illegal size!"
  134. ENDCASE
  135. ;
  136. : (S+UC@) ( addr offset -- val ) + c@ ;
  137. : (S+UW@) ( addr offset -- val ) + w@ ;
  138. : (S+@) ( addr offset -- val ) + @ ;
  139. : (S+REL@) ( addr offset -- val ) + @ if.rel->use ;
  140. : (S+C@) ( addr offset -- val ) + c@ b->s ;
  141. : (S+W@) ( addr offset -- val ) + w@ w->s ;
  142. : compile+@bytes ( offset size -- )
  143. \ ." compile+@bytes ( " over . dup . ." )" cr
  144. swap [compile] literal \ compile offset into word
  145. CASE
  146. cell OF compile (s+@) ENDOF
  147. 2 OF compile (s+uw@) ENDOF
  148. 1 OF compile (s+uc@) ENDOF
  149. -cell OF compile (s+rel@) ENDOF \ 00002
  150. -2 OF compile (s+w@) ENDOF
  151. -1 OF compile (s+c@) ENDOF
  152. true abort" s@ - illegal size!"
  153. ENDCASE
  154. ;
  155. : (S@) ( offset size -- , compile proper fetch )
  156. state @
  157. IF compile+@bytes
  158. ELSE >r + r> @bytes
  159. THEN
  160. ;
  161. : S@ ( object <member> -- value , fetch value from member )
  162. ob.stats?
  163. (s@)
  164. ; immediate
  165. exists? F* [IF]
  166. \ 951112 Floating Point support
  167. : FLPT ( <name> -- , declare space for a floating point value. )
  168. 1 floats bytes
  169. ;
  170. : (S+F!) ( val addr offset -- ) + f! ;
  171. : (S+F@) ( addr offset -- val ) + f@ ;
  172. : FS! ( value object <member> -- , fetch value from member )
  173. ob.stats?
  174. 1 floats <> abort" FS@ with non-float!"
  175. state @
  176. IF
  177. [compile] literal
  178. compile (s+f!)
  179. ELSE (s+f!)
  180. THEN
  181. ; immediate
  182. : FS@ ( object <member> -- value , fetch value from member )
  183. ob.stats?
  184. 1 floats <> abort" FS@ with non-float!"
  185. state @
  186. IF
  187. [compile] literal
  188. compile (s+f@)
  189. ELSE (s+f@)
  190. THEN
  191. ; immediate
  192. [THEN]
  193. 0 [IF]
  194. :struct mapper
  195. long map_l1
  196. long map_l2
  197. short map_s1
  198. ushort map_s2
  199. byte map_b1
  200. ubyte map_b2
  201. aptr map_a1
  202. rptr map_r1
  203. flpt map_f1
  204. ;struct
  205. mapper map1
  206. ." compiling TT" cr
  207. : TT
  208. 123456 map1 s! map_l1
  209. map1 s@ map_l1 123456 - abort" map_l1 failed!"
  210. 987654 map1 s! map_l2
  211. map1 s@ map_l2 987654 - abort" map_l2 failed!"
  212. -500 map1 s! map_s1
  213. map1 s@ map_s1 dup . cr -500 - abort" map_s1 failed!"
  214. -500 map1 s! map_s2
  215. map1 s@ map_s2 -500 $ FFFF and - abort" map_s2 failed!"
  216. -89 map1 s! map_b1
  217. map1 s@ map_b1 -89 - abort" map_s1 failed!"
  218. here map1 s! map_r1
  219. map1 s@ map_r1 here - abort" map_r1 failed!"
  220. -89 map1 s! map_b2
  221. map1 s@ map_b2 -89 $ FF and - abort" map_s2 failed!"
  222. 23.45 map1 fs! map_f1
  223. map1 fs@ map_f1 f. ." =?= 23.45" cr
  224. ;
  225. ." Testing c_struct.fth" cr
  226. TT
  227. [THEN]