FWEB recognizes two kinds of macros: outer macros, and WEB macros or inner macros. Control codes associated with either of these kinds normally begin the definition part. However, FWEB macros are sometimes allowed in the code part as well; see section FWEB macros.
Macros are processed by FTANGLE only; FWEAVE merely prints them as they occur in the source file.
Outer macros are defined by `@d' (see section `@d': Define outer macro, and mark) or `@D' (see section `@D': Define outer macro). They may be placed in any definition part. FTANGLE collects them during phase 1; during phase 2, they are simply copied in order of their appearance to the beginning of the output file. This is most useful for C or C++ codes; it's a shorthand way of typing `#define' when the positioning of the `#define' is unimportant.
As an example,
@c @ @d YES 1 @d NO 0 @a main() {} @ @d BUF_LEN 100 @a ...
The keyword into which the `@d' is translated is language-dependent; it is controlled by the style-file parameter `outer_def'. See section Miscellaneous style-file parameters.
Outer macros can be undefined by `@u'. The translation is controlled by the style-file parameter `outer_undef'. See section Miscellaneous style-file parameters.
The default behavior, in which the outer macro definitions are just
copied to the top of the output file, is fine for simple applications.
However, often C programmers prefer to maintain their macro definitions
in a header file `test.h'. One way of accomplishing this is to
redirect FTANGLE's output from the command line, as in
`ftangle test -=test.h', then use an `@O' command immediately
after the first `@a' in the web
file to open up
`test.c'. A more complicated variant of this allows additional
information to be placed into the header file:
@c @* INTRO. We assume command-line redirection into \.{test.h} (`\.{-=test.h}'). @d A 1 // This will go into \.{test.h}. @a @<Header material@>@; // Also goes into \.{test.h}. @O test.c // Remaining unnamed sections go into \.{test.c}. @ Header material may be defined as needed throughout the code, but with this design it will all go into \.{test.h}. @<Header material@>= @<Includes@>@; @<Typedefs@>@; @<Global variables@>@;
FWEB macros are defined by `@m' (see section `@m': Define FWEB macro, and mark) or `@M' (see section `@M': Define FWEB macro). These should normally be placed in the definition section, as in
@ Documentation... @m CUBE(x) pow(x, 3.0) @a
They are collected during FTANGLE's phase 1 and effectively placed at the top of the unnamed section, so they are all known during the output in phase 2.
In unusual situations when macros are being conditionally defined and/or undefined, the order of processing a macro definition becomes significant. If the command-line option `-TD' is used, then FWEB macros may be used in the code part as well; they are then called deferred macros. These definitions will be processed during phase 2 in the order that the code sections are processed, which may not be the same as the physical order in the source file.
The use of deferred macros is highly discouraged, for the following reason. FWEB macros are often used in conjunction with the FWEB preprocessor commands. Preprocessor commands are always processed during phase 1, so they do not interact properly with deferred macros. It is for this reason that deferred macros are normally prohibited from appearing in the code part.
- Fundamentally, FWEB macros follow the syntax for ANSI C. There are also a few extensions, notably the possibility of variable (optional) arguments (see next item) and some additional preprocessing tokens (see section Special tokens).
- FWEB macros with a variable number of arguments are indicated by an ellipsis, as in
@m VAR(x,y,z,...) text- Adjacent strings in macro text are automatically concatenated.
The following special tokens may be used in the text of FWEB macro definitions:
## -- Paste tokens on either side to form a new identifier. #parameter -- Convert parameter to string (without expansion).
For example,
@m FORTRAN(type, name) type _##name() @m TRACE(where) puts("At " #where) @a FORTRAN(int, fcalc); // Expands to `int _fcalc();' TRACE(predictor); // Expands to `puts("At " "predictor");
The most frequently used extensions are the following ones associated with variable arguments: `#0', `#n', and `#.'. FORTRAN-77 users should also employ `#:0' to allow symbolic rather than numeric statement labels. Try to use the other extensions sparingly; they are experimental, complicated, and unlikely to work in all situations.
In the following list, the forms `#{n}' and `#[n]' may not work correctly in complicated situations. This is a design deficiency that may be corrected someday.
#*parameter -- Like #parameter, but pass a quoted string through unchanged. #!parameter -- Don't expand argument. #'parameter -- Convert parameter to a single-quoted string (no expansion). #"parameter -- Convert parameter to a double-quoted string (no expansion). #0 -- Number of variable arguments. #n -- n-th variable argument, counting from 1. #{0} -- Like #0, but the argument may be a macro expression known at run time. #{n} -- Like #n, but the argument may be a macro expression. #[0] -- The total number of arguments (fixed + variable). (The argument inside the brackets may be a macro expression.) #[n] -- The n-th argument (including the fixed ones), counting from 1. (The argument inside the brackets may be a macro expressions.) #. -- Comma-separated list of all variable arguments. #:0 -- Unique statement number (expanded in phase 1). #:nnn -- Unique statement number for each invocation of this macro (expanded in phase 2). #< -- Begin a module name. #, -- Internal comma; doesn't delimit macro argument.
A few examples of the more important of these tokens are as follows:
@c @m FPRINTF(fmt,...) fprintf(fp,fmt,#.) // Use the whole list of variable args. @m B(...) printf("There were %i arguments\n", #0) // Use the number of var args. @n @ @m DONE #:0 // Symbolic statement label in FORTRAN. @a goto DONE ... DONE: call endup
Built-in functions behave in most ways like macros. In some cases they actually are macros, but more often they implement functions that a user could not define. They all begin with a dollar sign and are in upper case.
In using these built-ins, confusion may arise regarding the order of
expansion of various arguments. When they are implemented as macros,
they are subject to the same ANSI-C preprocessor rules as other
FWEB macros, which is that all arguments are fully expanded before
generating the replacement text of the macro. When they are directly
implemented as a primitive function, however, that rule may not apply.
For example, $IF
expands only its first argument during its first
pass of processing; depending on the results of that expansion, it then
expands either its second or third argument, but not both.
The built-in function $DUMPDEF
can be used to understand and
debug the action of the built-in functions. See section $DUMPDEF
: Dump macro definitions to the terminal.
In the original FWEB design, built-in functions began with an underscore. This usage conflicts with the conventions for reserved words in ANSI C, and has been eliminated. All FWEB built-ins now begin with a dollar sign.
No user-defined macro should begin with a dollar sign! It might interfere with the functioning of some internal built-in function.
Several of the built-in functions expect or return a string argument.
Examples include $STRING
(see section $STRING
: Expand, then stringize), $UNQUOTE
(see section $UNQUOTE
: Remove quotes from string), and $UNSTRING
(see section $UNSTRING
: Convert string into characters).
In understanding the operation of those functions, it is important to
understand just what a string means in the FWEB context. As usual,
it is a collection of characters. However, these need not be
delimited by quotes, although they may be. Internally, a string is
represented by the construction sqc...cqs, where s is a special
string delimiter never seen by the user, q is an optional quote
character (either single or double quote depending on the language), and
c is an ordinary character. Whether or not the quotes are present,
the string delimiters inhibit macro expansion.
The difference between $UNQUOTE
and $UNSTRING
can now be
stated as follows. Given a quoted string such as "abc"
(in C),
abc
(and therefore is not very useful).
$UNSTRING
is primarily used internally.
The built-ins $P
(see section $P
: The C preprocessor symbol) and $PP
(see section $PP
: The C preprocessor symbol), which
both generate the preprocessor character `#', provide a good
illustration of the differences between $UNQUOTE
and
$UNSTRING
. Consider FORTRAN as an example. Essentially,
$P
is defined as `$UNQUOTE('#')', which is internally
s#s. When this single-character string is sent to the output, it is
treated like any other expression and therefore would appear in column 7
or greater even if the construction appeared at the very beginning of
the line. On the other hand, $PP
is (essentially) defined as
`$UNSTRING('#')', which is internally the single character #.
Because this character is not a string, the FORTRAN output driver
treats it as a special control character, defined in this case to force
the character into the first column.
$A
: Convert to ASCII`$A(string)' is the built-in equivalent of `@'...'' or `@"..."'. (See section Conversion to ASCII and section `@"': Convert string to ASCII.) Note the extra parentheses required by the built-in.
$A
first expands its argument, in case it is a macro defined as a
string.
$ABS
: Absolute value
`$ABS(expression)' returns the absolute value of the macro
expression. It is a macro implemented in terms of $IF
and $EVAL
.
$ASSERT
: Assert a condition`$ASSERT(expression)' evaluates the macro expression. If the expression is false, an error message is printed and the run aborts.
This built-in is useful for ensuring that FWEB macros required by the code are properly initialized. Because it is expanded during the output phase, it must appear in the code part (not in the definition part).
$AUTHOR
: Value of RCS keyword Author
Equivalent to `$KEYWORD(Author)'. See section $KEYWORD
: Value of RCS-like keyword.
$COMMENT
: Generate a comment`$COMMENT'(string) generates a comment in the output file.
This function is sometimes useful in conjunction with the processing of FWEB macros, since ordinary comments are removed when macros are processed. For example, if one says
@c @ @m M "abc" $COMMENT("Test") @a m = M
the tangled output will be `m= "abc"/* Test */'
$DATE
: Today's date
`$DATE' generates a string consisting of the date in the form
"August 16, 2001"
. It is implemented as a macro that calls other
macros and primitive functions.
$DATE_TIME
: Value of RCS keyword Date
Equivalent to `$KEYWORD(Date)'. See section $KEYWORD
: Value of RCS-like keyword.
$DAY
: The day
`$DAY' generates a string consisting of the day of the week, such
as "Monday"
. It is implemented as a macro that calls other
macros and primitive functions.
$DECR
: Decrement a macro`$DECR'(N) redefines the numeric macro N to be one less than its previous value. (If N does not simplify to a number, an error results.) In other words, in the language of C the effect is to say `N--'.
The two-argument form `$DECR'(N,m) executes the equivalent of `N -= m'.
$DEFINE
: Deferred macro definition
`$DEFINE' behaves like the FWEB macro command @m
, but
it is intended to appear in the code part, not the definition part (so
it is processed during output, not input). Thus, the code fragment
a = A; $DEFINE(A 1)@% a = A;
tangles to
a= A; a= 1;
(Notice how the `@%' command was used to kill an unwanted newline, analogous to the `dnl' macro in `m4'.)
In the above example, one could also say `$DEFINE(A=1)'. To define a macro with arguments, say something like `$DEFINE(A(x)x*x)'. Do not say `$DEFINE(A(x)=x*x)', as in this case the equals sign will be included in the macro expansion. One must use the equals sign as a means of preventing parentheses from being interpreted as an argument in examples like
$DEFINE(A=(x))
This expands to `(x)'.
A completely equivalent shorthand notation for $DEFINE
is
$M
.
$DO
: Macro do loop
`$DO(macro,imin,imax[,di]){...}' repetitively defines
macro as would the FORTRAN statement do macro =
imin,imax,di
. For example,
$DO(I,0,2) { a[I] = I; }
generates the three statements
a[0] = 0; a[1] = 1; a[2] = 2;
In general, the macro name used as loop counter should not be
explicitly defined as a macro prior to the $DO
. If it is not, it
will remain undefined after the end of the iteration.
Instead of the delimiting braces, parentheses may be used. These may be useful to help FWEAVE format certain constructions correctly.
Nested delimiters are handled correctly. The delimiters are required even if only a single statement is to expanded.
$DO
is implemented in terms of a command $UNROLL
.
However, if one says `$DUMPDEF($UNROLL(0,5,1))', it will respond
that $UNROLL
is not an FWEB macro. Rather, $UNROLL
is
processed like expandable commands in RATFOR such as while
.
This implies that it cannot be redefined as ordinary macros or built-in
functions can be.
$DUMPDEF
: Dump macro definitions to the terminalIn the call `$DUMPDEF'(m1, m2, ...), m1, m2, and so on are macro calls (with arguments if appropriate). Two lines of output are generated for each argument. Line 1 is the macro definition; line 2 is its expansion using the provided arguments.
One can use this built-in to debug one's own macros, or to find out the secrets of FWEB's built-ins.
As an example, if one says
$DUMPDEF($EVAL(2^^4))@%
it responds with the two lines
$EVAL($0) = $$EVAL($0) $EVAL(2**4) = 16
(The $n
notation indicates the n-th argument of the macro.)
If one replaces $EVAL
with $$EVAL
in the above
$DUMPDEF
, it will respond
$$EVAL($0) = <built-in> $$EVAL(2**4) = 16
The purpose of code such as `$EVAL($0) = $$EVAL($0)' is to ensure
that the argument of $EVAL
is expanded if it contains macros; the
primitive function $$EVAL
does not do that expansion
automatically.
Names indicated as `<built-in>' by $DUMPDEF
may be redefined
as ordinary macros, but this is in general a very bad idea; other
parts of FWEB may mysteriously stop working.
$E
: Base of natural logarithmsThe expression `$E' returns e, the base of the natural logarithms, to the default machine precision. The expression `$E(iprec)' returns e to the decimal precision iprec (which must be less than 50).
$ERROR
: Send error message to output`$ERROR(string)' prints an error message in FWEB's standard form.
$EVAL
: Evaluate a macro expression`$EVAL(expression)' uses FWEB's macro-expression evaluator (see section Preprocessing) to reduce the macro expression to its simplest form. An attempt to perform arithmetic on combinations of non-macro identifiers and numbers generates a warning message.
$EXP
: Exponential function$GETENV
: Get value of environment variable`$GETENV(name)' returns a string consisting of the current value of the environment variable name. (Under VMS, logical names behave like environment variables.)
The argument to $GETENV
need not be a string (double-quoted), but
it may be if necessary to avoid the expansion of a macro.
Header
Equivalent to `$KEYWORD(Header)'. See section $KEYWORD
: Value of RCS-like keyword.
$HOME
: The user's home directory`$HOME' is a convenience macro equivalent to `$GETENV(HOME)'.
$ID
: Value of RCS keyword Id
Equivalent to `$KEYWORD(Id)'. See section $KEYWORD
: Value of RCS-like keyword.
$IF
: Two-way conditional
$IF
is a primitive function (not a macro) that is the code-part
version of `@#if'.
The syntax is `$IF(expr, action-if-true, action-if-false)'.
The expr is an FWEB macro expression that must reduce to 0
(false) or 1 (true). First that argument is expanded. If it is true,
action-if-true is expanded; otherwise action-if-false is expanded.
There may be peculiarities with this and the other built-in $IF
function having to do with the order of expansion when the actions
contain macros whose arguments themselves are macros. Therefore, do not
use them unless absolutely necessary.
Do not redefine $IF
or any other built-in conditionals, as they
are used internally to FWEB.
$IFCASE
: n-way conditionalThis primitive built-in behaves like TeX's `\ifcase' command. The syntax is `$IFCASE(expr, case-0, case-1, ..., case-n-1, default)'. If expr reduces to an integer between 0 and n-1, inclusively, the appropriate case is selected; otherwise, the default case is selected.
As examples,
$IFCASE(2, zero, one, two, default) => `two' $IFCASE(2, zero, one, three) => `three' $IFCASE(2, zero, one) => `one'
$IFDEF
: Two-way conditionalThis built-in primitive is the code-part version of `@#ifdef'. The syntax is `$IFDEF(macro, action-if-defined, action-if-not-defined)'.
$IFNDEF
: Two-way conditionalThis built-in primitive is the code-part version of `@#ifndef'. The syntax is `$IFNDEF(macro, action-if-not-defined, action-if-defined)'.
$IFELSE
: Two-way conditionalThe syntax of this built-in primitive is `$IFELSE(expr1, expr2, action-if-equal, action-if-not-equal)'. The expansions of expr1 and expr2 are compared on a byte-by-byte basis. If they are equal, the first action is taken, otherwise the second action is taken.
For example,
$M(S="abc")@% $IFELSE("abc", S, yes, no)
evaluates to `yes'.
$INCR
: Increment a macro`$INCR(N)' redefines the numeric macro N to be one greater than its previous value. (If N does not simplify to a number, an error results.) In other words, in the language of C the effect is to say `N++'.
The two-argument form `$INCR(N,m)' executes the equivalent of `N += m'.
$INPUT_LINE
: Line number that begins current section
`$INPUT_LINE' is the number of the line in the web
source file
that begins the current section (not the source line in which the
$INPUT_LINE
command appears). Compare $OUTPUT_LINE
,
section $OUTPUT_LINE
: Current line number of tangled output.
$KEYWORD
: Value of RCS-like keyword
`$KEYWORD(Keyword)' extracts (as a character string) the text of an
RCS-like keyword
defined in the ignorable commentary between `@z' and `@x' at
the beginning of the code (see section `@z': Begin ignorable material, or terminate change). (RCS stands for
"revision-control system.") The general syntax is (UNIX users,
see man ident
)
$Keyword: text of keyword $
For example,
@z $Author: krommes $ @x @c @ @a char author[] = $KEYWORD(Author);
This tangles to
char author[] = "krommes";
In this example, `$Author' is one of the standard RCS keywords. However, any keyword that fits the syntax `$keyword:contents$' can be accessed by `$KEYWORD'.
For convenience, builtins are defined for some standard RCS keywords. These are
$AUTHOR == $KEYWORD(Author) $DATE_TIME == $KEYWORD(Date) $HEADER == $KEYWORD(Header) $ID == $KEYWORD(Id) $LOCKER == $KEYWORD(Locker) $NAME == $KEYWORD(Name) $RCSFILE == $KEYWORD(RCSfile) $REVISION == $KEYWORD(Revision) $SOURCE == $KEYWORD(Source) $STATE == $KEYWORD(State)
$L
: Change to lower case`$L(string)' changes string to lower case. The argument is first expanded in case it is a macro.
$LANGUAGE
: Identifier for current languageThis expands to an identifier that denotes the current language, as follows:
Language $LANGUAGE C $C C++ $CPP Fortran $N Fortran-90 $N90 Ratfor $R Ratfor-90 $R90 TeX $X VERBATIM $V
Note that this outputs identifiers, not FWEB macros. They are intended
to be used in $IF
or $IFELSE
statements such as
$IF($LANGUAGE==$C, C-text, other-text)
For multiway switches, the $LANGUAGE_NUM
built-in is more useful;
see section $LANGUAGE_NUM
: Number of current language.
$LANGUAGE_NUM
: Number of current language`$LANGUAGE_NUM' expands to an integer that uniquely defines the current language, as follows:
Language $LANGUAGE_NUM C 0 C++ 1 Fortran 2 Fortran-90 3 Ratfor 4 Ratfor-90 5 TeX 6 VERBATIM 7
This built-in is useful in conjunction with an $IFCASE
construction; see section $IFCASE
: n-way conditional.
$LEN
: Length of string`$LEN(string)' returns the length of string in bytes. If string is not surrounded by quotes, it is interpreted as if it were quoted (so it is not expanded if it is a macro). Thus, in the example
@m SS string $LEN(SS)
the value returned is 2, not 5.
$LOCKER
: Value of RCS keyword Locker
Equivalent to `$KEYWORD(Locker)'. See section $KEYWORD
: Value of RCS-like keyword.
$LOG
: Natural logarithm`$LOG(x)' returns the natural logarithm of x.
$LOG10
: Logarithm to the base 10`$LOG10(x)' returns the logarithm to the base 10 of x.
$M
: Define a deferred macro
$M
is equivalent to $DEFINE
. See section $DEFINE
: Deferred macro definition.
$MAX
: Maximum of a list`$MAX(x1,x2,...)' returns the maximum of the list of arguments. (There must be at least one argument.)
$MIN
: Minimum`$MIN(x1,x2,...)' returns the minimum of the list of arguments. (There must be at least one argument.)
$MODULE_NAME
: Name of present web
module
`$MODULE_NAME' returns the name of the present web
module. If the
present module is unnamed, it returns the string "unnamed"
.
$MODULES
: Total number of independent modules`$MODULES' gives the total number of independent modules--that is, the number of independent module names, plus 1 for the unnamed module.
$NAME
: Value of RCS keyword Name
Equivalent to `$KEYWORD(Name)'. See section $KEYWORD
: Value of RCS-like keyword.
$OUTPUT_LINE
: Current line number of tangled output
This returns the current line number of the tangled output. Contrast
this with $INPUT_LINE
, section $INPUT_LINE
: Line number that begins current section.
$P
: The C preprocessor symbol
$P
is (essentially) a synonym for `$UNQUOTE("#")'
(see section $UNQUOTE
: Remove quotes from string). It is useful for constructing FWEB macro
definitions that expand to C preprocessor statements. For example,
@m CHECK(flag) $P if(flag) special code; $P endif
Another version of the preprocessor symbol is $PP
(see section $PP
: The C preprocessor symbol).
For most purposes, $P
and $PP
will behave in exactly the
same way. The difference between them is that $P
is treated as a
string (without surrounding quotes), whereas $PP
is treated as a
character. The character nature of $PP
is used by FORTRAN
to reset the column number to 1, so C-like preprocessor commands appear
there rather than in column 7.
For further discussion of strings and the differences between $P
and $PP
, see section Strings and quotes.
$PI
: PiThe expression `$PI' returns to the default machine precision. The expression `$PI(iprec)' returns to the decimal precision iprec (which must be less than 50).
$POW
: Exponentiation
`$POW(x,y)' generates
(It is a macro defined in terms of $EVAL
and the exponentiation
operator.)
$PP
: The C preprocessor symbol
$PP
is shorthand for `$UNSTRING($P)' (see section $P
: The C preprocessor symbol), or
(essentially) a synonym for `$UNSTRING("#")' (see section $UNSTRING
: Convert string into characters).
It is useful, particularly in FORTRAN, for constructing FWEB
macro definitions that expand to C preprocessor statements. For an
example, see section $P
: The C preprocessor symbol. For a detailed discussion of the difference
between `$P' and `$PP', see section Strings and quotes.
$RCSFILE
: Value of RCS keyword $RCSfile
Equivalent to `$KEYWORD(RCSfile)'. See section $KEYWORD
: Value of RCS-like keyword.
$REVISION
: Value of RCS keyword Revision
Equivalent to `$KEYWORD(Revision)'. See section $KEYWORD
: Value of RCS-like keyword.
$ROUTINE
: Current function (RATFOR only)
When RATFOR is the current language, $ROUTINE
expands to a
string built of the name of the current program, function, or
subroutine. This function is not useful for other languages, for which
it expands to the null string.
$SECTION_NUM
: Number of current FWEB section
`$SECTION_NUM' returns an integer greater than 0 that is the
integer number of the current web
section. (This is not the
LaTeX section number such as 3.4.)
$SECTIONS
: Maximum section number`$SECTIONS' is the maximum section number as understood by FWEAVE.
$SOURCE
: Value of RCS keyword Source
Equivalent to `$KEYWORD(Source)'. See section $KEYWORD
: Value of RCS-like keyword.
$SQRT
: Square root
`$SQRT(x)' returns
It is a convenience macro defined in terms of $POW
. See section $POW
: Exponentiation.
$STATE
: Value of RCS keyword State
Equivalent to `$KEYWORD(State)'. See section $KEYWORD
: Value of RCS-like keyword.
$STRING
: Expand, then stringize`$STRING(s)' expands its argument if it is a macro, then makes the expansion into a quoted string. If the argument is already a quoted string, it is returned unchanged.
$STUB
: Trap for missing module
When a missing module is detected, FTANGLE inserts the command
`$STUB(module_name)' into the output code. The built-in
$STUB
expands to a function call appropriate to the current
language. For example, in C it expands to `missing_mod', in
FORTRAN it expands to `call nomod'.
$TIME
: The time
`$TIME' returns a string consisting of the local time in the form
"19:59"
.
$TRANSLIT
: TransliterationThe macro `$TRANSLIT(s, from, to)' interprets each of its arguments as strings (without expanding anything). Then `s' is modified by replacing any of the characters found in `from' by the corresponding characters in `to'. If `to' is shorter than `from', then the excess characters in `from' are deleted from `s'. As a limiting case, if `to' is empty, then all the characters in `from' are deleted from `s'. For example, `$TRANSLIT(s, aeiou, 12345)' replaces the vowels in `s' by the corresponding digits, and `$TRANSLIT(s, aeiou, )' deletes all the vowels. The backslash may be used to escape a character, as in ANSI C. For example, `$TRANSLIT("a\\"\\\\d", "d\\\\a\\"", "D,A'")' translates into `A',D'. Here one had to explicitly enclose strings involving `\\"' in double quotes in order to avoid a complaint about an unterminated string.
$U
: Change to upper case`$U(string)' changes string to upper case.
$UNDEF
: Undefine a macro`$UNDEF(macro)' undefines an FWEB macro.
$UNQUOTE
: Remove quotes from string`$UNQUOTE(string)' returns string without its surrounding quotes. (However, the resulting construction is still treated as a string; no macro expansion is done.)
For a more detailed discussion and a comparison with $UNSTRING
(see section $UNSTRING
: Convert string into characters), see section Strings and quotes.
$UNSTRING
: Convert string into characters`$UNSTRING(string)' removes quotes from the string, if they are present, and treats the result as a collection of characters. No tokenization is done, so macro expansion does not operate on those characters.
For a more detailed discussion and a comparison with $UNQUOTE
(see section $UNQUOTE
: Remove quotes from string), see section Strings and quotes.
$VERBATIM
: (Obsolete)
This was an old name for $UNQUOTE
(see section $UNQUOTE
: Remove quotes from string). Please
remove all references to this macro from existing codes.
$VERSION
: Present FWEB version number
`$VERSION' returns a string built out of the FWEB version
number, such as "1.60"
.
If an FWEB macro expands to more than one output line, debugging
can be a bit confusing if the debugger (e.g., gdb
) displays lines
in the web
source file instead of the output file (as it normally
does for C and C++). While single-stepping through the code, the
debugger will incorrectly step the screen display for each output line
even if the macro call occupies just one line in the source file. To
localize the debugger's confusion, insert a `@#line' command after
the macro call. For example,
@c @ Example of a macro that expands to several output lines. @m UPDATE(i, delta_i) i += delta_i; store(i)@; @a main() { UPDATE(j, 5); @#line // More code. The debugger will be in sync from here on. }
An alternative for highly confusing situations is to use the `-#' option (see section `-#': Turn off comments about line and section numbers (FTANGLE)).
Another potentially confusing situation occurs when `@%' is used to comment out a line. FWEB deals with the line-number problem that arises here automatically; see section `-T#': Don't insert `#line' command after `@%'.
Generally, the FWEB preprocessor commands follow a syntax identical to their C/C++ counterparts. The one exception is the `@#line' command. Whereas the C command takes a line number and file name as arguments, the FWEB command takes no arguments; its expansion automatically inserts the current line number and file name. This command should be necessary only in rare circumstances. One of those involves situations in which an FWEB macro expands to more than one output line; see section Debugging with macros.
The FWEB preprocessor commands may appear in either the definition or the code parts. But BEWARE: No matter where they appear, they are expanded during INPUT, not output. (This is probably a design flaw.) For more discussion, see section FWEB macros.
The syntax of each command is as follows:
@#line -- Insert a #line
command.
@#define identifier -- Define an FWEB macro; equivalent to `@m'.
@#undef identifier -- Undefine an FWEB macro.
@#ifdef identifier -- Is FWEB macro defined? Equivalent to
`@#if defined identifier'.
@#ifndef identifier -- Is FWEB macro not defined? Equivalent to
`@#if !defined identifier'.
@#if expression
@#elif expression
@#else
@#endif
In the `@#if' statement, the expression may contain FWEB macros, but must ultimately evaluate to a number. If that number is zero, the expression is false; otherwise, it is true.
The expression following constructions such as `@#if' is
evaluated by a built-in expression evaluator that can also be used for
other purposes, such as in macro expansion. Its behavior is again
motivated by expression
evaluation in ANSI C; it is not quite as general, but should be more than
adequate. (One design flaw that will be fixed someday is that the order
of expression evaluation is not necessarily left-to-right, as it is in C.)
It supports both integer and floating-point arithmetic (with type
promotion from integer to floating-point if necessary), and the ANSI
defined
operator. Operators with the highest precedence
(see table below) are evaluated first; as usual, parentheses override the
natural order of evaluation. The unary operator defined
has the highest
precedence; all the other unary operators have the next highest (and equal)
precedence; then come the binary operators. When the operator exists in C,
the action taken by FWEB is precisely that that the C compiler would take.
Arithmetic is done in either long or double variables, as
implemented by the C compiler that compiled FTANGLE. (This was the
easy choice, not necessarily the most desirable one.)
The operators, listed from highest precedence to lowest, are as follows (printed documentation only):
Go to the first, previous, next, last section, table of contents.