(index ("declare-foreign-features" 0) ("register-foreign-features" 827) ("define-foreign-features" 1887) ("declaration-prefix" 2115) ("registration-prefix" 2333) ("#+" 2555) ("#-" 4299) ("#?" 4385))
(def (sig (syntax "(declare-foreign-features FEATURE1 FEATURE2 ...)" (id declare-foreign-features))) (p "For each feature F, tests whether F is " (tt "#defined") " in C, and creates a new boolean " (tt "#define") " reflecting this.  This new " (tt "#define") " is prefixed with the " (tt "declaration-prefix") ".") (p "For example, using the (default) declaration prefix " (tt "HAVE_") " and the feature " (tt "AF_UNIX") ":") (pre "(declaration-prefix HAVE_)\n(declare-foreign-features AF_UNIX)") (pre "/* generates the C code */\n#ifdef AF_UNIX\n#define HAVE_AF_UNIX 1\n#else\n#define HAVE_AF_UNIX 0\n#endif") (p "The boolean define " (tt "HAVE_AF_UNIX") " is now safely visible to a " (tt "foreign-variable") ".  In contrast, referring to " (tt "AF_UNIX") " from Scheme when undefined would result in a compilation error."))
(def (sig (syntax "(register-foreign-features FEATURE1 FEATURE2 ...)" (id register-foreign-features))) (p "For each feature F, accesses the corresponding boolean " (tt "#define") " in C, usually generated by " (tt "declare-foreign-features") ".  Then, generates code to register or unregister the feature for future compiles.") (p "The boolean define is prefixed with the current " (tt "declaration-prefix") ", and the registered feature will be prefixed with the " (tt "registration-prefix") ".") (p "For example:") (pre "(declaration-prefix \"HAVE_\")\n(registration-prefix \"MYEGG_\")\n(register-foreign-features AF_UNIX)") (p "will expand to code like:") (pre "(declare-foreign-variable HAVE_AF_UNIX bool \"HAVE_AF_UNIX\")\n(if HAVE_AF_UNIX (emit-register!   'MYEGG_AF_UNIX)\n                 (emit-unregister! 'MYEGG_AF_UNIX))") (p "And when compiled and executed, the following is printed to standard output") (pre "(register-feature! 'MYEGG_AF_UNIX)     ;; if AF_UNIX was defined\n(unregister-feature! 'MYEGG_AF_UNIX)   ;; if AF_UNIX was not defined"))
(def (sig (syntax "(define-foreign-features FEATURE1 FEATURE2 ...)" (id define-foreign-features))) (p "Equivalent to") (pre "(declare-foreign-features FEATURE1 FEATURE2 ...)\n(register-foreign-features FEATURE1 FEATURE2 ...)"))
(def (sig (syntax "(declaration-prefix X)" (id declaration-prefix))) (p "Prefix added to the base feature name when declaring a foreign feature. This can be a string or a symbol.") (p "Defaults to " (tt "HAVE_") "."))
(def (sig (syntax "(registration-prefix X)" (id registration-prefix))) (p "Prefix added to the base feature name when registering a foreign feature. This can be a string or a symbol.") (p "Defaults to the empty string."))
(def (sig (read "#+" (id "#+"))) (pre "#+FEATURE EXPR") (p "Test " (tt "FEATURE") " at read-time and, if present, expand to " (tt "EXPR") ". " (tt "FEATURE") " may be any feature expression permitted in a " (tt "cond-expand") ", such as " (tt "windows") " or " (tt "(and windows macosx)") ".") (p (tt "#+") " can be used inside macros because it is expanded when the macro form is read, prior to macroexpansion.  However, this requires a Chicken version >= 4.6.7, which will omit " (tt "EXPR") " if the feature test is false.  In earlier versions, the test expands to a " (tt "(void)") " form, like the built-in " (tt "#+") ".  " (tt "(void)") " forms are usually illegal inside macro bodies.") (p "Here is an example that assumes Chicken is at least 4.6.7, which will omit " (tt "EXPR") " on a false test:") (pre "(cond ((eq? x _af_inet) \"internet address family\")\n      #+AF_UNIX\n      ((eq? x _af_unix) \"unix address family\")\n      (else \"unknown address family\")") (p "If " (tt "AF_UNIX") " is a registered feature at compile-time, it will be read as:") (pre "(cond ((eq? x _af_inet) \"internet address family\")\n      ((eq? x _af_unix) \"unix address family\")\n      (else \"unknown address family\")") (p "If " (tt "AF_UNIX") " is not a registered feature, it will be read as:") (pre "(cond ((eq? x _af_inet) \"internet address family\")\n      (else \"unknown address family\")") (p "However, if " (tt "AF_UNIX") " is unregistered " (i "and") " you are using Chicken prior to 4.6.7, it will instead expand into the illegal:") (pre "(cond ((eq? x _af_inet) \"internet address family\")\n      (##core#undefined)\n      ((eq? x _af_unix) \"unix address family\")\n      (else \"unknown address family\")") (p "So be careful."))
(def (sig (read "#-" (id "#-"))) (p "Like " (tt "#+") ", but of opposite polarity."))
(def (sig (read "#?" (id "#?"))) (pre "#?(FEATURE CONSEQUENT ALTERNATE)") (p "Perform an if-then test at read-time on " (tt "FEATURE") ", expanding to " (tt "CONSEQUENT") " if " (tt "FEATURE") " is present or " (tt "ALTERNATE") " if absent.  " (tt "FEATURE") " may be any feature expression permitted in a " (tt "cond-expand") ", such as " (tt "windows") " or " (tt "(and windows macosx)") ".") (p (tt "#?") " can be used inside macros because it is expanded when the macro form is read, prior to macroexpansion.  It expands correctly irrespective of Chicken version.") (p (tt "#?") " is similar to the Common Lisp idiom") (pre "#+FEATURE CONSEQUENT\n#-FEATURE ALTERNATE") (p "and, in Chicken versions >= 4.6.7 it is exactly equivalent, even inside macro bodies.  However, in previous versions " (tt "#+") " and " (tt "#-") " will not work properly inside macros; see " (tt "#+") " for further explanation.") (p "An example of " (tt "#?") " which is essentially equivalent to " (tt "cond-expand") ":") (pre "(define af/unix #?(AF_UNIX _af_unix #f))\n;; is basically the same as\n(define af/unix (cond-expand (AF_UNIX _af_unix) (else #f)))") (p "A more powerful example of " (tt "#?") ":") (pre "(cond ((eq? x _af_inet) \"internet address family\")\n      #?(AF_UNIX\n         ((eq? x _af_unix) \"unix address family\")\n         (#f))\n      (else \"unknown address family\")") (p "which, if " (tt "AF_UNIX") " is a registered feature, expands into") (pre "(cond ((eq? x _af_inet) \"internet address family\")\n      ((eq? x _af_unix) \"unix address family\")\n      (else \"unknown address family\")") (p "and if not, expands into") (pre "(cond ((eq? x _af_inet) \"internet address family\")\n      (#f)\n      (else \"unknown address family\")") (p "In the latter case, the false clause cannot succeed and is hopefully optimized out by the compiler. " (tt "#+") " would be more appropriate, but requires Chicken >= 4.6.7.  This technique doesn't work with every macro, but you do what you can."))
