Next: guile-tools generate-METAINFO, Previous: guile-tools frisk, Up: Miscellaneous Tools
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.