GDOC - C Documentation Tool

This page explains the documentation tool I use in Libidn, GNU SASL, Shishi and other projects. It is based on an old version of GNOME's GTK-DOC tools, but (I believe) I first noticed it from how it was used in GNUTLS. My memory may be incorrect though.

The features include:

For examples of the kind of results you may get, see the Libidn manual page, GNU SASL manual page, or Shishi manual page.

Begin by downloading gdoc.

Then start to comment your source code. See the comments in 'gdoc' for the full story, but here is an example:

/**
 * stringprep_utf8_to_locale:
 * @str: input zero terminated string.
 *
 * Convert string encoded in UTF-8 into the locale's character set by
 * using stringprep_convert().
 *
 * Return value: Returns newly allocated zero-terminated string which
 *   is @str transcoded into the locale's character set.
 **/
char *
stringprep_utf8_to_locale (const char *str)
{
  return stringprep_convert (str, stringprep_locale_charset (), "UTF-8");
}

You can then extract Man pages, Texinfo fragments, etc, using 'gdoc' as follows:

$ gdoc -texinfo file.c
@deftypefun {char *} {stringprep_utf8_to_locale} (const char * @var{str})
@var{str}:  input zero terminated string.
 
Convert string encoded in UTF-8 into the locale's character set by
using @code{stringprep_convert()}.
 
@strong{Return value:}  Returns newly allocated zero-terminated string which
is @code{str} transcoded into the locale's character set.
@end deftypefun

$

To simplify generating Texinfo fragments or Man pages for your entire project -- which might contain many files, each contain many functions, that would result in lots of boring Makefile rules to keep track of -- I use a Automake 'include' file to simplify matters.

In this example, I assume you are already building a texinfo manual from Makefile.am, e.g.:

info_TEXINFOS = libidn.texi
libidn_TEXINFOS = fdl.texi example.c.texi

Now to use GDOC generated output in your manual, add Makefile.gdoci to your project, and change the above into:

info_TEXINFOS = libidn.texi
libidn_TEXINFOS = fdl.texi example.c.texi $(gdoc_TEXINFOS)

