generate-c-header.scm 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Marcus Crestani,
  3. ; Harald Glab-Phlak
  4. ; [This is a kludge. Richard is loathe to include it in the
  5. ; distribution. But now the system itself uses it, so we're stuck.]
  6. ; Reads arch.scm and data.scm and writes out a C .h file with constants
  7. ; and macros for dealing with Scheme 48 data structures.
  8. ; Needs Big Scheme.
  9. ; (make-c-header-file "scheme48.h" "scheme48.h.in"
  10. ; "vm/arch.scm" "vm/data.scm" "rts/record.scm")
  11. (define (make-c-header-file c-file c-in-file arch-file data-file record-file)
  12. (receive (stob-list stob-data exception-list channel-status-list)
  13. (search-file arch-file
  14. '("stob enumeration"
  15. "(define stob-data ...)"
  16. "exception enumeration"
  17. "channel-status enumeration")
  18. (defines-enum? 'stob)
  19. enum-definition-list
  20. (lambda (x)
  21. (and (eq? (car x) 'define)
  22. (eq? (cadr x) 'stob-data)))
  23. (lambda (x) (cadr (caddr x)))
  24. (defines-enum? 'exception)
  25. enum-definition-list
  26. (defines-enum? 'channel-status-option)
  27. enum-definition-list)
  28. (receive (tag-list immediate-list)
  29. (search-file data-file
  30. '("tag enumeration" "imm enumeration")
  31. (defines-enum? 'tag)
  32. enum-definition-list
  33. (defines-enum? 'imm)
  34. enum-definition-list)
  35. (let ((record-type-fields
  36. (search-file record-file
  37. '("(define record-type-fields ...")
  38. (lambda (x)
  39. (and (eq? (car x) 'define)
  40. (eq? (cadr x) 'record-type-fields)))
  41. (lambda (x) (cadr (caddr x))))))
  42. (with-output-to-file c-file
  43. (lambda ()
  44. (format #t "/* This file was generated automatically.~%")
  45. (format #t " It's probably not a good idea to change it. */~%")
  46. (newline)
  47. (format #t "#ifndef _H_SCHEME48~%")
  48. (format #t "#define _H_SCHEME48~%")
  49. (newline)
  50. (format #t "#include <scheme48arch.h>~%")
  51. (newline)
  52. (format #t "#ifdef __cplusplus~%")
  53. (format #t "extern \"C\"~%")
  54. (format #t "{~%")
  55. (format #t "#endif~%")
  56. (newline)
  57. (copy-file c-in-file)
  58. (newline)
  59. (format #t "/* New FFI */~%")
  60. (newline)
  61. (tag-stuff-2 tag-list)
  62. (newline)
  63. (immediate-stuff-2 immediate-list)
  64. (newline)
  65. (stob-stuff-2 stob-list stob-data)
  66. (newline)
  67. (enumeration-stuff-2 record-type-fields
  68. "s48_record_type_~A_2(c, x) s48_unsafe_record_ref_2(c, (x), ~D)")
  69. (newline)
  70. (enumeration-stuff-2 exception-list "s48_exception_~A ~D")
  71. (newline)
  72. (enumeration-stuff-2 channel-status-list
  73. "s48_channel_status_~A_2(c) s48_unsafe_enter_long_as_fixnum_2(c, ~D)")
  74. (newline)
  75. (format #t "#ifndef NO_OLD_FFI~%")
  76. (newline)
  77. (tag-stuff tag-list)
  78. (newline)
  79. (immediate-stuff immediate-list)
  80. (newline)
  81. (stob-stuff stob-list stob-data)
  82. (newline)
  83. (enumeration-stuff record-type-fields
  84. "S48_RECORD_TYPE_~A(x) S48_RECORD_REF((x), ~D)")
  85. (newline)
  86. (enumeration-stuff channel-status-list
  87. "S48_CHANNEL_STATUS_~A S48_UNSAFE_ENTER_FIXNUM(~D)")
  88. (newline)
  89. (format #t "#endif /* !NO_OLD_FFI */~%")
  90. (newline)
  91. (enumeration-stuff exception-list "S48_EXCEPTION_~A ~D")
  92. (newline)
  93. (format #t "#include <scheme48write-barrier.h>~%")
  94. (newline)
  95. (format #t "#ifdef __cplusplus~%")
  96. (format #t "/* closing brace for extern \"C\" */~%")
  97. (format #t "}~%")
  98. (format #t "#endif~%")
  99. (newline)
  100. (format #t "#endif /* _H_SCHEME48 */")
  101. (newline)))))))
  102. (define (tag-stuff-2 tag-list)
  103. (do ((tags tag-list (cdr tags))
  104. (i 0 (+ i 1)))
  105. ((null? tags))
  106. (let ((name (downcase (car tags))))
  107. (c-define "s48_~A_tag ~D" name i)
  108. (c-define "s48_~A_p_2(c,x) (((long)s48_deref(x) & 3L) == s48_~A_tag)" name name)))
  109. ;; The write barrier of the bibop garbage collector needs S48_STOB_P.
  110. ;; Make sure it is defined for the combination of BIBOP and new FFI.
  111. (format #t "#if defined(S48_GC_BIBOP) && defined(NO_OLD_FFI)~%")
  112. (c-define "S48_STOB_P(x) (((long)(x) & 3L) == s48_stob_tag)")
  113. (format #t "#endif~%")
  114. (newline)
  115. (c-define "s48_unsafe_enter_long_as_fixnum_2(c, n) (s48_make_local_ref(c,(s48_value)((n) << 2)))")
  116. (c-define "s48_unsafe_extract_long_2(c, x) ((long)s48_deref(x) >> 2)"))
  117. (define (immediate-stuff-2 imm-list)
  118. (c-define "MISC_IMMEDIATE_INTERNAL_2(n) (s48_immediate_tag | ((n) << 2))")
  119. (do ((imm imm-list (cdr imm))
  120. (i 0 (+ i 1)))
  121. ((null? imm))
  122. (let ((name (downcase (car imm))))
  123. (c-define "_s48_value_~A MISC_IMMEDIATE_INTERNAL_2(~D)" name i)
  124. (c-define "s48_~A_2(c) s48_make_local_ref(c, _s48_value_~A)" name name)))
  125. (newline)
  126. (c-define "s48_unsafe_enter_char_2(call, c) s48_make_local_ref (call, _s48_value_char | ((c) << 8))")
  127. (c-define "s48_unsafe_extract_char_2(c,x) ((long)(s48_deref(x) >> 8))")
  128. (c-define "s48_char_p_2(c, x) ((((long) s48_deref(x)) & 0xff) == _s48_value_char)"))
  129. (define (enumeration-stuff-2 names format-string)
  130. (do ((names names (cdr names))
  131. (i 0 (+ 1 i)))
  132. ((null? names))
  133. (let ((name (downcase (car names))))
  134. (c-define format-string name i))))
  135. (define (stob-stuff-2 stob-list stob-data)
  136. (let ((type-mask (let ((len (length stob-list)))
  137. (do ((i 2 (* i 2)))
  138. ((>= i len) (- i 1))))))
  139. (c-define "ADDRESS_AFTER_HEADER_INTERNAL_2(x, type) ((type *)((x) - s48_stob_tag))")
  140. (c-define "STOB_REF_INTERNAL_2(x, i) ADDRESS_AFTER_HEADER_INTERNAL_2(x, s48_value)[i]")
  141. (c-define "STOB_BYTE_REF_INTERNAL_2(x, i) (((char *) ADDRESS_AFTER_HEADER_INTERNAL_2(x, s48_value))[i])")
  142. (c-define "s48_address_after_header_2(c, x, type) ADDRESS_AFTER_HEADER_INTERNAL_2(s48_deref(x), type)")
  143. (c-define "s48_unsafe_stob_ref_2(c, x, i) s48_make_local_ref(c, (STOB_REF_INTERNAL_2(s48_deref(x), i)))")
  144. (c-define "s48_unsafe_stob_byte_ref_2(c, x, i) STOB_BYTE_REF_INTERNAL_2(s48_deref(x), i)")
  145. (c-define (string-append
  146. "s48_unsafe_stob_set_2(c, x, i, r) "
  147. "do { "
  148. "s48_ref_t __stob_set_x_ref = (x); "
  149. "s48_ref_t __stob_set_r_ref = (r); "
  150. "long __stob_set_i = (i); "
  151. "s48_value __stob_set_x = s48_deref(__stob_set_x_ref); "
  152. "s48_value __stob_set_v = s48_deref(__stob_set_r_ref); "
  153. "if (s48_stob_immutablep_2(c, (x))) "
  154. "s48_assertion_violation_2(c, NULL, \"immutable stob\", 1, __stob_set_x); "
  155. "else { "
  156. "S48_WRITE_BARRIER((__stob_set_x), "
  157. "(char *) (&(STOB_REF_INTERNAL_2((__stob_set_x), (__stob_set_i)))),"
  158. "(__stob_set_v)); "
  159. "*(&STOB_REF_INTERNAL_2((__stob_set_x), (__stob_set_i))) = (__stob_set_v); "
  160. "} "
  161. "} while (0)"))
  162. (c-define (string-append
  163. "s48_unsafe_stob_byte_set_2(c, x, i, v) "
  164. "do { "
  165. "long __stob_set_i = (i); "
  166. "char __stob_set_v = (v); "
  167. "s48_value __stob_set_x = s48_deref(x); "
  168. "if (s48_stob_immutablep_2(c, (x))) "
  169. "s48_assertion_violation(NULL, \"immutable stob\", 1, __stob_set_x); "
  170. "else "
  171. "*(&STOB_BYTE_REF_INTERNAL_2((__stob_set_x), (__stob_set_i))) = (__stob_set_v); "
  172. "} while (0)"))
  173. (c-define "s48_stob_header_2(c, x) (STOB_REF_INTERNAL_2(s48_deref(x), -1))")
  174. (c-define "s48_stob_type_2(c, x) ((s48_stob_header_2(c, x)>>2)&~D)" type-mask)
  175. (c-define "s48_stob_address_2(c, x) (&(s48_stob_header_2(c, x)))")
  176. (c-define "s48_unsafe_stob_byte_length_2(c, x) (s48_stob_header_2(c, x) >> 8)")
  177. (c-define "s48_unsafe_stob_descriptor_length_2(c, x) (s48_unsafe_stob_byte_length_2(c, x) >> S48_LOG_BYTES_PER_CELL)")
  178. (c-define "s48_stob_immutablep_2(c, x) ((s48_stob_header_2(c, x)>>7) & 1)")
  179. (c-define "s48_stob_make_immutable_2(c, x) ((s48_stob_header_2(c, x)) |= (1<<7))")
  180. (newline)
  181. (do ((stob stob-list (cdr stob))
  182. (i 0 (+ i 1)))
  183. ((null? stob))
  184. (let ((name (downcase (car stob))))
  185. (c-define "s48_stobtype_~A ~D" name i)
  186. (c-define "s48_~A_p_2(c, x) (s48_stob_has_type_2(c, x, ~D))" name i)))
  187. (newline)
  188. (for-each (lambda (data)
  189. (let ((type (downcase (car data))))
  190. (do ((accs (cdddr data) (cdr accs))
  191. (i 0 (+ i 1)))
  192. ((null? accs))
  193. (let ((name (downcase (caar accs))))
  194. (c-define "s48_~A_offset ~D" name i)
  195. (c-define "s48_~A_2(c, x) (s48_stob_ref_2(c, (x), s48_stobtype_~A, ~D))"
  196. name type i)
  197. (c-define "s48_unsafe_~A_2(c, x) (s48_unsafe_stob_ref_2(c, (x), ~D))" name i))
  198. (if (not (null? (cdar accs)))
  199. (let ((name (downcase (cadar accs))))
  200. (c-define "s48_~A_2(c, x, r) (s48_stob_set_2(c, (x), s48_stobtype_~A, ~D, (r)))"
  201. name type i)
  202. (c-define "s48_unsafe_~A_2(c, x, r) s48_unsafe_stob_set_2(c, (x), ~D, (r))" name i))))))
  203. stob-data)
  204. (newline)
  205. (for-each (lambda (type index)
  206. (c-define "s48_~A_length_2(c, x) (s48_stob_length_2(c, (x), s48_stobtype_~A))"
  207. type type)
  208. (c-define "s48_unsafe_~A_length_2(c, x) (s48_unsafe_stob_descriptor_length_2(c, x))"
  209. type)
  210. (c-define "s48_unsafe_~A_ref_2(c, x, i) (s48_unsafe_stob_ref_2(c, (x), ~A))"
  211. type index)
  212. (c-define "s48_unsafe_~A_set_2(c, x, i, r) s48_unsafe_stob_set_2(c, (x), ~A, (r))"
  213. type index)
  214. (c-define "s48_~A_ref_2(c, x, i) (s48_stob_ref_2(c, (x), s48_stobtype_~A, ~A))"
  215. type type index)
  216. (c-define "s48_~A_set_2(c, x, i, r) s48_stob_set_2(c, (x), s48_stobtype_~A, ~A, (r))"
  217. type type index))
  218. '("vector" "record")
  219. '("(i)" "(i) + 1"))
  220. (c-define "s48_record_type_2(c, x) (s48_stob_ref_2(c, (x), s48_stobtype_record, 0))")
  221. (c-define "s48_unsafe_record_type_2(c, x) (s48_unsafe_stob_ref_2(c, (x), 0))")
  222. (for-each (lambda (type)
  223. (c-define "s48_~A_length_2(c, x) (s48_stob_byte_length_2(c, (x), s48_stobtype_~A))"
  224. type type)
  225. (c-define "s48_~A_ref_2(c, x, i) (s48_stob_byte_ref_2(c, (x), s48_stobtype_~A, (i)))"
  226. type type)
  227. (c-define "s48_~A_set_2(c, x, i, v) (s48_stob_byte_set_2(c, (x), s48_stobtype_~A, (i), (v)))"
  228. type type)
  229. (c-define "s48_unsafe_~A_length_2(c, x) (s48_unsafe_stob_byte_length_2(c, (x), s48_stobtype_~A))"
  230. type type)
  231. (c-define "s48_unsafe_~A_ref_2(c, x, i) (s48_stob_byte_ref_2(c, (x), s48_stobtype_~A, (i)))"
  232. type type)
  233. (c-define "s48_unsafe_~A_set_2(c, x, i, v) (s48_stob_byte_set_2(c, (x), s48_stobtype_~A, (i), (v)))"
  234. type type))
  235. '("byte_vector"))
  236. (c-define "s48_unsafe_extract_byte_vector_2(c, x) (s48_address_after_header_2(c, (x), char))")
  237. (c-define (string-append "s48_extract_external_object_2(c, x, type) "
  238. "((type *)(s48_address_after_header_2(c, x, long)+1))"))))
  239. (define (tag-stuff tag-list)
  240. (do ((tags tag-list (cdr tags))
  241. (i 0 (+ i 1)))
  242. ((null? tags))
  243. (let ((name (upcase (car tags))))
  244. (c-define "S48_~A_TAG ~D" name i)
  245. (c-define "S48_~A_P(x) (((long)(x) & 3L) == S48_~A_TAG)" name name)))
  246. (newline)
  247. (c-define "S48_UNSAFE_ENTER_FIXNUM(n) ((s48_value)((n) << 2))")
  248. (c-define "S48_UNSAFE_EXTRACT_FIXNUM(x) ((long)(x) >> 2)"))
  249. (define (immediate-stuff imm-list)
  250. (c-define "S48_MISC_IMMEDIATE(n) (S48_IMMEDIATE_TAG | ((n) << 2))")
  251. (do ((imm imm-list (cdr imm))
  252. (i 0 (+ i 1)))
  253. ((null? imm))
  254. (let ((name (upcase (car imm))))
  255. (c-define "S48_~A (S48_MISC_IMMEDIATE(~D))" name i)))
  256. (newline)
  257. (c-define "S48_UNSAFE_ENTER_CHAR(c) (S48_CHAR | ((c) << 8))")
  258. (c-define "S48_UNSAFE_EXTRACT_CHAR(x) ((long)((x) >> 8))")
  259. (c-define "S48_CHAR_P(x) ((((long) (x)) & 0xff) == S48_CHAR)"))
  260. (define (stob-stuff stob-list stob-data)
  261. (let ((type-mask (let ((len (length stob-list)))
  262. (do ((i 2 (* i 2)))
  263. ((>= i len) (- i 1))))))
  264. (c-define "ADDRESS_AFTER_HEADER_INTERNAL(x, type) ((type *)((x) - S48_STOB_TAG))")
  265. (c-define "STOB_REF_INTERNAL(x, i) ADDRESS_AFTER_HEADER_INTERNAL(x, s48_value)[i]")
  266. (c-define "STOB_BYTE_REF_INTERNAL(x, i) (((char *) ADDRESS_AFTER_HEADER_INTERNAL(x, s48_value))[i])")
  267. (c-define "S48_ADDRESS_AFTER_HEADER(x, type) ADDRESS_AFTER_HEADER_INTERNAL(x, type)")
  268. (c-define "S48_STOB_REF(x, i) STOB_REF_INTERNAL((x), i)")
  269. (c-define "S48_STOB_BYTE_REF(x, i) STOB_BYTE_REF_INTERNAL((x), i)")
  270. (c-define (string-append
  271. "S48_STOB_SET(x, i, v) "
  272. "do { "
  273. "s48_value __stob_set_x = (x); "
  274. "long __stob_set_i = (i); "
  275. "s48_value __stob_set_v = (v); "
  276. "if (S48_STOB_IMMUTABLEP(__stob_set_x)) "
  277. "s48_assertion_violation(NULL, \"immutable stob\", 1, __stob_set_x); "
  278. "else { "
  279. "S48_WRITE_BARRIER((__stob_set_x), "
  280. "(char *) (&S48_STOB_REF((__stob_set_x), (__stob_set_i))),"
  281. "(__stob_set_v)); "
  282. "*(&S48_STOB_REF((__stob_set_x), (__stob_set_i))) = (__stob_set_v); "
  283. "} "
  284. "} while (0)"))
  285. (c-define (string-append
  286. "S48_STOB_BYTE_SET(x, i, v) "
  287. "do { "
  288. "s48_value __stob_set_x = (x); "
  289. "long __stob_set_i = (i); "
  290. "char __stob_set_v = (v); "
  291. "if (S48_STOB_IMMUTABLEP(__stob_set_x)) "
  292. "s48_assertion_violation(NULL, \"immutable stob\", 1, __stob_set_x); "
  293. "else "
  294. "*(&S48_STOB_BYTE_REF((__stob_set_x), (__stob_set_i))) = (__stob_set_v); "
  295. "} while (0)"))
  296. (c-define "S48_STOB_HEADER(x) (S48_STOB_REF((x),-1))")
  297. (c-define "S48_STOB_TYPE(x) ((S48_STOB_HEADER(x)>>2)&~D)" type-mask)
  298. (c-define "S48_STOB_ADDRESS(x) (&(S48_STOB_HEADER(x)))")
  299. (c-define "S48_STOB_BYTE_LENGTH(x) ((unsigned long)S48_STOB_HEADER(x) >> 8)")
  300. (c-define "S48_STOB_DESCRIPTOR_LENGTH(x) (S48_STOB_BYTE_LENGTH(x) >> S48_LOG_BYTES_PER_CELL)")
  301. (c-define "S48_STOB_IMMUTABLEP(x) ((S48_STOB_HEADER(x)>>7) & 1)")
  302. (c-define "S48_STOB_MAKE_IMMUTABLE(x) ((S48_STOB_HEADER(x)) |= (1<<7))")
  303. (newline)
  304. (do ((stob stob-list (cdr stob))
  305. (i 0 (+ i 1)))
  306. ((null? stob))
  307. (let ((name (upcase (car stob))))
  308. (c-define "S48_STOBTYPE_~A ~D" name i)
  309. (c-define "S48_~A_P(x) (s48_stob_has_type(x, ~D))" name i)))
  310. (newline)
  311. (for-each (lambda (data)
  312. (let ((type (upcase (car data))))
  313. (do ((accs (cdddr data) (cdr accs))
  314. (i 0 (+ i 1)))
  315. ((null? accs))
  316. (let ((name (upcase (caar accs))))
  317. (c-define "S48_~A_OFFSET ~D" name i)
  318. (c-define "S48_~A(x) (s48_stob_ref((x), S48_STOBTYPE_~A, ~D))"
  319. name type i)
  320. (c-define "S48_UNSAFE_~A(x) (S48_STOB_REF((x), ~D))" name i))
  321. (if (not (null? (cdar accs)))
  322. (let ((name (upcase (cadar accs))))
  323. (c-define "S48_~A(x, v) (s48_stob_set((x), S48_STOBTYPE_~A, ~D, (v)))"
  324. name type i)
  325. (c-define "S48_UNSAFE_~A(x, v) S48_STOB_SET((x), ~D, (v))" name i))))))
  326. stob-data)
  327. (newline)
  328. (for-each (lambda (type index)
  329. (c-define "S48_~A_LENGTH(x) (s48_stob_length((x), S48_STOBTYPE_~A))"
  330. type type)
  331. (c-define "S48_UNSAFE_~A_LENGTH(x) (S48_STOB_DESCRIPTOR_LENGTH(x))"
  332. type)
  333. (c-define "S48_~A_REF(x, i) (s48_stob_ref((x), S48_STOBTYPE_~A, ~A))"
  334. type type index)
  335. (c-define "S48_~A_SET(x, i, v) (s48_stob_set((x), S48_STOBTYPE_~A, ~A, (v)))"
  336. type type index)
  337. (c-define "S48_UNSAFE_~A_REF(x, i) (S48_STOB_REF((x), ~A))"
  338. type index)
  339. (c-define "S48_UNSAFE_~A_SET(x, i, v) S48_STOB_SET((x), ~A, (v))"
  340. type index))
  341. '("VECTOR" "RECORD")
  342. '("(i)" "(i) + 1"))
  343. (c-define "S48_RECORD_TYPE(x) (s48_stob_ref((x), S48_STOBTYPE_RECORD, 0))")
  344. (c-define "S48_UNSAFE_RECORD_TYPE(x) (S48_STOB_REF((x), 0))")
  345. (for-each (lambda (type)
  346. (c-define "S48_~A_LENGTH(x) (s48_stob_byte_length((x), S48_STOBTYPE_~A))"
  347. type type)
  348. (c-define "S48_~A_REF(x, i) (s48_stob_byte_ref((x), S48_STOBTYPE_~A, (i)))"
  349. type type)
  350. (c-define "S48_~A_SET(x, i, v) (s48_stob_byte_set((x), S48_STOBTYPE_~A, (i), (v)))"
  351. type type)
  352. (c-define "S48_UNSAFE_~A_REF(x, i) (S48_STOB_BYTE_REF((x), (i)))"
  353. type)
  354. (c-define "S48_UNSAFE_~A_SET(x, i, v) S48_BYTE_STOB_SET((x), (i), (v))"
  355. type))
  356. '("BYTE_VECTOR"))
  357. (c-define "S48_UNSAFE_BYTE_VECTOR_LENGTH(x) (S48_STOB_BYTE_LENGTH(x))")
  358. (c-define "S48_UNSAFE_EXTRACT_BYTE_VECTOR(x) (S48_ADDRESS_AFTER_HEADER((x), char))")
  359. (c-define "S48_STRING_LENGTH(s) (s48_string_length(s))")
  360. (c-define "S48_STRING_REF(s, i) (s48_string_ref((s), (i)))")
  361. (c-define "S48_STRING_SET(s, i, v) (s48_string_set((s), (i), (v)))")
  362. (c-define (string-append "S48_EXTRACT_EXTERNAL_OBJECT(x, type) "
  363. "((type *)(S48_ADDRESS_AFTER_HEADER(x, long)+1))"))))
  364. (define (enumeration-stuff names format-string)
  365. (do ((names names (cdr names))
  366. (i 0 (+ 1 i)))
  367. ((null? names))
  368. (let ((name (upcase (car names))))
  369. (c-define format-string name i))))
  370. ; - becomes _ > becomes TO_ (so -> turns into _TO_)
  371. ; ? becomes P
  372. ; ! disappears
  373. (define (upcase symbol)
  374. (do ((chars (string->list (symbol->string symbol)) (cdr chars))
  375. (res '() (case (car chars)
  376. ((#\>) (append (string->list "_OT") res))
  377. ((#\-) (cons #\_ res))
  378. ((#\?) (cons #\P res))
  379. ((#\/ #\!) res)
  380. (else (cons (char-upcase (car chars)) res)))))
  381. ((null? chars)
  382. (list->string (reverse res)))))
  383. (define (downcase symbol)
  384. (do ((chars (string->list (symbol->string symbol)) (cdr chars))
  385. (res '() (case (car chars)
  386. ((#\>) (append (string->list "_ot") res))
  387. ((#\-) (cons #\_ res))
  388. ((#\?) (cons #\p res))
  389. ((#\/ #\!) res)
  390. (else (cons (char-downcase (car chars)) res)))))
  391. ((null? chars)
  392. (list->string (reverse res)))))
  393. (define (c-define string . stuff)
  394. (format #t "#define ~?~%" string stuff))
  395. (define (defines-enum? name)
  396. (lambda (x)
  397. (and (eq? (car x) 'define-enumeration)
  398. (eq? (cadr x) name))))
  399. (define enum-definition-list caddr)
  400. ; Copy the file to the current-output-file.
  401. (define (copy-file filename)
  402. (call-with-input-file filename
  403. (lambda (in)
  404. (let loop ()
  405. (let ((c (read-char in)))
  406. (if (not (eof-object? c))
  407. (begin
  408. (write-char c)
  409. (loop))))))))
  410. ; WHAT-FOR is a list of names, used only for debugging.
  411. ; PRED+EXTRACT is a list of <predicate0> <extract0> <predicate1> <extract1> ... .
  412. ; Each form in the file is read and passed to the predicates that haven't yet
  413. ; matched. If the predicate matches the corresponding extractor is called on
  414. ; the form. The results of the extractors are returned.
  415. ;
  416. ; STUFF is list of ((predicate . extract) . name). <name> is replaced
  417. ; with the value when it is found.
  418. (define (search-file file what-for . pred+extract)
  419. (let ((stuff (do ((p+e pred+extract (cddr p+e))
  420. (names what-for (cdr names))
  421. (ps '() (cons (cons (cons (car p+e) (cadr p+e))
  422. (car names))
  423. ps)))
  424. ((null? p+e) (reverse ps)))))
  425. (define (search next not-found)
  426. (let loop ((n-f not-found) (checked '()))
  427. (cond ((null? n-f)
  428. #f)
  429. (((caaar n-f) next)
  430. (set-cdr! (car n-f) ((cdaar n-f) next))
  431. (append (reverse checked) (cdr n-f)))
  432. (else
  433. (loop (cdr n-f) (cons (car n-f) checked))))))
  434. (with-input-from-file file
  435. (lambda ()
  436. (let loop ((not-found stuff))
  437. (let ((next (read)))
  438. (cond ((null? not-found)
  439. (apply values (map cdr stuff)))
  440. ((eof-object? next)
  441. (error "file ~S doesn't have ~A" file (cdar not-found)))
  442. (else
  443. (loop (or (and (pair? next)
  444. (search next not-found))
  445. not-found))))))))))