--- /dev/null
+package Ast;
+use strict;
+
+use vars qw/ $this $pack @endCodes /;
+
+#-----------------------------------------------------------------------------
+# This package is used to create a simple Abstract Syntax tree. Each node
+# in the AST is an associative array and supports two kinds of properties -
+# scalars and lists of scalars.
+# See SchemParser.pm for an example of usage.
+# ... Sriram
+#-----------------------------------------------------------------------------
+
+# Constructor
+# e.g AST::New ("personnel")
+# Stores the argument in a property called astNodeName whose sole purpose
+# is to support Print()
+
+sub New {
+ my ($this) = {"astNodeName" => $_[0]};
+ bless ($this);
+ return $this;
+}
+
+# Add a property to this object
+# $astNode->AddProp("className", "Employee");
+
+sub AddProp {
+ my ($this) = $_[0];
+ $this->{$_[1]} = $_[2];
+}
+
+# Equivalent to AddProp, except the property name is associated
+# with a list of values
+# $classAstNode->AddProp("attrList", $attrAstNode);
+
+sub AddPropList {
+ my ($this) = $_[0];
+ if (! exists $this->{$_[1]}) {
+ $this->{$_[1]} = [];
+ }
+ push (@{$this->{$_[1]}}, $_[2]);
+}
+
+# Returns a list of all the property names of this object
+sub GetProps {
+ my ($this) = $_[0];
+ return keys %{$this};
+}
+
+sub Visit {
+ # Converts each of this AstNode's properties into global variables.
+ # The global variables are introduced into package "main"
+ # At the same time, a piece of code is formed to undo this work above -
+ # $endCode essentially contains the values of these global variables
+ # before they are mangled. endCode gets pushed into a stack (endCodes),
+ # which is unwound by UnVisit().
+
+ local ($this, $pack) = @_;
+
+
+ my $code = "";
+ my $endCode = "";
+
+
+ foreach my $k (keys %{$this}) {
+
+ my $glob = $pack."::".$k;
+
+ if ( defined $$glob ) {
+
+ if ( ${$glob} ne "" ) {
+ $$glob =~ s/\'/\\\'/g;
+ }
+
+ $endCode .= '$'.$pack.'::'.$k. " = '".$$glob."';";
+ } else {
+ $endCode .= '$'.$pack . "::". $k . ' = "";';
+ }
+ $code .= '$'.$pack . "::" . $k . "= \$this->{\"$k\"};";
+ }
+ push (@endCodes, $endCode);
+ eval($code) if $code;
+}
+
+sub UnVisit {
+ my $code = pop(@endCodes);
+ eval($code) if ($code);
+}
+
+1;
--- /dev/null
+package Iter;
+
+=head1 Iterator Module
+
+A set of iterator functions for traversing the various trees and indexes.
+Each iterator expects closures that operate on the elements in the iterated
+data structure.
+
+
+=head2 Generic
+
+ Params: $node, &$loopsub, &$skipsub, &$applysub, &$recursesub
+
+Iterate over $node's children. For each iteration:
+
+If loopsub( $node, $kid ) returns false, the loop is terminated.
+If skipsub( $node, $kid ) returns true, the element is skipped.
+
+Applysub( $node, $kid ) is called
+If recursesub( $node, $kid ) returns true, the function recurses into
+the current node.
+
+=cut
+
+sub Generic
+{
+ my ( $root, $loopcond, $skipcond, $applysub, $recursecond ) = @_;
+
+ return sub {
+ foreach my $node ( @{$root->{Kids}} ) {
+
+ if ( defined $loopcond ) {
+ return 0 unless $loopcond->( $root, $node );
+ }
+
+ if ( defined $skipcond ) {
+ next if $skipcond->( $root, $node );
+ }
+
+ my $ret = $applysub->( $root, $node );
+ return $ret if defined $ret && $ret;
+
+ if ( defined $recursecond
+ && $recursecond->( $root, $node ) ) {
+ $ret = Generic( $node, $loopcond, $skipcond,
+ $applysub, $recursecond)->();
+ if ( $ret ) {
+ return $ret;
+ }
+ }
+ }
+
+ return 0;
+ };
+}
+
+sub Class
+{
+ my ( $root, $applysub, $recurse ) = @_;
+
+ return Generic( $root, undef,
+ sub {
+ return !( $node->{NodeType} eq "class"
+ || $node->{NodeType} eq "struct" );
+ },
+ $applysub, $recurse );
+}
+
+=head2 Tree
+
+ Params: $root, $recurse?, $commonsub, $compoundsub, $membersub,
+ $skipsub
+
+Traverse the ast tree starting at $root, skipping if skipsub returns true.
+
+Applying $commonsub( $node, $kid),
+then $compoundsub( $node, $kid ) or $membersub( $node, $kid ) depending on
+the Compound flag of the node.
+
+=cut
+
+sub Tree
+{
+ my ( $rootnode, $recurse, $commonsub, $compoundsub, $membersub,
+ $skipsub ) = @_;
+
+ my $recsub = $recurse ? sub { return 1 if $_[1]->{Compound}; }
+ : undef;
+
+ Generic( $rootnode, undef, $skipsub,
+ sub { # apply
+ my ( $root, $node ) = @_;
+ my $ret;
+
+ if ( defined $commonsub ) {
+ $ret = $commonsub->( $root, $node );
+ return $ret if defined $ret;
+ }
+
+ if ( $node->{Compound} && defined $compoundsub ) {
+ $ret = $compoundsub->( $root, $node );
+ return $ret if defined $ret;
+ }
+
+ if( !$node->{Compound} && defined $membersub ) {
+ $ret = $membersub->( $root, $node );
+ return $ret if defined $ret;
+ }
+ return;
+ },
+ $recsub # skip
+ )->();
+}
+
+=head2 LocalCompounds
+
+Apply $compoundsub( $node ) to all locally defined compound nodes
+(ie nodes that are not external to the library being processed).
+
+=cut
+
+sub LocalCompounds
+{
+ my ( $rootnode, $compoundsub ) = @_;
+
+ return unless defined $rootnode && defined $rootnode->{Kids};
+
+ foreach my $kid ( sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @{$rootnode->{Kids}} ) {
+ next if !defined $kid->{Compound};
+
+ $compoundsub->( $kid ) unless defined $kid->{ExtSource};
+ LocalCompounds( $kid, $compoundsub );
+ }
+}
+
+=head2 Hierarchy
+
+ Params: $node, $levelDownSub, $printSub, $levelUpSub
+
+This allows easy hierarchy traversal and printing.
+
+Traverses the inheritance hierarchy starting at $node, calling printsub
+for each node. When recursing downward into the tree, $levelDownSub($node) is
+called, the recursion takes place, and $levelUpSub is called when the
+recursion call is completed.
+
+=cut
+
+sub Hierarchy
+{
+ my ( $node, $ldownsub, $printsub, $lupsub, $nokidssub ) = @_;
+
+ return if defined $node->{ExtSource}
+ && (!defined $node->{InBy}
+ || !kdocAstUtil::hasLocalInheritor( $node ));
+
+ $printsub->( $node );
+
+ if ( defined $node->{InBy} ) {
+ $ldownsub->( $node );
+
+ foreach my $kid (
+ sort {$a->{astNodeName} cmp $b->{astNodeName}}
+ @{ $node->{InBy} } ) {
+ Hierarchy( $kid, $ldownsub, $printsub, $lupsub );
+ }
+
+ $lupsub->( $node );
+ }
+ elsif ( defined $nokidssub ) {
+ $nokidssub->( $node );
+ }
+
+ return;
+}
+
+
+sub Ancestors
+{
+ my ( $node, $rootnode, $noancessub, $startsub, $printsub,
+ $endsub ) = @_;
+ my @anlist = ();
+
+ return if $node eq $rootnode;
+
+ if ( !exists $node->{InList} ) {
+ $noancessub->( $node ) unless !defined $noancessub;
+ return;
+ }
+
+ foreach my $innode ( @{ $node->{InList} } ) {
+ my $nref = $innode->{Node}; # real ancestor
+ next if defined $nref && $nref == $rootnode;
+
+ push @anlist, $innode;
+ }
+
+ if ( $#anlist < 0 ) {
+ $noancessub->( $node ) unless !defined $noancessub;
+ return;
+ }
+
+ $startsub->( $node ) unless !defined $startsub;
+
+ foreach my $innode ( sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @anlist ) {
+
+ # print
+ $printsub->( $innode->{Node}, $innode->{astNodeName},
+ $innode->{Type}, $innode->{TmplType} )
+ unless !defined $printsub;
+ }
+
+ $endsub->( $node ) unless !defined $endsub;
+
+ return;
+
+}
+
+sub Descendants
+{
+ my ( $node, $nodescsub, $startsub, $printsub, $endsub ) = @_;
+
+ if ( !exists $node->{InBy} ) {
+ $nodescsub->( $node ) unless !defined $nodescsub;
+ return;
+ }
+
+
+ my @desclist = ();
+ DescendantList( \@desclist, $node );
+
+ if ( $#desclist < 0 ) {
+ $nodescsub->( $node ) unless !defined $nodescsub;
+ return;
+ }
+
+ $startsub->( $node ) unless !defined $startsub;
+
+ foreach my $innode ( sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @desclist ) {
+
+ $printsub->( $innode)
+ unless !defined $printsub;
+ }
+
+ $endsub->( $node ) unless !defined $endsub;
+
+ return;
+
+}
+
+sub DescendantList
+{
+ my ( $list, $node ) = @_;
+
+ return unless exists $node->{InBy};
+
+ foreach my $kid ( @{ $node->{InBy} } ) {
+ push @$list, $kid;
+ DescendantList( $list, $kid );
+ }
+}
+
+=head2 DocTree
+
+=cut
+
+sub DocTree
+{
+ my ( $rootnode, $allowforward, $recurse,
+ $commonsub, $compoundsub, $membersub ) = @_;
+
+ Generic( $rootnode, undef,
+ sub { # skip
+ my( $node, $kid ) = @_;
+
+ unless (!(defined $kid->{ExtSource})
+ && ($allowforward || $kid->{NodeType} ne "Forward")
+ && ($main::doPrivate || !($kid->{Access} =~ /private/))
+ && exists $kid->{DocNode} ) {
+
+ return 1;
+ }
+
+ return;
+ },
+ sub { # apply
+ my ( $root, $node ) = @_;
+
+ my $ret;
+
+ if ( defined $commonsub ) {
+ $ret = $commonsub->( $root, $node );
+ return $ret if defined $ret;
+ }
+
+ if ( $node->{Compound} && defined $compoundsub ) {
+ $ret = $compoundsub->( $root, $node );
+ return $ret if defined $ret;
+ }
+ elsif( defined $membersub ) {
+ $ret = $membersub->( $root, $node );
+ return $ret if defined $ret;
+ }
+
+ return;
+ },
+ sub { return 1 if $recurse; return; } # recurse
+ )->();
+
+}
+
+sub MembersByType
+{
+ my ( $node, $startgrpsub, $methodsub, $endgrpsub, $nokidssub ) = @_;
+
+# public
+ # types
+ # data
+ # methods
+ # signals
+ # slots
+ # static
+# protected
+# private (if enabled)
+
+ if ( !defined $node->{Kids} ) {
+ $nokidssub->( $node ) if defined $nokidssub;
+ return;
+ }
+
+ foreach my $access ( qw/public protected private/ ) {
+ next if $access eq "private" && !$main::doPrivate;
+
+ my @types = ();
+ my @data = ();
+ my @signals = ();
+ my @slots =();
+ my @methods = ();
+ my @static = ();
+ my @modules = ();
+ my @interfaces = ();
+
+ # Build lists
+ foreach my $kid ( @{$node->{Kids}} ) {
+ next if !(($kid->{Access} =~ /$access/
+ && !$kid->{ExtSource})
+ || ( $access eq "public"
+ && $kid->{Access} eq "signals" ));
+
+ my $type = $kid->{NodeType};
+
+ if ( $type eq "method" ) {
+ if ( $kid->{Flags} =~ "s" ) {
+ push @static, $kid;
+ }
+ elsif ( $kid->{Flags} =~ "l" ) {
+ push @slots, $kid;
+ }
+ elsif ( $kid->{Flags} =~ "n" ) {
+ push @signals, $kid;
+ }
+ else {
+ push @methods, $kid;
+ }
+ }
+ elsif ( $kid->{Compound} ) {
+ if ( $type eq "module" ) {
+ push @modules, $kid;
+ }
+ elsif ( $type eq "interface" ) {
+ push @interfaces, $kid;
+ }
+ else {
+ push @types, $kid;
+ }
+ }
+ elsif ( $type eq "typedef" || $type eq "enum" ) {
+ push @types, $kid;
+ }
+ else {
+ push @data, $kid;
+ }
+ }
+
+ # apply
+ $access = ucfirst( $access );
+
+ doGroup( "$access Types", $node, \@types, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "Modules", $node, \@modules, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "Interfaces", $node, \@interfaces, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "$access Methods", $node, \@methods, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "$access Slots", $node, \@slots, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "Signals", $node, \@signals, $startgrpsub,
+ $methodsub, $endgrpsub);
+ doGroup( "$access Static Methods", $node, \@static,
+ $startgrpsub, $methodsub, $endgrpsub);
+ doGroup( "$access Members", $node, \@data, $startgrpsub,
+ $methodsub, $endgrpsub);
+ }
+}
+
+sub doGroup
+{
+ my ( $name, $node, $list, $startgrpsub, $methodsub, $endgrpsub ) = @_;
+
+ return if $#$list < 0;
+
+ $startgrpsub->( $name ) if defined $startgrpsub;
+
+ if ( defined $methodsub ) {
+ foreach my $kid ( @$list ) {
+ $methodsub->( $node, $kid );
+ }
+ }
+
+ $endgrpsub->( $name ) if defined $endgrpsub;
+}
+
+sub ByGroupLogical
+{
+ my ( $root, $startgrpsub, $itemsub, $endgrpsub ) = @_;
+
+ return 0 unless defined $root->{Groups};
+
+ foreach my $groupname ( sort keys %{$root->{Groups}} ) {
+ next if $groupname eq "astNodeName"||$groupname eq "NodeType";
+
+ my $group = $root->{Groups}->{ $group };
+ next unless $group->{Kids};
+
+ $startgrpsub->( $group->{astNodeName}, $group->{Desc} );
+
+ foreach my $kid (sort {$a->{astNodeName} cmp $b->{astNodeName}}
+ @group->{Kids} ) {
+ $itemsub->( $root, $kid );
+ }
+ $endgrpsub->( $group->{Desc} );
+ }
+
+ return 1;
+}
+
+sub SeeAlso
+{
+ my ( $node, $nonesub, $startsub, $printsub, $endsub ) = @_;
+
+ if( !defined $node ) {
+ $nonesub->();
+ return;
+ }
+
+ my $doc = $node;
+
+ if ( $node->{NodeType} ne "DocNode" ) {
+ $doc = $node->{DocNode};
+ if ( !defined $doc ) {
+ $nonesub->() if defined $nonesub;
+ return;
+ }
+ }
+
+ if ( !defined $doc->{See} ) {
+ $nonesub->() if defined $nonesub;
+ return;
+ }
+
+ my $see = $doc->{See};
+ my $ref = $doc->{SeeRef};
+
+ if ( $#$see < 1 ) {
+ $nonesub->() if defined $nonesub;
+ return;
+ }
+
+ $startsub->( $node ) if defined $startsub;
+
+ for my $i ( 0..$#$see ) {
+ my $seelabel = $see->[ $i ];
+ my $seenode = undef;
+ if ( defined $ref ) {
+ $seenode = $ref->[ $i ];
+ }
+
+ $printsub->( $seelabel, $seenode ) if defined $printsub;
+ }
+
+ $endsub->( $node ) if defined $endsub;
+
+ return;
+}
+
+1;
--- /dev/null
+
+all: configure
+
+configure: configure.in
+ autoconf
--- /dev/null
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+perl = @perl@
+install = @INSTALL@
+bin = kdoc qt2kdoc makekdedoc
+pm = kdocUtil.pm kdocAstUtil.pm kdocParseDoc.pm kdocCxxHTML.pm kdocLib.pm \
+ Ast.pm kdocIDLhtml.pm kdocHTMLutil.pm kdoctexi.pm kdocCxxLaTeX.pm \
+ kdocDocHelper.pm kdocCxxDocbook.pm Iter.pm
+pmextra =
+bindir = ${exec_prefix}/bin
+pmdir = ${prefix}/share/kdoc
+srcdocdir= doc
+VERSION=@Version@
+
+all: kdoc.local qt2kdoc.local makekdedoc.local
+ (cd doc; make)
+
+kdoc.local: @srcdir@/kdoc
+ cp @srcdir@/kdoc kdoc.local
+ perl -npi -e 's%^#\!.*$$%#!'${perl}' -I'${pmdir}'%g;' kdoc.local
+ perl -npi -e 's#\$$Version\\\$$#'"${VERSION}"'#g;' kdoc.local
+
+qt2kdoc.local: @srcdir@/qt2kdoc
+ cp @srcdir@/qt2kdoc qt2kdoc.local
+ perl -npi -e 's%^#\!.*$$%#!'${perl}' -I'${pmdir}'%g;' qt2kdoc.local
+
+makekdedoc.local: @srcdir@/makekdedoc
+ cp @srcdir@/makekdedoc makekdedoc.local
+ perl -npi -e 's%^#\!.*$$%#!'${perl}' -I'${pmdir}'%g;' makekdedoc.local
+
+install: all
+ ${install} -d $(DESTDIR)${bindir}
+ ${install} -m 755 kdoc.local $(DESTDIR)${bindir}/kdoc
+ ${install} -m 755 qt2kdoc.local $(DESTDIR)${bindir}/qt2kdoc
+ ${install} -m 755 makekdedoc.local $(DESTDIR)${bindir}/makekdedoc
+ ${install} -d $(DESTDIR)${pmdir}
+ for file in ${pm} ${pmextra}; do \
+ ${install} -m 644 @srcdir@/$$file $(DESTDIR)${pmdir}; \
+ done
+ (cd doc; make install)
+
+uninstall:
+ (cd $(DESTDIR)${bindir} && rm -f ${bin})
+ (cd $(DESTDIR)${pmdir} && rm -f ${pm})
+ (cd $(DESTDIR)${mandir} && rm -f ${man})
+ -rmdir $(DESTDIR)${bindir}
+ -rmdir $(DESTDIR)${pmdir}
+ -rmdir $(DESTDIR)${mandir}
+
+clean:
+ (cd doc; make clean)
+ rm -f kdoc.local qt2kdoc.local makekdedoc.local
+
+distclean: clean
+ rm -f Makefile config.status config.log config.cache perlbin \
+ doc/Makefile
+
+srcdoc:
+ pod2html --flush --title KDOC $(bin) $(pm) \
+ --outfile $(srcdocdir)/kdoc-doc.html
+tags:
+ perltags kdoc qt2kdoc makekdedoc *.pm
+
+check:
+ @for dir in $(bin) $(pm); do \
+ echo "** Checking: $$dir"; \
+ perl -wc $$dir; done
--- /dev/null
+
+KDOC -- C++ and IDL Source Documentation System
+Version 2.0 ALPHA
+
+KDOC creates cross-referenced documentation for C++ and CORBA IDL libraries
+directly from the source. Documentation can be embedded in special doc
+comments in the source.
+
+Also included:
+
+qt2kdoc: Generates cross-reference index to link kdoc output with
+ Qt documentation.
+
+makekdedoc: Generates documentation for the KDE libraries.
+
+KDOC 2.0 is still under development.
+
+REQUIREMENTS
+
+You need perl 5.005 or greater to run kdoc.
+
+HOWTO
+
+If you are running this straight from CVS, you will need to run
+
+ make -f Makefile.cvs
+
+before building.
+
+This should install kdoc:
+
+./configure; make; make install
+rehash; man kdoc
+
+The KDOC manual in docbook format is available in doc/kdoc.docbook.
+This can be converted to various other online and print formats using
+the jade and docbook packages.
+
+CREDITS
+-------
+
+Thanks to the following people for providing testing, feedback, encouragment,
+new features and patches:
+
+Bernd Gehrmann
+David Sweet
+Harald Hoyer
+Jochen Wilhelmy
+Marcin Kasperski
+Rainer Dorsch
+Stephane Matamontero
+Torben Weis
+Wolfgang Bangerth
+Andrew W. Nosenko
+
+------
+Copyright(C) 1999, Sirtaj Singh Kang <taj@kde.org>
+Distributed under the GPL.
--- /dev/null
+
+Bugs
+----
+Refs for external nodes are being double-escaped.
+
+templates
+ template functions
+variables
+ multivars cannot have values
+ array initializers don't work
+ pointers to functions
+compound typedefs
+functions
+ Constructor initializers are appearing as part of the args.
+ functions with funcptr or paren'd arguments
+ operators are not properly quoted
+ operators not always correctly parsed
+
+Source for Forward decls should not be picked up.
+Preprocessor screws up line numbers.
+
+check "@params ... */"
+check namespaces
+
+HTML: links are screwed (multiple escapes somewhere).
+
+General
+-------
+Running kdoc in-place
+Major IDL cleanup
+
+parser
+------
+documentation in source
+CODE etc
+templates
+
+IDL specific:
+ parse "raises"
+
+Doc specific
+------------
+ pre should be allowed inline.
+ exceptions:
+ @exception <exception> Reason
+ exception is a class
+
+Ast
+---
+Allow cross-referencing between languages. I don't know how to do this,
+other than by reading every language into the same syntax tree.
+
+postprocessor
+------------
+referenced text use namespaces
+ searchspaces:
+ upward-searching (this and parents)
+ enclosed (namespaces)
+
+DocBook
+-------
+Don't use deref, we need a textref function instead.
+ deref is for @refs etc.
+visibility and flags in member docs.
+Globals.
+group indices.
+Index.
+
+HTML
+----
+Filenames - "/" being replaced by "#" is silly.
+group indices.
+cross-referenced headers
+
+Libs
+----
+-L doesn't work properly (KDOCLIBS works ok).
+
+Other
+-----
+Man
+lxr
--- /dev/null
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
--- /dev/null
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=qt2kdoc
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:557: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall installbsd scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+echo $ac_n "checking for perl 5 or greater""... $ac_c" 1>&6
+echo "configure:608: checking for perl 5 or greater" >&5
+if $srcdir/findperl; then
+ perl=`cat perlbin`
+ echo $perl
+else
+ echo "Couldn't find perl 5 or later. kdoc will not run."
+ exit 1
+fi
+
+
+
+echo $ac_n "checking kdoc version""... $ac_c" 1>&6
+echo "configure:620: checking kdoc version" >&5
+Version=`cat $srcdir/Version | sed 's#Revision##g' | tr -d '\$:'`
+echo $Version
+
+
+
+mandir='${prefix}/man/man1'
+docdir='${prefix}/doc/kdoc'
+
+
+
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile doc/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@perl@%$perl%g
+s%@Version@%$Version%g
+s%@docdir@%$docdir%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile doc/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
--- /dev/null
+AC_INIT(qt2kdoc)
+
+AC_DEFUN(AC_FIND_PERL,
+[
+AC_MSG_CHECKING(for perl 5 or greater)
+if $srcdir/findperl; then
+ $1=`cat perlbin`
+ echo $$1
+else
+ echo "Couldn't find perl 5 or later. kdoc will not run."
+ exit 1
+fi
+])
+
+AC_DEFUN(AC_KDOC_VERSION,
+[
+AC_MSG_CHECKING(kdoc version)
+$1=`cat $srcdir/Version | sed 's#Revision##g' | tr -d '\$:'`
+echo $$1
+])
+
+AC_PROG_INSTALL
+AC_FIND_PERL(perl)
+AC_SUBST(perl)
+AC_KDOC_VERSION(Version)
+AC_SUBST(Version)
+
+mandir='${prefix}/man/man1'
+docdir='${prefix}/doc/kdoc'
+
+AC_SUBST(mandir)
+AC_SUBST(docdir)
+
+
+AC_OUTPUT(Makefile doc/Makefile)
--- /dev/null
+kdoc (2.0a15-1.0) unstable; urgency=low
+
+ * New upstream version
+
+ -- Ivan E. Moore II <rkrusty@debian.org> Wed, 13 Oct 1999 23:30:06 -0400
+
+kdoc (2.0a12-1.0) unstable; urgency=low
+
+ * New upstream version
+
+ -- Ivan E. Moore II <rkrusty@debian.org> Mon, 27 Sep 1999 23:30:06 -0400
+
+kdoc (2.0a9-2) unstable; urgency=low
+
+ * Use DESTDIR for 'make install'
+
+ -- Bernd Gehrmann <bernd@physik.hu-berlin.de> Sat, 22 May 1999 18:30:06 +0200
+
+kdoc (2.0a9-1) experimental; urgency=low
+
+ * Initial Release.
+
+ -- Bernd Gehrmann <bernd@physik.hu-berlin.de> Fri, 23 Apr 1999 19:30:14 +0200
+
+Local variables:
+mode: debian-changelog
+End:
--- /dev/null
+Source: kdoc
+Section: devel
+Priority: optional
+Maintainer: Bernd Gehrmann <bernd@physik.hu-berlin.de>
+Standards-Version: 3.0.1
+
+Package: kdoc
+Architecture: all
+Section: devel
+Depends: ${perl:Depends}
+Description: C++ and IDL Source Documentation System
+ KDOC creates cross-referenced documentation for C++
+ and CORBA IDL libraries directly from the source.
+ Documentation can be embedded in special doccomments
+ in the source.
+
--- /dev/null
+This package was debianized by Bernd Gehrmann <bernd@physik.hu-berlin.de>
+
+Copyright:
+
+KDOC is released under the terms of the GNU GPL.
+
+See /usr/doc/copyright/GPL for the full license.
--- /dev/null
+#! /bin/sh
+# postinst script for kdoc
+#
+# see: dh_installdeb(1)
+
+set -e
+
+case "$1" in
+ configure)
+
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 0
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
--- /dev/null
+#! /bin/sh
+# postrm script for kdoc
+#
+# see: dh_installdeb(1)
+
+set -e
+
+case "$1" in
+ purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
+
+ # update the menu system
+
+ ;;
+
+ *)
+ echo "postrm called with unknown argument \`$1'" >&2
+ exit 0
+
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
--- /dev/null
+#! /bin/sh
+# preinst script for kdoc
+#
+# see: dh_installdeb(1)
+
+set -e
+
+case "$1" in
+ install|upgrade)
+ ;;
+
+ abort-upgrade)
+ ;;
+
+ *)
+ echo "preinst called with unknown argument \`$1'" >&2
+ exit 0
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
--- /dev/null
+#! /bin/sh
+# prerm script for kdoc
+#
+# see: dh_installdeb(1)
+
+set -e
+
+case "$1" in
+ remove|upgrade|deconfigure)
+ ;;
+ failed-upgrade)
+ ;;
+ *)
+ echo "prerm called with unknown argument \`$1'" >&2
+ exit 0
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
+
--- /dev/null
+#!/usr/bin/make -f
+# Made with the aid of dh_make, by Craig Small
+# Sample debian/rules that uses debhelper. GNU copyright 1997 by Joey Hess.
+# Some lines taken from debmake, by Cristoph Lameter.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+build:
+ dh_testdir
+ ./configure --prefix=/usr
+ $(MAKE)
+ touch build
+
+clean:
+ dh_testdir
+ -rm -f build
+ -$(MAKE) distclean
+ -rm -f `find . -name "*~"`
+ dh_clean
+
+binary-indep: build
+ dh_testroot
+ dh_testdir
+
+binary-arch: build
+ dh_testroot
+ dh_testdir
+ dh_clean
+ dh_installdirs
+ $(MAKE) install DESTDIR=`pwd`/debian/tmp/
+ dh_installdocs
+ dh_installexamples
+ dh_installmanpages
+ dh_undocumented
+ dh_installchangelogs
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_suidregister
+ dh_makeshlibs
+ dh_perl
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+
+.PHONY: binary binary-arch binary-indep clean checkroot
--- /dev/null
+
+Some of the functions are documented with perlpod, so you can create an HTML
+file with
+
+ pod2html *.pm kdoc > kdocfunc.html
+
+If only pod was as usable as javadoc. maybe kdoc could... naah, 2 languages are
+enough for now. ;)
+
+Ast
+---
+
+AST nodes used by kdoc are very flexible. You can assign as many
+properties as you like, and each property can be a scalar or list (perhaps
+other nodes).
+
+this list may not be complete, but all important properties should be here.
+
+-> properties of all nodes:
+astNodeName string name of node, ie class, function, method name etc.
+NodeType string describing node type.
+
+-> properties of all syntax nodes:
+Forward Only Forward declaration yet.
+Compound can contain other nodes (see: KidHash)
+ExtSource came from a library
+Parent Parent node (root nodes have no parent)
+Access Visibility from parent (public, private, etc.)
+DocNode Documentation node, if it exists
+Deprecated
+Internal
+
+-> properties of compound nodes:
+Kids List of all kids
+KidHash hash of all kids by name
+KidAccess Access that should be set for new children
+Ancestors List of ancestors as parsed (See "ancestor nodes" )
+InList list of ancestor nodes.
+InBy list of derived nodes.
+Pure Contains pure virtuals
+
+-> ancestor nodes
+astNodeName Ancestor name as parsed
+Type Type of derivation (eg "virtual protected");
+Node A reference to the ancestor. Created by makeInherit.
+TmplType The inherited template args, if present.
+
+-> properties of DocNode as attached to syntax nodes: (kdocDocParse.pm)
+
+These currently hold 3 kinds of documentation. See the exact property
+names in kdocParseDoc::newDocNode().
+
+TextProperties Nodes, stored sequentially in Text
+ This is normal text, parabreaks, params, and @li (list items)
+
+doc and list Props Nodes, stored in 1 property per type
+ This is stuff that is not regular text, ie short name, returns etc.
+
+code props Properties of the node to which we will be attached
+ Currently this is just deprecated and internal.
+ NOTE: now all code props are lists, to allow for stuff like
+ groups.
+
+
+Parser (kdoc)
+------
+
+The parser assumes that a single declaration is a bunch of non-comment
+text uptil a ";" or "{"
+
+When identifyDecl is called with such a decl, all blank lines, comments
+and newlines are removed. This makes the regexp matching in identifyDecl
+much easier.
+
+If identifyDecl returns true and the decl finished with a {, the parser
+will skip all text till the matching } (ie nested {} is handled).
+
+Of course, in the case of compound decls (structs, classes etc), this means
+that we should return false since we want to parse everything in the class
+as well.
+
+The current node is stored in $cNode. A stack is maintained for parsed
+nodes, so everytime we enter a new compound node we push the current
+node onto the stack. the node will be popped once an compound end "};"
+is reached.
+
+Languages
+---------
+
+One root node is maintained per language. The correct node is selected
+depending on the file extension, using the getRoot sub.
+
+Libraries (kdocLib.pm)
+---------
+
+Libraries are now read directly into the parse tree and treated like syntax
+elements, except that their ExtSource property is set. The old library format
+is still supported, but the new one stores slightly more information, including
+the class hierarchy.
+
+
+AST routines (kdocAstUtil.pm)
+------------
+
+These are general routines that are used for all languages and output formats.
+They include generation of the hierarchy, finding of syntax nodes by identifier.
+Fully qualified and unqualified identifiers are supported.
+
+Output
+------
+
+Just like the old kdoc, the correct output module is loaded and called
+once all parsing is done and the tree has been post-processed as much
+as possible (hierarchy etc).
+
+Options
+-------
+
+The options have changed but are better, IMHO. Also, I now use Getopt::Long
+which makes option processing much easier and very robust.
+
+Thanks for reading this far.
+
+Sirtaj <taj@kde.org>
--- /dev/null
+prefix=@prefix@
+Version = @Version@
+mandir=@mandir@
+docdir=@docdir@
+install=@INSTALL@
+
+MANPAGES = kdoc.1 makekdedoc.1 qt2kdoc.1
+MAINDOC = @srcdir@/kdoc.docbook @top_srcdir@/README
+
+all: ${MANPAGES}
+
+install:
+ ${install} -d $(DESTDIR)${mandir}
+ for file in ${MANPAGES}; do \
+ ${install} -m 644 $$file $(DESTDIR)${mandir}; \
+ done
+
+ ${install} -d ${DESTDIR}${docdir}
+ ${install} -m 644 ${MAINDOC} ${DESTDIR}${docdir}
+ for file in ${MAINDOC}; do \
+ ${install} -m 644 $$file $(DESTDIR)${docdir}; \
+ done
+
+
+kdoc.1: @srcdir@/kdoc.pod @top_srcdir@/Version
+ pod2man --center "KDOC Documentation System" --release "${Version}" \
+ @srcdir@/kdoc.pod > kdoc.1.local && mv kdoc.1.local kdoc.1
+
+makekdedoc.1: @top_srcdir@/makekdedoc @top_srcdir@/Version
+ pod2man --center "KDOC Documentation System" --release "${Version}" \
+ @top_srcdir@/makekdedoc > makekdedoc.1.local \
+ && mv makekdedoc.1.local makekdedoc.1
+
+qt2kdoc.1: @top_srcdir@/qt2kdoc @top_srcdir@/Version
+ pod2man --center "KDOC Documentation System" --release "${Version}" \
+ @top_srcdir@/qt2kdoc > qt2kdoc.1.local \
+ && mv qt2kdoc.1.local qt2kdoc.1
+
+clean:
+ rm -rf kdoc.1 makekdedoc.1 qt2kdoc.1
+
+
+html: kdoc.docbook
+ mkdir html; (cd html && jade -d \
+ /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl -t sgml \
+ ../$< )
--- /dev/null
+<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
+]>
+<book lang="EN" ID="KDOC">
+
+<!-- This header contains all of the meta-information for the document such
+as Authors, publish date, the abstract, and Keywords -->
+
+<bookinfo>
+
+<title>The KDOC Handbook</title>
+<subtitle>Write developer documentation, easily and quickly</subtitle>
+
+<authorgroup>
+<author>
+<firstname>Sirtaj</firstname>
+<othername>Singh</othername>
+<surname>Kang</surname>
+</author>
+</authorGroup>
+<address>
+<email>taj@kde.org</email>
+</address>
+
+<keywordset>
+<keyword>KDOC</keyword>
+<keyword>C++</keyword>
+<keyword>C</keyword>
+<keyword>KDE Libraries</keyword>
+<keyword>Documentation</keyword>
+<keyword>API</keyword>
+<keyword>Literate Programming</keyword>
+</keywordset>
+
+<date>10/11/1999</date>
+<releaseinfo>2.0.0</releaseinfo>
+
+<revhistory>
+<revision>
+<revnumber>0.1</revnumber>
+<date>10/11/1999</date>
+<authorinitials>S.S.K</authorinitials>
+</revision>
+</revhistory>
+
+<!-- Abstract about this handbook -->
+
+<abstract>
+
+<para> <application>KDOC</application> generates documentation in a
+variety of formats, directly from C, C++ and IDL interface definitions.
+<application>KDOC</application> uses specially formatted comments in
+the source to allow customized documentation. </para>
+
+</abstract>
+
+</bookinfo>
+
+
+<chapter ID="Introduction">
+ <title>Introduction</title>
+
+<Sect1 id="whatiskdoc">
+ <title>What is KDOC?</title>
+<para> <application>KDOC</application> generates documentation in a
+variety of formats, directly from C, C++ and IDL interface definitions.
+<application>KDOC</application> uses specially formatted comments in
+the source to allow customized documentation. </para>
+
+<para>It is also very useful as a general class browser for libraries,
+since the output is quickly navigable and many index views are
+presented.</para>
+
+<para>KDOC is distributed under the GNU General Public License. In short,
+this allows you to modify and redistribute the package as much as you
+like, but all modifications will automatically also fall under the
+GNU General Public License. See the file <filename>COPYING</filename>
+that comes with the distribution for the full text version of the
+license.</para>
+</Sect1>
+
+<Sect1 id="features">
+ <title>Features</title>
+ <ItemizedList Spacing="Normal">
+ <ListItem><para>Support for C, C++ and OMG CORBA IDL languages.
+ </para></ListItem>
+
+ <ListItem><para>Output in HTML, LaTeX, Manpage, Texinfo and
+ DocBook SGML formats. The DocBook format can in turn be
+ converted to various printable and online formats.
+ </para></ListItem>
+
+ <ListItem><para>Automatically works out many relationships
+ between objects and their properties, such as hierarchies,
+ overridden virtuals, non-instantiable (abstract) classes and more.
+ </para></ListItem>
+
+ <ListItem><para>Doc Comments are written in the javadoc style,
+ with many useful extensions for organizing, documenting
+ and presenting libraries.
+ </para></ListItem>
+
+ <ListItem><para>Supports a CPP (preprocessor) pass
+ via an external preprocessor, to expand macros and
+ <SystemItem>#ifdefs</SystemItem>. </para></ListItem>
+
+ <ListItem><para>Support for the Qt GUI Toolkit's signal and
+ slot specifiers.</para></ListItem>
+
+ <ListItem><para>Cross-reference documentation generated for other
+ libraries. Links and class hierarchies that reference external
+ libraries are correctly shown. </para></ListItem>
+
+ <ListItem><para>Includes <Application>makekdedoc</Application>,
+ an easy automake-like tool for generating documentation for
+ multiple libraries at once.</para></ListItem>
+
+ <ListItem><para>Includes <Application>qt2kdoc</Application>,
+ which allows you to link your documentation with the Qt GUI
+ Toolkit's HTML documentation as if it had been generated by
+ <Application>KDOC</Application> itself.
+ </para></ListItem>
+
+ <ListItem><para>An output mode that allows you to check for
+ errors or omissions in your documentation.</para></ListItem>
+ <ListItem><para>The application is written entirely in Perl, and
+ is therefore quite portable and extensible. </para></ListItem>
+
+ </ItemizedList>
+</Sect1>
+
+<Sect1 ID="History">
+ <title>History</title>
+<para>Torben Weis <email>weis@kde.org</email> wrote a perl script that
+proved how simple it was to parse the KDE Library headers to generate
+documentation that looked like the Qt documentation. </para>
+
+<para>Sirtaj Singh Kang <email>taj@kde.org</email> took it upon himself to
+extend this program to turn it into a full-fledged application. He found
+out the hard way that while it takes 10% effort to parse 75% of source,
+the next 10% takes another 100%. </para>
+
+<para>KDOC 1.0 still used some of Torben's source, but never really
+worked properly but was useful enough for a year or so.</para>
+
+<para>KDOC 2.0 is a complete rewrite of KDOC, and is much more extensible
+and robust, even though it has scores of new features that were impossible
+to put into 1.0.</para>
+
+</Sect1>
+
+
+</chapter>
+
+<chapter ID="usingkdoc">
+ <title>Using KDOC</title>
+
+<sect1 ID="Support-and-Downloads">
+ <title>Support and Downloads</title>
+
+<ItemizedList Spacing="Normal">
+
+<ListItem id="web">
+<epigraph><para>Web page</para></epigraph>
+<para><application>KDOC</application> has a web page at
+<ULink URL="http://www.ph.unimelb.edu.au/~ssk/kde/kdoc/">http://www.ph.unimelb.edu.au/~ssk/kde/kdoc/</ULink>.
+It can be downloaded from there.
+</para>
+</ListItem>
+
+<ListItem id="cvs">
+<epigraph><para>Via KDE CVS or CVSUp</para></epigraph>
+<para>You can checkout KDOC from the KDE CVS server in the module
+<userinput>kdoc</userinput>. This is the repository used for KDOC development,
+so it will always be up to date.
+</para>
+</ListItem>
+
+<ListItem id="mlist">
+<epigraph><para>Mailing List</para></epigraph>
+<para>There is a KDOC mailing list hosted by the KDE project, at
+<email>kdoc-list@kde.org</email>. To subscribe, mail
+<email>kdoc-list-request@kde.org</email>
+with <userinput>subscribe</userinput> in the message body (not the subject).
+</para>
+</ListItem>
+
+<ListItem id="faqref"><epigraph><para>The KDOC FAQ</para></epigraph>
+<para>
+The KDOC FAQ has answers to common questions and problems with KDOC.
+</para>
+</ListItem>
+
+<ListItem id="email">
+<epigraph><para>E-mail: The Last Resort</para></epigraph>
+<para>If all else fails, I will respond to decent questions via
+email, but I cannot promise prompt replies. Mail the KDOC "team" at
+<email>kdoc@kde.org</email>.</para>
+</ListItem>
+</ItemizedList>
+</sect1>
+
+
+<Sect1 ID="Installation">
+ <title>Installation</title>
+<Sect2 id="sys">
+<title>Supported Environments</title>
+<para>KDOC requires <application>Perl 5.004</application> to function.
+Most environments where this is installed are supported by KDOC.
+</para>
+<para>KDOC has been reported to run to some extent on Win32 (NT/95/98),
+but you may encounter some problems with filenames. Also, you will probably
+have to hack the install scripts and file locations manually since the
+configure script only works on UNIX.
+</para>
+</Sect2>
+<Sect2 id="build">
+ <title>Building the distribution</title>
+<para>
+The procedure for building KDOC is similar to most other GPL programs that
+come with a <application>configure</application> script.
+</para>
+<procedure>
+<step>
+<title>Unpack the distribution</title>
+<para>Unpack the distribution into a temporary directory. It will extract
+itself into its own directory. If you have downloaded the tar.bz2 version:
+<screen>
+<prompt>#</prompt> <userinput>bunzip2 < kdoc-2.0a1.tar.bz2 | tar xf -</userinput>
+</screen>
+</para>
+<para>Or if you have downloaded the tar.gz version:
+<screen>
+<prompt>#</prompt> <userinput>gunzip < kdoc-2.0a1.tar.gz | tar xf -</userinput>
+</screen>
+</para>
+<para>Replace the distribution file name in the above procedure with the one
+you have downloaded.</para>
+</step>
+<step>
+<title>Build the application</title>
+<para>This will configure KDOC to install itself in
+<filename>/usr/local/</filename>:
+<screen>
+<prompt>#</prompt> <userinput>cd kdoc-2.0a1</userinput>
+<prompt>#</prompt> <userinput>./configure</userinput>
+</screen>
+</para>
+<para>To install it in a different directory,
+say <filename>/opt/kdoc</filename>, add a prefix option to configure like this:
+<screen>
+<prompt>#</prompt> <userinput>./configure --prefix=/opt/kdoc</userinput>
+</screen>
+</para>
+</step>
+<step>
+<title>Perform the installation</title>
+<screen>
+<prompt>#</prompt> <userinput>make; make install</userinput>
+</screen>
+</step>
+<step>
+<title>Remove the temporary directory</title>
+<screen>
+<prompt>#</prompt> <userinput>cd ..</userinput>
+<prompt>#</prompt> <userinput>rm -rf kdoc-2.0a1</userinput>
+</screen>
+</step>
+</procedure>
+<para>Now kdoc should be installed on your system.</para>
+</Sect2>
+</Sect1>
+
+<Sect1 ID="cmdline">
+ <title>KDOC at the command line</title>
+<abstract>
+<para>The most up-to-date source for command line options is always the
+man page that is distributed with the application. This section
+will provide a general overview of how to run the program.</para>
+</abstract>
+</Sect1>
+
+</chapter>
+
+
+<chapter ID="writingkdoc">
+ <title>Writing Documentation</title>
+<Sect1 ID="Commenting-Source"><title>Commenting Source</title>
+<para>TODO: Explain doc comments. Explain tags. Examples.</para>
+</Sect1>
+<Sect1 ID="Commenting-Style">
+ <title>Tips on Style</title>
+<para>TODO: Various doc suggestions: internal/deprecated, short
+descriptions, link to Qt documentation guidelines.</para>
+</Sect1>
+</chapter>
+
+<chapter ID="faq">
+ <title>Frequently Asked Questions</title>
+<para>TODO: No questions, no answers.</para>
+</chapter>
+
+<chapter ID="AppendixA">
+ <title>Appendix A: Doc tag reference</title>
+<Sect1 id="tagsdoccmt">
+ <title>Doc Comments</title>
+ <para>TODO</para>
+</Sect1>
+<Sect1 id="tagscommon">
+ <title>Common tags</title>
+ <VariableList>
+ <VarListEntry>
+ <term>@li <text></term>
+ <ListItem><para>A list item.</para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@internal</term>
+ <ListItem><para>Mark member as internal to the
+ library and not for external use.</para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@deprecated</term>
+ <ListItem><para>Marks member as obsolete.</para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@version <string></term>
+ <ListItem><para>Provide version information about the
+ member. I normally set this to the RCS/CVS Id tag.
+ </para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@author <string></term>
+ <ListItem><para>Specify the author.</para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@since <string></term>
+ <ListItem><para>Specify the version of the API in which this
+ member was added.</para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@sect <string></term>
+ <ListItem><para>A section heading, for grouping your doc
+ comment logically.</para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term><pre> text </pre></term>
+ <ListItem><para>A block of literal (preformatted) text,
+ useful for code examples.</para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@image <path></term>
+ <ListItem><para>Embed an image in the output. This can be
+ set to a URL, but it is better to use a path if possible
+ since this will allow the image to be included in other
+ formats in the future.</para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@see <ref>,...</term>
+ <ListItem><para>Links to related information.</para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@ref <ref></term>
+ <ListItem><para>Like @see, but inline, so it can be used
+ within a text paragraph. Also, only one member can be
+ referenced at a time, so you will have to include multiple
+ @ref tags for multiple members.</para></ListItem>
+ </VarListEntry>
+
+ </VariableList>
+</Sect1>
+<Sect1 id="tagslibdoc">
+ <title>Tags for Library Documentation</title>
+ <para>To provide documentation for the entire library, use the
+ @libdoc tag within a doc comment. If this appears in a doc comment,
+ the comment is associated with the library instead of with the
+ following syntax member.
+ </para>
+ <VariableList>
+ <VarListEntry>
+ <term>@libdoc <string></term>
+ <ListItem><para>Marks a doc comment as documentation for
+ the library. The string is used as the title of the
+ library.</para></ListItem>
+ </VarListEntry>
+ </VariableList>
+</Sect1>
+
+<Sect1 id="tagsclass">
+ <title>Tags for Classes</title>
+
+ <VariableList>
+ <VarListEntry>
+ <term>@short <string></term>
+ <ListItem><para>Short description of the class, one
+ sentence long.</para>
+ <para>If class documentation is present but no short
+ description is specified, the first sentence (up to and
+ including the first period) is used instead.
+ </para>
+ </ListItem>
+ </VariableList>
+
+</Sect1>
+<Sect1 id="tagsfun">
+ <title>Tags for Functions</title>
+ <VariableList>
+ <VarListEntry>
+ <term>@param <paramname> <text></term>
+ <ListItem><para>Documentation for a parameter.
+ No check is done whether the parameter name specified
+ is actually a parameter of the function.
+ </para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@return <text></term>
+ <ListItem><para>Documentation for the value returned by
+ the function.</para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@throws <ref>,...</term>
+ <ListItem><para>Define the exceptions that may be thrown
+ from this function. Synonyms are: @exception and @raises.
+ </para></ListItem>
+ </VarListEntry>
+ <VarListEntry>
+ <term>@param <paramname> <text></term>
+ <ListItem><para>Documentation for a parameter.
+ No check is done whether the parameter name specified
+ is actually a parameter of the function.
+ </para></ListItem>
+ </VarListEntry>
+ </VariableList>
+</Sect1>
+</chapter>
+
+<chapter ID="AppendixB"><title>Appendix B: Utilities</title>
+<Sect1 id="qt2kdoc"><title>qt2kdoc: Link with Qt HTML documentation</title>
+</Sect1>
+<Sect1 id="makekdedoc"><title>makekdedoc: Generate docs for KDELIBS and other groups of libraries</title>
+</Sect1>
+</chapter>
+
+<chapter ID="AppendixC"><title>Appendix B: Other useful tools</title></chapter>
+
+</book>
--- /dev/null
+
+=head1 NAME
+
+KDOC -- Programmers' Documentation Extraction and Generation Tool
+
+=head1 SYNOPSIS
+
+ kdoc [-DqpieaP] [-f format] [-n libname] [-d outdir] [-u url] [-l lib]
+
+ kdoc [--help]
+
+ kdoc [--version]
+
+=head1 DESCRIPTION
+
+KDOC uses specially formatted comments in your C++ headers and CORBA IDL
+files to create cross-referenced documentation in various formats.
+
+KDOC can also correctly handle "signal" and "slot" specifiers as used by the
+Qt GUI Toolkit.
+
+=head1 EXAMPLES
+
+ kdoc -f html -d /home/web/komdoc -n kom *.idl
+ kdoc -d /home/web/kdecore
+ -u "http://www.mydomain/kdecore/"
+ -n kdecore ~/kdelibs/kdecore/*.h -lqt
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--stdin>, B<-i>
+
+Read the filenames to process from standard input. Ignored if
+filenames are specified at the command line.
+
+=item B<--format> <string>, B<-f> <string>
+
+Generate output in the specific format. This can be used many times to
+generate documentation in multiple formats. The default format is "html".
+
+See the OUTPUT FORMAT OPTIONS section for a list of available formats.
+
+=item B<--outputdir> <path>, B<-d> <path>
+
+Write output in the specified path.
+
+=item B<--url> <url>, B<-u> <url>
+
+The URL which will be used for links when cross-referencing with this library.
+
+=item B<--name> <string>, B<-n> <string>
+
+Set the name of the library being processed, eg "kdecore"
+If no name is set, no index file is produced.
+
+=item B<--xref> <library>, B<-l> <library>
+
+Cross-reference with the specified library. This will allow referencing
+of classes etc that exist in the linked library. This option can be
+specified multiple times.
+
+For linking to work, you need to have generated documentation for the
+linked library with kdoc, so that the necessary index file is produced.
+
+=item B<--libdir> <path>, B<-L> <path>
+
+Set the directory that will be used to store the index files generated
+for cross-referencing. This is also used to search for index files for
+xref. The default is $HOME/.kdoc.
+
+=item B<--compress>, B<-z>
+
+Compress generated KDOC index files with gzip to save space.
+
+=item B<--private>, B<-p>
+
+Document all private members. These are not documented by default.
+
+=item B<--skip-internal>, B<-i>
+
+Do not document internal members. They are documented as internal by default.
+
+=item B<--skip-deprecated>, B<-e>
+
+Do not document deprecated members. They are documented as deprecated by
+default.
+
+=item B<--strip-h-path>
+
+Strip the path from the filenames in the output.
+
+=back
+
+=head1 PREPROCESSOR OPTIONS
+
+=over 4
+
+=item B<--cpp>, B<-P>
+
+Pass each source file through the C preprocessor. Currently g++
+is required for this, but this requirement will change before
+2.0. Directories for inclusion in the preprocessor header search path
+can be specified via the B<-I> option.
+
+=item B<-cppcmd> <command>, B<-C> <command>
+
+Specify the preprocessor command that will be used. The default is:
+
+ g++ -Wp,-C -E
+
+All specified B<-I> paths will be appended to the command. This option
+quietly enables the B<-P> option.
+
+=item B<--includedir> <path>, B<-I> <path>
+
+Add a directory to the preprocessor's header search paths. Requires the
+B<-P> option. This option can be specified multiple times.
+
+=back
+
+=head1 OUTPUT FORMAT OPTIONS
+
+=over 4
+
+=item B<html>
+
+Output documentation in HTML format. This is the default.
+
+=item B<latex>
+
+Output documentation as a LaTeX document. (unimplemented)
+
+=item B<man>
+
+Output documentation as man pages. (unimplemented)
+
+=item B<texinfo>
+
+Output documentation in texinfo format. You must set the library name
+with the B<-n> option for the output to be generated.
+
+=item B<docbook>
+
+Output documentation in the DocBook SGML format. You must set the library
+name with the B<-n> option for the output to be generated.
+
+=item B<check>
+
+Print a report about the documentation, eg undocumented classes
+and functions.
+
+=back
+
+=head1 CROSS-REFERENCING LIBRARIES
+
+=head1 FILES
+
+=over 4
+
+=item B<*.kdoc>, B<*.kdoc.gz>
+
+These are files that contain information about a library that has been
+processed with kdoc. It is read for cross-referencing with other libraries
+when the B<-l> option is used.
+
+The B<.gz> extension signifies gzipped cross-reference files. kdoc is
+capable of reading these, and generates them when the B<-z> option is used.
+
+=back
+
+=head1 ENVIRONMENT
+
+=over 4
+
+=item B<KDOCLIBS>
+
+If this is set, it is used as the default for the directory where generated
+cross-reference index files are saved. See also the B<--libdir> option.
+
+=back
+
+=head1 SEE ALSO
+
+See L<qt2kdoc> for info on linking with the Qt docs, and L<makekdedoc> for
+info on generating documentation for the KDE libraries.
+
+=head1 BUGS
+
+Lots and Lots. Please send reports to the address B<kdoc@kde.org>.
+
+=head1 AUTHOR
+
+Sirtaj Singh Kang <taj@kde.org>. B<KDOC> has a web page at:
+ http://www.ph.unimelb.edu.au/~ssk/kde/kdoc
+
+=head1 COPYRIGHT
+
+The KDOC tool is Copyright (c) 1998 by Sirtaj Singh Kang. KDOC is free
+software under the conditions of the GNU Public License.
+
+=cut
--- /dev/null
+#!/bin/sh
+
+test -f perlbin && rm perlbin
+
+for p in `echo $PATH | tr ":" " "`
+do
+ if [ -x $p/perl ]
+ then
+ if $p/perl -e 'require 5.000;'
+ then
+ echo $p/perl > perlbin
+ exit 0
+ fi
+ fi
+
+done
+exit 1
--- /dev/null
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
--- /dev/null
+#!/usr/local/bin/perl
+
+# KDOC -- C++ and CORBA IDL interface documentation tool.
+# Sirtaj Singh Kang <taj@kde.org>, Jan 1999.
+# $Id$
+
+# All files in this project are distributed under the GNU General
+# Public License. This is Free Software.
+
+require 5.000;
+
+use Carp;
+use Getopt::Long;
+use File::Basename;
+use strict;
+
+use Ast;
+
+use kdocUtil;
+use kdocAstUtil;
+use kdocParseDoc;
+
+use vars qw/ %rootNodes $declNodeType %options @formats_wanted
+ @includeclasses $includeclasses
+ $libdir $libname $outputdir @libs $striphpath $doPrivate $readstdin
+ $Version $quiet $debug $parseonly $currentfile $cSourceNode $exe
+ %formats %flagnames $rootNode @classStack $cNode
+ $lastLine $docNode @includes $cpp $defcppcmd $cppcmd $inExtern
+ %stats /;
+
+## globals
+
+%rootNodes = (); # root nodes for each file type
+$declNodeType = undef; # last declaration type
+
+# All options
+
+%options = (); # hash of options (set getopt below)
+@formats_wanted = ();
+$libdir = $ENV{KDOCLIBS};
+$libname = "";
+$outputdir = ".";
+@libs = (); # list of includes
+$striphpath = 0;
+
+@includeclasses = (); # names of classes to include
+$includeclasses = "";
+
+$doPrivate = 0;
+$Version = "$Version\$";
+
+$quiet = 0;
+$debug = 0;
+$parseonly = 0;
+
+$currentfile = "";
+
+$cpp = 0;
+$defcppcmd = "g++ -Wp,-C -E";
+$cppcmd = "";
+
+$exe = basename $0;
+
+# Supported formats
+%formats = ( "html" => "kdocCxxHTML", "latex" => "kdocCxxLaTeX",
+ "texinfo" => "kdoctexi", "docbook" => "kdocCxxDocbook",
+ "check" => "kdocDocHelper", "idlhtml" => "kdocIDLhtml" );
+
+# these are for expansion of method flags
+%flagnames = ( v => 'virtual', 's' => 'static', p => 'pure',
+ c => 'const', l => 'slot', i => 'inline', n => 'signal' );
+
+
+=head1 KDOC -- Source documentation tool
+
+ Sirtaj Singh Kang <taj@kde.org>, Dec 1998.
+
+=cut
+
+# read options
+
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+GetOptions( \%options,
+ "format|f=s", \@formats_wanted,
+ "url|u=s",
+ "skip-internal|i",
+ "skip-deprecated|e",
+ "document-all|a",
+ "compress|z",
+
+ # HTML options
+ "html-cols=i",
+ "html-logo=s",
+
+ "strip-h-path", \$striphpath,
+ "outputdir|d=s", \$outputdir,
+ "stdin|i", \$readstdin,
+ "name|n=s", \$libname,
+ "help|h", \&show_usage,
+ "version|v|V", \&show_version,
+ "private|p", \$doPrivate,
+ "libdir|L=s", \$libdir,
+ "xref|l=s", \@libs,
+ "classes|c=s", \@includeclasses,
+
+ "cpp|P", \$cpp,
+ "cppcmd|C", \$cppcmd,
+ "includedir|I=s", \@includes,
+
+ "quiet|q", \$quiet,
+ "debug|D", \$debug,
+ "parse-only", \$parseonly )
+ || exit 1;
+
+$| = 1 if $debug;
+
+# preprocessor settings
+
+if ( $cppcmd eq "" ) {
+ $cppcmd = $defcppcmd;
+}
+else {
+ $cpp = 1;
+}
+
+if ($#includeclasses>=0)
+{
+ $includeclasses = join (" ", @includeclasses);
+ print "Using Classes: $includeclasses\n" unless $quiet;
+}
+
+if ( $#includes >= 0 && !$cpp ) {
+ die "$exe: --includedir requires --cpp\n";
+}
+
+# Check output formats. HTML is the default
+if( $#formats_wanted < 0 ) {
+ push @formats_wanted, "html";
+}
+
+foreach my $format ( @formats_wanted ) {
+ die "$exe: unsupported format '$format'.\n"
+ if !defined $formats{$format};
+}
+
+# Check if there any files to process.
+# We do it here to prevent the libraries being loaded up first.
+
+checkFileArgs();
+
+# work out libdir. This is created by kdocLib:writeDoc when
+# required.
+$libdir = $ENV{HOME}."/.kdoc" unless $libdir ne "";
+
+
+######
+###### main program
+######
+ readLibraries();
+ parseFiles();
+
+ if ( $parseonly ) {
+ print "\n\tParse Tree\n\t------------\n\n";
+ kdocAstUtil::dumpAst( $rootNode );
+ }
+ else {
+ writeDocumentation();
+ writeLibrary() unless $libname eq "";
+ }
+
+ kdocAstUtil::printDebugStats() if $debug;
+
+ exit 0;
+######
+
+sub checkFileArgs
+{
+ return unless $#ARGV < 0;
+
+ die "$exe: no input files.\n" unless $readstdin;
+
+ # read filenames from standard input
+ while (<STDIN>) {
+ chop;
+ $_ =~ s,\\,/,g; # back to fwd slash (for Windows)
+ foreach my $file ( split( /\s+/, $_ ) ) {
+ push @ARGV, $file;
+ }
+ }
+}
+
+sub readLibraries
+{
+ return if $#libs < 0;
+
+ require kdocLib;
+ foreach my $lib ( @libs ) {
+ print "$exe: reading lib: $lib\n" unless $quiet;
+
+ my $relpath = exists $options{url} ?
+ $options{url} : $outputdir;
+ kdocLib::readLibrary( \&getRoot, $lib, $libdir, $relpath );
+ }
+}
+
+sub parseFiles
+{
+ foreach $currentfile ( @ARGV ) {
+ my $lang = "CXX";
+
+ if ( $currentfile =~ /\.idl\s*$/ ) {
+ # IDL file
+ $lang = "IDL";
+
+ open( INPUT, "$currentfile" )
+ || croak "Can't read from $currentfile";
+ }
+ # assume cxx file
+ elsif( $cpp ) {
+ # pass through preprocessor
+ my $cmd = $cppcmd;
+ foreach my $dir ( @includes ) {
+ $cmd .= " -I $dir ";
+ }
+ open( INPUT, $cmd." -DQOBJECTDEFS_H $currentfile|" )
+ || croak "Can't preprocess $currentfile";
+ }
+ else {
+ open( INPUT, "$currentfile" )
+ || croak "Can't read from $currentfile";
+ }
+
+ print "$exe: processing $currentfile\n" unless $quiet;
+
+ # reset vars
+ $rootNode = getRoot( $lang );
+
+
+ # add to file lookup table
+ my $showname = $striphpath ? basename( $currentfile )
+ : $currentfile;
+
+ $cSourceNode = Ast::New( $showname );
+ $cSourceNode->AddProp( "NodeType", "source" );
+ $cSourceNode->AddProp( "Path", $currentfile );
+ $rootNode->AddPropList( "Sources", $cSourceNode );
+
+
+ # reset state
+ @classStack = ();
+ $cNode = $rootNode;
+ $inExtern = 0;
+
+ # parse
+ my $k = undef;
+ while ( defined ($k = readDecl()) ) {
+ print "\nDecl: <$k>[$declNodeType]\n" if $debug;
+ if( identifyDecl( $k ) && $k =~ /{/ ) {
+ readCxxCodeBlock();
+ }
+ }
+ close INPUT;
+ }
+}
+
+
+sub writeDocumentation
+{
+ foreach my $node ( values %rootNodes ) {
+ # postprocess
+ kdocAstUtil::linkNamespaces( $node );
+ kdocAstUtil::makeInherit( $node, $node );
+ kdocAstUtil::linkReferences( $node, $node );
+ kdocAstUtil::calcStats( \%stats, $node, $node );
+
+ # write
+ no strict "refs";
+ foreach my $format ( @formats_wanted ) {
+ my $pack = $formats{ $format };
+ require $pack.".pm";
+
+ print "Generating documentation in $format ",
+ "format...\n" unless $quiet;
+
+ my $f = "$pack\::writeDoc";
+ &$f( $libname, $node, $outputdir, \%options );
+ }
+ }
+}
+
+sub writeLibrary
+{
+ if( $libname ne "" ) {
+ require kdocLib;
+ foreach my $lang ( keys %rootNodes ) {
+ my $node = $rootNodes{ $lang };
+ kdocLib::writeDoc( $libname, $node, $lang, $libdir,
+ $outputdir, $options{url},
+ exists $options{compress} ? 1 : 0 );
+ }
+ }
+}
+
+###### Parser routines
+
+=head2 readSourceLine
+
+ Returns a raw line read from the current input file.
+ This is used by routines outside main, since I don't know
+ how to share fds.
+
+=cut
+
+sub readSourceLine
+{
+ return <INPUT>;
+}
+
+=head2 readCxxLine
+
+ Reads a C++ source line, skipping comments, blank lines,
+ preprocessor tokens and the Q_OBJECT macro
+
+=cut
+
+sub readCxxLine
+{
+ my( $p );
+ my( $l );
+
+ while( 1 ) {
+ return undef if !defined ($p = <INPUT>);
+
+ $p =~ s#//.*$##g; # C++ comment
+ $p =~ s#/\*(?!\*).*?\*/##g; # C comment
+
+ # join all multiline comments
+ if( $p =~ m#/\*(?!\*)#s ) {
+ # unterminated comment
+LOOP:
+ while( defined ($l = <INPUT>) ) {
+ $l =~ s#//.*$##g; # C++ comment
+ $p .= $l;
+ $p =~ s#/\*(?!\*).*?\*/##sg; # C comment
+ last LOOP unless $p =~ m#(/\*(?!\*))|(\*/)#sg;
+ }
+ }
+
+ next if ( $p =~ /^\s*$/s # blank lines
+ || $p =~ /^\s*Q_OBJECT/ # QObject macro
+ );
+
+ # remove all preprocessor macros
+ if( $p =~ /^\s*#\s*(\w+)/ ) {
+ if ($p =~ /^\s*#\s*[0-9]+\s*\".*$/
+ && not($p =~ /\"$currentfile\"/)) {
+ # include file markers
+ while( <INPUT> ) {
+ last if(/\"$currentfile\"/);
+ print "Overread $_" if $debug;
+ };
+ print "Cont: $_" if $debug;
+ }
+ else {
+ # multiline macros
+ while ( defined $p && $p =~ m#\\\s*$# ) {
+ $p = <INPUT>;
+ }
+ }
+ next;
+ }
+
+ $lastLine = $p;
+ return $p;
+ }
+}
+
+=head2 readCxxCodeBlock
+
+ Reads a C++ code block (recursive curlies), returning the last line
+ or undef on error.
+
+ Parameters: none
+
+=cut
+
+sub readCxxCodeBlock
+{
+# Code: begins in a {, ends in }\s*;?
+# In between: cxx source, including {}
+ my ( $count ) = 0;
+ my $l = undef;
+
+ if ( defined $lastLine ) {
+ print "lastLine: '$lastLine'" if $debug;
+
+ my $open = kdocUtil::countReg( $lastLine, "{" );
+ my $close = kdocUtil::countReg( $lastLine, "}" );
+ $count = $open - $close;
+
+ return $lastLine if ( $open || $close) && $count == 0;
+ }
+
+ # find opening brace
+ if ( $count == 0 ) {
+ while( $count == 0 ) {
+ $l = readCxxLine();
+ return undef if !defined $l;
+ $l =~ s/\\.//g;
+ $l =~ s/'.?'//g;
+ $l =~ s/".*?"//g;
+
+ $count += kdocUtil::countReg( $l, "{" );
+ print "c ", $count, " at '$l'" if $debug;
+ }
+ $count -= kdocUtil::countReg( $l, "}" );
+ }
+
+ # find associated closing brace
+ while ( $count > 0 ) {
+ $l = readCxxLine();
+ croak "Confused by unmatched braces" if !defined $l;
+ $l =~ s/\\.//g;
+ $l =~ s/'.?'//g;
+ $l =~ s/".*?"//g;
+
+ my $add = kdocUtil::countReg( $l, "{" );
+ my $sub = kdocUtil::countReg( $l, "}" );
+ $count += $add - $sub;
+
+ print "o ", $add, " c ", $sub, " at '$l'" if $debug;
+ }
+
+ undef $lastLine;
+ return $l;
+}
+
+=head2 readDecl
+
+ Returns a declaration and sets the $declNodeType variable.
+
+ A decl starts with a type or keyword and ends with [{};]
+ The entire decl is returned in a single line, sans newlines.
+
+ declNodeType values: undef for error, "a" for access specifier,
+ "c" for doc comment, "d" for other decls.
+
+ readCxxLine is used to read the declaration.
+
+=cut
+
+sub readDecl
+{
+ undef $declNodeType;
+ my $l = readCxxLine();
+ my ( $decl ) = "";
+
+ if( !defined $l ) {
+ return undef;
+ }
+ elsif ( $l =~ /^\s*(private|public|protected|signals)
+ (\s+\w+)?\s*:/x ) { # access specifier
+ $declNodeType = "a";
+
+ return $l;
+ }
+ elsif ( $l =~ m#^\s*/\*\*# ) { # doc comment
+ $declNodeType = "c";
+ return $l;
+ }
+
+ do {
+ $decl .= $l;
+
+ if ( $l =~ /[{};]/ ) {
+ $decl =~ s/\n/ /gs;
+ $declNodeType = "d";
+ return $decl;
+ }
+ return undef if !defined ($l = readCxxLine());
+
+ } while ( 1 );
+}
+
+#### AST Generator Routines
+
+=head2 getRoot
+
+ Return a root node for the given type of input file.
+
+=cut
+
+sub getRoot
+{
+ my $type = shift;
+ carp "getRoot called without type" unless defined $type;
+
+ if ( !exists $rootNodes{ $type } ) {
+ my $node = Ast::New( "Global" ); # parent of all nodes
+ $node->AddProp( "NodeType", "root" );
+ $node->AddProp( "RootType", $type );
+ $node->AddProp( "Compound", 1 );
+ $node->AddProp( "KidAccess", "public" );
+
+ $rootNodes{ $type } = $node;
+ }
+ print "getRoot: call for $type\n" if $debug;
+
+ return $rootNodes{ $type };
+}
+
+=head2 identifyDecl
+
+ Parameters: decl
+
+ Identifies a declaration returned by readDecl. If a code block
+ needs to be skipped, this subroutine returns a 1, or 0 otherwise.
+
+=cut
+
+sub identifyDecl
+{
+ my( $decl ) = @_;
+
+ my $newNode = undef;
+ my $skipBlock = 0;
+
+ # Doc comment
+ if ( $declNodeType eq "c" ) {
+ $docNode = kdocParseDoc::newDocComment( $decl );
+
+ # if it's the main doc, it is attached to the root node
+ if ( defined $docNode->{LibDoc} ) {
+ kdocParseDoc::attachDoc( $rootNode, $docNode,
+ $rootNode );
+ undef $docNode;
+ }
+
+ }
+ elsif ( $declNodeType eq "a" ) {
+ newAccess( $decl );
+ }
+
+ # Typedef struct/class
+ elsif ( $decl =~ /^\s*typedef
+ \s+(struct|union|class|enum)
+ \s*([_\w\:]*)
+ \s*([;{])
+ /xs ) {
+ my ($type, $name, $endtag, $rest ) = ($1, $2, $3, $' );
+ $name = "--" if $name eq "";
+
+ warn "typedef '$type' n:'$name'\n" if $debug;
+
+ if ( $rest =~ /}\s*([\w_]+(?:::[\w_])*)\s*;/ ) {
+ # TODO: Doesn't parse members yet!
+ $endtag = ";";
+ $name = $1;
+ }
+
+ $newNode = newTypedefComp( $type, $name, $endtag );
+ }
+
+ # Typedef
+ elsif ( $decl =~ /^\s*typedef\s+
+ (.*?\s*[\*&]?) # type
+ \s*([-\w_\:]+) # name
+ \s*[{;]\s*$/xs ) {
+
+ print "Typedef: <$1> <$2>\n" if $debug;
+ $newNode = newTypedef( $1, $2 );
+ }
+
+ # Enum
+ elsif ( $decl =~ /^\s*enum(\s+[-\w_:]*)?\s*\{(.*)/s ) {
+
+ print "Enum: <$1>\n" if $debug;
+ my $enumname = defined $2 ? $1 : "";
+
+ $newNode = newEnum( $enumname );
+ }
+
+ # Class/Struct
+ elsif ( $decl =~ /^\s*((?:template\s*<.*>)?) # 1 template
+ \s*(class|struct|union|namespace) # 2 struct type
+ \s+([\w_]+ # 3 name
+ (?:<[\w_ :,]+?>)? # maybe explicit template
+ # (eat chars between <> non-hungry)
+ (?:::[\w_]+)* # maybe nested
+ )
+ (.*?) # 4 inheritance
+ ([;{])/xs ) { # 5 rest
+
+ print "Class: [$1]\n\t[$2]\n\t[$3]\n\t[$4]\n\t[$5]\n" if $debug;
+ my ( $tmpl, $ntype, $name, $rest, $endtag ) =
+ ( $1, $2, $3, $4, $5 );
+
+ if ($includeclasses)
+ {
+ if (! ($includeclasses =~ /$name/) )
+ {
+ return 1;
+
+ }
+ }
+
+ my @inherits = ();
+
+ $tmpl =~ s/<(.*)>/$1/ if $tmpl ne "";
+
+ if( $rest =~ /^\s*:\s*/ ) {
+ # inheritance
+ $rest = $';
+ @inherits = parseInheritance( $rest );
+ }
+
+ $newNode = newClass( $tmpl, $ntype,
+ $name, $endtag, @inherits );
+ }
+ # IDL compound node
+ elsif( $decl =~ /^\s*(module|interface|exception) # struct type
+ \s+([-\w_]+) # name
+ (.*?) # inheritance?
+ ([;{])/xs ) {
+
+ my ( $type, $name, $rest, $fwd, $complete )
+ = ( $1, $2, $3, $4 eq ";" ? 1 : 0,
+ 0 );
+ my @in = ();
+ print "IDL: [$type] [$name] [$rest] [$fwd]\n" if $debug;
+
+ if( $rest =~ /^\s*:\s*/ ) {
+ $rest = $';
+ $rest =~ s/\s+//g;
+ @in = split ",", $rest;
+ }
+ if( $decl =~ /}\s*;/ ) {
+ $complete = 1;
+ }
+
+ $newNode = newIDLstruct( $type, $name, $fwd, $complete, @in );
+ }
+ # Method
+ elsif ( $decl =~ /^\s*([^=]+?(?:operator\s*(?:\(\)|.?=)\s*)?) # ret+nm
+ \( (.*?) \) # parameters
+ \s*((?:const)?)\s*
+ \s*((?:=\s*0(?:L?))?)\s* # Pureness. is "0L" allowed?
+ \s*[;{]+/xs ) { # rest
+
+ print "Method: R+N:[$1]\n\tP:[$2]\n\t[$3]\n" if $debug;
+
+ my $tpn = $1; # type + name
+ my $params = $2;
+
+ my $const = $3 eq "" ? 0 : 1;
+ my $pure = $4 eq "" ? 0 : 1;
+
+ if ( $tpn =~ /((?:\w+\s*::\s*)?operator.*?)\s*$/ # operator
+ || $tpn =~ /((?:\w*\s*::\s*~?)?[-\w:]+)\s*$/ ) { # normal
+ my $name = $1;
+ $tpn = $`;
+ $newNode = newMethod( $tpn, $name,
+ $params, $const, $pure );
+ }
+
+ $skipBlock = 1; # FIXME check end token before doing this!
+ }
+ # Using: import namespace
+ elsif ( $decl =~ /^\s*using\s+namespace\s+(\w+)/ ) {
+ newNamespace( $1 );
+
+ }
+
+ # extern block
+ elsif ( $decl =~ /^\s*extern\s*"(.*)"\s*{/ ) {
+ $inExtern = 1 unless $decl =~ /}/;
+ }
+
+ # Single variable
+ elsif ( $decl =~ /^
+ \s*( (?:[\w_:]+(?:\s+[\w_:]+)*? )# type
+ \s*(?:<.+>)? # template
+ \s*(?:[\&\*])? # ptr or ref
+ (?:\s*(?:const|volatile))* )
+ \s*([\w_:]+) # name
+ \s*( (?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? ) # array
+ \s*((?:=.*)?) # value
+ \s*([;{])\s*$/xs ) {
+ my $type = $1;
+ my $name = $2;
+ my $arr = $3;
+ my $val = $4;
+ my $end = $5;
+
+ print "Var: [$name] type: [$type$arr] val: [$val]\n"
+ if $debug;
+
+ $newNode = newVar( $type.$arr, $name, $val );
+
+ $skipBlock = 1 if $end eq '{';
+
+ }
+
+ # Multi variables
+ elsif ( $decl =~ m/^
+ \s*( (?:[\w_:]+(?:\s+[\w_:]+)*? ) # type
+ \s*(?:<.+>)?) # template
+
+ \s*( (?:\s*(?: [\&\*][\&\*\s]*)? # ptr or ref
+ [\w_:]+) # name
+ \s*(?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? # array
+ \s*(?:, # extra vars
+ \s*(?: [\&\*][\&\*\s]*)? # ptr or ref
+ \s*(?:[\w_:]+) # name
+ \s*(?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? # array
+ )*
+ \s*(?:=.*)?) # value
+ \s*[;]/xs ) {
+
+ my $type = $1;
+ my $names = $2;
+ my $end = $3;
+ my $doc = $docNode;
+
+ print "Multivar: type: [$type] names: [$names] \n" if $debug;
+
+ foreach my $vardecl ( split( /\s*,\s*/, $names ) ) {
+ next unless $vardecl =~ m/
+ \s*((?: [\&\*][\&\*\s]*)?) # ptr or ref
+ \s*([\w_:]+) # name
+ \s*( (?:\[[^\[\]]*\] (?:\s*\[[^\[\]]*\])*)? ) # array
+ \s*((?:=.*)?) # value
+ /xs;
+ my ($ptr, $name, $arr, $val) = ($1, $2, $3, $4);
+
+ print "Split: type: [$type$ptr$arr] ",
+ " name: [$name] val: [$val] \n" if $debug;
+
+ my $node = newVar( $type.$ptr.$arr, $name, $val );
+
+ $docNode = $doc; # reuse docNode for each
+ postInitNode( $node ) unless !defined $node;
+ }
+
+ $skipBlock = 1 if $end eq '{';
+ }
+ # end of an "extern" block
+ elsif ( $decl =~ /^\s*}\s*$/ ) {
+ $inExtern = 0;
+ }
+ # end of an in-block declaration
+ elsif ( $decl =~ /^\s*}\s*(.*?)\s*;\s*$/ ) {
+
+ if ( $cNode->{astNodeName} eq "--" ) {
+ # structure typedefs should have no name preassigned.
+ # If they do, then the name in
+ # "typedef struct <name> { ..." is kept instead.
+ # TODO: Buglet. You should fix YOUR code dammit. ;)
+
+
+ $cNode->{astNodeName} = $1;
+ my $siblings = $cNode->{Parent}->{KidHash};
+ undef $siblings->{"--"};
+ $siblings->{ $1 } = $cNode;
+ }
+
+ if ( $#classStack < 0 ) {
+ confess "close decl found, but no class in stack!" ;
+ $cNode = $rootNode;
+ }
+ else {
+ $cNode = pop @classStack;
+ print "end decl: popped $cNode->{astNodeName}\n"
+ if $debug;
+ }
+ }
+ # unidentified block start
+ elsif ( $decl =~ /{/ ) {
+ print "Unidentified block start: $decl\n" if $debug;
+ $skipBlock = 1;
+ }
+ else {
+
+ ## decl is unidentified.
+ warn "Unidentified decl: $decl\n";
+ }
+
+ # once we get here, the last doc node is already used.
+ # postInitNode should NOT be called for forward decls
+ postInitNode( $newNode ) unless !defined $newNode;
+
+ return $skipBlock;
+}
+
+sub postInitNode
+{
+ my $newNode = shift;
+
+ carp "Cannot postinit undef node." if !defined $newNode;
+
+ # The reasoning here:
+ # Forward decls never get a source node.
+ # Once a source node is defined, don't assign another one.
+
+ if ( $newNode->{NodeType} ne "Forward" && !defined $newNode->{Source}) {
+ $newNode->AddProp( "Source", $cSourceNode );
+ }
+ elsif ($debug) {
+ print "postInit: skipping fwd: $newNode->{astNodeName}\n";
+ }
+
+ if( defined $docNode ) {
+ kdocParseDoc::attachDoc( $newNode, $docNode, $rootNode );
+ undef $docNode;
+ }
+}
+
+
+##### Node generators
+
+=head2 newEnum
+
+ Reads the parameters of an enumeration.
+
+ Returns the parameters, or undef on error.
+
+=cut
+
+sub newEnum
+{
+ my ( $enum ) = @_;
+ my $k = undef;
+ my $params = "";
+
+ $k = $lastLine if defined $lastLine;
+
+ if( defined $lastLine && $lastLine =~ /{/ ) {
+ $params = $';
+ if ( $lastLine =~ /}(.*?);/ ) {
+ return initEnum( $enum, $1, $params );
+ }
+ }
+
+ while ( defined ( $k = readCxxLine() ) ) {
+ $params .= $k;
+
+ if ( $k =~ /}(.*?);/ ) {
+ return initEnum( $enum, $1, $params );
+ }
+ }
+
+ return undef;
+}
+
+=head2 initEnum
+
+ Parameters: name, (ref) params
+
+ Returns an initialized enum node.
+
+=cut
+
+sub initEnum
+{
+ my( $name, $end, $params ) = @_;
+
+ ($name = $end) if $name eq "" && $end ne "";
+
+ $params =~ s#\s+# #sg; # no newlines
+ $params = $1 if $params =~ /^\s*{?(.*)}/;
+ print "$name params: [$params]\n" if $debug;
+
+
+ my ( $node ) = Ast::New( $name );
+ $node->AddProp( "NodeType", "enum" );
+ $node->AddProp( "Params", $params );
+ kdocAstUtil::attachChild( $cNode, $node );
+
+ return $node;
+}
+
+=head2 newIDLstruct
+
+ Parameters: type, name, forward, complete, inherits...
+
+ Handles an IDL structure definition (ie module, interface,
+ exception).
+
+=cut
+
+sub newIDLstruct
+{
+ my ( $type, $name, $fwd, $complete ) = @_;
+
+ my $node = exists $cNode->{KidHash} ?
+ $cNode->{KidHash}->{ $name } : undef;
+
+ if( !defined $node ) {
+ $node = Ast::New( $name );
+ $node->AddProp( "NodeType", $fwd ? "Forward" : $type );
+ $node->AddProp( "KidAccess", "public" );
+ $node->AddProp( "Compound", 1 ) unless $fwd;
+ kdocAstUtil::attachChild( $cNode, $node );
+ }
+ elsif ( $fwd ) {
+ # If we have a node already, we ignore forwards.
+ return undef;
+ }
+ elsif ( $node->{NodeType} eq "Forward" ) {
+ # we are defining a previously forward node.
+ $node->AddProp( "NodeType", $type );
+ $node->AddProp( "Compound", 1 );
+ $node->AddProp( "Source", $cSourceNode );
+ }
+
+ # register ancestors.
+ foreach my $ances ( splice ( @_, 4 ) ) {
+ my $n = kdocAstUtil::newInherit( $node, $ances );
+ }
+
+ if( !( $fwd || $complete) ) {
+ print "newIDL: pushing $cNode->{astNodeName},",
+ " new is $node->{astNodeName}\n"
+ if $debug;
+ push @classStack, $cNode;
+ $cNode = $node;
+ }
+
+ return $node;
+}
+
+=head2 newClass
+
+ Parameters: tmplArgs, cNodeType, name, endTag, @inheritlist
+
+ Handles a class declaration (also fwd decls).
+
+=cut
+
+sub newClass
+{
+ my( $tmplArgs, $cNodeType, $name, $endTag ) = @_;
+
+ my $access = "private";
+ $access = "public" if $cNodeType ne "class";
+
+ # try to find an exisiting node, or create a new one
+ my $oldnode = kdocAstUtil::findRef( $cNode, $name );
+ my $node = defined $oldnode ? $oldnode : Ast::New( $name );
+
+ if ( $endTag ne "{" ) {
+ # forward
+ if ( !defined $oldnode ) {
+ # new forward node
+ $node->AddProp( "NodeType", "Forward" );
+ $node->AddProp( "KidAccess", $access );
+ kdocAstUtil::attachChild( $cNode, $node );
+ }
+ return $node;
+ }
+
+ # this is a class declaration
+
+ print "ClassName: $name\n" if $debug;
+
+ $node->AddProp( "NodeType", $cNodeType );
+ $node->AddProp( "Compound", 1 );
+ $node->AddProp( "Source", $cSourceNode );
+
+ $node->AddProp( "KidAccess", $access );
+ $node->AddProp( "Tmpl", $tmplArgs ) unless $tmplArgs eq "";
+
+ if ( !defined $oldnode ) {
+ kdocAstUtil::attachChild( $cNode, $node );
+ }
+
+ # inheritance
+
+ foreach my $ances ( splice (@_, 4) ) {
+ my $type = "";
+ my $name = $ances;
+ my $intmpl = undef;
+
+WORD:
+ foreach my $word ( split ( /([\w:]+(:?\s*<.*>)?)/, $ances ) ) {
+ next WORD unless $word =~ /^[\w:]/;
+ if ( $word =~ /(private|public|protected|virtual)/ ) {
+ $type .= "$1 ";
+ }
+ else {
+
+ if ( $word =~ /<(.*)>/ ) {
+ # FIXME: Handle multiple tmpl args
+ $name = $`;
+ $intmpl = $1;
+ }
+ else {
+ $name = $word;
+ }
+
+ last WORD;
+ }
+ }
+
+ # set inheritance access specifier if none specified
+ if ( $type eq "" ) {
+ $type = $cNodeType eq "class" ? "private ":"public ";
+ }
+ chop $type;
+
+ # attach inheritance information
+ my $n = kdocAstUtil::newInherit( $node, $name );
+ $n->AddProp( "Type", $type );
+
+ $n->AddProp( "TmplType", $intmpl ) if defined $intmpl;
+
+ print "In: $name type: $type, tmpl: $intmpl\n" if $debug;
+ }
+
+ # new current node
+ print "newClass: Pushing $cNode->{astNodeName}\n" if $debug;
+ push ( @classStack, $cNode );
+ $cNode = $node;
+
+ return $node;
+}
+
+
+=head3 parseInheritance
+
+ Param: inheritance decl string
+ Returns: list of superclasses (template decls included)
+
+ This will fail if < and > appear in strings in the decl.
+
+=cut
+
+sub parseInheritance
+{
+ my $instring = shift;
+ my @inherits = ();
+
+ my $accum = "";
+ foreach $instring ( split (/\s*,\s*/, $instring) ) {
+ $accum .= $instring.", ";
+ next unless (kdocUtil::countReg( $accum, "<" )
+ - kdocUtil::countReg( $accum, ">" ) ) == 0;
+
+ # matching no. of < and >, so assume the parent is
+ # complete
+ $accum =~ s/,\s*$//;
+ print "Inherits: '$accum'\n" if $debug;
+ push @inherits, $accum;
+ $accum = "";
+ }
+
+ return @inherits;
+}
+
+
+=head2 newNamespace
+
+ Param: namespace name.
+ Returns nothing.
+
+ Imports a namespace into the current node, for ref searches etc.
+ Triggered by "using namespace ..."
+
+=cut
+
+sub newNamespace
+{
+ $cNode->AddPropList( "ImpNames", shift );
+}
+
+
+
+=head2 newTypedef
+
+ Parameters: realtype, name
+
+ Handles a type definition.
+
+=cut
+
+sub newTypedef
+{
+ my ( $realtype, $name ) = @_;
+
+ my ( $node ) = Ast::New( $name );
+
+ $node->AddProp( "NodeType", "typedef" );
+ $node->AddProp( "Type", $realtype );
+
+ kdocAstUtil::attachChild( $cNode, $node );
+
+ return $node;
+}
+
+=head2 newTypedefComp
+
+ Params: realtype, name endtoken
+
+ Creates a new compound type definition.
+
+=cut
+
+sub newTypedefComp
+{
+ my ( $realtype, $name, $endtag ) = @_;
+
+ my ( $node ) = Ast::New( $name );
+
+ $node->AddProp( "NodeType", "typedef" );
+ $node->AddProp( "Type", $realtype );
+
+ kdocAstUtil::attachChild( $cNode, $node );
+
+ if ( $endtag eq '{' ) {
+ print "newTypedefComp: Pushing $cNode->{astNodeName}\n"
+ if $debug;
+ push ( @classStack, $cNode );
+ $cNode = $node;
+ }
+
+ return $node;
+}
+
+
+=head2 newMethod
+
+ Parameters: retType, name, params, const, pure?
+
+ Handles a new method declaration or definition.
+
+=cut
+
+sub newMethod
+{
+ my ( $retType, $name, $params, $const, $pure ) = @_;
+ my $parent = $cNode;
+ my $class;
+
+ print "Cracked: [$retType] [$name]\n\t[$params]\n\t[$const]\n"
+ if $debug;
+
+ if ( $retType =~ /([\w\s_<>,]+)\s*::\s*$/ ) {
+ # check if stuff before :: got into rettype by mistake.
+ $retType = $`;
+ ($name = $1."::".$name);
+ $name =~ s/\s+/ /g;
+ print "New name = \"$name\" and type = '$retType'\n" if $debug;
+ }
+
+ if( $name =~ /^\s*(.*?)\s*::\s*(.*?)\s*$/ ) {
+ # Fully qualified method name.
+ $name = $2;
+ $class = $1;
+
+ if( $class =~ /^\s*$/ ) {
+ $parent = $rootNode;
+ }
+ elsif ( $class eq $cNode->{astNodeName} ) {
+ $parent = $cNode;
+ }
+ else {
+ my $node = kdocAstUtil::findRef( $cNode, $class );
+
+ if ( !defined $node ) {
+ # if we couldn't find the name, try again with
+ # all template parameters stripped off:
+ my $strippedClass = $class;
+ $strippedClass =~ s/<[^<>]*>//g;
+
+ $node = kdocAstUtil::findRef( $cNode, $strippedClass );
+
+ # if still not found: give up
+ if ( !defined $node ) {
+ warn "$exe: Unidentified class: $class ".
+ "in $currentfile\:$.\n";
+ return undef;
+ }
+ }
+
+ $parent = $node;
+ }
+ }
+ else {
+ # Within current class/global
+ }
+
+
+ # flags
+
+ my $flags = "";
+
+ if( $retType =~ /static/ ) {
+ $flags .= "s";
+ $retType =~ s/static//g;
+ }
+
+ if( $const ) {
+ $flags .= "c";
+ }
+
+ if( $pure ) {
+ $flags .= "p";
+ }
+
+ if( $retType =~ /virtual/ ) {
+ $flags .= "v";
+ $retType =~ s/virtual//g;
+ }
+
+ print "\n" if $flags ne "" && $debug;
+
+ if ( !defined $parent->{KidAccess} ) {
+ warn "'", $parent->{astNodeName}, "' has no KidAccess ",
+ exists $parent->{Forward} ? "(forward)\n" :"\n";
+ }
+
+ if ( $parent->{KidAccess} =~ /slot/ ) {
+ $flags .= "l";
+ }
+ elsif ( $parent->{KidAccess} =~ /signal/ ) {
+ $flags .= "n";
+ }
+
+ # node
+
+ my $node = Ast::New( $name );
+ $node->AddProp( "NodeType", "method" );
+ $node->AddProp( "Flags", $flags );
+ $node->AddProp( "ReturnType", $retType );
+ $node->AddProp( "Params", $params );
+
+ $parent->AddProp( "Pure", 1 ) if $pure;
+ kdocAstUtil::attachChild( $parent, $node );
+
+ return $node;
+}
+
+
+=head2 newAccess
+
+ Parameters: access
+
+ Sets the default "Access" specifier for the current class node. If
+ the access is a "slot" type, "_slots" is appended to the access
+ string.
+
+=cut
+
+sub newAccess
+{
+ my ( $access ) = @_;
+
+ return undef unless ($access =~ /^\s*(\w+)\s*(slots)?/);
+
+ print "Access: [$1] [$2]\n" if $debug;
+
+ $access = $1;
+
+ if ( defined $2 && $2 ne "" ) {
+ $access .= "_" . $2;
+ }
+
+ $cNode->AddProp( "KidAccess", $access );
+
+ return $cNode;
+}
+
+
+=head2 newVar
+
+ Parameters: type, name, value
+
+ New variable. Value is ignored if undef
+
+=cut
+
+sub newVar
+{
+ my ( $type, $name, $val ) = @_;
+
+ my $node = Ast::New( $name );
+ $node->AddProp( "NodeType", "var" );
+
+ my $static = 0;
+ if ( $type =~ /static/ ) {
+ # $type =~ s/static//;
+ $static = 1;
+ }
+
+ $node->AddProp( "Type", $type );
+ $node->AddProp( "Flags", 's' ) if $static;
+ $node->AddProp( "Value", $val ) if defined $val;
+ kdocAstUtil::attachChild( $cNode, $node );
+
+ return $node;
+}
+
+
+
+=head2 show_usage
+
+ Display usage information and quit.
+
+=cut
+
+sub show_usage
+{
+print<<EOF;
+usage:
+ $exe [options] [-f format] [-d outdir] [-n name] files... [-llib..]
+
+See the man page kdoc[1] for more info.
+EOF
+ exit 1;
+}
+
+
+=head2 show_version
+
+ Display short version information and quit.
+
+=cut
+
+sub show_version
+{
+ die "$exe: $Version (c) Sirtaj S. Kang <taj\@kde.org>\n";
+}
+
+
--- /dev/null
+=head1 kdocAstUtil
+
+ Utilities for syntax trees.
+
+=cut
+
+
+package kdocAstUtil;
+
+use Ast;
+use Carp;
+use File::Basename;
+use kdocUtil;
+use Iter;
+use strict;
+
+use vars qw/ $depth $refcalls $refiters @noreflist %noref /;
+
+sub BEGIN {
+# statistics for findRef
+
+ $depth = 0;
+ $refcalls = 0;
+ $refiters = 0;
+
+# findRef will ignore these words
+
+ @noreflist = qw( const int char long double template
+ unsigned signed float void bool true false uint
+ uint32 uint64 extern static inline virtual operator );
+
+ foreach my $r ( @noreflist ) {
+ $noref{ $r } = 1;
+ }
+}
+
+
+=head2 findNodes
+
+ Parameters: outlist ref, full list ref, key, value
+
+ Find all nodes in full list that have property "key=value".
+ All resulting nodes are stored in outlist.
+
+=cut
+
+sub findNodes
+{
+ my( $rOutList, $rInList, $key, $value ) = @_;
+
+ my $node;
+
+ foreach $node ( @{$rInList} ) {
+ next if !exists $node->{ $key };
+ if ( $node->{ $key } eq $value ) {
+ push @$rOutList, $node;
+ }
+ }
+}
+
+=head2 allTypes
+
+ Parameters: node list ref
+ returns: list
+
+ Returns a sorted list of all distinct "NodeType"s in the nodes
+ in the list.
+
+=cut
+
+sub allTypes
+{
+ my ( $lref ) = @_;
+
+ my %types = ();
+ foreach my $node ( @{$lref} ) {
+ $types{ $node->{NodeType} } = 1;
+ }
+
+ return sort keys %types;
+}
+
+
+
+
+=head2 findRef
+
+ Parameters: root, ident, report-on-fail
+ Returns: node, or undef
+
+ Given a root node and a fully qualified identifier (:: separated),
+ this function will try to find a child of the root node that matches
+ the identifier.
+
+=cut
+
+sub findRef
+{
+ my( $root, $name, $r ) = @_;
+
+ confess "findRef: no name" if !defined $name || $name eq "";
+
+ $name =~ s/\s+//g;
+ return undef if exists $noref{ $name };
+
+ $name =~ s/^#//g;
+
+ my ($iter, @tree) = split /(?:\:\:|#)/, $name;
+ my $kid;
+
+ $refcalls++;
+
+ # Upward search for the first token
+ return undef if !defined $iter;
+
+ while ( !defined findIn( $root, $iter ) ) {
+ return undef if !defined $root->{Parent};
+ $root = $root->{Parent};
+ }
+ $root = $root->{KidHash}->{$iter};
+ carp if !defined $root;
+
+ # first token found, resolve the rest of the tree downwards
+ foreach $iter ( @tree ) {
+ confess "iter in $name is undefined\n" if !defined $iter;
+ next if $iter =~ /^\s*$/;
+
+ unless ( defined findIn( $root, $iter ) ) {
+ confess "findRef: failed on '$name' at '$iter'\n"
+ if defined $r;
+ return undef;
+ }
+
+ $root = $root->{KidHash}->{ $iter };
+ carp if !defined $root;
+ }
+
+ return $root;
+}
+
+=head2 findIn
+
+ node, name: search for a child
+
+=cut
+
+sub findIn
+{
+ return undef unless defined $_[0]->{KidHash};
+
+ my $ret = $_[0]->{KidHash}->{ $_[1] };
+
+ return $ret;
+}
+
+=head2 linkReferences
+
+ Parameters: root, node
+
+ Recursively links references in the documentation for each node
+ to real nodes if they can be found. This should be called once
+ the entire parse tree is filled.
+
+=cut
+
+sub linkReferences
+{
+ my( $root, $node ) = @_;
+
+ if ( exists $node->{DocNode} ) {
+ linkDocRefs( $root, $node, $node->{DocNode} );
+
+ if( exists $node->{Compound} ) {
+ linkSee( $root, $node, $node->{DocNode} );
+ }
+ }
+
+ my $kids = $node->{Kids};
+ return unless defined $kids;
+
+ foreach my $kid ( @$kids ) {
+ # only continue in a leaf node if it has documentation.
+ next if !exists $kid->{Kids} && !exists $kid->{DocNode};
+ if( !exists $kid->{Compound} ) {
+ linkSee( $root, $node, $kid->{DocNode} );
+ }
+ linkReferences( $root, $kid );
+ }
+}
+
+sub linkNamespaces
+{
+ my ( $node ) = @_;
+
+ if ( defined $node->{ImpNames} ) {
+ foreach my $space ( @{$node->{ImpNames}} ) {
+ my $spnode = findRef( $node, $space );
+
+ if( defined $spnode ) {
+ $node->AddPropList( "ExtNames", $spnode );
+ }
+ else {
+ warn "namespace not found: $space\n";
+ }
+ }
+ }
+
+ return unless defined $node->{Compound} || !defined $node->{Kids};
+
+
+ foreach my $kid ( @{$node->{Kids}} ) {
+ next unless localComp( $kid );
+
+ linkNamespaces( $kid );
+ }
+}
+
+sub calcStats
+{
+ my ( $stats, $root, $node ) = @_;
+# stats:
+# num types
+# num nested
+# num global funcs
+# num methods
+
+
+ my $type = $node->{NodeType};
+
+ if ( $node eq $root ) {
+ # global methods
+ if ( defined $node->{Kids} ) {
+ foreach my $kid ( @{$node->{Kids}} ) {
+ $stats->{Global}++ if $kid->{NodeType} eq "method";
+ }
+ }
+
+ $node->AddProp( "Stats", $stats );
+ }
+ elsif ( kdocAstUtil::localComp( $node )
+ || $type eq "enum" || $type eq "typedef" ) {
+ $stats->{Types}++;
+ $stats->{Nested}++ if $node->{Parent} ne $root;
+ }
+ elsif( $type eq "method" ) {
+ $stats->{Methods}++;
+ }
+
+ return unless defined $node->{Compound} || !defined $node->{Kids};
+
+ foreach my $kid ( @{$node->{Kids}} ) {
+ next if defined $kid->{ExtSource};
+ calcStats( $stats, $root, $kid );
+ }
+}
+
+=head2 linkDocRefs
+
+ Parameters: root, node, docnode
+
+ Link references in the docs if they can be found. This should
+ be called once the entire parse tree is filled.
+
+=cut
+
+sub linkDocRefs
+{
+ my ( $root, $node, $docNode ) = @_;
+ return unless exists $docNode->{Text};
+
+ my ($text, $ref, $item, $tosearch);
+
+ foreach $item ( @{$docNode->{Text}} ) {
+ next if $item->{NodeType} ne 'Ref';
+
+ $text = $item->{astNodeName};
+
+ if ( $text =~ /^(?:#|::)/ ) {
+ $text = $';
+ $tosearch = $node;
+ }
+ else {
+ $tosearch = $root;
+ }
+
+ $ref = findRef( $tosearch, $text );
+ $item->AddProp( 'Ref', $ref ) if defined $ref;
+
+ confess "Ref failed for ", $item->{astNodeName},
+ "\n" unless defined $ref;
+ }
+}
+
+sub linkSee
+{
+ my ( $root, $node, $docNode ) = @_;
+ return unless exists $docNode->{See};
+
+ my ( $text, $tosearch, $ref );
+
+ foreach $text ( @{$docNode->{See}} ) {
+ if ( $text =~ /^\s*(?:#|::)/ ) {
+ $text = $';
+ $tosearch = $node;
+ }
+ else {
+ $tosearch = $root;
+ }
+
+ $ref = findRef( $tosearch, $text );
+ $docNode->AddPropList( 'SeeRef', $ref )
+ if defined $ref;
+ }
+}
+
+
+
+#
+# Inheritance utilities
+#
+
+=head2 makeInherit
+
+ Parameter: $rootnode, $parentnode
+
+ Make an inheritance graph from the parse tree that begins
+ at rootnode. parentnode is the node that is the parent of
+ all base class nodes.
+
+=cut
+
+sub makeInherit
+{
+ my( $rnode, $parent ) = @_;
+
+ foreach my $node ( @{ $rnode->{Kids} } ) {
+ next if !defined $node->{Compound};
+
+ # set parent to root if no inheritance
+
+ if ( !exists $node->{InList} ) {
+ newInherit( $node, "Global", $parent );
+ $parent->AddPropList( 'InBy', $node );
+
+ makeInherit( $node, $parent );
+ next;
+ }
+
+ # link each ancestor
+ my $acount = 0;
+ANITER:
+ foreach my $in ( @{ $node->{InList} } ) {
+ unless ( defined $in ) {
+ Carp::cluck "warning: $node->{astNodeName} "
+ ." has undef in InList.";
+ next ANITER;
+ }
+
+ my $ref = kdocAstUtil::findRef( $rnode,
+ $in->{astNodeName} );
+
+ if( !defined $ref ) {
+ # ancestor undefined
+ warn "warning: ", $node->{astNodeName},
+ " inherits unknown class '",
+ $in->{astNodeName},"'\n";
+
+ $parent->AddPropList( 'InBy', $node );
+ }
+ else {
+ # found ancestor
+ $in->AddProp( "Node", $ref );
+ $ref->AddPropList( 'InBy', $node );
+ $acount++;
+ }
+ }
+
+ if ( $acount == 0 ) {
+ # inherits no known class: just parent it to global
+ newInherit( $node, "Global", $parent );
+ $parent->AddPropList( 'InBy', $node );
+ }
+ makeInherit( $node, $parent );
+ }
+}
+
+=head2 newInherit
+
+ p: $node, $name, $lnode?
+
+ Add a new ancestor to $node with raw name = $name and
+ node = lnode.
+=cut
+
+sub newInherit
+{
+ my ( $node, $name, $link ) = @_;
+
+ my $n = Ast::New( $name );
+ $n->AddProp( "Node", $link ) unless !defined $link;
+
+ $node->AddPropList( "InList", $n );
+ return $n;
+}
+
+=head2 inheritName
+
+ pr: $inheritance node.
+
+ Returns the name of the inherited node. This checks for existence
+ of a linked node and will use the "raw" name if it is not found.
+
+=cut
+
+sub inheritName
+{
+ my ( $innode ) = @_;
+
+ return defined $innode->{Node} ?
+ $innode->{Node}->{astNodeName}
+ : $innode->{astNodeName};
+}
+
+=head2 inheritedBy
+
+ Parameters: out listref, node
+
+ Recursively searches for nodes that inherit from this one, returning
+ a list of inheriting nodes in the list ref.
+
+=cut
+
+sub inheritedBy
+{
+ my ( $list, $node ) = @_;
+
+ return unless exists $node->{InBy};
+
+ foreach my $kid ( @{ $node->{InBy} } ) {
+ push @$list, $kid;
+ inheritedBy( $list, $kid );
+ }
+}
+
+=head2 hasLocalInheritor
+
+ Parameter: node
+ Returns: 0 on fail
+
+ Checks if the node has an inheritor that is defined within the
+ current library. This is useful for drawing the class hierarchy,
+ since you don't want to display classes that have no relationship
+ with classes within this library.
+
+ NOTE: perhaps we should cache the value to reduce recursion on
+ subsequent calls.
+
+=cut
+
+sub hasLocalInheritor
+{
+ my $node = shift;
+
+ return 0 if !exists $node->{InBy};
+
+ my $in;
+ foreach $in ( @{$node->{InBy}} ) {
+ return 1 if !exists $in->{ExtSource}
+ || hasLocalInheritor( $in );
+ }
+
+ return 0;
+}
+
+
+
+=head2 allMembers
+
+ Parameters: hashref outlist, node, $type
+
+ Fills the outlist hashref with all the methods of outlist,
+ recursively traversing the inheritance tree.
+
+ If type is not specified, it is assumed to be "method"
+
+=cut
+
+sub allMembers
+{
+ my ( $outlist, $n, $type ) = @_;
+ my $in;
+ $type = "method" if !defined $type;
+
+ if ( exists $n->{InList} ) {
+
+ foreach $in ( @{$n->{InList}} ) {
+ next if !defined $in->{Node};
+ my $i = $in->{Node};
+
+ allMembers( $outlist, $i )
+ unless $i == $main::rootNode;
+ }
+ }
+
+ return unless exists $n->{Kids};
+
+ foreach $in ( @{$n->{Kids}} ) {
+ next if $in->{NodeType} ne $type;
+
+ $outlist->{ $in->{astNodeName} } = $in;
+ }
+}
+
+=head2 findOverride
+
+ Parameters: root, node, name
+
+ Looks for nodes of the same name as the parameter, in its parent
+ and the parent's ancestors. It returns a node if it finds one.
+
+=cut
+
+sub findOverride
+{
+ my ( $root, $node, $name ) = @_;
+ return undef if !exists $node->{InList};
+
+ foreach my $in ( @{$node->{InList}} ) {
+ my $n = $in->{Node};
+ next unless defined $n && $n != $root && exists $n->{KidHash};
+
+ my $ref = $n->{KidHash}->{ $name };
+
+ return $n if defined $ref && $ref->{NodeType} eq "method";
+
+ if ( exists $n->{InList} ) {
+ $ref = findOverride( $root, $n, $name );
+ return $ref if defined $ref;
+ }
+ }
+
+ return undef;
+}
+
+=head2 attachChild
+
+ Parameters: parent, child
+
+ Attaches child to the parent, setting Access, Kids
+ and KidHash of respective nodes.
+
+=cut
+
+sub attachChild
+{
+ my ( $parent, $child ) = @_;
+ confess "Attempt to attach ".$child->{astNodeName}." to an ".
+ "undefined parent\n" if !defined $parent;
+
+ $child->AddProp( "Access", $parent->{KidAccess} );
+ $child->AddProp( "Parent", $parent );
+
+ $parent->AddPropList( "Kids", $child );
+
+ if( !exists $parent->{KidHash} ) {
+ my $kh = Ast::New( "LookupTable" );
+ $parent->AddProp( "KidHash", $kh );
+ }
+
+ $parent->{KidHash}->AddProp( $child->{astNodeName},
+ $child );
+}
+
+=head2 makeClassList
+
+ Parameters: node, outlist ref
+
+ fills outlist with a sorted list of all direct, non-external
+ compound children of node.
+
+=cut
+
+sub makeClassList
+{
+ my ( $rootnode, $list ) = @_;
+
+ @$list = ();
+
+ Iter::LocalCompounds( $rootnode,
+ sub {
+ my $node = shift;
+
+ my $her = join ( "::", heritage( $node ) );
+ $node->AddProp( "FullName", $her );
+
+ push @$list, $node;
+ } );
+
+ @$list = sort { $a->{FullName} cmp $b->{FullName} } @$list;
+}
+
+#
+# Debugging utilities
+#
+
+=head2 dumpAst
+
+ Parameters: node, deep
+ Returns: none
+
+ Does a recursive dump of the node and its children.
+ If deep is set, it is used as the recursion property, otherwise
+ "Kids" is used.
+
+=cut
+
+sub dumpAst
+{
+ my ( $node, $deep ) = @_;
+
+ $deep = "Kids" if !defined $deep;
+
+ print "\t" x $depth, $node->{astNodeName},
+ " (", $node->{NodeType}, ")\n";
+
+ my $kid;
+
+ foreach $kid ( $node->GetProps() ) {
+ print "\t" x $depth, " -\t", $kid, " -> ", $node->{$kid},"\n"
+ unless $kid =~ /^(astNodeName|NodeType|$deep)$/;
+ }
+ if ( exists $node->{Ancestors} ) {
+ print "\t" x $depth, "Ancestors:\t",
+ join( ",", @{$node->{Ancestors}}),"\n";
+ }
+
+
+ $depth++;
+ foreach $kid ( @{$node->{ $deep }} ) {
+ dumpAst( $kid );
+ }
+
+ print "\t" x $depth, "Documentation nodes:\n" if defined
+ @{ $node->{Doc}->{ "Text" }};
+
+ foreach $kid ( @{ $node->{Doc}->{ "Text" }} ) {
+ dumpAst( $kid );
+ }
+
+ $depth--;
+}
+
+=head2 testRef
+
+ Parameters: rootnode
+
+ Interactive testing of referencing system. Calling this
+ will use the readline library to allow interactive entering of
+ identifiers. If a matching node is found, its node name will be
+ printed.
+
+=cut
+
+sub testRef {
+ require Term::ReadLine;
+
+ my $rootNode = $_[ 0 ];
+
+ my $term = new Term::ReadLine 'Testing findRef';
+
+ my $OUT = $term->OUT || *STDOUT{IO};
+ my $prompt = "Identifier: ";
+
+ while( defined ($_ = $term->readline($prompt)) ) {
+
+ my $node = kdocAstUtil::findRef( $rootNode, $_ );
+
+ if( defined $node ) {
+ print $OUT "Reference: '", $node->{astNodeName},
+ "', Type: '", $node->{NodeType},"'\n";
+ }
+ else {
+ print $OUT "No reference found.\n";
+ }
+
+ $term->addhistory( $_ ) if /\S/;
+ }
+}
+
+sub printDebugStats
+{
+ print "findRef: ", $refcalls, " calls, ",
+ $refiters, " iterations.\n";
+}
+
+sub External
+{
+ return defined $_[0]->{ExtSource};
+}
+
+sub Compound
+{
+ return defined $_[0]->{Compound};
+}
+
+sub localComp
+{
+ my ( $node ) = $_[0];
+ return defined $node->{Compound}
+ && !defined $node->{ExtSource}
+ && $node->{NodeType} ne "Forward";
+}
+
+sub hasDoc
+{
+ return defined $_[0]->{DocNode};
+}
+
+
+sub heritage
+{
+ my $node = shift;
+ my @heritage;
+
+ while( 1 ) {
+ push @heritage, $node->{astNodeName};
+
+ last unless defined $node->{Parent};
+ $node = $node->{Parent};
+ last unless defined $node->{Parent};
+ }
+
+ return reverse @heritage;
+}
+
+sub refHeritage
+{
+ my $node = shift;
+ my @heritage;
+
+ while( 1 ) {
+ push @heritage, $node;
+
+ last unless defined $node->{Parent};
+ $node = $node->{Parent};
+ last unless defined $node->{Parent};
+ }
+
+ return reverse @heritage;
+
+}
+
+
+1;
--- /dev/null
+
+package kdocCxxDocbook;
+use Carp;
+use File::Path;
+use Iter;
+
+use strict;
+no strict "subs";
+
+use vars qw/ $lib $rootnode $outputdir $opt $paraOpen/;
+
+=head2 kdocCxxDocBook
+
+ TODO:
+
+ Templates
+ Fix tables, add index.
+ Global docs
+ Groups
+
+=cut
+
+sub writeDoc
+{
+ ( $lib, $rootnode, $outputdir, $opt ) = @_;
+
+ makeReferences( $rootnode );
+
+ $lib = "kdoc-out" if $lib eq ""; # if no library name set
+
+ mkpath( $outputdir) unless -f $outputdir;
+
+ open ( DOC, ">$outputdir/$lib.sgml" ) || die "Couldn't write output.";
+
+ my $time = localtime;
+
+print DOC<<EOF;
+<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
+]>
+<book id="$lib-lib">
+ <bookinfo>
+ <date>$time</date>
+ <title>$lib API Documentation</title>
+ </bookinfo>
+EOF
+
+ printLibDoc();
+ printHierarchy();
+ printClassIndex();
+ printClassDoc();
+
+print DOC<<EOF;
+</book>
+EOF
+
+}
+
+sub printLibDoc
+{
+ return unless kdocAstUtil::hasDoc( $rootnode );
+
+ print DOC chapter( "$lib-intro", "Introduction" );
+ printDoc( $rootnode->{DocNode}, *DOC, $rootnode );
+ print DOC C( "chapter" );
+}
+
+
+sub printHierarchy
+{
+
+ print DOC chapter( "class-hierarchy", "$lib Class Hierarchy" );
+
+ Iter::Hierarchy( $rootnode,
+ sub { # down
+ print DOC "<ItemizedList>\n";
+ },
+ sub { # print
+ my $node = shift;
+ return if $node == $rootnode;
+
+ my $src = defined $node->{ExtSource} ? " ($node->{ExtSource})":"";
+ print DOC "<ListItem><para>", refName($node), "$src</para>\n"
+ },
+ sub { # up
+ if ( $_[0] == $rootnode ) {
+ print DOC "</ItemizedList>\n";
+ }
+ else {
+ print DOC "</ItemizedList></ListItem>\n";
+ }
+ },
+ sub { print DOC "</ListItem>"; }
+ );
+
+ print DOC C( "chapter" );
+}
+
+sub printClassIndex
+{
+ my @clist = ();
+ kdocAstUtil::makeClassList( $rootnode, \@clist );
+
+ print DOC chapter( "class-index", "$lib Class Index" ),
+ O( "Table", "TocEntry", 0, "PgWide", 1, "ColSep", 0 ),
+ tblk( "title", $lib,' classes' ),
+ O( "tgroup", "Cols", 2 ), O( "TBody" );
+
+ foreach my $kid ( @clist ) {
+
+ # Internal, deprecated, abstract
+ my $name = refName( $kid );
+
+ if ( $kid->{Abstract} ) {
+ $name = tblk( "Emphasis", $name );
+ }
+
+ my $extra = "";
+
+ if ( $kid->{Internal} ) {
+ $extra .= " internal";
+ }
+
+ if ( $kid->{Deprecated} ) {
+ $extra .= " ".tblk( "Emphasis", "deprecated" );
+ }
+
+ $extra = " [$extra]" unless $extra eq "";
+
+ # print class entry
+ print DOC tblk( 'Row', tblk( 'ENTRY', $name )
+ . tblk( 'ENTRY', deref( $kid->{DocNode}->{ClassShort},
+ $rootnode).$extra ));
+ }
+
+ print DOC C( "TBody", "TGroup", "Table", "chapter" );
+}
+
+sub printClassDoc
+{
+ print DOC chapter( "class-doc", "$lib Class Documentation" );
+
+ Iter::LocalCompounds( $rootnode, sub { docChildren( shift ); } );
+
+ print DOC C("Chapter"), "\n";
+}
+
+sub docChildren
+{
+ my ( $node ) = @_;
+
+ return if $node == $rootnode;
+
+ ## document self
+ printClassInfo( $node );
+
+ if ( kdocAstUtil::hasDoc( $node ) ) {
+ printDoc( $node->{DocNode}, *DOC{IO}, $rootnode, 1 );
+ }
+
+ # First a member index by type
+ print DOC O( "BridgeHead", "Renderas", "Sect2" ),
+ "Interface Synopsis", C( "BridgeHead" );
+
+ Iter::MembersByType( $node,
+ sub { # start
+ print DOC O( 'Table', 'PgWide', 1, "colsep", 0,
+ "rowsep", 0, "tocentry", 0 ),
+ tblk( 'Title', fullName($node)," ",$_[0] ),
+ O( "TGroup", "cols", 1 ), O( "TBody" );
+ },
+ \&sumListMember, # print
+ sub { # end
+ print DOC C( "TBody", "TGroup", "Table" ), "\n";
+ },
+ sub { # no kids
+ print DOC tblk( "para", "(Empty interface)" );
+ }
+ );
+
+ print DOC O( "BridgeHead", "Renderas", "Sect2" );
+ print DOC "Member Documentation", C( "BridgeHead" );
+
+ # Then long docs for each member
+ Iter::MembersByType ( $node, undef, \&printMemberDoc, undef,
+ sub { print DOC tblk( "para", "(Empty interface)" ); }
+ );
+
+ print DOC C( "Sect1" );
+
+ return;
+}
+
+sub printClassInfo
+{
+ my $node = shift;
+
+ print DOC O( "Sect1", "id", $node->{DbRef},
+ "XRefLabel", fullName( $node, "::" ) ), "\n",
+ tblk( "Title", esc($node->{NodeType})," ",fullName( $node ) );
+
+
+ if ( defined $node->{DocNode} && $node->{DocNode}->{ClassShort} ) {
+ printClassInfoField( "Description",
+ deref( $node->{DocNode}->{ClassShort}, $rootnode ) );
+ }
+
+ printClassInfoField( "Header", tblk( "Literal",
+ $node->{Source}->{astNodeName} ));
+
+ my ($text, $comma ) = ("", "");
+
+ Iter::Ancestors( $node, $rootnode, undef, undef,
+ sub { # print
+ my ( $node, $name, $type ) = @_;
+ $name = refName( $node ) if defined $node;
+ $name .= " (".$node->{ExtSource}.")" if defined $node->{ExtSource};
+ $text .= $comma.$name;
+ $text .= " [$type]" unless $type eq "public";
+
+ $comma = ", ";
+ },
+ sub { # end
+ printClassInfoField( "Inherits", $text );
+ }
+ );
+
+ $text = $comma = "";
+
+ Iter::Descendants( $node, undef, undef,
+ sub { # print
+ my $desc = shift;
+ $text .= $comma.refName( $desc );
+ $text .= " (".$desc->{ExtSource}.")" if defined $desc->{ExtSource};
+
+ $comma = ", ";
+ },
+ sub { # end
+ printClassInfoField( "Inherited By", $text );
+ }
+ );
+
+ if ( $node->{Internal} ) {
+ printClassInfoField( "Note", "Internal use only." );
+ }
+
+ if ( $node->{Deprecated} ) {
+ printClassInfoField( "Note", "Deprecated, to be removed." );
+ }
+
+ return;
+}
+
+sub printClassInfoField
+{
+ my ( $label, $text ) = @_;
+
+ print DOC tblk( "formalpara", tblk( "title", $label ),
+ tblk( "para", " ".$text ) );
+}
+
+sub sumListMember
+{
+ my( $class, $m ) = @_;
+
+ print DOC O( "Row"), O( "Entry" );
+
+
+ my $type = $m->{NodeType};
+ my $name = esc( $m->{astNodeName} );
+ my $pname = tblk( "Emphasis", $name );
+
+ if( $type eq "var" ) {
+ print DOC tblk( "Literal", esc($m->{Type}) ), " $pname\n";
+ }
+ elsif( $type eq "method" ) {
+ my $flags = $m->{Flags};
+
+ if ( !defined $flags ) {
+ warn "Method ".$m->{astNodeName}.
+ " has no flags";
+ }
+
+ my $extra = "";
+ $extra .= "virtual " if $flags =~ "v";
+ $extra .= "static " if $flags =~ "s";
+
+ my $params = esc( $m->{Params} );
+ $params =~ s/^\s+//g;
+ $params =~ s/\s+$//g;
+ $params = " $params " unless $params eq "";
+ my $c = $flags =~ /c/ ? " const" : "";
+ my $p = $flags =~ /p/ ? " [pure]" : "";
+
+
+ print DOC esc($m->{ReturnType}), " $pname\($params\)$c$p\n";
+ }
+ elsif( $type eq "enum" ) {
+ my $n = $name eq "" ? "" : $pname." ";
+
+ print DOC tblk("Literal","enum"),
+ " $n\{ ",tblk("Literal",esc($m->{Params}))," }";
+ }
+ elsif( $type eq "typedef" ) {
+ print DOC tblk( "Literal", "typedef " ), esc($m->{Type}),
+ tblk( "Emphasis", $name );
+ }
+ else {
+ # unknown type
+ print DOC tblk( "Literal", esc( $type ) )," $pname\n";
+ }
+
+ print DOC C( "Entry", "Row" ),"\n";
+
+ return;
+}
+
+=head2 printMemberDoc
+
+ params: classnode, membernode
+
+ Prints title and long documentation for one class member.
+
+=cut
+
+sub printMemberDoc
+{
+ my ( $class, $mem ) = @_;
+
+ return unless kdocAstUtil::hasDoc( $mem );
+
+ print DOC O( "BridgeHead",
+ "id", $mem->{DbRef},
+ "XRefLabel", fullName( $mem, "::" ),
+ "Renderas", "Sect3" );
+
+ # title
+ my $type = $mem->{NodeType};
+ my $name = esc( $mem->{astNodeName} );
+ my $pname = tblk( "Emphasis", $name );
+
+ if( $type eq "var" ) {
+ print DOC tblk( "Literal", esc($mem->{Type}) ), " $pname\n";
+ }
+ elsif( $type eq "method" ) {
+ my $flags = $mem->{Flags};
+
+ if ( !defined $flags ) {
+ warn "Method ".$mem->{astNodeName}.
+ " has no flags";
+ }
+
+ my $extra = "";
+ $extra .= "virtual " if $flags =~ "v";
+ $extra .= "static " if $flags =~ "s";
+
+ my $params = $mem->{Params};
+ $params =~ s/^\s+//g;
+ $params =~ s/\s+$//g;
+ $params = " $params " unless $params eq "";
+ my $c = $flags =~ /c/ ? " const" : "";
+ my $p = $flags =~ /p/ ? " [pure]" : "";
+
+ print DOC deref($mem->{ReturnType}, $rootnode), " $pname\(".
+ deref( $params, $rootnode )."\)$c$p\n";
+ }
+ elsif( $type eq "enum" ) {
+ my $n = $name eq "" ? "" : $pname." ";
+
+ print DOC tblk("Literal","enum"),
+ " $n\{ ",tblk("Literal",esc($mem->{Params}))," }";
+ }
+ elsif( $type eq "typedef" ) {
+ print DOC tblk( "Literal", "typedef" ), " ", esc($mem->{Type}), $pname;
+ }
+ # TODO nested compounds
+ else {
+ # unknown type
+ print DOC tblk( "Literal", esc( $type ) )," $pname\n";
+ }
+
+ print DOC C( "BridgeHead" );
+
+ # documentation
+ printDoc( $mem->{DocNode}, *DOC, $rootnode );
+
+ if ( $type eq "method" ) {
+ my $ref = kdocAstUtil::findOverride( $rootnode,
+ $class, $mem->{astNodeName} );
+ if ( defined $ref ) {
+ print DOC tblk( "formalpara",
+ tblk( "title", "Reimplemented from" ),
+ tblk( "para", fullName( $ref, "::" )) ), "\n";
+ }
+ }
+}
+
+=head2 printDoc
+
+Parameters: docnode, *filehandle, rootnode, compound
+
+Print a doc node. If compound is specified and non-zero, various
+compound node properties are not printed.
+
+=cut
+
+sub printDoc
+{
+ my $docNode = shift;
+ local *CLASS = shift;
+
+ my ( $rootnode, $comp ) = @_;
+ my $node;
+ my $type;
+ my $text;
+ my $lasttype = "none";
+
+ $comp = 0 if !defined $comp;
+
+ $text = $docNode->{Text};
+
+ if ( defined $text ) {
+ $paraOpen = 0;
+
+ foreach $node ( @$text ) {
+ $type = $node->{NodeType};
+ my $name = $node->{astNodeName};
+ warn "Node '", $name, "' has no type"
+ if !defined $type;
+
+ if( $lasttype eq "ListItem" && $type ne $lasttype ) {
+ print CLASS "</ItemizedList>\n";
+ }
+
+ if( $type eq "DocText" ) {
+ print CLASS "", pc(), po(),
+ deref( $name, $rootnode );
+ }
+ elsif ( $type eq "Pre" ) {
+ print CLASS "", pc(),
+ tblk( "ProgramListing", esc( $name ) );
+ }
+ elsif( $type eq "DocSection" ) {
+ print CLASS "", pc(), O( "BridgeHead",
+ "Renderas", "Sect4" ),
+ deref( $name, $rootnode ),
+ C( "BridgeHead" ),"\n";
+ }
+ elsif( $type eq "Ref" ) {
+ my $ref = $node->{Ref};
+ if ( defined $ref ) {
+ print CLASS refName( $ref );
+ }
+ else {
+ print CLASS $name;
+ }
+ }
+ elsif ( $type eq "Image" ) {
+ print CLASS pc(),"<Graphic FileRef=\"",
+ $node->{Path}, "\"></Graphic>";
+ }
+ elsif ( $type eq "ListItem" ) {
+ if ( $lasttype ne "ListItem" ) {
+ print CLASS "", pc(),"<ItemizedList>\n";
+ }
+ print CLASS "", tblk( "ListItem",
+ tblk("para", deref($name,$rootnode )) );
+ }
+ elsif ( $type eq "ParaBreak" || $type eq "Param" ) {
+ # ignore parabreak, they're taken
+ # care of already.
+
+ # ignore parameters, handled later
+ }
+ else {
+ warn "Unhandled doc type $type\n";
+ }
+
+ $lasttype = $type;
+ }
+
+ if( $lasttype eq "ListItem" ) {
+ print CLASS "", pc(), "</ItemizedList>";
+ }
+
+ print CLASS "", pc();
+ }
+
+ # Params
+ my @paramlist = ();
+ kdocAstUtil::findNodes( \@paramlist, $docNode->{Text},
+ "NodeType", "Param" );
+
+ if( $#paramlist >= 0 ) {
+ my $pnode;
+ print CLASS "", O( 'Table', 'PgWide', 0, "colsep", 0,
+ "frame", "none", "tocentry", 0 ),
+ tblk( 'Title', 'Parameters' ),
+ O( "TGroup", "cols", "2" ), O( "TBody" );
+
+ foreach $pnode ( @paramlist ) {
+ print CLASS "<ROW><ENTRY>", esc($pnode->{Name}),
+ "</ENTRY><ENTRY>",
+ deref($pnode->{astNodeName}, $rootnode ),
+ "</ROW>\n";
+ }
+ print CLASS "", C( "TBody", "TGroup", "Table" );
+ }
+
+ # Return
+ printTextItem( $docNode, *CLASS, "Returns" );
+
+ # Exceptions
+ $text = $docNode->{Throws};
+
+ if ( defined $text ) {
+ my $comma = "<formalpara><title>Exceptions</title><para>";
+
+ foreach my $tosee ( @$text ) {
+ print CLASS $comma, esc( $tosee );
+ $comma = ", ";
+ }
+ print CLASS C( "para", "formalpara" );
+ }
+
+ # See
+ my $comma = "";
+
+ Iter::SeeAlso ( $docNode, undef,
+ sub { # start
+ print CLASS "", O( "Tip" ),tblk( "Title", "See Also"),O( "Para" );
+ },
+ sub { # print
+ my ( $label, $ref ) = @_;
+ $label = defined $ref ? refName( $ref ):esc( $label );
+
+ print CLASS $comma, $label;
+ $comma = ", ";
+ },
+ sub { # end
+ print CLASS "", C( "Para", "Tip" );
+ }
+ );
+
+ printTextItem( $docNode, *CLASS, "Since" );
+ printTextItem( $docNode, *CLASS, "Version" );
+ printTextItem( $docNode, *CLASS, "Id" );
+ printTextItem( $docNode, *CLASS, "Author" );
+}
+
+sub makeReferences
+{
+ my $root = shift;
+ my $idcount = 0;
+
+ return Iter::Tree( $root, 1,
+ sub {
+ my ( $parent, $node ) = @_;
+ return if $node->{ExtSource};
+
+ $idcount++;
+
+ $node->AddProp( "DbRef", "docid-$idcount" );
+
+ print fullName( $node ), " = ", $node->{DbRef},"\n";
+
+ return;
+ }
+ );
+}
+
+sub printTextItem
+{
+ my $node = shift;
+ local *CLASS = shift;
+ my ( $prop, $label ) = @_;
+
+ my $text = $node->{ $prop };
+
+ return unless defined $text;
+ $label = $prop unless defined $label;
+
+ print CLASS "<formalpara><title>", $label, "</title><para> ",
+ deref( $text, $rootnode ), "</para></formalpara>\n";
+}
+
+
+# utilities
+
+
+sub refName
+{
+ my( $node ) = @_;
+
+ return fullName( $node ) if defined $node->{ExtSource}
+ || !kdocAstUtil::hasDoc( $node );
+
+ return '<xref LinkEnd="'.$node->{DbRef}.'">';
+}
+
+sub fullName
+{
+ my( $node, $sep ) = @_;
+
+ $sep = "::" unless defined $sep;
+
+ my @heritage = kdocAstUtil::heritage( $node );
+ foreach my $n ( @heritage ) { $n = esc( $n ); }
+
+ return join( $sep, @heritage );
+}
+
+=head2 deref
+
+ Parameters: text, rootnode
+ returns text
+
+ dereferences all @refs in the text and returns it.
+
+=cut
+
+sub deref
+{
+ my ( $str, $rootnode ) = @_;
+ confess "rootnode is null" if !defined $rootnode;
+ my $out = "";
+ my $text;
+
+ foreach $text ( split (/(\@\w+\s+[\w:#]+)/, $str ) ) {
+ if ( $text =~ /\@ref\s+([\w:#]+)/ ) {
+ my $name = $1;
+ $name =~ s/^\s*#//g;
+ $out .= wordRef( $name, $rootnode );
+ }
+ elsif ( $text =~ /\@p\s+([\w:]+)/ ) {
+ $out .= tblk( "Literal", esc($1) );
+ }
+ else {
+ $out .= esc($text);
+ }
+ }
+
+ return $out;
+}
+
+
+
+=head3 wordRef
+
+ Parameters: word
+
+ Prints a hyperlink to the word's reference if found, otherwise
+ just prints the word. Good for @refs etc.
+
+=cut
+
+sub wordRef
+{
+ my ( $str, $rootnode ) = @_;
+ confess "rootnode is undef" if !defined $rootnode;
+
+ return "" if $str eq "";
+
+ my $ref = kdocAstUtil::findRef( $rootnode, $str );
+ return esc($str) if !defined $ref;
+
+ return refName( $ref );
+}
+
+
+=head2 esc
+
+ Escape special SGML characters for normal text.
+
+=cut
+
+sub esc
+{
+ my $str = $_[ 0 ];
+
+ return "" if !defined $str || $str eq "";
+
+ $str =~ s/&/&/g;
+ $str =~ s/</</g;
+ $str =~ s/>/>/g;
+
+ return $str;
+}
+
+
+sub chapter
+{
+ my ( $id, $title ) = @_;
+
+ return "<chapter id=\"$id\"><title>$title</title>";
+}
+
+
+=head2 tblk
+
+ Params: tagname, text..
+
+ Inserts text in a block tag of type tagname (ie both
+ opening and closing tags)
+=cut
+
+sub tblk
+{
+ my $tag = shift;
+ return "<$tag>".join( "", @_ )."</$tag>";
+}
+
+
+=head2 O
+
+ Params: tagname, list of id and idtext interspersed.
+
+=cut
+
+sub O
+{
+ my $tag = shift;
+
+ carp "mismatched ids and tags" if ($#_+1) % 2 != 0;
+
+ my $out = "<$tag";
+
+ while ( $#_ >= 0 ) {
+ $out .= " ".shift( @_ ).'="'.shift( @_ ).'"';
+ }
+
+ $out .= ">";
+
+ return $out;
+}
+
+=head2 C
+
+ Params: list of tagnames
+
+ returns a list of close tags in the order specified in the
+ params.
+
+=cut
+
+sub C
+{
+ my $out = "";
+
+ foreach my $tag ( @_ ) {
+ $out .= "</$tag>";
+ }
+
+ return $out;
+}
+
+sub po
+{
+ my $text = $paraOpen ? "" : "<para>";
+ $paraOpen = 1;
+
+ return $text;
+}
+
+sub pc
+{
+ my $text = $paraOpen ? "</para>" : "";
+ $paraOpen = 0;
+
+ return $text;
+}
+1;
--- /dev/null
+package kdocCxxHTML;
+
+use File::Path;
+use File::Basename;
+
+use Carp;
+use Ast;
+use kdocAstUtil;
+use kdocHTMLutil;
+use kdocUtil;
+use Iter;
+
+use strict;
+no strict "subs";
+
+use vars qw/ @clist $host $who $now $gentext %toclinks $docBotty
+ $lib $rootnode $outputdir $opt $debug *CLASS/;
+
+=head1 kdocCxxHTML
+
+Capabilities required from Ast bit:
+
+1. Create an inheritance tree
+
+2. Referencing ability: convert a fully qualified class or member name
+to a node reference.
+
+=cut
+
+BEGIN
+{
+ @clist = ();
+
+ # Contents entries in HTML page header
+
+ %toclinks = (
+ 'Index' => 'index.html',
+ 'Annotated List' => 'index-long.html',
+ 'Hierarchy' => 'hier.html',
+ 'Globals' => 'all-globals.html',
+ 'Files' => 'header-list.html'
+ );
+
+ # Page footer
+
+ $who = kdocUtil::userName();
+ $host = kdocUtil::hostName();
+ $now = localtime;
+ $gentext = "$who\@$host on $now, using kdoc $main::Version.";
+
+ $docBotty =<<EOF
+<HR>
+ <table>
+ <tr><td><small>Generated by: $gentext</small></td></tr>
+ </table>
+</BODY>
+</HTML>
+EOF
+
+}
+
+sub writeDoc
+{
+ ( $lib, $rootnode, $outputdir, $opt ) = @_;
+
+ $debug = $main::debug;
+
+ mkpath( $outputdir ) unless -f $outputdir;
+
+ makeSourceReferences( $rootnode );
+ makeReferences( $rootnode );
+ kdocAstUtil::makeClassList( $rootnode, \@clist );
+
+ writeGlobalDoc( $rootnode, "$outputdir/".$toclinks{Globals} );
+ writeClassList( $rootnode , "$outputdir/".$toclinks{Index} );
+ writeAnnotatedList( $rootnode,
+ "$outputdir/".$toclinks{ "Annotated List" } );
+ writeHier( $rootnode, "$outputdir/".$toclinks{Hierarchy} );
+ writeHeaderList( "$outputdir/".$toclinks{Files} );
+
+
+ # Document all compound nodes
+ Iter::LocalCompounds( $rootnode, sub { writeClassDoc( shift ); } );
+}
+
+=head2 writeClassList
+
+ Parameters: rootnode
+
+ Writes out a concise list of classes to index.html
+
+=cut
+
+sub writeClassList
+{
+ my ( $root, $file ) = @_;
+
+ open(CLIST, ">$file")
+ || die "Couldn't create $file\n";
+
+ newPgHeader( *CLIST{IO}, "$lib Class Index", "", "", \%toclinks );
+
+ if ( defined $root->{DocNode} ) {
+ printDoc( $root->{DocNode}, *CLIST, $root, 1 );
+ }
+
+ if ( $#clist < 0 ) {
+ print CLIST "<h2>No classes</h2>";
+ # TODO: Perhaps display C-specific index.
+ }
+ else {
+ writeTable( *CLIST{IO}, \@clist,
+ exists $opt->{"html-cols"} ? $opt->{"html-cols"} : 3 );
+ }
+
+ print CLIST $docBotty;
+ close CLIST;
+}
+
+
+
+=head2 writeAnnotatedList
+
+ Parameters: rootnode
+
+ Writes out a list of classes with short descriptions to
+ index-long.html.
+
+=cut
+
+sub writeAnnotatedList
+{
+ my ( $root, $file ) = @_;
+ my $short;
+
+ open(CLIST, ">$file")
+ || die "Couldn't create $file\n";
+
+ newPgHeader( *CLIST{IO}, "$lib Annotated List", "", "", \%toclinks );
+
+ print CLIST '<TABLE WIDTH="100%" BORDER=\"0\">';
+
+ my $colnum = 0;
+ my $colour;
+ my $col = 0;
+
+ foreach my $node ( @clist ) {
+ print "undef in clist\n" if !defined $node;
+
+ my $docnode = $node->{DocNode};
+ $short = "";
+
+ if( defined $docnode ) {
+ if ( exists $docnode->{ClassShort} ) {
+ $short = deref($docnode->{ClassShort},
+ $rootnode );
+ }
+ if ( defined $docnode->{Internal} ) {
+ $short .= " <small>(internal)</small>";
+ }
+ if ( defined $docnode->{Deprecated} ) {
+ $short .= " <small>(deprecated)</small>";
+ }
+ }
+
+ $col = $col ? 0 : 1;
+ $colour = $col ? "" : 'bgcolor="#eeeeee"';
+
+ print CLIST "<TR $colour><TD>", refNameFull( $node ),
+ "</TD><TD>", $short, "</TD></TR>";
+ }
+
+ print CLIST "</TABLE>", $docBotty;
+ close CLIST;
+}
+
+
+=head2 writeAllMembers
+
+ Parameters: node
+
+ Writes a list of all methods to "full-list-<class file>"
+
+=cut
+
+sub writeAllMembers
+{
+ my( $node ) = @_;
+ my $file = "$outputdir/full-list-".$node->{Ref};
+ my %allmem = ();
+
+ kdocAstUtil::allMembers( \%allmem, $node );
+
+ open( ALLMEM, ">$file" ) || die "Couldn't create $file\n";
+
+# print ALLMEM pageHeader( \%toclinks, esc($node->{astNodeName})
+# ." - All Methods" ), "<UL>";
+
+ newPgHeader( *ALLMEM,
+ $node->{NodeType}." ".esc($node->{astNodeName}).
+ ": All methods", "", "", \%toclinks );
+
+ my $mem;
+ my $col = 0;
+ my $colour = "";
+
+ my @memlist = sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ values %allmem;
+ writeTable( *ALLMEM{IO}, \@memlist, 3 );
+
+ print ALLMEM "$docBotty";
+
+ close ALLMEM;
+}
+
+=head2 writeHier
+
+ Parameters: rootnode
+
+ Writes out the class hierarchy index to hier.html.
+
+=cut
+
+sub writeHier
+{
+ my ( $root, $file ) = @_;
+
+ open( HIER, ">$file")
+ || die "Couldn't create $file\n";
+
+ newPgHeader( *HIER{IO}, "$lib Class Hierarchy", "", "", \%toclinks );
+
+ Iter::Hierarchy( $root,
+ sub { # down
+ print HIER "<UL>";
+ },
+ sub { # print
+ my ( $node ) = @_;
+ return if $node == $rootnode;
+
+ my $src = defined $node->{ExtSource} ?
+ " ($node->{ExtSource})" : "";
+
+ print HIER "<LI>", refNameFull( $node )," $src\n";
+ },
+ sub { # up
+ if ( $_[0] == $root ) {
+ print HIER "</UL>\n";
+ }
+ else {
+ print HIER "</UL></LI>\n";
+ }
+ },
+ sub { print HIER "</LI>\n"; }
+ );
+
+ print HIER $docBotty;
+ close HIER;
+}
+
+=head2 writeHeaderList
+
+ Generates the header-list.html file, which contains links
+ to each processed header. The $rootnode->{Sources} List is used.
+
+=cut
+
+sub writeHeaderList
+{
+ my ( $file ) = @_;
+
+ # Convert all to HTML
+
+ my @clist = sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @{$rootnode->{Sources}};
+
+ foreach my $hdr ( @clist ) {
+ writeSrcHTML( $outputdir."/".$hdr->{Ref}, $hdr->{Path} );
+ }
+
+
+ # Write the list
+
+ open(HDRIDX, ">$file") || die "Couldn't create $file\n";
+
+
+ newPgHeader( *HDRIDX{IO}, "$lib File Index", "", "", \%toclinks );
+
+ writeTable( *HDRIDX{IO}, \@clist,
+ exists $opt->{"html-cols"} ? $opt->{"html-cols"} : 3 );
+
+ print HDRIDX "</UL>\n",$docBotty;
+ close HDRIDX;
+}
+
+
+
+
+=head2 writeClassDoc
+
+ Write documentation for one compound node.
+
+=cut
+
+sub writeClassDoc
+{
+ my( $node ) = @_;
+
+ print "Enter: $node->{astNodeName}\n" if $debug;
+ if( exists $node->{ExtSource} ) {
+ warn "Trying to write doc for ".$node->{AstNodeName}.
+ " from ".$node->{ExtSource}."\n";
+ return;
+ }
+
+ my $file = "$outputdir/".join("__", kdocAstUtil::heritage($node)).".html";
+ my $docnode = $node->{DocNode};
+ my @list = ();
+ my $version = undef;
+ my $author = undef;
+
+ open( CLASS, ">$file" ) || die "Couldn't create $file\n";
+
+ # Header
+
+ my $short = "";
+ my $extra = "";
+
+ if( kdocAstUtil::hasDoc( $node ) ) {
+ if ( exists $docnode->{ClassShort} ) {
+ $short .= deref($docnode->{ClassShort},
+ $rootnode).
+ " <small>".
+ hyper( "#longdesc", "More..." )."</small>";
+ }
+
+ if ( exists $docnode->{Deprecated} ) {
+ $extra .= '<TR><TH colspan="2">'.
+ 'Deprecated! use with care</TH></TR>';
+ }
+
+ if ( exists $docnode->{Internal} ) {
+ $extra .= '<TR><TH colspan="2">'.
+ 'Internal Use Only</TH></TR>';
+
+ }
+ $version = esc($docnode->{Version})
+ if exists $docnode->{Version};
+ $author = esc($docnode->{Author})
+ if exists $docnode->{Author};
+ }
+
+ # pure virtual check
+ if ( exists $node->{Pure} ) {
+ $extra .= '<TR><TH colspan="2">'
+ .'Contains pure virtuals</TH></TR>';
+ }
+
+ # full name, if not in global scope
+ if ( $node->{Parent} != $rootnode ) {
+ $extra .= tabRow( "Full name",
+ "<code>".refNameEvery( $node, $rootnode )."</code>" );
+ }
+
+ # include (not for namespaces)
+ if ( $node->{NodeType} ne "namespace"
+ && $node->{NodeType} ne "Forward" ) {
+ $extra .= tabRow( 'Definition', '<code>#include <'.
+ refName( $node->{Source} ).'></code>' );
+ }
+
+ # template form
+ if ( exists $node->{Tmpl} ) {
+ $extra .= tabRow( "Template form",
+ esc($node->{astNodeName})
+ ."<".textRef($node->{Tmpl}, $rootnode )."> "
+ ."</code>" );
+ }
+
+
+ my $comma = "";
+ my $out = "";
+
+ # ancestors
+ Iter::Ancestors( $node, $rootnode, undef, undef,
+ sub { # print
+ my ( $ances, $name, $type, $template ) = @_;
+
+ if( !defined $ances ) {
+ $out .= $comma.esc($name);
+ }
+ else {
+ $out .= $comma.refNameFull( $ances );
+ }
+
+ $out .= " <".wordRef($template, $rootnode ).">"
+ unless !defined $template;
+
+ if ( exists $ances->{ExtSource} ) {
+ $out .=" <small>(".$ances->{ExtSource}
+ .")</small>";
+ }
+
+ $out .= " <small>[$type]</small>"
+ unless $type eq "public";
+
+ $comma = ", ";
+
+ },
+ sub { # end
+ $extra .= tabRow( "Inherits", $out );
+ }
+ );
+
+ # descendants
+ Iter::Descendants( $node, undef,
+ sub { $comma = $out = ""; }, # start
+ sub { # print
+ my ( $in ) = @_;
+ $out .= $comma.refName( $in );
+
+ if ( exists $in->{ExtSource} ) {
+ $short .= " <small>(".
+ $in->{ExtSource}.")</small>";
+ }
+
+ $comma = ", ";
+
+ },
+ sub { # end
+ $extra .= tabRow( "Inherited by", $out );
+ }
+ );
+
+ $extra .= '<TR><TH>'.
+ hyper( encodeURL("full-list-".$node->{Ref}),
+ "List of all Methods" )."</TH></TR>";
+
+
+ #### print it
+
+ newPgHeader( *CLASS{IO},
+ $node->{NodeType}." ".esc($node->{astNodeName}),
+ $short, $extra, \%toclinks );
+
+
+ if( $#{$node->{Kids}} < 0 ) {
+ print CLASS "<center><H4>No members</H4></center>\n";
+ }
+ else {
+ Iter::MembersByType ( $node,
+ sub { print CLASS "<h4>", $_[0], "</h4><ul>"; },
+ sub { my ($node, $kid ) = @_;
+ listMember( $node, $kid ); },
+ sub { print CLASS "</ul>"; }
+ );
+ }
+
+ # long description
+ if ( kdocAstUtil::hasDoc( $node ) ) {
+ print CLASS "<HR><A NAME=\"longdesc\">",
+ "<H2>Detailed Description</H2>";
+ printDoc( $docnode, *CLASS, $node, 1 );
+ }
+
+ # member doc
+ my $kid;
+ my ($numref, $ref);
+
+
+ Iter::DocTree( $node, 0, 0,
+ sub { # common
+ my ( $node, $kid ) = @_;
+
+ if( !exists $kid->{NumRef} ) {
+ warn $kid->{astNodeName}, " type ",
+ $kid->{NodeType}, " doesn't have a numref\n";
+ }
+
+ ( $numref = $kid->{NumRef} ) =~ s/^.*?#//g;
+ ( $ref = $kid->{Ref} ) =~ s/^.*?#//g;
+
+ printMemberName( $kid, $ref, $numref );
+ printDoc( $kid->{DocNode}, *CLASS, $node );
+
+ return;
+ },
+ undef, # compound
+ sub { # other
+ my ( $node, $kid ) = @_;
+
+ if ( $kid->{NodeType} eq "method" ) {
+ $ref = kdocAstUtil::findOverride( $rootnode,
+ $node, $kid->{astNodeName} );
+ if ( defined $ref ) {
+ print CLASS "<p>Reimplemented from ",
+ refName( $ref ), "</p>\n";
+ }
+ }
+
+ return;
+ }
+ );
+
+ # done
+
+ if ( defined $version || defined $author ) {
+ print CLASS "<HR><UL>",
+ defined $version ?
+ "<LI><i>Version</i>: $version</LI>" : "",
+ defined $author ?
+ "<LI><i>Author</i>: $author</LI>" : "",
+ "<LI><i>Generated</i>: $gentext</LI></UL>",
+ "</BODY></HTML>\n";
+ }
+ else {
+ print CLASS $docBotty;
+ }
+
+ close CLASS;
+
+ # full member list
+
+ writeAllMembers( $node );
+}
+
+sub writeGlobalDoc
+{
+ my( $node, $file ) = @_;
+ my $docnode = $node->{DocNode};
+ my $hasdoc = exists $node->{DocNode} ? 1 : 0;
+ my $cumu = Ast::New( "nodelist" );
+
+ # make a list of nodes by file
+ foreach my $kid ( @{$node->{Kids}} ) {
+ next if exists $kid->{ExtSource}
+ || exists $kid->{Compound}
+ || (!$main::doPrivate &&
+ $kid->{Access} =~ /private/);
+
+ if ( exists $kid->{Source} ) {
+ $kid->{Source}->AddPropList( "Glob", $kid )
+ }
+ }
+
+ open( CLASS, ">$file" ) || die "Couldn't create $file\n";
+
+ newPgHeader( *CLASS{IO}, $lib." Globals", "", "", \%toclinks );
+
+ my @list = sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @{$node->{Sources}};
+
+ foreach my $source ( @list ) {
+ next unless defined $source->{Glob};
+
+ listMethods( $node, refName( $source ), "", $source->{Glob} );
+ }
+
+ # member doc
+ my ($numref, $ref);
+
+ foreach my $source ( @list ) {
+ next unless defined $source->{Glob};
+
+ foreach my $kid ( @{$source->{Glob}} ) {
+ next if exists $kid->{ExtSource}
+ || exists $kid->{Compound}
+ || !exists $kid->{DocNode}
+ || (!$main::doPrivate &&
+ $kid->{Access} =~ /private/);
+
+ if( !exists $kid->{NumRef} ) {
+ warn $kid->{astNodeName}, " type ",
+ $kid->{NodeType}, " doesn't have a numref\n";
+ }
+
+ ( $numref = $kid->{NumRef} ) =~ s/^.*?#//g;
+ ( $ref = $kid->{Ref} ) =~ s/^.*?#//g;
+
+ printMemberName( $kid, $ref, $numref );
+
+ print CLASS "<p><small><code>#include <",
+ refName( $source ),
+ "></code></small></p>";
+
+ printDoc( $kid->{DocNode}, *CLASS, $node );
+ }
+ }
+
+ print CLASS $docBotty;
+ close CLASS;
+}
+
+
+sub listMember
+{
+ my( $class, $m ) = @_;
+ my $name;
+
+ if( exists $m->{Compound} ) {
+ # compound docs not printed for rootnode
+ next if $class eq $rootnode;
+
+ $name = refName( $m );
+ }
+ elsif( exists $m->{DocNode} ) {
+ # compound nodes have their own page
+ $name = refName( $m, 'NumRef' );
+ } else {
+ $name = esc( $m->{astNodeName} );
+ }
+
+ my $type = $m->{NodeType};
+
+ print CLASS "<LI>";
+
+ if( $type eq "var" ) {
+ print CLASS esc( $m->{Type}), B( "b", $name );
+ }
+ elsif( $type eq "method" ) {
+ my $flags = $m->{Flags};
+
+ if ( !defined $flags ) {
+ warn "Method ".$m->{astNodeName}. " has no flags\n";
+ }
+
+ $name = B("i", $name ) if $flags =~ /p/;
+ $name = B("b", $name );
+
+ my $extra = "";
+ $extra .= "virtual " if $flags =~ "v";
+ $extra .= "static " if $flags =~ "s";
+
+ print CLASS $extra, textRef($m->{ReturnType}, $rootnode ),
+ "\ $name (", textRef( $m->{Params}, $rootnode ), ") ",
+ $flags =~ /c/ ? " const\n": "\n";
+ }
+ elsif( $type eq "enum" ) {
+ print CLASS "enum $name {", esc($m->{Params}),"}\n";
+ }
+ elsif( $type eq "typedef" ) {
+ print CLASS "typedef ", esc($m->{Type}), " $name\n";
+ }
+ else {
+ # unknown type
+ print CLASS esc($type), " $name\n";
+ }
+
+ print CLASS "</LI>\n";
+
+}
+
+sub listMethods
+{
+ my( $class, $desc, $vis, $nodes ) = @_;
+ my $name;
+ my $type;
+ my $flags;
+ my @n=();
+
+ if ( !defined $nodes ) {
+ kdocAstUtil::findNodes( \@n, $class->{Kids},
+ "Access", $vis );
+ $nodes = \@n;
+ }
+
+ return if ( $#{$nodes} < 0 );
+
+print CLASS<<EOF;
+<H2>$desc</H2>
+<UL>
+EOF
+ foreach my $m ( @$nodes ) {
+ next if exists $m->{ExtSource};
+ if( exists $m->{Compound} ) {
+ # compound docs not printed for rootnode
+ next if $class eq $rootnode;
+
+ $name = refName( $m );
+ }
+ elsif( exists $m->{DocNode} ) {
+ # compound nodes have their own page
+ $name = refName( $m, 'NumRef' );
+ } else {
+ $name = esc( $m->{astNodeName} );
+ }
+
+ $type = $m->{NodeType};
+ $name = B( "b", $name );
+
+ print CLASS "<LI>";
+
+ if( $type eq "var" ) {
+ print CLASS esc( $m->{Type}), " $name\n";
+ }
+ elsif( $type eq "method" ) {
+ $flags = $m->{Flags};
+
+ if ( !defined $flags ) {
+ warn "Method ".$m->{astNodeName}.
+ " has no flags\n";
+ }
+
+ $name = "<i>$name</i>" if $flags =~ /p/;
+ my $extra = "";
+ $extra .= "virtual " if $flags =~ "v";
+ $extra .= "static " if $flags =~ "s";
+
+ print CLASS $extra, textRef($m->{ReturnType}, $rootnode),
+ "\ $name (", textRef( $m->{Params}, $rootnode), ") ",
+ $flags =~ /c/ ? " const\n": "\n";
+ }
+ elsif( $type eq "enum" ) {
+ print CLASS "enum $name {", esc($m->{Params}),"}\n";
+ }
+ elsif( $type eq "typedef" ) {
+ print CLASS "typedef ", esc($m->{Type}), " $name";
+ }
+ else {
+ # unknown type
+ print CLASS esc($type), " $name\n";
+ }
+
+ print CLASS "</LI>\n";
+ }
+
+print CLASS<<EOF;
+</UL>
+EOF
+
+}
+
+=head2 printIndexEntry
+
+ Parameters: member node
+
+ Prints an index entry for a single node.
+
+ TODO: stub
+
+=cut
+
+sub printIndexEntry
+{
+ my ( @node ) = @_;
+}
+
+=head2 printMemberName
+
+ Parameters: member node, names...
+
+ Prints the name of one member, customized to type. If names are
+ specified, a name anchor is written for each one.
+
+=cut
+
+sub printMemberName
+{
+ my $m = shift;
+
+ my $name = B( "underline", esc( $m->{astNodeName} ) );
+ my $type = $m->{NodeType};
+ my $ref;
+ my $flags = undef;
+
+ foreach $ref ( @_ ) {
+ print CLASS "<A NAME=\"", $ref, "\"></A>";
+ }
+
+ print CLASS '<table width="100%"><tr bgcolor="#eeeeee"><td><strong>';
+
+ if( $type eq "var" ) {
+ print CLASS textRef($m->{Type}, $rootnode ), " $name\n";
+ }
+ elsif( $type eq "method" ) {
+ $flags = $m->{Flags};
+ $name = "<i>$name</i>" if $flags =~ /p/;
+
+ print CLASS textRef($m->{ReturnType}, $rootnode ),
+ "\ $name (", textRef($m->{Params}, $rootnode ), ")\n";
+ }
+ elsif( $type eq "enum" ) {
+ print CLASS "enum $name {", esc($m->{Params}),"}\n";
+ }
+ elsif( $type eq "typedef" ) {
+ print CLASS "typedef ",
+ textRef($m->{Type}, $rootnode ), " $name";
+ }
+ else {
+ print CLASS $name, " ", B( "small", "(", esc($type), ")" );
+ }
+
+ print CLASS "</strong></td></tr></table><p>";
+
+# extra attributes
+ my @extra = ();
+
+ if( !exists $m->{Access} ) {
+ warn "Member without access:\n";
+ kdocAstUtil::dumpAst( $m );
+ }
+
+ ($ref = $m->{Access}) =~ s/_slots//g;
+
+ push @extra, $ref
+ unless $ref =~ /public/
+ || $ref =~ /signal/;
+
+ if ( defined $flags ) {
+ foreach my $f ( split( "", $flags ) ) {
+ my $n = $main::flagnames{ $f };
+
+ if ( defined $n ) {
+ push @extra, $n;
+ }
+ else {
+ warn "flag $f has no long name.";
+ }
+
+ }
+ }
+
+ if ( $#extra >= 0 ) {
+ print CLASS " <small>[", join( " ", @extra ), "]</small>";
+ }
+
+ print CLASS "</p>";
+
+ return;
+}
+
+
+
+sub writeSrcHTML
+{
+ my ( $outfile, $infile ) = @_;
+
+ open ( OUT, ">$outfile" ) || die "Couldn't open $outfile for".
+ "writing.\n";
+
+ newPgHeader( *OUT{IO}, "Source: $infile", "", "", \%toclinks );
+ makeHeader( *OUT{IO}, $infile );
+
+ print OUT $docBotty;
+ close OUT;
+}
+
+1;
--- /dev/null
+package kdocCxxLaTeX;
+
+use File::Path;
+use File::Basename;
+
+use Carp;
+use Ast;
+use kdocAstUtil;
+
+=head1 kdocCxxLaTex
+
+Capabilities required from Ast bit:
+
+1. Create an inheritance tree
+
+2. Referencing ability: convert a fully qualified class or member name
+ to a node reference.
+
+=cut
+
+BEGIN
+{
+ @clist = ();
+ @docQueue = ();
+
+ eval {
+ use Sys::Hostname;
+ $host = hostname();
+ chomp $host;
+ };
+ eval {
+ $who = `whoami`;
+ if($who =~ /DCL-W-IVVERB/) {
+ $who = `show process`;
+ ($who) = ( $who =~ /User: ([^\s]+)/ );
+ }
+ chomp $who;
+ };
+ $now = localtime;
+ chomp $now;
+ $gentext = "$who\@$host, $now.";
+}
+
+sub writeDoc
+{
+ ( $lib, $rootnode, $outputdir, $opt ) = @_;
+
+ $debug = $main::debug;
+
+ print "Generating LaTeX documentation. \n" unless $main::quiet;
+
+ mkpath( $outputdir ) unless -f $outputdir;
+
+# makeReferences( $rootnode );
+ makeClassList( $rootnode );
+
+ startMainDocument();
+
+# ??? Wykomentowane rzeczy jeszcze nie przerobione
+
+ writeGlobalDoc( $rootnode );
+ writeAnnotatedList( $rootnode );
+ writeHier( $rootnode );
+# writeHeaderList();
+
+ foreach $node ( @{$rootnode->{Kids}} ) {
+ next if !defined $node->{Compound}
+ || defined $node->{ExtSource}
+ || $node->{NodeType} eq "Forward";
+
+ push @docQueue, $node;
+ }
+
+ # Próbujemy posortowaæ t± kolejkê
+ @docQueue = sort { $b->{astNodeName} cmp $a->{astNodeName} } @docQueue;
+
+ while( $#docQueue >= 0 ) {
+ $node = pop @docQueue;
+ writeClassDoc( $node );
+ }
+
+ print "Generating LaTeXized headers.\n" unless $main::quiet;
+ foreach $header ( @main::ARGV ) {
+ markupCxxHeader( $header, $rootnode );
+ }
+
+ finishMainDocument();
+}
+
+=head2 writeAnnotatedList
+
+ Parameters: rootnode
+
+ Writes out a list of classes with short descriptions to
+ index-long.tex.
+
+=cut
+
+sub writeAnnotatedList
+{
+ my ( $root ) = @_;
+ my $short;
+
+ open(CLIST, ">$outputdir/index-long.tex")
+ || die "Couldn't create $outputdir/index-long.tex\n";
+
+ print MAIN "\\input{index-long.tex}\n\n";
+
+ print CLIST sectionHeader( "Lista klas " . $lib );
+ print CLIST <<EOF;
+\\begin{longtable}{lp{8cm}}
+EOF
+ foreach $node ( @clist ) {
+ print "undef in clist\n" if !defined $node;
+
+ $docnode = $node->{DocNode};
+ $short = "";
+
+ if( defined $docnode && exists $docnode->{ClassShort} ) {
+ $short = deref($docnode->{ClassShort}, $rootnode );
+ if( !defined $short ) {
+ print $root->{astNodeName}, "has undef short\n";
+ next;
+ }
+
+ }
+
+ print CLIST refName($node), ' & ', $short, "\\\\\n";
+ }
+
+ print CLIST "\\end{longtable}\n";
+ close CLIST;
+}
+
+=head2 writeClassList
+
+ Parameters: rootnode
+
+ Writes out a concise list of classes to index.tex
+
+=cut
+
+=head3
+
+ Parameters: list, start index, end index
+
+ Helper for writeClassList. Prints a table containing a
+ hyperlinked list of all nodes in the list from start index to
+ end index. A table header is also printed.
+
+=cut
+
+sub writeListPart
+{
+ my( $list, $start, $stop ) = @_;
+
+ print CLIST "<TABLE BORDER=\"0\">";
+
+ print CLIST "<TR><TH>",
+ esc( $list->[ $start ]->{astNodeName} ),
+ " - ", esc( $list->[ $stop ]->{astNodeName} ),
+ "</TH></TR>";
+
+ for $ctr ( $start..$stop ) {
+ print CLIST "<TR><TD>", refName( $list->[ $ctr ] ),
+ "</TD></TR>\n";
+ }
+
+ print CLIST "</TABLE>";
+}
+
+
+=head2 writeAllMembers
+
+ Parameters: node
+
+ Writes a list of all methods to "full-list-<class file>"
+
+=cut
+
+sub writeAllMembers
+{
+ my( $node ) = @_;
+ my $file = "$outputdir/full-list-".$node->{Ref};
+ my %allmem = ();
+
+ kdocAstUtil::allMembers( \%allmem, $node );
+
+ open( ALLMEM, ">$file" ) || die "Couldn't create $file\n";
+
+ my $thisClassName = $node->{astNodeName};
+ print ALLMEM sectionHeader( "Wszystkie metody " . esc($thisClassName) ),
+ "<UL>";
+
+ my $mem;
+ foreach $mem ( sort keys %allmem ) {
+ my $parentName = $allmem{$mem}->{Parent}->{astNodeName};
+ print ALLMEM "<LI>";
+ print ALLMEM refName( $allmem{ $mem } );
+ if($parentName ne $thisClassName) {
+ print ALLMEM " <small>[$parentName]</small>"
+ }
+ print ALLMEM "</LI>\n";
+ }
+
+ print ALLMEM "</UL>$docBotty";
+
+ close ALLMEM;
+}
+
+=head2 writeHier
+
+ Parameters: rootnode
+
+ Writes out the class hierarchy index to hier.html.
+
+=cut
+
+sub writeHier
+{
+ my ( $root ) = @_;
+
+ open( HIER, ">$outputdir/hier.tex")
+ || die "Couldn't create $outputdir/hier.tex\n";
+
+ print MAIN "\\input{hier.tex}\n\n";
+
+ print HIER sectionHeader( $lib.": Class Hierachy" );
+
+ printNodeHier( $root, 0 );
+
+ close HIER;
+}
+
+=head3 printNodeHier
+
+ Parameters: node
+
+ Lists all classes that inherit from this node in an unordered list.
+
+=cut
+
+sub printNodeHier
+{
+ my( $node, $level ) = @_;
+ my $kid;
+ my $src = "";
+
+ # non-derived external classes are not printed.
+ if ( defined $node->{ExtSource} ) {
+ return if !defined $node->{InBy}
+ || !kdocAstUtil::hasLocalInheritor( $node );
+
+ $src = "{\\small ".$node->{ExtSource}.")}";
+ }
+
+# print HIER "\\item ",
+ print HIER "\\verb!", ' ' x $level, "!",
+ refName( $node )," $src\\\\\n"
+ unless $node == $rootnode;
+
+ return if !defined $node->{InBy};
+
+# print HIER "\\begin{itemize}\n";
+
+ foreach $kid ( sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @{ $node->{InBy} } ) {
+ printNodeHier( $kid, $level + 1 );
+ }
+# print HIER "\\end{itemize}\n";
+}
+
+=head2 writeHeaderList
+
+ Generates the header-list.html file, which contains links
+ to each processed header. The ARGV list is used.
+
+=cut
+
+sub writeHeaderList
+{
+ open(HDRIDX, ">$outputdir/header-list.html")
+ || die "Couldn't create $outputdir/header-list.html\n";
+
+ print HDRIDX sectionHeader( $lib . ": Header List" ), "<UL>\n";
+
+ foreach $header ( sort @main::ARGV ) {
+ $_ = $header;
+ $header = basename ( $_ ) if $main::striphpath;
+# convert dashes to double dash, convert path to dash
+ s/-/--g/g;
+ s/\/|\./-/g;
+
+ print HDRIDX "\t<LI>",hyper($_.".html",$header),"</LI>\n";
+ }
+
+ print HDRIDX "</UL>\n",$docBotty;
+
+}
+
+=head2 sectionHeader
+
+ Parameters: libname, heading
+
+ Returns a string containing an HTML section heading.
+
+=cut
+
+sub sectionHeader
+{
+ my( $heading, $desc ) = @_;
+
+ $desc = "" if !defined $desc;
+
+ my $libtext = "";
+ if( $lib ne "" ) {
+ $libtext = "<TR><TD><small>Dokumentacja $lib</small>".
+ "</TD></TR>";
+ }
+
+ return <<EOF;
+\\section{$heading}
+
+EOF
+
+}
+
+=head2 writeClassDoc
+
+ Write documentation for one compound node.
+
+=cut
+
+sub writeClassDoc
+{
+ my( $node ) = @_;
+ if( exists $node->{ExtSource} ) {
+ warn "Trying to write doc for ".$node->{AstNodeName}.
+ " from ".$node->{ExtSource}."\n";
+ return;
+ }
+
+ my $file = "$outputdir/".$node->{astNodeName}.".tex";
+ my $docnode = $node->{DocNode};
+ my $hasdoc = exists $node->{DocNode} ? 1 : 0;
+ my @list = ();
+ my $version = undef;
+ my $author = undef;
+
+ open( CLASS, ">$file" ) || die "Couldn't create $file\n";
+
+ print MAIN "\\input{".$node->{astNodeName}.".tex}\n\n";
+
+ # Header
+
+ my $source = kdocAstUtil::nodeSource( $node );
+ my $short = "";
+
+ if( $hasdoc ) {
+ if ( exists $docnode->{ClassShort} ) {
+# $short .= deref($docnode->{ClassShort}, $rootnode );
+ $short .= $docnode->{ClassShort};
+ }
+
+ if ( exists $docnode->{Deprecated} ) {
+ $short .= "\n\n\\textbf{Przestarza³e: u¿ywaæ ostro¿nie.}";
+ }
+
+ if ( exists $docnode->{Internal} ) {
+ $short .= "\n\n\\textbf{Tylko do wewnêtrznego u¿ytku.}";
+ }
+ $version = esc($docnode->{Version})
+ if exists $docnode->{Version};
+ $author = esc($docnode->{Author})
+ if exists $docnode->{Author};
+ }
+
+ # pure virtual check
+ if ( exists $node->{Pure} ) {
+ $short .=
+ "\n\n\\textbf{Klasa abstrakcyjna}\n\n";
+ }
+
+ # full name, if not in global scope
+ if ( $node->{Parent} != $rootnode ) {
+ $short .= "\n\n\\texttt{" . $node->{astNodeName} ."}";
+ }
+
+ # include
+ # MK --> hack (link z #include)
+ $short .= "\n\n\\verb!#include <".$source.">!\n\n";
+
+ # template form
+ if ( exists $node->{Tmpl} ) {
+ $short .= "\n\nKlasa parametryzowana (template): \\verb!<"
+ .textRef($node->{Tmpl}, $rootnode)."> ".
+ esc($node->{astNodeName},
+ $rootnode )."!\n\n";
+ }
+
+ # inheritance
+ if ( $node != $rootnode && exists $node->{InList} ) {
+ my $comma = "Dziedziczy z: ";
+
+ foreach $in ( @{ $node->{InList} } ) {
+ next if $in == $rootnode;
+
+ $short .= $comma.refName( $in );
+ if ( exists $in->{ExtSource} ) {
+ $short .= " {\\small(".$in->{ExtSource}
+ .")}";
+ }
+
+ $comma = ", ";
+ }
+
+ $short .= "\n\n";
+ }
+
+ if ( $node != $rootnode && exists $node->{InBy} ) {
+ my $comma .= "Klasy dziedzicz±ce: ";
+
+ @list = ();
+ kdocAstUtil::inheritedBy( \@list, $node );
+
+ foreach $in ( @list ) {
+ $short .= $comma.refName( $in );
+ if ( exists $in->{ExtSource} ) {
+ $short .= " {\\small(".
+ $in->{ExtSource}.")}";
+ }
+
+ $comma = ", ";
+ }
+ $short .= "\n\n";
+ }
+
+ # print it
+
+ print CLASS sectionHeader(
+ $node->{NodeType}." ".esc($node->{astNodeName}),
+ $short );
+
+ if( $#{$node->{Kids}} < 0 ) {
+ print CLASS <<EOF;
+\\begin{quote}
+Brak sk³adowych
+\\end{quote}
+EOF
+ }
+ else {
+ listMethods( $node, "Sk³adowe publiczne", "public" );
+ listMethods( $node, "Public Slots", "public_slots" );
+ listMethods( $node, "Sk³adowe chronione", "protected" );
+ listMethods( $node, "Protected Slots", "protected_slots" );
+ listMethods( $node, "Signals", "signals" );
+
+ if ( $main::doPrivate ) {
+ listMethods( $node, "Sk³adowe prywatne", "private" );
+ listMethods( $node, "Private Slots", "private_slots" );
+ }
+ }
+
+ # long description
+ if ( $hasdoc ) {
+ print CLASS "\n\\subsection*{Opis klasy}\n\n";
+ printDoc( $docnode, *CLASS, $rootnode, 1 );
+ }
+
+ # member doc
+ my $kid;
+ my ($numref, $ref);
+
+ foreach $kid ( @{$node->{Kids}} ) {
+ next if defined $kid->{ExtSource}
+ || $node->{NodeType} eq "Forward"
+ || (!$main::doPrivate &&
+ $kid->{Access} =~ /private/);
+
+ if ( exists $kid->{Compound} ) {
+ push @docQueue, $kid;
+ }
+
+ next if !defined $kid->{DocNode};
+
+# ??? Przywróciæ kiedy¶
+# if( !exists $kid->{NumRef} ) {
+# warn $kid->{astNodeName}, " type ",
+# $kid->{NodeType}, " doesn't have a numref\n";
+# }
+
+# ??? Przywróciæ kiedy¶ ???
+# ( $numref = $kid->{NumRef} ) =~ s/^.*?#//g;
+# ( $ref = $kid->{Ref} ) =~ s/^.*?#//g;
+
+ printMemberName( $kid, $ref, $numref );
+ printDoc( $kid->{DocNode}, *CLASS, $rootnode );
+
+ if ( $kid->{NodeType} eq "method" ) {
+ $ref = kdocAstUtil::findOverride( $rootnode, $node,
+ $kid->{astNodeName} );
+ if ( defined $ref ) {
+ print CLASS "\n\nPrzykrywa metodê z klasy ",
+ refName( $ref ), "\n\n";
+ }
+ }
+ }
+
+ # done
+
+# if ( defined $version || defined $author ) {
+# print CLASS "\\begin{itemize}\n",
+# defined $version ?
+# "\\item Wersja: $version;\n" : "",
+# defined $author ?
+# "\\item Autor: $author;\n" : "",
+# "\\item Generowane: $gentext;\n",
+# "\\end{itemize}\n";
+# }
+# else {
+# print CLASS "Generowane: $gentext\n";
+# }
+
+ close CLASS;
+
+ # full member list
+
+# ??? Kiedy¶ jednak zrobiæ
+# writeAllMembers( $node );
+}
+
+sub writeGlobalDoc
+{
+ my( $node ) = @_;
+ my $file = "$outputdir/all-globals.tex";
+ my $docnode = $node->{DocNode};
+ my $hasdoc = exists $node->{DocNode} ? 1 : 0;
+ my @list = ();
+ my $cumu = Ast::New( "nodelist" );
+ my $kid;
+
+ # make a list of nodes by file
+ foreach $kid ( @{$node->{Kids}} ) {
+ next if exists $kid->{ExtSource}
+ || exists $kid->{Compound}
+ || (!$main::doPrivate &&
+ $kid->{Access} =~ /private/);
+
+ $cumu->AddPropList( kdocAstUtil::nodeSource( $kid ), $kid )
+ unless !exists $kid->{Source};
+ }
+
+ open( CLASS, ">$file" ) || die "Couldn't create $file\n";
+
+ print MAIN "\\input{all-globals.tex}\n\n";
+
+ print CLASS sectionHeader( "Zmienne, typy i funkcje globalne " . $lib);
+ @list = sort keys %$cumu;
+
+ foreach $file ( @list ) {
+ next if $file eq "astNodeName";
+
+ listMethods( $node, esc($file), "", $cumu->{$file} );
+ }
+
+ # member doc
+ my ($numref, $ref);
+
+ foreach $file ( @list ) {
+ next if $file eq "astNodeName";
+
+ foreach $kid ( @{$cumu->{$file}} ) {
+ next if exists $kid->{ExtSource}
+ || exists $kid->{Compound}
+ || !exists $kid->{DocNode}
+ || (!$main::doPrivate &&
+ $kid->{Access} =~ /private/);
+
+# ??? Przywróciæ kiedy¶
+# if( !exists $kid->{NumRef} ) {
+# warn $kid->{astNodeName}, " type ",
+# $kid->{NodeType}, " doesn't have a numref\n";
+# }
+
+# ??? Przywróciæ kiedy¶
+# ( $numref = $kid->{NumRef} ) =~ s/^.*?#//g;
+# ( $ref = $kid->{Ref} ) =~ s/^.*?#//g;
+
+ printMemberName( $kid, $ref, $numref );
+
+ print CLASS "\n\n{\\small\\verb!#include <",
+ kdocAstUtil::nodeSource( $kid ),
+ ">!}\n\n";
+
+ printDoc( $kid->{DocNode}, *CLASS, $rootnode );
+ }
+ }
+
+# print CLASS $docBotty;
+ close CLASS;
+}
+
+sub listMethods
+{
+ my( $class, $desc, $vis, $nodes ) = @_;
+ my $name;
+ my $type;
+ my $flags;
+ my @n=();
+
+ if ( !defined $nodes ) {
+ kdocAstUtil::findNodes( \@n, $class->{Kids},
+ "Access", $vis );
+ $nodes = \@n;
+ }
+
+ return if ( $#{$nodes} < 0 );
+
+print CLASS<<EOF;
+\\subsection*{$desc}
+
+\\begin{itemize}
+EOF
+ foreach $m ( @$nodes ) {
+ next if exists $m->{ExtSource};
+ if( exists $m->{Compound} ) {
+ # compound docs not printed for rootnode
+ next if $class eq $rootnode;
+
+ $name = refName( $m );
+ }
+ elsif( exists $m->{DocNode} ) {
+ # compound nodes have their own section
+ $name = refName( $m, 'NumRef' );
+ } else {
+ $name = esc( $m->{astNodeName} );
+ }
+
+ $type = $m->{NodeType};
+
+ print CLASS "\\item ";
+
+ if( $type eq "var" ) {
+ print CLASS esc( $m->{Type}),
+ " \\textbf{", $name,"}\n";
+ }
+ elsif( $type eq "method" ) {
+ $flags = $m->{Flags};
+
+ if ( !defined $flags ) {
+ warn "Method ".$m->{astNodeName}.
+ " has no flags\n";
+ }
+
+ $name = "\\emph{$name}" if $flags =~ /p/;
+ my $extra = "";
+ $extra .= "virtual " if $flags =~ "v";
+ $extra .= "static " if $flags =~ "s";
+
+ print CLASS $extra, esc($m->{ReturnType}),
+ " \\textbf{", $name, "} (",
+ esc($m->{Params}), ") ",
+ $flags =~ /c/ ? " const\n": "\n";
+ }
+ elsif( $type eq "enum" ) {
+ print CLASS "enum \\textbf{", $name, "} {",
+ esc($m->{Params}),"}\n";
+ }
+ elsif( $type eq "typedef" ) {
+ print CLASS "typedef ",
+ esc($m->{Type}), " \\textbf{",
+ $name,"}";
+ }
+ else {
+ # unknown type
+ print CLASS esc($type), " \\textbf{",
+ $name,"}\n";
+ }
+
+ print CLASS "\n";
+ }
+
+print CLASS<<EOF;
+\\end{itemize}
+EOF
+
+}
+
+=head2 printIndexEntry
+
+ Parameters: member node
+
+ Prints an index entry for a single node.
+
+ TODO: stub
+
+=cut
+
+sub printIndexEntry
+{
+ my ( @node ) = @_;
+}
+
+=head2 printMemberName
+
+ Parameters: member node, names...
+
+ Prints the name of one member, customized to type. If names are
+ specified, a name anchor is written for each one.
+
+=cut
+
+sub printMemberName
+{
+ my $m = shift;
+
+ my $name = esc( $m->{astNodeName} );
+ my $type = $m->{NodeType};
+ my $ref;
+ my $flags = undef;
+
+ foreach $ref ( @_ ) {
+# ??? Pomy¶leæ o tym
+# print CLASS "\\label{", $ref, "}";
+ }
+
+# print CLASS "\n\n\\textbf{";
+ print CLASS "\n\n\\subsubsection*{";
+
+ if( $type eq "var" ) {
+ print CLASS textRef($m->{Type}, $rootnode ),
+ " \\texttt{", $name,"} ";
+ }
+ elsif( $type eq "method" ) {
+ $flags = $m->{Flags};
+ $name = "\\emph{$name}" if $flags =~ /p/;
+
+ print CLASS textRef($m->{ReturnType}, $rootnode ),
+ " \\texttt{", $name, "} (",
+ textRef($m->{Params}, $rootnode ), ") ";
+ }
+ elsif( $type eq "enum" ) {
+ print CLASS "enum \\texttt{", $name, "} {",
+ esc($m->{Params}),"} ";
+ }
+ elsif( $type eq "typedef" ) {
+ print CLASS "typedef ",
+ textRef($m->{Type}, $rootnode ), " \\texttt{",
+ $name,"} ";
+ }
+ else {
+ print CLASS $name, " {\\small (",
+ esc($type), ")} ";
+ }
+
+# extra attributes
+ my @extra = ();
+
+ if( !exists $m->{Access} ) {
+ print "Member without access:\n";
+ kdocAstUtil::dumpAst( $m );
+ }
+
+ ($ref = $m->{Access}) =~ s/_slots//g;
+
+ push @extra, $ref
+ unless $ref =~ /public/
+ || $ref =~ /signal/;
+
+ if ( defined $flags ) {
+ my $f;
+ my $n;
+ foreach $f ( split( "", $flags ) ) {
+ $n = $main::flagnames{ $f };
+ warn "flag $f has no long name.\n" if !defined $n;
+ push @extra, $n;
+ }
+ }
+
+ if ( $#extra >= 0 ) {
+ print CLASS " {\\small [", join( " ", @extra ), "]}";
+ }
+
+ print CLASS "}"; # Po subsubsection
+ print CLASS "\n\n";
+
+# finis
+}
+
+
+
+=head2 makeClassList
+
+ Parameters: node
+
+ fills global @clist with a list of all direct, non-external
+ compound children of node.
+
+=cut
+
+sub makeClassList
+{
+ my ( $rootnode ) = @_;
+
+ @clist = ();
+
+ foreach $node ( @ {$rootnode->{Kids}} ) {
+ if ( !defined $node ) {
+ print "makeClassList: undefined child in rootnode!\n";
+ next;
+ }
+
+ push( @clist, $node ) unless exists $node->{ExtSource}
+ || !exists $node->{Compound};
+ }
+
+ @clist = sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @clist;
+}
+
+# MK --> skopiowane z 1.0
+sub markupCxxHeader
+{
+ my( $filename, $rootnode ) = @_;
+ $className = "";
+ my( $reference );
+ my( @inheritance );
+ my( $word );
+
+ open( HFILE, $filename ) || die "Couldn't open $filename to read.\n";
+
+ $_ = $filename;
+ # convert dashes to double dash, convert path to dash
+ s/-/--g/g;
+ s/\/|\./-/g;
+ $outputName = $_;
+ $outputFilename = $outputdir."/".$outputName;
+
+ open( HTMLFILE, ">$outputFilename.tex" )
+ || die "Couldn't open $outputFilename to write.\n";
+
+ print MAIN "\\input{$outputName.tex}\n\n";
+
+ print HTMLFILE sectionHeader( esc("$filename") );
+
+ print HTMLFILE <<EOF;
+\\selectlisting{cpp}
+\\begin{listing}
+EOF
+ while( <HFILE> )
+ {
+ print HTMLFILE;
+
+# ??? Co¶ zrobiæ
+# if( /^\s*(template.*\s+)?(class|struct)/ ) {
+# if($rootnode) {
+# $_ = textRef($_, $rootnode);
+# } else {
+# print STDERR "$0: can not make hyperlinks in file $filename\n";
+# }
+# }
+
+ }
+
+ print HTMLFILE <<EOF;
+\\end{listing}
+EOF
+}
+
+sub startMainDocument {
+
+ open(MAIN, ">$outputdir/main.tex")
+ || die "Couldn't create $outputdir/main.tex\n";
+
+ print MAIN <<EOF;
+\\documentclass[a4paper,10pt]{article}
+
+% Geometria strony (twoside ?)
+\\usepackage[a4paper,hmargin={2cm,2cm},vmargin={2cm,2cm}]{geometry}
+
+\\usepackage[latin2]{inputenc}
+\\usepackage{polski}
+
+\\usepackage{longtable}
+
+% Specyficzne listingi
+\\usepackage{listings}
+\\keywordstyle{\\bfseries\\sffamily}
+%\\commentstyle{\\slshape}
+\\commentstyle{\\itshape}
+%\\stringstyle{\\ttfamily}
+\\blankstringtrue
+\\prelisting{\\small\\sffamily}
+
+% Przynajmniej nie bêdzie krzycza³
+% \\catcode`\\_=12
+
+% Odstêpy miêdzy akapitami itp
+\\setlength{\\parindent}{0cm}
+\\addtolength{\\parskip}{1ex}
+
+\\title{Dokumentacja referencyjna $lib}
+
+\\begin{document}
+
+\\maketitle
+\\tableofcontents
+
+\\begin{abstract}
+Dokumentacja referencyjna $lib.
+
+Generowana: $gentext.
+\\end{abstract}
+
+EOF
+}
+
+sub finishMainDocument {
+ print MAIN <<EOF;
+
+\\end{document}
+EOF
+}
+
+sub esc
+{
+ my $str = $_[ 0 ];
+
+ return "" if !defined $str || $str eq "";
+
+ # Trzeba zrobiæ sztuczkê by nie zamieniaæ w³asnych klamerek
+ # lub backslashy
+ $str =~ s/{/\\lbrace/g;
+ $str =~ s/}/\\rbrace/g;
+ $str =~ s/\\/\\ensuremath{\\backslash}/g;
+# $str =~ s/{/\\{/g;
+# $str =~ s/}/\\}/g;
+
+ $str =~ s/</\\ensuremath{<}/g;
+ $str =~ s/>/\\ensuremath{>}/g;
+ $str =~ s/#/\\#/g;
+ $str =~ s/%/\\%/g;
+ $str =~ s/&/\\&/g;
+ $str =~ s/\$/\\\$/g;
+ $str =~ s/_/\\_/g;
+ $str =~ s/~/\\ensuremath{\\sim}/g;
+# $str =~ s/\^/{\\ensuremath{^}}/g;
+
+ return $str;
+}
+
+sub refName
+{
+ my ( $node ) = @_;
+ confess "refName called with undef" if !defined $node->{astNodeName};
+
+ my $ref = defined $_[1] ? $_[1] : 'Ref';
+
+ $ref = $node->{ $ref };
+
+ my $out;
+
+# if ( !defined $ref ) {
+ $out = esc($node->{astNodeName});
+# } else {
+# $out = '<A HREF="'.encodeURL($ref).'">'.
+# esc($node->{astNodeName}).'</A>';
+# }
+
+ $out = "\\emph{".$out."}" if exists $node->{Pure};
+
+# print "DIAG: refName zwraca $out\n";
+ return $out;
+
+}
+
+sub deref
+{
+ my ( $str, $rootnode ) = @_;
+ confess "rootnode is null" if !defined $rootnode;
+
+ my $out = "";
+ my $text;
+
+ foreach $text ( split (/(\@ref\s+[\w:#]+)/, $str ) ) {
+ if ( $text =~ /\@ref\s+([\w:#]+)/ ) {
+ my $x = wordRef( $1, $rootnode );
+# print "DIAG: w derefie $1 -> $x\n";
+ $out .= $x;
+ }
+ else {
+ $out .= esc($text);
+ }
+ }
+
+# print "DIAG: deref dla\n$str\nzwraca\n$out\n" if $str ne $out;
+ return $out;
+}
+
+=head2 printDoc
+
+ Parameters: docnode, *filehandle, rootnode, compound
+
+ Print a doc node. If compound is specified and non-zero, various
+ compound node properties are not printed.
+
+=cut
+
+sub printDoc
+{
+ local ($docNode, *CLASS, $rootnode, $comp ) = @_;
+ my $node;
+ my $type;
+ my $text;
+ my $lasttype = "none";
+
+ $comp = defined $comp? $comp : 0;
+
+ $text = $docNode->{Text};
+
+ if ( defined $text ) {
+ print CLASS "\n\n";
+
+ foreach $node ( @$text ) {
+ $type = $node->{NodeType};
+ $name = $node->{astNodeName};
+ warn "Node '", $name, "' has no type"
+ if !defined $type;
+
+ if( $lasttype eq "ListItem" && $type ne $lasttype ) {
+ print CLASS "\\end{itemize}\n";
+ }
+
+ if( $type eq "DocText" ) {
+ print CLASS "", deref( $name, $rootnode );
+ }
+ elsif ( $type eq "Pre" ) {
+# ??? verbatim'ów nie escapeujê. Ale mo¿e w ogóle u¿yæ tu listings
+ print CLASS "\n\\begin{verbatim}\n",
+ $name , "\n\\end{verbatim}\n";
+ }
+ elsif( $type eq "Ref" ) {
+ my $ref = $node->{Ref};
+ if ( defined $ref ) {
+ print "found reference for $name\n";
+ print CLASS refName( $ref );
+ }
+ else {
+ print CLASS $name;
+ }
+ }
+ elsif ( $type eq "ParaBreak" ) {
+ print CLASS "\n\n";
+ }
+ elsif ( $type eq "ListItem" ) {
+ if ( $lasttype ne "ListItem" ) {
+ print CLASS "\n\\begin{itemize}\n";
+ }
+ print CLASS "\\item ",
+ deref( $name, $rootnode ), "\n";
+ }
+
+ $lasttype = $type;
+ }
+
+ if( $type eq "ListItem" ) {
+ print CLASS "\n\\end{itemize}\n";
+ }
+
+ print CLASS "\n\n";
+
+ }
+
+
+ # Params
+ my @paramlist = ();
+ kdocAstUtil::findNodes( \@paramlist, $docNode->{Text},
+ "NodeType", "Param" );
+
+ if( $#paramlist >= 0 ) {
+ my $pnode;
+ print CLASS "\n\n\\textbf{Parametry}:\n\n",
+ "\\begin{longtable}{lp{8cm}}\n";
+
+ foreach $pnode ( @paramlist ) {
+ print CLASS
+ "\\emph{", esc($pnode->{Name}), '} & ',
+ deref($pnode->{astNodeName}, $rootnode ),
+ "\\\\\n";
+ }
+ print CLASS "\\end{longtable}\n";
+ }
+
+ # Return
+ printTextItem( $docNode, CLASS, "Returns", "Wynik" );
+
+ my @exception_list = ();
+ kdocAstUtil::findNodes( \@exception_list, $docNode->{Text},
+ "NodeType", "Throws" );
+ if( $#exception_list >= 0 ) {
+ my $pnode;
+ print CLASS "\n\n\\textbf{Wyj±tki}:\n",
+ "\\begin{longtable}{lp{8cm}}\n";
+
+ foreach $pnode ( @exception_list ) {
+ print CLASS
+ "\\emph{", esc($pnode->{Name}), '} & ',
+ deref($pnode->{astNodeName}, $rootnode ),
+ "\\\\\n";
+ }
+ print CLASS "\\end{longtable}\n";
+ }
+
+ # See
+ $text = $docNode->{See};
+ my $tref = $docNode->{SeeRef};
+
+ if ( defined $text ) {
+ my $comma = "\n\n\\textbf{Patrz te¿}: ";
+
+ foreach $ctr ( 0..$#{$text} ) {
+ if ( defined $tref->[ $ctr ] ) {
+ print CLASS $comma, refName( $tref->[ $ctr ] );
+ }
+ else {
+ print CLASS $comma, esc( $text->[ $ctr ] );
+ }
+
+ $comma = ", ";
+ }
+ print CLASS "\n\n";
+ }
+
+ return if $comp;
+
+ printTextItem( $docNode, CLASS, "Since", "Od" );
+ printTextItem( $docNode, CLASS, "Version", "Wersja" );
+ printTextItem( $docNode, CLASS, "Id" );
+ printTextItem( $docNode, CLASS, "Author", "Autor" );
+}
+
+=head3 printTextItem
+
+ Parameters: node, *filehandle, prop, label
+
+ If prop is set, it prints the label and the prop value deref()ed.
+
+=cut
+
+sub printTextItem
+{
+ local ( $node, *CLASS, $prop, $label ) = @_;
+ my $text = $node->{ $prop };
+
+ return unless defined $text;
+ $label = $prop unless defined $label;
+
+# print CLASS "\n\n\\textbf{", $label, "}: ", deref( $text, $rootnode ), "\n\n";
+# print CLASS "\n\n\\textbf{$label}:\n\n", deref( $text, $rootnode ), "\n\n";
+ my $txt = deref($text, $rootnode);
+ print CLASS <<EOF
+
+\\textbf{$label}:
+
+\\begin{longtable}{lp{10cm}}
+ & $txt \\\\
+\\end{longtable}
+EOF
+}
+
+sub textRef
+{
+ my ( $str, $rootnode ) = @_;
+ my $word;
+ my $out = "";
+
+ foreach $word ( split( /([^\w:]+)/, $str ) ) {
+ if ( $word =~ /^[^\w:]/ ) {
+ $out .= esc($word);
+ }
+ else {
+ $out .= wordRef( $word, $rootnode );
+ }
+ }
+
+ return $out;
+}
+
+=head3 wordRef
+
+ Parameters: word
+
+ Prints a hyperlink to the word's' reference if found, otherwise
+ just prints the word. Good for @refs etc.
+
+=cut
+
+sub wordRef
+{
+ my ( $str, $rootnode ) = @_;
+ confess "rootnode is undef" if !defined $rootnode;
+
+ return "" if $str eq "";
+
+ # MK --> chcê linkowaæ Ref'y i ConstRef'y
+# my $ref = kdocAstUtil::findRef( $rootnode, $str );
+ my $str2 = $str;
+ $str2 =~ s/(Const)?Ref$//;
+ my $ref = kdocAstUtil::findRef( $rootnode, $str2 );
+
+# ??? Powy¿sze nigdy siê nie znajdzie bo jeszcze nie robiê referencji. A
+# hashe zostaj±...
+ $str =~ s/^\#//;
+
+ return esc($str) if !defined $ref;
+
+ return hyper( $ref->{Ref}, esc($str) );
+}
+
+sub hyper
+{
+ confess "hyper: undefed parameter $_[0], $_[1]"
+# unless defined $_[0] && defined $_[1];
+ unless defined $_[1];
+# return "<A HREF=\"$_[0]\">".esc($_[1])."</A>";
+ my $result = esc($_[1]);
+# print "DIAG: hyper zwraca $result\n";
+ return $result;
+}
+
+
+1;
--- /dev/null
+package kdocDocHelper;
+
+use Carp;
+use Ast;
+use kdocAstUtil;
+use kdocUtil;
+
+use strict;
+use vars qw/ @undoc_class @undoc_func @no_short
+ $lib $rootnode $outputdir $opt /;
+
+=head1 kdocDocCheck
+
+ Check source files for documentation statistics.
+
+ Undocumented globals
+
+=cut
+
+BEGIN {
+ @undoc_class = ();
+ @undoc_func = ();
+ @no_short = ();
+}
+
+sub writeDoc
+{
+ ( $lib, $rootnode, $outputdir, $opt ) = @_;
+
+ foreach my $node ( @{$rootnode->{Kids}} ) {
+ next if defined $node->{ExtSource}
+ || defined $node->{Forward}
+ || $node->{NodeType} eq "Forward";
+
+ if ( !defined $node->{Compound} ) {
+ push @undoc_func, $node
+ unless defined $node->{DocNode};
+
+ next;
+ }
+
+ if ( !defined $node->{DocNode} ) {
+ push @undoc_class, $node;
+ }
+ elsif ( !defined $node->{DocNode}->{ClassShort} ) {
+ push @no_short, $node;
+ }
+ }
+
+ listOffenders( "Undocumented classes", \@undoc_class );
+ listOffenders( "No short description", \@no_short );
+ listOffenders( "Undocumented functions", \@undoc_func );
+}
+
+sub listOffenders
+{
+ my ( $reason, $list ) = @_;
+
+ return if $#{$list} < 0;
+
+ my $source = "";
+
+ print "$reason:\n";
+ foreach my $node (
+ sort { $a->{Source} cmp $b->{Source} } @{$list} ) {
+
+ my $newsource = kdocAstUtil::nodeSource( $node );
+ if ( $source ne $newsource ) {
+ print "\t", kdocAstUtil::nodeSource( $node ),":\n";
+ $source = $newsource;
+ }
+
+ print "\t\t(", $node->{NodeType}, ") ",
+ $node->{astNodeName}, "\n";
+ }
+}
+
+1;
--- /dev/null
+
+=head1 kdocHTMLutil - Common HTML routines.
+
+=cut
+
+package kdocHTMLutil;
+
+use kdocAstUtil;
+use Carp;
+use Iter;
+use strict;
+no strict qw/ subs/;
+
+use vars qw( $VERSION @ISA @EXPORT $rcount $docNode $rootnode $comp *CLASS );
+
+BEGIN {
+ $VERSION = '$Revision$';
+ @ISA = qw( Exporter );
+ @EXPORT = qw( makeReferences refName refNameFull refNameEvery hyper
+ esc printDoc printTextItem wordRef textRef deref
+ encodeURL newPgHeader tabRow makeHeader
+ HeaderPathToHTML writeTable makeSourceReferences B);
+
+ $rcount = 0;
+}
+
+## generic HTML generator routines
+
+sub newPgHeader
+{
+ my ( $html, $heading, $desc, $rest, $toclist ) = @_;
+ my $bw=0;
+ my $cspan = defined $main::options{"html-logo"} ? 2 : 1;
+
+ print $html <<EOF;
+<HTML>
+<HEAD>
+<TITLE>$heading</TITLE>
+<META NAME="Generator" CONTENT="KDOC $main::version">
+</HEAD>
+<BODY bgcolor="#ffffff" text="#000000" link="#0000ff" vlink="#000099" alink= "#ffffff">
+<TABLE WIDTH="100%" BORDER="$bw">
+<TR>
+<TD>
+ <TABLE BORDER="$bw">
+ <TR><TD valign="top" align="left" cellspacing="10">
+ <h1>$heading</h1>
+ </TD>
+ <TD valign="top" align="right" colspan="1">$desc</TD></TR>
+ </TABLE>
+ <HR>
+ <TABLE BORDER="$bw">
+ $rest
+ </TABLE>
+ </TD>
+EOF
+
+# print $html '<TABLE BORDER="',$bw,'"><TR><TD>';
+ my @klist = keys %$toclist;
+
+ print $html '<TD align="right"><TABLE BORDER="',$bw,'">';
+
+ # image
+ print $html '<TD rowspan="', ($#klist)+2,'"><IMG SRC="',
+ $main::options{"html-logo"},'"></TD>'
+ if defined $main::options{"html-logo"};
+
+ # TOC
+
+ foreach my $item ( sort @klist ) {
+ print $html '<TR><TD>',
+ '<small><A HREF="',$toclist->{$item},'">',
+ $item, "</small></TD></TR>\n";
+ }
+
+ print $html "</TABLE></TD></TR></TABLE>\n";
+
+}
+
+sub writeTable
+{
+ my ( $file, $list, $columns ) = @_;
+
+ my ( $ctr, $size ) = ( 0, int(($#$list+1)/$columns) );
+ $size = 1 if $size < 1;
+
+# spread out unallocated items across columns.
+# The old behaviour was to dump them in the last column.
+ my $s = $size * $columns;
+ $size++ if $s < ($#$list+1);
+
+ print $file '<TABLE WIDTH="100%" BORDER="0"><TR>';
+
+ while ( $ctr <= $#$list ) {
+ print $file '<TD VALIGN="top">';
+ $s = $ctr+$size-1;
+
+ if ( $s > $#$list ) {
+ $s = $#$list;
+ }
+ elsif ( ($#$list - $s) < $columns) {
+ $s = $#$list;
+ }
+
+ writeListPart( $file, $list, $ctr, $s );
+ print $file "</TD>";
+ $ctr = $s+1;
+ }
+
+ print $file '</TR></TABLE>';
+}
+
+=head3
+
+ Parameters: fd, list, start index, end index
+
+ Helper for writeClassList. Prints a table containing a
+ hyperlinked list of all nodes in the list from start index to
+ end index. A table header is also printed.
+
+=cut
+
+sub writeListPart
+{
+ my( $file, $list, $start, $stop ) = @_;
+
+ print $file "<TABLE BORDER=\"0\">";
+
+ print $file '<TR bgcolor="b0b0b0"><TH>',
+ esc( $list->[ $start ]->{astNodeName} ),
+ " - ", esc( $list->[ $stop ]->{astNodeName} ),
+ "</TH></TR>";
+
+ my $col = 0;
+ my $colour = "";
+
+ for my $ctr ( $start..$stop ) {
+ $col = $col ? 0 : 1;
+ $colour = $col ? "" : 'bgcolor="#eeeeee"';
+
+ print $file "<TR $colour><TD>", refNameFull( $list->[ $ctr ] ),
+ "</TD></TR>\n";
+ }
+
+ print $file "</TABLE>";
+}
+
+
+=head2 makeReferences
+
+ Parameters: rootnode
+
+ Recursively traverses the Kids of the root node, setting
+ the "Ref" property for each. This is the HTML reference for
+ the node.
+
+ A "NumRef" property is also set for non-compound members,
+ which is used for on-page links.
+
+=cut
+
+sub makeReferences
+{
+ my ( $rootnode ) = @_;
+
+ $rootnode->AddProp( "rcount", 0 );
+
+ return Iter::Tree ( $rootnode, 1,
+ sub { # common
+ my ( $root, $node ) = @_;
+
+ $root->{rcount}++;
+ $node->AddProp( 'NumRef', "#ref".$root->{rcount} );
+
+ return;
+ },
+ sub { # compound
+ my ( $root, $node ) = @_;
+ return if defined $node->{ExtSource};
+
+ my @heritage = kdocAstUtil::heritage( $node );
+
+ foreach my $n ( @heritage ) { $n = encodeURL( $n ); }
+ $node->AddProp( "Ref", join( "__", @heritage ). ".html" );
+
+ $node->AddProp( "rcount", 0 );
+
+ return;
+ },
+ sub { # member
+ my ( $root, $node ) = @_;
+ $node->AddProp( 'Ref', $root->{Ref}.
+ "#".encodeURL($node->{astNodeName}) )
+ unless defined $node->{ExtSource};
+
+ return;
+ }
+ );
+}
+
+sub makeSourceReferences
+{
+ my( $rootnode ) = shift;
+
+ return if !exists $rootnode->{Sources};
+
+ # Set up references
+
+ foreach my $header ( @{$rootnode->{Sources}} ) {
+ my $htmlname = HeaderPathToHTML( $header->{astNodeName} );
+ $header->AddProp( "Ref", $htmlname );
+ }
+
+
+}
+
+
+=head2 refName
+
+ Parameters: node, refprop?
+
+ Returns a hyperlinked name of the node if a reference exists,
+ or just returns the name otherwise. Useful for printing node names.
+
+ If refprop is specified, it is used as the reference property
+ instead of 'Ref'.
+
+=cut
+
+sub refName
+{
+ my ( $node ) = @_;
+ confess "refName called with undef" unless defined $node->{astNodeName};
+
+ my $ref = defined $_[1] ? $_[1] : 'Ref';
+
+ $ref = $node->{ $ref };
+
+ my $out;
+
+ if ( !defined $ref ) {
+ $out = $node->{astNodeName};
+ } else {
+ $out = hyper( encodeURL($ref), $node->{astNodeName} );
+ }
+
+ $out = "<i>".$out."</i>" if exists $node->{Pure};
+
+ return $out;
+
+}
+
+=head2 refNameFull
+
+ Parameters: node, rootnode, refprop?
+
+ Returns a hyperlinked, fully qualified (ie including parents)
+ name of the node if a reference exists, or just returns the name
+ otherwise. Useful for printing node names.
+
+ If refprop is specified, it is used as the reference property
+ instead of 'Ref'.
+
+=cut
+
+sub refNameFull
+{
+ my ( $node, $rootnode, $refprop ) = @_;
+
+ my $ref = defined $refprop ? $refprop : 'Ref';
+ $ref = $node->{ $ref };
+ my $name = join( "::", kdocAstUtil::heritage( $node ) );
+
+ my $out;
+
+ if ( !defined $ref ) {
+ $out = esc($name);
+ } else {
+ $out = hyper( encodeURL( $ref ), $name );
+ }
+
+ $out = "<i>".$out."</i>" if exists $node->{Pure};
+
+ return $out;
+}
+
+
+=head2 refNameEvery
+
+ Parameters: node
+
+ Like refNameFull, but every separate link in the chain is
+ referenced.
+
+=cut
+
+sub refNameEvery
+{
+ my ( $node, $rootnode ) = @_;
+
+
+
+ # make full name
+ my $name = $node->{astNodeName};
+
+ my $parent = $node->{Parent};
+
+ while ( $parent != $rootnode ) {
+ $name = refName($parent)."::".$name;
+ $parent = $parent->{Parent};
+ }
+
+ return $name;
+}
+
+=head2 hyper
+
+ Parameters: hyperlink, text
+
+ Returns an HTML hyperlink. The text is escaped.
+
+=cut
+
+sub hyper
+{
+ confess "hyper: undefed parameter $_[0], $_[1]"
+ unless defined $_[0] && defined $_[1];
+ return "<A HREF=\"$_[0]\">".esc($_[1])."</A>";
+}
+
+
+sub B
+{
+ my $tag = shift;
+
+ return "<$tag>". join( "", @_). "</$tag>";
+}
+
+=head2 esc
+
+ Escape special HTML characters.
+
+=cut
+
+sub esc
+{
+ my $str = $_[ 0 ];
+
+ return "" if !defined $str || $str eq "";
+
+ $str =~ s/&/&/g;
+ $str =~ s/</</g;
+ $str =~ s/>/>/g;
+
+ return $str;
+}
+
+
+=head2 printDoc
+
+ Parameters: docnode, *filehandle, rootnode, compound
+
+ Print a doc node. If compound is specified and non-zero, various
+ compound node properties are not printed.
+
+=cut
+
+sub printDoc
+{
+ my $docNode = shift;
+ local ( *CLASS, $rootnode ) = @_;
+ my ( $comp ) = @_;
+
+ my $type;
+ my $lasttype = "none";
+
+ $comp = defined $comp? $comp : 0;
+
+ if ( defined $docNode->{Main} ) {
+ print CLASS "<H2>",
+ deref( $docNode->{Main}, $rootnode ), "</H2>\n";
+ }
+
+ my $text = $docNode->{Text};
+
+ if ( defined $text ) {
+ print CLASS "<p>";
+
+ foreach my $node ( @$text ) {
+ $type = $node->{NodeType};
+ my $name = $node->{astNodeName};
+ warn "Node '", $name, "' has no type"
+ if !defined $type;
+
+ if( $lasttype eq "ListItem" && $type ne $lasttype ) {
+ print CLASS "</ul><p>\n";
+ }
+
+ if( $type eq "DocText" ) {
+ print CLASS "", deref( $name, $rootnode );
+ }
+ elsif ( $type eq "Pre" ) {
+ print CLASS "</p><pre>\n",
+ esc( $name ), "\n</pre><p>";
+ }
+ elsif( $type eq "Ref" ) {
+ my $ref = $node->{Ref};
+ if ( defined $ref ) {
+ print "found reference for $name\n";
+ print CLASS refName( $ref );
+ }
+ else {
+ print CLASS $name;
+ }
+ }
+ elsif ( $type eq "DocSection" ) {
+ print CLASS "</p><H3>",
+ deref( $name, $rootnode),"</H3><p>";
+ }
+ elsif ( $type eq "Image" ) {
+ print CLASS "</p><img url=\"",
+ $node->{Path}, "\"><p>";
+ }
+ elsif ( $type eq "ParaBreak" ) {
+ print CLASS "</p><p>";
+ }
+ elsif ( $type eq "ListItem" ) {
+ if ( $lasttype ne "ListItem" ) {
+ print CLASS "</p><ul>\n";
+ }
+ print CLASS "<li>",
+ deref( $name, $rootnode ), "</li>\n";
+ }
+
+ $lasttype = $type;
+ }
+
+ if( $type eq "ListItem" ) {
+ print CLASS "</ul><p>\n";
+ }
+
+ print CLASS "</p>";
+
+ }
+
+
+ # Params
+ my @paramlist = ();
+ kdocAstUtil::findNodes( \@paramlist, $docNode->{Text},
+ "NodeType", "Param" );
+
+ if( $#paramlist >= 0 ) {
+ my $pnode;
+ print CLASS "<p><b>Parameters</b>:",
+ "<TABLE BORDER=\"0\" CELLPADDING=\"5\">\n";
+
+ foreach $pnode ( @paramlist ) {
+ print CLASS "<TR><TD align=\"left\" valign=\"top\"><i>",
+ esc($pnode->{Name}),
+ "</i></TD><TD align=\"left\" valign=\"top\">",
+ deref($pnode->{astNodeName}, $rootnode ),
+ "</TD></TR>\n";
+ }
+ print CLASS "</TABLE></P>\n";
+ }
+
+ # Return
+ printTextItem( $docNode, *CLASS, "Returns" );
+
+ # Exceptions
+ $text = $docNode->{Throws};
+
+ if ( defined $text ) {
+ my $comma = "<p><b>Throws</b>: ";
+
+ foreach my $tosee ( @$text ) {
+ print CLASS $comma, esc( $tosee );
+ $comma = ", ";
+ }
+ print CLASS "</p>\n";
+ }
+
+ # See
+ my $comma = "";
+
+ Iter::SeeAlso ( $docNode, undef,
+ sub { # start
+ print CLASS "<p><b>See also</b>: ";
+ },
+ sub { # print
+ my ( $label, $ref ) = @_;
+ $label = defined $ref ? refName( $ref ): esc( $label );
+
+ print CLASS $comma, $label;
+ $comma = ", ";
+ },
+ sub { # end
+ print CLASS "</p>\n";
+ }
+ );
+
+ return if $comp;
+
+ printTextItem( $docNode, *CLASS, "Since" );
+ printTextItem( $docNode, *CLASS, "Version" );
+ printTextItem( $docNode, *CLASS, "Id" );
+ printTextItem( $docNode, *CLASS, "Author" );
+}
+
+=head3 printTextItem
+
+ Parameters: node, *filehandle, prop, label
+
+ If prop is set, it prints the label and the prop value deref()ed.
+
+=cut
+
+sub printTextItem
+{
+ my $node = shift;
+ local *CLASS = shift;
+ my ( $prop, $label ) = @_;
+
+ my $text = $node->{ $prop };
+
+ return unless defined $text;
+ $label = $prop unless defined $label;
+
+ print CLASS "<p><b>", $label, "</b>: ",
+ deref( $text, $rootnode ), "</p>\n";
+}
+
+
+=head3 wordRef
+
+ Parameters: word
+
+ Prints a hyperlink to the word's reference if found, otherwise
+ just prints the word. Good for @refs etc.
+
+=cut
+
+sub wordRef
+{
+ my ( $str, $rootnode ) = @_;
+ confess "rootnode is undef" if !defined $rootnode;
+
+ return "" if $str eq "";
+
+ my $ref = kdocAstUtil::findRef( $rootnode, $str );
+
+ return esc($str) if !defined $ref;
+
+ warn fullName( $ref ). " hasn't a reference." unless defined $ref->{Ref};
+
+ return hyper( $ref->{Ref}, $str ) unless !defined $ref->{Ref};
+}
+
+=head2 textRef
+
+ Parameters: string
+ Returns: hyperlinked, escaped text.
+
+ Tries to find a reference for EVERY WORD in the string, replacing it
+ with a hyperlink where possible. All non-hyper text is escaped.
+
+ Needless to say, this is quite SLOW.
+
+=cut
+
+sub textRef
+{
+ my ( $str, $rootnode ) = @_;
+ my $word;
+ my $out = "";
+
+ foreach $word ( split( /([^\w:]+)/, $str ) ) {
+ if ( $word =~ /^[^\w:]/ ) {
+ $out .= esc($word);
+ }
+ else {
+ $out .= wordRef( $word, $rootnode );
+ }
+ }
+
+ return $out;
+}
+
+=head2 deref
+
+ Parameters: text
+ returns text
+
+ dereferences all @refs in the text and returns it.
+
+=cut
+
+sub deref
+{
+ my ( $str, $rootnode ) = @_;
+ confess "rootnode is null" if !defined $rootnode;
+ my $out = "";
+ my $text;
+
+ foreach $text ( split (/(\@\w+\s+[\w:#]+)/, $str ) ) {
+ if ( $text =~ /\@ref\s+([\w:#]+)/ ) {
+ my $name = $1;
+ $name =~ s/^\s*#//g;
+ $out .= wordRef( $name, $rootnode );
+ }
+ elsif ( $text =~ /\@p\s+([\w:#]+)/ ) {
+ $out .= "<code>".esc($1)."</code>";
+ }
+ elsif ( $text =~/\@em\s+(\w+)/ ) { # emphasized
+ $out .= "<em>".esc($1)."</em>";
+ }
+ else {
+ $out .= esc($text);
+ }
+ }
+
+ return $out;
+}
+
+=head2 encodeURL
+
+ Parameters: url
+
+ Returns: encoded URL
+
+=cut
+
+sub encodeURL
+{
+ my $url = shift;
+ $url =~ s/:/%3A/g;
+ $url =~ s/</%3C/g;
+ $url =~ s/>/%3E/g;
+ $url =~ s/ /%20/g;
+ $url =~ s/%/%25/g;
+
+ return $url;
+}
+
+=head2 tabRow
+
+ Returns a table row with each element in the arg list as
+ one cell.
+
+=cut
+
+sub tabRow
+{
+ return "<TR><TH>$_[0]</TH><TD>$_[1]</TD></TR>\n";
+}
+
+=head2 makeHeader
+
+ Writes an HTML version of a file.
+
+=cut
+
+sub makeHeader
+{
+ my ( $out, $filename ) = @_;
+
+ open ( SOURCE, "$filename" ) || die "Couldn't read $filename\n";
+
+ print $out "<pre>\n";
+
+ while ( <SOURCE> ) {
+ print $out esc( $_ );
+ }
+
+ print $out "</pre>\n";
+}
+
+=head2 HeaderPathToHTML
+
+ Takes the path to a header file and returns an html file name.
+
+=cut
+
+sub HeaderPathToHTML
+{
+ my ( $path ) = @_;
+
+ $path =~ s/_/__/g;
+ $path =~ s/\//___/g;
+ $path =~ s/\./_/g;
+ $path =~ s/:/____/g;
+
+ return $path.".html";
+}
+
+# for printing debug node.
+
+sub fullName
+{
+ return join( "::", kdocAstUtil::heritage( shift ) );
+}
+
+1;
--- /dev/null
+package kdocIDLhtml;
+
+use File::Path;
+use File::Basename;
+
+use Carp;
+use Ast;
+use kdocAstUtil;
+use kdocHTMLutil;
+
+=head1 kdocIDLhtml
+
+Generate HTML docs for an IDL syntax tree.
+
+=cut
+
+BEGIN
+{
+ @clist = ();
+
+ # Host information
+
+ if ( $^O eq "MsWin32" ) {
+ # Windows
+ $host=$ENV{COMPUTERNAME};
+ $who = $ENV{USERNAME};
+ }
+ else {
+ # Unix
+ $host = `uname -n`; chop $host;
+ $who = `whoami`; chop $who;
+ }
+
+ $now = localtime;
+ $gentext = "$who\@$host on $now, using kdoc $main::Version.";
+
+ # bottom of every page
+ $docBotty =<<EOF;
+<HR>
+ <table>
+ <tr><td><small>Generated by: $gentext</small></td></tr>
+ </table>
+</BODY>
+</HTML>
+EOF
+
+ # used to convert node types to headings
+
+ %typedesc = (
+ 'enum' => 'Enumerations',
+ 'exception' => 'Exceptions',
+ 'interface' => 'Interfaces',
+ 'method' => 'Methods',
+ 'struct' => 'Structures',
+ 'typedef' => 'Types',
+ 'var' => 'Constants'
+ );
+}
+
+sub writeDoc
+{
+ ( $lib, $rootnode, $outputdir, $opt ) = @_;
+
+ $debug = $main::debug;
+ @docQueue = ();
+
+ print "Generating HTML documentation. \n" unless $main::quiet;
+
+ mkpath( $outputdir ) unless -f $outputdir;
+
+ makeReferences( $rootnode );
+ makeModuleList( $rootnode );
+
+ writeModList( $rootnode );
+ writeAnnotatedList( $rootnode );
+ writeHeaderList();
+
+ my $node;
+
+ foreach $node ( @{$rootnode->{Kids}} ) {
+ next if !defined $node->{Compound}
+ || defined $node->{ExtSource};
+ print "list: Queueing $node->{astNodeName} for doc\n"
+ if $debug;
+ push @docQueue, $node;
+ }
+
+ while( $#docQueue >= 0 ) {
+ $node = pop @docQueue;
+ print "Dequeueing $node->{astNodeName} for doc\n"
+ if $debug;
+ writeCompoundDoc( $node );
+ }
+}
+
+=head2 writeAnnotatedList
+
+ Parameters: rootnode
+
+ Writes out a list of classes with short descriptions to
+ index-long.html.
+
+=cut
+
+sub writeAnnotatedList
+{
+ my ( $root ) = @_;
+ my $short;
+
+ open(CLIST, ">$outputdir/index-long.html")
+ || die "Couldn't create $outputdir/index-long.html: $?\n";
+
+ print CLIST pageHeader( $lib." Annotated List" ),
+ "<TABLE WIDTH=\"100%\" BORDER=\"0\">\n";
+
+ foreach my $node ( @clist ) {
+ confess "undef in clist\n" if !defined $node;
+
+ $docnode = $node->{DocNode};
+ $short = "";
+
+ if( defined $docnode && exists $docnode->{ClassShort} ) {
+ $short = deref($docnode->{ClassShort}, $rootnode );
+ if( !defined $short ) {
+ print $root->{astNodeName}, "has undef short\n";
+ next;
+ }
+
+ }
+
+ print CLIST "<TR><TD>", refName( $node ),
+ "</TD><TD>", $short, "</TD></TR>";
+ }
+
+ print CLIST "</TABLE>", $docBotty;
+ close CLIST;
+}
+
+=head2 writeModList
+
+ Parameters: rootnode
+
+ Writes out a concise list of classes to index.html
+
+=cut
+
+sub writeModList
+{
+ my ( $root ) = @_;
+
+ open(CLIST, ">$outputdir/index.html")
+ || die "Couldn't create $outputdir/index.html: $?\n";
+
+ print CLIST pageHeader( $lib." Module Index" ),
+ "<TABLE WIDTH=\"100%\" BORDER=\"0\">\n";
+
+ my $cols = exists $opt->{"html-cols"} ? $opt->{"html-cols"} : 3;
+ my ( $ctr, $size ) = ( 0, int(($#clist+1)/$cols) );
+ $size = 1 if $size < 1;
+
+ print CLIST "<TR>";
+ my $s;
+
+ while ( $ctr <= $#clist ) {
+ print CLIST "<TD>";
+ $s = $ctr+$size-1;
+
+ if ( $s > $#clist ) {
+ $s = $#clist;
+ }
+ elsif ( ($#clist - $s) < $cols) {
+ $s = $#clist;
+ }
+
+ print "Writing from $ctr to ",$ctr+$size-1,"\n" if $debug;
+ writeListPart( \@clist, $ctr, $s );
+ print CLIST "</TD>";
+ $ctr = $s+1;
+ }
+
+ print CLIST<<EOF;
+</TR>
+</TABLE>
+$docBotty
+EOF
+ close CLIST;
+}
+
+=head3
+
+ Parameters: list, start index, end index
+
+ Helper for writeModList. Prints a table containing a hyperlinked
+ list of all nodes in the list from start index to end index. A
+ table header is also printed.
+
+=cut
+
+sub writeListPart
+{
+ my( $list, $start, $stop ) = @_;
+
+ print CLIST "<TABLE BORDER=\"0\">";
+
+ print CLIST "<TR><TH>",
+ esc( $list->[ $start ]->{astNodeName} ),
+ " - ", esc( $list->[ $stop ]->{astNodeName} ),
+ "</TH></TR>";
+
+ for $ctr ( $start..$stop ) {
+ print CLIST "<TR><TD>", refName( $list->[ $ctr ] ),
+ "</TD></TR>\n";
+ }
+
+ print CLIST "</TABLE>";
+}
+
+
+=head2 writeAllMembers
+
+ Parameters: node
+
+ Writes a list of all methods to "full-list-<class file>"
+
+=cut
+
+sub writeAllMembers
+{
+ my( $node ) = @_;
+ my $file = "$outputdir/full-list-".$node->{Ref};
+ my %allmem = ();
+
+ kdocAstUtil::allMembers( \%allmem, $node );
+
+ open( ALLMEM, ">$file" ) || die "Couldn't create $file: $?\n";
+
+ print ALLMEM pageHeader( esc($node->{astNodeName})." - All Methods" ),
+ "<UL>";
+
+ my $mem;
+ foreach $mem ( sort keys %allmem ) {
+ print ALLMEM "<LI>", refName( $allmem{ $mem } ), "</LI>\n";
+ }
+
+ print ALLMEM "</UL>$docBotty";
+
+ close ALLMEM;
+}
+
+=head2 writeHeaderList
+
+ Generates the header-list.html file, which contains links
+ to each processed header. The ARGV list is used.
+
+=cut
+
+sub writeHeaderList
+{
+ open(HDRIDX, ">$outputdir/header-list.html")
+ || die "Couldn't create $outputdir/header-list.html: $?\n";
+
+ print HDRIDX pageHeader( $lib." File Index" ), "<UL>\n";
+
+ foreach $header ( sort @main::ARGV ) {
+ $_ = $header;
+ $header = basename ( $_ ) if $main::striphpath;
+# convert dashes to double dash, convert path to dash
+ s/-/--g/g;
+ s/\/|\./-/g;
+
+ print HDRIDX "\t<LI>",hyper($_.".html",$header),"</LI>\n";
+ }
+
+print HDRIDX "</UL>\n",$docBotty;
+
+}
+
+=head2 pageHeader
+
+ Parameters: heading, description
+
+ Returns a string containing an HTML page heading.
+
+=cut
+
+sub pageHeader
+{
+ my( $heading, $desc ) = @_;
+
+ $desc = "" if !defined $desc;
+
+ my $libtext = "";
+ if( $lib ne "" ) {
+ $libtext = "<TR><TD><small>$lib documentation</small>".
+ "</TD></TR>";
+ }
+
+ return <<EOF;
+<HTML><HEAD>
+<TITLE>$heading</TITLE>
+<META NAME="Generator" CONTENT="KDOC $main::Version">
+</HEAD>
+<BODY bgcolor="#ffffff" text="#000000" link="#0000ff" vlink="#000099" alink= "#ffffff">
+<TABLE WIDTH="100%" BORDER="0">
+<TD VALIGN="top" align="left">
+<TABLE BORDER="0"><TR>
+$libtext
+<TR><TD><small><A HREF="index.html">Index</small></TD></TR>
+<TR><TD><small><A HREF="index-long.html">Annotated List</small></TD></TR>
+<TR><TD><small><A HREF="header-list.html">Files</A></small></TD></TR>
+</TABLE>
+</TD>
+
+<TD VALIGN="top" align="right"><H1>$heading</H1><p>$desc</p></TD>
+</TR></TABLE>
+<HR>
+EOF
+
+}
+
+=head2 writeCompoundDoc
+
+ Parameters: $node
+
+ Write documentation for one compound node.
+
+=cut
+
+sub writeCompoundDoc
+{
+ my( $node ) = @_;
+ if( exists $node->{ExtSource} ) {
+ warn "Trying to write doc for ".$node->{AstNodeName}.
+ " from ".$node->{ExtSource}."\n";
+ return;
+ }
+
+ my $file = "$outputdir/".$node->{Ref};
+ my $docnode = $node->{DocNode};
+ my $hasdoc = exists $node->{DocNode} ? 1 : 0;
+ my @list = ();
+ my $version = undef;
+ my $author = undef;
+
+ open( CLASS, ">$file" ) || die "Couldn't create $file: $?\n";
+
+ # Header
+
+ my $source = kdocAstUtil::nodeSource( $node );
+ my $short = "";
+
+ if( $hasdoc ) {
+ if ( exists $docnode->{ClassShort} ) {
+ $short .= deref($docnode->{ClassShort}, $rootnode );
+ }
+
+ if ( exists $docnode->{Deprecated} ) {
+ $short .= "</p><p><b>Deprecated: use with care</b>";
+ }
+
+ if ( exists $docnode->{Internal} ) {
+ $short .= "</p><p><b>Internal use only</b>";
+ }
+ $version = esc($docnode->{Version})
+ if exists $docnode->{Version};
+ $author = esc($docnode->{Author})
+ if exists $docnode->{Author};
+ }
+
+ # check for pure abstract
+ if ( exists $node->{Pure} ) {
+ $short .=
+ "</p><p><b>Contains pure virtuals</b></p><p>";
+ }
+
+ # full name
+ $short .= "</p><p><code>".refNameEvery( $node, $rootnode )."</code><p>"
+ unless $node->{Parent} eq $rootnode;
+
+ # include
+ $short .= "</p><p><code>#include <".$source
+ ."></code></p><p>";
+
+ # inheritance
+ if ( $node != $rootnode && exists $node->{InList} ) {
+ my $comma = "Inherits: ";
+
+ # FIXME: bad hack to get rid of duplicates.
+ my $last = undef;
+ my $out = "";
+
+ foreach my $in ( sort{ $a->{astNodeName} cmp $b->{astNodeName}}
+ @{$node->{InList}} ) {
+ next if $in == $last;
+
+ my $n = $in->{Node};
+ if( defined $n ) {
+ next if $n eq $rootnode;
+ $out .= $comma.refNameFull( $n, $rootnode );
+ if ( exists $n->{ExtSource} ) {
+ $out .= " <small>(".$n->{ExtSource}
+ .")</small>";
+ }
+ }
+ else {
+ $out .= esc( $in->{astNodeName} );
+ }
+
+ $comma = ", ";
+ $last = $in;
+ }
+
+ $short .= "$out</p><p>" unless $out eq "";
+ }
+
+ if ( $node != $rootnode && exists $node->{InBy} ) {
+ my $comma .= "Inherited by: ";
+
+ @list = ();
+ kdocAstUtil::inheritedBy( \@list, $node );
+
+ # FIXME: bad hack to get rid of duplicates.
+ my $last = 1;
+
+ foreach $in ( sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @list ) {
+ $short .= $comma.refNameFull( $in, $rootnode );
+ if ( exists $in->{ExtSource} ) {
+ $short .= " <small>(".
+ $in->{ExtSource}.")</small>";
+ }
+
+ $comma = ", ";
+ }
+ $short .= "</p><p>";
+ }
+
+ $short .= "<small>".hyper( "#longdesc", "More..." )."</small>";
+
+ # print it
+
+ print CLASS pageHeader(
+ $node->{NodeType}." ".esc($node->{astNodeName}),
+ $short );
+
+
+ # member list
+
+ print CLASS "<p>", hyper( encodeURL("full-list-".$node->{Ref}),
+ "List of all Methods" ),"</p>\n";
+
+ if ( exists $node->{Kids} ) {
+ foreach my $type ( kdocAstUtil::allTypes( $node->{Kids} ) ) {
+ @list = ();
+ kdocAstUtil::findNodes( \@list, $node->{Kids},
+ "NodeType", $type );
+
+ listMembers( $node, exists $typedesc{$type}
+ ? $typedesc{$type} : $type, \@list );
+ }
+
+ }
+ else {
+ print CLASS "<center><H4>No members</H4></center>\n";
+ return;
+ }
+
+ # long description
+ if ( $hasdoc ) {
+ print CLASS "<HR><A NAME=\"longdesc\">",
+ "<H2>Detailed Description</H2>";
+ printDoc( $docnode, *CLASS, $rootnode, 1 );
+ }
+
+ # member doc
+ my $kid;
+ my ($numref, $ref);
+
+ foreach $kid ( @{$node->{Kids}} ) {
+ next if defined $kid->{ExtSource}
+ || (!$main::doPrivate &&
+ $kid->{Access} =~ /private/);
+
+ if( exists $kid->{Compound} ) {
+ print "idl: Queueing $kid->{astNodeName} for doc\n"
+ if $debug;
+ push @docQueue, $kid;
+ }
+
+ # we check this after checking if the node is compound,
+ # so it is queued for c.doc even if it doesn't have explicit
+ # documentation.
+ next if !defined $kid->{DocNode};
+
+ if( !exists $kid->{NumRef} ) {
+ warn $kid->{astNodeName}, " type ",
+ $kid->{NodeType}, " doesn't have a numref\n";
+ }
+
+ ( $numref = $kid->{NumRef} ) =~ s/^.*?#//g;
+ ( $ref = $kid->{Ref} ) =~ s/^.*?#//g;
+
+ printMemberName( $kid, $ref, $numref );
+ printDoc( $kid->{DocNode}, *CLASS, $rootnode );
+
+ if ( $kid->{NodeType} eq "method" ) {
+ $ref = kdocAstUtil::findOverride( $rootnode, $node,
+ $kid->{astNodeName} );
+ if ( defined $ref ) {
+ print CLASS "<p>Reimplemented from ",
+ refNameFull( $ref, $rootnode ), "</p>\n";
+ }
+ }
+ }
+
+ # done
+
+ if ( defined $version || defined $author ) {
+ print CLASS "<HR><UL>",
+ defined $version ?
+ "<LI><i>Version</i>: $version</LI>" : "",
+ defined $author ?
+ "<LI><i>Author</i>: $author</LI>" : "",
+ "<LI><i>Generated</i>: $gentext</LI></UL>",
+ "</BODY></HTML>\n";
+ }
+ else {
+ print CLASS $docBotty;
+ }
+
+ close CLASS;
+
+ # full member list
+
+ writeAllMembers( $node );
+}
+
+
+
+
+=head2 listMembers
+
+ Parameters: compound node, description, node list ref?
+
+=cut
+
+sub listMembers
+{
+ my( $class, $desc, $nodelist ) = @_;
+ my $name;
+ my $type;
+ my $flags;
+
+
+ my $nodes = defined $nodelist ? $nodelist : $class->{Kids};
+
+ if ( $#{$nodes} < 0 ) {
+ print CLASS "<center><H4>No members</H4></center>\n";
+ return;
+ }
+
+print CLASS<<EOF;
+<H2>$desc</H2>
+<UL>
+EOF
+ foreach $m ( @{$nodes} ) {
+ next if exists $m->{ExtSource};
+ if( exists $m->{Compound} ) {
+ # compound docs not printed for rootnode
+ next if $class eq $rootnode;
+
+ $name = refName( $m );
+ }
+ elsif( exists $m->{DocNode} ) {
+ # compound nodes have their own page
+ $name = refName( $m, 'NumRef' );
+ } else {
+ $name = esc( $m->{astNodeName} );
+ }
+
+ $type = $m->{NodeType};
+
+ print CLASS "<LI>";
+
+ if( $type eq "var" ) {
+ print CLASS esc( $m->{Type}),
+ " <b>", $name,"</b>\n";
+ }
+ elsif( $type eq "method" ) {
+ $flags = $m->{Flags};
+
+ if ( !defined $flags ) {
+ warn "Method ".$m->{astNodeName}.
+ " has no flags\n";
+ }
+
+ $name = "<i>$name</i>" if $flags =~ /p/;
+ my $extra = "";
+ $extra .= "virtual " if $flags =~ "v";
+ $extra .= "static " if $flags =~ "s";
+
+ print CLASS $extra, esc($m->{ReturnType}),
+ " <b>", $name, "</b> (",
+ esc($m->{Params}), ") ",
+ $flags =~ /c/ ? " const\n": "\n";
+ }
+ elsif( $type eq "enum" ) {
+ print CLASS "enum <b>", $name, "</b> {",
+ esc($m->{Params}),"}\n";
+ }
+ elsif( $type eq "typedef" ) {
+ print CLASS "typedef ",
+ esc($m->{Type}), " <b>",
+ $name,"</b>";
+ }
+ else {
+ # unknown type
+ print CLASS esc($type), " <b>",
+ $name,"</b>\n";
+ }
+
+ print CLASS "</LI>\n";
+ }
+
+print CLASS<<EOF;
+</UL>
+EOF
+
+}
+
+=head2 printMemberName
+
+ Parameters: member node, names...
+
+ Prints the name of one member, customized to type. If names are
+ specified, a name anchor is written for each one.
+
+=cut
+
+sub printMemberName
+{
+ my $m = shift;
+
+ my $name = esc( $m->{astNodeName} );
+ my $type = $m->{NodeType};
+ my $ref;
+ my $flags = undef;
+
+ foreach $ref ( @_ ) {
+ print CLASS "<A NAME=", $ref, "></A>";
+ }
+
+ print CLASS "<HR><p><strong>";
+
+ if( $type eq "var" ) {
+ print CLASS textRef($m->{Type}, $rootnode ),
+ " <b>", $name,"</b>\n";
+ }
+ elsif( $type eq "method" ) {
+ $flags = $m->{Flags};
+ $name = "<i>$name</i>" if $flags =~ /p/;
+
+ print CLASS textRef($m->{ReturnType}, $rootnode ),
+ " <b>", $name, "</b> (",
+ textRef($m->{Params}, $rootnode ), ")\n";
+ }
+ elsif( $type eq "enum" ) {
+ print CLASS "enum <b>", $name, "</b> {",
+ esc($m->{Params}),"}\n";
+ }
+ elsif( $type eq "typedef" ) {
+ print CLASS "typedef ",
+ textRef($m->{Type}, $rootnode ), " <b>",
+ $name,"</b>";
+ }
+ else {
+ print CLASS $name, " <small>(",
+ esc($type), ")</small>";
+ }
+
+ print CLASS "</strong>";
+
+# extra attributes
+ my @extra = ();
+
+ if( !exists $m->{Access} ) {
+ print "Member without access:\n";
+ kdocAstUtil::dumpAst( $m );
+ }
+
+ ($ref = $m->{Access}) =~ s/_slots//g;
+
+ push @extra, $ref
+ unless $ref =~ /public/
+ || $ref =~ /signal/;
+
+ if ( defined $flags ) {
+ my $f;
+ my $n;
+ foreach $f ( split( "", $flags ) ) {
+ $n = $main::flagnames{ $f };
+ warn "flag $f has no long name.\n" if !defined $n;
+ push @extra, $n;
+ }
+ }
+
+ if ( $#extra >= 0 ) {
+ print CLASS " <small>[", join( " ", @extra ), "]</small>";
+ }
+
+ print CLASS "</p>";
+
+# finis
+}
+
+
+
+=head2 makeModuleList
+
+ Parameters: node
+
+ fills global @clist with a list of all direct, non-external
+ compound children of node.
+
+=cut
+
+sub makeModuleList
+{
+ my ( $rootnode ) = @_;
+
+ @clist = ();
+
+ foreach my $node ( @{$rootnode->{Kids}} ) {
+ confess "undefined child in rootnode" unless defined $node;
+
+ push @clist, $node unless (exists $node->{ExtSource}
+ || !exists $node->{Compound});
+
+ }
+
+ @clist = sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @clist;
+}
+
+1;
--- /dev/null
+
+=head1 kdocLib
+
+Writes out a library file.
+
+NOTES ON THE NEW FORMAT
+
+ Stores: class name, members, hierarchy
+ node types are not stored
+
+
+ File Format Spec
+ ----------------
+
+ header
+ zero or more members, each of
+ method
+ member
+ class, each of
+ inheritance
+ zero or more members
+
+
+
+ Unrecognized lines ignored.
+
+ Sample
+ ------
+
+ <! KDOC Library HTML Reference File>
+ <VERSION="2.0">
+ <BASE URL="http://www.kde.org/API/kdecore/">
+
+ <C NAME="KApplication" REF="KApplication.html">
+ <IN NAME="QObject">
+ <ME NAME="getConfig" REF="KApplication.html#getConfig">
+ <M NAME="" REF="">
+ </C>
+
+=cut
+
+package kdocLib;
+use strict;
+
+use Carp;
+use File::Path;
+use File::Basename;
+
+use Ast;
+use kdocAstUtil;
+use kdocUtil;
+
+
+use vars qw/ $exe $lib $root $plang $outputdir $docpath $url $compress /;
+
+BEGIN {
+ $exe = basename $0;
+}
+
+sub writeDoc
+{
+ ( $lib, $root, $plang, $outputdir, $docpath, $url,
+ $compress ) = @_;
+ my $outfile = "$outputdir/$lib.kdoc";
+ $url = $docpath unless defined $url;
+
+ mkpath( $outputdir ) unless -f $outputdir;
+
+ if( $compress ) {
+ open( LIB, "| gzip -9 > \"$outfile.gz\"" )
+ || die "$exe: couldn't write to $outfile.gz\n";
+
+ }
+ else {
+ open( LIB, ">$outfile" )
+ || die "$exe: couldn't write to $outfile\n";
+ }
+
+ my $libdesc = "";
+ if ( defined $root->{LibDoc} ) {
+ $libdesc="<LIBDESC>".$root->{LibDoc}->{astNodeName}."</LIBDESC>";
+ }
+
+ print LIB<<LTEXT;
+<! KDOC Library HTML Reference File>
+<VERSION="$main::Version">
+<BASE URL="$url">
+<PLANG="$plang">
+<LIBNAME>$lib</LIBNAME>
+$libdesc
+
+LTEXT
+
+ writeNode( $root, "" );
+ close LIB;
+}
+
+sub writeNode
+{
+ my ( $n, $prefix ) = @_;
+ return if !exists $n->{Compound};
+ return if exists $n->{Forward} && !exists $n->{KidAccess};
+
+ if( $n != $root ) {
+ $prefix .= $n->{astNodeName};
+ print LIB "<C NAME=\"", $n->{astNodeName},
+ "\" REF=\"$prefix.html\">\n";
+ }
+ else {
+ print LIB "<STATS>\n";
+ my $stats = $root->{Stats};
+ foreach my $stat ( keys %$stats ) {
+ print LIB "<STAT NAME=\"$stat\">",
+ $stats->{$stat},"</STAT>\n";
+ }
+ print LIB "</STATS>\n";
+ }
+
+ if( exists $n->{Ancestors} ) {
+ my $in;
+ foreach $in ( @{$n->{Ancestors}} ) {
+ $in =~ s/\s+//g;
+ print LIB "<IN NAME=\"",$in,"\">\n";
+ }
+ }
+
+ return if !exists $n->{Kids};
+ my $kid;
+ my $type;
+
+ foreach $kid ( @{$n->{Kids}} ) {
+ next if exists $kid->{ExtSource}
+ || $kid->{Access} eq "private";
+
+ if ( exists $kid->{Compound} ) {
+ if( $n != $root ) {
+ writeNode( $kid, $prefix."::" );
+ }
+ else {
+ writeNode( $kid, "" );
+ }
+ next;
+ }
+
+ $type = $kid->{NodeType} eq "method" ?
+ "ME" : "M";
+
+ print LIB "<$type NAME=\"", $kid->{astNodeName},
+ "\" REF=\"$prefix.html#", $kid->{astNodeName}, "\">\n";
+ }
+
+ if( $n != $root ) {
+ print LIB "</C>\n";
+ }
+}
+
+sub readLibrary
+{
+ my( $rootsub, $name, $path, $relurl ) = @_;
+ $path = "." unless defined $path;
+ my $real = $path."/".$name.".kdoc";
+ my $url = ".";
+ my @stack = ();
+ my $version = "2.0";
+ my $new;
+ my $root = undef;
+ my $n = undef;
+ my $havecomp = -r "$real.gz";
+ my $haveuncomp = -r "$real";
+
+ if ( $haveuncomp ) {
+ open( LIB, "$real" ) || die "Can't read lib $real\n";
+ }
+
+ if( $havecomp ) {
+ if ( $haveuncomp ) {
+ warn "$exe: two libs exist: $real and $real.gz. "
+ ."Using $real\n";
+ }
+ else {
+ open( LIB, "gunzip < \"$real.gz\"|" )
+ || die "Can't read pipe gunzip < \"$real.gz\": $?\n";
+ }
+ }
+
+ while( <LIB> ) {
+ next if /^\s*$/;
+ if ( !/^\s*</ ) {
+ close LIB;
+ readOldLibrary( $root, $name, $path );
+ return;
+ }
+
+ if( /<VER\w+\s+([\d\.]+)>/ ) {
+ # TODO: what do we do with the version number?
+ $version = $1;
+ }
+ elsif ( /<BASE\s*URL\s*=\s*"(.*?)"/ ) {
+ $url = $1;
+ $url .= "/" unless $url =~ m:/$:;
+
+ my $test = kdocUtil::makeRelativePath( $relurl, $url );
+ $url = $test;
+ }
+ elsif( /<PLANG\s*=\s*"(.*?)">/ ) {
+ $root = $rootsub->( $1 );
+ $n = $root;
+ }
+ elsif ( /<C\s*NAME="(.*?)"\s*REF="(.*?)"\s*>/ ) {
+ # class
+ $new = Ast::New( $1 );
+ $new->AddProp( "NodeType", "class" );
+ $new->AddProp( "Compound", 1 );
+ $new->AddProp( "ExtSource", $name );
+
+ # already escaped at this point!
+ $new->AddProp( "Ref", $url.$2 );
+
+ $root = $n = $rootsub->( "CXX" ) unless defined $root;
+ kdocAstUtil::attachChild( $n, $new );
+ push @stack, $n;
+ $n = $new;
+ }
+ elsif ( m#<IN\s*NAME\s*=\s*"(.*?)"\s*># ) {
+ # ancestor
+ kdocAstUtil::newInherit( $n, $1 );
+ }
+ elsif ( m#</C># ) {
+ # end class
+ $n = pop @stack;
+ }
+ elsif ( m#<(M\w*)\s+NAME="(.*?)"\s+REF="(.*?)"\s*># ) {
+ # member
+ $new = Ast::New( $2 );
+ $new->AddProp( "NodeType", $1 eq "ME" ? "method" : "var" );
+ $new->AddProp( "ExtSource", $name );
+ $new->AddProp( "Flags", "" );
+ $new->AddProp( "Ref", $url.$3 );
+
+ kdocAstUtil::attachChild( $n, $new );
+ }
+ }
+}
+
+=head2 readLibrary
+
+ Parameters: rootnode, libname.
+
+ Read a kdoc 1.0 library into the node tree. Each external class
+ will have its "ExtSource" property set to the library name.
+
+=cut
+
+sub readOldLibrary
+{
+ my ( $root, $libname, $libdir ) = @_;
+
+ my @nodeStack = ();
+ my $cnode = $root;
+ my $fullpath = $libdir."/".$libname.".kdoc";
+ my $liburl = "";
+ my $newNode;
+ my $newMem;
+
+ open( LIB, $fullpath) || die "$exe: Can't read library $fullpath\n";
+
+ $liburl = <LIB>;
+ carp "Empty libfile: $fullpath\n" if !defined $liburl;
+ $liburl =~ s/\s+//g;
+
+ while( <LIB> ) {
+ # class url
+ next if !/^([^=]+)=/;
+ my $src = $1;
+ my $target = $';
+ if ( $src =~ /::/ ) {
+ # member
+ next if !defined $newNode
+ || $newNode->{astNodeName} ne $src;
+ $newMem = Ast::New( $' );
+ $newMem->AddProp( "NodeType", "Anon" );
+ $newMem->AddProp( "Ref", $liburl."/".$target );
+ kdocAstUtil::attachChild( $newNode, $newMem );
+ }
+ else {
+ # class
+ $src =~ s/^\s*(.*?)\s*$/$1/g;
+ $newNode = Ast::New( $src );
+ $newNode->AddProp( "NodeType", "class" );
+ $newNode->AddProp( "ExtSource", $libname );
+ $newNode->AddProp( "Compound", 1 );
+ $newNode->AddProp( "KidAccess", "public" );
+ $newNode->AddProp( "Ref", $liburl."/".$target );
+ kdocAstUtil::attachChild( $root, $newNode );
+ }
+ }
+
+ close( LIB );
+}
+
+1;
--- /dev/null
+package kdocParseDoc;
+
+use Ast;
+use strict;
+
+use vars qw/ $buffer $docNode %extraprops $currentProp $propType /;
+
+=head1 kdocParseDoc
+
+ Routines for parsing of javadoc comments.
+
+=head2 newDocComment
+
+ Parameters: begin (starting line of declaration)
+
+ Reads a doc comment to the end and creates a new doc node.
+
+ Read a line
+ check if it changes the current context
+ yes
+ flush old context
+ check if it is a non-text tag
+ (ie internal/deprecated etc)
+ yes
+ reset context to text
+ set associated property
+ no
+ set the new context
+ assign text to new buffer
+ no add to text buffer
+ continue
+ at end
+ flush anything pending.
+
+=cut
+
+sub newDocComment
+{
+ my( $text ) = @_;
+ return undef unless $text =~ m#/\*\*+#;
+
+ setType( "DocText", 2 );
+ $buffer = $';
+ $docNode = undef;
+ %extraprops = (); # used for textprops when flushing.
+ my $finished = 0;
+ my $inbounded = 0;
+
+ if ( $buffer =~ m#\*/# ) {
+ $buffer = $`;
+ $finished = 1;
+ }
+
+PARSELOOP:
+ while ( defined $text && !$finished ) {
+ # read text and remove leading junk
+ $text = main::readSourceLine();
+ next if !defined $text;
+ $text =~ s#^\s*\*(?!\/)##;
+
+ if ( $text =~ /^\s*<\/pre>/i ) {
+ flushProp();
+ $inbounded = 0;
+ }
+ elsif( $inbounded ) {
+ if ( $text =~ m#\*/# ) {
+ $finished = 1;
+ $text = $`;
+ }
+ $buffer .= $text;
+ next PARSELOOP;
+ }
+ elsif ( $text =~ /^\s*<pre>/i ) {
+ textProp( "Pre" );
+ $inbounded = 1;
+ }
+ elsif ( $text =~ /^\s*$/ ) {
+ textProp( "ParaBreak", "\n" );
+ }
+ elsif ( $text =~ /^\s*\@internal\s*/ ) {
+ codeProp( "Internal", 1 );
+ }
+ elsif ( $text =~ /^\s*\@deprecated\s*/ ) {
+ codeProp( "Deprecated", 1 );
+ }
+ elsif ( $text =~ /^\s*\@group\s*/ ) {
+ # logical group tag in which this node belongs
+ # multiples allowed
+
+ my $groups = $';
+ $groups =~ s/^\s*(.*?)\s*$/$1/;
+
+ if ( $groups ne "" ) {
+ foreach my $g ( split( /[^_\w]+/, $groups) ) {
+
+ codeProp( "InGroup", $g );
+ }
+ }
+ }
+ elsif ( $text =~ /^\s*\@defgroup\s+(\w+)\s*/ ) {
+ # parse group tag and description
+ my $grptag = $1;
+ my $grpdesc = $' eq "" ? $grptag : $';
+
+ # create group node
+ my $grpnode = Ast::New( $grptag );
+ $grpnode->AddProp( "Desc", $grpdesc );
+ $grpnode->AddProp( "NodeType", "GroupDef" );
+
+ # attach
+ codeProp( "Groups", $grpnode );
+ }
+ elsif ( $text =~ /^\s*\@see\s*/ ) {
+ docListProp( "See" );
+ }
+ elsif( $text =~ /^\s*\@short\s*/ ) {
+ docProp( "ClassShort" );
+ }
+ elsif( $text =~ /^\s*\@author\s*/ ) {
+ docProp( "Author" );
+
+ }
+ elsif( $text =~ /^\s*\@version\s*/ ) {
+ docProp( "Version" );
+ }
+ elsif( $text =~ /^\s*\@id\s*/ ) {
+
+ docProp( "Id" );
+ }
+ elsif( $text =~ /^\s*\@since\s*/ ) {
+ docProp( "Since" );
+ }
+ elsif( $text =~ /^\s*\@returns?\s*/ ) {
+ docProp( "Returns" );
+ }
+ elsif( $text =~ /^\s*\@(?:throws|exception|raises)\s*/ ) {
+ docListProp( "Throws" );
+ }
+ elsif( $text =~ /^\s*\@image\s+(\w+)\s*/ ) {
+ textProp( "Image" );
+ $extraprops{ "Path" } = $1;
+ }
+ elsif( $text =~ /^\s*\@param\s+(\w+)\s*/ ) {
+ textProp( "Param" );
+ $extraprops{ "Name" } = $1;
+ }
+ elsif( $text =~ /^\s*\@sect\s+/ ) {
+
+ textProp( "DocSection" );
+ }
+ elsif( $text =~ /^\s*\@li\s+/ ) {
+
+ textProp( "ListItem" );
+ }
+ elsif ( $text =~ /^\s*\@libdoc\s+/ ) {
+ # Defines the text for the entire library
+ docProp( "LibDoc" );
+ }
+ else {
+ if ( $text =~ m#\*/# ) {
+ $finished = 1;
+ $text = $`;
+ }
+ $buffer .= $text;
+ }
+ }
+
+ flushProp();
+
+
+ return undef if !defined $docNode;
+
+# postprocess docnode
+
+ # add a . to the end of the short if required.
+ my $short = $docNode->{ClassShort};
+
+ if ( defined $short ) {
+ if ( !($short =~ /\.\s*$/) ) {
+ $docNode->{ClassShort} =~ s/\s*$/./;
+ }
+ }
+ else {
+ # use first line of normal text as short name.
+ if ( defined $docNode->{Text} ) {
+ my $node;
+ foreach $node ( @{$docNode->{Text}} ) {
+ next if $node->{NodeType} ne "DocText";
+ $short = $node->{astNodeName};
+ $short = $`."." if $short =~ /\./;
+ $docNode->{ClassShort} = $short;
+ goto shortdone;
+ }
+ }
+ }
+shortdone:
+
+# Join and break all word list props so that they are one string per list
+# node, ie remove all commas and spaces.
+
+ recombineOnWords( $docNode, "See" );
+ recombineOnWords( $docNode, "Throws" );
+
+ return $docNode;
+}
+
+=head3 setType
+
+ Parameters: propname, proptype ( 0 = single, 1 = list, 2 = text )
+
+ Set the name and type of the pending property.
+
+=cut
+
+sub setType
+{
+ ( $currentProp, $propType ) = @_;
+}
+
+=head3 flushProp
+
+ Flush any pending item and reset the buffer. type is set to DocText.
+
+=cut
+
+sub flushProp
+{
+ return if $buffer eq "";
+ initDocNode() unless defined $docNode;
+
+ if( $propType == 1 ) {
+ # list prop
+ $docNode->AddPropList( $currentProp, $buffer );
+ }
+ elsif ( $propType == 2 ) {
+ # text prop
+ my $textnode = Ast::New( $buffer );
+ $textnode->AddProp( 'NodeType', $currentProp );
+ $docNode->AddPropList( 'Text', $textnode );
+
+ foreach my $prop ( keys %extraprops ) {
+ $textnode->AddProp( $prop,
+ $extraprops{ $prop } );
+ }
+
+ %extraprops = ();
+ }
+ else {
+ # one-off prop
+ $docNode->AddProp( $currentProp, $buffer );
+ }
+
+ # reset buffer
+ $buffer = "";
+ setType( "DocText", 2 );
+}
+
+=head3 codeProp
+
+ Flush the last node, add a new property and reset type to DocText.
+
+=cut
+
+sub codeProp
+{
+ my( $prop, $val ) = @_;
+
+ flushProp();
+
+ initDocNode() unless defined $docNode;
+ $docNode->AddPropList( $prop, $val );
+
+ setType( "DocText", 2 );
+
+}
+
+=head3 docListProp
+
+ The next item is a list property of docNode.
+
+=cut
+
+sub docListProp
+{
+ my( $prop ) = @_;
+
+ flushProp();
+
+ $buffer = $';
+ setType( $prop, 1 );
+}
+
+=head3 docProp
+
+ The next item is a simple property of docNode.
+
+=cut
+
+sub docProp
+{
+ my( $prop ) = @_;
+
+ flushProp();
+
+ $buffer = $';
+ setType( $prop, 0 );
+}
+
+=head3 textProp
+
+ Parameters: prop, val
+
+ Set next item to be a 'Text' list node. if val is assigned, the
+ new node is assigned that text and flushed immediately. If this
+ is the case, the next item is given the 'DocText' text property.
+
+=cut
+
+sub textProp
+{
+ my( $prop, $val ) = @_;
+
+ flushProp();
+
+ if ( defined $val ) {
+ $buffer = $val;
+ setType( $prop, 2 );
+ flushProp();
+ $prop = "DocText";
+ }
+
+ setType( $prop, 2 );
+ $buffer = $';
+}
+
+
+=head3 initDocNode
+
+ Creates docNode if it is not defined.
+
+=cut
+
+sub initDocNode
+{
+ $docNode = Ast::New( "Doc" );
+ $docNode->AddProp( "NodeType", "DocNode" );
+}
+
+sub recombineOnWords
+{
+ my ( $docNode, $prop ) = @_;
+
+ if ( exists $docNode->{$prop} ) {
+ my @oldsee = @{$docNode->{$prop}};
+ @{$docNode->{$prop}} = split (/[\s,]+/, join( " ", @oldsee ));
+ }
+}
+
+###############
+
+=head2 attachDoc
+
+Connects a docnode to a code node, setting any other properties
+if required, such as groups, internal/deprecated flags etc.
+
+=cut
+
+sub attachDoc
+{
+ my ( $node, $doc, $rootnode ) = @_;
+
+ $node->AddProp( "DocNode", $doc );
+ $node->AddProp( "Internal", 1 ) if defined $doc->{Internal};
+ $node->AddProp( "Deprecated", 1 ) if defined $doc->{Deprecated};
+
+ # attach group definitions if they exist
+ if ( defined $doc->{Groups} ) {
+ my $groupdef = $rootnode->{Groups};
+ if( !defined $groupdef ) {
+ $groupdef = Ast::New( "Groups" );
+ $rootnode->AddProp( "Groups", $groupdef );
+ }
+
+ foreach my $grp ( @{$doc->{Groups}} ) {
+ if ( defined $groupdef->{ $grp->{astNodeName} } ) {
+ $groupdef->{ $grp->{ astNodeName}
+ }->AddProp( "Desc", $grp->{Desc} );
+ }
+ else {
+ $groupdef->AddProp( $grp->{astNodeName}, $grp );
+ }
+ }
+ }
+
+ # attach node to group index(es)
+ # create groups if not found, they may be parsed later.
+
+ if ( defined $doc->{InGroup} ) {
+ my $groupdef = $rootnode->{Groups};
+
+ foreach my $grp ( @{$doc->{InGroup}} ) {
+ if ( !exists $groupdef->{$grp} ) {
+ my $newgrp = Ast::New( $grp );
+ $newgrp->AddProp( "Desc", $grp );
+ $newgrp->AddProp( "NodeType", "GroupDef" );
+ $groupdef->AddProp( $grp, $newgrp );
+ }
+
+ $groupdef->{$grp}->AddPropList( "Kids", $node );
+ }
+ }
+}
+
+1;
--- /dev/null
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+package kdocTeX;
+
+require Ast;
+
+## LaTeX Output.
+# Peeks in main: quiet, version, classSource
+
+BEGIN {
+ $modname = "kdocTeX";
+}
+
+sub dumpDoc {
+ my( $name, $node, $outputdir ) = @_;
+
+ print "Generating LaTeX documentation.\n" unless $main::quiet;
+
+ open(TEX,"> $outputdir/$name.tex")
+ || die "Couldn't create $outputdir/".$name.".tex.\n";
+
+ print TEX<<EOF;
+\\documentclass[12pt]\{article\}
+\\usepackage\{a4\}
+\\usepackage\{makeidx\}
+\\title\{$name Library Index\}
+\\date\{\\today\}
+\\def\\mtl{{\\tt\\~\\relax}}
+\\author{Generated with KDOC $main::version}
+\\makeindex
+\\begin\{document\}
+\\maketitle
+\\pagestyle\{headings\}
+\\tableofcontents
+\\newpage
+\\sloppy
+EOF
+
+ $node->Visit($modname);
+
+ foreach $class ( @{$classes} ) {
+
+ $class->Visit($modname);
+
+ $inPre = 0;
+ $doc = "";
+
+ foreach $line ( split /\n/, $Description ) {
+ if( $line =~ /<(pre|PRE)>/ ) {
+ $inPre = 1;
+ $doc .= "\\begin{verbatim}\n";
+ next;
+ }
+ if( $line =~ m#</(pre|PRE)># ) {
+ $inPre = 0;
+ $doc .= "\\end{verbatim}\n";
+ next;
+ }
+ if( !$inPre ) {
+ $line =~ s/\@ref(\s*(#|::))?//g;
+ $line =~ s/([~#\$\\\&%#_\{\}])/\\$1/g;
+ $line =~ s/<(code|pre)>/\\texttt\{/g;
+ $line =~ s/<\/(code|pre)>/}/g;
+ $line =~ s/([<>])/\\texttt\{$1\} /g;
+ $line =~ s/~/\\texttt{~}\\relax /g;
+ }
+
+ $doc .= $line."\n";
+ }
+
+ $ClassName = escape( $astNodeName );
+ $Header = escape( $Header );
+ $ClassSee = escape( $ClassSee );
+
+ print TEX<<EOF;
+\\section[$ClassName]\{\\emph\{$ClassName\} class reference \\small\\sf ($Header)\}
+\\vspace{-0.6cm}
+\\hrulefill
+\\index\{$ClassName\}
+EOF
+
+ if( $class->{ "TmplArgs" } ne "" ) {
+ print TEX "\\begin{description}\n",
+ "\\item{template form:}",
+ "\\texttt{template <", escape( $class->{ "TmplArgs" } ),
+ "> ",
+ $ClassName, "}\n";
+
+ print TEX "\\end{description}\n";
+ }
+
+ if( defined $class->{ "Ancestors" } ){
+ print TEX "\\begin{description}\n",
+ "\\item{inherits:}";
+
+ foreach $ancestor ( @{$Ancestors} ) {
+ $ancName = $ancestor->{"astNodeName"};
+
+ $str = " ".$ancName;
+
+ if( defined $main::classSource{ $ancName } ) {
+ $str .="(".$main::classSource{$ancName}.
+ ")";
+ }
+
+ print TEX escape( $str ),"\n";
+ }
+
+ print TEX "\\end{description}\n";
+ }
+
+
+ if( $Author ne "" || $Version ne "" || $ClassShort ne ""
+ || $ClassSee ne "" ) {
+ print TEX "\\begin{description}\n";
+
+ print TEX "\\item[Description:] ",
+ escape( $ClassShort ),"\n"
+ if $ClassShort ne "";
+ print TEX "\\item[Version:] ", escape( $Version ),"\n"
+ if $Version ne "";
+
+ print TEX "\\item[Author:] ", escape( $Author ),"\n"
+ if $Author ne "";
+
+ print TEX "\\item[See Also:] ", escape( $ClassSee ),"\n"
+ if $ClassSee ne "";
+
+ print TEX "\\end{description}\n";
+ }
+
+ print TEX "$doc\n\n" if $Description ne "";
+
+ dumpMembers( "public members", $public )
+ if defined $class->{"public"};
+ dumpMembers( "public slots", $public_slots )
+ if defined $class->{"public_slots"};
+ dumpMembers( "protected members", $protected )
+ if defined $class->{"protected"};
+ dumpMembers( "protected slots", $protected_slots )
+ if defined $class->{"protected_slots"};
+ dumpMembers( "signals", $signals )
+ if defined $class->{"signals"};
+
+ if( $main::dontDoPrivate == 0 ) {
+ dumpMembers( "private members", $private )
+ if defined $class->{"private"};
+ dumpMembers( "private slots", $private_slots )
+ if defined $class->{"private_slots"};
+ }
+
+ Ast::UnVisit();
+ }
+
+ Ast::UnVisit();
+
+ print TEX "\\printindex\n\\end{document}\n";
+
+}
+
+sub dumpMembers
+{
+ my( $access, $nodes ) = @_;
+
+ print TEX "\\subsection{$access}\n";
+
+ foreach $member ( @{$nodes} ) {
+
+ $member->Visit($modname);
+
+ $inPre = 0;
+ $doc = "";
+
+ foreach $line ( split /\n/, $Description ) {
+ if( $line =~ /<(pre|PRE)>/ ) {
+ $inPre = 1;
+ $doc .= "\\begin{verbatim}\n";
+ next;
+ }
+ if( $line =~ /<\/(pre|PRE)>/ ) {
+ $inPre = 0;
+ $doc .= "\\end{verbatim}\n";
+ next;
+ }
+ if( !$inPre ) {
+ $line =~ s/\@ref(\s*(#|::))?//g;
+ $line =~ s/([~#\$\\\&%#_\{\}])/\\$1/g;
+ $line =~ s/<(code|pre)>/\\texttt\{/g;
+ $line =~ s/<\/(code|pre)>/}/g;
+ $line =~ s/([<>])/\\texttt\{$1\} /g;
+ $line =~ s/~/\\texttt{~}\\relax /g;
+ }
+
+ $doc .= $line."\n";
+ }
+
+ $astNodeName = escape( $astNodeName );
+
+
+ print TEX<<EOF;
+\\subsubsection*{$ClassName\:\:$astNodeName}
+\\vspace{-0.65cm}
+\\hrulefill
+\\index{$ClassName!$astNodeName}
+\\index{$astNodeName!$ClassName}
+\\begin{flushleft}
+EOF
+
+ if( $Keyword eq "method" ) {
+ $ReturnType = escape( $ReturnType );
+ $Parameters = escape( $Parameters );
+ $Parameters =~ s/\n+/ /g;
+
+ print TEX "\\texttt{$ReturnType$astNodeName(",
+ "$Parameters)$Const;}\n";
+ }
+ elsif ( $Keyword eq "property" ) {
+ $Type = escape( $Type );
+ print TEX "\\texttt{$Type$astNodeName;}\n";
+ }
+ elsif ( $Keyword eq "typedef" ) {
+ $Type = escape( $Type );
+ print TEX "\\texttt{$Type$astNodeName;}\n";
+ }
+ elsif ( $Keyword eq "enum" ) {
+ $Constants = escape( $Constants );
+ $Constants =~ s/\n+/ /g;
+
+ print TEX<<EOF
+\\texttt{enum $astNodeName\\{
+$Constants
+\\};}
+
+EOF
+ }
+
+ print TEX<<EOF;
+\\end{flushleft}
+
+$doc
+
+EOF
+ if ( $Keyword eq "method" &&
+ ($Returns ne "" || $Exceptions ne "") ) {
+
+ if ( $Returns ne "" ) {
+ $Returns = escape ( $Returns );
+ print TEX<<EOF;
+\\begin{description}
+\\item[Returns:] $Returns
+\\end{description}
+EOF
+ }
+
+ if ( $Exceptions ne "" ) {
+ $Exceptions = escape ( $Exceptions );
+ print TEX<<EOF;
+\\begin{description}
+\\item[Throws:] $Exceptions
+\\end{description}
+EOF
+ }
+
+ }
+ Ast::UnVisit();
+ }
+}
+
+sub escape
+{
+ my( $str ) = @_;
+
+ $str =~ s/\@ref\s+//g;
+ $str =~ s/([#\$\\\&%#_\{\}])/\\$1/g;
+ $str =~ s/([<>]+)/\\texttt\{$1\}/g;
+ $str =~ s/~/\\mtl /g;
+
+ return $str;
+}
+
+1;
--- /dev/null
+
+package kdocUtil;
+
+use strict;
+
+
+=head1 kdocUtil
+
+ General utilities.
+
+=head2 countReg
+
+ Parameters: string, regexp
+
+ Returns the number of times of regexp occurs in string.
+
+=cut
+
+sub countReg
+{
+ my( $str, $regexp ) = @_;
+ my( $count ) = 0;
+
+ while( $str =~ /$regexp/s ) {
+ $count++;
+
+ $str =~ s/$regexp//s;
+ }
+
+ return $count;
+}
+
+=head2 findCommonPrefix
+
+ Parameters: string, string
+
+ Returns the prefix common to both strings. An empty string
+ is returned if the strings have no common prefix.
+
+=cut
+
+sub findCommonPrefix
+{
+ my @s1 = split( "/", $_[0] );
+ my @s2 = split( "/", $_[1] );
+ my $accum = "";
+ my $len = ($#s2 > $#s1 ) ? $#s1 : $#s2;
+
+ for my $i ( 0..$len ) {
+# print "Compare: $i '$s1[$i]', '$s2[$i]'\n";
+ last if $s1[ $i ] ne $s2[ $i ];
+ $accum .= $s1[ $i ]."/";
+ }
+
+ return $accum;
+}
+
+=head2 makeRelativePath
+
+ Parameters: localpath, destpath
+
+ Returns a relative path to the destination from the local path,
+ after removal of any common prefix.
+
+=cut
+
+sub makeRelativePath
+{
+ my ( $from, $to ) = @_;
+
+ # remove prefix
+ $from .= '/' unless $from =~ m#/$#;
+ $to .= '/' unless $to =~ m#/$#;
+
+ my $pfx = findCommonPrefix( $from, $to );
+
+ if ( $pfx ne "" ) {
+ $from =~ s/^$pfx//g;
+ $to =~ s/^$pfx//g;
+ }
+# print "Prefix is '$pfx'\n";
+
+ $from =~ s#/+#/#g;
+ $to =~ s#/+#/#g;
+ $pfx = countReg( $from, '\/' );
+
+ my $rel = "../" x $pfx;
+ $rel .= $to;
+
+ return $rel;
+}
+
+sub hostName
+{
+ my $host = "";
+ my @hostenvs = qw( HOST HOSTNAME COMPUTERNAME );
+
+ # Host name
+ foreach my $evar ( @hostenvs ) {
+ next unless defined $ENV{ $evar };
+
+ $host = $ENV{ $evar };
+ last;
+ }
+
+ if( $host eq "" ) {
+ $host = `uname -n`;
+ chop $host;
+ }
+
+ return $host;
+}
+
+sub userName
+{
+ my $who = "";
+ my @userenvs = qw( USERNAME USER LOGNAME );
+
+ # User name
+ foreach my $evar ( @userenvs ) {
+ next unless defined $ENV{ $evar };
+
+ $who = $ENV{ $evar };
+ last;
+ }
+
+ if( $who eq "" ) {
+ if ( $who = `whoami` ) {
+ chop $who;
+ }
+ elsif ( $who - `who am i` ) {
+ $who = ( split (/ /, $who ) )[0];
+ }
+ }
+
+ return $who;
+}
+
+1;
+
--- /dev/null
+package kdoctexi;
+
+# kdoctexi.pm -- C++ TexInfo output module for KDOC.
+# Copyright (C) 1998, Bernd Gehrmann
+# $Id$
+
+# The KDOC package is distributed under the GNU Public License.
+
+use Ast;
+use kdocAstUtil;
+use File::Path;
+use File::Basename;
+use Iter;
+
+use strict;
+
+use vars qw/ $lib $rootnode $outputdir @clist $depth /;
+
+=head1 kdoctexi
+ TexInfo output module.
+=cut
+
+sub writeDoc
+{
+ ( $lib, $rootnode, $outputdir ) = @_;
+
+ print "Generating texinfo documentation.\n" unless $main::quiet;
+
+ mkpath( $outputdir ) unless -f $outputdir;
+
+ makeClassList( $rootnode );
+ writeMain();
+ writeHierarchy();
+ writeOverview();
+ writeClasses();
+
+}
+
+
+
+sub makeClassList
+{
+ my ( $rootnode ) = @_;
+
+ @clist = ();
+
+ foreach my $node ( @ {$rootnode->{Kids}} ) {
+ if ( !defined $node ) {
+ print "makeClassList: undefined child in rootnode!\n";
+ next;
+ }
+
+ push( @clist, $node ) unless exists $node->{ExtSource}
+ || !exists $node->{Compound};
+ }
+
+ @clist = sort { $a->{astNodeName} cmp $b->{astNodeName} }
+ @clist;
+}
+
+
+
+sub writeMain {
+
+ open( TEXMAIN, ">$outputdir/$lib.texi" )
+ || die "Couldn't write to $outputdir/$lib-main.texi\n";
+
+ print TEXMAIN<<EOF;
+\\input texinfo
+\@c %**start of header
+\@comment ----- automatically generated - do not edit! -----
+\@afourpaper
+\@setfilename $lib.info
+\@settitle $lib documentation
+\@headings on
+\@setchapternewpage on
+\@c %**end of header
+
+\@include $lib-hier.tex
+\@include $lib-overvw.tex
+\@include $lib-inc.tex
+
+\@page
+\@comment \@printindex fn
+\@shortcontents
+\@bye
+EOF
+
+ close( TEXMAIN );
+}
+
+
+
+sub writeHierarchy
+{
+ my @bullets = ( '@bullet', '*', '+', '-' );
+ my $depth = 0;
+
+ open( TEX, ">$outputdir/$lib-hier.tex" )
+ || die "Couldn't write to $outputdir/$lib-hier.tex\n";
+
+ print TEX "\@comment ----- automatically generated - do not edit! -----\n";
+ print TEX "\@unnumbered $lib Class Hierarchy\n\n";
+
+ Iter::Hierarchy( $rootnode,
+ sub { # down
+ my $bullet = $bullets[ $depth ];
+ $bullet = "-" unless defined $bullet;
+ ++$depth;
+
+ print TEX "\@itemize $bullet\n";
+ },
+ sub { # print
+ my ($node) = @_;
+ return if $node == $rootnode;
+
+ my $src = defined $node->{ExtSource} ?
+ " (from $node->{ExtSource})" : "";
+ my $item = $depth > 0 ? "\@item\n" : "";
+
+ print TEX "$item\@code{",$node->{astNodeName},"$src\n";
+ },
+ sub { # up
+ print TEX "\@end itemize\n";
+ --$depth;
+ }
+ );
+
+ close TEX;
+}
+
+
+sub writeOverview
+{
+ open( TEX, ">$outputdir/$lib-overvw.tex" )
+ || die "Couldn't write to $outputdir/$lib-classes.tex\n";
+
+ print TEX "\@comment ----- automatically generated - do not edit! -----\n";
+ print TEX "\@unnumbered $lib Library Overview\n\n";
+
+ if ( defined $rootnode->{DocNode} ) {
+ writeDescription( $rootnode->{DocNode} );
+ }
+
+
+ print TEX "\@table \@asis\n";
+
+ foreach my $node ( @clist ) {
+
+ my $docnode = $node->{DocNode};
+
+ my $short = "";
+ if ( defined $docnode && exists $docnode->{ClassShort} ) {
+ $short = formatText($docnode->{ClassShort});
+ }
+
+ my $className = $node->{astNodeName};
+
+ # The following is really a dirty hack
+ # Find something better!
+ print TEX "\@item \@code{$className ";
+ print TEX "@ @ @ @ @ @ @ @ @ @ @ @ @ }", "\n";
+ print TEX escape($short), "\n";
+ }
+
+ print TEX "\@end table\n";
+ close TEX;
+}
+
+
+
+sub writeClasses
+{
+ open( TEXINC, ">$outputdir/$lib-inc.tex" )
+ || die "Couldn't write to $outputdir/$lib-inc.tex\n";
+ print TEXINC "\@comment ----- automatically generated - do not edit! -----\n";
+
+ foreach my $node ( @clist ) {
+
+ next if !defined $node->{Compound}
+ || defined $node->{ExtSource};
+
+ my $className = $node->{astNodeName};
+
+ print TEXINC "\@include $className.tex\n";
+ open( TEX, ">$outputdir/$className.tex" )
+ || die "Couldn't write to $outputdir/$className.tex\n";
+ print TEX "\@comment ----- automatically generated - do not edit! -----\n";
+
+ writeClass( $node );
+ close TEX;
+ }
+
+ close TEXINC;
+}
+
+
+
+sub writeClass
+{
+ my ( $node ) = @_;
+
+ my $docnode = $node->{DocNode};
+ my $header = $node->{Source}->{astNodeName};
+ my $className = $node->{astNodeName};
+
+ my $classType = (exists $node->{Tmpl} )? "Template" : "Class";
+
+ print TEX<<EOF;
+\@unnumbered \@code\{$className\} $classType Reference \@i\{($header)\}
+\@findex $className
+EOF
+
+ if ( exists $docnode->{Deprecated} ) {
+ print TEX "\@noindent\n\@b{Deprecated Class}\n";
+ }
+
+ if ( exists $docnode->{Internal} ) {
+ print TEX "\@noindent\n\@b{For internal use only}\n";
+ }
+
+ if ( exists $node->{Pure} ) {
+ print TEX "\@noindent\n\@b{Contains pure virtuals}\n";
+ }
+
+ if ( $classType eq "template" ) {
+ print TEX "\@table \@asis\n\@item Template form:\n",
+ "\@code{template <", escape( $node->{Tmpl} ),
+ "> ", $className, "}\n\@end table\n";
+ }
+
+ my $comma = "";
+
+ Iter::Ancestors( $node, $rootnode, undef,
+ sub { # start
+ print TEX "\@table \@asis\n\@item Inherits:\n"
+ },
+ sub { # print
+ my ( $n, $name, $type, $template ) = @_;
+ my $source;
+
+ if ( defined $n ) {
+ $source = defined $n->{ExtSource} ?
+ " ($n->{ExtSource})" : "";
+ $name = $n->{astNodeName};
+ }
+
+ print TEX $comma, escape( $name ), $source, "\n";
+ },
+ sub { #end
+ print TEX "\@end table\n";
+ }
+ );
+
+ Iter::Descendants( $node, undef,
+ sub { #start
+ print TEX "\@table \@asis\n\@item Inherited by:\n";
+ $comma = "";
+ },
+ sub { #print
+ my ($in) = @_;
+ my $source;
+ $source = defined $in->{ExtSource} ?
+ " ($in->{ExtSource})\n" :"\n";
+
+ print TEX $comma, escape( $in->{astNodeName} ),
+ $source;
+ },
+ sub { #end
+ print TEX "\n\@end table\n";
+ }
+ );
+
+ my $author = $node->{Author};
+ my $version = $node->{Version};
+ my $classSee = $node->{See};
+
+ if( $author ne "" || $version ne "" || $classSee ne "" ) {
+ my $escVersion = escape( $version );
+ my $escAuthor = escape( $author );
+ $escAuthor =~ s/<(.+\@\@.+)>/\@email{$1}/mg;
+ $escAuthor =~ s/\((.+\@\@.+)\)/\@email{$1}/mg;
+ my $escSee = escape( $classSee );
+ print TEX "\@table \@asis\n";
+ print TEX "\@item Version:\n$escVersion\n" unless $escVersion eq "";
+ print TEX "\@item Author:\n$escAuthor\n" unless $escAuthor eq "";
+ print TEX "\@item See Also:\n$escSee\n" unless $escSee eq "";
+ print TEX "\@end table\n";
+ }
+
+ writeDescription( $docnode );
+
+ Iter::MembersByType( $node,
+ sub { #startgroup
+ print TEX "\@unnumberedsec $_[0]\n";
+ },
+ sub { # member
+ my ( $node, $kid ) = @_;
+
+ writeMember( $node, $kid );
+ }
+ );
+}
+
+sub writeMember
+{
+ my ( $classnode, $member ) = @_;
+ my $className = $classnode->{astNodeName};
+ my $memberName = $member->{astNodeName};
+ my $escName = escape( $memberName );
+ my $type = $member->{NodeType};
+ $_ = $type;
+ SWITCH: {
+
+ if( /^method/ ) {
+ my $escRetType = escape( $member->{ReturnType} );
+ my $escParams = escape( $member->{Params} );
+ my $flags = $member->{Flags};
+
+ if ( $memberName eq $className ) {
+ print TEX "\@deftypefn Constructor {} $escName {($escParams)}\n";
+ }
+ elsif ( $memberName eq "~$className" ) {
+ print TEX "\@deftypefn Destructor {} $escName {($escParams)}\n";
+ }
+ elsif ( $flags =~ /s/ ) {
+ print TEX "\@deftypefn {Static Method} {$escRetType} $escName ",
+ "{($escParams)}\n";
+ }
+ else {
+ print TEX "\@deftypefn Method {$escRetType} $escName ",
+ "{($escParams)}", $flags =~ /c/? " const\n" : "\n";
+ }
+
+ my $ref = kdocAstUtil::findOverride( $rootnode,
+ $classnode, $member->{astNodeName} );
+ if ( defined $ref ) {
+ print TEX "Reimplemented from $ref\n";
+ }
+
+ writeMemberInfo( $member->{DocNode} );
+
+ my @paramlist = ();
+ kdocAstUtil::findNodes( \@paramlist, $member->{Text},
+ "NodeType", "Param" );
+
+ if ( $#paramlist >= 0 ) {
+ print TEX "\@noindent\nParameters:\n",
+ "\@multitable \@columnfractions .1 .15 .75\n";
+ foreach my $paramnode ( @paramlist ) {
+ print TEX "\@item \@tab ",
+ escape($paramnode->{Name}), " \@tab ",
+ escape($paramnode->{astNodeName}), "\n";
+
+ }
+ print TEX "\@end multitable\n";
+ }
+
+ my $returns = $member->{Returns};
+ print TEX "\@noindent\nReturns: ",
+ escape($returns), "\n" unless $returns eq "";
+
+ my $exceptions = $member->{Throws};
+ if ( $exceptions ne "" ) {
+ print TEX "\@noindent\n\@table ",
+ "\@asis\n\@item Throws:\n",
+ escape($exceptions), "\n\@end table\n";
+ }
+
+ print TEX "\@end deftypefn\n\n";
+ last SWITCH;
+ } # /^method/
+
+ if ( /^var/ ) {
+ my $type = $member->{Type};
+ print TEX "\@deftypevar ", escape($type), " $escName\n";
+ writeMemberInfo( $member->{DocNode} );
+ print TEX "\@end deftypevar\n";
+ last SWITCH;
+ } # /^var/
+
+ if( /^typedef/ ) {
+ my $escType = escape( $member->{Type} );
+ print TEX "\@deftp {typedef} {$escType} $escName\n";
+ writeMemberInfo( $member->{DocNode} );
+ print TEX "\@end deftp\n";
+ last SWITCH;
+ } # /^typedef/
+
+ if ( /^enum/ ) {
+ # I'm not really convinced that it makes sense to list all constants.
+ # Normally, I would expect that all constants are explained in the
+ # doc comment, embedded in a <ul>..</ul> list.
+ my $escConstants = escape( $member->{Params} );
+ $escConstants =~ s/\n+/\n/g;
+ my $enumName = ($escName =~ /^\s*$/)?
+ "(Anonymous)" : $escName;
+ print TEX "\@deftp Enumeration \@code{enum} $enumName\n";
+ print TEX "\@example\nenum $enumName \@{\n",
+ "$escConstants\@};\n\@end example\n";
+ writeMemberInfo( $member->{DocNode} );
+ print TEX "\@end deftp\n";
+ last SWITCH;
+ } # /^enum/
+
+ } # SWITCH
+
+}
+
+
+
+sub writeDescription
+{
+ my ( $docnode ) = @_;
+
+ my $text = $docnode->{Text};
+ if ( $text eq "") { return; }
+
+ my $lasttype = "";
+ my $type = undef;
+ foreach my $node ( @$text ) {
+ $type = $node->{NodeType};
+ my $name = $node->{astNodeName};
+
+ if ( $lasttype eq "ListItem" && $type ne $lasttype ) {
+ print TEX "\@end itemize\n";
+ }
+
+ if ( $type eq "Pre" ) {
+ print TEX "\@example\n";
+ print TEX escape($name);
+ print TEX "\n\@end example\n";
+ }
+ elsif ( $type eq "DocText" || $type eq "Ref" ) {
+ print TEX formatText($name);
+ }
+ elsif ( $type eq "ParaBreak" ) {
+ print TEX "\n\n";
+ }
+ elsif ( $type eq "ListItem" ) {
+ if ( $lasttype ne "ListItem" ) {
+ print TEX "\@itemize \@bullet\n";
+ }
+ print TEX "\@item ", formatText($name), "\n";
+ }
+
+ $lasttype = $type;
+
+ }
+
+ if( $type eq "ListItem" ) {
+ print TEX "\@end itemize\n";
+ }
+
+ print TEX "\n";
+
+}
+
+
+
+sub writeMemberInfo
+{
+
+ my ( $docnode ) = @_;
+
+ writeDescription( $docnode );
+
+# if( $MethDeprecated ) {
+# print TEX "\@noindent\n\@b{Deprecated Member}\n";
+# }
+#
+# if( $MethInternal ) {
+# print TEX "\@noindent\n\@b{For internal use only}\n";
+# }
+
+}
+
+
+# This is for conversion of general, non-preformatted text
+
+sub formatText
+{
+ my ( $text ) = @_;
+
+ $text = escape($text);
+ # After escape, @ is @@
+ $text =~ s/\@\@ref\s+([\w\d_~]+)(#|::)([\w\d_~]+)/$1::$3/g;
+ $text =~ s/\@\@ref\s+(#|::)?([\w\d_~]+)/$2/g;
+ $text =~ s/\@\@see\s+([\w\d_~]+)(#|::)([\w\d_~]+)/$1::$3/g;
+ $text =~ s/\@\@see\s+(#|::)?([\w\d_~]+)/$2/g;
+ $text =~ s/<em>/\@emph\{/ig;
+ $text =~ s/<\/em>/\}/ig;
+ $text =~ s/<strong>/\@strong\{/ig;
+ $text =~ s/<\/strong>/\}/ig;
+ $text =~ s/<dfn>/\@dfn\{/ig;
+ $text =~ s/<\/dfn>/\}/ig;
+ $text =~ s/<code>/\@code\{/ig;
+ $text =~ s/<\/code>/\}/ig;
+ $text =~ s/<samp>/\@samp\{/ig;
+ $text =~ s/<\/samp>/\}/ig;
+ $text =~ s/<kbd>/\@kbd\{/ig;
+ $text =~ s/<\/kbd>/\}/ig;
+ $text =~ s/<var>/\@var\{/ig;
+ $text =~ s/<\/var>/\}/ig;
+ $text =~ s/<cite>/\@cite\{/ig;
+ $text =~ s/<\/cite>/\}/ig;
+ $text =~ s/<i>/\@i\{/ig;
+ $text =~ s/<\/i>/\}/ig;
+ $text =~ s/<b>/\@b\{/ig;
+ $text =~ s/<\/b>/\}/ig;
+ $text =~ s/<tt>/\@t\{/ig;
+ $text =~ s/<\/tt>/\}/ig;
+
+ $text =~ s/<br>/\@*/ig;
+ $text =~ s/<p>/\n/ig;
+ $text =~ s/<\/p>//ig;
+
+ $text =~ s/</</g;
+ $text =~ s/>/>/g;
+ $text =~ s/&/&/g;
+ $text =~ s/ /\@ /g;
+ $text =~ s/©/\@copyright{}/g;
+
+# Support for other languages?
+ $text =~ s/ä/\@"a/g;
+ $text =~ s/ö/\@"o/g;
+ $text =~ s/ü/\@"u/g;
+ $text =~ s/Ä/\@"A/g;
+ $text =~ s/Ö/\@"O/g;
+ $text =~ s/Ü/\@"U/g;
+ $text =~ s/ß/\@ss/g;
+
+ $text =~ s/^\s*<blockquote>\s*$/\@quotation/mig;
+ $text =~ s/^\s*<\/blockquote>\s*$/\@end quotation/mig;
+ $text =~ s/^\s*<ul>\s*$/\@itemize \@bullet/mig;
+ $text =~ s/^\s*<\/ul>\s*$/\@end itemize/mig;
+ $text =~ s/^\s*<ol>\s*$/\@enumerate/mig;
+ $text =~ s/^\s*<\/ol>\s*$/\@end enumerate/mig;
+ $text =~ s/^\s*<dl>\s*$/\@table \@asis/mig;
+ $text =~ s/^\s*<\/dl>\s*$/\@end table/mig;
+ $text =~ s/^\s*<li>/\@item /mig;
+ $text =~ s/^\s*<\/li>//mig;
+ $text =~ s/^\s*<dt>/\@item /mig;
+ $text =~ s/^\s*<\/dt>//mig;
+ $text =~ s/^\s*<dd>//mig;
+ $text =~ s/^\s*<\/dd>//mig;
+
+ return $text;
+}
+
+
+# This is for preformatted or similar text
+sub escape
+{
+ my( $text ) = @_;
+
+ $text =~ s/([\@\{\}])/\@$1/g;
+
+# i18n support
+# $text =~ s/ä/\@"a/g;
+# $text =~ s/ö/\@"o/g;
+# $text =~ s/ü/\@"u/g;
+# $text =~ s/Ä/\@"A/g;
+# $text =~ s/Ö/\@"O/g;
+# $text =~ s/Ü/\@"U/g;
+# $text =+ s/ß/\@ss{}/g;
+
+ return $text;
+}
+
+#
+
+sub deref
+{
+ my ( $str ) = @_;
+ my $out = "";
+ my $text;
+
+ $str =~ s/\@\@ref\s+([\w\d_~]+)(#|::)([\w\d_~]+)/$1::$3/g;
+ $str =~ s/\@\@ref\s+(#|::)?([\w\d_~]+)/$2/g;
+ $out = $str;
+
+# foreach $text ( split (/(\@ref\s+[\w:#]+)/, $str ) ) {
+# if ( $text =~ /\@ref\s+([\w:#]+)/ ) {
+# $out .= $1;
+# }
+# else {
+# $out .= $text;
+# }
+# }
+
+ return $out;
+}
+
+1;
--- /dev/null
+#!/usr/local/bin/perl
+
+# makekdedoc -- Generates HTML documentation KDE libraries using KDOC 2.
+# Sirtaj Singh Kang <taj@kde.org> Apr 1999.
+# $Id$
+
+require 5.000;
+
+use Getopt::Long;
+
+%files = ();
+%libs = ();
+%mods = ();
+%dirs = ();
+
+($ver = '$Revision$') =~ s/\$//g;
+$rulefile= "";
+$libdir=$ENV{KDOCLIBS};
+$outdir="srcdoc";
+$url="";
+$srcdir=".";
+$kdoc= "kdoc";
+$kdocopt = "--strip-h-path --format html --compress";
+$cwd = `pwd`;
+chop $cwd;
+
+# options
+
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+$err = GetOptions(
+ "url|u=s", \$url,
+ "outputdir|d=s", \$outdir,
+ "rule-file|r=s", \$rulefile,
+ "help|h", \&show_usage,
+ "libdir|L=s", \$libdir,
+ "kdoc|s=s", \$kdoc,
+ "srcdir|b=s", \$srcdir,
+ "kdocopt|p=s", \$extraopts );
+
+if ( $err == 0 ) {
+ show_usage();
+}
+
+$srcdir =~ s#^\.#$cwd#g;
+$outdir =~ s#^\.#$cwd#g;
+$outdir = $cwd."/$outdir" unless $outdir =~ m#^/#;
+$url = $outdir unless $url ne "";
+$libdir=$ENV{HOME}."/.kdoc" unless defined $libdir;
+
+if ( $rulefile eq "" ) {
+ $rulefile = $srcdir."/kdoc.rules";
+}
+else {
+ $rulefile =~ s#^\.#$cwd#g;
+}
+
+# read rule file
+
+readRules();
+
+die "$0: no modules to document.\n" if $#mods < 0;
+
+# generate docs
+
+if ($#ARGV >= 0 ) {
+ @mods = @ARGV;
+}
+
+foreach my $mod ( @mods ) {
+ print "$0: generating $mod...\n";
+
+ die "module $mod: no files defined\n" unless exists $files{ $mod };
+
+ # build the kdoc command
+ chdir $dirs{ $mod } ||
+ die "Couldn't cd to: $dirs{$mod} (try the -h option)\n";
+ @filelist = glob( $files{ $mod } );
+
+ if ( $#filelist < 0 ) {
+ chdir $cwd;
+ die "module $mod: no files defined\n";
+ }
+
+ $cmd = "$kdoc $kdocopt $extraopts -n '$mod' -d '$outdir/$mod'"
+ ." -L '$libdir' "
+ ."-u '$url/$mod' '".join( "' '", @filelist)."' ".$libs{ $mod };
+
+ system( $cmd ) == 0 || die "kdoc call failed:\n$cmd\n";
+
+ chdir $cwd;
+}
+
+exit 0;
+### done
+
+sub readRules
+{
+ open ( RULES, "$rulefile" ) || die "$0: couldn't read ",$rulefile,".".
+ "(try the -h option)\n";
+
+ while( <RULES> ) {
+ next unless /^\s*([\w\/]+) # module
+ _(\w+) # key
+ \s*=\s*/xs; # rest: value
+
+ $mod = $1;
+ $key = $2;
+ $v = $';
+ chop $v;
+
+ if ( $key eq "FILES" ) {
+ $files{ $mod } = $v;
+ }
+ elsif ( $key eq "LIBS" ) {
+ $libs{ $mod } = $v;
+ }
+ elsif ( $key eq "MODULES" ) {
+ @mods = split /\s+/, $v;
+
+# default path for module is $srcdir/$mod
+ foreach my $mod ( @mods ) {
+ $dirs{ $mod } = "$srcdir/$mod";
+ }
+ }
+ elsif ( $key eq "PATH" ) {
+ if ( $v =~ m#^/# ) {
+# allow absolute paths
+ $dirs{ $mod } = $v;
+ }
+ else {
+ $dirs{ $mod } = "$srcdir/$v";
+ }
+
+ }
+ else {
+ die "$rulefile:$.: Unrecognized key: $key\n";
+ }
+ }
+
+ close RULES;
+}
+
+
+
+sub show_usage
+{
+ print STDERR<<EOF;
+$0:
+ Generates HTML documentation for KDE libs.
+ Author: Sirtaj S. Kang <taj\@kde.org>
+ $ver
+
+Usage:
+ $0 [--rule-file=<rulefile>] [--libdir=<libdir>]
+ [--outputdir=<outputdir>] [--url=<url>]
+ [--srcdir=<kdelibs src dir>]
+ [--kdoc=<path to kdoc>] [<library>...]
+
+ By default all libraries defined by the rule file are
+ documented.
+
+Defaults:
+ rulefile "<srcdir>/kdoc.rules"
+ libdir "\$KDOCLIBS" or "\$HOME/.kdoc"
+ outputdir "./srcdoc"
+ url same as outdir
+ srcdir current dir
+ kdoc "kdoc"
+ kdocopts ""
+EOF
+
+ exit 1;
+}
+
+
+
+
+
+
+=head1 NAME
+
+makekdedoc -- Generates HTML documentation for KDE libraries using B<KDOC>.
+
+=head1 SYNOPSIS
+
+ makekdedoc [--rule-file=<rulefile>] [--libdir=<libdir>]
+ [--outputdir=<outputdir>] [--url=<url>]
+ [--srcdir=<kdelibs src dir>]
+ [--kdoc=<path to kdoc>] [<library>...]
+
+ makekdedoc --help
+
+=head1 DESCRIPTION
+
+This is a perl script that uses B<KDOC> to generate documentation for
+kdelibs. A "rule" file is used to figure out the libraries to document,
+the order in which to document them and the libraries with which each
+one will be cross-referenced (eg kdeui uses -lkdecore). See L<"FILES">
+for more info.
+
+NOTE: The script assumes that you have already generated a Qt
+cross-reference using qt2kdoc[1].
+
+=head1 OPTIONS
+
+Defaults for each option are in square brackets.
+
+=over 4
+
+=item B<library...>
+
+Specify the libraries to document. By default, all libraries defined by
+the rule file are documented.
+
+=item B<--outputdir> <path>, B<-d> <path>
+
+The directory where the output will be written. [`cwd`/srcdoc]
+
+=item B<--url> <url>, B<-u> <url>
+
+The base URL by which the generated docs will be accessed. For
+example, if your web server is configured to use $HOME/public_html for
+your home page, you could set the outputdir to $HOME/public_html/srcdoc
+and the url to http://myhost/~mylogin/srcdoc. [output dir]
+
+=item B<--rule-file> <path>, B<-r> <path>
+
+The path to the rule file to use for generating the documentation.
+[<srcdir>/kdoc.rules]
+
+=item B<--libdir> <path>, B<-L> <path>
+
+The directory in which the KDOC cross-reference files are
+stored. [$KDOCLIBS if set, otherwise $HOME/.kdoc]
+
+=item B<--kdoc> <path>, B<-k> <path>
+
+The path to the kdoc program. [kdoc]
+
+=item B<--kdocopt> <options>, B<-p> <options>
+
+Extra options to be passed to kdoc.
+
+=item B<--srcdir> <path>, B<-b> <path>
+
+The path to the kdelibs source, eg "$HOME/baseline/kdelibs". [`cwd`]
+
+=item B<--help>, B<-h>
+
+Quit with a usage message.
+
+=back
+
+=head1 EXAMPLES
+
+ makekdedoc --srcdir $HOME/baseline/kdelibs
+ --outputdir $HOME/public_html/src/kdelibs/
+ --url "http://www.ph.unimelb.edu.au/~ssk/src/kdelibs"
+
+=head1 FILES
+
+=over 4
+
+=item B<Rule file>
+
+This file lists the directories in the source directory to document. It
+also lists the files to document from each directory, and the libraries
+with which to cross-reference the generated documentation. Here is a small
+example that documents two libraries and links the second to the first.
+
+ # makekdedoc rule file
+ doc_MODULES = eenie meenie
+
+ # rules for eenie
+ eenie_FILES = *.h
+ eenie_LIBS = -lqt
+
+ # rules for meenie
+ meenie_FILES = a.h b.h
+ meenie_LIBS = -leenie -lqt
+
+In this example, all files in C<eenie/*.h> will be documented then two files
+from C<meenie/> will be documented, in the order declared in
+C<doc_MODULES>.
+
+=back
+
+=head1 SEE ALSO
+
+See L<kdoc[1]> and L<qt2kdoc[1]>.
+
+=head1 VERSION
+
+ makekdedoc $Revision$
+
+=head1 AUTHOR
+
+The script and this documentation were written by Sirtaj Singh Kang
+<taj@kde.org> in April 1999.
+
+=cut
--- /dev/null
+#!/usr/local/bin/perl -w
+
+# qt2kdoc -- Generates KDOC reference index for the Qt GUI toolkit.
+# Sirtaj Singh Kang 1997
+# $Id$
+
+use Getopt::Long;
+
+Getopt::Long::config qw( no_ignore_case permute bundling auto_abbrev );
+
+$lib = "./qt.kdoc";
+$destUrl = "";
+$libdir = $ENV{KDOCLIBS};
+$comp = 0;
+
+$err = GetOptions( "url|u=s", \$destUrl,
+ "outdir|o=s", \$libdir,
+ "compress|z", \$comp );
+
+if( $err == 0 ) {
+ usage();
+}
+
+$libdir = $ENV{HOME}."/.kdoc" unless defined $libdir;
+
+
+if( $#ARGV != 0 ) {
+ usage();
+}
+
+$file = $ARGV[ 0 ];
+$destUrl = $file if $destUrl eq "";
+$lib = $libdir."/qt.kdoc" if $libdir ne "";
+
+# Read hierarchy
+
+open( IN, $file."/hierarchy.html" )
+ || die "Could not open $file for reading\n";
+open( OUT, ">$lib" ) || die "Could not open $lib for writing\n";
+
+@stack = ();
+%ref = ();
+%parent = ();
+$current = undef;
+
+while ( <IN> )
+{
+ if( m#<ul\s+# ) {
+ push @stack, $current;
+ $current = undef;
+ }
+ elsif ( /^<li><a href=\"([\w\.]*)\">([\w]*)<\/a>/ ) { # "vim..grmbl
+ $current = $2;
+ $ref{ $current } = $1;
+
+ if ( $#stack >= 0 ) {
+ $parent{ $current } .= $stack[ $#stack ].",";
+ }
+ }
+ elsif ( m#</ul># ) {
+ $current = pop @stack;
+ }
+}
+
+# read all members
+
+%members = ();
+%refs = ();
+
+$lastmem = undef;
+
+open( IN, $file."/functions.html" )
+ || die "Could not open $file for reading\n";
+
+while ( <IN> ) {
+ if ( /^\s*<li.*?>(\w+):/ ) {
+ # function
+ $lastmem = $1;
+ }
+ elsif ( /^\s*<a href=\"(.*?)\">(\w+)/ && defined $lastmem ) { #"
+ # class
+ if ( !exists $members{ $2 } ) {
+ $members{ $2 } = [ $lastmem ];
+ $refs{ $2 } = [ $1 ];
+ }
+ else {
+ push @{$members{ $2 }}, $lastmem;
+ push @{$refs{ $2 }}, $1;
+ }
+ }
+ elsif ( defined $lastmem ) {
+ $lastmem = undef;
+ }
+}
+
+# write it
+
+print OUT<<LTEXT;
+<! KDOC Library HTML Reference File>
+<VERSION="2.0">
+<BASE URL="$destUrl">
+LTEXT
+
+foreach my $current ( sort keys %ref ) {
+ print OUT '<C NAME="', $current, '" REF="',
+ $ref{ $current }, '">',"\n";
+ if ( exists $parent{ $current } ) {
+ foreach $p ( sort split( ",", $parent{ $current } ) ) {
+ print OUT '<IN NAME="', $p, '">', "\n";
+ }
+ }
+
+ my $m = $members{ $current };
+ if( $#{$m} >= 0 ) {
+ my $r = $refs{ $current };
+ for $p ( 0..$#{$m} ) {
+ print OUT '<ME NAME="', $m->[$p], '" REF="',
+ $r->[$p],'">',"\n";
+ }
+ }
+ print OUT "</C>\n";
+}
+
+close( IN );
+close( OUT );
+
+# compress
+
+if ( $comp ) {
+ system ( 'gzip -9 "'.$lib.'"' ) == 0
+ || die "Couldn't compress $lib: $?\n";
+
+ $lib .= ".gz";
+}
+
+print "Qt reference written to $lib\n";
+
+# end main
+
+sub usage
+{
+ my $arg = shift;
+
+ print "qt2kdoc: Creates a kdoc reference file from".
+ " Qt HTML documentation.",
+ "\n\n", "usage:\n\tqt2kdoc [-u<URL>] [-o<dest>] [-z]",
+ " <path-to-Qt-html>\n";
+ exit 1;
+}
+
+=head1 NAME
+
+qt2kdoc -- Generates cross-reference file suitable for use with B<KDOC>
+from Qt Toolkit HTML documentation.
+
+=head1 SYNOPSIS
+
+ qt2kdoc [-u URL] [-o <destdir>] [-z] <path to qt html>
+
+=head1 DESCRIPTION
+
+B<qt2kdoc> generates a kdoc(1) cross-reference file from the classes.html
+file that is included with the Qt GUI Toolkit HTML documentation.
+
+The resulting file can be used to cross-reference documentation generated
+with KDOC for other classes with the Qt HTML documentation.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--url> <url>, B<-u> <url>
+
+The URL by which the Qt documentation can be accessed. This will
+allow other libraries to link to the Qt documentation.
+
+=item B<--outdir> <path>, B<-o> <path>
+
+The directory where the generated index file will be written.
+
+=item B<--compress>, B<-z>
+
+Compress the generated index with gzip. KDOC can read these compressed
+index files.
+
+=back
+
+=head1 EXAMPLES
+
+ qt2kdoc -u "http://www.mydomain/src/qthtml/" \
+ $HOME/web/src/qthtml
+
+=head1 ENVIRONMENT
+
+=over 4
+
+=item B<KDOCLIBS>
+
+If set, it is used as the default output path. It is overridden by the
+B<--outdir> option.
+
+=back
+
+=head1 FILES
+
+=over 4
+
+=item B<classes.html>, B<functions.html>
+
+The files from which information about the Qt library is read. They are
+parsed by qt2kdoc.
+
+=item B<qt.kdoc>
+
+A kdoc(1) cross-reference file that will be generated by qt2kdoc and can
+be used to link documentation generated by kdoc with the Qt documentation.
+
+=back
+
+=head1 SEE ALSO
+
+This script is a utility for kdoc(1).
+
+=head1 BUGS
+
+Dependent on format of Qt documentation.
+
+=head1 AUTHOR
+
+Sirtaj S. Kang <taj@kde.org>, 1998.
+
+=cut
--- /dev/null
+
+const char *bar;
+
+typedef
+(const char *)
+(Taj::GlobalType, Hi& *) foo;
+
+int sillyVar = 1;
+
+enum Test::FuBar { Test1 = 1, // Test
+ Test2, // Also a test
+ Test3,
+ Test4 = 4
+};
+
+/* gringrin
+* multi
+* line \
+ comment
+*/
+
+#include<taj.h>
+#define MY_DEF 1
+
+const char *FuBar( const char *str = "dog", int, 2 )const;
+
+/**
+* Doc
+* Documentation.
+*
+* What does it mean to write class documentation? Is it something naughty?
+*
+* Is it something nice?
+* @li Maybe
+* @li Maybe not. Maybe if we wrote lots of text here, it would make it into
+* the list we have got here.
+* @li Perhaps.
+*
+* Or should it be something that we'll never ever do if we're sober? After
+* all, sobriety is the vice of strife.
+*
+* @li another
+* @li list
+*
+* @see Taj and others.
+* @see Testing
+*
+* @author Taj
+* @version Break
+*/
+template <class T, // Comment
+ basic_string<T<TWibble>, 2>>
+class TWibble
+ :
+ public normal,
+ protected templated<T>
+{
+
+ /**
+ * I believe that I have documentation, and you don't.
+ */
+ virtual const char *retthis(
+ (TWibble *), // A pointer thing
+ Test *(test) ); // another one
+
+ struct MyClass {
+ int a;
+ int b;
+ const char *c;
+ void init( int, int, const char * );
+ };
+
+ /** @return a small dog. */
+ const char *doggie() const;
+
+protected:
+ /**
+ * Stufff
+ */
+ int _myVar;
+
+public slots:
+
+ const char *dontRet() const = 0;
+}; /* end of class */
+
+const char *MyVar;
--- /dev/null
+#!/usr/bin/perl
+
+use kdocUtil;
+
+print kdocUtil::makeRelativePath( $ARGV[0], $ARGV[1] ), "\n";
--- /dev/null
+
+/**
+ * @libdoc The Battle of Tweedles Dum and Dee
+ *
+ * Tweedledum
+ * and Tweedledee
+ * agreed to have a battle,
+ * for Tweedledum
+ * said TweedleDee
+ * had spoilt his nice new rattle.
+ *
+ * @defgroup animate Animate Objects
+ * @defgroup inanimate Inanimate Objects.
+ *
+ */
+
+/**
+ * @group inanimate
+ */
+template <class T>
+class Rattle {
+public:
+ class Prop {
+ vector<int> colours;
+ map<T, string> hums, rattles;
+ };
+
+ virtual int battle() const;
+};
+
+/**
+ * @group animate
+ */
+class Dum : public Rattle<int>::Prop {
+public:
+ /** You stole it! */
+ virtual int battle() const;
+};
+
+/**
+ * The younger brother.
+ * @group animate
+ */
+class Dee : public Rattle, map<int, int *>::iterator {
+public:
+ /** Did not! */
+ virtual int battle() const;
+};