Go to the first, previous, next, last section, table of contents.


MACROS and PREPROCESSING

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

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

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.

Various features of FWEB macros

Special tokens

The following special tokens may be used in the text of FWEB macro definitions:

ANSI C-compatible tokens

 ##          -- 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");

Extensions to ANSI C macro syntax

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

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.

Strings and quotes

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),

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 terminal

In 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 logarithms

The 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

`$EXP(x)' returns

$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: Value of RCS keyword 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 conditional

This 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 conditional

This 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 conditional

This 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 conditional

The 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 language

This 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: Pi

The 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: Transliteration

The 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".

Debugging with macros

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 `@%'.

Preprocessing

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.