Cfunctions

Ben K. Bullock


Copying

Cfunctions and this manual are copyright (C) 1998 Ben K. Bullock. Some parts of the Cfunctions distribution, the files in the subdirectory `missing', are copyright (C) 1997 by the Free Software Foundation (see the actual files for details).

Cfunctions, and this manual, are free software under the GNU General Public Licence (otherwise known as the GNU GPL or just the GPL. The GNU General Public Licence is in the file `COPYING' in the Cfunctions distribution directory. The GNU General Public Licence does not apply to the output of Cfunctions. The file `c-extensions.h', which is used with Cfunctions, is licenced differently. Please refer to that file for more information.

Because of the small size of this manual the GNU General Public Licence is not included.

You can find the GNU General Public License at The Free Software Foundation .

Introduction

This is the manual for Cfunctions version @version {}. This manual explains Cfunctions, a program for making header files from C files. Cfunctions (pronounced "see-functions") gets function declarations, prototypes and global (otherwise known as external) variable declarations from C files and makes them into header files.

Simple examples

Here are some simple examples of how to run Cfunctions. If you have already compiled the program, you might like to try it out on some C files using the following examples as a template.

Detailed examples

This section gives some examples that you can type in to Cfunctions using it as a pipe, reading standard input.

Input some C to Cfunctions, for example

int func (int y) { return 0; }

and Cfunctions outputs

int func (int y);

the function declaration. Now try

int z;

Cfunctions outputs

extern int z;

This is a declaration of the variable z suitable for use in a header file. Now input

extern int z;

to Cfunctions. Cfunctions outputs nothing, because extern means z was declared elsewhere, so it should not be declared in a header file. Now input

static int q; 
static char * tub (int jub) { return array[ jub ]; }

Cfunctions outputs nothing. That is because both q and tub are declared with static. Cfunctions assumes that it is writing a header file, so it doesn't output anything declared static.

Now, try cfunctions --wrap chap, with input

int s, t, u;
char * func() { return "junk"; }

Cfunctions outputs

#ifndef _CHAP
#define _CHAP
extern int s, t, u;
char * func();
#endif /* _CHAP */

because the -w chap option requested a wrapper See section Wrappers. This is already enough to declare the external variables and functions in the input file and write them out to a header file.

Invoking Cfunctions

Cfunctions can be configured with a file `.cfunctionsrc' in your home directory. The possible command-line and configuration options for Cfunctions are

-a argument
--advert argument
If argument is `off', don't print an advert. If argument is a file name, print the file instead. See section Advertisements and banners. You can also control this with a line `advert' in `.cfunctionsrc'
-b
--backup
Back up `.h' files. See section Backups. You can also control this with a line `backup' in `.cfunctionsrc'
-c
--copy-c-ex
Copy the `c-extensions.h' into the header file. See section C extensions. You can also control this with a line `copy c ex' in `.cfunctionsrc'
-C
--cpp
Pass input through the C preprocessor. See section Using Cfunctions with the C preprocessor.
-D argument
--debug argument
Set debugging option argument.
-e
--etags
Create an Emacs tag table.
-g argument
--global argument
Write one global header for all C files. See section Making one header for several C files.
-G argument
--global-macro argument
Give global header macro the name argument. See section Extra header information. You can also control this with a line `global macro' in `.cfunctionsrc'
-h
--help
Print a help message and exit.
-I
--include-c-ex
Write #include <c-extensions.h>. See section C extensions. You can also control this with a line `include c ex' in `.cfunctionsrc'
-i
--individual
Write an individual header for each C file. See section Making a separate header for each C file.
-k
--keep
Don't delete generated .h files which are empty.
-l argument
--local argument
Write one local header file for all C files. See section Extra local information.
-L argument
--local-macro argument
Give local header macro the name argument. See section Extra local information. You can also control this with a line `local macro' in `.cfunctionsrc'
-m
--write-comments
Write comments to header file. See section Comments. You can also control this with a line `write comments' in `.cfunctionsrc'
-n
--line-numbers
Write #line information in the .h files. See section C compiler. You can also control this with a line `line numbers' in `.cfunctionsrc'
-o argument
--output argument
Redirect standard output to argument. See section Output files.
-P argument
--cpp-arg argument
Pass argument to the C preprocessor. See section Using Cfunctions with the C preprocessor.
-p argument
--proto-macro argument
Give prototype macro the name argument. See section Traditional C. You can also control this with a line `proto macro' in `.cfunctionsrc'
-s
--static
Don't ignore things declared `static'. See section static.
-S argument
--suffix argument
Use suffix `argument' for simple backups. See section Backups. You can also control this with a line `backup suffix' in `.cfunctionsrc'
-t
--tags
Create a tag table. See section Making tag tables.
-v
--version
Write version information and exit.
-V argument
--version-control argument
Use version control style argument. See section Backups. You can also control this with a line `version control' in `.cfunctionsrc'
-W argument
--warn argument
Warn about malpractices. See section Warnings. You can also control this with a line `warn' in `.cfunctionsrc'
-w argument
--wrap argument
Write a wrapper when writing to stdout. See section Wrappers.
-x
--extensions
Don't copy the `c-extensions.h' file. See section Input file format.

