--- /dev/null
+package Ast;
+
+#-----------------------------------------------------------------------------
+# 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
+#-----------------------------------------------------------------------------
+
+sub BEGIN {
+ $currLevel = 0;
+ $indent = " " x 2;
+}
+
+# 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) = @_;
+
+
+ $code = ""; $endCode = "";
+
+
+
+ foreach $k (keys %{$this}) {
+
+ $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 {
+ $code = pop(@endCodes);
+ eval($code) if ($code);
+}
+
+1;
--- /dev/null
+#!/usr/local/bin/perl
+
+# Documentation generator.
+# Torben Weis (weis@kde.org) and Sirtaj Kang (taj@kde.org)
+# $Id$
+
+# 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.
+
+###########################################################
+#
+# Global Variables
+#
+###########################################################
+
+# system options
+require 5.000;
+
+$PREFIX="/usr/local";
+push( @INC, $PREFIX."/share/kdoc");
+
+require Ast;
+
+# User options
+
+$dontDoPrivate = 1;
+$strictParser = 0;
+$documentAll = 1;
+$docDeprecated = 1;
+$docInternal = 1;
+$debug = 0;
+$docPath = ".";
+$urlBase = "";
+$libPath = ".";
+$lib = "";
+$genHTML = 0;
+$genTeX = 0;
+$genMan = 0;
+$quiet = 0;
+
+# running environment
+($version = '$Version$') =~ s/:\s*//g;
+
+$version =~ s/Version//g;
+
+$thisHost = `uname -n`; chop $thisHost;
+$user = `whoami`; chop $user;
+
+$generatedByText= 'Documentation generated by '.$user. '@'.
+ $thisHost.' on '.`date`;
+
+$libPath = $ENV{'KDOCLIBS'} if $ENV{'KDOCLIBS'} ne "";
+
+# globals - for method
+
+$exceptions = "";
+%paramDesc = ();
+$paramName = "";
+$paramText = "";
+$retText = "";
+$see = "";
+$text = "";
+$methInternal = 0;
+$methDeprecated = 0;
+
+# for class
+$class = "";
+$classAuthor = "";
+$classDeprecated = 0;
+$classInternal = 0;
+$classSee = "";
+$classShortText = "";
+$classShortTextSet = 0;
+$classText = "";
+$classVersion = "";
+$classInherits = "";
+$classAbstract = 0;
+$classTmplArgs = "";
+
+%classRef = (); # KDOC reference file
+%classSource = (); # tracks headers given a class name
+%classNode = (); # tracks nodes given a class name
+@headerList = (); # list of processed header files
+
+$filename = ""; # Current file being processed
+
+# index of stuff that shouldn't flag referencing errors
+# (not currently used)
+
+%noErr = ();
+$noErr{ "void" } = 1;
+$noErr{ "int" } = 1;
+$noErr{ "uint" } = 1;
+$noErr{ "uchar" } = 1;
+$noErr{ "short" } = 1;
+$noErr{ "ushort" } = 1;
+$noErr{ "unsignedint" } = 1;
+$noErr{ "unsignedchar" } = 1;
+$noErr{ "unsignedshort" } = 1;
+$noErr{ "float" } = 1;
+$noErr{ "double" } = 1;
+$noErr{ "short" } = 1;
+$noErr{ "char" } = 1;
+$noErr{ "unsigned" } = 1;
+$noErr{ "bool" } = 1;
+$noErr{ "long" } = 1;
+$noErr{ "string" } = 1;
+
+# for main
+
+$i = 0;
+@myargs = @ARGV;
+
+%children = ();
+%parents = ();
+
+# "<>" is the root of all classes.
+$children{"<>"} = "";
+$parents{"<>"} = "<>";
+
+$rootNode = Ast::New("ROOT");
+
+####
+#
+# Function addClass
+# Inserts a class into the hierarchy
+####
+
+sub addClass
+{
+ my($parent, $child) = @_;
+
+ $parents{ $child } = $parent;
+
+ $children{ $parent } = $child.";".$children{ $parent };
+
+ $children{ $child } = "" if !defined $children{ $child };
+}
+
+###########################################################
+#
+# Function
+# readLibrary
+#
+###########################################################
+
+sub readLibrary
+{
+ my( $libname ) = @_;
+ my( $prefix );
+ my( $libFull );
+
+ $libFull = $libPath."/".$libname.".kdoc";
+
+ open( IMP, "$libFull" )
+ || die "Could not open ".$libFull." for reading\n";
+
+ # the first line of a library contains the base url under
+ # which is was stored (using the -u flag at invokation of
+ # kdoc)
+ $prefix = <IMP>;
+ chop $prefix;
+
+ # However, there is one problem: kdoc references other symbols
+ # relative to the files of the library it is working on and that
+ # will not be in the present directory but somewhere else.
+ # Therefore $prefix is relative to the present directory, while
+ # the files of the present library will go to $docPath; we
+ # therefore need to modify $prefix for the number of subdirectories
+ # in $docPath. That scheme will fail, however, if $docPath is an
+ # absolute path, if $prefix is an absolute path or if $docPath
+ # contains "../". I (WB) am not proficient enough to invent a
+ # workaround
+
+ foreach ( split "/", $prefix)
+ {
+ $prefix = "../" . $prefix;
+ }
+ if ( ! ( $prefix =~ /\/$/) )
+ {
+ $prefix .= "/";
+ }
+
+ while ( <IMP> )
+ {
+ chop;
+ if ( /^(.*)=(.*)$/ )
+ {
+ $classRef{ $1 } = $prefix . "$2";
+ }
+ if( /^(\w+)=/ ) {
+ # add classes to external list
+ $classSource{ $1 } = $libname;
+ }
+ }
+
+ close( IMP );
+}
+
+###########################################################
+#
+# Function
+# processClass
+#
+###########################################################
+
+sub processClass
+{
+ my( $end );
+
+# New Ast Node for class
+
+ $classNode = Ast::New( $class );
+
+# use first line of text as short text if we have none yet.
+ if( $classShortText eq "" && $classText ne "" ) {
+ $_ = $classText;
+ /((\s|\w|[^.\n])*)\.*/;
+ $classShortText = $1." ";
+ $classShortTextSet = 1;
+ }
+
+
+
+# work out ancestors
+ $_ = $classInherits;
+ tr/\:\{//d;
+ s/protected//g;
+ s/private//g;
+ s/public//g;
+ s/virtual//g;
+
+ if ( !( /^\s*$/ ) )
+ {
+ foreach $c ( split /,/, $_ )
+ {
+ $c =~ s/\s//g;
+ addClass( $c, $class );
+
+ $inheritNode = Ast::New($c);
+ $classNode->AddPropList( "Ancestors", $inheritNode );
+ }
+
+ }
+ else {
+ addClass( "<>", $class );
+ }
+
+# process the rest of the class declaration
+
+ while ( <IN> )
+ {
+ next if /^\s*$/g;
+
+# parse out // comments, except where in a string or
+ s#//.*$##g unless m#"[^"]+".*//# || m#^\s*///#;
+
+ $line = $_;
+
+ if ( /^\s*\}\s*;\s*(\/\/.*)?$/ )
+ {
+# end of class declaration
+# dump all stored stuff to file
+
+ print "CLASS END: $class\n" if $debug;
+
+ if( ($classInternal == 0 || $docInternal )
+ && ( $classDeprecated == 0 || $docDeprecated ) ) {
+
+ # add class to list only if it is expected to be
+ # documented
+
+ addReference( $classNode->{"astNodeName"},
+ $classNode->{"astNodeName"}.".html" );
+
+ print "Added $class to tree\n" if $debug;
+
+ $rootNode->AddPropList( "classes", $classNode );
+
+ $filename =~ s/^\s+$//g;
+ $classAuthor =~ s/^\s+$//g;
+ $classVersion =~ s/^\s+$//g;
+ $classText =~ s/^\s+$//g;
+ $classSee =~ s/^\s+$//g;
+
+ $classNode->AddProp( "Author", $classAuthor );
+ $classNode->AddProp( "ClassSee", $classSee );
+ $classNode->AddProp( "ClassShort", $classShortText );
+ $classNode->AddProp( "Deprecated", $classDeprecated );
+ $classNode->AddProp( "Description", $classText );
+ $classNode->AddProp( "Header", $filename );
+ $classNode->AddProp( "Internal", $classInternal );
+ $classNode->AddProp( "TmplArgs", $classTmplArgs );
+ $classNode->AddProp( "Version", $classVersion );
+
+ }
+
+ resetClassDoc();
+
+ return;
+ }
+ elsif ( /^\s*public\s*:\s*$/ && $access ne "public" )
+ {
+ $access = "public";
+ }
+ elsif ( /^\s*protected\s*:\s*$/ && $access ne "protected" )
+ {
+ $access = "protected";
+ }
+ elsif ( /^\s*private\s*:\s*$/ && $access ne "private" )
+ {
+ $access = "private";
+ }
+ elsif ( /^\s*signals\s*:\s*$/ && $access ne "signals" )
+ {
+ $access = "signals";
+ }
+ elsif ( /^\s*protected\s+slots\s*:\s*$/ && $access ne "protected_slots" )
+ {
+ $access = "protected_slots";
+ }
+ elsif ( /^\s*public\s+slots\s*:\s*$/ && $access ne "public_slots" )
+ {
+ $access = "public_slots";
+ }
+ elsif ( /^\s*private\s+slots\s*:\s*$/ && $access ne "private_slots" )
+ {
+ $access = "private_slots";
+ }
+
+ #### Preprocessor directive
+
+ elsif( /^\s*#[\w\.-_]+/ ) {
+
+ print "CPP: $_\n" if $debug;
+
+ # skip lines carried on with \
+ while( /\\\s*$/ ) {
+ if( !($_ = <IN>) ) {
+ die "Bad Finish";
+ }
+ print "CPP: Skipped: $_" if $debug;
+ }
+ }
+
+ #### Typedef
+
+ elsif( /^\s*typedef\s+(.*[&\*\s])\s*([\w-:_]+)\s*(\[[^\]]*\])*;\s*$/ ) {
+ # 1 2 3 4
+ # 1: type name, possibly more than one
+ # 2: name of new type
+ # 3: possible array declaration(s)
+ # 4: anything else
+ print "TYPED: $2: $1\n" if $debug;
+
+ if( ( $methInternal == 0 || $docInternal)
+ && ($methDeprecated == 0 || $docDeprecated) ) {
+
+ addReference( $class."::".$2, $class.".html#".$2 );
+
+ $newNode = Ast::New( $2 );
+
+ $classNode->AddPropList( $access, $newNode );
+
+ $newNode->AddProp( "Keyword", "typedef" );
+ $newNode->AddProp( "Description", $text );
+ $newNode->AddProp( "See", $see );
+ $newNode->AddProp( "MethInternal", $methInternal );
+ $newNode->AddProp( "MethDeprecated", $methDeprecated );
+
+ $newNode->AddProp( "Type", $1 );
+ $newNode->AddProp( "Array", $3 );
+ }
+
+ resetMemberDoc();
+ }
+
+ #### Enum
+
+ elsif ( /^\s*enum\s+([\w_]*)\s*\{(.*)(\/\/.*)?/ )
+ {
+ $enum = $1;
+ $tmp = $2;
+ $args = "";
+
+ # collect constants till } is found
+
+ while ( !($tmp =~ /\}/) )
+ {
+ $args = $args . $tmp;
+ $tmp = <IN>;
+ }
+
+ $_ = $tmp;
+ /^(.*)\}/;
+ $args = $args . $1;
+
+
+ # update Ast node
+
+ if( ( !$methInternal || $docInternal)
+ && (!$methDeprecated || $docDeprecated) ) {
+
+ addReference( $class."::".$enum, $class.".html#".$enum );
+
+ $see =~ s/^\s*$//g;
+ $text =~ s/^\s*$//g;
+ $args =~ s/^\s*$//g;
+
+ $newNode = Ast::New( $enum );
+ $classNode->AddPropList( $access, $newNode );
+ $newNode->AddProp( "Keyword", "enum" );
+ $newNode->AddProp( "Description", $text );
+ $newNode->AddProp( "See", $see );
+ $newNode->AddProp( "Constants", $args );
+ $newNode->AddProp( "MethInternal", $methInternal );
+ $newNode->AddProp( "MethDeprecated", $methDeprecated );
+ }
+
+ resetMemberDoc();
+ }
+
+ #### parse out Q_OBJECT macro
+ elsif ( /^\s*Q_OBJECT[^\w]+(\/\/.*)?/ ) {
+ # dont do anything
+ }
+
+
+ #### Variables
+ elsif ( /^[^\(]*$/ && /^[\w_\:\s]+[\&\s*]+[\w_]+\s*(\[[^\]]*\])*\s*;\s*(\/\/.*)?$/ )
+ # 1 2 3 4 5 6
+ # 1: variable declarations have no ()
+ # 2: data type, possibly several words as in 'unsigned int'
+ # 3: reference pointer or at least a space before variable name
+ # 4: variable name
+ # 5: array declaration
+ # 6: spaces and or comments
+ {
+ $str = $_;
+
+ # split variable declaration:
+ # $1 = data type
+ # $2 = reference or pointer (why are there two \s's?)
+ # $3 = variable name
+ # $4 = array declaration
+ $str =~ /^(.+)([\s&\s\*])([\w_]+)\s*((\[[^\]]*\])*)\s*;\s*$/;
+ $var = $3;
+ $rest = $1.$2;
+ $array_declaration = $4;
+
+
+ if( ( !$methInternal || $docInternal)
+ && (!$methDeprecated || $docDeprecated) ) {
+
+ addReference( $class."::".$var, $class.".html#".$var );
+
+ $rest =~ s/^\s*$//g;
+ $see =~ s/^\s*$//g;
+ $text =~ s/^\s*$//g;
+
+ $newNode = Ast::New( $var );
+ $classNode->AddPropList( $access, $newNode );
+ $newNode->AddProp( "Keyword", "property" );
+ $newNode->AddProp( "Type", $rest );
+ $newNode->AddProp( "Array", $array_declaration);
+ $newNode->AddProp( "Description", $text );
+ $newNode->AddProp( "See", $see );
+ $newNode->AddProp( "MethInternal", $methInternal );
+ $newNode->AddProp( "MethDeprecated", $methDeprecated );
+ }
+
+ resetMemberDoc();
+ }
+
+
+ #### Nested class
+
+ elsif ( /^\s*(class|struct)/ ) {
+ # TODO: Implement nested classes
+ # Till then, find end of declaration
+ print "NESTED $_\n" if $debug;
+
+ if( !/;/ )
+ {
+# probably unterminated as yet
+ print "\nNESTED begin (for $methodName): $_\n"
+ if $debug == 1;
+ $foundMemberEnd = 0;
+ $lookingFor = ";";
+ $depth = 0;
+
+ while( $foundMemberEnd == 0 ) {
+
+ if( /\{/ ) {
+ $depth += countReg( $_, "\{" );
+ $lookingFor = "\}";
+ }
+
+ print "NESTED '$lookingFor': $_\n" if $debug == 1;
+
+ if ( /$lookingFor/ )
+ {
+ $depth -= countReg( $_, $lookingFor );
+
+ $foundMemberEnd = 1 if $depth <= 0;
+ }
+
+ if ($foundMemberEnd == 0 ) {
+ $_ = <IN>;
+ s#//.*$##g;
+ }
+ }
+ }
+ }
+ elsif ( m#^\s*///\s*(.*)# && $strictParser == 0 ) {
+ # DOC++ style "///" single-line member doccer
+ # will be used only if no other documentation exists.
+
+ resetMemberDoc();
+
+ $text = $1;
+
+ print "DOCXX-STYLE: $text\n" if $debug != 0;
+ }
+
+ elsif ( /^\s*\/\// )
+ {
+ # parse out comment
+ print "C++ comment: $_" if $debug != 0;
+ }
+
+ elsif ( /^\s*\/\*\*+\s*(.*)\*+\/\s*/ && $strictParser == 0 ) {
+ # single-line "/**..*/" type doc line
+ # not allowed by the spec but we'll let it pass
+ # if we're being lenient.
+
+ resetMemberDoc();
+
+ $text = $1;
+ print "ONELINE: $text\n" if $debug == 1;
+ }
+
+ elsif( /^\s*\/\*[^*]/ ) {
+ # (multiline) comment
+ while( !/\*\// ) {
+ # skip lines till we find its end
+ $_ = <IN>;
+ }
+ }
+
+ elsif ( /^\s*\/\*\*+\s*(.*)/ ) {
+ # member documentation begins
+ processMemberDoc();
+ }
+
+ #### Member Function
+
+ elsif ( /^\s*([^\(]*)\s+([^\s\(]+)\s*\((.*)(\/\/.*)?$/ )
+ {
+ processMethod( $1, $2, $3 );
+ }
+
+ }
+
+} # processClass
+
+sub processMethod {
+
+ my( $returnType, $methodName, $rest ) = @_;
+
+
+
+
+# ensure that everything after the operator keyword goes into the
+# member name and not the return type
+
+ if( $returnType =~ /operator/ ) {
+ $returnType =~ s/(operator.*)//g;
+ $methodName = $1." ".$methodName;
+ }
+
+# special case: if we have operator(), then the operator keyword got
+# matched into methodName, the first "(" was thrown away and $rest
+# contains ") (argumentlist)..."
+ if( ($methodName =~ /^operator$/) && ($rest =~ /^\)/) ) {
+ $methodName .= " ()";
+ $rest =~ s/^\)\s*\(//;
+ }
+
+# ensure that "*" is part of return type
+
+ if( $methodName =~ /^\s*([\*|\&]+)(.*)$/ ) {
+ $returnType = $returnType.$1;
+ $methodName = $2;
+ }
+
+## Read the parameters ($3 onward)
+
+ $params = "";
+
+ # Find end of params
+ while ( !($rest =~ /^[^)]*\)(.*)(\/\/.*)?$/) )
+ {
+ print "SEARCHING: $rest\n" if $debug == 1;
+ $params = $params . $rest;
+ ($rest = <IN>) =~ s#//.*$##g;
+ }
+
+ $rest =~ s#//.*$##g;
+ $_ = $rest;
+ /^([^\)]*)\)(.*)/;
+
+ # include all parameters before )
+ $params .= $1;
+ my($restOfLine) = $2;
+
+ my($constness) = "";
+
+ if( $restOfLine =~ /^\s*const/ ) {
+ $constness = "const";
+ }
+
+# need to skip inline function if it is there, or if the
+# end of declaration is staggered for some other reason.
+
+ if( ! /\)[\s\w=]*;/ )
+ {
+# probably unterminated as yet
+ print "\nINLINE begin (for $methodName): $_\n" if $debug == 1;
+
+ $_ = $rest;
+ $foundMemberEnd = 0;
+ $lookingFor = ";";
+ $depth = 0;
+
+ while( $foundMemberEnd == 0 ) {
+
+ if( /\{/ ) {
+ $depth += countReg( $_, "\{" );
+ $lookingFor = "\}";
+ }
+
+ print "INLINE '$lookingFor': $_\n" if $debug == 1;
+
+ if ( /$lookingFor/ )
+ {
+ $depth -= countReg( $_, $lookingFor );
+
+ $foundMemberEnd = 1 if $depth <= 0;
+ }
+
+ if ($foundMemberEnd == 0 ) {
+ $_ = <IN>;
+ s#//.*$##g;
+ }
+ }
+ }
+
+ # Register if not internal or deprecated
+
+ if( ( !$methInternal || $docInternal)
+ && (!$methDeprecated || $docDeprecated) ) {
+
+ $returnType =~ s/^\s*$//g;
+ $see =~ s/^\s*$//g;
+ $text =~ s/^\s*$//g;
+ $retText =~ s/^\s*$//g;
+ $params =~ s/^\s*$//g;
+ $constness =~ s/^\s*$//g;
+
+ addReference( $class."::".$methodName, $class.".html#".$methodName );
+
+ $newNode = Ast::New( $methodName );
+ $classNode->AddPropList( $access, $newNode );
+
+ $newNode->AddProp( "ReturnType", $returnType );
+ $newNode->AddProp( "Const", $constness );
+ $newNode->AddProp( "Parameters", $params );
+ $newNode->AddProp( "Keyword", "method" );
+ $newNode->AddProp( "Description", $text );
+ $newNode->AddProp( "Returns", $retText );
+ $newNode->AddProp( "See", $see );
+ $newNode->AddProp( "Exceptions", $exceptions );
+ $newNode->AddProp( "MethInternal", $methInternal );
+ $newNode->AddProp( "MethDeprecated", $methDeprecated );
+
+ foreach $param ( keys %paramDesc ) {
+ $paramNode = Ast::New( $param );
+ ($desc = $paramDesc{$param}) =~ s/^\s*$//g;
+ $paramNode->AddProp("Description", $desc );
+
+ $newNode->AddPropList( "ParamDoc", $paramNode );
+ }
+ }
+
+ resetMemberDoc();
+} # processMethod
+
+#
+# Processes a doc comment
+#
+
+sub processMemberDoc
+{
+ my( $endDocBlock ) = 0;
+ my( $paramFlag ) = 0;
+ my( $retFlag ) = 0;
+
+ resetMemberDoc();
+
+ $lastLineBlank = 0;
+
+# allow documentation on first line only if
+# we're being lenient.
+
+ if( $strictParser == 0 ) {
+ $text = $1;
+ }
+ else {
+ $text = "";
+ }
+
+ $endDocBlock = 0;
+
+ while ( $endDocBlock == 0 ) {
+ $_ = <IN>;
+ $line = $_;
+
+ if ( $paramFlag == 1 ) {
+
+ if ( /^\s*\**\s*\@/ || /^\s*\**\s*\*\// ) {
+#parameter ends.
+ $paramDesc{ $paramName } = $paramText;
+ $paramFlag = 0;
+ }
+ else {
+ /^\s*\**(.*)$/;
+ $paramText .= $1."\n";
+ $_ = "";
+ }
+ }
+ elsif ( $retFlag == 1 ) {
+ if ( /^\s*\**\s*\@/ || /^\s*\**\s*\*\// ) {
+ $retFlag = 0;
+ }
+ else {
+ /^\s*\*+(.*)$/;
+ $retText .= "\n$1";
+ $_ = "";
+ }
+ }
+
+ if ( /^\s*(.*)\*+\// ) {
+# end of member documentation
+ $endDocBlock = 1;
+ }
+ elsif ( /^(.*)\*+\/\s*$/ && ($strictParser == 0) ) {
+# end of member documentation, with extraneous
+# space before end tag
+# only used if we're being lenient.
+
+ $text = $text . $_ . '\n';
+
+ $endDocBlock = 1;
+
+ print "BAD MEMBER END: $_\n" if $debug == 1;
+ }
+ elsif ( /^\s*\**\s*\@param\s+([^\s]+)\s(.*)$/ ) {
+# "@param"
+ $paramName = $1;
+ $paramText = $2;
+
+ $paramFlag = 1;
+ }
+ elsif ( /^\s*\**\s*\@return\s+(.*)/ ) {
+# "@return"
+
+ $retText = $1;
+ $retFlag = 1;
+ }
+ elsif( /^\s*\**\s*\@internal/ ) {
+# "@internal"
+ $methInternal = 1;
+ }
+ elsif( /^\s*\**\s*\@deprecated/ ) {
+# "@deprecated"
+ $methDeprecated = 1;
+ }
+ elsif ( /^\s*\**\s*\@exception\s+([:#\w_~]+)/ ) {
+# "@exception"
+ $exceptions .= $1;
+ }
+ elsif ( /^\s*\**\s*\@see\s+([:#\w_~]+)/ ) {
+# "@see"
+ $see .= ", " if $see ne "";
+
+ $c = $1;
+ $see .= $c;
+ }
+ elsif( /^\s*\**\s*\@(short|author|version)/ ) {
+# ignore tags that cannot exist in
+# member doc
+ }
+ elsif ( /^\s*\**\s*(.*)$/ ) {
+# normal member documentation text,
+# " * blah blah"
+ $text = $text. $1 . "\n";
+ } # if
+ } # while still in doc block
+} # processMemberDoc
+
+###########################################################
+#
+# Function
+# processFile #
+###########################################################
+
+sub processFile
+{
+ while ( <IN> )
+ {
+ $line = $_;
+
+ next if /^\s*$/;
+
+ if( m#^\s*/\*[^*]# ) {
+# skip multiline comment started with /* (but only one asterisk!)
+ while( !/\*\// ) {
+ $_ = <IN>;
+ }
+ }
+ elsif ( m#^\s*/\*\*+\s*(.*)\*/\s*# && ($strictParser == 0) ) {
+ # single-line "/**..*/" type doc line
+ # not allowed by the spec but we'll let it pass
+ # if we're being lenient.
+ resetMemberDoc();
+ $classText = $1;
+ $classShortText = $1;
+ print "ONELINE classdoc: $text\n" if $debug == 1;
+ }
+ elsif( /^\s*#[\w\.-_]+/ ) {
+ #### Preprocessor directive
+ print "CPP: $_\n" if $debug;
+
+ # skip lines carried on with \
+ while( /\\\s*$/ ) {
+ if( !($_ = <IN>) ) {
+ die "Bad Finish";
+ }
+ print "CPP: Skipped: $_" if $debug;
+ }
+ }
+ elsif ( /^\s*\/\*\*+\s*(.*)$/ )
+ {
+ # start of class doc comment
+ $classSee = "";
+ $classText = "";
+ $classShortText = "";
+ $lastLineBlank = 0;
+
+ $classText = $1 if( $strictParser == 0 );
+
+ $end = 0;
+ while ( $end == 0 )
+ {
+ $_ = <IN>;
+ $line = $_;
+
+ if ( /^\s*\*\// )
+ {
+ # end of documentation, assume class
+ # declaration is next.
+ $end = 1;
+ }
+ elsif ( /^(.*)\*+\/\s*$/ && ($strictParser == 0) )
+ {
+ # end of class documentation, with extraneous
+ # space before end tag
+ # only used if we are being lenient.
+
+ $text = $text . $1 . '\n';
+
+ $end = 1;
+
+ print "BAD CLASSDOC END: $_\n" if $debug == 1;
+ }
+ elsif ( /^\s*\**\s*\@see\s+([#\w_~]+)/ )
+ {
+ # @see
+ if ( $classSee ne "" )
+ {
+ $classSee .= ", ";
+ }
+ $c = $1;
+ $classSee .= $c;
+ }
+ elsif ( /^\s*\*?\s*\@author\s+(.*)/ )
+ {
+ # @author
+ $classAuthor .= $1 . " ";
+ }
+ elsif ( /^\s*\**\s*\@version\s+(.*)/ )
+ {
+ # @version
+ $classVersion .= $1 . " ";
+ }
+ elsif ( /^\s*\**\s*\@short\s+(.*)/ )
+ {
+ # @short
+ $classShortText .= $1 . " ";
+ }
+ elsif ( /^\s*\**\s*\@deprecated/ )
+ {
+ # @deprecated
+ $classDeprecated = 1;
+ }
+ elsif ( /^\s*\**\s*\@internal/ )
+ {
+ # @internal
+ $classInternal = 1;
+ }
+ elsif ( /^\s*\**(.*)$/ )
+ {
+ # normal documentation text
+ $lead = $1;
+
+ # check for asterisk
+ if ( /^\s*\*+/ ) {
+ $classText .= $lead. "\n";
+ }
+ else {
+ # preserve leading space.
+ $classText .= $_. "\n";
+ }
+ }
+ }
+ $_ = <IN>;
+ $line = $_;
+
+ } # documentation if
+
+ if ( /^(\s*template\s*<(([-\w,_\s]|<([-\w,+\s])+>)+)>)/ ) {
+ $classTmplArgs = $2;
+
+ ($resetme = $1);
+ $resetme =~ s/([\W])/\\$1/g;
+
+ s/$resetme//g;
+ }
+
+ if ( !(/;/) && /^\s*(class|struct)\s+([-\w_]+)(.*)$/ )
+ {
+
+# class declaration begins.
+
+ #TODO: skip class if it doesn't have documentation
+ #and we aren't documenting NULL classes.
+
+ $class = $2;
+ ($classInherits = $3) =~ s#//.*##g;
+
+ # handle template-instantiation class
+ if($classInherits =~
+ /^\s*(<([-\w,_\s]|<([-\w,+\s])+>)+>)/) {
+ $class .= $1;
+ $class =~ s/\s+//g;
+ }
+
+ $classInherits =~ s/<([-\w,_\s]|<([-\w,+\s])+>)+>//g;
+
+ print "\n $class " unless $quiet;
+
+# set default visibility
+ if( $1 eq "class" ) {
+ $access = "private";
+ } else {
+ $access = "public";
+ }
+
+# process everything in the class
+ processClass();
+ }
+
+ } # outer file while
+
+ close( IN );
+}
+
+#
+#
+#
+
+sub addReference
+{
+ my( $target, $pointer) = @_;
+
+ print KDOC $target."=".$pointer."\n";
+ $classRef{ $target } = $pointer;
+}
+
+# Reset the documentation variables for a class member.
+
+sub resetMemberDoc
+{
+ $exceptions = "";
+ %paramDesc = ();
+ $paramName = "";
+ $paramText = "";
+ $retText = "";
+ $see = "";
+ $text = "";
+ $methInternal = 0;
+ $methDeprecated=0;
+}
+
+#
+# Reset the documentation variables for a class.
+#
+sub resetClassDoc
+{
+ $classAuthor = "";
+ $classDeprecated= 0;
+ $classInternal = 0;
+ $classSee = "";
+ $classShortText = "";
+ $classShortTextSet = 0;
+ $classTmplArgs = "";
+ $classAbstract = 0;
+ $classText = "";
+ $classVersion = "";
+}
+
+# Counts the number of times a regular expression occurs in a string
+
+sub countReg
+{
+ my( $str, $regexp ) = @_;
+ my( $count ) = 0;
+
+ while( $str =~ /$regexp/ ) {
+ $count++;
+
+ $str =~ s/$regexp//;
+ }
+
+ return $count;
+}
+
+#
+# Display usage and quit with an error code.
+#
+
+sub usage
+{
+die<<EOF;
+
+KDOC: The KDE Class Documentation Tool for C++, $version
+ Torben Weis <weis\@kde.org>, Sirtaj Kang <taj\@kde.org>
+
+Usage:
+ kdoc [-a] [-M][-H][-T] [-a][-e][-i][-p][-q] [-L<lib-path>]
+ [-d<outdir>] [-u <base URL>] <library> <header>...
+ [-l<lib> ... ]
+
+ -T Generate LaTeX documentation.
+ -M Generate man pages.
+
+ -H Generate HTML documentation (default).
+ -d<dir> Directory for HTML and LaTeX output.
+ -u<url> Base path/url by which this library will be accessed.
+
+ -a Document methods/classes without explicit doc comment.
+ -e Skip deprecated methods and classes (\@deprecated tag)
+ -i Skip classes marked internal (\@internal tag)
+ -p Document private members.
+ -q Proceed quietly (display errors only)
+
+ -L<dir> Path to kdoc libraries. Default is current dir, or
+ \$KDOCLIBS if it is set.
+
+ <library> The name of the kdoc library to create.
+ <headers> C++ headers to process.
+
+ -l<lib> Cross reference these libraries.
+EOF
+}
+
+sub bumpArg
+{
+ return $1 if $1 ne "";
+ my($real);
+
+ $i = $i + 1;
+
+ $real = $myargs[ $i ];
+ $myargs[ $i ] = "-".$myargs[ $i ];
+
+
+ return $real;
+}
+
+
+#
+# Calls dumpDoc for each format for which output was requested.
+#
+
+sub generateDocs
+{
+
+ if( $genHTML == 0 && $genTeX == 0 && $genMan == 0)
+ {
+ $genHTML = 1;
+ require kdocHTML;
+ }
+
+ if( $genHTML != 0 ) {
+ kdocHTML::dumpDoc( $name, $rootNode, $docPath );
+ }
+
+ if( $genTeX != 0 ) {
+ kdocTeX::dumpDoc( $name, $rootNode, $docPath );
+ }
+
+ if( $genMan != 0 ) {
+ kdocMan::dumpDoc( $name, $rootNode, $docPath );
+ }
+
+ print "Done.\n" unless $quiet;
+}
+
+###########################################################
+#
+# Main
+#
+###########################################################
+
+if ( $#ARGV == -1 )
+{
+ die "kdoc: No arguments. Type 'kdoc -h' for help.\n";
+}
+
+#
+# process switches and args #
+#
+
+$libFoundAt = -1;
+
+$i = 0;
+
+while( $i <=$#myargs )
+{
+ $filename = $myargs[ $i ];
+ if ( $filename =~ /^-d(.*)$/ ) {
+
+ $docPath = bumpArg();
+ }
+ elsif ( $filename =~ /^-u(.*)$/ ) {
+ $urlBase= bumpArg();
+ }
+ elsif ( $filename =~ /^-L(.*)$/ ) {
+ $libPath = bumpArg();
+ }
+ elsif ( $filename =~ /^-l(.*)$/ ) {
+ readLibrary( bumpArg() );
+ }
+ elsif ( $filename =~ /^-a/ ) {
+ $documentAll = 1;
+ }
+ elsif ( $filename =~ /^-M/ ) {
+ $genMan = 1;
+ require kdocMan;
+ }
+ elsif ( $filename =~ /^-T/ ) {
+ $genTeX = 1;
+ require kdocTeX;
+ }
+ elsif ( $filename =~ /^-H/ ) {
+ $genHTML = 1;
+ require kdocHTML;
+ }
+ elsif ( $filename =~ /^-e/ ) {
+ $docDeprecated = 0;
+ }
+ elsif ( $filename =~ /^-D/ ) {
+ $debug = 1;
+ }
+ elsif ( $filename =~ /^-i/ ) {
+ $docInternal = 0;
+ }
+ elsif ( $filename =~ /^-p/ ) {
+ $dontDoPrivate = 0;
+ }
+ elsif ( $filename =~ /^-q/ ) {
+ $quiet = 1;
+ }
+ elsif( $filename =~ /^-v(.*)/ ) {
+ die "kdoc: $version (c) Torben Weis, Sirtaj S. Kang\n";
+ }
+ elsif( $filename =~ /^-h/ || $filename =~ /^--help/ )
+ {
+ usage();
+ }
+ elsif( $filename =~ /^-(.*)/ ) {
+ die "kdoc: -$1 is an unsupported option. Type kdoc -h for help.\n";
+ }
+ elsif( $lib eq "" ) {
+ $lib = $filename;
+ $libFoundAt = $i;
+ }
+
+ $i = $i + 1;
+}
+
+$urlBase = $docPath if $urlBase eq "";
+
+usage() if $lib eq "";
+
+#parse out path name for printed libName
+( $name = $lib ) =~ s#.*/##g;
+
+$lib = $libPath."/".$lib.".kdoc";
+
+open( KDOC, ">$lib" ) || die "Could not open $lib for writing\n";
+print KDOC "$urlBase\n";
+
+
+# check document output path
+
+if( !(-d $docPath))
+{
+ if( system("mkdir $docPath") ) {
+ close ( KDOC );
+ unlink( $lib );
+ die "Document path '$docPath' doesn't exist and it couldn't\n".
+ "be created.\n";
+ }
+}
+
+#
+# process each file
+#
+
+foreach $i (0..$#myargs)
+{
+ $filename = $myargs[ $i ];
+ if ( $filename =~ /^-(.*)$/ )
+ {
+#option... don't process
+ }
+ elsif( $i != $libFoundAt )
+ {
+ print "Processing $filename:" unless $quiet;
+ push( @headerList, $filename );
+ open( IN, $filename ) || die "Could not open $filename for input\n";
+
+ processFile();
+
+ print "\n" unless $quiet;
+
+ close( IN );
+ }
+}
+
+
+close( KDOC );
+
+# reparent all parentless classes to root.
+
+$rootNode->Visit("main");
+
+if( defined $classes ) {
+
+ foreach $class ( @{$classes} )
+ {
+ $className = $class->{"astNodeName"};
+
+ if ( !defined $parents{ $parents{$className} }) {
+ addClass( "<>", $parents{$className} );
+ }
+ }
+}
+
+Ast::UnVisit();
+
+generateDocs();
+
+# file ends
--- /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 kdocHTML;
+
+## KDOC HTML output
+#
+# From main:
+# children classRef classSource dontDoPrivate
+# generatedByText headerList quiet
+
+require Ast;
+
+BEGIN
+{
+ $lib = "";
+ $outputdir = ".";
+ $linkRef = 0;
+ $modname = "kdocHTML";
+ %classList = ();
+}
+
+
+sub dumpDoc
+{
+ $genText = $main::generatedByText;
+
+ ($lib, $root, $outputdir) = @_;
+
+ print "Generating HTML documentation.\n" unless $main::quiet;
+ writeList();
+ writeHier();
+ writeHeaderList();
+
+ print "Generating HTMLized headers.\n" unless $main::quiet;
+ foreach $header ( @main::headerList ) {
+ markupCxxHeader( $header );
+ }
+}
+
+sub writeHeaderList
+{
+
+ open(HDRIDX, ">$outputdir/header-list.html")
+ || die "Couldn't create $outputdir/header-list.html\n";
+
+ print HDRIDX<<EOF;
+<HTML><HEAD><TITLE>$lib Header Index</TITLE></HEAD><BODY bgcolor="#ffffff">
+ <H1>$lib Header Index</H1>
+<p>
+[<A HREF="index.html">Index</A>] [<A HREF="hier.html">Hierarchy</A>] [Headers]
+</p>
+<HR>
+<UL>
+EOF
+
+ foreach $header ( sort @main::headerList ) {
+ $_ = $header;
+# convert dashes to double dash, convert path to dash
+ s/-/--g/g;
+ s/\/|\./-/g;
+
+ # never let a file name start with a '-' sign, since this makes
+ # some programs think the file name really was a parameter to the
+ # program. Filenames starting with '-' usually happen if you let
+ # kdoc work on files like '../../include/foo/bar.h', given the
+ # above substitution rules. Therefore: if a filename starts with
+ # '-', prepend a '_'
+ s/^-/_-/;
+
+ print HDRIDX "\t<LI><A HREF=\"$_.html\">$header</A></LI>\n";
+ }
+print HDRIDX "</UL>\n<HR>\n<address>$genText",
+ "</address>\n</BODY>\n</HTML>\n";
+}
+
+sub escape
+{
+ my( $str ) = @_;
+
+ $str =~ s/&/\&/g;
+ $str =~ s/</\</g;
+ $str =~ s/>/\>/g;
+ $str =~ s/"/\"/g;
+
+ return $str;
+}
+
+# In file names, we don't want to have the special characters be
+# replaced by the rules '>' -> '>' etc., so we revert the
+# replacement. The reason is that when giving Netscape the tag
+# <a href="abc<2>.html"> xyz </a>, it looks for the file
+# "abc<2>.html". Strange, eh? We'd like to replace filenames
+# back to the original names, which is not a good idea also, since
+# filenames containing <>&" are no good. Therefore, we stay with
+# the HTML tags, but replace the '&' and ';' by ',' which should
+# not be a character which appears in class and file names, but
+# which has no special meaning for the shell either.
+sub filenameUnescape
+{
+ my( $str ) = @_;
+
+ $str =~ s/\&/,amp,/g;
+ $str =~ s/\</,lt,/g;
+ $str =~ s/\>/,gt,/g;
+ $str =~ s/\"/,quot,/g;
+
+ return $str;
+}
+
+sub writeList()
+{
+
+ $root->Visit( $modname );
+
+ foreach $class ( @{$classes} )
+ {
+ $classList{ $class->{'astNodeName'} } = $class;
+ }
+
+ open ( LIBIDX, ">".$outputdir."/index.html" )
+ || die "Couldn't write to ".$outputdir."/index.html" ;
+
+ print LIBIDX<<EOF;
+<HTML><HEAD><TITLE>$lib Class Index</TITLE></HEAD><BODY bgcolor="#ffffff">
+ <H1>$lib Class Index</H1>
+<p>
+[Index] [<A HREF="hier.html">Hierarchy</A>] [<A HREF="header-list.html">Headers</A>]
+</p>
+<HR>
+<TABLE BORDER="0" WIDTH="100%">
+EOF
+
+ foreach $className ( sort keys %classList ) {
+ $class = $classList { $className };
+
+ $class->Visit( $modname );
+
+ $className = $astNodeName;
+
+ # escape special characters in class names (e.g. <>&)
+ # however, we need to unescape them when using the
+ # class name as a file name
+ $astNodeName = escape( $astNodeName );
+
+ print LIBIDX "<TR><TD ALIGN=\"LEFT\" VALIGN=\"TOP\">",
+ "<a href=\"", filenameUnescape($astNodeName), ".html\">",
+ $astNodeName, "</a></TD>\n", "\t<TD>",
+ makeReferencedText( $ClassShort ), "</TD></TR>\n";
+
+ writeClass();
+
+ Ast::UnVisit();
+
+ }
+
+ Ast::UnVisit();
+
+print LIBIDX<<EOF;
+</TABLE>
+<HR>
+<TABLE WIDTH="100%" BORDER="0">
+<TR>
+<TD ALIGN="LEFT" VALIGN="TOP"><address>$genText</address></TD>
+<TD ALIGN="RIGHT" VALIGN="TOP">
+<b>K</b><i>doc</i>
+</TD>
+</TR>
+</TABLE>
+</BODY></HTML>
+EOF
+
+}
+
+###########################################################
+#
+# Function
+# makeReferencedText( text )
+#
+###########################################################
+
+sub makeReferencedText
+{
+ local( $t ) = @_;
+
+ while ( $t =~ /(\@ref\s+)([\w_\#~\d\:]+\W)/ )
+ {##
+ $pat = $1.$2;
+ $ref = $2;
+ chop $ref;
+ $repl = findClassReference( $ref ) . " ";
+ $pat =~ s/\(/\\(/g;
+ $pat =~ s/\)/\\)/g;
+ $t =~ s/$pat/$repl/;
+ }
+
+ $t =~ s/</</g;
+ $t =~ s/>/>/g;
+ $t =~ s/<\/p><p>/<\/p><p>/g;
+ $t =~ s/\#([^\#]*)\#/<CODE>$1<\/CODE>/g;
+ $t =~ s/\\begin\{verbatim\}/<pre>/g;
+ $t =~ s/\\end\{verbatim\}/<\/pre>/g;
+ $t =~ s/\\begin\{itemize\}/<UL>/g;
+ $t =~ s/\\end\{itemize\}/<\/UL>/g;
+ $t =~ s/\\item/<LI>/g;
+ $t =~ s/\{\\bf([^}]*)}/<b>$1<\/b>/g;
+ $t =~ s/\\section\{([^}]*)\}/<H3>$1<\/H3>/g;
+ $t =~ s/\\subsection\{([^}]*)\}/<H4>$1<\/H4>/g;
+ $t =~ s/\\subsubsection\{([^}]*)\}/<H5>$1<\/H5>/g;
+
+ return $t;
+}
+
+###########################################################
+#
+# Function
+# findClassReference( class )
+#
+###########################################################
+
+sub findClassReference
+{
+ my( $c ) = @_;
+ my( $old );
+
+
+ if ( $c eq "" ) { return ""; }
+ if ( $c eq "#" ) { return "#"; }
+
+ $c =~ s/\#/::/g;
+
+ $old = $c;
+
+ if ( $c =~ /^\s*(\#|::)(.*)$/ )
+ {
+ $c = "$className\:\:$2";
+ $pref = $1;
+ $old =~ s/$pref//;
+ }
+
+ if ( !defined $main::classRef{ $c } )
+ {
+ if ( !defined $main::noErr{ $c } )
+ {
+# print main::ERROUT "$filename: '$c' undefined Reference\n\n";
+ }
+ return $c;
+ }
+ else
+ {
+ if ( $c =~ /\:\:/ )
+ {
+ return "<a href=\"".escape($main::classRef{ $c })."\">".
+ escape($old)."</a>";
+ }
+ else
+ {
+ return "<a href=\"".escape($main::classRef{ $c })."\">".
+ escape($c)."</a>";
+ }
+ }
+}
+
+#############
+#
+# writeHier -- Write HTML Class Hierarchy
+#
+#############
+
+sub writeHier
+{
+
+open( HIER, ">".$outputdir."/hier.html" )
+ ||die "Cannot write to $outputdir/hier.html";
+
+print HIER <<EOF;
+<HTML><HEAD><TITLE>$lib Class Hierarchy</TITLE></HEAD>
+<BODY BGCOLOR="#ffffff">
+<H1>$lib Class Hierarchy</H1>
+<p>
+[<A HREF="index.html">Index</A>] [Hierarchy] [<A HREF="header-list.html">Headers</A>]
+</p>
+<HR>
+EOF
+
+printHierarchy( "<>" );
+
+print HIER<<EOF;
+<HR>
+<TABLE WIDTH="100%" BORDER="0">
+<TR>
+<TD ALIGN="LEFT" VALIGN="TOP"><address>$genText</address></TD>
+<TD ALIGN="RIGHT" VALIGN="TOP">
+<b>K</b><i>doc</i>
+</TD>
+</TR>
+</TABLE>
+</BODY></HTML>
+EOF
+
+### here we are!!
+ # build a list of parents and children for each class
+ # use it to generate a tree of classes suitable for
+ # a tree view of the inheritance lattice
+
+ # we may not use the %classList for the children information
+ # since some classes are parents but not in %classList (those
+ # classes that are found as base classes but are not documented
+ # within this module
+# my (%kids);
+# my (%parents);
+# my (%classLevel);
+# my ($classNames);
+#
+# foreach $className (keys %main::children)
+# {
+# $kids{$className} = $main::children{$className};
+# }
+#
+# foreach $className (keys %kids)
+# {
+# foreach $c (split /;/, $main::children{$className})
+# {
+# $parents{$c} = $parents{$c} . $className . ";"
+# if !($className eq "<>");
+# }
+# }
+#
+# # build a list of all class names, irrespective of whether
+# # they are documented or not.
+# foreach $class (keys %kids, keys %parents, keys %classList)
+# {
+# $classNames = $classNames . $class . ";"
+# if (! ($classNames =~ /$class;/) &&
+# ! ($class eq "<>"));
+# }
+#
+#
+# # now evaluate the list to get the proper hierarchy level
+# # for each class. Loop until all classes are processed,
+# # which may take some iterations since a class can only
+# # be processed if all of its parents have been processed
+# my ($unprocessedClasses);
+# my ($classLevel);
+# my ($maxParentLevel);
+# $unprocessedClasses = 1;
+# while ($unprocessedClasses == 1)
+# {
+# $unprocessedClasses = 0;
+# foreach $class (split /;/, $classNames)
+# {
+# if (! defined $classLevel{$class})
+# {
+# # if class has no children or no parents: assign
+# # level zero. for classes with no parents, this
+# # decision may later be revised
+# if ((! $parents{$class}) ||
+# (! defined $parents{$class}))
+# {
+# $classLevel{$class} = 0;
+# }
+# else
+# {
+# foreach $parent (split /;/, $parents{$class})
+# {
+# # find the maximum level any of the
+# # children has
+# $maxParentLevel = 0;
+#
+# # if the parent has not been processed,
+# # then don't do so for this class also
+# if (! defined $classLevel{$parent})
+# {
+# $unprocessedClasses = 1;
+# last;
+# }
+# else
+# {
+# if ($classLevel{$parent} > $maxParentLevel)
+# {
+# $maxParentLevel = $classLevel{$parent};
+# }
+# }
+# $classLevel{$class} = $maxParentLevel+1;
+# }
+# }
+# }
+# }
+# }
+#
+#
+# foreach $class (sort split /;/, $classNames )
+# {
+# print "--> ", $class, ": $classLevel{$class} <c=", $kids{$class}, "><p=",
+# $parents{$class}, ">\n";
+#
+# }
+}
+
+
+######
+#
+# Dump the hierarchy for a particular class
+#
+######
+
+sub printHierarchy
+{
+ my( $className ) = @_;
+
+ print HIER "\t<LI>", findClassReference($className),"\n"
+ if $className ne "<>";
+
+ if( defined $main::classSource{ $className } ) {
+ print HIER "<small> (",$main::classSource{$className},")</small>\n";
+ }
+
+ if ( defined $main::children{$className} ) {
+
+ print HIER "\t<UL>\n";
+
+ foreach $kid ( sort split /;/, $main::children{$className} )
+ {
+ printHierarchy( $kid );
+ }
+ print HIER "\t</UL>\n";
+ }
+
+ print HIER "\t</LI>" if $className ne "<>";
+}
+
+# #############
+#
+# Write out the documentation for a single class.
+#
+# #############
+
+sub writeClass()
+{
+ open( CLASS, ">" .
+ $outputdir."/".filenameUnescape($astNodeName) .
+ ".html"
+ ) || die "Couldn't write to file " .
+ $outputdir."/".filenameUnescape($astNodeName).".html";
+
+ print CLASS<<EOF;
+<HTML><HEAD><TITLE>$astNodeName Class</TITLE></HEAD>
+<BODY bgcolor="#ffffff\">\n
+<H1>$astNodeName Class Reference</H1>
+<p>
+[<A HREF="index.html">$lib Index</A>] [<A HREF="hier.html">$lib Hierarchy</A>]
+[<A HREF="header-list.html">Headers</A>]
+</p>
+<HR>
+EOF
+
+ print CLASS "<h3>This class is Deprecated.</h3>\n" if $Deprecated;
+ print CLASS "<h3>Internal class - general use not recommended.</h3>\n"
+ if $Internal;
+
+ print CLASS "<P>", makeReferencedText( $ClassShort ),
+ " <a href=\"#short\">More...</a></P>\n"
+ if $ClassShort ne "";
+
+ $_ = $Header;
+ s/-/--/g;
+ s/\/|\./-/g;
+
+ # never let a file name start with a '-' sign, since this makes
+ # some programs think the file name really was a parameter to the
+ # program. Filenames starting with '-' usually happen if you let
+ # kdoc work on files like '../../include/foo/bar.h', given the
+ # above substitution rules. Therefore: if a filename starts with
+ # '-', prepend a '_'
+ s/^-/_-/;
+
+ $escapedpath = $_;
+
+# include file
+
+ print CLASS<<EOF;
+<P>
+<code>
+ #include <<a href=\"$escapedpath.html\">$Header</a>>
+</code>\n
+</P>
+EOF
+
+
+# Template
+
+ if( $class->{ "TmplArgs" } ne "" ) {
+
+ print CLASS "\n<p>Template Form: <code>",
+ "template < ", escape( $class->{ "TmplArgs" }),
+ " > $astNodeName</code> </p>\n";
+ }
+
+# Inheritance
+ my ( $pcount ) = 0;
+
+ if( defined $class->{ "Ancestors" } ) {
+ print CLASS "\n<P>\nInherits: ";
+
+ foreach $foreparent ( @{$Ancestors} ) {
+ print CLASS ", " if $pcount != 0;
+ $pcount = 1;
+
+ print CLASS findClassReference(
+ $foreparent->{"astNodeName"} );
+
+ if( defined $main::classSource{$foreparent->{
+ "astNodeName"}} ) {
+ print CLASS " (",$main::classSource{
+ $foreparent->{"astNodeName"}},")";
+ }
+ }
+
+ print CLASS "\n<\P>";
+ }
+
+# Now list members.
+
+ $linkRef = 0;
+
+ listMethods( "Public Members", $public );
+ listMethods( "Public Slots", $public_slots );
+ listMethods( "Protected Members", $protected );
+ listMethods( "Protected Slots", $protected_slots );
+ listMethods( "Signals", $signals );
+
+ if( $main::dontDoPrivate == 0 ) {
+ listMethods( "Private Members", $private );
+ listMethods( "Private Slots", $private_slots );
+ }
+print CLASS<<EOF;
+<HR>
+EOF
+
+# Dump Description.
+ Ast::UnVisit();
+ $class->Visit($modname);
+ writeClassDescription();
+
+# Document members.
+
+ $linkRef = 0;
+
+ writeMemberDoc( "public", $public );
+ writeMemberDoc( "public slot", $public_slots );
+ writeMemberDoc( "protected", $protected );
+ writeMemberDoc( "protected slot", $protected_slots );
+ writeMemberDoc( "signal", $signals );
+
+ if( $main::dontDoPrivate == 0 ) {
+ writeMemberDoc( "private", $private );
+ writeMemberDoc( "private slot", $private_slots );
+ }
+
+# File Generation info
+ print CLASS "<HR>\n<TABLE WIDTH=\"100%\">",
+ "<TR><TD ALIGN=\"left\" VALIGN=\"top\">\n";
+
+ if( $Author ne "" || $Version ne "" ) {
+ print CLASS "\n<UL>";
+
+ print CLASS "<LI><I>Author</I>: ", escape($Author), "</LI>\n"
+ if $Author ne "";
+
+ print CLASS "<LI><I>Version</I>: ", escape($Version), "</LI>\n"
+ if $Version ne "";
+ print CLASS "<LI>$genText</LI>\n";
+
+ print CLASS "</UL>";
+ } else {
+ print CLASS "<address>$genText<address>\n";
+ }
+
+ print CLASS<<EOF;
+</TD><TD ALIGN="RIGHT" VALIGN="TOP">
+<b>K</b><i>doc</i>
+</TD>
+</TR></TABLE></BODY></HTML>\n
+EOF
+
+}
+
+######
+# Lists all methods of a particular visibility.
+#####
+
+sub listMethods()
+{
+ my( $desc, $members ) = @_;
+
+ return if !defined $members || $#{$members} == -1;
+
+print CLASS<<EOF;
+
+<H2>$desc</H2>
+<UL>
+EOF
+
+ foreach $member ( @{$members} ) {
+ $member->Visit($modname);
+
+ print CLASS "<LI>";
+
+ if( $Description eq "" && $See eq "" ) {
+ $link = "name=\"";
+ } else {
+ $link = "href=\"\#";
+ }
+
+ if( $Keyword eq "property" ) {
+ print CLASS escape($Type),
+ "<b><a ",$link,"ref$linkRef\">",
+ escape($astNodeName), "</a></b>",
+ escape($Array),
+ "\n";
+ }
+ elsif( $Keyword eq "method" ) {
+ print CLASS escape($ReturnType),
+ " <b><a ", $link, "ref$linkRef\">",
+ escape($astNodeName), "</a></b> (",
+ escape($Parameters),
+ ") ",$Const,"\n";
+ }
+ elsif( $Keyword eq "enum" ) {
+ print CLASS "enum <b><a ", $link, "ref$linkRef\">",
+ escape($astNodeName),"</a></b> {",
+ escape($Constants),"}\n";
+ }
+ elsif( $Keyword eq "typedef" ) {
+ print CLASS "typedef ", escape($Type), " <b><a ", $link,
+ "ref$linkRef\">", escape($astNodeName),
+ "</a>", escape($Array), "</b>";
+ }
+
+ print CLASS "</LI>\n";
+
+ $linkRef += 1;
+
+ Ast::UnVisit();
+ }
+
+print CLASS<<EOF;
+</UL>
+EOF
+
+}
+
+sub writeClassDescription
+{
+ my( $term ) = "";
+ my( $once ) = 0;
+
+ if( $Description ne "" ) {
+ print CLASS "<H2><a name=\"short\">Detailed Description</a>",
+ "</H2>\n<P>\n";
+
+ $term = "<HR>\n";
+
+ $Description =~ s/\n\n+/\n<\/p><p>\n/g;
+
+ print CLASS "\n", makeReferencedText($Description) ,"\n</P>";
+ }
+
+ if( $ClassSee ne "" ) {
+ print CLASS "<p><b>See Also</b>: ";
+
+ $once = 0;
+ $term = "<HR>" if $term eq "";
+
+ foreach $item ( split /[\s,]+/, $ClassSee ) {
+
+ if( $once ) { print CLASS ", "; }
+ else { $once = 1; }
+
+ print CLASS findClassReference( $item );
+ }
+
+ print CLASS "</p>\n";
+ }
+
+ print CLASS $term if $term ne "";
+}
+
+sub writeMemberDoc
+{
+ my( $visibility, $node ) = @_;
+ my( $once ) = 0;
+ my( $myvis ) = "";
+
+ return if !defined $node || $#{$node} == -1 ;
+
+ foreach $member ( @{$node} ) {
+ $member->Visit($modname);
+
+ if( $Description eq "" && $See eq "" ) {
+ $linkRef++;
+ Ast::UnVisit();
+ next;
+ }
+
+ if( $Keyword eq "property" ) {
+ print CLASS "<H4><b>",refString(escape($Type)),
+ "<a name=\"ref",$linkRef,"\"></a>",
+ "<a name=\"",$astNodeName,"\">",
+ escape($astNodeName), "</a>",
+ refString(escape($Array)),
+ " </b><font color=gray><code>[", $visibility, "]</code>",
+ "</font></H4>\n";
+ }
+ elsif( $Keyword eq "method" ) {
+ $myvis = $visibility;
+
+ if ( $ReturnType =~ /virtual/ ) {
+ $myvis .= " virtual";
+ $ReturnType =~ s/\s*virtual\s*//g;
+ }
+
+ if ( $ReturnType =~ /static/ ) {
+ $myvis .= " static";
+ $ReturnType =~ s/\s*static\s*//g;
+ }
+
+ print CLASS "<H4><b>",
+ refString(escape($ReturnType)),
+ " <a name=\"ref",$linkRef,"\"></a>",
+ "<a name=\"",$astNodeName,"\">",
+ escape($astNodeName), "</a>(",
+ refString(escape($Parameters)),
+ ") $Const </b><font color=gray>",
+ "<code>[", $myvis, "]</code></font></H4>\n";
+ }
+ elsif( $Keyword eq "enum" ) {
+ print CLASS "<H4><b>enum <a name=\"ref",
+ $linkRef,"\"></a>",
+ "<a name=\"",$astNodeName, "\"></a>",
+ escape($astNodeName), " (",
+ $Constants,") </b><font color=gray>",
+ "<code>[", $visibility, "]</code></font></H4>\n";
+ }
+ elsif( $Keyword eq "typedef" ) {
+ print CLASS "<H4><b>typedef ",refString(escape($Type)),
+ " <a name=\"ref", $linkRef,"\"></a>",
+ escape($astNodeName),
+ refString(escape($Array)),
+ " </b><font color=gray>",
+ "<code>[", $visibility, "]</code></font></H4>";
+ }
+
+ print CLASS "<p><strong>Deprecated member.</strong></p>\n"
+ if $MethDeprecated;
+ print CLASS "<p><strong>For internal use only.</strong></p>\n"
+ if $MethInternal;
+
+ $Description =~ s/\n\n+/\n<\/p><p>\n/g;
+
+ print CLASS "<p>",makeReferencedText($Description),"</p>\n";
+
+
+ if( $Keyword eq "method" ) {
+
+ if( $#{$ParamDoc} != -1 ) {
+ print CLASS "<dl><dt><b>Parameters</b>:<dd>\n",
+ "<table width=\"100%\" border=\"0\">\n";
+
+ foreach $parameter ( @{$ParamDoc} ) {
+ print CLASS
+ "<tr><td align=\"left\" valign=\"top\">\n",
+ $parameter->{"astNodeName"};
+
+ print CLASS
+ "</td><td align=\"left\" valign=\"top\">\n",
+ makeReferencedText(
+ $parameter->{"Description"}),
+ "</td></tr>\n";
+ }
+
+ print CLASS "</table>\n</dl>\n";
+
+ }
+
+ print CLASS "<dl><dt><b>Returns</b>:<dd>\n",
+ makeReferencedText( $Returns ),
+ "</dl>\n" if $Returns ne "";
+
+ print CLASS "<dl><dt><b>Throws</b>:<dd>\n",
+ makeReferencedText( $Exceptions ),
+ "</dl>\n" if $Exceptions ne "";
+ }
+
+ if( $See ne "" ) {
+ print CLASS "<dl><dt><b>See Also</b>:<dd>";
+
+ $once = 0;
+
+ foreach $item ( split /[\s,]+/, $See ) {
+
+ if( $once ) { print CLASS ", "; }
+ else { $once = 1; }
+
+ print CLASS findClassReference( $item );
+ }
+
+ print CLASS "</dl>\n";
+ }
+
+ print CLASS $term if $term ne "";
+
+ Ast::UnVisit();
+
+ $linkRef++;
+ }
+}
+
+#
+# Check and markup words that are in the symbol table.
+# Use sparingly, since EVERY WORD is looked up in the table.
+#
+
+sub refString
+{
+ my( $source ) = @_;
+
+ foreach $werd ( split /[^\w><]+/, $source ) {
+
+ $ref = findClassReference( $werd );
+ if( $ref ne $werd ) {
+ $source =~ s/$werd/$ref/g;
+ }
+ }
+
+ return $source;
+}
+
+######################################################################
+# markupCxxHeader -- Converts the header into a semi-fancy HTML doc
+######################################################################
+
+$outputFilename = "";
+
+# tokens
+#$nonIdentifier="[^\w]+";
+#$keywords="if|union|class|struct|operator|for|while|do|goto|new|delete|friend|typedef|return|switch|const|inline|asm|sizeof|virtual|static";
+#$types="void|int|long|float|double|unsigned|char|bool|short";
+
+# styles
+#$keywordStyle="strong";
+#$typeStyle="u";
+#$stringStyle="i";
+
+# Takes the path to a C++ source file,
+# spits out a marked-up and cross-referenced HTML file.
+
+sub markupCxxHeader
+{
+ my( $filename ) = @_;
+ $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;
+
+ # never let a file name start with a '-' sign, since this makes
+ # some programs think the file name really was a parameter to the
+ # program. Filenames starting with '-' usually happen if you let
+ # kdoc work on files like '../../include/foo/bar.h', given the
+ # above substitution rules. Therefore: if a filename starts with
+ # '-', prepend a '_'
+ s/^-/_-/;
+
+ $outputFilename = $_;
+ $outputFilename = $outputdir."/".$outputFilename;
+
+ open( HTMLFILE, ">$outputFilename.html" )
+ || die "Couldn't open $outputFilename to read.\n";
+
+ print HTMLFILE "<HTML>\n<HEAD><TITLE>$outputFilename</TITLE></HEAD>\n".
+ "<BODY BGCOLOR=\"#ffffff\">\n<PRE>";
+
+ while( <HFILE> )
+ {
+
+ s/</\</g;
+ s/>/\>/g;
+ s/"/\"/g;
+
+ if( /^\s*(template.*\s+)?(class|struct)/ ) {
+ $_ = refString($_);
+ }
+
+ print HTMLFILE;
+ }
+
+ print HTMLFILE "</PRE>\n<HR>\n<address>$genText",
+ "</address>\n</BODY>\n</HTML>\n";
+}
+
+#sub Linkize
+#{
+# my( $str ) = @_;
+#
+# $str =~ s/ /%20/g;
+# $str =~ s/</%3C/g;
+# $str =~ s/>/%3E/g;
+#
+# return $str;
+#}
+
+1;
+
--- /dev/null
+# kdocMan -- man page output for kdoc.
+# Copyright(c) 1998, Sirtaj Singh Kang (taj@kde.org).
+
+# $Id$
+
+# 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 kdocMan;
+
+require Ast;
+
+BEGIN {
+ $modname = "kdocMan";
+ $outputdir = ".";
+ $genText = "";
+ $className = "";
+}
+
+sub dumpDoc
+{
+ ( $lib, $root, $outputdir ) = @_;
+
+ print "Generating man pages.\n" unless $main::quiet;
+ $genText = $main::generatedByText;
+ $datestamp = `date +%D`;
+ chop $datestamp;
+
+ writeIndex();
+ writeClasses();
+}
+
+sub writeIndex()
+{
+ @classNames = ();
+ %classNodes = ();
+
+ foreach $class ( @{$root->{'classes'}} ) {
+ push( @classNames, $class->{'astNodeName'} );
+ $classNodes{ $class->{'astNodeName'} } = $class;
+ }
+
+ @classNames = sort @classNames;
+
+ open( MANPAGE, ">$outputdir/$lib.1$lib" )
+ || die "Couldn't write to $outputdir/$lib.1$lib\n";
+
+print MANPAGE<<EOF;
+.TH $lib 1 "$datestamp" "KDOC"
+.SH NAME
+$lib - C++ Class Library
+.SH SYNOPSIS
+The $lib library consists of the following classes:
+.PP
+EOF
+ writeHierarchy("<>");
+
+print MANPAGE<<EOF;
+.SH DESCRIPTION
+EOF
+
+ foreach $class ( @classNames ) {
+ $short = $classNodes{$class}->{ "ClassShort" };
+
+ print MANPAGE "\n.TP 4\n.BI \"$class\"\n$short\n.PP\n";
+ }
+
+
+print MANPAGE<<EOF;
+.SH AUTHOR
+$genText
+.PP
+EOF
+ close MANPAGE;
+
+}
+
+sub writeClasses
+{
+ foreach $classNode ( @{$root->{'classes'}} ) {
+ $classNode->Visit( $modname );
+ $className=$astNodeName;
+ writeClass();
+ Ast::UnVisit();
+ }
+}
+
+sub writeClass
+{
+ ($fname = $astNodeName) =~ tr/[A-Z]/[a-z]/;
+ $fname .= ".3$lib";
+
+ $className = $astNodeName;
+ $Description = makeReferencedText( $Description );
+ $Description =~ s/\n\s+/\n/g;
+
+ open ( CLASSMAN, ">$outputdir/$fname" )
+ || die "couldn't open $outputdir/$fname for writing.\n";
+
+ open( REDIR, ">$outputdir/$astNodeName.3$lib" )
+ ||die "couldn't open $outputdir/$astNodeName.3$lib ".
+ " for writing.\n";
+
+ print REDIR ".so $fname\n";
+ close REDIR;
+
+
+print CLASSMAN<<EOF;
+.TH $className 3 "$datestamp\" "KDOC" "$lib Class Library"
+.SH NAME
+$className - $ClassShort
+
+.SH SYNOPSIS
+#include <$Header>
+
+EOF
+
+# Internal or Deprecated
+
+print ".ti +1c\n.b \"Deprecated Class\"\n" if $Deprecated;
+print ".ti +1c\n.b \"Internal use only\"\n" if $Internal;
+
+
+print CLASSMAN<<EOF;
+Inherits:
+EOF
+
+# Inheritance list
+ my($pcount) = 0;
+ if (defined @{$Ancestors} ) {
+ foreach $foreparent ( @{$Ancestors} ) {
+ print CLASSMAN ", " if $pcount != 0;
+ $pcount = 1;
+
+ print CLASSMAN $foreparent->{"astNodeName"};
+
+ if( defined $main::classSource{
+ $foreparent->{"astNodeName"}} ) {
+ print CLASSMAN " (",
+ $main::classSource{$foreparent->{"astNodeName"}},")";
+ }
+ }
+ }
+ else {
+ print CLASSMAN "nothing";
+ }
+
+print CLASSMAN<<EOF;
+
+.PP
+EOF
+ listMembers( "Public Members", $public );
+ listMembers( "Public Slots", $public_slots );
+ listMembers( "Protected Members", $protected );
+ listMembers( "Protected Slots", $protected_slots );
+ listMembers( "Signals", $signals );
+
+ if( $main::dontDoPrivate == 0 ) {
+ listMembers( "Private Members", $private );
+ listMembers( "Private Slots", $private_slots );
+ }
+
+
+print CLASSMAN<<EOF;
+
+.SH DESCRIPTION
+$Description
+.SH MEMBER DOCUMENTATION
+EOF
+
+ documentMembers( $public );
+ documentMembers( $public_slots );
+ documentMembers( $protected );
+ documentMembers( $protected_slots );
+ documentMembers( $signals );
+
+ if( $main::dontDoPrivate == 0 ) {
+ documentMembers( $private );
+ documentMembers( $private_slots );
+ }
+
+ if( $ClassSee ne "" ) {
+ $ClassSee = ", ".$ClassSee
+ }
+
+print CLASSMAN<<EOF;
+.SH "SEE ALSO"
+$lib(1)$ClassSee
+EOF
+
+print CLASSMAN<<EOF;
+.SH AUTHOR
+EOF
+
+ if( ! ($Author =~ /^\s*$/) ) {
+ print CLASSMAN "$Author\n.PP\n";
+ }
+
+print CLASSMAN<<EOF;
+$genText
+.SH VERSION
+$Version
+EOF
+
+ close CLASSMAN;
+}
+
+sub writeHierarchy
+{
+ local( $node ) = @_;
+ local( @kids );
+
+# Display class
+ if( $node ne "<>" ) {
+ print MANPAGE "$node";
+ if( defined $main::classSource{ $node } ) {
+ print MANPAGE " (from ",$main::classSource{$node},")";
+ }
+ print MANPAGE "\n";
+ }
+
+# Recurse for each child class
+ if ( defined $main::children{$node} ) {
+ print MANPAGE ".in +1c\n";
+ foreach $kid ( sort split /;/, $main::children{$node} )
+ {
+ print MANPAGE ".br\n";
+ writeHierarchy( $kid );
+ }
+
+ print MANPAGE ".in -1c\n";
+ }
+}
+
+sub makeReferencedText
+{
+ my( $str ) = @_;
+
+ $str =~ s/\@ref(\s+[-:#\w\._]+)/\n.BI "$1"\n/g;
+
+ return $str;
+}
+
+sub listMembers
+{
+ my( $access, $nodelist ) = @_;
+ my( $node );
+
+ return if !defined $nodelist || $#{$nodelist} == -1;
+
+print CLASSMAN<<EOF;
+.PP
+.BI "$access"
+.in +2c
+EOF
+
+ foreach $node ( @{$nodelist} ) {
+ $node->Visit( $modname );
+
+ print CLASSMAN ".ti -1c\n";
+
+ if( $Keyword eq "property" ) {
+ $Type =~ s/^\s+//g;
+ $Type =~ s/\s+$//g;
+ print CLASSMAN ".BI \"$Type $astNodeName\"\n.br\n";
+ }
+ elsif( $Keyword eq "method" ) {
+ $ReturnType =~ s/^\s+//g;
+ $ReturnType =~ s/\s+$//g;
+ $ReturnType .= " " if $ReturnType ne "";
+
+ print CLASSMAN ".BI \"$ReturnType$astNodeName ",
+ "($Parameters) $Const\"\n.br\n";
+ }
+ elsif( $Keyword eq "enum" ) {
+ print CLASSMAN ".BI \"",
+ "enum $astNodeName {$Constants}\"\n.br\n";
+ }
+ elsif( $Keyword eq "typedef" ) {
+ print CLASSMAN ".BI \"",
+ "typedef $astNodeName\"\n.br\n";
+ }
+ Ast::UnVisit();
+ }
+
+print CLASSMAN<<EOF;
+.in -2c
+EOF
+}
+
+sub documentMembers
+{
+ my( $nodelist ) = @_;
+
+ return if !defined $nodelist || $#{$nodelist} == -1;
+
+ foreach $member ( @{$nodelist} ) {
+ $member->Visit( $modname );
+
+ if( $Description eq "" && $See eq "" ) {
+ Ast::UnVisit();
+ next;
+ }
+
+ if( $Keyword eq "property" ) {
+ $Type =~ s/^\s+//g;
+ print CLASSMAN ".SH \"$Type $className","::",
+ "$astNodeName\"\n";
+ }
+ elsif( $Keyword eq "method" ) {
+ $ReturnType =~ s/^\s+//g;
+ $ReturnType =~ s/\s+$//g;
+ $ReturnType .= " " if $ReturnType ne "";
+
+ print CLASSMAN ".SH \"$ReturnType$className",
+ "::","$astNodeName ","($Parameters) $Const\"\n";
+ }
+ elsif( $Keyword eq "enum" ) {
+ print CLASSMAN ".SH \"",
+ "enum $className","::",
+ "$astNodeName {$Constants}\"\n";
+ }
+ elsif( $Keyword eq "typedef" ) {
+ print CLASSMAN ".SH \"", "typedef $className",
+ "::","$astNodeName\"\n";
+ }
+
+# Internal or Deprecated
+
+ print ".ti +1c\n.b \"Deprecated member\"\n" if $MethDeprecated;
+ print ".ti +1c\n.b \"Internal use only\"\n" if $MethInternal;
+
+# Description
+ print CLASSMAN makeReferencedText($Description),
+ "\n.br\n" if $Description ne "";
+
+# Parameters
+ if( $Keyword eq "method" ) {
+ if( $#{$ParamDoc} != -1 ) {
+ print CLASSMAN "\n.br\n.in +1c\n",
+ "Parameters\n.in +1c\n.";
+
+ foreach $parameter ( @{$ParamDoc} ) {
+print CLASSMAN ".br\n.BI \"", $parameter->{"astNodeName"},
+ "\"\n.in +1c\n",
+ $parameter->{"Description"}, "\n.in -1c\n";
+ }
+print CLASSMAN<<EOF;
+.in -1c
+.in -1c
+EOF
+ }
+
+ print CLASSMAN ".in +1c\nReturns\n.in +1c\n",
+ "$Returns\n.in -1c\n.in -1c\n" if $Returns ne "";
+ print CLASSMAN ".in +1c\nThrows\n.in +1c\n",
+ "$Exceptions\n.in -1c\n.in -1c\n"
+ if $Exceptions ne "";
+ }
+
+ print CLASSMAN ".in +1c\nSee Also\n.in +1c\n$See\n",
+ ".in -1c\n.in -1c\n" if $See ne "";
+
+ Ast::UnVisit();
+ }
+}
+
+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, $nodem $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;