git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1221130 283d02a7-25f6-0310-bc7c-ecb5cbfe19dav3.5.13-sru
parent
f4fae92b67
commit
084c86a818
@ -1,91 +0,0 @@
|
||||
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;
|
@ -1,532 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
=head2
|
||||
|
||||
Call $printsub for each *direct* ancestor of $node.
|
||||
Only multiple inheritance can lead to $printsub being called more than once.
|
||||
|
||||
=cut
|
||||
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 $acc ( qw/public protected private/ ) {
|
||||
next if $acc eq "private" && !$main::doPrivate;
|
||||
$access = $acc;
|
||||
|
||||
my @types = ();
|
||||
my @data = ();
|
||||
my @signals = ();
|
||||
my @k_dcops = ();
|
||||
my @k_dcop_signals = ();
|
||||
my @k_dcop_hiddens = ();
|
||||
my @slots =();
|
||||
my @methods = ();
|
||||
my @static = ();
|
||||
my @modules = ();
|
||||
my @interfaces = ();
|
||||
|
||||
# Build lists
|
||||
foreach my $kid ( @{$node->{Kids}} ) {
|
||||
next unless ( $kid->{Access} =~ /$access/
|
||||
&& !$kid->{ExtSource})
|
||||
|| ( $access eq "public"
|
||||
&& ( $kid->{Access} eq "signals"
|
||||
|| $kid->{Access} =~ "k_dcop" # note the =~
|
||||
|| $kid->{Access} eq "K_DCOP"));
|
||||
|
||||
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;
|
||||
}
|
||||
elsif ( $kid->{Flags} =~ "d" ) {
|
||||
push @k_dcops, $kid;
|
||||
}
|
||||
elsif ( $kid->{Flags} =~ "z" ) {
|
||||
push @k_dcop_signals, $kid;
|
||||
}
|
||||
elsif ( $kid->{Flags} =~ "y" ) {
|
||||
push @k_dcop_hiddens, $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
|
||||
$uc_access = ucfirst( $access );
|
||||
|
||||
doGroup( "$uc_access Types", $node, \@types, $startgrpsub,
|
||||
$methodsub, $endgrpsub);
|
||||
doGroup( "Modules", $node, \@modules, $startgrpsub,
|
||||
$methodsub, $endgrpsub);
|
||||
doGroup( "Interfaces", $node, \@interfaces, $startgrpsub,
|
||||
$methodsub, $endgrpsub);
|
||||
doGroup( "$uc_access Methods", $node, \@methods, $startgrpsub,
|
||||
$methodsub, $endgrpsub);
|
||||
doGroup( "$uc_access Slots", $node, \@slots, $startgrpsub,
|
||||
$methodsub, $endgrpsub);
|
||||
doGroup( "Signals", $node, \@signals, $startgrpsub,
|
||||
$methodsub, $endgrpsub);
|
||||
doGroup( "k_dcop", $node, \@k_dcops, $startgrpsub,
|
||||
$methodsub, $endgrpsub);
|
||||
doGroup( "k_dcop_signals", $node, \@k_dcop_signals, $startgrpsub,
|
||||
$methodsub, $endgrpsub);
|
||||
doGroup( "k_dcop_hiddens", $node, \@k_dcop_hiddens, $startgrpsub,
|
||||
$methodsub, $endgrpsub);
|
||||
doGroup( "$uc_access Static Methods", $node, \@static,
|
||||
$startgrpsub, $methodsub, $endgrpsub);
|
||||
doGroup( "$uc_access Members", $node, \@data, $startgrpsub,
|
||||
$methodsub, $endgrpsub);
|
||||
}
|
||||
}
|
||||
|
||||
sub doGroup
|
||||
{
|
||||
my ( $name, $node, $list, $startgrpsub, $methodsub, $endgrpsub ) = @_;
|
||||
|
||||
my ( $hasMembers ) = 0;
|
||||
foreach my $kid ( @$list ) {
|
||||
if ( !exists $kid->{DocNode}->{Reimplemented} ) {
|
||||
$hasMembers = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return if !$hasMembers;
|
||||
|
||||
if ( defined $methodsub ) {
|
||||
foreach my $kid ( @$list ) {
|
||||
if ( !exists $kid->{DocNode}->{Reimplemented} ) {
|
||||
$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;
|
@ -1,5 +0,0 @@
|
||||
dnl we need to use our own copy, since kmailicalIface needs post 3.3 fixes in it
|
||||
dnl TODO: remove once we rely on kdelibs 3.4
|
||||
DCOPIDLNG='$(top_srcdir)/dcopidlng/dcopidlng'
|
||||
AC_SUBST(DCOPIDLNG)
|
||||
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
trap "rm -f dcopidlng.stderr.$$" 0 1 2 15
|
||||
LIBDIR=`dirname $0`
|
||||
perl -I"$LIBDIR" "$LIBDIR/kalyptus" --allow_k_dcop_accessors -f dcopidl $1 2>dcopidlng.stderr.$$
|
||||
RET=$?
|
||||
if [ $RET -ne 0 ]
|
||||
then
|
||||
cat dcopidlng.stderr.$$ >&2
|
||||
fi
|
||||
exit $RET
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,762 +0,0 @@
|
||||
=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 );
|
||||
|
||||
if ( !exists $node->{DocNode}->{Internal} ||
|
||||
!$main::skipInternal ) {
|
||||
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->{InList} ) {
|
||||
print "\t" x $depth, " -\tAncestors -> ";
|
||||
foreach my $innode ( @{$node->{InList}} ) {
|
||||
print $innode->{astNodeName} . ",";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
|
||||
print "\t" x $depth, " -\n" if (defined $node->{ $deep } && scalar(@{$node->{ $deep }}) != 0);
|
||||
|
||||
$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};
|
||||
}
|
||||
|
||||
### Warning: this returns the list of parents, e.g. the 3 words in KParts::ReadOnlyPart::SomeEnum
|
||||
### It has nothing do to with inheritance.
|
||||
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;
|
@ -1,245 +0,0 @@
|
||||
|
||||
=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.kalyptus";
|
||||
$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.".kalyptus";
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
@ -1,419 +0,0 @@
|
||||
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 );
|
||||
$text =~ m#/\*#; # need to do the match again, otherwise /***/ doesn't parse
|
||||
### TODO update this method from kdoc
|
||||
$buffer = $'; # everything after the first \*
|
||||
$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;
|
||||
# }
|
||||
if( $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*\@reimplemented\s*/ ) {
|
||||
codeProp( "Reimplemented", 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+([^\s]+)\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;
|
@ -1,189 +0,0 @@
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
=head2 splitUnnested
|
||||
Helper to split a list using a delimiter, but looking for
|
||||
nesting with (), {}, [] and <>.
|
||||
Example: splitting int a, QPair<c,b> d, e=","
|
||||
on ',' will give 3 items in the list.
|
||||
|
||||
Parameter: delimiter, string
|
||||
Returns: array, after splitting the string
|
||||
|
||||
Thanks to Ashley Winters
|
||||
=cut
|
||||
sub splitUnnested($$) {
|
||||
my $delim = shift;
|
||||
my $string = shift;
|
||||
my(%open) = (
|
||||
'[' => ']',
|
||||
'(' => ')',
|
||||
'<' => '>',
|
||||
'{' => '}',
|
||||
);
|
||||
my(%close) = reverse %open;
|
||||
my @ret;
|
||||
my $depth = 0;
|
||||
my $start = 0;
|
||||
my $indoublequotes = 0;
|
||||
while($string =~ /($delim|<<|>>|[][}{)(><\"])/g) {
|
||||
my $c = $1;
|
||||
if(!$depth and !$indoublequotes and $c eq $delim) {
|
||||
my $len = pos($string) - $start - 1;
|
||||
push @ret, substr($string, $start, $len);
|
||||
$start = pos($string);
|
||||
} elsif($open{$c}) {
|
||||
$depth++;
|
||||
} elsif($close{$c}) {
|
||||
$depth--;
|
||||
} elsif($c eq '"') {
|
||||
if ($indoublequotes) {
|
||||
$indoublequotes = 0;
|
||||
} else {
|
||||
$indoublequotes = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $subs = substr($string, $start);
|
||||
push @ret, $subs if ($subs);
|
||||
return @ret;
|
||||
}
|
||||
|
||||
1;
|
||||
|
Loading…
Reference in new issue