As in libvirt, allow internal documentation comments in C files.
These are marked using '/**' comments. Unlike libvirt which has an
ill-defined and inconsistent markup, the markup we use is Perl POD.
These comments are added to guestfs-internals(1), but are most likely
to be read in-place.
This commit changes some existing comments in src/launch.c to
demonstrate how this can be used.
---
.gitignore | 1 +
docs/Makefile.am | 15 ++-
docs/guestfs-internals.pod | 9 ++
docs/make-internal-documentation.pl | 234 ++++++++++++++++++++++++++++++++++++
po/POTFILES | 1 +
src/launch.c | 70 +++++++----
6 files changed, 305 insertions(+), 25 deletions(-)
create mode 100755 docs/make-internal-documentation.pl
diff --git a/.gitignore b/.gitignore
index ca4e89c..ff5f2de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -153,6 +153,7 @@ Makefile.in
/docs/guestfs-release-notes.1
/docs/guestfs-security.1
/docs/guestfs-testing.1
+/docs/internal-documentation.pod
/docs/stamp-guestfs-building.pod
/docs/stamp-guestfs-faq.pod
/docs/stamp-guestfs-hacking.pod
diff --git a/docs/Makefile.am b/docs/Makefile.am
index f880e72..f765966 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -27,6 +27,7 @@ EXTRA_DIST = \
guestfs-release-notes.pod \
guestfs-security.pod \
guestfs-testing.pod \
+ make-internal-documentation.pl \
README
CLEANFILES = \
@@ -39,6 +40,7 @@ CLEANFILES = \
guestfs-release-notes.1 \
guestfs-security.1 \
guestfs-testing.1 \
+ internal-documentation.pod \
stamp-guestfs-building.pod \
stamp-guestfs-faq.pod \
stamp-guestfs-hacking.pod \
@@ -105,15 +107,26 @@ stamp-guestfs-hacking.pod: guestfs-hacking.pod
guestfs-internals.1 $(top_builddir)/website/guestfs-internals.1.html:
stamp-guestfs-internals.pod
-stamp-guestfs-internals.pod: guestfs-internals.pod
+stamp-guestfs-internals.pod: guestfs-internals.pod internal-documentation.pod
$(PODWRAPPER) \
--section 1 \
--man guestfs-internals.1 \
--html $(top_builddir)/website/guestfs-internals.1.html \
+ --insert internal-documentation.pod:__INTERNAL_DOCUMENTATION__ \
--license LGPLv2+ \
$<
touch $@
+source_files := $(shell grep -Ev '^(gobject/|builder/index-scan.c)'
$(top_srcdir)/po/POTFILES)
+
+internal-documentation.pod: $(source_files:%=$(top_srcdir)/%)
+ rm -f $@ $@-t
+ ./make-internal-documentation.pl \
+ --srcdir $(top_srcdir) \
+ -o $@-t \
+ $(source_files)
+ mv $@-t $@
+
guestfs-performance.1 $(top_builddir)/website/guestfs-performance.1.html:
stamp-guestfs-performance.pod
stamp-guestfs-performance.pod: guestfs-performance.pod
diff --git a/docs/guestfs-internals.pod b/docs/guestfs-internals.pod
index a554b13..bbb278d 100644
--- a/docs/guestfs-internals.pod
+++ b/docs/guestfs-internals.pod
@@ -397,6 +397,15 @@ on a platform that does support supermin using
L<libguestfs-make-fixed-appliance(1)>, copy it over, and use that
to run libguestfs.
+=head1 INTERNAL DOCUMENTATION
+
+This section documents internal functions inside libguestfs and
+various utilities. It is intended for libguestfs developers only.
+These functions are not publicly exported, and may change or be
+removed at any time.
+
+__INTERNAL_DOCUMENTATION__
+
=head1 SEE ALSO
L<guestfs(3)>,
diff --git a/docs/make-internal-documentation.pl b/docs/make-internal-documentation.pl
new file mode 100755
index 0000000..4edb5bc
--- /dev/null
+++ b/docs/make-internal-documentation.pl
@@ -0,0 +1,234 @@
+#!/usr/bin/env perl
+# Copyright (C) 2016 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+use warnings;
+use strict;
+
+use Getopt::Long;
+
+=head1 NAME
+
+make-internal-documentation.pl - Generate internal documentation from C files
+
+=head1 SYNOPSIS
+
+ make-internal-documentation.pl --output internal-documentation.pod
+ [C source files ...]
+
+=head1 DESCRIPTION
+
+C<make-internal-documentation.pl> is a script that generates
+L<guestfs-internals(1)/INTERNAL DOCUMENTATION>.
+
+You must specify the name of the output file using the I<-o> or
+I<--output> option, and a list of the C source files in the project.
+
+Internal documentation is added to the C source files using special
+comments which look like this:
+
+ /**
+ * Returns true if C<foo> equals C<bar>.
+ */
+ bool
+ is_equal (const char *foo, const char *bar)
+ ...
+
+The comment is written in POD format (see L<perlpod(1)>). It may be
+on several lines, and be split into paragraphs using blank lines.
+
+The function being documented should appear immediately after the
+special comment, and is also copied into the documentation.
+
+In addition, each C file may have a special comment at the top of the
+file (before any C<#include> lines) which outlines what the file does.
+
+=head1 OPTIONS
+
+=over 4
+
+=cut
+
+my $help;
+
+=item B<--help>
+
+Display brief help.
+
+=cut
+
+my $output;
+
+=item B<-o output.pod>
+
+=item B<--output output.pod>
+
+Set the name of the output file (required).
+
+=cut
+
+my $srcdir = ".";
+
+=item B<--srcdir top_srcdir>
+
+Path to the top source directory. Input filenames are
+located relative to this path.
+
+=back
+
+=cut
+
+# Clean up the program name.
+my $progname = $0;
+$progname =~ s{.*/}{};
+
+# Parse options.
+GetOptions ("help|?" => \$help,
+ "output=s" => \$output,
+ "srcdir=s" => \$srcdir,
+ ) or pod2usage (2);
+pod2usage (1) if $help;
+
+die "$progname: missing -o/--output parameter\n" unless defined $output;
+
+die "$progname: missing argument: make-internal-documentation [C source files
...]\n" unless @ARGV >= 1;
+
+# Only consider input files which
+# - are C source files
+# - exist
+# - contain /** comments.
+
+my @inputs = ();
+my $input;
+my $path;
+foreach $input (@ARGV) {
+ if ($input =~ /\.c$/) {
+ $path = "$srcdir/$input";
+ if (-r $path) {
+ my @cmd = ("grep", "-q", "^/\\*\\*", $path);
+ if (system (@cmd) == 0) {
+ push @inputs, $input
+ }
+ }
+ }
+}
+@inputs = sort @inputs;
+
+open OUTPUT, ">$output" or die "$progname: $output: $!";
+
+foreach $input (@inputs) {
+ $path = "$srcdir/$input";
+
+ print OUTPUT ("=head2 F<$input>\n\n");
+
+ open INPUT, $path or die "$progname: $input: $!";
+
+ # A single special comment seen before any #includes can be used
+ # to outline the purpose of the source file.
+ my $seen_includes = 0;
+ my $lineno = 0;
+
+ while (<INPUT>) {
+ chomp;
+ $lineno++;
+ $seen_includes = 1 if /^#include/;
+
+ if (m{^/\*\*$}) {
+ # Found a special comment. Read the whole comment.
+ my @comment = ();
+ my $found_end = 0;
+ my $start_lineno = $lineno;
+ while (<INPUT>) {
+ chomp;
+ $lineno++;
+
+ if (m{^ \*/$}) {
+ $found_end = 1;
+ last;
+ }
+ elsif (m{^ \* (.*)}) {
+ push @comment, $1;
+ }
+ elsif (m{^ \*$}) {
+ push @comment, "";
+ }
+ else {
+ die "$progname: $input: $lineno: special comment with incorrect
format\n";
+ }
+ }
+ die "$progname: $input: $start_lineno: unterminated special
comment"
+ unless $found_end;
+
+ unless ($seen_includes) {
+ # If we've not seen the includes yet, then this is the
+ # top of file special comment, so we just write it out.
+ print OUTPUT join("\n", @comment), "\n";
+ print OUTPUT "\n";
+ }
+ else {
+ # Otherwise it's a function description, so now we
+ # need to read in the function definition.
+ my @function = ();
+ $found_end = 0;
+ $start_lineno = $lineno;
+ while (<INPUT>) {
+ chomp;
+ $lineno++;
+
+ if (m/^{/) {
+ $found_end = 1;
+ last;
+ }
+ else {
+ push @function, $_;
+ }
+ }
+
+ die "$progname: $input: $start_lineno: unterminated function
definition"
+ unless $found_end;
+
+ # Print the function definition, followed by the comment.
+ print OUTPUT " ", join ("\n ", @function),
"\n";
+ print OUTPUT "\n";
+ print OUTPUT join("\n", @comment), "\n";
+ print OUTPUT "\n";
+ }
+ }
+ elsif (m{^/\*\*}) {
+ die "$progname: $input: $lineno: special comment with incorrect
format\n";
+ }
+ }
+
+
+ close INPUT;
+}
+
+close OUTPUT or die "$progname: $output: close: $!";
+
+exit 0;
+
+=head1 SEE ALSO
+
+L<perlpod(1)>,
+libguestfs.git/README.
+
+=head1 AUTHOR
+
+Richard W.M. Jones.
+
+=head1 COPYRIGHT
+
+Copyright (C) 2012-2016 Red Hat Inc.
diff --git a/po/POTFILES b/po/POTFILES
index 20a330e..9e4d9cc 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -126,6 +126,7 @@ df/main.c
df/output.c
df/parallel.c
diff/diff.c
+docs/make-internal-documentation.pl
edit/edit.c
erlang/erl-guestfs-proto.c
erlang/erl-guestfs.c
diff --git a/src/launch.c b/src/launch.c
index 7bc9cf9..32f725b 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -16,6 +16,15 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+/**
+ * This file implements L<guestfs(3)/guestfs_launch>.
+ *
+ * Most of the work is done by the backends (see
+ * L<guestfs(3)/BACKEND>), which are implemented in
+ * F<src/launch-direct.c>, F<src/launch-libvirt.c> etc, so this file
+ * mostly passes calls through to the current backend.
+ */
+
#include <config.h>
#include <stdio.h>
@@ -119,9 +128,11 @@ guestfs_int_launch_send_progress (guestfs_h *g, int perdozen)
}
}
-/* Compute Y - X and return the result in milliseconds.
+/**
+ * Compute C<y - x> and return the result in milliseconds.
+ *
* Approximately the same as this code:
- *
http://www.mpp.mpg.de/~huber/util/timevaldiff.c
+ * L<http://www.mpp.mpg.de/~huber/util/timevaldiff.c>
*/
int64_t
guestfs_int_timeval_diff (const struct timeval *x, const struct timeval *y)
@@ -148,7 +159,10 @@ guestfs_impl_get_pid (guestfs_h *g)
return g->backend_ops->get_pid (g, g->backend_data);
}
-/* Maximum number of disks. */
+/**
+ * Returns the maximum number of disks allowed to be added to the
+ * backend (backend dependent).
+ */
int
guestfs_impl_max_disks (guestfs_h *g)
{
@@ -159,8 +173,10 @@ guestfs_impl_max_disks (guestfs_h *g)
return g->backend_ops->max_disks (g, g->backend_data);
}
-/* You had to call this function after launch in versions <= 1.0.70,
- * but it is now a no-op.
+/**
+ * Implementation of L<guestfs(3)/guestfs_wait_ready>. You had to
+ * call this function after launch in versions E<le> 1.0.70, but it is
+ * now an (almost) no-op.
*/
int
guestfs_impl_wait_ready (guestfs_h *g)
@@ -251,25 +267,6 @@ guestfs_impl_config (guestfs_h *g,
return 0;
}
-/* Construct the Linux command line passed to the appliance. This is
- * used by the 'direct' and 'libvirt' backends, and is simply
- * located in this file because it's a convenient place for this
- * common code.
- *
- * The 'appliance_dev' parameter must be the full device name of the
- * appliance disk and must have already been adjusted to take into
- * account virtio-blk or virtio-scsi; eg "/dev/sdb".
- *
- * The 'flags' parameter can contain the following flags logically
- * or'd together (or 0):
- *
- * GUESTFS___APPLIANCE_COMMAND_LINE_IS_TCG: If we are launching a qemu
- * TCG guest (ie. KVM is known to be disabled or unavailable). If you
- * don't know, don't pass this flag.
- *
- * Note that this returns a newly allocated buffer which must be freed
- * by the caller.
- */
#if defined(__powerpc64__)
#define SERIAL_CONSOLE "console=hvc0 console=ttyS0"
#elif defined(__arm__) || defined(__aarch64__)
@@ -284,6 +281,31 @@ guestfs_impl_config (guestfs_h *g,
#define EARLYPRINTK ""
#endif
+/**
+ * Construct the Linux command line passed to the appliance. This is
+ * used by the C<direct> and C<libvirt> backends, and is simply
+ * located in this file because it's a convenient place for this
+ * common code.
+ *
+ * The C<appliance_dev> parameter must be the full device name of the
+ * appliance disk and must have already been adjusted to take into
+ * account virtio-blk or virtio-scsi; eg C</dev/sdb>.
+ *
+ * The C<flags> parameter can contain the following flags logically
+ * or'd together (or 0):
+ *
+ * =over 4
+ *
+ * =item C<GUESTFS___APPLIANCE_COMMAND_LINE_IS_TCG>
+ *
+ * If we are launching a qemu TCG guest (ie. KVM is known to be
+ * disabled or unavailable). If you don't know, don't pass this flag.
+ *
+ * =back
+ *
+ * Note that this function returns a newly allocated buffer which must
+ * be freed by the caller.
+ */
char *
guestfs_int_appliance_command_line (guestfs_h *g, const char *appliance_dev,
int flags)
--
2.7.4