macOS port: graceful FFI loading with foreign-entry? guards

ober

52f15d4eb5935164cb71c3eadfa71d9fcfb6d7d5

diff --git a/src/chez-scintilla/ffi.sls b/src/chez-scintilla/ffi.sls
index 68c4691..6a01c86 100644
--- a/src/chez-scintilla/ffi.sls
+++ b/src/chez-scintilla/ffi.sls
@@ -80,184 +80,310 @@
     (or (getenv "CHEZ_SCINTILLA_LIB")
         "."))
 
+  (define shlib-ext
+    (let ((mt (symbol->string (machine-type))))
+      (if (and (>= (string-length mt) 3)
+               (string=? (substring mt (- (string-length mt) 3) (string-length mt)) "osx"))
+          "dylib"
+          "so")))
+
   (define _shim-loaded
-    (load-shared-object
-      (format "~a/chez_scintilla_shim.so" shim-dir)))
+    (guard (e [#t #f])  ;; gracefully skip if shim not available (e.g. macOS Qt-only build)
+      (load-shared-object
+        (format "~a/chez_scintilla_shim.~a" shim-dir shlib-ext))))
+
+  ;; Optional FFI — returns error-raising thunk if symbol not present.
+  ;; Used when the termbox shim may not be available (e.g. macOS Qt builds).
+  (define-syntax define-scintilla-ffi
+    (syntax-rules ()
+      [(_ name c-name (arg-type ...) ret-type)
+       (define name
+         (if (foreign-entry? c-name)
+             (foreign-procedure c-name (arg-type ...) ret-type)
+             (lambda _ (error 'chez-scintilla "termbox shim not loaded" c-name))))]))
 
   ;; ====================================================================
   ;; Instance lifecycle
   ;; ====================================================================
 
   (define ffi-scintilla-new
-    (foreign-procedure "chez_scintilla_new" () void*))
+    (if (foreign-entry? "chez_scintilla_new")
+        (foreign-procedure "chez_scintilla_new" () void*)
+        (lambda () (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_new"))))
 
   (define ffi-scintilla-delete
-    (foreign-procedure "chez_scintilla_delete" (void*) void))
+    (if (foreign-entry? "chez_scintilla_delete")
+        (foreign-procedure "chez_scintilla_delete" (void*) void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_delete"))))
 
   ;; ====================================================================
   ;; Message passing
   ;; ====================================================================
 
   (define ffi-scintilla-send-message
-    (foreign-procedure "chez_scintilla_send_message"
-      (void* unsigned int unsigned-long long) long))
+    (if (foreign-entry? "chez_scintilla_send_message")
+        (foreign-procedure "chez_scintilla_send_message"
+      (void* unsigned int unsigned-long long) long)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_send_message"))))
 
   (define ffi-scintilla-send-message-string
-    (foreign-procedure "chez_scintilla_send_message_string"
-      (void* unsigned-int unsigned-long string) long))
+    (if (foreign-entry? "chez_scintilla_send_message_string")
+        (foreign-procedure "chez_scintilla_send_message_string"
+      (void* unsigned-int unsigned-long string) long)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_send_message_string"))))
 
   (define ffi-scintilla-receive-string
-    (foreign-procedure "chez_scintilla_receive_string"
-      (void* unsigned-int unsigned-long) string))
+    (if (foreign-entry? "chez_scintilla_receive_string")
+        (foreign-procedure "chez_scintilla_receive_string"
+      (void* unsigned-int unsigned-long) string)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_receive_string"))))
 
   (define ffi-scintilla-set-property
-    (foreign-procedure "chez_scintilla_set_property"
-      (void* unsigned-int string string) long))
+    (if (foreign-entry? "chez_scintilla_set_property")
+        (foreign-procedure "chez_scintilla_set_property"
+      (void* unsigned-int string string) long)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_set_property"))))
 
   ;; ====================================================================
   ;; Input
   ;; ====================================================================
 
   (define ffi-scintilla-send-key
-    (foreign-procedure "chez_scintilla_send_key"
-      (void* int int int int) void))
+    (if (foreign-entry? "chez_scintilla_send_key")
+        (foreign-procedure "chez_scintilla_send_key"
+      (void* int int int int) void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_send_key"))))
 
   (define ffi-scintilla-send-mouse
-    (foreign-procedure "chez_scintilla_send_mouse"
-      (void* int int int int int int int) int))
+    (if (foreign-entry? "chez_scintilla_send_mouse")
+        (foreign-procedure "chez_scintilla_send_mouse"
+      (void* int int int int int int int) int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_send_mouse"))))
 
   ;; ====================================================================
   ;; Display
   ;; ====================================================================
 
   (define ffi-scintilla-refresh
-    (foreign-procedure "chez_scintilla_refresh" (void*) void))
+    (if (foreign-entry? "chez_scintilla_refresh")
+        (foreign-procedure "chez_scintilla_refresh" (void*) void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_refresh"))))
 
   (define ffi-scintilla-resize
-    (foreign-procedure "chez_scintilla_resize" (void* int int) void))
+    (if (foreign-entry? "chez_scintilla_resize")
+        (foreign-procedure "chez_scintilla_resize" (void* int int) void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_resize"))))
 
   (define ffi-scintilla-move
-    (foreign-procedure "chez_scintilla_move" (void* int int) void))
+    (if (foreign-entry? "chez_scintilla_move")
+        (foreign-procedure "chez_scintilla_move" (void* int int) void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_move"))))
 
   ;; ====================================================================
   ;; Clipboard
   ;; ====================================================================
 
   (define ffi-scintilla-get-clipboard
-    (foreign-procedure "chez_scintilla_get_clipboard" (void*) string))
+    (if (foreign-entry? "chez_scintilla_get_clipboard")
+        (foreign-procedure "chez_scintilla_get_clipboard" (void*) string)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_get_clipboard"))))
 
   ;; ====================================================================
   ;; Lexer
   ;; ====================================================================
 
   (define ffi-scintilla-set-lexer-language
-    (foreign-procedure "chez_scintilla_set_lexer_language" (void* string) void))
+    (if (foreign-entry? "chez_scintilla_set_lexer_language")
+        (foreign-procedure "chez_scintilla_set_lexer_language" (void* string) void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_set_lexer_language"))))
 
   ;; ====================================================================
   ;; Notification queue
   ;; ====================================================================
 
   (define ffi-scintilla-drain-one
-    (foreign-procedure "chez_scintilla_drain_one" (void*) int))
+    (if (foreign-entry? "chez_scintilla_drain_one")
+        (foreign-procedure "chez_scintilla_drain_one" (void*) int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scintilla_drain_one"))))
 
   (define ffi-scn-code
-    (foreign-procedure "chez_scn_code" () int))
+    (if (foreign-entry? "chez_scn_code")
+        (foreign-procedure "chez_scn_code" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_code"))))
   (define ffi-scn-position
-    (foreign-procedure "chez_scn_position" () long))
+    (if (foreign-entry? "chez_scn_position")
+        (foreign-procedure "chez_scn_position" () long)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_position"))))
   (define ffi-scn-ch
-    (foreign-procedure "chez_scn_ch" () int))
+    (if (foreign-entry? "chez_scn_ch")
+        (foreign-procedure "chez_scn_ch" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_ch"))))
   (define ffi-scn-modifiers
-    (foreign-procedure "chez_scn_modifiers" () int))
+    (if (foreign-entry? "chez_scn_modifiers")
+        (foreign-procedure "chez_scn_modifiers" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_modifiers"))))
   (define ffi-scn-modification-type
-    (foreign-procedure "chez_scn_modification_type" () int))
+    (if (foreign-entry? "chez_scn_modification_type")
+        (foreign-procedure "chez_scn_modification_type" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_modification_type"))))
   (define ffi-scn-text
-    (foreign-procedure "chez_scn_text" () string))
+    (if (foreign-entry? "chez_scn_text")
+        (foreign-procedure "chez_scn_text" () string)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_text"))))
   (define ffi-scn-length
-    (foreign-procedure "chez_scn_length" () long))
+    (if (foreign-entry? "chez_scn_length")
+        (foreign-procedure "chez_scn_length" () long)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_length"))))
   (define ffi-scn-lines-added
-    (foreign-procedure "chez_scn_lines_added" () long))
+    (if (foreign-entry? "chez_scn_lines_added")
+        (foreign-procedure "chez_scn_lines_added" () long)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_lines_added"))))
   (define ffi-scn-message
-    (foreign-procedure "chez_scn_message" () int))
+    (if (foreign-entry? "chez_scn_message")
+        (foreign-procedure "chez_scn_message" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_message"))))
   (define ffi-scn-line
-    (foreign-procedure "chez_scn_line" () long))
+    (if (foreign-entry? "chez_scn_line")
+        (foreign-procedure "chez_scn_line" () long)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_line"))))
   (define ffi-scn-fold-level-now
-    (foreign-procedure "chez_scn_fold_level_now" () int))
+    (if (foreign-entry? "chez_scn_fold_level_now")
+        (foreign-procedure "chez_scn_fold_level_now" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_fold_level_now"))))
   (define ffi-scn-fold-level-prev
-    (foreign-procedure "chez_scn_fold_level_prev" () int))
+    (if (foreign-entry? "chez_scn_fold_level_prev")
+        (foreign-procedure "chez_scn_fold_level_prev" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_fold_level_prev"))))
   (define ffi-scn-margin
-    (foreign-procedure "chez_scn_margin" () int))
+    (if (foreign-entry? "chez_scn_margin")
+        (foreign-procedure "chez_scn_margin" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_margin"))))
   (define ffi-scn-list-type
-    (foreign-procedure "chez_scn_list_type" () int))
+    (if (foreign-entry? "chez_scn_list_type")
+        (foreign-procedure "chez_scn_list_type" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_list_type"))))
   (define ffi-scn-x
-    (foreign-procedure "chez_scn_x" () int))
+    (if (foreign-entry? "chez_scn_x")
+        (foreign-procedure "chez_scn_x" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_x"))))
   (define ffi-scn-y
-    (foreign-procedure "chez_scn_y" () int))
+    (if (foreign-entry? "chez_scn_y")
+        (foreign-procedure "chez_scn_y" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_y"))))
   (define ffi-scn-token
-    (foreign-procedure "chez_scn_token" () int))
+    (if (foreign-entry? "chez_scn_token")
+        (foreign-procedure "chez_scn_token" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_token"))))
   (define ffi-scn-updated
-    (foreign-procedure "chez_scn_updated" () int))
+    (if (foreign-entry? "chez_scn_updated")
+        (foreign-procedure "chez_scn_updated" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_scn_updated"))))
 
   ;; ====================================================================
   ;; Termbox
   ;; ====================================================================
 
   (define ffi-tb-init
-    (foreign-procedure "chez_tb_init" () int))
+    (if (foreign-entry? "chez_tb_init")
+        (foreign-procedure "chez_tb_init" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_init"))))
   (define ffi-tb-shutdown
-    (foreign-procedure "chez_tb_shutdown" () void))
+    (if (foreign-entry? "chez_tb_shutdown")
+        (foreign-procedure "chez_tb_shutdown" () void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_shutdown"))))
   (define ffi-tb-width
-    (foreign-procedure "chez_tb_width" () int))
+    (if (foreign-entry? "chez_tb_width")
+        (foreign-procedure "chez_tb_width" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_width"))))
   (define ffi-tb-height
-    (foreign-procedure "chez_tb_height" () int))
+    (if (foreign-entry? "chez_tb_height")
+        (foreign-procedure "chez_tb_height" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_height"))))
   (define ffi-tb-clear
-    (foreign-procedure "chez_tb_clear" () void))
+    (if (foreign-entry? "chez_tb_clear")
+        (foreign-procedure "chez_tb_clear" () void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_clear"))))
   (define ffi-tb-present
-    (foreign-procedure "chez_tb_present" () void))
+    (if (foreign-entry? "chez_tb_present")
+        (foreign-procedure "chez_tb_present" () void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_present"))))
   (define ffi-tb-set-cursor
-    (foreign-procedure "chez_tb_set_cursor" (int int) void))
+    (if (foreign-entry? "chez_tb_set_cursor")
+        (foreign-procedure "chez_tb_set_cursor" (int int) void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_set_cursor"))))
 
   (define ffi-tb-poll-event
-    (foreign-procedure "chez_tb_poll_event" () int))
+    (if (foreign-entry? "chez_tb_poll_event")
+        (foreign-procedure "chez_tb_poll_event" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_poll_event"))))
   (define ffi-tb-peek-event
-    (foreign-procedure "chez_tb_peek_event" (int) int))
+    (if (foreign-entry? "chez_tb_peek_event")
+        (foreign-procedure "chez_tb_peek_event" (int) int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_peek_event"))))
 
   (define ffi-tb-event-type
-    (foreign-procedure "chez_tb_event_type" () int))
+    (if (foreign-entry? "chez_tb_event_type")
+        (foreign-procedure "chez_tb_event_type" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_event_type"))))
   (define ffi-tb-event-mod
-    (foreign-procedure "chez_tb_event_mod" () int))
+    (if (foreign-entry? "chez_tb_event_mod")
+        (foreign-procedure "chez_tb_event_mod" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_event_mod"))))
   (define ffi-tb-event-key
-    (foreign-procedure "chez_tb_event_key" () int))
+    (if (foreign-entry? "chez_tb_event_key")
+        (foreign-procedure "chez_tb_event_key" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_event_key"))))
   (define ffi-tb-event-ch
-    (foreign-procedure "chez_tb_event_ch" () unsigned-int))
+    (if (foreign-entry? "chez_tb_event_ch")
+        (foreign-procedure "chez_tb_event_ch" () unsigned-int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_event_ch"))))
   (define ffi-tb-event-w
-    (foreign-procedure "chez_tb_event_w" () int))
+    (if (foreign-entry? "chez_tb_event_w")
+        (foreign-procedure "chez_tb_event_w" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_event_w"))))
   (define ffi-tb-event-h
-    (foreign-procedure "chez_tb_event_h" () int))
+    (if (foreign-entry? "chez_tb_event_h")
+        (foreign-procedure "chez_tb_event_h" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_event_h"))))
   (define ffi-tb-event-x
-    (foreign-procedure "chez_tb_event_x" () int))
+    (if (foreign-entry? "chez_tb_event_x")
+        (foreign-procedure "chez_tb_event_x" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_event_x"))))
   (define ffi-tb-event-y
-    (foreign-procedure "chez_tb_event_y" () int))
+    (if (foreign-entry? "chez_tb_event_y")
+        (foreign-procedure "chez_tb_event_y" () int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_event_y"))))
 
   ;; ====================================================================
   ;; Termbox extended
   ;; ====================================================================
 
   (define ffi-tb-change-cell
-    (foreign-procedure "chez_tb_change_cell"
-      (int int unsigned-32 unsigned-32 unsigned-32) void))
+    (if (foreign-entry? "chez_tb_change_cell")
+        (foreign-procedure "chez_tb_change_cell"
+      (int int unsigned-32 unsigned-32 unsigned-32) void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_change_cell"))))
 
   (define ffi-tb-set-clear-attributes
-    (foreign-procedure "chez_tb_set_clear_attributes"
-      (unsigned-32 unsigned-32) void))
+    (if (foreign-entry? "chez_tb_set_clear_attributes")
+        (foreign-procedure "chez_tb_set_clear_attributes"
+      (unsigned-32 unsigned-32) void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_set_clear_attributes"))))
 
   (define ffi-tb-select-input-mode
-    (foreign-procedure "chez_tb_select_input_mode" (int) int))
+    (if (foreign-entry? "chez_tb_select_input_mode")
+        (foreign-procedure "chez_tb_select_input_mode" (int) int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_select_input_mode"))))
 
   (define ffi-tb-select-output-mode
-    (foreign-procedure "chez_tb_select_output_mode" (int) int))
+    (if (foreign-entry? "chez_tb_select_output_mode")
+        (foreign-procedure "chez_tb_select_output_mode" (int) int)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_select_output_mode"))))
 
   (define ffi-tb-print-string
-    (foreign-procedure "chez_tb_print_string"
-      (int int unsigned-32 unsigned-32 string) void))
+    (if (foreign-entry? "chez_tb_print_string")
+        (foreign-procedure "chez_tb_print_string"
+      (int int unsigned-32 unsigned-32 string) void)
+        (lambda _ (error 'chez-scintilla "termbox shim not loaded" "chez_tb_print_string"))))
 
 ) ;; end library