Variable and function declarations

This chapter explains how to make Cfunctions generate correct variable and function declarations.

Global variables

Cfunctions gets global variables from C files and writes them with an extern prefix. For example,

int x;

becomes

extern int x;

It does not prefix functions with extern, because there is no point in doing so.

Using struct, union, and enum

Cfunctions writes out struct, union and enum declarations by copying the declaration. For example

struct bee gee;

becomes

extern struct bee gee;

in Cfunctions's output.

struct, union, enum body

Cfunctions does not write the body (part between { and }) of unions, structs and enums. Even if the declaration of a variable contains a definition of a data structure, Cfunctions does not write the data structure's definition. For example,

struct heeby { int x, y; unsigned z; } geeby;

becomes

extern struct heeby geeby;

which will not be understandable to compilers, because struct heeby was not declared: you will get an error message about the `incomplete type'. To avoid this problem, declare structure instances such as geeby in the above with static so that Cfunctions ignores them. When you want a global instance of a structure like geeby, ask Cfunctions to copy the body as well. See section Extra header information.

Untagged structs

Cfunctions ignores untagged structures such as

struct {int a} d; 

except when copying verbatim. See section Extra header information.

typedef

Cfunctions ignores typedef statements except when copying verbatim. See section Extra header information.

Arrays

Cfunctions outputs one dimensional array declarations with the array's size removed. For example,

int mung[N_MUNG];

becomes

extern int mung[];

However C does not allow multidimensional arrays with any but the first dimension removed. Therefore for example Cfunctions writes

int mung_sq[N_MUNG][N_MUNG];

as

extern int mung_sq[][N_MUNG];

N_MUNG might be a macro defined only in the C file Cfunctions read the declaration from, and the C compiler would choke on this declaration. Cfunctions does not check that an array's dimensions are valid, it merely copies them, so users must use array dimensions which remain valid in the header file.

static

Cfunctions usually ignores static functions and variables . To make forward declarations for static C functions, or to make a tag table which includes them, use the --static (-s) option.

Traditional C

Cfunctions can also make prototype declarations for traditional C files. (Traditional C is the language described in edition 1 of Kernighan and Ritchie's book `The C programming language'.) For traditional C files, Cfunctions writes a macro around the prototype function arguments. You then have to define this macro to give either prototype arguments (for an ANSI C compiler) or nothing (for a traditional C compiler). For example

