Next: , Previous: guile-tools frisk, Up: Miscellaneous Tools


13.15 guile-tools fspec2c

Usage: fspec2c [OPTIONS] FSPEC

Write C fragment to stdout derived from running gperf (GNU perfect
hash function generator) on the flags scanned from the header as
specified in FSPEC.  OPTIONS are zero or more of:

 -o, --output FILE    -- write to FILE instead of stdout
 -I, --include DIR    -- look in DIR instead of /usr/include
 -n, --no-cgen        -- write generated gperf input instead
                         of actually sending it to gperf

The FSPEC file contents is a Scheme list with alternating keyword and
data elements.  These configure the two phases of fspec2c operation:
scanning for entries and feeding properly formatted entries to gperf.
Entries may be extracted by regular expression matching of lines in a
file (or a region of the file) or by a custom (user-defined) procedure.
Formatting includes addition of boilerplate C code and specification of
command-line options.

Currently, these keywords are recognized:

 #:init (BODY...)     -- evaluate BODY forms prior to scan
 #:one-custom THUNK   -- call THUNK for a single entry
 #:acc-custom THUNK   -- call THUNK for a list of entries
 #:infile RELPATH     -- which header to scan (string)
 #:region (BEG . END) -- only scan lines inside BEG-END regexps (strings)
 #:regexp REGEXP      -- regexp w/ at least one subexpression (string)
 #:key-match-num NUM  -- which subexpression is the key
 #:struct SPEC        -- struct-member specifiers (list)
 #:struct-name NAME   -- for "struct NAME { ... }" (string)
 #:gperf-options OPT  -- additional options for gperf (string)
 #:pre-boilerplate S  -- gperf "%{ ... %}" declarations (symbol)
 #:post-boilerplate S -- mostly direct C inclusion (symbol)
 #:subst (SUBSPEC...) -- compute some of the boilerplate dynamically

For #:one-custom and #:acc-custom, THUNK is evaluated in the #:init
environment.  If #:one-custom is specified, THUNK should return an
entry or #f when there are no more entries.  Otherwise, if #:acc-custom
is specified, THUNK should return a list of entries.  Otherwise, the
default is to scan #:infile (in #:region if specified) for #:regexp,
and each entry is match data as returned by `regexp-exec'.

SPEC is a list of struct-member specifiers, each a list of the form:

  (MATCH C-TYPE-COMPONENT-1 [C-TYPE-COMPONENT-2 ...] C-VAR-NAME)

MATCH can be a number to specify a subexpression of REGEXP to use for
static-data initialization, a string to be used for same (note that
to indicate a C string, you need to escape its double-quotes), or #f
to indicate no initialization.  If MATCH is a negative number N, the
the init data is formed by taking the subexpression `(abs N)' of
REGEXP and formatting it with `~S', thus quoting it.  Note: Numerical
MATCH is only useful when the entries are match data.  If MATCH is a
symbol, the procedure it names (in the #:init) is applied to the
entry to returned the desired output.

MATCH can also be a list of the form:

  (FORMATTER ACCESS [REST...])

In this case, a value V is extracted by `(apply ACCESS entry REST)'
and furthermore formatted depending on the FORMATTER keyword, one of:

  #:~A          -- Use `(simple-format #f "~A" V)'.
  #:~S          -- Use `(simple-format #f "~S" V)'.
  #:SCM_MAKINUM -- Use `(simple-format #f "SCM_MAKINUM (~A)" V)'.

ACCESS and REST are evaluated in the #:init environment.  Per info node
"(gperf)User-supplied Struct", the first element of SPEC must be:

  (MATCH char * name)

This restriction may be lifted in the future, as fspec2c is enhanced
to interoperate better with those features of gperf that allow
customization of this struct element.  Specifying `#:key-match-num N'
is the same as specifying `-N' for MATCH.

The #:pre-boilerplate and #:post-boilerplate data elements are
symbols rather than strings, in order to minimize quoting headaches.
Such symbols have the syntax: #{ TEXT }# where TEXT can include
anything (including spaces, newlines, and quote characters) except
the closing curly-brace-hash token.  The only other stipulation is
that backslashes MUST be doubled.  Boilerplate text is processed
by #:subst specifications (see below) and then passed more or less
straight-through by both fspec2c and gperf; errors in the code will
only be flagged during compilation.

The #:subst keyword takes a list of "substitution specification"
forms, the general form of these being `("TAG" BODY...)', where "TAG"
is a string and BODY is a series of Scheme expressions.  In the
boilerplate (both pre and post), regions of text that look like:

  /*@TAG@*/        (NOTE: no double-quotes)

are deleted.  The BODY expressions are evaluated in the #:init
environment and their output (data sent to the current-output-port)
is used to replace the deleted text.  Two convenience procs are
pre-defined in the #:init environment to facilitate formatted output:

  (fs s . args)  -- Send format-string `s' to the current output port,
                    replacing `~A' with the `display', and `~S' with
                    the `write' representation, respectively, of `args'.
  (fln s . args) -- Like `fs' but also send a newline afterwards.

As a special shorthand notation, if SUBSPEC is a single symbol VAR, it
is taken to be equivalent to: `("VAR" (fs "~S" VAR))'.  This is useful
for concisely splicing in Scheme variable values, a common occurance.