generate-c-header.scm 19 KB

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