## Syntax and conditional compilation

### Feature testing

Syntax: `cond-expand` ``cond-expand-clause```*` [`(else` `command-or-definition*``)`]

> `cond-expand-clause` `::=` `(``feature-requirement` `command-or-definition`*`)`
> `feature-requirement` `::=` `feature-identifier`
> | `(and` `feature-requirement`*`)`
> | `(or` `feature-requirement`*`)`
> | `(not` `feature-requirement` `)`
> | `(library` `library-name` `)`
> `feature-identifier` `::=` a symbol which is the name or alias of a SRFI

> The `cond-expand` form tests for the existence of features at macro-expansion time. It either expands into the body of one of its clauses or signals an error during syntactic processing. `cond-expand` expands into the body of the first clause whose feature requirement is currently satisfied; the `else` clause, if present, is selected if none of the previous clauses is selected.

> The implementation has a set of feature identifiers which are “present”, as well as a set of libraries which can be imported. The value of a `feature-requirement` is determined by replacing each `feature-identifier` by `#t` if it is present (and `#f` otherwise); replacing `(library `library-name`)` by `#t` if `library-name` is importable (and `#f` otherwise); and then evaluating the resulting expression as a Scheme boolean expression under the normal interpretation of `and`, `or`, and `not`.

> Examples:

>     (cond-expand
>         ((and srfi-1 srfi-10)
>          (write 1))
>         ((or srfi-1 srfi-10)
>          (write 2))
>         (else))

>     (cond-expand
>       (command-line
>        (define (program-name) (car (argv)))))

> The second example assumes that `command-line` is an alias for some feature which gives access to command line arguments. Note that an error will be signaled at macro-expansion time if this feature is not present.

> You can use `java-6`, `java-7`, `java-8`, or `java-9` to check if the underlying Java is a specific version or newer. For example the name `java-7` matches for either Java 7, Java 8, or newer, as reported by `System` property `"java.version"`.

> You can use `class-exists:`ClassName`` to check if ``ClassName`` exists at compile-time. The identifier `class-exists:org.example.MyClass` is roughly equivalent to the test `(library (org example MyClass))`. (The latter has some special handling for `(srfi ...)` as well as builtin Kawa classes.)

Procedure: `features`

> Returns a list of feature identifiers which `cond-expand` treats as true. This not a complete list - for example `class-exists:`ClassName`` feature identifiers are not included. It is an error to modify this list. Here is an example of what `features` might return:

>     (features)  ⇒
>     (complex exact-complex full-unicode java-7 java-6 kawa
>      ratios srfi-0 srfi-4 srfi-6 srfi-8 srfi-9 srfi-11
>      srfi-16 srfi-17 srfi-23 srfi-25 srfi-26 srfi-28 srfi-30
>      srfi-39 string-normalize-unicode threads)

### File inclusion

Syntax: `include` `path``+`

Syntax: `include-relative` `path``+`

Syntax: `include-ci` `path``+`

> These take one or more path names expressed as string literals, find corresponding files, read the contents of the files in the specified order as if by repeated applications of `read`, and effectively replace the `include` with a `begin` form containing what was read from the files.

> You can control the search path used for `include` by setting the `kawa.include.path` property. For example:

>     $ kawa -Dkawa.include.path="|:/opt/kawa-includes"

> The special `"|"` path element means to search relative to the directory containing the including source file. The default search path is `"|:."` which means to first search the directory containing the including source file, and then search the directory specified by `(current-path)`.

> The search path for `include-relative` prepends `"|"` before the search path used by `include`, so it always searches first the directory containing the including source file. Note that if the default search path is used then `include` and `include-relative` are equivalent; there is only a difference if the `kawa.include.path` property changes the default.

> Using `include-ci` is like `include`, except that it reads each file as if it began with the `#!fold-case` directive.