Richard W.M. Jones
2016-Apr-12 10:46 UTC
[Libguestfs] [PATCH] Add internal documentation to C files.
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
Apparently Analagous Threads
- [PATCH v1 INCOMPLETE] tests: Implement script to check documented tool options match actual options.
- [PATCH libguestfs 1/3] podwrapper: __INCLUDE:file.pod__ and __VERBATIM:file.txt__ in POD files.
- [PATCH nbdkit 3/4] Add map filter.
- [PATCH] tests: Implement script to check documented tool options match actual options.
- tftpd remap rules