;;; ----------------------------------------------------------------------
;;;
;;; BIND-CLN: Generate a Talk binding for CLN
;;;
;;; ----------------------------------------------------------------------
;;;
;;; Created by Bruno Haible on Fri Nov 22 23:37:28 1996
;;;

;; Instructions:
;; 1. Set the environment variables CLN_DIR and CLN_TARGETDIR, e.g.
;;    export CLN_DIR="$HOME/cln"
;;    export CLN_TARGETDIR="$HOME/cln/linuxelf"
;; 2. Run italk,
;;    (pushf (workspace-path) #f"$CLN_DIR/italk-interface")
;;    (in-workspaces '(iclnws))
;;    (load-program-unit 'bind-cln)
;;    (bind-cln)

(defun bind-cln ()
  (let ((bind-dir (make-filename (.cln-binddir))))
    (unless (and (access bind-dir) (eq (file-type bind-dir) 'S_ISDIR))
      (mkdir bind-dir)))
  (bind-cpp-api
    (list (make-filename (catenate (.cln-dir) "/include/cln.h")))
    (make-filename (catenate (.cln-binddir) "/icln"))
    cpp-options: (list
                  (list 'other
                        (catenate "-I" (.cln-targetdir) "/include")
                        (catenate "-I" (.cln-dir) "/include")
                        "-DITALK_CLN_BINDING"))
    cppparse-options: (list
                       (list '|i86_linux1.2_gnu2.7|
                             "-D__GNUC_MINOR__=6")) ; problem in <_G_config.h>
    filter: #'.filter
    sgi_5_2_3-compatibility-p: ()
    boolean-types: '(cl_boolean)
    cpp-types-exporters: '(libiltcplibm)
    user-execution: '(libiltcplibe)
    description: "Talk/CLN binding"
    link-options: (list
                   (list '|i86_linux1.2_gnu2.7|
                         ; "-Wl,--sort-constructors" ; I have hacked my copy of GNU ld
                         (list 'executable
                           (catenate (.cln-targetdir) "/src/libcln.a")))
                   (list 'other
                         (list 'executable
                           (catenate (.cln-targetdir) "/src/libcln.a"))))
    libraryp: t
    executablep: t
    buildp: t
) )

(defun .filter (file name)
  (if (and (regexp-match "^cl_" (string (basename file)))
           (not (member name
                        '("cl_heap_string"      ; operator new/delete private
                          "cl_heap_modint_ring" ; operator new/delete private
                          "cl_R_div_t::cl_R_div_t"   ; constructor nonexistent
                          "cl_R_fdiv_t::cl_R_fdiv_t" ; constructor nonexistent
                          "cl_null_ring::cl_null_ring" ; constructor nonexistent
                          "abs" "min" "max" "equal" ; clash with Talk functions
                          "gcd" "lcm"               ; clash with Talk functions
                         )
                        #'string=)))
    (progn
      (printf "Binding %s\n" name)
      'always)
    'never
) )

(defun .cln-dir ()
  ;(or (getenv "CLN_DIR") "$HOME/cln")
  "$CLN_DIR"
)

(defun .cln-targetdir ()
  ;(or (getenv "CLN_TARGETDIR") "$HOME/cln/linuxelf")
  "$CLN_TARGETDIR"
)

(defun .cln-binddir ()
  ;; This should match the `root-directory'/`directories' in `iclnws.td'.
  ;(catenate (.cln-targetdir) "/italk-interface")
  (catenate (.cln-dir) "/italk-interface")
)