GDOC_SRC = $(top_srcdir)/lib/*.c
GDOC_TEXI_PREFIX = texi/
include $(srcdir)/Makefile.gdoci

You should also add the following to configure.ac so that people that doesn't have perl get a friendly error message.

AM_MISSING_PROG(PERL, perl, $missing_dir)

Currently you also have to make sure Makefile.gdoc exists (0 byte file is fine) when you invoke Automake.

When you re-run make, it will build Texinfo fragments for all documented functions in GDOC_SRC. Note that using wildcards is fine, the makefile takes care of turning that into explicit filenames.

You can then use such fragments within your Texinfo manual as follows:

@node Version Check
@section Version Check

It is often desirable to check that the version of `Libidn' used is
indeed one which fits all requirements.  Even with binary
compatibility new features may have been introduced but due to problem
with the dynamic linker an old version is actually used.  So you may
want to check that the version is okay right after program startup.

@include texi/stringprep_check_version.texi

The normal way to use the function is to put something similar to the
following first in your @code{main}:

This will result in the following Texinfo HTML output:

Version Check

It is often desirable to check that the version of `Libidn' used is indeed one which fits all requirements. Even with binary compatibility new features may have been introduced but due to problem with the dynamic linker an old version is actually used. So you may want to check that the version is okay right after program startup.

const char * stringprep_check_version (const char * req_version) Function
req_version: Required version number, or NULL.

Check that the the version of the library is at minimum the requested one and return the version string; return NULL if the condition is not satisfied. If a NULL is passed to this function, no check is done, but the version string is simply returned.

See STRINGPREP_VERSION for a suitable req_version string.

Return value: Version string of run-time library, or NULL if the run-time library does not meet the required version number.

The normal way to use the function is to put something similar to the following first in your main:

You can also generate man pages with gdoc. Consider if your Makefile.am look like:

dist_man_MANS = idn.1
MAINTAINERCLEANFILES = $(dist_man_MANS)

idn.1: $(top_srcdir)/src/idn.c
	$(HELP2MAN) \
		--name="Internationalized Domain Names command line tool" \
		--output=$@ $(top_builddir)/src/idn

Alter this into, e.g.:

dist_man_MANS = idn.1 $(gdoc_MANS)
MAINTAINERCLEANFILES = $(dist_man_MANS)

idn.1: $(top_srcdir)/src/idn.c
	$(HELP2MAN) \
		--name="Internationalized Domain Names command line tool" \
		--output=$@ $(top_builddir)/src/idn

GDOC_MAN_PREFIX = man/
GDOC_MAN_EXTRA_ARGS = -module $(PACKAGE) -sourceversion $(VERSION) \
	-bugsto $(PACKAGE_BUGREPORT) -includefuncprefix -seeinfo $(PACKAGE) \
	-copyright "2002, 2003 Simon Josefsson" -verbatimcopying
include $(srcdir)/Makefile.gdoci

Note however that you should only include Makefile.gdoci once.

A sample man page may look like the following. It looks better in 'man' though, with bold colors etc -- see nroff source if you are interested.

gsasl_check_version(3)               GSASL              gsasl_check_version(3)

NAME
       gsasl_check_version

SYNOPSIS
       #include <gsasl.h>

       const char * gsasl_check_version(const char * req_version);

ARGUMENTS
       const char * req_version
                   version string to compare with, or NULL

DESCRIPTION
       Check library version.

RETURN VALUE
       Check  that  the the version of the library is at minimum the one given
       as a string in req_version and return the actual version string of  the
       library; return NULL if the condition is not met.  If NULL
        is  passed  to  this  function  no  check is done and only the version
       string is returned.  It is a pretty good idea to run this  function  as
       soon as possible, because it may also intializes some subsystems.  In a
       multithreaded environment if should be called before any  more  threads
       are created.

REPORTING BUGS
       Report bugs to <bug-gsasl@josefsson.org>.

COPYRIGHT
       Copyright (C) 2002, 2003 Simon Josefsson.
       Permission  is  granted to copy, distribute and/or modify this document
       under the terms of the GNU Free Documentation License, Version  1.1  or
       any later version published by the Free Software Foundation.

SEE ALSO
       The full documentation for Gsasl is maintained as a Texinfo manual.  If
       the info and gsasl programs are properly installed at  your  site,  the
       command

              info gsasl

       should give you access to the complete manual.

GNU                               2003-10-15            gsasl_check_version(3)

A final Makefile.am might look like:

EXTRA_DIST = gdoc libidn.html libidn.ps libidn.pdf

info_TEXINFOS = libidn.texi
pdf_TEXINFOS = libidn.texi
ps_TEXINFOS = libidn.texi

libidn_TEXINFOS = fdl.texi $(gdoc_TEXINFOS) example.c.texi

dist_man_MANS = idn.1 $(gdoc_MANS)
MAINTAINERCLEANFILES = $(dist_man_MANS)

idn.1: $(top_srcdir)/src/idn.c
	$(HELP2MAN) \
		--name="Internationalized Domain Names command line tool" \
		--output=$@ $(top_builddir)/src/idn

GDOC_SRC = $(top_srcdir)/lib/*.c
GDOC_TEXI_PREFIX = texi/
GDOC_MAN_PREFIX = man/
GDOC_MAN_EXTRA_ARGS = -module $(PACKAGE) -sourceversion $(VERSION) \
	-bugsto $(PACKAGE_BUGREPORT) -includefuncprefix -seeinfo $(PACKAGE) \
	-copyright "2002, 2003 Simon Josefsson" -verbatimcopying
include $(srcdir)/Makefile.gdoci

The following is also possible but is not discussed here yet. If you are interested, see the libidn project CVS doc/ sub-directory.