int func (x, y, v)
    unsigned long y;
    char * v;
{
  ...

becomes

int func PROTO((/* default */ int x, unsigned long y, char * v));

Then for the traditional case PROTO is defined as

#define PROTO(x) ()

and for the ANSI C case PROTO is defined as

#define PROTO(x) x

which in the above example gives you either

int func (); /* traditional */

or

int func (/* default */ int x, unsigned long y, char * v); /* ANSI */

By default the macro is called PROTO, but you can change the macro name to xxx with the --proto-macro xxx (-pxxx) option.

The macro PROTO is defined in `c-extensions.h' (see section Input file format). If you change the macro name, you also need to ensure that your new macro name is defined.

If you always want to use a different prototype name such as xxx, add a line containing the name, such as

proto macro: xxx

to a file called `.cfunctionsrc' in your top level or home directory.

Comments

To copy the comments in the C file into the header file, use the --write-comments (-m) option. This makes Cfunctions copy the most recently read comment verbatim into the output whenever it writes a declaration.

Cfunctions understands C++ style // comments. GNU C allows C++ style comments and they are quite commonly used in C files, so Cfunctions is able to understand them.

Warnings

Cfunctions can warn about some kinds of problems in the input files. These warnings are optional. To get the warnings, use the --warning (-W) option together with one of the following:

implicit
Warn about implicit int functions and function arguments.
implicit-int
The same as implicit
reserved
Warn about the use of any reserved words.
strict-prototypes
Warn about any functions which don't have prototypes.

Some of the warning names are based on those of GNU C, but the things that Cfunctions warns about are not the same things as the warnings of GNU C.

If you always want to be warned about any of the above practices, put a line such as

warn: implicit strict-prototypes

to a file called `.cfunctionsrc' in your top level or home directory.

Output files

You can invoke Cfunctions with a list of C files as arguments. Without arguments, Cfunctions reads from standard input and writes to standard output. You can redirect this with the --output argument (-oargument) command line option, where argument is the name of the output file.

Making one header for several C files

To write information from several C files into one header file, use the command line option --global argument (-gargument). The argument is the base name of the header file. For example,

cfunctions --global x a.c b.c c.c

will generate a header file called `x.h' containing information from `a.c', `b.c' and `c.c'.

To include extra information in the global header which is not in any of the C files, create a file called `name.hin' where name is the argument to --global. Cfunctions copies verbatim the contents of this file after the beginning wrapper (see section Wrappers).

Making a separate header for each C file

The option --individual (-i) makes Cfunctions write a separate header file for each C file argument. The name of the header file is the C file name with an `.h' suffix instead of `.c'. For example,

cfunctions -i jub.c hub.c

creates `jub.h' and `hub.h'.

To generate both `local' headers for each C file and a global header, use the --individual and --global options together in conjunction with LOCAL and LOCAL_H directives in your C files. See section Making `local' headers.

Backups

Cfunctions does not change C files, but it may overwrite files with a `.h' suffix. The option --backup makes Cfunctions rename old files rather than overwrite them.

If one uses this option, Cfunctions usually renames old files with a ~ suffix. You can change the suffix with the command line option --suffix argument (-Sargument) where argument is the suffix to use, or by the environment variable SIMPLE_BACKUP_SUFFIX. Numbered backups are also possible. The command line option --version-control argument (-V argument) switches this on. The possible values of argument are

t, numbered
make numbered backups
nil, existing
numbered if numbered backups exist, simple otherwise
never, simple
always make simple backups

Putting the same strings into the environment variable VERSION_CONTROL has the same effect, and also causes the same behaviour in GNU programs such as Emacs, Indent, Patch, and the GNU fileutils. Refer to, for example, the GNU Emacs manual, section `Backup Names', for more details.

Advertisements and banners

Cfunctions usually advertises itself at the top of generated files. To turn this advertisement off, use the option --advert off (-aoff). To substitute another banner, use --advert file-name where file-name is the name of the file containing your information. Cfunctions will copy it verbatim, so don't forget to put text inside C comments.

If you always want to put the same text at the top of each generated header file, add a line containing the file you wish to have copied, such as

advert: /home/me/mydirectory/mycopyright

to a file called `.cfunctionsrc' in your top level or home directory.

Wrappers

Cfunctions usually writes a `wrapper' around header files so that they will not be read twice. For example, cfunctions -i jub.c will generate

#ifndef CFH_JUB_H
#define CFH_JUB_H
...
#endif /* CFH_JUB_H */

Cfunctions does not write wrappers when writing to standard output. To force wrappers, use the option --wrap argument (-w argument). Cfunctions converts argument to upper case and removes bad characters, and then uses it as the macro, CFH_JUB_H in the above example.

Making tag tables

A tag table is an index of functions and external variables. The reason that Cfunctions also makes this file is that a tag table for a C file consists of a list of global variables and function definitions, although in a different format to a header file. The tag table also includes type definitions, data structures, C unions and enumeration constants. Cfunctions understands #line instructions and it will adjust the tag table output accordingly.

Spacing

Cfunctions does not preserve decorative spacing. Cfunctions uses only a single space for all spacing within a particular prototype. In fact, Cfunctions has no facilities for formatting its output to a particular taste. To reformat the generated header files according to your tastes, use an indenting program such as GNU indent.

Input file format

Cfunctions does not require any particular C file format. However some extra facilities of Cfunctions require formatted input files. The formats do not affect compilation. The formats are designed so that Cfunctions never needs to alter C files.

If you use Cfunctions's special features, Cfunctions automatically writes

#include "c-extensions.h" 

into your generated header file. The file `c-extensions.h' contains definitions of macros which make the special features such as C extensions work both with compilers with the C extensions, and without them.

Cfunctions also usually copies the file itself into the current directory. You can prevent this with the --extension (-x) option.

If you prefer the following type of statement,

#include <c-extensions.h>

use the --include-c-ex (-I) command line option. In this case Cfunctions will never copy the file into the current directory, since that would be useless: you should instruct the C compiler where to find the file (this may be with the -I option, hence the short option name in Cfunctions is mnemonic).

Note that the file `c-extensions.h' is not under the GNU General Public Licence. It does not have any restrictions on its use. Whatever licencing terms your program is under, you can incorporate `c-extensions.h' into it.

C extensions

Cfunctions understands several GNU C extensions. See Info file `gcc.info', node `C extensions', to find out about the GNU C extensions. The following prefixes to functions get GNU C extensions in the generated header file:

NO_RETURN
Cfunctions writes a GNU C __attribute__((noreturn)) suffix in the prototype. It is a macro defined to void.
NO_SIDE_FX
Cfunctions writes a GNU C __attribute__((const)) suffix to the prototype. It is an empty macro.
INLINE
See section Inlining functions.
PRINT_FORMAT(a,b)
Cfunctions writes a GNU C __attribute__((format(printf,a,b))) suffix in the prototype. It is an empty macro.

Extra header information

To include material directly into the header file, surround it with #ifdef HEADER ... #endif. For example,

#ifdef HEADER
typedef struct dictionary Dictionary;
#endif

Cfunctions just copies everything between the #ifdef and the #endif into the header file. Because a macro HEADER is not usually defined, the C compiler ignores this material in the C file. (If by chance a macro HEADER is already defined, change the macro name Cfunctions recognizes with the --global-macro argument (-Gargument) option, where argument is a macro name to use instead of HEADER.)

Making `local' headers

When using the --global option, you may want to share some function declarations only with a few specific files. For example, suppose that a library lib is created from jub.c and hub.c but that only hub.c should use the function private from jub.c, not lib library users. To hide the private function by not putting its prototype into the library header lib.h, make a local header for jub.c by

cfunctions -g lib -i jub.c hub.c

This creates jub.h and hub.h as well as lib.h. To make the prototype of private appear in jub.h and not in lib.h, prefix private with LOCAL, and the prototype for private will appear in `jub.h'. LOCAL is a C macro defined to nothing by the `c-extensions.h' header file (see section C extensions).

To make just one `local' header file to share between `jub.c' and `hub.c' use

cfunctions -g lib -l private jub.c hub.c

This will create files `lib.h' and `private.h'. The declaration of private will go into `private.h' and not into `lib.h'.

Extra local information

To include information verbatim into a local header file use LOCAL_H preprocessor wrapper in the same way as #ifdef HEADER (see section Extra header information) If by chance a macro LOCAL_H is already defined, change the name LOCAL_H used for the wrapper with the option --local-macro argument, where argument is the name of the new macro.

The option --local argument (-largument) sends all the `local' header output from each C file to one header file instead of several. Contrast this with --individual (-i) which generates several header files, one for each input C file. The argument is the base name of the local header file.

Inlining functions

In GNU C, a function can be declared inline. Refer to the GNU C manual for details. However, GNU C cannot `inline' a function in a separate translation unit from the function body. To work around this restriction, Cfunctions can copy the entire function to a header file so that it can be used over several translation units. It uses the special GNU C prefix extern inline and a wrapper so as not to confuse other compilers.

To get Cfunctions to do this, prefix the function with Cfunctions's keyword INLINE and run Cfunctions. For example,

INLINE int square (int i) 
{
  return i*i;
} 

generates

#ifdef X_INLINE
extern inline int square (int i)
{
  return i*i;
}
#else /* not X_INLINE */
int square (int i);
#endif /* X_INLINE */

in the output header file. Cfunctions's special header file `c-extensions.h' defines the macro X_INLINE for GNU C, but not for other C compilers and it defines the macro INLINE to nothing, so as not to cause portability problems.

Using Cfunctions with other programs

This chapter explains some subtleties of using Cfunctions with other programs.

Using Cfunctions with make

It is possible to use Cfunctions to generate header files with make. There are two ways to do this. One way is to write explicit rules for generating header files in a `Makefile'. For example,

jubs.h:         jubs.c
        cfunctions --individual jubs.c

Another way is to teach make a rule for making header files from C files.

.c.h:   
        cfunctions --individual $<

The disadvantage of the rule method is that it might fool make into making a header file when not required, or even overwriting a non-Cfunctions header file. You definitely should not use this unless all your header files are generated by Cfunctions, and if you do use it, I recommend you to use --backup as well.

When using this kind of rule, a harmless but odd thing will occur. If Cfunctions sees that it has generated a new header file identical to an old one, it keeps the old one and discards the new one. When this happens, make runs Cfunctions again the next time. This might seem like an error, but it is a feature. If Cfunctions did update a header file even when it was identical to an old one, make would then recompile every dependency of that header file (in other words it would recompile all the C files which #included the header file). This would be inconvenient: Cfunctions runs much faster than a C compiler, so it is less inconvenient to run Cfunctions uselessly than to force useless recompilation.

Using Cfunctions with the C preprocessor

There are some coding practices with the C preprocessor which Cfunctions cannot cope with. Either avoid these coding practices or send Cfunctions the output of the C preprocessor by using the --cpp (-C) option. With this option, you can pass arguments to the preprocessor with the --cpp-arg (-P) argument. For example

cfunctions -C -P -DGUBBINS

will send the C preprocessor the argument -DGUBBINS.

Redefined C

Cfunctions cannot possibly process C code which uses macros like

#define begin {

or anything else of the sort.

Mixed ANSI and traditional C declarations

Some people write function declarations as follows:

#if ANSI
int options (int argc, char ** argv)
#else
int options (argc, argv)
    int argc;
    char ** argv;
#endif

This is not necessary, unless your program needs to be compilable by C++ as well as traditional C compilers. ANSI C allows you to write function declarations in either way. Cfunctions cannot currently understand the above syntax, so if you need backwards compatibility just use the old-style function declaration on its own.

Declaring functions via the preprocessor

Some people declare functions via the preprocessor for the sake of convenience. Unfortunately Cfunctions can't parse these functions unless you use the -C option.

C compiler

If there is an error in a header file generated by Cfunctions, the compiler usually writes a message which refers to the line number and file name of the header file. Because the error is actually in the original C file, this is inconvenient.

To make compiler messages refer to lines in a C file and not in a Cfunctions generated header file, use the --write-line-numbers (-n) option. Cfunctions will generate compiler directives of the form

#line number "file.c"

just before it writes each declaration. Here number is the line number of the C file `file.c' that the function or variable came from. The line numbers may be slightly off, because Cfunctions does not preserve the decorative spacing (see section Spacing). However, along, with the compiler message they should be enough to indicate where problems lie.

Particularly this is useful with the GNU Emacs `compile-mode' to go to the lines in the original C file which contain the errors.

Unfortunately this will force Cfunctions to update your header file every time that it is slightly changed, causing possible unnecessary recompilations of associated files.

If you always want to write line numbers in generated header files, add the line

line numbers: 1

to a file `.cfunctionsrc' in your top level directory.

The `fake-cfunctions' script

`fake-cfunctions' is a fake version of Cfunctions which uses `touch' to update header files. The reason for having this is so that one can distribute programs using Cfunctions with `make' rules for generating header files, without getting user complaints. For example in Cfunctions's `configure.in' script for GNU Autoconf there is a test for Cfunctions as follows:

CWD=`pwd`
AC_CHECK_PROG(CFUNCTIONS, cfunctions, cfunctions,
              "$CWD/fake-cfunctions")

then in each `Makefile.in' there is a variable CFUNCTIONS which the `configure' script fills in:

CFUNCTIONS = @CFUNCTIONS@

In the case that the user doesn't have Cfunctions installed, `configure' writes something like (assuming the current working directory is `/tmp/cfunctions-0.24')

CFUNCTIONS = /tmp/cfunctions-0.24/fake-cfunctions

whereas if the user does have Cfunctions, `configure' writes

CFUNCTIONS = cfunctions

`fake-cfunctions' just updates the file's modification time with `touch' in order to fool `make', so it won't work if the user makes major modifications to the C files, but in that case the user should get Cfunctions.

Please note that the `fake-cfunctions' script is not under the GNU GPL and you may use it whatever your licence terms are.

Index

Jump to: # - - - . - / - _ - a - b - c - d - e - f - g - h - i - k - l - m - n - o - p - r - s - t - u - v - w

#

  • #ifdef HEADER
  • #ifdef LOCAL_H
  • #line instructions
  • -

  • --advert
  • --backup
  • --copy-c-ex
  • --cpp
  • --cpp-arg
  • --debug
  • --etags
  • --extensions
  • --global
  • --global-macro
  • --help
  • --include-c-ex
  • --individual
  • --keep
  • --line-numbers
  • --local
  • --local-macro
  • --output
  • --proto-macro
  • --static
  • --suffix
  • --tags
  • --version
  • --version-control
  • --warn
  • --wrap
  • --write-comments
  • -a
  • -b
  • -C
  • -c
  • -D
  • -e
  • -g
  • -G
  • -h
  • -I
  • -i
  • -k
  • -L
  • -l
  • -m
  • -n
  • -o
  • -P
  • -p
  • -S
  • -s
  • -t
  • -V
  • -v
  • -w
  • -W
  • -x
  • .

  • .hin suffix
  • /

  • //
  • _

  • __attribute__((const))
  • __attribute__((format(printf,a,b)))
  • __attribute__((noreturn))
  • a

  • advert, changing
  • arrays
  • arrays, multidimensional
  • b

  • banner, adding your own
  • begin macro
  • body, of struct, union
  • c

  • C extensions
  • C preprocessor
  • C++ style comments
  • C, redefined
  • `c-extensions.h'
  • `c-extensions.h', licence for, `c-extensions.h', licence for
  • copying Cfunctions
  • copyright
  • cpp
  • d

  • decorative spacing, not preserved
  • e

  • enum
  • extern inline
  • extern prefix for global variables.
  • external variables, external variables
  • f

  • `fake-cfunctions'
  • format of output
  • format, for input
  • g

  • global header, extra information into
  • global variables
  • GNU C, C++ style comments allowed
  • GNU General Public Licence
  • GNU GPL
  • GNU GPL, and `c-extensions.h'
  • GNU GPL, and `fake-cfunctions'
  • GNU Indent
  • GPL
  • h

  • HEADER
  • heebygeeby
  • hin suffix
  • i

  • INLINE
  • inline in GNU C
  • input format
  • introduction
  • invocation
  • k

  • Kernighan and Ritchie's book, edition 1
  • l

  • LOCAL prefix
  • LOCAL_H macro
  • m

  • make, explicit rules
  • make, fooling
  • make, teaching patterns
  • multidimensional arrays
  • n

  • NO_RETURN
  • NO_SIDE_FX
  • o

  • one header
  • p

  • PRINT_FORMAT
  • pronunciation
  • PROTO
  • r

  • redefined C
  • s

  • SIMPLE_BACKUP_SUFFIX environment variable
  • static, ignored
  • struct
  • struct body
  • struct, parts copied into header
  • struct, untagged
  • t

  • traditional C
  • typedef
  • u

  • union
  • untagged struct
  • v

  • VERSION_CONTROL environment variable
  • w

  • wrapper
  • wrapper, for stdout output

  • This document was generated on 20 November 1998 using the texi2html translator version 1.52.