add directory study

This commit is contained in:
gohigh
2024-02-19 00:25:23 -05:00
parent b1306b38b1
commit f3774e2f8c
4001 changed files with 2285787 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -0,0 +1,577 @@
# $Id: Common.pm,v 1.6 1998/05/14 11:59:22 argggh Exp $
package LXR::Common;
use DB_File;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(&warning &fatal &abortall &fflush &urlargs
&fileref &idref &htmlquote &freetextmarkup &markupfile
&init &makeheader &makefooter &expandtemplate);
$wwwdebug = 1;
$SIG{__WARN__} = 'warning';
$SIG{__DIE__} = 'fatal';
@cterm = ('atom', '\\\\.', '',
'comment', '/\*', '\*/',
'comment', '//', "\n",
'string', '"', '"',
'string', "'", "'",
'include', '#include', "\n");
sub warning {
print(STDERR "[",scalar(localtime),"] warning: $_[0]\n");
print("<h4 align=\"center\"><i>** Warning: $_[0]</i></h4>\n") if $wwwdebug;
}
sub fatal {
print(STDERR "[",scalar(localtime),"] fatal: $_[0]\n");
print("<h4 align=\"center\"><i>** Fatal: $_[0]</i></h4>\n") if $wwwdebug;
exit(1);
}
sub abortall {
print(STDERR "[",scalar(localtime),"] abortall: $_[0]\n");
print("Content-Type: text/html\n\n",
"<html>\n<head>\n<title>Abort</title>\n</head>\n",
"<body><h1>Abort!</h1>\n",
"<b><i>** Aborting: $_[0]</i></b>\n",
"</body>\n</html>\n") if $wwwdebug;
exit(1);
}
sub fflush {
$| = 1; print('');
}
sub urlargs {
my @args = @_;
my %args = ();
my $val;
foreach (@args) {
$args{$1} = $2 if /(\S+)=(\S*)/;
}
@args = ();
foreach ($Conf->allvariables) {
$val = $args{$_} || $Conf->variable($_);
push(@args, "$_=$val") unless ($val eq $Conf->vardefault($_));
delete($args{$_});
}
foreach (keys(%args)) {
push(@args, "$_=$args{$_}");
}
return($#args < 0 ? '' : '?'.join(';',@args));
}
sub fileref {
my ($desc, $path, $line, @args) = @_;
return("<a href=\"source$path".
&urlargs(@args).
($line > 0 ? "#L$line" : "").
"\"\>$desc</a>");
}
sub diffref {
my ($desc, $path, $darg) = @_;
($darg,$dval) = $darg =~ /(.*?)=(.*)/;
return("<a href=\"diff$path".
&urlargs(($darg ? "diffvar=$darg" : ""),
($dval ? "diffval=$dval" : ""),
@args).
"\"\>$desc</a>");
}
sub idref {
my ($desc, $id, @args) = @_;
return("<a href=\"ident".
&urlargs(($id ? "i=$id" : ""),
@args).
"\"\>$desc</a>");
}
sub http_wash {
my $t = shift;
$t =~ s/\+/ /g;
$t =~ s/\%([\da-f][\da-f])/pack("C", hex($1))/gie;
# Paranoia check. Regexp-searches in Glimpse won't work.
# if ($t =~ tr/;<>*|\`&$!#()[]{}:\'\"//) {
# Should be sufficient to keep "open" from doing unexpected stuff.
if ($t =~ tr/<>|\"\'\`//) {
&abortall("Illegal characters in HTTP-parameters.");
}
return($t);
}
sub markspecials {
$_[0] =~ s/([\&\<\>])/\0$1/g;
}
sub htmlquote {
$_[0] =~ s/\0&/&amp;/g;
$_[0] =~ s/\0</&lt;/g;
$_[0] =~ s/\0>/&gt;/g;
}
sub freetextmarkup {
$_[0] =~ s#((ftp|http)://\S*[^\s.])#<a href=\"$1\">$1</a>#g;
$_[0] =~ s/(&lt;(.*@.*)&gt;)/<a href=\"mailto:$2\">$1<\/a>/g;
}
sub linetag {
#$frag =~ s/\n/"\n".&linetag($virtp.$fname, $line)/ge;
# my $tag = '<a href="'.$_[0].'#L'.$_[1].
# '" name="L'.$_[1].'">'.$_[1].' </a>';
my $tag;
$tag .= ' ' if $_[1] < 10;
$tag .= ' ' if $_[1] < 100;
$tag .= &fileref($_[1], $_[0], $_[1]).' ';
$tag =~ s/<a/<a name=L$_[1]/;
# $_[1]++;
return($tag);
}
sub markupfile {
my ($INFILE, $virtp, $fname, $outfun) = @_;
$line = 1;
# A C/C++ file
if ($fname =~ /\.([ch]|cpp?|cc)$/i) { # Duplicated in genxref.
&SimpleParse::init($INFILE, @cterm);
tie (%xref, "DB_File", $Conf->dbdir."/xref", O_RDONLY, 0664, $DB_HASH)
|| &warning("Cannot open xref database.");
&$outfun(# "<pre>\n".
#"<a name=\"L".$line++.'"></a>');
&linetag($virtp.$fname, $line++));
($btype, $frag) = &SimpleParse::nextfrag;
while (defined($frag)) {
&markspecials($frag);
if ($btype eq 'comment') {
# Comment
# Convert mail adresses to mailto:
&freetextmarkup($frag);
$frag = "<b><i>$frag</i></b>";
$frag =~ s#\n#</i></b>\n<b><i>#g;
} elsif ($btype eq 'string') {
# String
$frag = "<i>$frag</i>";
} elsif ($btype eq 'include') {
# Include directive
$frag =~ s#\"(.*)\"#
'"'.&fileref($1, $virtp.$1).'"'#e;
$frag =~ s#&lt;(.*)&gt;#
"&lt;".&fileref
($1,
$Conf->mappath($Conf->incprefix."/$1")).
"&gt;"#e;
} else {
# Code
$frag =~ s#(^|[^a-zA-Z_\#0-9])([a-zA-Z_~][a-zA-Z0-9_]*)\b#
"$1".(defined($xref{$2}) ?
&idref($2,$2) :
"$2")#ge;
}
&htmlquote($frag);
$frag =~ s/\n/"\n".&linetag($virtp.$fname, $line++)/ge;
&$outfun($frag);
($btype, $frag) = &SimpleParse::nextfrag;
}
# &$outfun("</pre>\n");
untie(%xref);
} elsif ($fname =~ /\.(gif|jpg)$/) {
&$outfun("<img src=\"http:source".$virtp.$fname. &urlargs("raw=1").
"\" border=0 alt=\"$fname\" align=middle>\n");
} elsif ($fname eq 'CREDITS') {
while (<$INFILE>) {
&SimpleParse::untabify($_);
&markspecials($_);
&htmlquote($_);
s/^N:\s+(.*)/<hr>\n<h3>$1<\/h3>/gm;
s/^(E:\s+)(\S+@\S+)/$1<a href=\"mailto:$2\">$2<\/a>/gm;
s/^(W:\s+)(.*)/$1<a href=\"$2\">$2<\/a>/gm;
# &$outfun("<a name=\"L$.\"><\/a>".$_);
&$outfun(&linetag($virtp.$fname, $.).$_);
}
} else {
while (<$INFILE>) {
&SimpleParse::untabify($_);
&markspecials($_);
&htmlquote($_);
&freetextmarkup($_);
# &$outfun("<a name=\"L$.\"><\/a>".$_);
&$outfun(&linetag($virtp.$fname, $.).$_);
}
}
}
sub fixpaths {
$Path->{'virtf'} = '/'.shift;
$Path->{'root'} = $Conf->sourceroot;
while ($Path->{'virtf'} =~ s#/[^/]+/\.\./#/#g) {
}
$Path->{'virtf'} =~ s#/\.\./#/#g;
$Path->{'virtf'} .= '/' if (-d $Path->{'root'}.$Path->{'virtf'});
$Path->{'virtf'} =~ s#//+#/#g;
($Path->{'virt'}, $Path->{'file'}) = $Path->{'virtf'} =~ m#^(.*/)([^/]*)$#;
$Path->{'real'} = $Path->{'root'}.$Path->{'virt'};
$Path->{'realf'} = $Path->{'root'}.$Path->{'virtf'};
@pathelem = $Path->{'virtf'} =~ /([^\/]+$|[^\/]+\/)/g;
$fpath = '';
foreach (@pathelem) {
$fpath .= $_;
push(@addrelem, $fpath);
}
unshift(@pathelem, $Conf->sourcerootname.'/');
unshift(@addrelem, "");
foreach (0..$#pathelem) {
if (defined($addrelem[$_])) {
$Path->{'xref'} .= &fileref($pathelem[$_], "/$addrelem[$_]");
} else {
$Path->{'xref'} .= $pathelem[$_];
}
}
$Path->{'xref'} =~ s#/</a>#</a>/#gi;
}
sub init {
my @a;
$HTTP->{'path_info'} = &http_wash($ENV{'PATH_INFO'});
$HTTP->{'this_url'} = &http_wash(join('', 'http://',
$ENV{'SERVER_NAME'},
':', $ENV{'SERVER_PORT'},
$ENV{'SCRIPT_NAME'},
$ENV{'PATH_INFO'},
'?', $ENV{'QUERY_STRING'}));
foreach ($ENV{'QUERY_STRING'} =~ /([^;&=]+)(?:=([^;&]+)|)/g) {
push(@a, &http_wash($_));
}
$HTTP->{'param'} = {@a};
$HTTP->{'param'}->{'v'} ||= $HTTP->{'param'}->{'version'};
$HTTP->{'param'}->{'a'} ||= $HTTP->{'param'}->{'arch'};
$HTTP->{'param'}->{'i'} ||= $HTTP->{'param'}->{'identifier'};
$identifier = $HTTP->{'param'}->{'i'};
$readraw = $HTTP->{'param'}->{'raw'};
if (defined($readraw)) {
print("\n");
} else {
print("Content-Type: text/html\n\n");
}
$Conf = new LXR::Config;
foreach ($Conf->allvariables) {
$Conf->variable($_, $HTTP->{'param'}->{$_}) if $HTTP->{'param'}->{$_};
}
&fixpaths($HTTP->{'path_info'} || $HTTP->{'param'}->{'file'});
if (defined($readraw)) {
open(RAW, $Path->{'realf'});
while (<RAW>) {
print;
}
close(RAW);
exit;
}
return($Conf, $HTTP, $Path);
}
sub expandtemplate {
my ($templ, %expfunc) = @_;
my ($expfun, $exppar);
while ($templ =~ s/(\{[^\{\}]*)\{([^\{\}]*)\}/$1\01$2\02/s) {}
$templ =~ s/(\$(\w+)(\{([^\}]*)\}|))/{
if (defined($expfun = $expfunc{$2})) {
if ($3 eq '') {
&$expfun;
} else {
$exppar = $4;
$exppar =~ s#\01#\{#gs;
$exppar =~ s#\02#\}#gs;
&$expfun($exppar);
}
} else {
$1;
}
}/ges;
$templ =~ s/\01/\{/gs;
$templ =~ s/\02/\}/gs;
return($templ);
}
# What follows is a pretty hairy way of expanding nested templates.
# State information is passed via localized variables.
# The first one is simple, the "banner" template is empty, so we
# simply return an appropriate value.
sub bannerexpand {
if ($who eq 'source' || $who eq 'diff') {
return($Path->{'xref'});
} else {
return('');
}
}
sub titleexpand {
if ($who eq 'source' || $who eq 'diff') {
return($Conf->sourcerootname.$Path->{'virtf'});
} elsif ($who eq 'ident') {
my $i = $HTTP->{'param'}->{'i'};
return($Conf->sourcerootname.' identfier search'.
($i ? " \"$i\"" : ''));
} elsif ($who eq 'search') {
my $s = $HTTP->{'param'}->{'string'};
return($Conf->sourcerootname.' freetext search'.
($s ? " \"$s\"" : ''));
} elsif ($who eq 'find') {
my $s = $HTTP->{'param'}->{'string'};
return($Conf->sourcerootname.' file search'.
($s ? " \"$s\"" : ''));
}
}
sub thisurl {
my $url = $HTTP->{'this_url'};
$url =~ s/([\?\&\;\=])/sprintf('%%%02x',(unpack('c',$1)))/ge;
return($url);
}
sub baseurl {
return($Conf->baseurl);
}
# This one isn't too bad either. We just expand the "modes" template
# by filling in all the relevant values in the nested "modelink"
# template.
sub modeexpand {
my $templ = shift;
my $modex = '';
my @mlist = ();
local $mode;
if ($who eq 'source') {
push(@mlist, "<b><i>source navigation</i></b>");
} else {
push(@mlist, &fileref("source navigation", $Path->{'virtf'}));
}
if ($who eq 'diff') {
push(@mlist, "<b><i>diff markup</i></b>");
} elsif ($who eq 'source' && $Path->{'file'}) {
push(@mlist, &diffref("diff markup", $Path->{'virtf'}));
}
if ($who eq 'ident') {
push(@mlist, "<b><i>identifier search</i></b>");
} else {
push(@mlist, &idref("identifier search", ""));
}
if ($who eq 'search') {
push(@mlist, "<b><i>freetext search</i></b>");
} else {
push(@mlist, "<a href=\"search".
&urlargs."\">freetext search</a>");
}
if ($who eq 'find') {
push(@mlist, "<b><i>file search</i></b>");
} else {
push(@mlist, "<a href=\"find".
&urlargs."\">file search</a>");
}
foreach $mode (@mlist) {
$modex .= &expandtemplate($templ,
('modelink', sub { return($mode) }));
}
return($modex);
}
# This is where it gets a bit tricky. varexpand expands the
# "variables" template using varname and varlinks, the latter in turn
# expands the nested "varlinks" template using varval.
sub varlinks {
my $templ = shift;
my $vlex = '';
my ($val, $oldval);
local $vallink;
$oldval = $Conf->variable($var);
foreach $val ($Conf->varrange($var)) {
if ($val eq $oldval) {
$vallink = "<b><i>$val</i></b>";
} else {
if ($who eq 'source') {
$vallink = &fileref($val,
$Conf->mappath($Path->{'virtf'},
"$var=$val"),
0,
"$var=$val");
} elsif ($who eq 'diff') {
$vallink = &diffref($val, $Path->{'virtf'}, "$var=$val");
} elsif ($who eq 'ident') {
$vallink = &idref($val, $identifier, "$var=$val");
} elsif ($who eq 'search') {
$vallink = "<a href=\"search".
&urlargs("$var=$val",
"string=".$HTTP->{'param'}->{'string'}).
"\">$val</a>";
} elsif ($who eq 'find') {
$vallink = "<a href=\"find".
&urlargs("$var=$val",
"string=".$HTTP->{'param'}->{'string'}).
"\">$val</a>";
}
}
$vlex .= &expandtemplate($templ,
('varvalue', sub { return($vallink) }));
}
return($vlex);
}
sub varexpand {
my $templ = shift;
my $varex = '';
local $var;
foreach $var ($Conf->allvariables) {
$varex .= &expandtemplate($templ,
('varname', sub {
return($Conf->vardescription($var))}),
('varlinks', \&varlinks));
}
return($varex);
}
sub makeheader {
local $who = shift;
if ($Conf->htmlhead && !open(TEMPL, $Conf->htmlhead)) {
&warning("Template ".$Conf->htmlhead." does not exist.");
$template ||= "<html><body>\n<hr>\n";
} else {
$save = $/; undef($/);
$template = <TEMPL>;
$/ = $save;
close(TEMPL);
}
print(
#"<!doctype html public \"-//W3C//DTD HTML 3.2//EN\">\n",
# "<html>\n",
# "<head>\n",
# "<title>",$Conf->sourcerootname," Cross Reference</title>\n",
# "<base href=\"",$Conf->baseurl,"\">\n",
# "</head>\n",
&expandtemplate($template,
('title', \&titleexpand),
('banner', \&bannerexpand),
('baseurl', \&baseurl),
('thisurl', \&thisurl),
('modes', \&modeexpand),
('variables', \&varexpand)));
}
sub makefooter {
local $who = shift;
if ($Conf->htmltail && !open(TEMPL, $Conf->htmltail)) {
&warning("Template ".$Conf->htmltail." does not exist.");
$template = "<hr>\n</body>\n";
} else {
$save = $/; undef($/);
$template = <TEMPL>;
$/ = $save;
close(TEMPL);
}
print(&expandtemplate($template,
('banner', \&bannerexpand),
('thisurl', \&thisurl),
('modes', \&modeexpand),
('variables', \&varexpand)),
"</html>\n");
}
1;

View File

@@ -0,0 +1,246 @@
# $Id: Config.pm,v 1.3 1998/04/30 11:58:17 argggh Exp $
package LXR::Config;
use LXR::Common;
require Exporter;
@ISA = qw(Exporter);
# @EXPORT = '';
$confname = 'lxr.conf';
sub new {
my ($class, @parms) = @_;
my $self = {};
bless($self);
$self->_initialize(@parms);
return($self);
}
sub makevalueset {
my $val = shift;
my @valset;
if ($val =~ /^\s*\(([^\)]*)\)/) {
@valset = split(/\s*,\s*/,$1);
} elsif ($val =~ /^\s*\[\s*(\S*)\s*\]/) {
if (open(VALUESET, "$1")) {
$val = join('',<VALUESET>);
close(VALUESET);
@valset = split("\n",$val);
} else {
@valset = ();
}
} else {
@valset = ();
}
return(@valset);
}
sub parseconf {
my $line = shift;
my @items = ();
my $item;
foreach $item ($line =~ /\s*(\[.*?\]|\(.*?\)|\".*?\"|\S+)\s*(?:$|,)/g) {
if ($item =~ /^\[\s*(.*?)\s*\]/) {
if (open(LISTF, "$1")) {
$item = '('.join(',',<LISTF>).')';
close(LISTF);
} else {
$item = '';
}
}
if ($item =~ s/^\((.*)\)/$1/s) {
$item = join("\0",($item =~ /\s*(\S+)\s*(?:$|,)/gs));
}
$item =~ s/^\"(.*)\"/$1/;
push(@items, $item);
}
return(@items);
}
sub _initialize {
my ($self, $conf) = @_;
my ($dir, $arg);
unless ($conf) {
($conf = $0) =~ s#/[^/]+$#/#;
$conf .= $confname;
}
unless (open(CONFIG, $conf)) {
&fatal("Couldn't open configuration file \"$conf\".");
}
while (<CONFIG>) {
s/\#.*//;
next if /^\s*$/;
if (($dir, $arg) = /^\s*(\S+):\s*(.*)/) {
if ($dir eq 'variable') {
@args = &parseconf($arg);
if (@args[0]) {
$self->{vardescr}->{$args[0]} = $args[1];
push(@{$self->{variables}},$args[0]);
$self->{varrange}->{$args[0]} = [split(/\0/,$args[2])];
$self->{vdefault}->{$args[0]} = $args[3];
$self->{vdefault}->{$args[0]} ||=
$self->{varrange}->{$args[0]}->[0];
$self->{variable}->{$args[0]} =
$self->{vdefault}->{$args[0]};
}
} elsif ($dir eq 'sourceroot' ||
$dir eq 'srcrootname' ||
$dir eq 'baseurl' ||
$dir eq 'incprefix' ||
$dir eq 'dbdir' ||
$dir eq 'glimpsebin' ||
$dir eq 'htmlhead' ||
$dir eq 'htmltail' ||
$dir eq 'htmldir') {
if ($arg =~ /(\S+)/) {
$self->{$dir} = $1;
}
} elsif ($dir eq 'map') {
if ($arg =~ /(\S+)\s+(\S+)/) {
push(@{$self->{maplist}}, [$1,$2]);
}
} else {
&warning("Unknown config directive (\"$dir\")");
}
next;
}
&warning("Noise in config file (\"$_\")");
}
}
sub allvariables {
my $self = shift;
return(@{$self->{variables}});
}
sub variable {
my ($self, $var, $val) = @_;
$self->{variable}->{$var} = $val if defined($val);
return($self->{variable}->{$var});
}
sub vardefault {
my ($self, $var) = @_;
return($self->{vdefault}->{$var});
}
sub vardescription {
my ($self, $var, $val) = @_;
$self->{vardescr}->{$var} = $val if defined($val);
return($self->{vardescr}->{$var});
}
sub varrange {
my ($self, $var) = @_;
return(@{$self->{varrange}->{$var}});
}
sub varexpand {
my ($self, $exp) = @_;
$exp =~ s{\$\{?(\w+)\}?}{
$self->{variable}->{$1} =~ /^([a-zA-Z0-9\.\-]*)$/ ? $1 : ''
}ge;
return($exp);
}
sub baseurl {
my $self = shift;
return($self->varexpand($self->{'baseurl'}));
}
sub sourceroot {
my $self = shift;
return($self->varexpand($self->{'sourceroot'}));
}
sub sourcerootname {
my $self = shift;
return($self->varexpand($self->{'srcrootname'}));
}
sub incprefix {
my $self = shift;
return($self->varexpand($self->{'incprefix'}));
}
sub dbdir {
my $self = shift;
return($self->varexpand($self->{'dbdir'}));
}
sub glimpsebin {
my $self = shift;
return($self->varexpand($self->{'glimpsebin'}));
}
sub htmlhead {
my $self = shift;
return($self->varexpand($self->{'htmlhead'}));
}
sub htmltail {
my $self = shift;
return($self->varexpand($self->{'htmltail'}));
}
sub htmldir {
my $self = shift;
return($self->varexpand($self->{'htmldir'}));
}
sub mappath {
my ($self, $path, @args) = @_;
my (%oldvars) = %{$self->{variable}};
my ($m);
foreach $m (@args) {
$self->{variable}->{$1} = $2 if $m =~ /(.*?)=(.*)/;
}
foreach $m (@{$self->{maplist}}) {
$path =~ s/$m->[0]/$self->varexpand($m->[1])/e;
}
$self->{variable} = {%oldvars};
return($path);
}
#sub mappath {
# my ($self, $path) = @_;
# my ($m);
#
# foreach $m (@{$self->{maplist}}) {
# $path =~ s/$m->[0]/$self->varexpand($m->[1])/e;
# }
# return($path);
#}
1;

View File

@@ -0,0 +1,121 @@
In order to install LXR, you will need:
- Perl version 5 or later.
- A webserver with cgi-script capabilities.
and optionally, to enable the freetext search queries:
- Glimpse
If you don't have Perl installed, get it from
<URL:http://www.perl.com/perl/info/software.html>.
If you need a webserver, take a look at Apache at
<URL:http://www.apache.org/>
If you want Glimpse and the freetext searching facilites, visit
<URL:http://glimpse.cs.arizona.edu/>.
LXR has so far been tested on the GNU/Linux operating system using the
Apache webserver. Other unix-like operating systems and decently
featured webservers should do as well.
To install LXR itself:
- Set the variables PERLBIN and INSTALLPREFIX in the makefile to
reflect where the Perl 5 binary is located on your system and where
you want the LXR files to be installed.
- Do "make install".
- Edit $(INSTALLPREFIX)/http/lxr.conf to fit your source code
installations and needs.
- Make sure the files in $(INSTALLPREFIX)/http can be reached via
your webserver. Make sure your webserver executes the files
search, source, ident and diff as cgi-scripts. With the Apache
webserver this can be accomplished by making
$(INSTALLPREFIX)/http/.htaccess contain the following lines:
<Files ~ (search|source|ident|diff)$>
SetHandler cgi-script
</Files>
- Generate the identifier database. Go to the directory you
configured as "dbdir" and do "$(INSTALLPREFIX)/bin/genxref foo",
where foo is the subdirectory containing the actual source code.
- (Optional) Generate the Glimpse database. Go to the directory you
configured as "dbdir" and do "glimpseindex -H . foo", where foo is
the same as above. You might want to add other options to the
commandline (e.g. "-n"), see the Glimpse documentation for details.
If it doesn't work:
- Make sure all the permissions are right. Remember that the
webserver needs to be able to access most of them.
- Check that all the Perl scripts find their library files, also when
executed by the webserver.
The lxr.conf file:
LXR does not care much about your directory structure, all relevant
paths can be configured from the lxr.conf file. This file is located
in the same directory as the perl script files. This makes it
possible to have different source trees in different directories on
the web server.
LXR recognizes the following options in the configuration file.
htmlhead
The header of all html files. This is a template that
contains mainly html code but it can also contain some special
directives, these are documented below.
htmltail
Template for bottom of pages.
htmldir
Template for the directory listing.
sourceroot
The root of the source that you want to index.
sourcerootname
The name of the root (more....)
incprefix
Where to find source specific include files.
dbdir
Where to find the database files that lxr needs (fileidx xref and
the glimpse files).
glimpsebin
Location of the glimpse binary on your system.
variable
This defines a variable that can be used in templates and
the config file. The syntax is
variable: <name>, <text>, <values>, <default>
<name> is the name of the variable, <text> is a textual description,
<values> are the possible values of the variable.
<default> is the default value of the variable.
The <values> field can either be a list starting with a "(" and
ending with a ")", with elements separated with ",", or it can be
[ <filename> ]. In this case the values are read from a file with
one value on each line.
map - This makes it possible to rewrite directories using variables.
The linux sourcecode for instance contains several different
architectures, the include files for each of these are found in the
directory /include/asm-<architecture>/. To remap each of these
according to a variable $a you can specify
map: /include/asm[^\/]*/ /include/asm-$a/
Find creative uses for this option :-)

View File

@@ -0,0 +1,33 @@
# Makefile for installation and configuration of LXR
# The location of your perl5 binary
PERLBIN=/usr/bin/perl
# LXR will be installed here
INSTALLPREFIX=/tmp/lxr
# End of configuration parameters
CGISCRIPTS=find ident search diff source
PERLMODULES=SimpleParse.pm Common.pm Config.pm
config: $(CGISCRIPTS) $(PERLMODULES) genxref
$(CGISCRIPTS) genxref: %: %.in
sed s%@perlbin@%$(PERLBIN)% < $< > $@
install: config genxref
install --directory $(INSTALLPREFIX)/http
install --directory $(INSTALLPREFIX)/http/lib
install --directory $(INSTALLPREFIX)/http/lib/LXR
install --directory $(INSTALLPREFIX)/bin
install --directory $(INSTALLPREFIX)/source
install --mode 755 $(CGISCRIPTS) $(INSTALLPREFIX)/http/
install --mode 750 genxref $(INSTALLPREFIX)/bin/
install --mode 755 Common.pm Config.pm $(INSTALLPREFIX)/http/lib/LXR
install --mode 755 SimpleParse.pm $(INSTALLPREFIX)/http/lib/
install --mode 644 http/* $(INSTALLPREFIX)/http/
clean:
rm -f $(CGISCRIPTS) genxref

View File

@@ -0,0 +1,12 @@
This is version 0.2 of the LXR cross-referencing engine. This is primarily
a security update to version 0.1.
The LXR engine is free software. See the file COPYING for copying
permission.
See the file INSTALL for installation instructions.
To visit the original LXR site, point your browser towards
<URL:http://lxr.linux.no/>.
To contact the authors, send mail to <lxr@linux.no>.

View File

@@ -0,0 +1,107 @@
# $Id: SimpleParse.pm,v 1.2 1998/04/30 11:58:17 argggh Exp $
use strict;
package SimpleParse;
require Exporter;
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(&doparse &untabify &init &nextfrag);
my $INFILE; # Input file handle
my @frags; # Fragments in queue
my @bodyid; # Array of body type ids
my @open; # Fragment opening delimiters
my @term; # Fragment closing delimiters
my $split; # Fragmentation regexp
my $open; # Fragment opening regexp
my $tabwidth; # Tab width
sub init {
my @blksep;
($INFILE, @blksep) = @_;
while (@_ = splice(@blksep,0,3)) {
push(@bodyid, $_[0]);
push(@open, $_[1]);
push(@term, $_[2]);
}
foreach (@open) {
$open .= "($_)|";
$split .= "$_|";
}
chop($open);
foreach (@term) {
next if $_ eq '';
$split .= "$_|";
}
chop($split);
$tabwidth = 8;
}
sub untabify {
my $t = $_[1] || 8;
$_[0] =~ s/([^\t]*)\t/$1.(' ' x ($t - (length($1) % $t)))/ge;
return($_[0]);
}
sub nextfrag {
my $btype = undef;
my $frag = undef;
while (1) {
if ($#frags < 0) {
my $line = <$INFILE>;
if ($. == 1 &&
$line =~ /^.*-[*]-.*?[ \t;]tab-width:[ \t]*([0-9]+).*-[*]-/) {
$tabwidth = $1;
}
&untabify($line, $tabwidth);
# $line =~ s/([^\t]*)\t/
# $1.(' ' x ($tabwidth - (length($1) % $tabwidth)))/ge;
@frags = split(/($split)/o, $line);
}
last if $#frags < 0;
unless ($frags[0]) {
shift(@frags);
} elsif (defined($frag)) {
if (defined($btype)) {
my $next = shift(@frags);
$frag .= $next;
last if $next =~ /^$term[$btype]$/;
} else {
last if $frags[0] =~ /^$open$/o;
$frag .= shift(@frags);
}
} else {
$frag = shift(@frags);
if (defined($frag) && (@_ = $frag =~ /^$open$/o)) {
my $i = 1;
$btype = grep { $i = ($i && !defined($_)) } @_;
}
}
}
$btype = $bodyid[$btype] if $btype;
return($btype, $frag);
}
1;

View File

@@ -0,0 +1,206 @@
#!@perlbin@
# $Id: diff,v 1.2 1998/04/30 11:58:15 argggh Exp $
# diff -- Display diff output with markup.
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
######################################################################
use lib 'lib/';
use SimpleParse;
use LXR::Common;
use LXR::Config;
use DB_File;
sub htmlsub {
my ($s, $l) = @_;
my @s = split(/(<[^>]*>|&[\#\w\d]+;?)/, $s);
$s = '';
while (@s) {
my $f = substr(shift(@s), 0, $l);
$l -= length($f);
$s .= $f;
$f = shift(@s);
if ($f =~ /^&/) {
if ($l > 0) {
$s .= $f;
$l--;
}
} else {
$s .= $f;
}
}
$s .= ' ' x $l;
return $s;
}
sub printdiff {
unless ($diffvar) {
foreach ($Conf->allvariables) {
push(@vars, $Conf->vardescription($_));
}
$vars[$#vars-1] .= " or ".pop(@vars) if $#vars > 0;
print("<p align=center>\n",
"Please indicate the version of the file you wish to\n",
"compare to by clicking on the appropriate\n",
join(", ",@vars)," button.\n",
"</p>\n");
return;
}
unless ($Path->{'file'}) {
print("<h3 align=center>Diff not yet supported for directories.</h3>\n");
return;
}
$origvirt = $Path->{'virt'}.$Path->{'file'};
$origreal = $Path->{'real'}.$Path->{'file'};
$origval = $Conf->variable($diffvar);
$Conf->variable($diffvar,$diffval);
$diffvirt = $Conf->mappath($Path->{'virt'}).$Path->{'file'};
$diffreal = $Conf->sourceroot.$diffvirt;
$Conf->variable($diffvar,$origval);
# print("<h3>Diff of $origvirt -> $diffvirt</h3>\n");
# print("<h3>($origreal -> $diffreal)</h3>\n");
# FIXME: Check existence of $origreal & $diffreal.
&fflush;
unless (open(DIFF, "-|")){
open(STDERR, ">&STDOUT");
exec('diff', '-U0', $origreal, $diffreal);
print "*** Diff subprocess died unexpextedly: $!\n";
exit;
}
while (<DIFF>) {
if (($os, $ol, $ns, $nl) =
/@@ -(\d+)(?:,(\d+)|) \+(\d+)(?:,(\d+)|) @@/) {
$os++ if $ol eq '0';
$ns++ if $nl eq '0';
$ol = 1 unless defined($ol);
$nl = 1 unless defined($nl);
$bo = $os + $ofs;
if ($ol < $nl) {
$ofs += $nl - $ol;
$dir = '&gt;&gt;';
$ms = $nl - $ol;
$ml = $ol;
$orig{$os+$ol} = $ms;
} else {
$dir = '&lt;&lt;';
$ms = $ol - $nl;
$ml = $nl;
$new{$ns+$nl} = $ms;
}
foreach (0..$ml - 1) {
$chg{$bo + $_} = '!!';
}
foreach (0..$ms - 1) {
$chg{$bo + $ml + $_} = $dir;
}
}
}
close(<DIFF>);
print("<h1>Diff markup</h1>\n",
"<h3>Differences between ",
&fileref("$origvirt <i>(".$Conf->vardescription($diffvar).
" $origval)</i>", $origvirt, undef, "$diffvar=$origval"),
" and ",
&fileref("$diffvirt <i>(".$Conf->vardescription($diffvar).
" $diffval)</i>",$diffvirt, undef, "$diffvar=$diffval"),
"</h3><hr>\n");
# "<table width=\"100%\" border=0 cellpadding=0><tr><td>",
#
# &fileref("<b>$origvirt <i>(".$Conf->vardescription($diffvar).
# " $origval)</i></b>", $origvirt, undef, "$diffvar=$origval"),
# "<hr></td>\n<td></td>\n<td>",
#
# &fileref("<b>$diffvirt <i>(".$Conf->vardescription($diffvar).
# " $diffval)</i></b>",$diffvirt, undef, "$diffvar=$diffval"),
# "<hr></td>\n</tr></table>\n");
open(FOO, $origreal);
$orig = '';
&markupfile(\*FOO, $Path->{'virt'}, $Path->{'file'},
sub { $orig .= shift });
$len = $.+$ofs;
close(FOO);
$Conf->variable($diffvar, $diffval);
open(FOO, $diffreal);
$new = '';
&markupfile(\*FOO, $Conf->mappath($Path->{'virt'}), $Path->{'file'},
sub { $new .= shift });
close(FOO);
$Conf->variable($diffvar, $origval);
$i = 1; $orig =~ s/^/"\n" x ($orig{$i++})/mge;
$i = 1; $new =~ s/^/"\n" x ($new{$i++})/mge;
@orig = split(/\n/, $orig);
@new = split(/\n/, $new);
print("<pre>");
foreach $i (0..$len) {
$o = &htmlsub($orig[$i], 50);
# $n = &htmlsub($new[$i], 999);
$n = $new[$i];
# print("<tr><td><code>$o</code></td>".
# "<td><font color=red> ", $chg{$i+1}, " </font></td>".
# "<td><code>$n</code></td></tr>\n");
print("$o <font color=red>", ($chg{$i+1} || " "), "</font> $n\n");
}
print("</pre>");
# print("</td></tr></table>");
}
($Conf, $HTTP, $Path) = &init;
$diffvar = $HTTP->{'param'}->{'diffvar'};
$diffval = $HTTP->{'param'}->{'diffval'};
&makeheader('diff');
&printdiff;
&makefooter('diff');

View File

@@ -0,0 +1,71 @@
#!@perlbin@
# $Id: find,v 1.3 1998/04/30 11:58:16 argggh Exp $
# find -- Find files
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
######################################################################
use lib 'lib/';
use LXR::Common;
use LXR::Config;
sub find {
print("<p align=center>\n",
"Search for files using regular expressions\n",
"<form method=get action=\"find\">\n");
foreach ($Conf->allvariables) {
if ($Conf->variable($_) ne $Conf->vardefault($_)) {
print("<input type=hidden name=\"",$_, "\" ",
"value=\"", $Conf->variable($_), "\">\n");
}
}
print("Find file: <input type=text name=\"string\" ",
"value=\"",$searchtext,"\" size =60>\n",
"<input type=submit value=\"search\">\n",
"</form>\n");
if ($searchtext ne "") {
unless (open(FILELLISTING,$Conf->dbdir."/.glimpse_filenames")) {
&warning("Could not open .glimpse_filenames.");
return;
}
print("<hr>\n");
$sourceroot = $Conf->sourceroot;
while($file = <FILELLISTING>) {
$file =~ s/^$sourceroot//;
if($file =~ /$searchtext/) {
print(&fileref("$file", "/$file"),"<br>\n");
}
}
}
}
($Conf, $HTTP, $Path) = &init;
$searchtext = $HTTP->{'param'}->{'string'};
&makeheader('find');
&find;
&makefooter('find');

View File

@@ -0,0 +1,338 @@
#!@perlbin@
# $Id: genxref,v 1.5 1998/04/22 12:16:12 pergj Exp $
# genxref.pl -- Finds identifiers in a set of C files using an
# extremely fuzzy algorithm. It sort of works.
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
# TODO: ns/cmd/xfe/src/MozillaApp.h, XFE_MozillaApp
######################################################################
use lib 'lib/';
use integer;
use DB_File;
%itype = (('macro', 'M'),
('typedef', 'T'),
('struct', 'S'),
('enum', 'E'),
('union', 'U'),
('function', 'F'),
('funcprot', 'f'),
('class', 'C'), # (C++)
('classforw', 'c'), # (C++)
('var', 'V'));
# ('reference', 'R')
@reserved = ('auto', 'break', 'case', 'char', 'const', 'continue',
'default', 'do', 'double', 'else', 'enum', 'extern',
'float', 'for', 'goto', 'if', 'int', 'long', 'register',
'return', 'short', 'signed', 'sizeof', 'static',
'struct', 'switch', 'typedef', 'union', 'unsigned',
'void', 'volatile', 'while', 'fortran', 'asm',
'inline', 'operator',
'class', # (C++)
# Her b<>r vi ha flere av disse:
'__asm__','__inline__');
$ident = '\~?_*[a-zA-Z][a-zA-Z0-9_]*';
$realpath = $ARGV[0];
$realpath ||= '.';
$realpath .= '/';
sub wash {
my $towash = $_[0];
$towash =~ s/[^\n]+//gs;
return($towash);
}
sub stripodd {
my $tostrip = $_[0];
while ($tostrip =~ s/\{([^\{\}]*)\}/
"\05".&wash($1)/ges) {}
$tostrip =~ s/\05/\{\}/gs;
$tostrip =~ s/[\{\}]//gs;
return($tostrip);
}
sub classes {
my @c = (shift =~ /($ident)\s*(?:$|,)/gm);
if (@c) {
return(join(":", @c)."::");
} else {
return('');
}
}
sub findident {
print(STDERR "Starting pass 1: Collect identifier definitions.\n");
$start = time;
$fnum = 0; $defs = 0;
foreach $f (@f) {
$f =~ s/^$realpath//o;
$fileidx{++$fnum} = $f;
open(SRCFILE, $realpath.$f);
$_ = $/; undef($/); $contents = <SRCFILE>; $/ = $_;
close(SRCFILE);
print(STDERR
"(Pass 1) $f (",length($contents),
"), file $fnum of ",$#f+1,"...\n");
# Remove comments.
$contents =~ s/\/\*(.*?)\*\//&wash($1)/ges;
$contents =~ s/\/\/[^\n]*//g; # C++
# Unwrap continunation lines.
$contents =~ s/\\\s*\n/$1\05/gs;
while ($contents =~ s/\05([^\n\05]+)\05/$1\05\05/gs) {}
$contents =~ s/(\05+)([^\n]*)/"$2"."\n" x length($1)/gse;
# Find macro (un)definitions.
$l = 0;
foreach ($contents =~ /^(.*)/gm) {
$l++;
if (/^[ \t]*\#\s*(define|undef)\s+($ident)/o) {
$xref{$2} .= "$itype{'macro'}$fnum:$l\t";
$defs++;
}
}
# We want to do some funky heuristics with preprocessor blocks
# later, so mark them. (FIXME: #elif)
$contents =~ s/^[ \t]*\#\s*if.*/\01/gm;
$contents =~ s/^[ \t]*\#\s*else.*/\02/gm;
$contents =~ s/^[ \t]*\#\s*endif.*/\03/gm;
# Strip all preprocessor directives.
$contents =~ s/^[ \t]*\#(.*)//gm;
# Now, remove all odd block markers ({,}) we find inside
# #else..#endif blocks. (And pray they matched one in the
# preceding #if..#else block.)
while ($contents =~ s/\02([^\01\02\03]*\03)/&stripodd($1)/ges ||
$contents =~ s/\01([^\01\02\03]*)\03/$1/gs) {}
while ($contents =~ /([\01\02\03\04\05])/gs) {
print(STDERR "\t ** stray ".($1 eq "\01"
? "#if"
: ($1 eq "\02"
? "#else"
: ($1 eq "\03"
? "#endif"
: "control sequence"
)
)
)." found.\n");
}
$contents =~ s/[\01\02\03\04\05]//gs;
# Remove all but outermost blocks. (No local variables.)
while ($contents =~ s/\{([^\{\}]*)\}/
"\05".&wash($1)/ges) {}
$contents =~ s/\05/\{\}/gs;
# Remove nested parentheses.
while ($contents =~ s/\(([^\)]*)\(/\($1\05/g ||
$contents =~ s/\05([^\(\)]*)\)/ $1 /g) {}
# Some heuristics here: Try to recognize "code" and delete
# everything up to the next block delimiter.
# $contents =~ s/([\;\}\{])(\s*$ident\s*\([^\)]*\)[^\{\}]*)/
# "$1".&wash($2)/goes;
# $contents =~ s/([\;\{])(\s*\**$ident\s*\=[^\{\}]*)/
# "$1".&wash($2)/goes;
# Parentheses containing commas are probably not interesting.
$contents =~ s/\(([^\)]*\,[^\)]*)\)/
"()".&wash($1)/ges;
# This operator-stuff messes things up. (C++)
$contents =~ s/operator[\<\>\=\!\+\-\*\%\/]{1,2}/operator/g;
# Ranges are uninteresting (and confusing).
$contents =~ s/\[.*?\]//gs;
# And so are assignments.
$contents =~ s/\=(.*?);/";".&wash($1)/ges;
# From here on, \01 and \02 are used to encapsulate found
# identifiers,
# Find struct, enum and union definitions.
$contents =~ s/((struct|enum|union)\s+($ident|)\s*({}|(;)))/
"$2 ".($3 ? "\01".$itype{$2}.$3."\02 " : "").$5.&wash($1)/goes;
# Find class definitions. (C++)
$contents =~ s/((class)\s+($ident)\s*(:[^;\{]*|)({}|(;)))/
"$2 "."\01".$itype{$2.($6 ? 'forw' : '')}.
&classes($4).$3."\02 ".$6.&wash($1)/goes;
@contents = split(/[;\}]/, $contents);
$contents = '';
foreach (@contents) {
s/^(\s*)(struct|enum|union|inline)/$1/;
if (/$ident[^a-zA-Z0-9_]+$ident/) { # It takes two, baby.
$t = /^\s*typedef/s; # Is this a type definition?
s/($ident(?:\s*::\s*$ident|)) # ($1) Match the identifier
([\s\)]* # ($2) Tokens allowed after identifier
(\([^\)]*\) # ($3) Function parameters?
(?:\s*:[^\{]*|) # inheritage specification (C++)
|) # No function parameters
\s*($|,|\{))/ # ($4) Allowed termination chars.
"\01". # identifier marker
($t # if type definition...
? $itype{'typedef'} # ..mark as such
: ($3 # $3 is empty unless function definition.
? ($4 eq '{' # Terminating token indicates
? $itype{'function'} # function or
: $itype{'funcprot'}) # function prototype.
: $itype{'var'}) # Variable.
)."$1\02 ".&wash($2)/goesx;
}
$contents .= $_;
}
$l = 0;
foreach ($contents =~ /^(.*)/gm) {
$l++;
while (/\01(.)(?:(.+?)\s*::\s*|)($ident)\02/go) {
$xref{$3} .= "$1$fnum:$l".($2 ? ":$2" : "")."\t";
$defs++;
}
}
}
# S<> juksar me litt.
foreach (@reserved) {
delete($xref{$_});
}
print(STDERR
"Completed pass 1 (",(time-$start),"s):",
" $defs definitions found.\n\n");
}
sub findusage {
print(STDERR "Starting pass 2: Generate reference statistics.\n");
$start = time;
$fnum = 0; $refs = 0;
foreach $f (@f) {
$f =~ s/^$realpath//o;
$fnum++;
$lcount = 0;
%tref = ();
open(SRCFILE, $realpath.$f);
$_ = $/; undef($/); $contents = <SRCFILE>; $/ = $_;
close(SRCFILE);
print(STDERR
"(Pass 2) $f (",length($contents),
"), file $fnum of ",$#f+1,"...\n");
# Remove comments
$contents =~ s/\/\*(.*?)\*\//&wash($1)/ges;
$contents =~ s/\/\/[^\n]*//g;
# Remove include statements
$contents =~ s/^[ \t]*\#include[ \t]+[^\n]*//gm;
# FIXME: "var"
@lines = split(/\n/, $contents);
foreach $line (@lines) {
$lcount++;
foreach ($line =~ /(?:^|[^a-zA-Z_\#])($ident)\b/og) {
$tref{$_} .= "$lcount," if $xref{$_};
}
}
while (($a, $b) = each(%tref)) {
chop($b);
$xref{$a} .= "R$fnum:$b\t";
$refs++;
}
}
print(STDERR
"Completed pass 2 (",(time-$start),"s):",
"$refs references to known identifiers found.\n\n");
}
sub dumpdb {
print(STDERR "Starting pass 3: Dump database to disk.\n");
$start = time;
tie (%xrefdb, "DB_File" , "xref", O_RDWR|O_CREAT, 0664, $DB_HASH)
|| die("Could not open \"xref\" for writing");
$i = 0;
while (($k, $v) = each(%xref)) {
$i++;
delete($xref{$k});
$xrefdb{$k} = $v;
unless ($i % 100) {
print(STDERR "(Pass 3) identifier $i of maximum $defs...\n");
}
}
untie(%xrefdb);
print(STDERR
"Completed pass 3 (",(time-$start),"s):",
"Information on $i identifiers dumped to disk.\n\n");
}
tie (%fileidx, "DB_File", "fileidx", O_RDWR|O_CREAT, 0660, $DB_HASH)
|| die("Could not open \"fileidx\" for writing");
open(FILES, "find $realpath -print |");
while (<FILES>) {
chop;
push(@f, $_) if /\.([ch]|cpp?|cc)$/i; # Duplicated in lib/LXR/Common.pm
}
close(FILES);
&findident;
&findusage;
&dumpdb;
dbmclose(%fileidx);

View File

@@ -0,0 +1,108 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>Linux Cross-Reference</TITLE>
</HEAD>
<BODY BGCOLOR=WHITE>
<H1 ALIGN=CENTER>
Cross-Referencing Linux<BR>
<A HREF="http:source/">
<I>Browse the code</I></A></H1>
<HR><H2>Motivation</H2>
The Linux Cross-Reference project is the testbed application of a
general hypertext cross-referencing tool. (Or the other way around.)
<P>
The main goal of the project is to create a versatile
cross-referencing tool for relatively large code repositories. The
project is based on stock web technology, so the codeview client may
be chosen from the full range of available web browsers. On the
server side, any Unix-based web server with cgi-script capability
should do nicely.
<P>
The main feature of the indexer is of course the ability to jump
easily to the declaration of any global identifier. Indeed, even all
<I>references</I> to global identifiers are indexed. Quick access to
function declarations, data (type) definitions and preprocessor macros
makes code browsing just that tad more convenient. At-a-glance
overview of e.g. which code areas that will be affected by changing a
function or type definition should also come in useful during
development and debugging.
<P>
Other bits of hypertextual sugar, such as e-mail and include file
links, are provided as well, but is on the whole, well, sugar. Some
minimal visual markup is also done. (Style sheets are considered as a
way to do this in the future.)
<HR><H2>Technicalities</H2>
The index generator is written in <A HREF="http://www.perl.org">Perl</A>
and relies heavily on Perl's regular expression facilities. The
algorithm used is very brute force and extremely sloppy. The
rationale behind the sloppiness is that too little information renders
the database useless, while too much information simply means the
users have to think and navigate at the same time.
<P>
The Linux source code, with which the project has initially been
linked, presents the indexer with some very tough obstacles.
Specifically, the heavy use of preprocessor macros makes the parsing a
virtual nightmare. We want to index the information in the
preprocessor directives as well as the actual C code, so we have to
parse both at once, which leads to no end of trouble. (Strict parsing
is right out.) Still, we're pretty satisfied with what the indexer
manages to get out of it.
<P>
There's also the question of actually broken code. We want to
reasonably index all code portions, even if some of it is not entirely
syntactically valid. This is another reason for the sloppiness.
<P>
There are obviously disadvantages to this approach. No scope checking
is done, and the most annoying effect of this is mistaking local
identifers for references to global ones with the same name. This
particular problem (and others) can only be solved by doing (almost)
full parsing. The feasibility of combining this with the fuzzy way
indexing is currently done is being looked into.
<P>
An identifier is a macro, typedef, struct, enum, union, function,
function prototype or variable. For the Linux source code between
50000 and 60000 identifiers are collected. The individual files of the
sourcecode are formatted on the fly and presented with clickable
identifiers.
<P>
It is possible to search among the identifiers and the entire
kernel source text. The freetext search is implemented using <A
HREF="http://glimpse.cs.arizona.edu">Glimpse</A>, so all the
capabilities of Glimpse are available. Especially the regular expression
search capabilities are useful.
<HR><H2>Availability</H2>
The code for the indexer is released under the
<A HREF="http://www.gnu.org">GNU</A>
<A HREF="http://www.gnu.org/copyleft/copyleft.html">Copyleft</A>
license. Go to <A HREF="http://lxr.linux.no">LXR main site</A> to
get the latest version.
<HR><H2>Contacting the authors</H2>
We would very much like to receive feedback on this project. If you
find it useful or have suggestions on how to make improvements, feel
free to send us e-mail. We hope that this will be a useful tool, both
for experienced developers and beginners wanting to explore the Linux
sourcecode.
<HR>
<ADDRESS>
<A HREF="mailto:lxr@linux.no">
Arne Georg Gleditsch and Per Kristian Gjermshus</A>
</ADDRESS>
</BODY>
</HTML>

View File

@@ -0,0 +1,37 @@
# Configuration file.
# Define typed variable "v", read valueset from file.
variable: v, Version, [/local/lxr/source/versions], [/local/lxr/source/defversion]
# Define typed variable "a". First value is default.
variable: a, Architecture, (i386, alpha, m68k, mips, ppc, sparc, sparc64)
# Define the base url for the LXR files.
baseurl: http://lxr/
# These are the templates for the HTML heading, directory listing and
# footer, respectively.
htmlhead: /local/lxr/http/template-head
htmltail: /local/lxr/http/template-tail
htmldir: /local/lxr/http/template-dir
# The source is here.
sourceroot: /local/lxr/source/$v/linux/
srcrootname: Linux
# "#include <foo.h>" is mapped to this directory (in the LXR source
# tree)
incprefix: /include
# The database files go here.
dbdir: /local/lxr/source/$v/
# Glimpse can be found here.
glimpsebin: /local/bin/glimpse
# The power of regexps. This is pretty Linux-specific, but quite
# useful. Tinker with it and see what it does. (How's that for
# documentation?)
map: /include/asm[^\/]*/ /include/asm-$a/
map: /arch/[^\/]+/ /arch/$a/

View File

@@ -0,0 +1,139 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>Linux Cross-Reference</TITLE>
</HEAD>
<BODY BGCOLOR=WHITE>
<H1 ALIGN=CENTER>
Help doing searches<BR>
<A HREF="http:/source/">
<I>Browse the code</I></A></H1>
<I> This text is directly stolen from the Glimpse manual page. I have
tried to remove things that do not apply to the lxr searcher, but
beware, some things might have slipped through. I'll try to put
together something better when I get the time. For more information on
glimpse go to the <A HREF="http://glimpse.cs.arizona.edu">Glimpse
homepage</A>.</I>
<A NAME="Patterns"></A><H2>Patterns</H2>
<P>
glimpse supports a large variety of patterns, including simple
strings, strings with classes of characters, sets of strings,
wild cards, and regular expressions (see <A HREF="#Limitations">Limitations</A>).
<P> <H3>Strings</H3>
Strings are any sequence of characters, including the special symbols
`^' for beginning of line and `$' for end of line. The following
special characters (`$', `^', `*', `[', `^', `|', `(', `)', `!', and
`\' ) as well as the following meta characters special to glimpse (and
agrep): `;', `,', `#', `&gt;', `&lt;', `-', and `.', should be preceded by
`\\' if they are to be matched as regular characters. For example,
\\^abc\\\\ corresponds to the string ^abc\\, whereas ^abc corresponds
to the string abc at the beginning of a line.
<P> <H3>Classes of characters</H3>
a list of characters inside [] (in order) corresponds to any character
from the list. For example, [a-ho-z] is any character between a and h
or between o and z. The symbol `^' inside [] complements the list.
For example, [^i-n] denote any character in the character set except
character 'i' to 'n'.
The symbol `^' thus has two meanings, but this is consistent with
egrep.
The symbol `.' (don't care) stands for any symbol (except for the
newline symbol).
<P> <H3>Boolean operations</H3>
Glimpse
supports an `AND' operation denoted by the symbol `;'
an `OR' operation denoted by the symbol `,',
a limited version of a 'NOT' operation (starting at version 4.0B1)
denoted by the symbol `~',
or any combination.
For example, pizza;cheeseburger' will output all lines containing
both patterns.
'{political,computer};science' will match 'political science'
or 'science of computers'.
<P><H3>Wild cards</H3>
The symbol '#' is used to denote a sequence
of any number (including 0)
of arbitrary characters (see <A HREF="#Limitations">Limitations</A>).
The symbol # is equivalent to .* in egrep.
In fact, .* will work too, because it is a valid regular expression
(see below), but unless this is part of an actual regular expression,
# will work faster.
(Currently glimpse is experiencing some problems with #.)
<P><H3>Combination of exact and approximate matching</H3>
Any pattern inside angle brackets &lt;&gt; must match the text exactly even
if the match is with errors. For example, &lt;mathemat&gt;ics matches
mathematical with one error (replacing the last s with an a), but
mathe&lt;matics&gt; does not match mathematical no matter how many errors are
allowed. (This option is buggy at the moment.)
<H3>Regular expressions</H3>
Since the index is word based, a regular expression must match words
that appear in the index for glimpse to find it. Glimpse first strips
the regular expression from all non-alphabetic characters, and
searches the index for all remaining words. It then applies the
regular expression matching algorithm to the files found in the index.
For example, glimpse 'abc.*xyz' will search the index for all files
that contain both 'abc' and 'xyz', and then search directly for
'abc.*xyz' in those files. (If you use glimpse -w 'abc.*xyz', then
'abcxyz' will not be found, because glimpse will think that abc and
xyz need to be matches to whole words.) The syntax of regular
expressions in glimpse is in general the same as that for agrep. The
union operation `|', Kleene closure `*', and parentheses () are all
supported. Currently '+' is not supported. Regular expressions are
currently limited to approximately 30 characters (generally excluding
meta characters). The maximal number of errors
for regular expressions that use '*' or '|' is 4.
<P>
<A NAME="Limitations"></A><H2>Limitations</H2>
The index of glimpse is word based. A pattern that contains more than
one word cannot be found in the index. The way glimpse overcomes this
weakness is by splitting any multi-word pattern into its set of words
and looking for all of them in the index.
For example, <I>'linear programming'</I> will first consult the index
to find all files containing both <I>linear</I> and <I>programming</I>,
and then apply agrep to find the combined pattern.
This is usually an effective solution, but it can be slow for
cases where both words are very common, but their combination is not.
<P>
As was mentioned in the section on <A HREF="#Patterns">Patterns</A> above, some characters
serve as meta characters for glimpse and need to be
preceded by '\\' to search for them. The most common
examples are the characters '.' (which stands for a wild card),
and '*' (the Kleene closure).
So, "glimpse ab.de" will match abcde, but "glimpse ab\\.de"
will not, and "glimpse ab*de" will not match ab*de, but
"glimpse ab\\*de" will.
The meta character - is translated automatically to a hypen
unless it appears between [] (in which case it denotes a range of
characters).
<P>
There is no size limit for simple patterns and simple patterns
within Boolean expressions.
More complicated patterns, such as regular expressions,
are currently limited to approximately 30 characters.
Lines are limited to 1024 characters.
<P>
<HR>
<ADDRESS>
<A HREF="mailto:lxr@linux.no">
Arne Georg Gleditsch and Per Kristian Gjermshus</A>
</ADDRESS>
</BODY>
</HTML>

View File

@@ -0,0 +1,15 @@
<table border=0 cellspacing=4>
<tr valign=middle>
<td>
<td nowrap><b>Name</b>
<td nowrap><b>Size</b>
<td nowrap><b>Last modified (GMT)</b>
<td nowrap><b>Description</b>
$files{
<tr valign=middle>
<td nowrap>$iconlink
<td nowrap>$namelink
<td nowrap align=right>$filesize{$bytes bytes}
<td nowrap>$modtime
<td>$description{<i>$desctext</i>}}
</table>

View File

@@ -0,0 +1,27 @@
<!doctype html public "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>$title</title>
<base href="$baseurl">
</head>
<body bgcolor=white>
<div align=center>
$modes{ ~ <b>[</b>&nbsp;$modelink&nbsp;<b>]</b>} ~
</div>
<h1 align=center>
<a href="http://www.linux.org/">
Linux</a>
<a href="http:blurb.html">
Cross Reference</a><br>
$banner
</h1>
<div align=center>
$variables{
<b>$varname:</b>
$varlinks{ ~ <b>[</b>&nbsp;$varvalue&nbsp;<b>]</b>} ~
<br>}
</div>
<hr>

View File

@@ -0,0 +1,11 @@
<hr>
<div align=center>
$modes{ ~ <b>[</b>&nbsp;$modelink&nbsp;<b>]</b>} ~
</div>
<hr>
This page was automatically generated by the
<a href="http:blurb.html">LXR engine</a>.
<br>
Visit the <a href="http://lxr.linux.no/">LXR main site</a> for more
information.

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

View File

@@ -0,0 +1,161 @@
#!@perlbin@
# $Id: ident,v 1.6 1998/04/30 11:58:16 argggh Exp $
# ident -- Look up identifiers
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
######################################################################
use lib 'lib/';
use LXR::Common;
use LXR::Config;
use DB_File;
%ty = (('M', 'preprocessor macro'),
('V', 'variable'),
('f', 'function prototype'),
('F', 'function'),
('C', 'class'), # C++
('c', '(forwarded) class'), # C++
('T', 'type'),
('S', 'struct type'),
('E', 'enum type'),
('U', 'union type'));
sub ident {
print("<form method=get action=\"ident\">\n");
foreach ($Conf->allvariables) {
if ($Conf->variable($_) ne $Conf->vardefault($_)) {
print("<input type=hidden name=\"",$_, "\" ",
"value=\"", $Conf->variable($_), "\">\n");
}
}
print("Identifier: <input type=text name=\"i\" ",
"value=\"",$identifier,"\" size=60>\n",
"<input type=submit value=\"Go get it\">\n",
"</form>\n");
if ($identifier) {
tie(%xref, "DB_File", $Conf->dbdir."/xref",
O_RDONLY, undef, $DB_HASH) ||
&fatal("Could not open \"".$Conf->dbdir."/xref\"");
@refs = split(/\t/,$xref{$identifier});
print("<h1>$identifier</h1>\n");
if (@refs) {
tie(%fileidx, "DB_File", $Conf->dbdir."/fileidx",
O_RDONLY, undef, $DB_HASH) ||
&fatal("Could not open \"".$Conf->dbdir."/fileidx\"");
foreach (@refs) {
$f{$1} .= "$2\t" if /^(.)(.*)/;
}
foreach $t (keys(%ty)) {
if ($f{$t}) {
print("Defined as a $ty{$t} in:<ul>\n");
@_ = split(/\t/, $f{$t});
unshift(@_);
foreach (@_) {
($fnum, $line, @clss) = split(/:/, $_);
print("<li>",
&fileref("$fileidx{$fnum}, line $line",
"/$fileidx{$fnum}", $line));
if (@clss) {
if ($t eq 'F' || $t eq 'f') {
print(", as member of ");
if ($xref{$clss[0]}) {
print(&idref("class $clss[0]", $clss[0]));
} else {
print("class $clss[0]");
}
} elsif ($t eq 'C') {
print(", inheriting <ul>\n");
foreach (@clss) {
print("<li>");
if ($xref{$_}) {
print(&idref("class $_", $clss[0]));
} else {
print("class $_");
}
}
print("</ul>");
}
}
print("\n");
}
print("</ul>\n");
}
}
print("Referenced (in ",int(grep(/^R/, @refs))," files total) in:\n",
"<ul>\n");
$concise = $#refs > 100;
foreach (@refs) {
if (/^R(.+):([\d,]+)/) {
$fnam = $fileidx{$1};
@fpos = split(/,/, $2);
if ($#fpos > 0) {
if ($concise) {
print("<li>", &fileref("$fnam", "/$fnam"),
", ",$#fpos+1," times\n");
} else {
print("<li>$fnam:\n<ul>\n");
foreach (@fpos) {
print("<li>", &fileref("line $_",
"/$fnam", $_),
"\n");
}
print("</ul>\n");
}
} else {
print("<li>", &fileref("$fnam, line $fpos[0]",
"/$fnam", $fpos[0]),
"\n");
}
}
}
print("</ul>\n");
untie(%fileidx);
} else {
print("<br><b>Not used</b>");
}
untie(%xref);
}
}
($Conf, $HTTP, $Path) = &init;
$identifier = $HTTP->{'param'}->{'i'};
&makeheader('ident');
&ident;
&makefooter('ident');

View File

@@ -0,0 +1,127 @@
#!@perlbin@
# $Id: search,v 1.3 1998/04/30 11:58:16 argggh Exp $
# search -- Freetext search
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
######################################################################
use lib 'lib/';
use LXR::Common;
use LXR::Config;
$maxhits = 1000;
sub search {
print("<p align=center>\n",
"This searchpage is powered by ",
"<a href=\"http://glimpse.cs.arizona.edu\">Glimpse</a>\n");
print("<form method=get action=\"search\">\n");
foreach ($Conf->allvariables) {
if ($Conf->variable($_) ne $Conf->vardefault($_)) {
print("<input type=hidden name=\"",$_, "\" ",
"value=\"", $Conf->variable($_), "\">\n");
}
}
print("Search for: <input type=text name=\"string\" ",
"value=\"",$searchtext,"\" size=60>\n",
"<input type=submit value=\"search\">\n",
# $Query->checkbox("case",0,0,"Case sensitive search"),
# $Query->checkbox("regexp",1,0,"Regular expression search"),
# $Query->popup_menu("fuzz",[0,1,2,3,4,5,6,7],0),
"</form>\n",
"<a href=\"search_help.html\">Hints</a> ",
"making queries.\n");
$| = 1; print('');
if ($searchtext ne "") {
print("<hr>\n");
unless (open(GLIMPSE, "-|")) {
open(STDERR, ">&STDOUT");
$!='';
exec($Conf->glimpsebin,"-H".$Conf->dbdir,'-y','-n',$searchtext);
print("Glimpse subprocess died unexpextedly: $!\n");
exit;
}
$numlines = 0;
while (<GLIMPSE>) {
$numlines++;
push(@glimpselines,$_);
if ($numlines > $maxhits) {
last;
}
}
close(GLIMPSE);
$retval = $? >> 8;
# The manpage for glimpse says that it returns 2 on syntax errors or
# inaccessible files. It seems this is not the case.
# We will have to work around it for the time being.
if ($retval == 0) {
if (@glimpselines == 0) {
print("No matching files<br>\n");
} else {
if ($numlines > $maxhits) {
print("<b> Too many hits, displaying first $maxhits</b><br>\n");
}
print("<h1>$searchtext</h1>\n");
$sourceroot = $Conf->sourceroot;
foreach $glimpseline (@glimpselines) {
$glimpseline =~ s/$sourceroot//;
($file, $line, $text) =
$glimpseline =~ /(.*?):\s*(\d+)\s*:(.*)/;
$text =~ s/&/&amp;/g;
$text =~ s/</&lt;/g;
$text =~ s/>/&gt;/g;
print(&fileref("$file, line $line", "/$file", $line),
" -- $text<br>\n");
}
}
} elsif ($retval == 1) {
$glimpsebin = $Conf->glimpsebin;
$glimpseresponse = join("<br>",@glimpselines);
$glimpseresponse =~ s/$glimpsebin/Reason/;
$glimpseresponse =~ s/glimpse: error in searching index//;
print("<b>Search failed</b><br>\n$glimpseresponse");
} else {
print("Unexpected returnvalue $retval from Glimpse\n");
}
}
}
($Conf, $HTTP, $Path) = &init;
$searchtext = $HTTP->{'param'}->{'string'};
&makeheader('search');
&search;
&makefooter('search');

View File

@@ -0,0 +1,235 @@
#!@perlbin@
# $Id: source,v 1.4 1998/05/14 11:59:22 argggh Exp $
# source -- Present sourcecode as html, complete with references
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
######################################################################
use lib 'lib/';
use SimpleParse;
use LXR::Common;
use LXR::Config;
sub descexpand {
my $templ = shift;
if ($index{$filename}) {
return(&expandtemplate($templ,
('desctext', sub {return($index{$filename})})
));
} else {
return('');
}
}
sub diricon {
if ($filename eq '..') {
return(&fileref("<img src=\"/icons/back.gif\"".
" border=0 alt=\"Back\">",
$parentdir));
} else {
return(&fileref("<img src=\"/icons/folder.gif\"".
" border=0 alt=\"Folder\">",
$Path->{'virt'}.$filename));
}
}
sub dirname {
if ($filename eq '..') {
return(&fileref("Parent directory", $parentdir));
} else {
return(&fileref($filename, $Path->{'virt'}.$filename));
}
}
sub fileicon {
if ($filename =~ /^.*\.[ch]$/) {
return(&fileref("<img src=\"/icons/c.gif\"".
" border=0 alt=\"C file\">",
$Path->{'virt'}.$filename));
} elsif ($filename =~ /^.*\.(cpp|cc)$/) {
# TODO: Find a nice icon for c++ files (KDE?)
return(&fileref("<img src=\"/icons/c.gif\"".
" border=0 alt=\"C++ file\">",
$Path->{'virt'}.$filename));
} else {
return(&fileref("<img src=\"/icons/text.gif\"".
" border=0 alt=\"File\">",
$Path->{'virt'}.$filename));
}
}
sub filename {
return(&fileref($filename,
$Path->{'virt'}.$filename));
}
sub filesize {
my $templ = shift;
my $s = (-s $Path->{'real'}.$filename);
return(&expandtemplate($templ,
('bytes', sub {return($s)}),
('kbytes', sub {return($s/1024)}),
('mbytes', sub {return($s/1048576)})
));
}
sub modtime {
my @t = gmtime((stat($Path->{'real'}.$filename))[9]);
$t[5] += 1900;
$t[4]++;
return(sprintf("%04d-%02d-%02d %02d:%02d:%02d", reverse(splice(@t, 0, 6))));
}
sub direxpand {
my $templ = shift;
my $direx = '';
local $filename;
local $filestat;
foreach $filename (@dirs) {
$direx .= &expandtemplate($templ,
('iconlink', \&diricon),
('namelink', \&dirname),
('filesize', sub {return('')}),
('modtime', \&modtime),
('description', \&descexpand));
}
foreach $filename (@files) {
next if $filename =~ /^.*\.[oa]$|^core$|^00-INDEX$/;
$direx .= &expandtemplate($templ,
('iconlink', \&fileicon),
('namelink', \&filename),
('filesize', \&filesize),
('modtime', \&modtime),
('description', \&descexpand));
}
return($direx);
}
sub printdir {
my $template;
my $index;
local %index;
local @dirs;
local @files;
local $parentdir;
$template = "<ul>\n\$files{\n<li>\$iconlink \$namelink\n}</ul>\n";
if ($Conf->htmldir) {
unless (open(TEMPL, $Conf->htmldir)) {
&warning("Template ".$Conf->htmldir." does not exist.");
} else {
$save = $/; undef($/);
$template = <TEMPL>;
$/ = $save;
close(TEMPL);
}
}
if (opendir(DIR, $Path->{'real'})) {
foreach $f (sort(grep/^[^\.]/,readdir(DIR))) {
if (-d $Path->{'real'}.$f) {
push(@dirs,"$f/");
} else {
push(@files,$f);
}
}
closedir(DIR);
} else {
print("<p align=center>\n<i>This directory does not exist.</i>\n");
if ($Path->{'real'} =~ m#(.+[^/])[/]*$#) {
if (-e $1) {
&warning("Unable to open ".$Path->{'real'});
}
}
return;
}
if (-f $Path->{'real'}."00-INDEX") {
open(INDEX,$Path->{'real'}."00-INDEX") ||
&warning("Existing \"00-INDEX\" could not be opened.");
$save = $/; undef($/);
$index = <INDEX>;
$/ = $save;
%index = $index =~ /\n(\S*)\s*\n\t-\s*([^\n]*)/gs;
}
if ($Path->{'virt'} =~ m#^(.*/)[^/]*/$#) {
$parentdir = $1;
unshift(@dirs, '..');
}
print(&expandtemplate($template,
('files', \&direxpand)));
}
sub printfile {
unless ($Path->{'file'}) {
&printdir;
if (open(SRCFILE, $Path->{'real'}.README)) {
print("<hr><pre>");
&markupfile(\*SRCFILE, $Path->{'virt'}, 'README',
sub { print shift });
print("</pre>");
close(SRCFILE);
}
} else {
if (open(SRCFILE, $Path->{'realf'})) {
print("<pre>");
&markupfile(\*SRCFILE, $Path->{'virt'}, $Path->{'file'},
sub { print shift });
print("</pre>");
close(SRCFILE);
} else {
print("<p align=center>\n<i>This file does not exist.</i>\n");
if (-f $Path->{'real'}.$Path->{'file'}) {
&warning("Unable to open ".$Path->{'realf'});
}
}
}
}
($Conf, $HTTP, $Path) = &init;
&makeheader('source');
&printfile;
&makefooter('source');

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,6 @@
html-dir.html
lxr.conf
html-head.html
html-search.html
html-tail.html
html-ident.html

View File

@@ -0,0 +1,17 @@
Options Indexes ExecCGI FollowSymlinks
order deny,allow
<Files lxr.conf>
deny from all
</Files>
<Files lib>
deny from all
</Files>
<Files ~ (find|search|source|ident|diff|cgi-bin)$>
SetHandler perl-script
PerlHandler Apache::Registry
PerlSetEnv PERL5LIB lib
</Files>

View File

@@ -0,0 +1,4 @@
See http://www.sourceforge.net/projects/lxr for a list of known bugs and
how to report bugs you find.

View File

@@ -0,0 +1,36 @@
CREDITS
=======
Original authors of LXR
-----------------------
Arne Georg Gleditsch <lxr@linux.no>
Per Kristian Gjermshus <lxr@linux.no>
Current Maintainer
------------------
Malcolm Box <mbox@users.sf.net>
Principal Developers
--------------------
Peder O. Klingenberg <peder@klingenberg.no>
Contributors
------------
Pavel Hlavnicka <pavel@gingerall.cz> CSS support
Jason Dorie Short <jshort@devon.dhs.org> File re-org
Joseph Corral <joseph_corral@hp.com>
Kristoffer Gleditsch <toffer@ping.uio.no> Postgres patches
Guido Sohne Updated INSTALL document
Jens Heimann <jens.heimann@materna.de> Oracle database support
-------------------------------------------------------------------------
To get your name added to this list, see:
http://sf.net/projects/lxr
Last updated: $Date: 2002/02/26 16:18:46 $

View File

@@ -0,0 +1,47 @@
Hacking LXR
-----------
Things have started to stabilize a bit, so I will attempt to explain
the internals of the new LXR.
The goal of this new version is to support version control systems.
The old LXR did version control by maintaining separate source trees
and separate identifier databases. While this seemed to work fine it
really was a kludge.
We realized early that db-file databases were too weak for our
purpose, a real relational database would enable us to do much more
without the speed penalties of the db-files. We have therefore
abstracted the database that contains information about the
identifiers into the module LXR::Index. The LXR::Index::DBI module
uses the perl DBI interface to a relational database (we used postgres
for most of our development), while LXR::Index::DB tries to accomplish
the same by using db-files. This makes it possible for those with
large source-trees to use DBI and those who do not want to install a
RDBMS can stay with the db-files.
The old lxr had to store a complete source-tree for each version you
wanted to index. When the number of versions were relatively low this
worked just fine, but if you wanted to index the whole linux kernel
history the space requirement would be very large. It would therefore
be nice to be able to do the indexing on a CVS tree. The LXR::Files
backend abstacts the underlying file storage mechanism from the rest
of the system. (If you think we are thinking too much object
orientation and abstracting too much remember that we are both brought
up at the university where object orientation was invented :-). The
LXR::Files::Plain uses the old method were each version is stored in a
separate repository, while LXR::Files::CVS fetches the files from a
CVS repository. It should be possible to add support for other forms
of version control in the future.
Another design-goal for this new version was to support multiple
languages. Our old index generator was very c-specific and its
internals were really messy. We decided to get rid of that code and
are now using external index generators. Exuberant c-tags is very
good, and finds as many indentifiers as our old genxref did. The new
genxref uses the LXR::Tagger module. This module dispatches each
source file to the correct index generator. The markup of the code
displayed to the user is handled by the LXR::Lang module. This means
that all that have to be done to add support for a new language is to
write a LXR::Lang::Foo and a LXR::Tagger::Foo module.

View File

@@ -0,0 +1,256 @@
Installation
------------
The current version of the lxr depends on three things:
1) A recent version of the exuberant ctags program. Available from
http://sf.net/projects/ctags
2) A relational database - MySQL (http://www.mysql.com), Postgresql
(http://www.postgresql.org) and Oracle are supported.
You will also need the right Perl DBI drivers for your particular database,
usually available from CPAN.
3) Apache with mod_perl - http://www.apache.org
4) For freetext searching, either Glimpse (http://glimpse.cs.arizona.edu) or
Swish-e (http://swish-e.org). You need the development version of
swish-e (i.e. 2.1.x or later).
Swish-e is fully GPL'ed, while Glimpse is only free for
non-commercial use.
Installing the database
-----------------------
You will need to create a database for lxr, and possibly create a user
as well. If you are unsure how to do this, or don't have admin rights
to the database, consult the documentation or your sysadmin
respectively. The steps below assume you know what you're doing.
For Postgresql:
Create a user for lxr and give the user permission to create databases:
createuser lxr
Create a database for lxr:
createdb -U lxr lxr
Initialise the database:
psql -U lxr lxr
\i initdb-postgres
Just ignore the errors about unimplemented functions.
For MySQL:
Run 'mysql' and then read in the initdb-mysql file using
'\. initdb-mysql'. This will create the database and a user called
lxr with access rights to the database.
For Oracle
Start script in sqlplus with:
@/[pathTo]/initdb-oracle.sql;
Create lxr installation directory
---------------------------------
Expand the tarball in the LXR distribution into a directory of your
choice. A good choice could be /usr/local/lxr so you would do
cd /usr/local/
tar -zxf /path/to/lxr/lxr-x.x.tgz (as root or with appropriate permissions)
Now you have to put the perl modules that LXR uses into a directory on
your system that will be searched by mod_perl when the LXR scripts are
executed. Execute:
cp /usr/local/lxr/Local.pm /usr/lib/perl5/site_perl/
cp -r /usr/local/lxr/lib/LXR /usr/lib/perl5/site_perl
Now you should copy the template files for LXR to your installation
mv /usr/local/lxr/templates/* /usr/local/lxr/
Edit the lxr config file
------------------------
Go through the config file and fill in the relevant values.
If you have glimpse installed, you should set
'glimpsebin' => '/path/to/your/glimpse/executable'
Now remember you copied the perl modules for Glimpse to a directory
in your perl module search path ? The example path I used was
/usr/lib/perl5/site_perl which is also needed in lxr.conf
'genericconf' => '/usr/lib/perl5/site_perl/LXR/Lang/generic.conf'
Next set your base URL and virtual root for LXR by setting
'baseurl' => 'http://your.host.name/your_lxr_virtual_root
'virtroot' => '/your_lxr_virtual_root'
Fill in the dbname, dbpass and dbuser variable to the right values for
the database you created above.
The 'v' (Version) variable needs to have the list of versions of your
sourcecode that you want to index. This list can be in the lxr.conf
file, read from a file or calculated at runtime. Select the right
method for your setup in the lxr.conf file.
Set the 'sourceroot' variable to point to the source code that you
want to index and browse.
You may also want to configure the 'graphicfile', 'filetype' and
'incprefix' variables, but the defaults should be reasonable for most setups.
Getting lxr to work with CVS
----------------------------
If you want lxr to work on files that are located in a CVS repository, edit
lxr.conf and set the range variable so that it uses a subroutine instead
of the default setting that reads the src/cvsversions file.
'range' => sub { return
($files->allreleases($LXR::Common::pathname),
$files->allrevisions($LXR::Common::pathname))
}, # deferred function call.
You should also set the default version retrieved to a version that really
does exist otherwise you will receive errors when generating your index.
A good value for the default version is head.
'default' => 'head'
Next, set the source root variable to point to the directory containing
the versions of your project in CVS. If your cvs repository in stored
in /path/to/cvs/repository and your cvs module is called lxr then set
'sourceroot' => 'cvs:/path/to/cvs/repository/lxr'
'sourcerootname' => 'A Friendly Name For Your Repository'
Using Swish-e with LXR
----------------------
This is simple:
1) Put the paths to swish-e and swish-search in the 'swishindex' and
'swishsearch' variables in lxr.conf. If there is no swish-search
executable on your system, use the path to swish-e as the
'swishsearch' value.
2) Create a directory for the swish index files to go in, and put the
path of this directory in the 'swishdir' variable.
3) Comment out the 'glimpsebin' variable
Now re-run genxref and it should build the swish indexes for you and
you're done.
Getting Glimpse to work with LXR
--------------------------------
Create a directory in your LXR directory called glimpse
mkdir /usr/local/lxr/glimpse
If you are using CVS, checkout a copy of your project in the
LXR directory, for example
cd /usr/local/lxr
cvs checkout my_project
otherwise just use the path to your project instead in the
example below
find /usr/local/lxr/my_project/ -name *.java |
glimpseindex -H /usr/local/lxr/glimpse -o -F
Be sure that the glimpse indexes are readable by the user
that Apache is running as. You can do
chmod a+x /usr/local/lxr/glimpse/.*
Now edit lxr.conf again and add the following variable for
the URL section that you configured earlier
'strip' => '/usr/local/lxr/sikasem'
This munges the output of glimpse so that you can go straight
to the file that contains a match for a search term.
Generate index.
---------------
It is now time to generate the index. This is done using the program
"genxref". genxref takes two arguments --url= and --version= where is
the url where the lxr cgi scripts are found.
Version is a tag from cvs if you are using the cvs backend or the name
of a directory in your "sourceroot" directory. It is worth noting that
one lxr.conf file can be used for several different
configurations. Which config block to use is selected according to the
url argument.
If you are setting up LXR to use files in a CVS repository, genxref
will most likely run without printing out any error messages. This is
*not* what you want. You have to explicitly state a version to use.
genxref --url=/path/to/lxr --version=head
You can also use the --allversions argument to automatically index all
the versions defined in the versions variable.
Note that genxref can be a very slow process the first time it is run,
for example on a 4Gb source tree a full run can take several
days. However, on future runs it will only index changed files, thus
speeding the process.
Set up webserver
----------------
The browsing scripts currently supplied depend on mod_perl to execute
properly, although it should be easy to modify them to work as plain
CGI scripts. Since mod_perl is an Apache add-on, this means using
Apache at the moment.
You may need to edit httpd.conf to point to the lxr files, for example
if you have installed the lxr files in /usr/local/lxr and you want to
have your URL be http://mysite/lxr then you would add:
Alias /lxr /usr/local/lxr
<Directory /usr/local/lxr>
AllowOverride All
</Directory>
The distribution contains a .htaccess file set up to ensure that lxr
will work. Edit it if you have special local policies.
That's it - lxr should now work. Fire up your webbrowser and go to
http://yoursite/lxr/source and you should see the listing for the top
of your source tree.
Getting help if it doesn't work:
--------------------------------
If you can't get LXR to work then you can try asking on the mailing
list or the support forums. Do check the archives of both first
though - your question may already have been answered.
By web: http://sourceforge.net/forum/forum.php?forum_id=86145
By email: Send a mail to lxr-general@lists.sf.net
Troubleshooting:
---------------
** Fatal: Can't find database
This message comes from the DB backend. The likely cause is that the
webserver url passed to the browsing scripts does not match the url in
lxr.conf. This means the configuration will not be found, and thus
the database will not be found
HTTP headers appearing in the html, or output not being interpreted as HTML
This can be caused by warning messages output before the script
outputs the right headers to tell the browser that the output is
HTML. This can normally be solved by changing the value of $wwwdebug
to 0 in Common.pm. But please report the warning message as a bug at
http://sf.net/projects/lxr first!

View File

@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@@ -0,0 +1,421 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Local.pm,v 1.11 2002/03/18 14:55:43 mbox Exp $
#
# Local.pm -- Subroutines that need to be customized for each installation
#
# Dawn Endico <dawn@cannibal.mi.org>
# 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.
######################################################################
# This package is for placing subroutines that are likely to need
# to be customized for each installation. In particular, the file
# and directory description snarfing mechanism is likely to be
# different for each project.
package Local;
$CVSID = '$Id: Local.pm,v 1.11 2002/03/18 14:55:43 mbox Exp $ ';
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(&fdescexpand &descexpand &dirdesc &convertwhitespace);
use LXR::Common;
# dme: Create descriptions for a file in a directory listing
# If no description, return the string "\&nbsp\;" to keep the
# table looking pretty.
#
# In mozilla search the beginning of a source file for a short
# description. Not all files have them and the ones that do use
# many different formats. Try to find as many of these without
# printing gobbeldygook or something silly like a file name or a date.
#
# Read in the beginning of the file into a string. I chose 60 because the
# Berkeley copyright notice is around 40 lines long so we need a bit more
# than this.
#
# Its common for file descriptions to be delimited by the file name or
# the word "Description" which preceeds the description. Search the entire
# string for these. Sometimes they're put in odd places such as inside
# the copyright notice or after the code begins. The file name should be
# followed by a colon or some pattern of dashes.
#
# If no such description is found then use the contents of the "first"
# comment as the description. First, strip off the copyright notice plus
# anything before it. Remove rcs comments. Search for the first bit of
# code (usually #include) and remove it plus anything after it. In what's
# left, find the contents of the first comment, and get the first paragraph.
# If that's too long, use only the first sentence up to a period. If that's
# still too long then we probably have a list or something that will look
# strange if we print it out so give up and return null.
#
# Yes, this is a lot of trouble to go through but its easier than getting
# people to use the same format and re-writing thousands of comments. Not
# everything printed will really be a summary of the file, but still the
# signal/noise ratio seems pretty high.
#
# Yea, though I walk through the valley of the shadow of pattern
# matching, I shall fear no regex.
sub fdescexpand {
# use global vars here because the expandtemplate subroutine makes
# passing parameters impossible. Use $filename from source and
# $Path from Common.pm
my $filename = $main::filename;
my $linecount=0;
my $copy= "";
local $desc= "";
my $maxlines = 40; #only look at the beginning of the file
#ignore files that aren't source code
if (!(
($filename =~ /\.c$/) |
($filename =~ /\.h$/) |
($filename =~ /\.cc$/) |
($filename =~ /\.cp$/) |
($filename =~ /\.cpp$/) |
($filename =~ /\.java$/)
)){
return("\&nbsp\;");
}
if (open(FILE, $Path->{'real'}."/".$filename)) {
while(<FILE>){
$desc = $desc . $_ ;
if($linecount++ > 60) {
last;
}
}
close(FILE);
}
# sanity check: if there's no description then stop
if (!($desc =~ /\w/)){
return("\&nbsp\;");;
}
# save a copy for later
$copy = $desc;
# Look for well behaved <filename><seperator> formatted
# descriptions before we go to the trouble of looking for
# one in the first comment. The whitespace between the
# delimeter and the description may include a newline.
if (($desc =~ s/(?:.*?$filename\s*?- ?-*\s*)([^\n]*)(?:.*)/$1/sgi) ||
($desc =~ s/(?:.*?$filename\s*?:\s*)([^\n]*)(?:.*)/$1/sgi) ||
($desc =~ s/(?:.*?Description:\s*)([^\n]*)(?:.*)/$1/sgi)
){
# if the description is non-empty then clean it up and return it
if ($desc =~ /\w/) {
#strip trailing asterisks and "*/"
$desc =~ s#\*/?\s*$##;
$desc =~ s#^[^\S]*\**[^\S]*#\n#gs;
# Strip beginning and trailing whitespace
$desc =~ s/^\s+//;
$desc =~ s/\s+$//;
# Strip junk from the beginning
$desc =~ s#[^\w]*##ms;
#htmlify the comments making links to symbols and files
$desc = markupstring($desc, $Path->{'virt'});
return($desc);
}
}
# we didn't find any well behaved descriptions above so start over
# and look for one in the first comment
$desc = $copy;
# Strip off code from the end, starting at the first cpp directive
$desc =~ s/\n#.*//s;
# Strip off code from the end, starting at typedef
$desc =~ s/\ntypedef.*//s;
# Strip off license
$desc =~ s#(?:/\*.*license.*?\*/)(.*)#$1#is;
# Strip off copyright notice
$desc =~ s#(?:/\*.*copyright.*?\*/)(.*)#$1#is;
# Strip off emacs line
$desc =~ s#(/\*.*tab-width.*?\*/)(.*)#$2#isg;
# excise rcs crud
$desc =~ s#Id: $filename.*?Exp \$##g;
# Yuck, nuke these silly comments in js/jsj /* ** */
$desc =~ s#\n\s*/\*+[\s\*]+\*/\n#\n#sg;
# Don't bother to continue if there aren't any comments here
if(!($desc =~ m#/\*#)) {
return("&nbsp;");
}
# Remove lines generated by jmc
$desc =~ s#\n.*?Source date:.*\n#\n#;
$desc =~ s#\n.*?Generated by jmc.*\n#\n#;
# Extract the first comment
$desc =~ s#(?:.*?/\*+)(.*?)(?:(?:\*+/.*)|(?:$))#$1#s;
# Strip silly borders
$desc =~ s#\n\s*[\*\=\-\s]+#\n#sg;
# Strip beginning and trailing whitespace
$desc =~ s/^\s+//;
$desc =~ s/\s+$//;
# Strip out file name
$desc =~ s#$filename##i;
# Strip By line
$desc =~ s#By [^\n]*##;
# Strip out dates
$desc =~ s#\d{1,2}/\d{1,2}/\d\d\d\d##;
$desc =~ s#\d{1,2}/\d{1,2}/\d\d##;
$desc =~ s#\d{1,2} \w\w\w \d\d\d\d##;
# Strip junk from the beginning
$desc =~ s#[^\w]*##;
# Extract the first paragraph
$desc =~ s#(\n\s*?\n.*)##s;
# If the description is too long then just use the first sentence
# this will fail if no period was used.
if (length($desc) > 200 ) {
$desc =~ s#([^\.]+\.)\s.*#$1#s;
}
# If the description is still too long then assume it will look
# like gobbeldygook and give up
if (length($desc) > 200 ) {
return("&nbsp;");
}
# htmlify the comments, making links to symbols and files
$desc = markupstring($desc, $Path->{'virt'});
if ($desc) {
return($desc);
}
else {
return("\&nbsp\;");
}
}
# dme: create a short description for a subdirectory in a directory listing
# If no description, return the string "\&nbsp\;" to keep the
# table looking pretty.
#
# In Mozilla, if the directory has a README file look in it for lines
# like the ones used in source code: "directoryname --- A short description"
sub descexpand {
my ($templ, $node, $dir, $index) = @_;
if ($$index{$node}) {
return LXR::Common::expandtemplate($templ,
('desctext',
sub { return $$index{$node} }));
}
else {
return "\&nbsp\;";
}
}
# dme: Print a descriptive blurb in directory listings between
# the document heading and the table containing the actual listing.
#
# For Mozilla, we extract this information from the README file if
# it exists. If the file is short then just print the whole thing.
# For longer files print the first paragraph or so. As much as
# possible make this work for randomly formatted files rather than
# inventing strict rules which create gobbeldygook when they're broken.
sub dirdesc {
my ($path) = @_;
if (-f $Path->{'real'}."/README") {
descreadme($path);
} elsif (-f $Path->{'real'}."/README.html") {
descreadmehtml($path);
}
}
sub descreadmehtml {
my ($path) = @_;
my $string = "";
if (!(open(DESC, $Path->{'real'}."/README.html"))) {
return;
}
# undef $/;
$string = <DESC>;
# $/ = "\n";
close(DESC);
# if the README is 0 length then give up
if (!$string) {
return;
}
# check if there's a short desc nested inside the long desc. If not, do
# a non-greedy search for a long desc. assume there are no other stray
# spans within the description.
if ($string =~ /<span class=["']?lxrlongdesc['"]?>(.*?<span class=["']?lxrshortdesc['"]?>.*?<\/span>.*?)<\/span>/is) {
$long = $1;
if (!($long =~ /<span.*?\<span/is)) {
print($long . "<p>\nSEE ALSO: <a href=\"README.html\">README</a></p>\n");
}
} elsif ($string =~ /<span class=["']?lxrlongdesc['"]?>(.*?)<\/span>/is) {
$long = $1;
if (!($long =~ /\<span/is)) {
print($long . "<p>\nSEE ALSO: <a href=\"README.html\">README</a></p>\n");
}
}
}
sub descreadme {
my ($path) = @_;
my $string = "";
# $string =~ s#(</?([^>^\s]+[^>]*)>.*$)#($2~/B|A|IMG|FONT|BR|EM|I|TT/i)?$1:""#sg;
my $n;
my $count;
my $temp;
my $maxlines = 20; # If file is less than this then just print it all
my $minlines = 5; # Too small. Go back and add another paragraph.
my $chopto = 10; # Truncate long READMEs to this length
if (!(open(DESC, $Path->{'real'}."/README"))) {
return;
}
# undef $/;
$string = <DESC>;
# $/ = "\n";
close(DESC);
# if the README is 0 length then give up
if (!$string){
return;
}
# strip the emacs tab line
$string =~ s/.*tab-width:[ \t]*([0-9]+).*\n//;
# strip the npl
$string =~ s/.*The contents of this .* All Rights.*Reserved\.//s;
# strip the short description from the beginning
$path =~ s#/(.+)/#$1#;
$string =~ s/.*$path\/*\s+--- .*//;
# strip away junk
$string =~ s/#+\s*\n/\n/;
$string =~ s/---+\s*\n/\n/g;
$string =~ s/===+\s*\n/\n/g;
# strip blank lines at beginning and end of file.
$string =~ s/^\s*\n//gs;
$string =~ s/\s*\n$//gs;
chomp($string);
$_ = $string;
$count = tr/\n//;
# If the file is small there's not much use splitting it up.
# Just print it all
if ($count <= $maxlines) {
$string = markupstring($string, $Path->{'virt'});
$string = convertwhitespace($string);
print($string);
} else {
# grab the first n paragraphs, with n decreasing until the
# string is 10 lines or shorter or until we're down to
# one paragraph.
$n = 6;
$temp = $string;
while ( ($count > $chopto) && ($n-- > 1) ) {
$string =~ s/^((?:(?:[\S\t ]*?\n)+?[\t ]*\n){$n}?)(.*)/$1/s;
$_ = $string;
$string =~ s/\s*\n$//gs;
$count = tr/\n//;
}
# if we have too few lines then back up and grab another paragraph
$_ = $string;
$count = tr/\n//;
if ($count < $minlines) {
$n = $n+1;
$temp =~ s/^((?:(?:[\S\t ]*?\n)+?[\t ]*\n){$n}?)(.*)/$1/s;
$string = $temp;
}
# if we have more than $maxlines then truncate to $chopto
# and add an elipsis.
if ($count > $maxlines) {
$string =~ s/^((?:[\S \t]*\n){$chopto}?)(.*)/$1/s;
chomp($string);
$string = $string . "\n...";
}
# since not all of the README is displayed here,
# add a link to it.
chomp($string);
if ($string =~ /SEE ALSO/) {
$string = $string . ", README";
} else {
$string = $string . "\n\nSEE ALSO: README";
}
$string = markupstring($string, $Path->{'virt'});
$string = convertwhitespace($string);
# strip blank lines at beginning and end of file again
$string =~ s/^\s*\n//gs;
$string =~ s/\s*\n$//gs;
chomp($string);
print($string . "<p>\n");
}
}
# dme: substitute carraige returns and spaces in original text
# for html equivalent so we don't need to use <pre> and can
# use variable width fonts but preserve the formatting
sub convertwhitespace {
my ($string) = @_;
# handle ascii bulleted lists
$string =~ s/<p>\n\s+o\s/<p>\n\&nbsp\;\&nbsp\;o /sg;
$string =~ s/\n\s+o\s/&nbsp\;\n<br>\&nbsp\;\&nbsp\;o /sg;
#find paragraph breaks and replace with <p>
$string =~ s/\n\s*\n/<p>\n/sg;
return($string);
}
1;

View File

@@ -0,0 +1,210 @@
#!/usr/bin/perl
# $Id: diff,v 1.9 2002/03/18 14:55:43 mbox Exp $
# diff -- Display diff output with markup.
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
######################################################################
$CVSID = '$Id: diff,v 1.9 2002/03/18 14:55:43 mbox Exp $ ';
use strict;
use lib do { $0 =~ m{(.*)/} ? "$1/lib" : "lib" };
use LXR::Common qw(:html);
use Local;
sub htmlsub {
my ($s, $l) = @_;
my @s = split(/(<[^>]*>|&[\#\w\d]+;?)/, $s);
$s = '';
while (@s) {
my $f = substr(shift(@s), 0, $l);
$l -= length($f);
$s .= $f;
$f = shift(@s);
if ($f =~ /^&/) {
if ($l > 0) {
$s .= $f;
$l--;
}
} else {
$s .= $f;
}
}
$s .= ' ' x $l;
return $s;
}
sub printdiff {
my ($diffvar, $diffval) = @_;
unless ($diffvar) {
my @vars;
foreach ($config->allvariables) {
push(@vars, $config->vardescription($_));
}
$vars[$#vars-1] .= " or ".pop(@vars) if $#vars > 0;
print("<p align=\"center\">\n",
"Please indicate the version of the file you wish to\n",
"compare to by clicking on the appropriate\n",
join(", ",@vars)," button.\n",
"</p>\n");
return;
}
if ($pathname =~ m|/$|) {
print("<h3 align=\"center\">Diff not yet supported for directories.</h3>\n");
return;
}
my $origval = $config->variable($diffvar);
my $origname = $pathname;
my $origtemp = $files->tmpfile($origname, $release);
$config->variable($diffvar,$diffval);
my $diffname = $config->mappath($pathname);
my $difftemp = $files->tmpfile($diffname, $config->variable('v'));
$config->variable($diffvar,$origval);
unless (defined($origtemp)) {
unlink($difftemp);
print("*** $origname does not exist ***\n");
return;
}
unless (defined($difftemp)) {
unlink($origtemp);
print("*** $diffname does not exist ***\n");
return;
}
fflush;
unless (open(DIFF, "-|")){
open(STDERR, ">&STDOUT");
exec('diff', '-U0', $origtemp, $difftemp);
print "*** Diff subprocess died unexpextedly: $!\n";
exit;
}
my ($os, $ol, $ns, $nl, $ms, $ml, $bo, $ofs, $dir, %orig, %new, %chg);
while (<DIFF>) {
if (($os, $ol, $ns, $nl) =
/@@ -(\d+)(?:,(\d+)|) \+(\d+)(?:,(\d+)|) @@/) {
$os++ if $ol eq '0';
$ns++ if $nl eq '0';
$ol = 1 unless defined($ol);
$nl = 1 unless defined($nl);
$bo = $os + $ofs;
if ($ol < $nl) {
$ofs += $nl - $ol;
$dir = '&gt;&gt;';
$ms = $nl - $ol;
$ml = $ol;
$orig{$os+$ol} = $ms;
} else {
$dir = '&lt;&lt;';
$ms = $ol - $nl;
$ml = $nl;
$new{$ns+$nl} = $ms;
}
foreach (0..$ml - 1) {
$chg{$bo + $_} = '!!';
}
foreach (0..$ms - 1) {
$chg{$bo + $ml + $_} = $dir;
}
}
}
close(DIFF);
print("<h1>Diff markup</h1>\n",
"<h3>Differences between ",
fileref("$origname (".$config->vardescription($diffvar).
" $origval)", "diff-fref",
$origname, undef, "$diffvar=$origval"),
" and ",
fileref("$diffname (".$config->vardescription($diffvar).
" $diffval)", "diff-fref",
$diffname, undef, "$diffvar=$diffval"),
"</h3><hr>\n");
my $origh = new FileHandle($origtemp);
my $orig = '';
markupfile($origh, sub { $orig .= shift }, 1);
my $len = $.+$ofs;
$origh->close;
$config->variable($diffvar, $diffval);
$pathname = $diffname;
my $diffh = new FileHandle($difftemp);
my $new = '';
markupfile($diffh, sub { $new .= shift });
$diffh->close;
$config->variable($diffvar, $origval);
$pathname = $origname;
my $i;
$i = 1; $orig =~ s/^/"\n" x ($orig{$i++})/mge;
$i = 1; $new =~ s/^/"\n" x ($new{$i++})/mge;
my @orig = split(/\n/, $orig);
my @new = split(/\n/, $new);
print("<pre class=\"file\">\n");
foreach $i (0..$len) {
my $o = htmlsub($orig[$i], 50);
my $n = $new[$i];
my $diffmark = $chg{$i+1} ?
("<span class=\"diff-mark\">" . $chg{$i+1} . "</span>") : " ";
#print("$o <span class=\"diff-mark\">",
# ($chg{$i+1} || " "), "</span> $n\n");
print "$o $diffmark $n\n";
}
print("</pre>");
unlink($origtemp, $difftemp);
}
httpinit;
makeheader('diff');
printdiff($$HTTP{'param'}{'diffvar'}, $$HTTP{'param'}{'diffval'});
makefooter('diff');
httpclean;

View File

@@ -0,0 +1,80 @@
#!/usr/bin/perl
# $Id: find,v 1.8 2002/03/18 14:55:43 mbox Exp $
# find -- Find files
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
######################################################################
$CVSID = '$Id: find,v 1.8 2002/03/18 14:55:43 mbox Exp $ ';
use lib do { $0 =~ m{(.*)/} ? "$1/lib" : "lib" };
use LXR::Common qw(:html);
use LXR::Config;
sub find {
print("<p align=\"center\">\n",
"Search for files (by name) using regular expressions.\n",
"<br>(Need some <a href=\"search-help.html\">Hints</a> ",
"on performing searches?)</p>\n");
print ("<form method=\"get\" action=\"find\">\n");
foreach ($config->allvariables) {
if ($config->variable($_) ne $config->vardefault($_)) {
print("<input type=\"hidden\" name=\"",$_, "\" ",
"value=\"", $config->variable($_), "\">\n");
}
}
print("<b>Find file: </b><input type=\"text\" name=\"string\" ",
"value=\"",$searchtext,"\" size=\"50\">\n",
"<input type=\"submit\" value=\"search\">\n",
"</form>\n");
if ($searchtext ne "") {
unless (open(FILELLISTING,$config->glimpsedir."/.glimpse_filenames")) {
&warning("Could not open .glimpse_filenames.");
return;
}
print("<hr>\n");
$sourceroot = $config->sourceroot;
while($file = <FILELLISTING>) {
$file =~ s/^$sourceroot//;
if($file =~ /$searchtext/) {
print(&fileref("$file", "find-file", "/$file"),"<br>\n");
}
}
}
}
httpinit;
$searchtext = $HTTP->{'param'}->{'string'};
&makeheader('find');
&find;
&makefooter('find');
httpclean;

View File

@@ -0,0 +1,12 @@
#!/bin/sh
if [ -z "$1" ]; then
echo First argument must be path of desired Perl interpreter.
exit 0;
fi
for f in `ls -ld ./* | grep '^-..x' | cut -d/ -f2`; do
sed -e "1s,^#!.*perl.*,#!$1," < $f > $f.new
cp $f.new $f
rm $f.new
done

View File

@@ -0,0 +1,70 @@
#!/usr/bin/perl
#
# added by jmason to support identifying references to java system classes in
# LXR-cross-referenced .java files.
#
# This only needs to be run when a new version of the Java system class set is
# released. The bundled JavaClassList.pm should do the trick nicely.
#
# This tool requires that the Info-Zip tool 'zipinfo' is installed in the PATH.
use lib 'lib/';
if (!defined ($ARGV[0])) {
die "usage: genjavaclasses { java_classes.zip | java_classes.jar }\n";
}
$classes_zip = $ARGV[0];
open (ZIPINFO, "zipinfo $classes_zip |")
|| die "cannot run 'zipinfo $classes_zip'\n";
$outfile = $INC[0]."/JavaClassList.pm";
open (OUT, "> $outfile.new") || die "cannot write to '$outfile.new'\n";
print OUT '# [Generated by genjavaclasses at '.localtime().']
package JavaClassList;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(&is_java_class);
sub is_java_class {
local ($name, @imported_packages) = @_;
local ($_);
if (!defined %java_system_classes) {
foreach $_ (@java_system_classes) { $java_system_classes{$_} = 1; }
}
if (defined ($java_system_classes{$name})) { return 1; }
foreach $_ (@imported_packages) {
if (defined ($java_system_classes{$_.$name})) { return 1; }
}
0;
}
@java_system_classes = qw(
# AUTOMATICALLY GENERATED LIST STARTS HERE
';
while (<ZIPINFO>) {
/ (\S+)\.class\s*$/ || next;
$_ = $1; s,/,.,g; print OUT "\t$_\n";
}
close ZIPINFO || die "'zipinfo $classes_zip' failed\n";
print OUT '
# AUTOMATICALLY GENERATED LIST ENDS HERE
);
1;
';
if (-r $outfile) {
rename ($outfile, "$outfile.bak") || die "rename of $outfile failed\n";
}
rename ("$outfile.new", $outfile) || die "rename to $outfile failed\n";
exit;
# vim:sw=4:

View File

@@ -0,0 +1,177 @@
#!/usr/bin/perl
# -*- tab-width: 4 -*-"
# 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.
use strict;
use lib 'lib';
use Fcntl;
use Getopt::Long;
use IO::Handle;
use LXR::Files;
use LXR::Index;
use LXR::Config;
use LXR::Tagger;
use LXR::Common;
my %option;
GetOptions(\%option, "help!", "url=s", "version=s", "allurls!", "allversions!");
if ($option{'help'}) {
# this may not be the best way to implement this, but at least it's something
print <<END_HELP;
Usage: genxref [option ...]
The genxref program automatically generates LXR database cross-reference
tokens for a set of URL configuration blocks and source code versions. These
are both defined in the lxr.conf configuration file. Each "URL" is a separate
source tree; LXR separates and identifies these by their URL. Each "version" is
a different version of the source tree being indexed. See lxr.conf or
lxr.conf.template for configuring URLs and versions.
Valid options are:
--help Print a summary of the options.
--url=URL Generate tokens for the given URL configuration block.
--allurls Generate tokens for all URL configuration blocks.
--version=VERSION Generate tokens for the given version of the code.
--allversions Generate tokens for all versions of the code (default).
Report bugs at http://sourceforge.net/projects/lxr/.
END_HELP
exit 0;
}
# TODO: implement --allurls
die("Option --allurls not implemented. Use --url instead.\n")
if $option{'allurls'};
die("URL must be specified. Try \"genxref --help\".\n")
unless $option{'url'};
$config = new LXR::Config($option{'url'});
die("No matching configuration") unless $config->sourceroot;
$files = new LXR::Files($config->sourceroot);
die "Can't create file access object ".$config->sourceroot if !defined($files);
$index = new LXR::Index($config->dbname, O_RDWR|O_CREAT);
die "Can't create Index ".$config->dbname if !defined($index);
my @versions;
if ($option{'allversions'} || !$option{'version'}) {
@versions = $config->varrange('v');
} else {
@versions = $option{'version'};
}
foreach my $version (@versions) {
genindex('/', $version);
genrefs('/', $version);
gensearch($version);
}
sub genindex {
my ($pathname, $release) = @_;
print(STDERR "*** $pathname $release \n");
if ($pathname =~ m|/$|) {
map {
genindex($pathname.$_, $release)
} $files->getdir($pathname, $release);
} else {
&LXR::Tagger::processfile($pathname, $release,
$config, $files, $index)
}
}
sub genrefs {
my ($pathname, $release) = @_;
print(STDERR "### $pathname $release \n");
if ($pathname =~ m|/$|) {
map {
genrefs($pathname.$_, $release)
} $files->getdir($pathname, $release);
} else {
&LXR::Tagger::processrefs($pathname, $release,
$config, $files, $index)
}
}
sub feedswish {
my ($pathname, $release, $swish) = @_;
print(STDERR "&&& $pathname $release \n");
if ($pathname =~ m|/$|) {
map {
feedswish($pathname.$_, $release, $swish)
} $files->getdir($pathname, $release);
} else {
my $contents = $files->getfile($pathname, $release);
$swish->print("Path-Name: $pathname\n",
"Content-Length: ".length($contents)."\n",
"Document-Type: TXT\n",
"\n",
$contents)
if length($contents) > 0;
}
}
sub gensearch {
my ($release) = @_;
my $string;
if ($config->glimpsebin and $config->glimpseindex) {
# Make sure the directory that the glimpse results go into
# already exists as glimpse won't work if the directory does
# not exist
$string = $config->glimpsedir."/".$release;
mkdir $string;
system("chmod 755 $string");
my $glimpse = new IO::Handle;
my $pid = open($glimpse, "|-");
if ($pid == 0) {
exec($config->glimpseindex,
"-n", "-o", "-H", $config->glimpsedir."/$release",
$config->sourceroot."/".$release);
print(STDERR "Couldn't exec ".$config->glimpseindex.": $!\n");
kill(9, $$);
}
$glimpse->close();
# Need to chmod the glimpse files so everybody can read them.
$string = $config->glimpsedir."/".$release."/.glimpse\*";
system("chmod 644 $string");
}
if ($config->swishdir and $config->swishindex) {
my $swish = new IO::Handle;
my $pid = open($swish, "|-");
if ($pid == 0) {
exec($config->swishindex,
"-S", "prog", "-i", "/bin/cat", "-v", "1",
"-f", $config->swishdir."/".$release.".index");
print(STDERR "Couldn't exec ".$config->swishindex.": $!\n");
kill(9, $$);
}
feedswish("/", $release, $swish);
$swish->close();
}
}

View File

@@ -0,0 +1,150 @@
#!/usr/bin/perl
# $Id: ident,v 1.15 2002/03/18 14:55:43 mbox Exp $
# ident -- Look up identifiers
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
######################################################################
$CVSID = '$Id: ident,v 1.15 2002/03/18 14:55:43 mbox Exp $ ';
use strict;
use lib do { $0 =~ m{(.*)/} ? "$1/lib" : "lib" };
use LXR::Common qw(:html);
use Local;
sub varinputs {
my $ret = '';
foreach ($config->allvariables) {
if ($config->variable($_) ne $config->vardefault($_)) {
$ret .= "<input type=\"hidden\" name=\"$_\" value=\"" .
$config->variable($_) . "\">\n";
}
}
return $ret;
}
sub refexpand {
my $templ = shift;
my $ret = '';
my @refs = $index->getindex($identifier, $release);
my $def;
foreach my $def (@refs) {
my ($file, $line, $type, $rel) = @$def;
$rel &&= "(member of ".idref($rel, "search-member", $rel).")";
$ret .= expandtemplate($templ,
(file => sub { $file },
line => sub { $line },
type => sub { $type },
rel => sub { $rel },
fileref => sub {
fileref("$file, line $line",
"search-decl",
$file, $line);
}
));
# print("<span class=\"search-li1\"> $type_names{$type} in ".
# fileref("$file, line $line", "search-decl",
# $file, $line).
# " $rel</span>\n");
}
return $ret;
}
sub usesexpand {
my $templ = shift;
my $ret = '';
my @uses = $index->getreference($identifier, $release);
foreach my $ref (sort { $$a[0] cmp $$b[0] } @uses) {
my ($file, $line) = @$ref;
$ret .= expandtemplate($templ,
(
file => sub { $file },
line => sub { $line },
fileref => sub {
fileref("$file, line $line", "search-ref",
$file, $line);
}
));
}
return $ret;
}
sub printident {
my $dir = shift;
my ($templ, $templ_refs);
#$templ = "<ul>\n\$files{\n<li>\$iconlink \$namelink\n}</ul>\n";
if ($config->htmlident) {
unless (open(TEMPL, $config->htmlident)) {
warning("Template ".$config->htmlident." does not exist.");
} else {
local($/) = undef;
$templ = <TEMPL>;
close(TEMPL);
}
} else {
die "Ident template not configured";
}
if ($config->htmlident_refs) {
unless (open(TEMPL, $config->htmlident_refs)) {
warning("Template ".$config->htmlident_refs." does not exist.");
} else {
local($/) = undef;
$templ_refs = <TEMPL>;
close(TEMPL);
}
} else {
die "Ident refs template not configured";
}
# print the description of the current directory
#dirdesc($dir);
# print the listing itself
print(expandtemplate($templ,
(variables => \&varinputs,
identifier => sub { return $identifier },
refs => sub { refexpand(@_) },
)));
print(expandtemplate($templ_refs,
(uses => sub { usesexpand(@_) },
)));
}
httpinit;
makeheader('ident');
printident;
makefooter('ident');
httpclean;

View File

@@ -0,0 +1,66 @@
drop sequence filenum;
drop sequence symnum;
drop table files;
drop table symbols;
drop table indexes;
drop table releases;
drop table usage;
drop table status;
create sequence filenum cache 50;
create sequence symnum cache 50;
create table files (
filename varchar,
revision varchar,
fileid int,
primary key (fileid),
unique (filename, revision)
);
create table symbols (
symname varchar,
symid int,
primary key (symid),
unique (symname)
);
create table indexes (
symid int references symbols,
fileid int references files,
line int,
type varchar,
relsym int references symbols
);
create table releases
(fileid int references files,
release varchar,
primary key (fileid,release)
);
create table usage
(fileid int references files,
line int,
symid int references symbols
);
create table status
(fileid int references files,
status int,
primary key (fileid)
);
create index indexindex on indexes using btree (symid);
create index symbolindex on symbols using btree (symname);
create index usageindex on usage using btree (symid);
grant select on files to public;
grant select on symbols to public;
grant select on indexes to public;
grant select on releases to public;
grant select on usage to public;
grant select on status to public;

View File

@@ -0,0 +1,66 @@
/* Read this into mysql with "\. initdb-mysql" when logged in as root
to delete the old lxr database and create a new */
drop if exists database lxr;
create database lxr;
use lxr;
/* symnum filenum */
create table files (
filename char(255) binary not null,
revision char(255) binary not null,
fileid int not null auto_increment,
primary key (fileid) /*,
unique (filename, revision) */
);
create table symbols (
symname char(255) binary not null,
symid int not null auto_increment,
primary key (symid),
unique (symname)
);
create table indexes (
symid int not null references symbols,
fileid int not null references files,
line int not null,
langid tinyint not null references declarations,
type smallint not null references declarations,
relsym int references symbols
);
create table releases
(fileid int not null references files,
release char(255) binary not null,
primary key (fileid,release)
);
create table useage
(fileid int not null references files,
line int not null,
symid int not null references symbols
);
create table status
(fileid int not null references files,
status tinyint not null,
primary key (fileid)
);
create table declarations
(declid smallint not null auto_increment,
langid tinyint not null,
declaration char(255) not null,
primary key (declid, langid)
);
create index indexindex on indexes (symid) ;
create unique index symbolindex on symbols (symname) ;
create index useageindex on useage (symid) ;
create index filelookup on files (filename);
grant all on lxr.* to lxr@localhost;

View File

@@ -0,0 +1,78 @@
drop sequence filenum;
drop sequence symnum;
drop table indexes;
drop table usage;
drop table symbols;
drop table releases;
drop table status;
drop table files;
commit;
create sequence filenum;
create sequence symnum;
commit;
create table files (
filename varchar2(250),
revision varchar2(250),
fileid number,
constraint pk_files primary key (fileid)
);
alter table files add unique (filename, revision);
create index i_files on files(filename);
commit;
create table symbols (
symname varchar2(250),
symid number,
constraint pk_symbols primary key (symid)
);
alter table symbols add unique(symname);
commit;
create table indexes (
symid number,
fileid number,
line number,
type varchar2(250),
relsym number,
constraint fk_indexes_fileid foreign key (fileid) references files(fileid),
constraint fk_indexes_symid foreign key (symid) references symbols(symid),
constraint fk_indexes_relsym foreign key (relsym) references symbols(symid)
);
create index i_indexes on indexes(symid);
commit;
create table releases (
fileid number,
release varchar2(250),
constraint pk_releases primary key (fileid,release),
constraint fk_releases_fileid foreign key (fileid) references files(fileid)
);
commit;
create table status (
fileid number,
status number,
constraint pk_status primary key (fileid),
constraint fk_status_fileid foreign key (fileid) references files(fileid)
);
commit;
create table usage (
fileid number,
line number,
symid number,
constraint fk_usage_fileid foreign key (fileid) references files(fileid),
constraint fk_usage_symid foreign key (symid) references symbols(symid)
);

View File

@@ -0,0 +1,79 @@
drop sequence filenum;
drop sequence symnum;
drop sequence declnum;
drop table files;
drop table symbols;
drop table indexes;
drop table releases;
drop table usage;
drop table status;
drop table declarations;
create sequence filenum cache 50;
create sequence symnum cache 50;
create sequence declnum cache 10;
create table files (
filename varchar,
revision varchar,
fileid int,
primary key (fileid),
unique (filename, revision)
);
create table symbols (
symname varchar,
symid int,
primary key (symid),
unique (symname)
);
create table declarations (
declid smallint not null,
langid smallint not null,
declaration char(255) not null,
primary key (declid, langid)
);
create table indexes (
symid int references symbols,
fileid int references files,
line int,
langid smallint not null,
type smallint not null,
relsym int references symbols,
foreign key (langid, type) references declarations (langid, declid)
);
create table releases
(fileid int references files,
release varchar,
primary key (fileid,release)
);
create table usage
(fileid int references files,
line int,
symid int references symbols
);
create table status
(fileid int references files,
status smallint,
primary key (fileid)
);
create index indexindex on indexes using btree (symid);
create index symbolindex on symbols using btree (symname);
create index usageindex on usage using btree (symid);
create index filelookup on files using btree (filename);
grant select on files to public;
grant select on symbols to public;
grant select on indexes to public;
grant select on releases to public;
grant select on usage to public;
grant select on status to public;
grant select on declarations to public;

View File

@@ -0,0 +1,877 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Common.pm,v 1.43 2002/07/29 01:17:32 mbox Exp $
#
# FIXME: java doesn't support super() or super.x
# 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 LXR::Common;
$CVSID = '$Id: Common.pm,v 1.43 2002/07/29 01:17:32 mbox Exp $ ';
use strict;
require Exporter;
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS
$files $index $config $pathname $identifier $release
$HTTP $wwwdebug $tmpcounter);
@ISA = qw(Exporter);
@EXPORT = qw($files $index $config &fatal);
@EXPORT_OK = qw($files $index $config $pathname $identifier $release
$HTTP
&warning &fatal &abortall &fflush &urlargs &fileref
&idref &incref &htmlquote &freetextmarkup &markupfile
&markupstring &httpinit &makeheader &makefooter
&expandtemplate &httpclean);
%EXPORT_TAGS = ('html' => [ @EXPORT_OK ]);
require Local;
require LXR::SimpleParse;
require LXR::Config;
require LXR::Files;
require LXR::Index;
require LXR::Lang;
$wwwdebug = 1;
$tmpcounter = 23;
sub warning {
my $c = join(", line ", (caller)[0,2]);
print(STDERR "[",scalar(localtime),"] warning: $c: $_[0]\n");
print("<h4 align=\"center\"><i>** Warning: $_[0]</i></h4>\n") if $wwwdebug;
}
sub fatal {
my $c = join(", line ", (caller)[0,2]);
print(STDERR "[",scalar(localtime),"] fatal: $c: $_[0]\n");
print(STDERR '[@INC ', join(" ", @INC), ' $0 ', $0, "\n");
print(STDERR '$config', join(" ", %$config), "\n") if ref($config) eq "HASH";
print("<h4 align=\"center\"><i>** Fatal: $_[0]</i></h4>\n") if $wwwdebug;
exit(1);
}
sub abortall {
my $c = join(", line ", (caller)[0,2]);
print(STDERR "[",scalar(localtime),"] abortall: $c: $_[0]\n");
print("Content-Type: text/html; charset=iso-8859-1\n\n",
"<html>\n<head>\n<title>Abort</title>\n</head>\n",
"<body><h1>Abort!</h1>\n",
"<b><i>** Aborting: $_[0]</i></b>\n",
"</body>\n</html>\n") if $wwwdebug;
exit(1);
}
sub fflush {
$| = 1; print('');
}
sub tmpcounter {
return $tmpcounter++;
}
sub urlargs {
my @args = @_;
my %args = ();
my $val;
foreach (@args) {
$args{$1} = $2 if /(\S+)=(\S*)/;
}
@args = ();
foreach ($config->allvariables) {
$val = $args{$_} || $config->variable($_);
push(@args, "$_=$val") unless ($val eq $config->vardefault($_));
delete($args{$_});
}
foreach (keys(%args)) {
push(@args, "$_=$args{$_}");
}
return ($#args < 0 ? '' : '?'.join(';',@args));
}
sub fileref {
my ($desc, $css, $path, $line, @args) = @_;
# jwz: URL-quote any special characters.
$path =~ s|([^-a-zA-Z0-9.\@/_\r\n])|sprintf("%%%02X", ord($1))|ge;
if ($line > 0 && length($line) < 3) {
$line = ('0' x (3-length($line))).$line;
}
return ("<a class='$css' href=\"$config->{virtroot}/source$path".
&urlargs(@args).
($line > 0 ? "#$line" : "").
"\"\>$desc</a>");
}
sub diffref {
my ($desc, $css, $path, $darg) = @_;
my $dval;
($darg, $dval) = $darg =~ /(.*?)=(.*)/;
return ("<a class='$css' href=\"$config->{virtroot}/diff$path".
&urlargs(($darg ? "diffvar=$darg" : ""),
($dval ? "diffval=$dval" : "")).
"\"\>$desc</a>");
}
sub idref {
my ($desc, $css, $id, @args) = @_;
return ("<a class='$css' href=\"$config->{virtroot}/ident".
&urlargs(($id ? "i=$id" : ""),
@args).
"\"\>$desc</a>");
}
sub incref {
my ($name, $css, $file, @paths) = @_;
my ($dir, $path);
push(@paths, $config->incprefix);
foreach $dir (@paths) {
$dir =~ s/\/+$//;
$path = $config->mappath($dir."/".$file);
return &fileref($name, $css, $path) if $files->isfile($path, $release);
}
return $name;
}
sub http_wash {
my $t = shift;
if(!defined($t)) {
return(undef);
}
$t =~ s/\+/ /g;
$t =~ s/\%([\da-f][\da-f])/pack("C", hex($1))/gie;
# Paranoia check. Regexp-searches in Glimpse won't work.
# if ($t =~ tr/;<>*|\`&$!#()[]{}:\'\"//) {
# Should be sufficient to keep "open" from doing unexpected stuff.
if ($t =~ tr/<>|\"\'\`//) {
&abortall("Illegal characters in HTTP-parameters.");
}
return($t);
}
# dme: Smaller version of the markupfile function meant for marking up
# the descriptions in source directory listings.
sub markupstring {
my ($string, $virtp) = @_;
# Mark special characters so they don't get processed just yet.
$string =~ s/([\&\<\>])/\0$1/g;
# Look for identifiers and create links with identifier search query.
# TODO: Is there a performance problem with this?
$string =~ s#(^|\s)([a-zA-Z_~][a-zA-Z0-9_]*)\b#
$1.(is_linkworthy($2) ? &idref($2, "", $2) : $2)#ge;
# HTMLify the special characters we marked earlier,
# but not the ones in the recently added xref html links.
$string=~ s/\0&/&amp;/g;
$string=~ s/\0</&lt;/g;
$string=~ s/\0>/&gt;/g;
# HTMLify email addresses and urls.
$string =~ s#((ftp|http|nntp|snews|news)://(\w|\w\.\w|\~|\-|\/|\#)+(?!\.\b))#<a href=\"$1\">$1</a>#g;
# htmlify certain addresses which aren't surrounded by <>
$string =~ s/([\w\-\_]*\@netscape.com)(?!&gt;)/<a href=\"mailto:$1\">$1<\/a>/g;
$string =~ s/([\w\-\_]*\@mozilla.org)(?!&gt;)/<a href=\"mailto:$1\">$1<\/a>/g;
$string =~ s/([\w\-\_]*\@gnome.org)(?!&gt;)/<a href=\"mailto:$1\">$1<\/a>/g;
$string =~ s/([\w\-\_]*\@linux.no)(?!&gt;)/<a href=\"mailto:$1\">$1<\/a>/g;
$string =~ s/([\w\-\_]*\@sourceforge.net)(?!&gt;)/<a href=\"mailto:$1\">$1<\/a>/g;
$string =~ s/([\w\-\_]*\@sf.net)(?!&gt;)/<a href=\"mailto:$1\">$1<\/a>/g;
$string =~ s/(&lt;)(.*@.*)(&gt;)/$1<a href=\"mailto:$2\">$2<\/a>$3/g;
# HTMLify file names, assuming file is in the current directory.
$string =~ s#\b(([\w\-_\/]+\.(c|h|cc|cp|hpp|cpp|java))|README)\b#<a href=\"$config->{virtroot}/source$virtp$1\">$1</a>#g;
return($string);
}
# dme: Return true if string is in the identifier db and it seems like its
# use in the sentence is as an identifier and its not just some word that
# happens to have been used as a variable name somewhere. We don't want
# words like "of", "to" and "a" to get links. The string must be long
# enough, and either contain "_" or if some letter besides the first
# is capitalized
sub is_linkworthy{
my ($string) = @_;
if ($string =~ /....../
&& ($string =~ /_/ || $string =~ /.[A-Z]/)
# && defined($xref{$string}) FIXME
) {
return (1);
}
else {
return (0);
}
}
sub markspecials {
$_[0] =~ s/([\&\<\>])/\0$1/g;
}
sub htmlquote {
$_[0] =~ s/\0&/&amp;/g;
$_[0] =~ s/\0</&lt;/g;
$_[0] =~ s/\0>/&gt;/g;
}
sub freetextmarkup {
$_[0] =~ s{((f|ht)tp://[^\s<>\0]*[^\s<>\0.])}
{<a class='offshore' href="$1">$1</a>}g;
$_[0] =~ s{(\0<([^\s<>\0]+@[^\s<>\0]+)\0>)}
{<a class='offshore' href="mailto:$2">$1</a>}g;
}
sub markupfile {
#_PH_ supress block is here to avoid the <pre> tag output
#while called from diff
my ($fileh, $outfun) = @_;
my ($dir) = $pathname =~ m|^(.*/)|;
my $line = '001';
my @ltag = &fileref(1, "fline", $pathname, 1) =~ /^(<a)(.*\#)001(\">)1(<\/a>)$/;
$ltag[0] .= ' name=';
$ltag[3] .= " ";
my @itag = &idref(1, "fid", 1) =~ /^(.*=)1(\">)1(<\/a>)$/;
my $lang = new LXR::Lang($pathname, $release, @itag);
# A source code file
if ($lang) {
my $language = $lang->language; # To get back to the key to lookup the tabwidth.
&LXR::SimpleParse::init($fileh, $config->filetype->{$language}[3], $lang->parsespec);
my ($btype, $frag) = &LXR::SimpleParse::nextfrag;
#&$outfun("<pre class=\"file\">\n");
&$outfun(join($line++, @ltag)) if defined($frag);
while (defined($frag)) {
&markspecials($frag);
if ($btype eq 'comment') {
# Comment
# Convert mail adresses to mailto:
&freetextmarkup($frag);
$lang->processcomment(\$frag);
}
elsif ($btype eq 'string') {
# String
$frag = "<span class='string'>$frag</span>";
}
elsif ($btype eq 'include') {
# Include directive
$lang->processinclude(\$frag, $dir);
}
else {
# Code
$lang->processcode(\$frag);
}
&htmlquote($frag);
my $ofrag = $frag;
($btype, $frag) = &LXR::SimpleParse::nextfrag;
$ofrag =~ s/\n$// unless defined($frag);
$ofrag =~ s/\n/"\n".join($line++, @ltag)/ge;
&$outfun($ofrag);
}
#&$outfun("</pre>");
}
elsif ($pathname =~ /$config->graphicfile/) {
&$outfun("<ul><table><tr><th valign=\"center\"><b>Image: </b></th>");
&$outfun("<img src=\"$config->{virtroot}/source".
$pathname.&urlargs("raw=1").
"\" border=\"0\" alt=\"$pathname\">\n");
&$outfun("</tr></td></table></ul>");
}
elsif ($pathname =~ m|/CREDITS$|) {
while (defined($_ = $fileh->getline)) {
&LXR::SimpleParse::untabify($_);
&markspecials($_);
&htmlquote($_);
s/^N:\s+(.*)/<strong>$1<\/strong>/gm;
s/^(E:\s+)(\S+@\S+)/$1<a href=\"mailto:$2\">$2<\/a>/gm;
s/^(W:\s+)(.*)/$1<a href=\"$2\">$2<\/a>/gm;
# &$outfun("<a name=\"L$.\"><\/a>".$_);
&$outfun(join($line++, @ltag).$_);
}
}
else {
return unless defined ($_ = $fileh->getline);
# If it's not a script or something with an Emacs spec header and
# the first line is very long or containts control characters...
if (! /^\#!/ && ! /-\*-.*-\*-/i &&
(length($_) > 132 || /[\000-\010\013\014\016-\037\200-<2D>]/))
{
# We postulate that it's a binary file.
&$outfun("<ul><b>Binary File: ");
# jwz: URL-quote any special characters.
my $uname = $pathname;
$uname =~ s|([^-a-zA-Z0-9.\@/_\r\n])|sprintf("%%%02X", ord($1))|ge;
&$outfun("<a href=\"$config->{virtroot}/source".$uname.
&urlargs("raw=1")."\">");
&$outfun("$pathname</a></b>");
&$outfun("</ul>");
}
else {
#&$outfun("<pre class=\"file\">\n");
do {
&LXR::SimpleParse::untabify($_);
&markspecials($_);
&freetextmarkup($_);
&htmlquote($_);
# &$outfun("<a name=\"L$.\"><\/a>".$_);
&$outfun(join($line++, @ltag).$_);
} while (defined($_ = $fileh->getline));
#&$outfun("</pre>");
}
}
}
sub fixpaths {
my $node = '/'.shift;
while ($node =~ s|/[^/]+/\.\./|/|g) {}
$node =~ s|/\.\./|/|g;
$node .= '/' if $files->isdir($node);
$node =~ s|//+|/|g;
return $node;
}
sub printhttp {
# Print out a Last-Modified date that is the larger of: the
# underlying file that we are presenting; and the "source" script
# itself (passed in as an argument to this function.) If we can't
# stat either of them, don't print out a L-M header. (Note that this
# stats lxr/source but not lxr/lib/LXR/Common.pm. Oh well, I can
# live with that I guess...) -- jwz, 16-Jun-98
# Made it stat all currently loaded modules. -- agg.
# Todo: check lxr.conf.
print("HTTP/1.0 200 OK\n");
my $time = $files->getfiletime($pathname, $release);
my $time2 = (stat($config->confpath))[9];
$time = $time2 if $time2 > $time;
# Remove this to see if we get a speed increase by not stating all
# the modules. Since for most sites the modules change rarely,
# this is a big hit for each access.
# my %mods = ('main' => $0, %INC);
# my ($mod, $path);
# while (($mod, $path) = each %mods) {
# $mod =~ s/.pm$//;
# $mod =~ s|/|::|g;
# $path =~ s|/+|/|g;
# no strict 'refs';
# next unless $ {$mod.'::CVSID'};
# $time2 = (stat($path))[9];
# $time = $time2 if $time2 > $time;
# }
if ($time > 0) {
my ($sec, $min, $hour, $mday, $mon, $year,$wday) = gmtime($time);
my @days = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");
my @months = ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
$year += 1900;
$wday = $days[$wday];
$mon = $months[$mon];
# Last-Modified: Wed, 10 Dec 1997 00:55:32 GMT
printf("Last-Modified: %s, %2d %s %d %02d:%02d:%02d GMT\n",
$wday, $mday, $mon, $year, $hour, $min, $sec);
}
if ($HTTP->{'param'}->{'raw'}) {
#FIXME - need more types here
my %type = ('gif' => 'image/gif',
'html' => 'text/html');
if ($pathname =~ /\.([^.]+)$/ && $type{$1}) {
print("Content-type: ", $type{$1}, "\n");
}
else {
print("Content-Type: text/plain\n");
}
}
else {
print("Content-Type: text/html; charset=iso-8859-1\n");
# print("Content-Type: text/html\n");
}
# Close the HTTP header block.
print("\n");
}
# init - Returns the array ($config, $HTTP, $Path)
#
# Path:
# file - Name of file without path
# realf - The current file
# real - The directory portion of the current file
# root - The root of the sourcecode, same as sourceroot in $config
# virtf - Name of file within the sourcedir
# virt - Directory portion of same
# xref - Links to the different portions of the patname
#
# HTTP:
# path_info -
# param - Array of parameters
# this_url - The current url
#
# config:
# maplist - A list of the different mappings
# that are applied to the filename
# sourcedirhead - Corresponds to the configig options
# sourcehead -
# htmldir -
# sourceroot -
# htmlhead -
# incprefix -
# virtroot -
# glimpsebin -
# srcrootname -
# baseurl -
# htmltail -
sub httpinit {
$SIG{__WARN__} = \&warning;
$SIG{__DIE__} = \&fatal;
$HTTP->{'path_info'} = http_wash($ENV{'PATH_INFO'});
$HTTP->{'this_url'} = 'http://'.$ENV{'SERVER_NAME'};
$HTTP->{'this_url'} .= ':'.$ENV{'SERVER_PORT'} if
$ENV{'SERVER_PORT'} != 80;
$HTTP->{'this_url'} .= $ENV{'SCRIPT_NAME'}.$ENV{'PATH_INFO'};
$HTTP->{'this_url'} .= '?'.$ENV{'QUERY_STRING'} if
$ENV{'QUERY_STRING'};
$HTTP->{'param'} = { map { http_wash($_) }
$ENV{'QUERY_STRING'} =~ /([^;&=]+)(?:=([^;&]+)|)/g };
$HTTP->{'param'}->{'v'} ||= $HTTP->{'param'}->{'version'};
$HTTP->{'param'}->{'a'} ||= $HTTP->{'param'}->{'arch'};
$HTTP->{'param'}->{'i'} ||= $HTTP->{'param'}->{'identifier'};
$identifier = $HTTP->{'param'}->{'i'};
$config = new LXR::Config($HTTP->{'this_url'});
die "Can't find config for ".$HTTP->{'this_url'} if !defined($config);
$files = new LXR::Files($config->sourceroot);
die "Can't create Files for ".$config->sourceroot if !defined($files);
$index = new LXR::Index($config->dbname);
die "Can't create Index for ".$config->dbname if !defined($index);
foreach ($config->allvariables) {
$config->variable($_, $HTTP->{'param'}->{$_}) if $HTTP->{'param'}->{$_};
}
$release = $config->variable('v');
$pathname = fixpaths($HTTP->{'path_info'} || $HTTP->{'param'}->{'file'});
printhttp;
}
sub httpclean {
$config = undef;
$files = undef;
$index = undef;
}
sub expandtemplate {
my ($templ, %expfunc) = @_;
my ($expfun, $exppar);
while ($templ =~ s/(\{[^\{\}]*)\{([^\{\}]*)\}/$1\01$2\02/s) {}
$templ =~ s/(\$(\w+)(\{([^\}]*)\}|))/{
if (defined($expfun = $expfunc{$2})) {
if ($3 eq '') {
&$expfun(undef);
}
else {
$exppar = $4;
$exppar =~ s#\01#\{#gs;
$exppar =~ s#\02#\}#gs;
&$expfun($exppar);
}
}
else {
$1;
}
}/ges;
$templ =~ s/\01/\{/gs;
$templ =~ s/\02/\}/gs;
return($templ);
}
# What follows is somewhat less hairy way of expanding nested
# templates than it used to be. State information is passed via
# function arguments, as God intended.
sub bannerexpand {
my ($templ, $who) = @_;
if ($who eq 'source' || $who eq 'sourcedir' || $who eq 'diff') {
my $fpath = '';
my $furl = fileref($config->sourcerootname.'/', "banner", '/');
foreach ($pathname =~ m|([^/]+/?)|g) {
$fpath .= $_;
# jwz: put a space after each / in the banner so that it's
# possible for the pathnames to wrap. The <wbr> tag ought
# to do this, but it is ignored when sizing table cells,
# so we have to use a real space. It's somewhat ugly to
# have these spaces be visible, but not as ugly as getting
# a horizontal scrollbar...
$furl .= ' '.fileref($_, "banner", "/$fpath");
}
$furl =~ s|/</a>|</a>/|gi;
return "<span class=\"banner\">$furl</span>";
}
else {
return '';
}
}
sub pathname {
return $pathname;
}
sub titleexpand {
my ($templ, $who) = @_;
if ($who eq 'source' || $who eq 'diff' || $who eq 'sourcedir') {
return $config->sourcerootname.$pathname;
}
elsif ($who eq 'ident') {
my $i = $HTTP->{'param'}->{'i'};
return $config->sourcerootname.' identfier search'.($i ? " \"$i\"" : '');
}
elsif ($who eq 'search') {
my $s = $HTTP->{'param'}->{'string'};
return $config->sourcerootname.' freetext search'.($s ? " \"$s\"" : '');
}
elsif ($who eq 'find') {
my $s = $HTTP->{'param'}->{'string'};
return $config->sourcerootname.' file search'.($s ? " \"$s\"" : '');
}
}
sub thisurl {
my $url = $HTTP->{'this_url'};
$url =~ s/([\?\&\;\=])/sprintf('%%%02x',(unpack('c',$1)))/ge;
return($url);
}
sub baseurl {
(my $url = $config->baseurl) =~ s|/*$|/|;
return $url;
}
sub stylesheet {
return $config->stylesheet;
}
sub dotdoturl {
my $url = $config->baseurl;
$url =~ s@/$@@;
$url =~ s@/[^/]*$@@;
return($url);
}
# This one isn't too bad either. We just expand the "modes" template
# by filling in all the relevant values in the nested "modelink"
# template.
sub modeexpand {
my ($templ, $who) = @_;
my $modex = '';
my @mlist = ();
my $mode;
if ($who eq 'source' || $who eq 'sourcedir') {
push(@mlist, "<span class='modes-sel'>source navigation</span>");
}
else {
push(@mlist, fileref("source navigation", "modes", $pathname));
}
if ($who eq 'diff') {
push(@mlist, "<span class='modes-sel'>diff markup</span>");
}
elsif ($who eq 'source' && $pathname !~ m|/$|) {
push(@mlist, diffref("diff markup", "modes", $pathname));
}
if ($who eq 'ident') {
push(@mlist, "<span class='modes-sel'>identifier search</span>");
}
else {
push(@mlist, idref("identifier search", "modes", ""));
}
if ($who eq 'search') {
push(@mlist, "<span class='modes-sel'>freetext search</span>");
}
else {
push(@mlist, "<a class=\"modes\" ".
"href=\"$config->{virtroot}/search".
urlargs."\">freetext search</a>");
}
if ($who eq 'find') {
push(@mlist, "<span class='modes-sel'>file search</span>");
}
else {
push(@mlist, "<a class='modes' ".
"href=\"$config->{virtroot}/find".
urlargs."\">file search</a>");
}
foreach $mode (@mlist) {
$modex .= expandtemplate($templ,
('modelink' => sub { return $mode }));
}
return($modex);
}
# This is where it gets a bit tricky. varexpand expands the
# "variables" template using varname and varlinks, the latter in turn
# expands the nested "varlinks" template using varval.
sub varlinks {
my ($templ, $who, $var) = @_;
my $vlex = '';
my ($val, $oldval);
my $vallink;
$oldval = $config->variable($var);
foreach $val ($config->varrange($var)) {
if ($val eq $oldval) {
$vallink = "<span class=\"var-sel\">$val</span>";
}
else {
if ($who eq 'source' || $who eq 'sourcedir') {
$vallink = &fileref($val, "varlink",
$config->mappath($pathname,
"$var=$val"),
0,
"$var=$val");
}
elsif ($who eq 'diff') {
$vallink = &diffref($val, "varlink", $pathname, "$var=$val");
}
elsif ($who eq 'ident') {
$vallink = &idref($val, "varlink", $identifier, "$var=$val");
}
elsif ($who eq 'search') {
$vallink = "<a class=\"varlink\" href=\"$config->{virtroot}/search".
&urlargs("$var=$val",
"string=".$HTTP->{'param'}->{'string'}).
"\">$val</a>";
}
elsif ($who eq 'find') {
$vallink = "<a class=\"varlink\" href=\"$config->{virtroot}/find".
&urlargs("$var=$val",
"string=".$HTTP->{'param'}->{'string'}).
"\">$val</a>";
}
}
$vlex .= expandtemplate($templ,
('varvalue' => sub { return $vallink }));
}
return($vlex);
}
sub varexpand {
my ($templ, $who) = @_;
my $varex = '';
my $var;
foreach $var ($config->allvariables) {
$varex .= expandtemplate
($templ,
('varname' => sub { $config->vardescription($var) },
'varlinks' => sub { varlinks(@_, $who, $var) }));
}
return($varex);
}
sub devinfo {
my ($templ) = @_;
my (@mods, $mod, $path);
my %mods = ('main' => $0, %INC);
while (($mod, $path) = each %mods) {
$mod =~ s/.pm$//;
$mod =~ s|/|::|g;
$path =~ s|/+|/|g;
no strict 'refs';
next unless $ {$mod.'::CVSID'};
push(@mods, [ $ {$mod.'::CVSID'}, $path, (stat($path))[9] ]);
}
return join('',
map { expandtemplate
($templ,
('moduleid' => sub { $$_[0] },
'modpath' => sub { $$_[1] },
'modtime' => sub { scalar(localtime($$_[2])) }));
}
sort { $$b[2] <=> $$a[2] } @mods);
}
sub makeheader {
my $who = shift;
my $tmplname;
my $template = "<html><body>\n<hr>\n";
$tmplname = $who."head";
unless ($who ne "sourcedir" || $config->sourcedirhead) {
$tmplname = "sourcehead";
}
unless ($config->value($tmplname)) {
$tmplname = "htmlhead";
}
if ($config->value($tmplname)) {
if (open(TEMPL, $config->value($tmplname))) {
local($/) = undef;
$template = <TEMPL>;
close(TEMPL);
}
else {
warning("Template ".$config->value($tmplname)." does not exist.");
}
}
#CSS checked _PH_
print(expandtemplate($template,
('title' => sub { titleexpand(@_, $who) },
'banner' => sub { bannerexpand(@_, $who) },
'baseurl' => sub { baseurl(@_) },
'stylesheet' => sub { stylesheet(@_) },
'dotdoturl' => sub { dotdoturl(@_) },
'thisurl' => sub { thisurl(@_) },
'pathname' => sub { pathname(@_) },
'modes' => sub { modeexpand(@_, $who) },
'variables' => sub { varexpand(@_, $who) },
'devinfo' => sub { devinfo(@_) })));
}
sub makefooter {
my $who = shift;
my $tmplname;
my $template = "<hr>\n</body>\n";
$tmplname = $who."tail";
unless ($who ne "sourcedir" || $config->sourcedirhead) {
$tmplname = "sourcetail";
}
unless ($config->value($tmplname)) {
$tmplname = "htmltail";
}
if ($config->value($tmplname)) {
if (open(TEMPL, $config->value($tmplname))) {
local($/) = undef;
$template = <TEMPL>;
close(TEMPL);
}
else {
warning("Template ".$config->value($tmplname)." does not exist.");
}
}
print(expandtemplate($template,
('banner' => sub { bannerexpand(@_, $who) },
'thisurl' => sub { thisurl(@_) },
'modes' => sub { modeexpand(@_, $who) },
'variables' => sub { varexpand(@_, $who) },
'devinfo' => sub { devinfo(@_) })),
"</html>\n");
}
1;

View File

@@ -0,0 +1,213 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Config.pm,v 1.26 2002/02/26 15:59:32 mbox Exp $
# 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 LXR::Config;
$CVSID = '$Id: Config.pm,v 1.26 2002/02/26 15:59:32 mbox Exp $ ';
use strict;
use LXR::Common;
require Exporter;
use vars qw($AUTOLOAD $confname);
$confname = 'lxr.conf';
sub new {
my ($class, @parms) = @_;
my $self = {};
bless($self);
$self->_initialize(@parms);
return($self);
die("Foo!\n");
}
sub readfile {
local($/) = undef; # Just in case; probably redundant.
my $file = shift;
my @data;
open(INPUT, $file) || fatal("Config: cannot open $file\n");
$file = <INPUT>;
close(INPUT);
@data = $file =~ /([^\s]+)/gs;
return wantarray ? @data : $data[0];
}
sub _initialize {
my ($self, $url, $confpath) = @_;
my ($dir, $arg);
unless ($url) {
$url = 'http://'.$ENV{'SERVER_NAME'}.':'.$ENV{'SERVER_PORT'};
$url =~ s/:80$//;
$url .= $ENV{'SCRIPT_NAME'};
}
$url =~ s|^http://([^/]*):443/|https://$1/|;
unless ($confpath) {
($confpath) = ($0 =~ /(.*?)[^\/]*$/);
$confpath .= $confname;
}
unless (open(CONFIG, $confpath)) {
die("Couldn't open configuration file \"$confpath\".");
}
$$self{'confpath'} = $confpath;
local($/) = undef;
my @config = eval("\n#line 1 \"configuration file\"\n".
<CONFIG>);
die($@) if $@;
my $config;
foreach $config (@config) {
if ($config->{baseurl}) {
my $root = quotemeta($config->{baseurl});
next unless $url =~ /^$root/;
}
%$self = (%$self, %$config);
}
die "Can't find config for $url\n" if !defined $$self{baseurl};
}
sub allvariables {
my $self = shift;
return keys(%{$self->{variables} || {}});
}
sub variable {
my ($self, $var, $val) = @_;
$self->{variables}{$var}{value} = $val if defined($val);
return $self->{variables}{$var}{value} ||
$self->vardefault($var);
}
sub vardefault {
my ($self, $var) = @_;
return $self->{variables}{$var}{default} ||
$self->{variables}{$var}{range}[0];
}
sub vardescription {
my ($self, $var, $val) = @_;
$self->{variables}{$var}{name} = $val if defined($val);
return $self->{variables}{$var}{name};
}
sub varrange {
my ($self, $var) = @_;
if (ref($self->{variables}{$var}{range}) eq "CODE") {
return &{$self->{variables}{$var}{range}};
}
return @{$self->{variables}{$var}{range} || []};
}
sub varexpand {
my ($self, $exp) = @_;
$exp =~ s/\$\{?(\w+)\}?/$self->variable($1)/ge;
return $exp;
}
sub value {
my ($self, $var) = @_;
if (exists($self->{$var})) {
my $val = $self->{$var};
if (ref($val) eq 'ARRAY') {
return map { $self->varexpand($_) } @$val;
}
elsif (ref($val) eq 'CODE') {
return $val;
}
else {
return $self->varexpand($val);
}
}
else {
return undef;
}
}
sub AUTOLOAD {
my $self = shift;
(my $var = $AUTOLOAD) =~ s/.*:://;
my @val = $self->value($var);
if (ref($val[0]) eq 'CODE') {
return $val[0]->(@_);
}
else {
return wantarray ? @val : $val[0];
}
}
sub mappath {
my ($self, $path, @args) = @_;
my %oldvars;
my ($m, $n);
foreach $m (@args) {
if ($m =~ /(.*?)=(.*)/) {
$oldvars{$1} = $self->variable($1);
$self->variable($1, $2);
}
}
while (($m, $n) = each %{$self->{maps} || {}}) {
$path =~ s/$m/$self->varexpand($n)/e;
}
while (($m, $n) = each %oldvars) {
$self->variable($m, $n);
}
return $path;
}
1;

View File

@@ -0,0 +1,42 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Files.pm,v 1.6 2001/08/15 15:50:27 mbox Exp $
# 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 LXR::Files;
$CVSID = '$Id: Files.pm,v 1.6 2001/08/15 15:50:27 mbox Exp $ ';
use strict;
sub new {
my ($self, $srcroot) = @_;
my $files;
if ($srcroot =~ /^CVS:(.*)/i) {
require LXR::Files::CVS;
$srcroot = $1;
$files = new LXR::Files::CVS($srcroot);
}
else {
require LXR::Files::Plain;
$files = new LXR::Files::Plain($srcroot);
}
return $files;
}
1;

View File

@@ -0,0 +1,369 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: CVS.pm,v 1.17 2002/02/03 08:22:08 mbox Exp $
# 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 LXR::Files::CVS;
$CVSID = '$Id: CVS.pm,v 1.17 2002/02/03 08:22:08 mbox Exp $ ';
use strict;
use FileHandle;
use Time::Local;
use LXR::Common;
use vars qw(%cvs $cache_filename);
sub new {
my ($self, $rootpath) = @_;
$self = bless({}, $self);
$self->{'rootpath'} = $rootpath;
$self->{'rootpath'} =~ s@/*$@/@;
return $self;
}
sub filerev {
my ($self, $filename, $release) = @_;
if ($release =~ /rev_([\d\.]+)/) {
return $1;
}
elsif ($release =~ /^([\d\.]+)$/) {
return $1;
}
else {
$self->parsecvs($filename);
return $cvs{'header'}{'symbols'}{$release};
}
}
sub getfiletime {
my ($self, $filename, $release) = @_;
return undef if $self->isdir($filename, $release);
$self->parsecvs($filename);
my $rev = $self->filerev($filename, $release);
return undef unless defined($rev);
my @t = reverse(split(/\./, $cvs{'branch'}{$rev}{'date'}));
return undef unless @t;
$t[4]--;
return timegm(@t);
}
sub getfilesize {
my ($self, $filename, $release) = @_;
return length($self->getfile($filename, $release));
}
sub getfile {
my ($self, $filename, $release) = @_;
my $fileh = $self->getfilehandle($filename, $release);
return undef unless $fileh;
return join('', $fileh->getlines);
}
sub getannotations {
my ($self, $filename, $release) = @_;
$self->parsecvs($filename);
my $rev = $self->filerev($filename, $release);
return undef unless defined($rev);
my $hrev = $cvs{'header'}{'head'};
my $lrev;
my @anno;
my $headfh = $self->getfilehandle($filename, $release);
my @head = $headfh->getlines;
while (1) {
if ($rev eq $hrev) {
@head = 0..$#head;
}
$lrev = $hrev;
$hrev = $cvs{'branch'}{$hrev}{'next'} || last;
my @diff = $self->getdiff($filename, $lrev, $hrev);
my $off = 0;
while (@diff) {
my $dir = shift(@diff);
if ($dir =~ /^a(\d+)\s+(\d+)/) {
splice(@diff, 0, $2);
splice(@head, $1-$off, 0, ('') x $2);
$off -= $2;
}
elsif ($dir =~ /^d(\d+)\s+(\d+)/) {
map {
$anno[$_] = $lrev if $_ ne '';
} splice(@head, $1-$off-1, $2);
$off += $2;
}
else {
warn("Oops! Out of sync!");
}
}
}
map {
$anno[$_] = $lrev if $_ ne '';
} @head;
# print(STDERR "** Anno: ".scalar(@anno).join("\n", '', @anno, ''));
return @anno;
}
sub getauthor {
my ($self, $filename, $revision) = @_;
$self->parsecvs($filename);
return $cvs{'branch'}{$revision}{'author'};
}
sub getfilehandle {
my ($self, $filename, $release) = @_;
my ($fileh);
$self->parsecvs($filename);
my $rev = $self->filerev($filename, $release);
return undef unless defined($rev);
$fileh = new FileHandle("co -q -p$rev ".
$self->toreal($filename, $release).
" |"); # FIXME: Exploitable?
die("Error execting \"co\", rcs not installed?") unless $fileh;
return $fileh;
}
sub getdiff {
my ($self, $filename, $release1, $release2) = @_;
my ($fileh);
$self->parsecvs($filename);
my $rev1 = $self->filerev($filename, $release1);
return undef unless defined($rev1);
my $rev2 = $self->filerev($filename, $release2);
return undef unless defined($rev2);
$fileh = new FileHandle("rcsdiff -q -a -n -r$rev1 -r$rev2 ".
$self->toreal($filename, $release1).
" |"); # FIXME: Exploitable?
die("Error execting \"rcsdiff\", rcs not installed?") unless $fileh;
return $fileh->getlines;
}
sub tmpfile {
my ($self, $filename, $release) = @_;
my ($tmp, $buf);
$buf = $self->getfile($filename, $release);
return undef unless defined($buf);
$tmp = $config->tmpdir.'/lxrtmp.'.time.'.'.$$.'.'.&LXR::Common::tmpcounter;
open(TMP, "> $tmp") || return undef;
print(TMP $buf);
close(TMP);
return $tmp;
}
sub dirempty {
my ($self, $pathname, $release) = @_;
my ($node, @dirs, @files);
my $DIRH = new IO::Handle;
my $real = $self->toreal($pathname, $release);
opendir($DIRH, $real) || return 1;
while (defined($node = readdir($DIRH))) {
next if $node =~ /^\.|~$|\.orig$/;
next if $node eq 'CVS';
if (-d $real.$node) {
push(@dirs, $node.'/');
}
elsif ($node =~ /(.*),v$/) {
push(@files, $1);
}
}
closedir($DIRH);
foreach $node (@files) {
return 0 if $self->filerev($pathname.$node, $release);
}
foreach $node (@dirs) {
return 0 unless $self->dirempty($pathname.$node, $release);
}
return 1;
}
sub getdir {
my ($self, $pathname, $release) = @_;
my ($node, @dirs, @files);
my $DIRH = new IO::Handle;
my $real = $self->toreal($pathname, $release);
opendir($DIRH, $real) || return ();
while (defined($node = readdir($DIRH))) {
next if $node =~ /^\.|~$|\.orig$/;
next if $node eq 'CVS';
if (-d $real.$node) {
if ($node eq 'Attic') {
push(@files, $self->getdir($pathname.$node.'/', $release));
}
else {
push(@dirs, $node.'/')
unless defined($release)
&& $self->dirempty($pathname.$node.'/', $release);
}
}
elsif ($node =~ /(.*),v$/) {
push(@files, $1)
if ! defined($release)
|| $self->getfiletime($pathname.$1, $release);
}
}
closedir($DIRH);
return (sort(@dirs), sort(@files));
}
sub toreal {
my ($self, $pathname, $release) = @_;
my $real = $self->{'rootpath'}.$pathname;
return $real if -d $real;
return $real.',v' if -f $real.',v';
$real =~ s|(/[^/]+/?)$|/Attic$1|;
return $real if -d $real;
return $real.',v' if -f $real.',v';
return undef;
}
sub isdir {
my ($self, $pathname, $release) = @_;
return -d $self->toreal($pathname, $release);
}
sub isfile {
my ($self, $pathname, $release) = @_;
return -f $self->toreal($pathname, $release);
}
sub getindex {
my ($self, $pathname, $release) = @_;
my $index = $self->getfile($pathname, $release);
return $index =~ /\n(\S*)\s*\n\t-\s*([^\n]*)/gs;
}
sub allreleases {
my ($self, $filename) = @_;
$self->parsecvs($filename);
return sort(keys(%{$cvs{'header'}{'symbols'}}));
}
sub allrevisions {
my ($self, $filename) = @_;
$self->parsecvs($filename);
return sort(keys(%{$cvs{'branch'}}));
}
sub parsecvs {
# Actually, these days it just parses the header.
# RCS tools are much better at parsing RCS files.
# -pok
my ($self, $filename) = @_;
return if $cache_filename eq $filename;
$cache_filename = $filename;
%cvs = ();
my $file = '';
open (CVS, $self->toreal($filename, undef));
while (<CVS>) {
if (/^text\s*$/) {
# stop reading when we hit the text.
last;
}
$file .= $_;
}
close (CVS);
my @cvs = $file =~ /((?:(?:[^\n@]+|@[^@]*@)\n?)+)/gs;
$cvs{'header'} = { map { s/@@/@/gs;
/^@/s && substr($_, 1, -1) || $_ }
shift(@cvs) =~ /(\w+)\s*((?:[^;@]+|@[^@]*@)*);/gs };
$cvs{'header'}{'symbols'}
= { $cvs{'header'}{'symbols'} =~ /(\S+?):(\S+)/g };
my ($orel, $nrel, $rev);
while (($orel, $rev) = each %{$cvs{'header'}{'symbols'}}) {
$nrel = $config->cvsversion($orel);
next unless defined($nrel);
if ($nrel ne $orel) {
delete($cvs{'header'}{'symbols'}{$orel});
$cvs{'header'}{'symbols'}{$nrel} = $rev if $nrel;
}
}
$cvs{'header'}{'symbols'}{'head'} = $cvs{'header'}{'head'};
while (@cvs && $cvs[0] !~ /\s*desc/s) {
my ($r, $v) = shift(@cvs) =~ /\s*(\S+)\s*(.*)/s;
$cvs{'branch'}{$r} = { map { s/@@/@/gs;
/^@/s && substr($_, 1, -1) || $_ }
$v =~ /(\w+)\s*((?:[^;@]+|@[^@]*@)*);/gs };
}
$cvs{'desc'} = shift(@cvs) =~ /\s*desc\s+((?:[^\n@]+|@[^@]*@)*)\n/s;
$cvs{'desc'} =~ s/^@|@($|@)/$1/gs;
}
1;

View File

@@ -0,0 +1,171 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Plain.pm,v 1.19 2002/02/26 15:57:55 mbox Exp $
# 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 LXR::Files::Plain;
$CVSID = '$Id: Plain.pm,v 1.19 2002/02/26 15:57:55 mbox Exp $ ';
use strict;
use FileHandle;
use LXR::Common;
sub new {
my ($self, $rootpath) = @_;
$self = bless({}, $self);
$self->{'rootpath'} = $rootpath;
$self->{'rootpath'} =~ s@/*$@/@;
return $self;
}
sub filerev {
my ($self, $filename, $release) = @_;
# return $release;
return join("-", $self->getfiletime($filename, $release),
$self->getfilesize($filename, $release));
}
sub getfiletime {
my ($self, $filename, $release) = @_;
return (stat($self->toreal($filename, $release)))[9];
}
sub getfilesize {
my ($self, $filename, $release) = @_;
return -s $self->toreal($filename, $release);
}
sub getfile {
my ($self, $filename, $release) = @_;
my ($buffer);
local ($/) = undef;
open(FILE, "<", $self->toreal($filename, $release)) || return undef;
$buffer = <FILE>;
close(FILE);
return $buffer;
}
sub getfilehandle {
my ($self, $filename, $release) = @_;
my ($fileh);
$fileh = new FileHandle($self->toreal($filename, $release));
return $fileh;
}
sub tmpfile {
my ($self, $filename, $release) = @_;
my ($tmp, $tries);
local ($/) = undef;
$tmp = $config->tmpdir.'/lxrtmp.'.time.'.'.$$.'.'.&LXR::Common::tmpcounter;
open(TMP, "> $tmp") || return undef;
open(FILE, "<", $self->toreal($filename, $release)) || return undef;
print(TMP <FILE>);
close(FILE);
close(TMP);
return $tmp;
}
sub getannotations {
return ();
}
sub getauthor {
return undef;
}
sub getdir {
my ($self, $pathname, $release) = @_;
my ($dir, $node, @dirs, @files);
$dir = $self->toreal($pathname, $release);
opendir(DIR, $dir) || die ("Can't open $dir");
while (defined($node = readdir(DIR))) {
next if $node =~ /^\.|~$|\.orig$/;
next if $node eq 'CVS';
if (-d $dir.$node) {
push(@dirs, $node.'/');
}
else {
push(@files, $node);
}
}
closedir(DIR);
return sort(@dirs), sort(@files);
}
# This function should not be used outside this module
# except for printing error messages
# (I'm not sure even that is legitimate use, considering
# other possible File classes.)
sub toreal {
my ($self, $pathname, $release) = @_;
return ($self->{'rootpath'}.$release.$pathname);
}
sub isdir {
my ($self, $pathname, $release) = @_;
return -d $self->toreal($pathname, $release);
}
sub isfile {
my ($self, $pathname, $release) = @_;
return -f $self->toreal($pathname, $release);
}
sub getindex {
my ($self, $pathname, $release) = @_;
my ($index, %index);
my $indexname = $self->toreal($pathname, $release)."00-INDEX";
if (-f $indexname) {
open(INDEX, "<", $indexname) ||
warning("Existing $indexname could not be opened.");
local($/) = undef;
$index = <INDEX>;
%index = $index =~ /\n(\S*)\s*\n\t-\s*([^\n]*)/gs;
}
return %index;
}
sub allreleases {
my ($self, $filename) = @_;
opendir(SRCDIR, $self->{'rootpath'});
my @dirs = readdir(SRCDIR);
closedir(SRCDIR);
return grep { /^[^\.]/ && -r $self->toreal($filename, $_) } @dirs;
}
1;

View File

@@ -0,0 +1,46 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Index.pm,v 1.9 2001/08/15 15:50:27 mbox Exp $
# 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 LXR::Index;
$CVSID = '$Id: Index.pm,v 1.9 2001/08/15 15:50:27 mbox Exp $ ';
use LXR::Common;
use strict;
sub new {
my ($self, $dbname, @args) = @_;
my $index;
if ($dbname =~ /^DBI:/i) {
require LXR::Index::DBI;
$index = new LXR::Index::DBI($dbname, @args);
}
elsif ($dbname =~ /^DBM:/i) {
require LXR::Index::DB;
$index = new LXR::Index::DB($dbname, @args);
}
else {
die "Can't find database, $dbname";
}
return $index;
}
# TODO: Add skeleton code here to define the Index interface
1;

View File

@@ -0,0 +1,137 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: DB.pm,v 1.11 2001/08/15 15:50:27 mbox Exp $
# 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 LXR::Index::DB;
$CVSID = '$Id: DB.pm,v 1.11 2001/08/15 15:50:27 mbox Exp $ ';
use strict;
use DB_File;
use NDBM_File;
sub new {
my ($self, $dbpath, $mode) = @_;
my ($foo);
$self = bless({}, $self);
$$self{'dbpath'} = $dbpath;
$$self{'dbpath'} =~ s@/*$@/@;
foreach ('releases', 'files', 'symbols', 'indexes', 'status') {
$foo = {};
tie (%$foo, 'NDBM_File' , $$self{'dbpath'}.$_,
$mode||O_RDONLY, 0664) ||
die "Can't open database ".$$self{'dbpath'}.$_. "\n";
$$self{$_} = $foo;
}
return $self;
}
sub index {
my ($self, $symname, $fileid, $line, $type, $rel) = @_;
my $symid = $self->symid($symname);
$self->{'indexes'}{$symid} .= join("\t", $fileid, $line, $type, $rel)."\0";
# $$self{'index'}{$self->symid($symname, $release)} =
# join("\t", $filename, $line, $type, '');
}
# Returns array of (fileid, line, type)
sub getindex {
my ($self, $symname, $release) = @_;
my (@d, $f);
foreach $f (split(/\0/,
$$self{'indexes'}{$self->symid($symname, $release)})) {
my ($fi, $l, $t, $s) = split(/\t/, $f);
my %r = map { ($_ => 1) } split(/;/, $self->{'releases'}{$fi});
next unless $r{$release};
push(@d, [ $self->filename($fi), $l, $t, $s ]);
}
return @d;
}
sub getreference {
return ();
}
sub relate {
my ($self, $symname, $release, $rsymname, $reltype) = @_;
my $symid = $self->symid($symname, $release);
$$self{''}{$symid} = join("", $$self{'relation'}{$self->symid($symname, $release)}, join("\t", $self->symid($rsymname, $release), $reltype, ''));
}
sub getrelations {
my ($self, $symname, $release) = @_;
}
sub fileid {
my ($self , $filename, $release) = @_;
return $filename.';'.$release;
}
# Convert from fileid to filename
sub filename {
my ($self, $fileid) = @_;
my ($filename) = split(/;/, $fileid);
return $filename;
}
# If this file has not been indexed earlier, mark it as being indexed
# now and return true. Return false if already indexed.
sub toindex {
my ($self, $fileid) = @_;
return undef if $self->{'status'}{$fileid} >= 1;
$self->{'status'}{$fileid} = 1;
return 1;
}
# Indicate that this filerevision is part of this release
sub release {
my ($self, $fileid, $release) = @_;
$self->{'releases'}{$fileid} .= $release.";";
}
sub symid {
my ($self, $symname, $release) = @_;
my ($symid);
return $symname;
}
sub issymbol {
my ($self, $symname, $release) = @_;
return $$self{'indexes'}{$self->symid($symname, $release)};
}
sub empty_cache {
}
1;

View File

@@ -0,0 +1,43 @@
# -*- tab-width: 4 perl-indent-level: 4-*- ###############################
#
# $Id: DBI.pm,v 1.19 2002/02/26 16:18:46 mbox Exp $
# 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 LXR::Index::DBI;
$CVSID = '$Id: DBI.pm,v 1.19 2002/02/26 16:18:46 mbox Exp $ ';
use strict;
sub new {
my ($self, $dbname) = @_;
my ($index);
if($dbname =~ /^dbi:mysql:/i) {
require LXR::Index::Mysql;
$index = new LXR::Index::Mysql($dbname);
} elsif($dbname =~ /^dbi:Pg:/i) {
require LXR::Index::Postgres;
$index = new LXR::Index::Postgres($dbname);
} elsif($dbname =~ /^dbi:oracle:/i) {
require LXR::Index::Oracle;
$index = new LXR::Index::Oracle($dbname);
}
return $index;
}
1;

View File

@@ -0,0 +1,308 @@
# -*- tab-width: 4 perl-indent-level: 4-*- ###############################
#
# $Id: Mysql.pm,v 1.12 2001/11/18 03:31:34 mbox Exp $
# 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 LXR::Index::Mysql;
$CVSID = '$Id: Mysql.pm,v 1.12 2001/11/18 03:31:34 mbox Exp $ ';
use strict;
use DBI;
use LXR::Common;
use vars qw(%files %symcache @ISA);
@ISA = ("LXR::Index");
sub new {
my ($self, $dbname) = @_;
$self = bless({}, $self);
if(defined($config->{dbpass})) {
$self->{dbh} = DBI->connect($dbname, $config->{dbuser},
$config->{dbpass})
|| fatal "Can't open connection to database\n";
} else {
$self->{dbh} = DBI->connect($dbname, "lxr", $config->{dbpass})
|| fatal "Can't open connection to database\n";
}
%files = ();
%symcache = ();
$self->{files_select} = $self->{dbh}->prepare
("select fileid from files where filename = ? and revision = ?");
$self->{files_insert} = $self->{dbh}->prepare
("insert into files (filename, revision, fileid) values (?, ?, NULL)");
$self->{symbols_byname} = $self->{dbh}->prepare
("select symid from symbols where symname = ?");
$self->{symbols_byid} = $self->{dbh}->prepare
("select symname from symbols where symid = ?");
$self->{symbols_insert} = $self->{dbh}->prepare
("insert into symbols (symname, symid) values ( ?, NULL)");
$self->{symbols_remove} = $self->{dbh}->prepare
("delete from symbols where symname = ?");
$self->{indexes_select} = $self->{dbh}->prepare
("select f.filename, i.line, d.declaration, i.relsym ".
"from symbols s, indexes i, files f, releases r, declarations d ".
"where s.symid = i.symid and i.fileid = f.fileid ".
"and f.fileid = r.fileid ".
"and i.langid = d.langid and i.type = d.declid ".
"and s.symname = ? and r.release = ?");
$self->{indexes_insert} = $self->{dbh}->prepare
("insert into indexes (symid, fileid, line, langid, type, relsym) values (?, ?, ?, ?, ?, ?)");
$self->{releases_select} = $self->{dbh}->prepare
("select * from releases where fileid = ? and release = ?");
$self->{releases_insert} = $self->{dbh}->prepare
("insert into releases (fileid, release) values (?, ?)");
$self->{status_get} = $self->{dbh}->prepare
("select status from status where fileid = ?");
$self->{status_insert} = $self->{dbh}->prepare
# ("insert into status select ?, 0 except select fileid, 0 from status");
("insert into status (fileid, status) values (?, ?)");
$self->{status_update} = $self->{dbh}->prepare
("update status set status = ? where fileid = ? and status <= ?");
$self->{usage_insert} = $self->{dbh}->prepare
("insert into useage (fileid, line, symid) values (?, ?, ?)");
$self->{usage_select} = $self->{dbh}->prepare
("select f.filename, u.line ".
"from symbols s, files f, releases r, useage u ".
"where s.symid = u.symid ".
"and f.fileid = u.fileid ".
"and u.fileid = r.fileid ".
"and s.symname = ? and r.release = ? ".
"order by f.filename");
$self->{decl_select} = $self->{dbh}->prepare
("select declid from declarations where langid = ? and ".
"declaration = ?");
$self->{decl_insert} = $self->{dbh}->prepare
("insert into declarations (declid, langid, declaration) values (NULL, ?, ?)");
return $self;
}
sub index {
my ($self, $symname, $fileid, $line, $langid, $type, $relsym) = @_;
$self->{indexes_insert}->execute($self->symid($symname),
$fileid,
$line,
$langid,
$type,
$relsym ? $self->symid($relsym) : undef);
}
sub reference {
my ($self, $symname, $fileid, $line) = @_;
$self->{usage_insert}->execute($fileid,
$line,
$self->symid($symname));
}
sub getindex {
my ($self, $symname, $release) = @_;
my ($rows, @ret);
$rows = $self->{indexes_select}->execute("$symname", "$release");
while ($rows-- > 0) {
push(@ret, [ $self->{indexes_select}->fetchrow_array ]);
}
$self->{indexes_select}->finish();
map { $$_[3] &&= $self->symname($$_[3]) } @ret;
return @ret;
}
sub getreference {
my ($self, $symname, $release) = @_;
my ($rows, @ret);
$rows = $self->{usage_select}->execute("$symname", "$release");
while ($rows-- > 0) {
push(@ret, [ $self->{usage_select}->fetchrow_array ]);
}
$self->{usage_select}->finish();
return @ret;
}
sub fileid {
my ($self, $filename, $revision) = @_;
my ($fileid);
# CAUTION: $revision is not $release!
unless (defined($fileid = $files{"$filename\t$revision"})) {
$self->{files_select}->execute($filename, $revision);
($fileid) = $self->{files_select}->fetchrow_array();
unless ($fileid) {
$self->{files_insert}->execute($filename, $revision);
$self->{files_select}->execute($filename, $revision);
($fileid) = $self->{files_select}->fetchrow_array();
}
$files{"$filename\t$revision"} = $fileid;
$self->{files_select}->finish();
}
return $fileid;
}
# Indicate that this filerevision is part of this release
sub release {
my ($self, $fileid, $release) = @_;
my $rows = $self->{releases_select}->execute($fileid+0, $release);
$self->{releases_select}->finish();
unless ($rows > 0) {
$self->{releases_insert}->execute($fileid, $release);
$self->{releases_insert}->finish();
}
}
sub symid {
my ($self, $symname) = @_;
my ($symid);
$symid = $symcache{$symname};
unless (defined($symid)) {
$self->{symbols_byname}->execute($symname);
($symid) = $self->{symbols_byname}->fetchrow_array();
$self->{symbols_byname}->finish();
unless ($symid) {
$self->{symbols_insert}->execute($symname);
# Get the id of the new symbol
$self->{symbols_byname}->execute($symname);
($symid) = $self->{symbols_byname}->fetchrow_array();
$self->{symbols_byname}->finish();
}
$symcache{$symname} = $symid;
}
return $symid;
}
sub symname {
my ($self, $symid) = @_;
my ($symname);
$self->{symbols_byid}->execute($symid+0);
($symname) = $self->{symbols_byid}->fetchrow_array();
$self->{symbols_byid}->finish();
return $symname;
}
sub issymbol {
my ($self, $symname) = @_;
my ($symid);
$symid = $symcache{$symname};
unless (defined($symid)) {
$self->{symbols_byname}->execute($symname);
($symid) = $self->{symbols_byname}->fetchrow_array();
$self->{symbols_byname}->finish();
$symcache{$symname} = $symid;
}
return $symid;
}
# If this file has not been indexed earlier, mark it as being indexed
# now and return true. Return false if already indexed.
sub toindex {
my ($self, $fileid) = @_;
my ($status);
$self->{status_get}->execute($fileid);
$status = $self->{status_get}->fetchrow_array();
$self->{status_get}->finish();
if(!defined($status)) {
$self->{status_insert}->execute($fileid+0, 0);
}
return $self->{status_update}->execute(1, $fileid, 0) > 0;
}
sub toreference {
my ($self, $fileid) = @_;
my ($rv);
return $self->{status_update}->execute(2, $fileid, 1) > 0;
}
# This function should be called before parsing each new file,
# if this is not done the too much memory will be used and
# tings will become very slow.
sub empty_cache {
%symcache = ();
}
sub getdecid {
my ($self, $lang, $string) = @_;
my $rows = $self->{decl_select}->execute($lang, $string);
$self->{decl_select}->finish();
unless ($rows > 0) {
$self->{decl_insert}->execute($lang, $string);
}
$self->{decl_select}->execute($lang, $string);
my $id = $self->{decl_select}->fetchrow_array();
$self->{decl_select}->finish();
return $id;
}
sub DESTROY {
my ($self) = @_;
$self->{files_select} = undef;
$self->{files_insert} = undef;
$self->{symbols_byname} = undef;
$self->{symbols_byid} = undef;
$self->{symbols_insert} = undef;
$self->{indexes_insert} = undef;
$self->{releases_insert} = undef;
$self->{status_insert} = undef;
$self->{status_update} = undef;
$self->{usage_insert} = undef;
$self->{usage_select} = undef;
$self->{decl_select} = undef;
$self->{decl_insert} = undef;
if($self->{dbh}) {
$self->{dbh}->disconnect();
$self->{dbh} = undef;
}
}
1;

View File

@@ -0,0 +1,291 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Oracle.pm,v 1.1 2002/02/26 16:18:47 mbox Exp $
# 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 LXR::Index::Oracle;
$CVSID = '$Id: Oracle.pm,v 1.1 2002/02/26 16:18:47 mbox Exp $ ';
use strict;
use DBI;
use LXR::Common;
use vars qw(%files %symcache @ISA);
@ISA = ("LXR::Index");
sub new {
my ($self, $dbname) = @_;
$self = bless({}, $self);
$self->{dbh} = DBI->connect($dbname, $config->{dbuser}, $config->{dbpass}, { RaiseError => 1, AutoCommit => 1 })
|| fatal "Can't open connection to database\n";
%files = ();
%symcache = ();
$self->{files_select} = $self->{dbh}->prepare
("select fileid from files where filename = ? and revision = ?");
$self->{files_insert} = $self->{dbh}->prepare
("insert into files values (?, ?, filenum.nextval)");
$self->{symbols_byname} = $self->{dbh}->prepare
("select symid from symbols where symname = ?");
$self->{symbols_byid} = $self->{dbh}->prepare
("select symname from symbols where symid = ?");
$self->{symbols_insert} = $self->{dbh}->prepare
("insert into symbols values ( ?, symnum.nextval)");
$self->{symbols_remove} = $self->{dbh}->prepare
("delete from symbols where symname = ?");
$self->{indexes_select} = $self->{dbh}->prepare
("select f.filename, i.line, i.type, i.relsym ".
"from symbols s, indexes i, files f, releases r ".
"where s.symid = i.symid and i.fileid = f.fileid ".
"and f.fileid = r.fileid ".
"and s.symname = ? and r.release = ? ");
$self->{indexes_insert} = $self->{dbh}->prepare
("insert into indexes values (?, ?, ?, ?, ?)");
$self->{releases_select} = $self->{dbh}->prepare
("select * from releases where fileid = ? and release = ?");
$self->{releases_insert} = $self->{dbh}->prepare
("insert into releases values (?, ?)");
$self->{status_get} = $self->{dbh}->prepare
("select status from status where fileid = ?");
$self->{status_insert} = $self->{dbh}->prepare
# ("insert into status select ?, 0 except select fileid, 0 from status");
("insert into status values (?, ?)");
$self->{status_update} = $self->{dbh}->prepare
("update status set status = ? where fileid = ? and status <= ?");
$self->{usage_insert} = $self->{dbh}->prepare
("insert into usage values (?, ?, ?)");
$self->{usage_select} = $self->{dbh}->prepare
("select f.filename, u.line ".
"from symbols s, files f, releases r, usage u ".
"where s.symid = u.symid ".
"and f.fileid = u.fileid ".
"and u.fileid = r.fileid and ".
"s.symname = ? and r.release = ? ".
"order by f.filename");
return $self;
}
sub index {
my ($self, $symname, $fileid, $line, $type, $relsym) = @_;
$self->{indexes_insert}->execute($self->symid($symname),
$fileid,
$line,
$type,
$relsym ? $self->symid($relsym) : undef);
}
sub reference {
my ($self, $symname, $fileid, $line) = @_;
$self->{usage_insert}->execute($fileid,
$line,
$self->symid($symname));
}
sub getindex { # Hinzugef<65>gt von Variable @row, While-Schleife
my ($self, $symname, $release) = @_;
my ($rows, @ret, @row);
$rows = $self->{indexes_select}->execute("$symname", "$release");
while (@row = $self->{indexes_select}->fetchrow_array){
push (@ret,[@row]);
}
#while ($rows-- > 0) {
# push(@ret, [ $self->{indexes_select}->fetchrow_array ]);
#}
$self->{indexes_select}->finish();
map { $$_[3] &&= $self->symname($$_[3]) } @ret;
return @ret;
}
sub getreference {
my ($self, $symname, $release) = @_;
my ($rows, @ret, @row);
$rows = $self->{usage_select}->execute("$symname", "$release");
while (@row = $self->{usage_select}->fetchrow_array){
push (@ret,[@row]);
}
#while ($rows-- > 0) {
# push(@ret, [ $self->{usage_select}->fetchrow_array ]);
#}
$self->{usage_select}->finish();
return @ret;
}
sub fileid {
my ($self, $filename, $revision) = @_;
my ($fileid);
# CAUTION: $revision is not $release!
unless (defined($fileid = $files{"$filename\t$revision"})) {
$self->{files_select}->execute($filename, $revision);
($fileid) = $self->{files_select}->fetchrow_array();
unless ($fileid) {
$self->{files_insert}->execute($filename, $revision);
$self->{files_select}->execute($filename, $revision);
($fileid) = $self->{files_select}->fetchrow_array();
}
$files{"$filename\t$revision"} = $fileid;
$self->{files_select}->finish();
}
return $fileid;
}
# Indicate that this filerevision is part of this release
sub release {
my ($self, $fileid, $release) = @_;
my (@row);
my $rows = $self->{releases_select}->execute($fileid+0, $release);
while (@row = $self->{releases_select}->fetchrow_array){
$rows=1;
}
$self->{releases_select}->finish();
unless ($rows > 0) {
$self->{releases_insert}->execute($fileid+0, $release);
$self->{releases_insert}->finish();
}
}
sub symid {
my ($self, $symname) = @_;
my ($symid);
$symid = $symcache{$symname};
unless (defined($symid)) {
$self->{symbols_byname}->execute($symname);
($symid) = $self->{symbols_byname}->fetchrow_array();
$self->{symbols_byname}->finish();
unless ($symid) {
$self->{symbols_insert}->execute($symname);
# Get the id of the new symbol
$self->{symbols_byname}->execute($symname);
($symid) = $self->{symbols_byname}->fetchrow_array();
$self->{symbols_byname}->finish();
}
$symcache{$symname} = $symid;
}
return $symid;
}
sub symname {
my ($self, $symid) = @_;
my ($symname);
$self->{symbols_byid}->execute($symid+0);
($symname) = $self->{symbols_byid}->fetchrow_array();
$self->{symbols_byid}->finish();
return $symname;
}
sub issymbol {
my ($self, $symname) = @_;
my ($symid);
$symid = $symcache{$symname};
unless (defined($symid)) {
$self->{symbols_byname}->execute($symname);
($symid) = $self->{symbols_byname}->fetchrow_array();
$self->{symbols_byname}->finish();
$symcache{$symname} = $symid;
}
return $symid;
}
# If this file has not been indexed earlier, mark it as being indexed
# now and return true. Return false if already indexed.
sub toindex {
my ($self, $fileid) = @_;
my ($status);
$self->{status_get}->execute($fileid);
$status = $self->{status_get}->fetchrow_array();
$self->{status_get}->finish();
if(!defined($status)) {
$self->{status_insert}->execute($fileid+0, 0);
}
return $self->{status_update}->execute(1, $fileid, 0) > 0;
}
sub toreference {
my ($self, $fileid) = @_;
my ($rv);
return $self->{status_update}->execute(2, $fileid, 1) > 0;
}
# This function should be called before parsing each new file,
# if this is not done the too much memory will be used and
# tings will become very slow.
sub empty_cache {
%symcache = ();
}
sub DESTROY {
my ($self) = @_;
$self->{files_select} = undef;
$self->{files_insert} = undef;
$self->{symbols_byname} = undef;
$self->{symbols_byid} = undef;
$self->{symbols_insert} = undef;
$self->{indexes_insert} = undef;
$self->{releases_insert} = undef;
$self->{status_insert} = undef;
$self->{status_update} = undef;
$self->{usage_insert} = undef;
$self->{usage_select} = undef;
if($self->{dbh}) {
$self->{dbh}->disconnect();
$self->{dbh} = undef;
}
}
1;

View File

@@ -0,0 +1,330 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Postgres.pm,v 1.10 2002/01/23 15:48:52 mbox Exp $
# 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 LXR::Index::Postgres;
$CVSID = '$Id: Postgres.pm,v 1.10 2002/01/23 15:48:52 mbox Exp $ ';
use strict;
use DBI;
use LXR::Common;
use vars qw($dbh $transactions %files %symcache $commitlimit
$files_select $filenum_nextval $files_insert
$symbols_byname $symbols_byid $symnum_nextval
$symbols_remove $symbols_insert $indexes_select $indexes_insert
$releases_select $releases_insert $status_insert
$status_update $usage_insert $usage_select $decl_select
$declid_nextnum $decl_insert);
sub new {
my ($self, $dbname) = @_;
$self = bless({}, $self);
$dbh ||= DBI->connect($dbname, $config->{'dbuser'}, $config->{'dbpass'});
die($DBI::errstr) unless $dbh;
$$dbh{'AutoCommit'} = 0;
# $dbh->trace(1);
$commitlimit = 100;
$transactions = 0;
%files = ();
%symcache = ();
$files_select = $dbh->prepare
("select fileid from files where filename = ? and revision = ?");
$filenum_nextval = $dbh->prepare
("select nextval('filenum')");
$files_insert = $dbh->prepare
("insert into files values (?, ?, ?)");
$symbols_byname = $dbh->prepare
("select symid from symbols where symname = ?");
$symbols_byid = $dbh->prepare
("select symname from symbols where symid = ?");
$symnum_nextval = $dbh->prepare
("select nextval('symnum')");
$symbols_insert = $dbh->prepare
("insert into symbols values (?, ?)");
$symbols_remove = $dbh->prepare
("delete from symbols where symname = ?");
$indexes_select = $dbh->prepare
("select f.filename, i.line, d.declaration, i.relsym ".
"from symbols s, indexes i, files f, releases r, declarations d ".
"where s.symid = i.symid and i.fileid = f.fileid ".
"and f.fileid = r.fileid ".
"and i.langid = d.langid and i.type = d.declid ".
"and s.symname = ? and r.release = ?");
$indexes_insert = $dbh->prepare
("insert into indexes (symid, fileid, line, langid, type, relsym) ".
"values (?, ?, ?, ?, ?, ?)");
$releases_select = $dbh->prepare
("select * from releases where fileid = ? and release = ?");
$releases_insert = $dbh->prepare
("insert into releases values (?, ?)");
$status_insert = $dbh->prepare
# ("insert into status select ?, 0 except select fileid, 0 from status");
("insert into status select ?, 0 where not exists ".
"(select * from status where fileid = ?)");
$status_update = $dbh->prepare
("update status set status = ? where fileid = ? and status <= ?");
$usage_insert = $dbh->prepare
("insert into usage values (?, ?, ?)");
$usage_select = $dbh->prepare
("select f.filename, u.line ".
"from symbols s, files f, releases r, usage u ".
"where s.symid = u.symid ".
"and f.fileid = u.fileid ".
"and f.fileid = r.fileid and ".
"s.symname = ? and r.release = ?");
$declid_nextnum = $dbh->prepare
("select nextval('declnum')");
$decl_select = $dbh->prepare
("select declid from declarations where langid = ? and ".
"declaration = ?");
$decl_insert = $dbh->prepare
("insert into declarations (declid, langid, declaration) values (?, ?, ?)");
return $self;
}
sub empty_cache {
%symcache = ();
}
sub commit_if_limit {
unless (++$transactions % $commitlimit) {
$dbh->commit();
}
}
sub index {
my ($self, $symname, $fileid, $line, $langid, $type, $relsym) = @_;
$indexes_insert->execute($self->symid($symname),
$fileid,
$line,
$langid,
$type,
$relsym ? $self->symid($relsym) : undef);
commit_if_limit();
}
sub reference {
my ($self, $symname, $fileid, $line) = @_;
$usage_insert->execute($fileid,
$line,
$self->symid($symname));
commit_if_limit();
}
sub getindex {
my ($self, $symname, $release) = @_;
my ($rows, @ret);
$rows = $indexes_select->execute("$symname", "$release");
while ($rows-- > 0) {
push(@ret, [ $indexes_select->fetchrow_array ]);
}
$indexes_select->finish();
map { $$_[3] &&= $self->symname($$_[3]) } @ret;
return @ret;
}
sub getreference {
my ($self, $symname, $release) = @_;
my ($rows, @ret);
$rows = $usage_select->execute("$symname", "$release");
while ($rows-- > 0) {
push(@ret, [ $usage_select->fetchrow_array ]);
}
$usage_select->finish();
return @ret;
}
sub relate {
my ($self, $symname, $release, $rsymname, $reltype) = @_;
# $relation{$self->symid($symname, $release)} .=
# join("\t", $self->symid($rsymname, $release), $reltype, '');
}
sub getrelations {
my ($self, $symname, $release) = @_;
}
sub fileid {
my ($self, $filename, $revision) = @_;
my ($fileid);
# CAUTION: $revision is not $release!
unless (defined($fileid = $files{"$filename\t$revision"})) {
$files_select->execute($filename, $revision);
($fileid) = $files_select->fetchrow_array();
unless ($fileid) {
$filenum_nextval->execute();
($fileid) = $filenum_nextval->fetchrow_array();
$files_insert->execute($filename, $revision, $fileid);
}
$files{"$filename\t$revision"} = $fileid;
}
commit_if_limit();
return $fileid;
}
# Indicate that this filerevision is part of this release
sub release {
my ($self, $fileid, $release) = @_;
$releases_select->execute($fileid+0, $release);
my $firstrow = $releases_select->fetchrow_array();
# $releases_select->finish();
unless ($firstrow) {
$releases_insert->execute($fileid+0, $release);
}
commit_if_limit();
}
sub symid {
my ($self, $symname) = @_;
my ($symid);
unless (defined($symid = $symcache{$symname})) {
$symbols_byname->execute($symname);
($symid) = $symbols_byname->fetchrow_array();
unless ($symid) {
$symnum_nextval->execute();
($symid) = $symnum_nextval->fetchrow_array();
$symbols_insert->execute($symname, $symid);
}
$symcache{$symname} = $symid;
}
commit_if_limit();
return $symid;
}
sub symname {
my ($self, $symid) = @_;
my ($symname);
$symbols_byid->execute($symid+0);
($symname) = $symbols_byid->fetchrow_array();
return $symname;
}
sub issymbol {
my ($self, $symname) = @_;
unless (exists($symcache{$symname})) {
$symbols_byname->execute($symname);
($symcache{$symname}) = $symbols_byname->fetchrow_array();
}
return $symcache{$symname};
}
# If this file has not been indexed earlier, mark it as being indexed
# now and return true. Return false if already indexed.
sub toindex {
my ($self, $fileid) = @_;
$status_insert->execute($fileid+0, $fileid+0);
commit_if_limit();
return $status_update->execute(1, $fileid+0, 0) > 0;
}
sub toreference {
my ($self, $fileid) = @_;
return $status_update->execute(2, $fileid, 1) > 0;
}
sub getdecid {
my ($self, $lang, $string) = @_;
my $rows = $decl_select->execute($lang, $string);
$decl_select->finish();
unless ($rows > 0) {
$declid_nextnum->execute();
my ($declid) = $declid_nextnum->fetchrow_array();
$decl_insert->execute($declid, $lang, $string);
}
$decl_select->execute($lang, $string);
my $id = $decl_select->fetchrow_array();
$decl_select->finish();
commit_if_limit();
return $id;
}
sub END {
$files_select= undef;
$filenum_nextval= undef;
$files_insert = undef;
$symbols_byname= undef;
$symbols_byid= undef;
$symnum_nextval = undef;
$symbols_remove= undef;
$symbols_insert= undef;
$indexes_select= undef;
$indexes_insert = undef;
$releases_select= undef;
$releases_insert= undef;
$status_insert = undef;
$status_update= undef;
$usage_insert= undef;
$usage_select= undef;
$decl_select = undef;
$declid_nextnum= undef;
$decl_insert = undef;
$dbh->commit();
$dbh->disconnect();
$dbh = undef;
}
1;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,95 @@
# -*- tab-width: 4; cperl-indent-level: 4 -*- ###############################################
#
# $Id: Lang.pm,v 1.29 2002/03/18 14:55:43 mbox Exp $
# 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 LXR::Lang;
$CVSID = '$Id: Lang.pm,v 1.29 2002/03/18 14:55:43 mbox Exp $ ';
use strict;
use LXR::Common;
sub new {
my ($self, $pathname, $release, @itag) = @_;
my ($lang, $type);
foreach $type (values %{$config->filetype}) {
if ($pathname =~ /$$type[1]/) {
eval "require $$type[2]";
die "Unable to load $$type[2] Lang class, $@" if $@;
my $create = "new $$type[2]".'($pathname, $release, $$type[0])';
$lang = eval($create);
die "Unable to create $$type[2] Lang object, $@" unless defined $lang;
last;
}
}
if (!defined $lang) {
# Try to see if it's a script
my $fh = $files->getfilehandle($pathname, $release);
return undef if !defined $fh;
$fh->getline =~ /^\#!\s*(\S+)/s;
my $shebang = $1;
my %filetype = %{$config->filetype};
my %inter = %{$config->interpreters};
foreach my $patt (keys %inter) {
if ($shebang =~ /$patt/) {
eval "require $filetype{$inter{$patt}}[2]";
die "Unable to load $filetype{$inter{$patt}}[2] Lang class, $@" if $@;
my $create = "new ".
$filetype{$inter{$patt}}[2].'($pathname, $release, $filetype{$inter{$patt}}[0])';
$lang = eval($create);
last if defined $lang;
die "Unable to create $filetype{$inter{$patt}}[2] Lang object, $@";
}
}
}
# No match for this file
return undef if !defined $lang;
$$lang{'itag'} = \@itag if $lang;
return $lang;
}
sub processinclude {
my ($self, $frag, $dir) = @_;
$$frag =~ s#(\")(.*?)(\")#
$1.&LXR::Common::incref($2, "include", $2, $dir).$3 #e;
$$frag =~ s#(\0<)(.*?)(\0>)#
$1.&LXR::Common::incref($2, "include", $2).$3 #e;
}
sub processcomment {
my ($self, $frag) = @_;
$$frag = "<span class=\"comment\">$$frag</span>";
$$frag =~ s#\n#</span>\n<span class=\"comment\">#g;
}
sub referencefile {
my ($self) = @_;
print(STDERR ref($self), "->referencefile not implemented.\n");
}
1;

View File

@@ -0,0 +1,293 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Generic.pm,v 1.12 2002/07/29 00:58:42 mbox Exp $
#
# Implements generic support for any language that ectags can parse.
# This may not be ideal support, but it should at least work until
# someone writes better support.
#
# 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 LXR::Lang::Generic;
$CVSID = '$Id: Generic.pm,v 1.12 2002/07/29 00:58:42 mbox Exp $ ';
use strict;
use LXR::Common;
use LXR::Lang;
use vars qw($AUTOLOAD);
my $generic_config;
@LXR::Lang::Generic::ISA = ('LXR::Lang');
sub new {
my ($proto, $pathname, $release, $lang) = @_;
my $class = ref($proto) || $proto;
my $self = {};
bless ($self, $class);
$$self{'release'} = $release;
$$self{'language'} = $lang;
read_config() unless defined $generic_config;
%$self = (%$self, %$generic_config);
# Set langid
$$self{'langid'} = $self->langinfo('langid');
die "No langid for language $lang" if !defined $self->langid;
return $self;
}
# This is only executed once, saving the overhead of processing the
# config file each time. Because it is only done once, we also use
# this to check the version of ctags.
sub read_config {
open (CONF, $config->genericconf) || die "Can't open ".$config->genericconf.", $!";
local($/) = undef;
$generic_config = eval ("\n#line 1 \"generic.conf\"\n".
<CONF>);
die ($@) if $@;
close CONF;
# Setup the ctags to declid mapping
my $langmap = $generic_config->{'langmap'};
foreach my $lang (keys %$langmap) {
my $typemap = $langmap->{$lang}{'typemap'};
foreach my $type (keys %$typemap) {
$typemap->{$type} =
$index->getdecid($langmap->{$lang}{'langid'},
$typemap->{$type});
}
}
my $ctags = $config->ectagsbin;
my $version = `$ctags --version`;
$version=~ /Exuberant ctags +(\d+)/i;
if($1 < 5 ) {
die "Exuberant ctags version 5 or above required, found $version\n";
}
}
sub indexfile {
my ($self, $name, $path, $fileid, $index, $config) = @_;
my $typemap = $self->langinfo('typemap');
my $langforce = $ {$self->eclangnamemapping}{$self->language};
if (!defined $langforce) {
$langforce = $self->language;
}
if ($config->ectagsbin) {
open(CTAGS, join(" ", $config->ectagsbin,
$self->ectagsopts,
"--excmd=number",
"--language-force=$langforce",
"-f", "-",
$path, "|")) or die "Can't run ectags, $!";
while (<CTAGS>) {
chomp;
my ($sym, $file, $line, $type,$ext) = split(/\t/, $_);
$line =~ s/;\"$//;
$ext =~ /language:(\w+)/;
$type = $typemap->{$type};
if(!defined $type) {
print "Warning: Unknown type ", (split(/\t/,$_))[3], "\n";
next;
}
# TODO: can we make it more generic in parsing the extension fields?
if (defined($ext) && $ext =~ /^(struct|union|class|enum):(.*)/) {
$ext = $2;
$ext =~ s/::<anonymous>//g;
} else {
$ext = undef;
}
$index->index($sym, $fileid, $line, $self->langid, $type, $ext);
}
close(CTAGS);
}
}
# This method returns the regexps used by SimpleParse to break the
# code into different blocks such as code, string, include, comment etc.
# Since this depends on the language, it's configured via generic.conf
sub parsespec {
my ($self) = @_;
my @spec = $self->langinfo('spec');
return @spec;
}
# Process a chunk of code
# Basically, look for anything that looks like an identifier, and if
# it is then make it a hyperlink, unless it's a reserved word in this
# language.
# Parameters:
# $code - reference to the code to markup
# @itag - ???
# TODO : Make the handling of identifier recognition language dependant
sub processcode {
my ($self, $code) = @_;
my ($start, $id);
$$code =~ s {(^|[^\w\#])([\w~][\w]*)\b}
# Replace identifier by link unless it's a reserved word
{
$1.
((!grep(/$2/, $self->langinfo('reserved')) &&
$index->issymbol($2, $$self{'release'})) ?
join($2, @{$$self{'itag'}}) :
$2);
}ge;
}
#
# Find references to symbols in the file
#
sub referencefile {
my ($self, $name, $path, $fileid, $index, $config) = @_;
require LXR::SimpleParse;
# Use dummy tabwidth here since it doesn't matter for referencing
&LXR::SimpleParse::init(new FileHandle($path), 1, $self->parsespec);
my $linenum = 1;
my ($btype, $frag) = &LXR::SimpleParse::nextfrag;
my @lines;
my $ls;
while (defined($frag)) {
@lines = ($frag =~ /(.*?\n)/g, $frag =~ /([^\n]*)$/);
if (defined($btype)) {
if ($btype eq 'comment' or $btype eq 'string' or $btype eq 'include') {
$linenum += @lines - 1;
} else {
print "BTYPE was: $btype\n";
}
} else {
my $l;
my $string;
foreach $l (@lines) {
foreach ($l =~ /(?:^|[^a-zA-Z_\#]) # Non-symbol chars.
(\~?_*[a-zA-Z][a-zA-Z0-9_]*) # The symbol.
\b/ogx) {
$string = $_;
# print "considering $string\n";
if (!grep(/$string/, $self->langinfo('reserved')) &&
$index->issymbol($string)) {
# print "adding $string to references\n";
$index->reference($string, $fileid, $linenum);
}
}
$linenum++;
}
$linenum--;
}
($btype, $frag) = &LXR::SimpleParse::nextfrag;
}
print("+++ $linenum\n");
}
# Autoload magic to allow access using $generic->variable syntax
# blatently ripped from Config.pm - I still don't fully understand how
# this works.
sub variable {
my ($self, $var, $val) = @_;
$self->{variables}{$var}{value} = $val if defined($val);
return $self->{variables}{$var}{value} ||
$self->vardefault($var);
}
sub varexpand {
my ($self, $exp) = @_;
$exp =~ s/\$\{?(\w+)\}?/$self->variable($1)/ge;
return $exp;
}
sub value {
my ($self, $var) = @_;
if (exists($self->{$var})) {
my $val = $self->{$var};
if (ref($val) eq 'ARRAY') {
return map { $self->varexpand($_) } @$val;
} elsif (ref($val) eq 'CODE') {
return $val;
} else {
return $self->varexpand($val);
}
} else {
return undef;
}
}
sub AUTOLOAD {
my $self = shift;
(my $var = $AUTOLOAD) =~ s/.*:://;
my @val = $self->value($var);
if (ref($val[0]) eq 'CODE') {
return $val[0]->(@_);
} else {
return wantarray ? @val : $val[0];
}
}
sub langinfo {
my ($self, $item) = @_;
my $val;
my $map = $self->langmap;
die if !defined $map;
if (exists $$map{$self->language}) {
$val = $$map{$self->language};
} else {
return undef;
}
if (defined $val && defined $$val{$item}) {
if (ref($$val{$item}) eq 'ARRAY') {
return wantarray ? @{$$val{$item}} : $$val{$item};
}
return $$val{$item};
} else {
return undef;
}
}
1;

View File

@@ -0,0 +1,71 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Java.pm,v 1.4 2001/11/14 15:27:36 mbox Exp $
#
# Enhances the support for the Java language over that provided by
# Generic.pm
#
# 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 LXR::Lang::Java;
my $CVSID = '$Id: Java.pm,v 1.4 2001/11/14 15:27:36 mbox Exp $ ';
use strict;
use LXR::Common;
require LXR::Lang;
require LXR::Lang::Generic;
@LXR::Lang::Java::ISA = ('LXR::Lang::Generic');
# Only override the include handling. For java, this is really package
# handling, as there is no include mechanism, so deals with "package"
# and "import" keywords
sub processinclude {
my ($self, $frag, $dir) = @_;
# Deal with package declaration of the form
# "package java.lang.util"
$$frag =~ s#(package\s+)([\w.]+)#
$1.
($index->issymbol($2, $$self{'release'}) ?
join($2, @{$$self{'itag'}}) : $2)
#e;
# Deal with import declaration of the form
# "import java.awt.*" by providing link to the package
$$frag =~ s#(import\s+)([\w.]+)(\.\*)#
$1.
($index->issymbol($2, $$self{'release'}) ?
join($2, @{$$self{'itag'}}) : $2) .
$3 #e;
# Deal with import declaration of the form
# "import java.awt.classname" by providing links to the
# package and the class
$$frag =~ s#(import\s+)([\w.]+)\.(\w+)(\W)#
$1.
($index->issymbol($2, $$self{'release'}) ?
join($2, @{$$self{'itag'}}) : $2) . "." .
($index->issymbol($3, $$self{'release'}) ?
join($3, @{$$self{'itag'}}) : $3) . $4#e;
}
1;

View File

@@ -0,0 +1,153 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Perl.pm,v 1.5 2002/03/18 14:55:43 mbox Exp $
# 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 LXR::Lang::Perl;
$CVSID = '$Id: Perl.pm,v 1.5 2002/03/18 14:55:43 mbox Exp $ ';
=head1 LXR::Lang::Perl
Da Perl package, man!
=cut
use strict;
use LXR::Common;
use LXR::Lang;
use vars qw(@ISA);
@ISA = ('LXR::Lang');
my @spec = (
'atom' => ('\$\W?', ''),
'atom' => ('\\\\.', ''),
'include' => ('\buse\s+', ';'),
'include' => ('\brequire\s+', ';'),
'string' => ('"', '"'),
'comment' => ('#', "\$"),
'comment' => ("^=\\w+", "^=cut"),
'string' => ("'", "'"));
sub new {
my ($self, $pathname, $release) = @_;
$self = bless({}, $self);
$$self{'release'} = $release;
return $self;
}
sub parsespec {
return @spec;
}
sub processcode {
my ($self, $code, @itag) = @_;
my $sym;
# $$code =~ s#([\@\$\%\&\*])([a-z0-9_]+)|\b([a-z0-9_]+)(\s*\()#
# $sym = $2 || $3;
# $1.($index->issymbol($sym, $$self{'release'})
# ? join($sym, @{$$self{'itag'}})
# : $sym).$4#geis;
$$code =~ s#\b([a-z][a-z0-9_:]*)\b#
($index->issymbol($1, $$self{'release'})
? join($1, @{$$self{'itag'}})
: $1)#geis;
}
sub modref {
my $mod = shift;
my $file = $mod;
$file =~ s,::,/,g;
$file .= ".pm";
return &LXR::Common::incref($mod, "include", $file);
}
sub processinclude {
my ($self, $frag, $dir) = @_;
$$frag =~ s/(use\s+|require\s+)([\w:]+)/$1.modref($2)/e;
}
sub processcomment {
my ($self, $comm) = @_;
if ($$comm =~ /^=/s) {
# Pod text
$$comm = join('', map {
if (/^=head(\d)\s*(.*)/s) {
"<span class=\"pod\"><font size=\"+".(4-$1)."\">$2<\/font></span>";
}
elsif (/^=item\s*(.*)/s) {
"<span class=\"podhead\">* $1 ".
("-" x (67 - length($1)))."<\/span>";
}
elsif (/^=(pod|cut)/s) {
"<span class=\"podhead\">".
("-" x 70)."<\/span>";
}
elsif (/^=.*/s) {
"";
}
else {
if (/^\s/s) { # Verbatim paragraph
s|^(.*)$|<span class="pod"><code>$1</code></span>|gm;
}
else { # Normal paragraph
s|^(.*)$|<span class="pod">$1</span>|gm;
s/C\0\<(.*?)\0\>/<code>$1<\/code>/g;
}
$_;
}
} split(/((?:\n[ \t]*)*\n)/, $$comm));
}
else {
$$comm =~ s|^(.*)$|<span class='comment'>$1</span>|gm;
}
}
sub indexfile {
my ($self, $name, $path, $fileid, $index, $config) = @_;
open(PLTAG, $path);
while (<PLTAG>) {
if (/^sub\s+(\w+)/) {
print(STDERR "Sub: $1\n");
$index->index($1, $fileid, $., 'f');
}
elsif (/^package\s+([\w:]+)/) {
print(STDERR "Class: $1\n");
$index->index($1, $fileid, $., 'c');
}
elsif (/^=item\s+[\@\$\%\&\*]?(\w+)/) {
print(STDERR "Doc: $1\n");
$index->index($1, $fileid, $., 'i');
}
}
close(PLTAG);
}

View File

@@ -0,0 +1,100 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Python.pm,v 1.2 2001/08/15 15:50:27 mbox Exp $
# 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 LXR::Lang::Python;
$CVSID = '$Id: Python.pm,v 1.2 2001/08/15 15:50:27 mbox Exp $ ';
use strict;
use LXR::Common;
use LXR::Lang;
use vars qw(@ISA);
@ISA = ('LXR::Lang');
my @spec = ('comment' => ('#', "\$"),
'string' => ('"', '"'),
'string' => ("'", "'"),
'atom' => ('\\\\.', ''));
sub new {
my ($self, $pathname, $release) = @_;
$self = bless({}, $self);
$$self{'release'} = $release;
if ($pathname =~ /(\w+)\.py$/ || $pathname =~ /(\w+)$/) {
$$self{'modulename'} = $1;
}
return $self;
}
sub parsespec {
return @spec;
}
sub processcode {
my ($self, $code, @itag) = @_;
$$code =~ s/([a-zA-Z_][a-zA-Z0-9_\.]*)/
($index->issymbol( $$self{'modulename'}.".".$1, $$self{'release'} )
? join('',
$$self{'itag'}[0],
$$self{'modulename'}.".".$1,
$$self{'itag'}[1],
$1,
$$self{'itag'}[2])
: $1)/ge;
}
sub indexfile {
my ($self, $name, $path, $fileid, $index, $config) = @_;
my (@ptag_lines, @single_ptag, $module_name);
if ($name =~ m|/(\w+)\.py$|) {
$module_name = $1;
}
open(PYTAG, $path);
while (<PYTAG>) {
chomp;
# Function definitions
if ( $_ =~ /^\s*def\s+([^\(]+)/ ) {
$index->index($module_name."\.$1", $fileid, $., "f");
}
# Class definitions
elsif ( $_ =~ /^\s*class\s+([^\(:]+)/ ) {
$index->index($module_name."\.$1", $fileid, $., "c");
}
# Targets that are identifiers if occurring in an assignment..
elsif ( $_ =~ /^(\w+) *=.*/ ) {
$index->index($module_name."\.$1", $fileid, $., "v");
}
# ..for loop header.
elsif ( $_ =~ /^for\s+(\w+)\s+in.*/ ) {
$index->index($module_name."\.$1", $fileid, $., "v");
}
}
close(PYTAG);
}

View File

@@ -0,0 +1,245 @@
# -*- mode: perl; tab-width: 2 -*-
# Configure options for the generic language support
{
# Options to always feed to ectags
'ectagsopts' => ["--c-types=+px", "--eiffel-types=+l",
"--fortran-types=+L",],
# How to map a language name to the ectags language-force name
# if there is no mapping, then the language name is used
'eclangnamemapping' => {'C' => 'c',
'C++' => 'c++',
'Python' => 'python',
},
# lang map specifies info for each language
# what the reserved words & comment chars are
'langmap' => {
'C' => {
'reserved' => [
'auto', 'break', 'case', 'char', 'const',
'continue', 'default', 'do', 'double',
'else', 'enum', 'extern', 'float', 'for',
'goto', 'if', 'int', 'long', 'register',
'return', 'short', 'signed', 'sizeof',
'static', 'struct', 'switch', 'typedef',
'union', 'unsigned', 'void', 'volatile',
'while',
],
'spec' => ['atom', '\\\\.', '',
'comment', '/\*', '\*/',
'comment', '//', "\$",
'string', '"', '"',
'string', "'", "'",
'include', '#\s*include', "\$"],
'typemap' => {
'c' => 'class',
'd' => 'macro (un)definition',
'e' => 'enumerator',
'f' => 'function definition',
'g' => 'enumeration name',
'm' => 'class, struct, or union member',
'n' => 'namespace',
'p' => 'function prototype or declaration',
's' => 'structure name',
't' => 'typedef',
'u' => 'union name',
'v' => 'variable definition',
'x' => 'extern or forward variable declaration',
'i' => 'interface'},
'langid' => '1',
},
'C++' => {
'reserved' => ['and', 'and_eq', 'asm', 'auto', 'bitand',
'bitor', 'bool', 'break', 'case', 'catch',
'char', 'class', 'const', 'const_cast',
'continue', 'default', 'delete', 'do',
'double', 'dynamic_cast', 'else', 'enum',
'explicit', 'export', 'extern', 'false',
'float', 'for', 'friend', 'goto', 'if',
'inline', 'int', 'long', 'mutable',
'namespace', 'new', 'not', 'not_eq',
'operator', 'or', 'or_eq', 'private',
'protected', 'public', 'register',
'reinterpret_cast', 'return', 'short',
'signed', 'sizeof', 'static',
'static_cast','struct', 'switch',
'template','this', 'throw', 'true','try',
'typedef', 'typeid','typename',
'union', 'unsigned','using',
'virtual', 'void','volatile',
'wchar_t', 'while','xor',
'xor_eq'],
'spec' => ['atom', '\\\\.', '',
'comment', '/\*', '\*/',
'comment', '//', "\$",
'string', '"', '"',
'string', "'", "'",
'include', '#\s*include', "\$"],
'typemap' => {
'c' => 'class',
'd' => 'macro (un)definition',
'e' => 'enumerator',
'f' => 'function definition',
'g' => 'enumeration name',
'm' => 'class, struct, or union member',
'n' => 'namespace',
'p' => 'function prototype or declaration',
's' => 'structure name',
't' => 'typedef',
'u' => 'union name',
'v' => 'variable definition',
'x' => 'extern or forward variable declaration',
'i' => 'interface'},
'langid' => '2',
},
'Java' => {
'reserved' => ['break', 'case', 'continue', 'default',
'do', 'else', 'for', 'goto', 'if',
'return', 'static', 'switch', 'void',
'volatile', 'while', 'public', 'class',
'final', 'private', 'protected',
'synchronized', 'package', 'import',
'boolean', 'byte', 'new', 'abstract',
'extends', 'implements', 'interface',
'throws', 'instanceof', 'super', 'this',
'native', 'null'],
'spec' => ['atom' => ('\\\\.', ''),
'comment' => ('/\*', '\*/'),
'comment' => ('//', "\$"),
'string' => ('"', '"'),
'string' => ("'", "'"),
'include' => ('import', "\$"),
'include' => ('package', "\$"),
],
'typemap' => {
'c' => 'class',
'f' => 'field',
'i' => 'interface',
'm' => 'method',
'p' => 'package',
},
'langid' => '3',
},
'Fortran' => {
'reserved' => [],
'typemap' => {
'b' => 'block data',
'c' => 'common block',
'e' => 'entry point',
'f' => 'function',
'i' => 'interface',
'k' => 'type component',
'l' => 'label',
'L' => 'local and common block variable',
'm' => 'module',
'n' => 'namelist',
'p' => 'program',
},
'langid' => '4',
},
'Pascal' => {
'reserved' => [],
'langid' => '5',
},
'COBOL' => {
'reserved' => [],
'langid' => '6',
},
'Perl' => {
'reserved' => [
'sub',
],
'spec' => ['atom' => ('\$\W?', ''),
'atom' => ('\\\\.', ''),
'include' => ('\buse\s+', ';'),
'include' => ('\brequire\s+', ';'),
'string' => ('"', '"'),
'comment' => ('#', "\$"),
'comment' => ("^=\\w+", "^=cut"),
'string' => ("'", "'")],
'typemap' => {
's' => 'subroutine',
'p' => 'package',
},
'langid' => '7',
},
'Python' => {
'reserved' => ['def','print','del','pass',
'break','continue','return',
'raise','import','from',
'global','exec','assert',
'if','elif','else','while',
'for','try','except','finally',
'class','as','import','or',
'and','is','in','for','if',
'not','lambda','self',
],
'spec' => ['comment' => ('#', "\$"),
'string' => ('"', '"'),
'string' => ("'", "'"),
'atom' => ('\\\\.', '')],
'typemap' => {
'c' => 'class',
'f' => 'function',
},
'langid' => '8',
},
'php' => {
'reserved' => ['and','$argv','$argc','break','case','class',
'continue','default','do','die','echo','else',
'elseif','empty','endfor','endforeach','endif',
'endswitch','endwhile','E_ALL','E_PARSE','E_ERROR',
'E_WARNING','exit','extends','FALSE','for','foreach',
'function','HTTP_COOKIE_VARS','HTTP_GET_VARS',
'HTTP_POST_VARS','HTTP_POST_FILES','HTTP_ENV_VARS',
'HTTP_SERVER_VARS','if','global','list','new','not',
'NULL','or','parent','PHP_OS','PHP_SELF','PHP_VERSION',
'print','return','static','switch','stdClass',
'this','TRUE','var','xor','virtual','while','__FILE__',
'__LINE__','__sleep','__wakeup',
],
'spec' => ['comment', '/\*', '\*/',
'comment', '//', "\$",
'comment', '#', "\$",
'string', '"', '"',
'string', "'", "'",
'include', 'require', "\$",
'include', 'include', "\$",
'include', 'require_once', "\$",
'include', 'include_once', "\$"
],
'typemap' => {
'c' => 'class',
'f' => 'function',
},
'langid' => '9',
},
'Make' => {
'reserved' => {},
'spec' => ['comment' => ('#', "\$"),
'string' => ('"', '"'),
'string' => ("'", "'"),
'include' => ('^ *-?include', '\$')],
'typemap' => {
'm' => 'macro',
},
'langid' => '10',
},
}
}

View File

@@ -0,0 +1,169 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: SimpleParse.pm,v 1.14 2001/11/14 15:03:29 mbox Exp $
# 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 LXR::SimpleParse;
$CVSID = '$Id: SimpleParse.pm,v 1.14 2001/11/14 15:03:29 mbox Exp $ ';
use strict;
use integer;
require Exporter;
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(&doparse &untabify &init &nextfrag);
my $fileh; # File handle
my @frags; # Fragments in queue
my @bodyid; # Array of body type ids
my @open; # Fragment opening delimiters
my @term; # Fragment closing delimiters
my $split; # Fragmentation regexp
my $open; # Fragment opening regexp
my $tabwidth; # Tab width
sub init {
my @blksep;
$fileh = "";
@frags = ();
@bodyid = ();
@open = ();
@term = ();
$split = "";
$open = "";
$tabwidth = 8;
my $tabhint;
($fileh, $tabhint, @blksep) = @_;
$tabwidth = $tabhint || $tabwidth;
while (@_ = splice(@blksep,0,3)) {
push(@bodyid, $_[0]);
push(@open, $_[1]);
push(@term, $_[2]);
}
foreach (@open) {
$open .= "($_)|";
$split .= "$_|";
}
chop($open);
foreach (@term) {
next if $_ eq '';
$split .= "$_|";
}
chop($split);
}
sub untabify {
my $t = $_[1] || 8;
$_[0] =~ s/^(\t+)/(' ' x ($t * length($1)))/ge; # Optimize for common case.
$_[0] =~ s/([^\t]*)\t/$1.(' ' x ($t - (length($1) % $t)))/ge;
return($_[0]);
}
sub nextfrag {
my $btype = undef;
my $frag = undef;
my $line = '';
# print "nextfrag called\n";
while (1) {
# read one more line if we have processed
# all of the previously read line
if ($#frags < 0) {
$line = $fileh->getline;
if ($. <= 2 &&
$line =~ /^.*-[*]-.*?[ \t;]tab-width:[ \t]*([0-9]+).*-[*]-/) {
$tabwidth = $1;
}
# &untabify($line, $tabwidth); # We inline this for performance.
# Optimize for common case.
if(defined($line)) {
$line =~ s/^(\t+)/' ' x ($tabwidth * length($1))/ge;
$line =~ s/([^\t]*)\t/$1.(' ' x ($tabwidth - (length($1) % $tabwidth)))/ge;
# split the line into fragments
@frags = split(/($split)/, $line);
}
}
last if $#frags < 0;
# skip empty fragments
if ($frags[0] eq '') {
shift(@frags);
}
# check if we are inside a fragment
if (defined($frag)) {
if (defined($btype)) {
my $next = shift(@frags);
# Add to the fragment
$frag .= $next;
# We are done if this was the terminator
last if $next =~ /^$term[$btype]$/;
}
else {
if ($frags[0] =~ /^$open$/) {
# print "encountered open token while btype was $btype\n";
last;
}
$frag .= shift(@frags);
}
}
else {
# print "start of new fragment\n";
# Find the blocktype of the current block
$frag = shift(@frags);
if (defined($frag) && (@_ = $frag =~ /^$open$/)) {
# print "hit\n";
# grep in a scalar context returns the number of times
# EXPR evaluates to true, which is this case will be
# the index of the first defined element in @_.
my $i = 1;
$btype = grep { $i &&= !defined($_) } @_;
if(!defined($term[$btype])) {
print "fragment without terminator\n";
last;
}
}
}
}
$btype = $bodyid[$btype] if defined($btype);
return($btype, $frag);
}
1;

View File

@@ -0,0 +1,95 @@
# -*- tab-width: 4 -*- ###############################################
#
# $Id: Tagger.pm,v 1.19 2001/10/23 14:30:18 mbox Exp $
# 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 LXR::Tagger;
$CVSID = '$Id: Tagger.pm,v 1.19 2001/10/23 14:30:18 mbox Exp $ ';
use strict;
use FileHandle;
use LXR::Lang;
sub processfile {
my ($pathname, $release, $config, $files, $index) = @_;
my $lang = new LXR::Lang($pathname, $release);
return unless $lang;
my $revision = $files->filerev($pathname, $release);
return unless $revision;
print(STDERR "--- $pathname $release $revision\n");
if ($index) {
my $fileid = $index->fileid($pathname, $revision);
$index->release($fileid, $release);
if ($index->toindex($fileid)) {
$index->empty_cache();
print(STDERR "--- $pathname $fileid\n");
my $path = $files->tmpfile($pathname, $release);
$lang->indexfile($pathname, $path, $fileid, $index, $config);
unlink($path);
} else {
print(STDERR "$pathname was already indexed\n");
}
} else { print(STDERR " **** FAILED ****\n"); }
$lang = undef;
$revision = undef;
}
sub processrefs {
my ($pathname, $release, $config, $files, $index) = @_;
my $lang = new LXR::Lang($pathname, $release);
return unless $lang;
my $revision = $files->filerev($pathname, $release);
return unless $revision;
print(STDERR "--- $pathname $release $revision\n");
if ($index) {
my $fileid = $index->fileid($pathname, $revision);
if ($index->toreference($fileid)) {
$index->empty_cache();
print(STDERR "--- $pathname $fileid\n");
my $path = $files->tmpfile($pathname, $release);
$lang->referencefile($pathname, $path, $fileid, $index, $config);
unlink($path);
} else {
print STDERR "$pathname was already referenced\n";
}
} else { print( STDERR " **** FAILED ****\n"); }
$lang = undef;
$revision = undef;
}
1;

View File

@@ -0,0 +1,30 @@
descexpand moved to local
source merging with mozilla done
test include file handing
Some documentation:
Template directives
In headers
'title', \&titleexpand
'banner',
'baseurl', \&baseurl
'dotdoturl', \&dotdoturl
'thisurl', \&thisurl
'pathname', \&pathname
'modes', \&modeexpand
'variables', \&varexpand
In footers:
'banner', \&bannerexpand
'thisurl', \&thisurl
'modes', \&modeexpand
'variables', \&varexpand
With caching and clearing cache, still memory leaks:
237.25user 108.06system 1:29:30elapsed 6%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (2188638major+1157837minor)pagefaults 0swaps

View File

@@ -0,0 +1,180 @@
#!/usr/bin/perl
# $Id: search,v 1.11 2002/07/29 01:17:32 mbox Exp $
# search -- Freetext search
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
######################################################################
$CVSID = '$Id: search,v 1.11 2002/07/29 01:17:32 mbox Exp $ ';
use strict;
use lib do { $0 =~ m{(.*)/} ? "$1/lib" : "lib" };
use LXR::Common qw(:html);
use LXR::Config;
my $maxhits = 1000;
sub glimpsesearch {
my ($searchtext) = @_;
unless (open(GLIMPSE, "-|")) {
open(STDERR, ">&STDOUT");
$!='';
exec($config->glimpsebin,"-i","-H".$config->glimpsedir."/".$release,'-y','-n',$searchtext);
print("Glimpse subprocess died unexpextedly: $!\n");
exit;
}
my $numlines = 0;
my @glimpselines = ();
while (<GLIMPSE>) {
$numlines++;
push(@glimpselines,$_);
if ($numlines > $maxhits) {
last;
}
}
close(GLIMPSE);
my $retval = $? >> 8;
# The manpage for glimpse says that it returns 2 on syntax errors or
# inaccessible files. It seems this is not the case.
# We will have to work around it for the time being.
if ($retval == 0) {
if (@glimpselines == 0) {
print("No matching files<br>\n");
} else {
if ($numlines > $maxhits) {
print("<b> Too many hits, displaying first $maxhits</b><br>\n");
}
print("<h1>$searchtext</h1>\n");
my $sourceroot = $config->sourceroot;
foreach my $glimpseline (@glimpselines) {
$glimpseline =~ s/$sourceroot//;
my ($file, $line, $text) =
$glimpseline =~ /(.*?):\s*(\d+)\s*:(.*)/;
$text =~ s/&/&amp;/g;
$text =~ s/</&lt;/g;
$text =~ s/>/&gt;/g;
print(&fileref("$file, line $line", "find-file",
"/$file", $line),
" -- $text<br>\n");
}
}
} elsif ($retval == 1) {
my $glimpsebin = $config->glimpsebin;
my $glimpseresponse = join("<br>",@glimpselines);
my $glimpseresponse =~ s/$glimpsebin/Reason/;
my $glimpseresponse =~ s/glimpse: error in searching index//;
print("<b>Search failed</b><br>\n$glimpseresponse");
} else {
print("Unexpected returnvalue $retval from Glimpse\n");
}
}
sub swishsearch {
my ($searchtext) = @_;
unless (open(SWISH, "-|")) {
open(STDERR, ">&STDOUT");
exec($config->swishsearch,
"-f", $config->swishdir."/".$release.".index",
"-m", $maxhits, "-w", $searchtext);
print(STDERR "Couldn't exec ".$config->swishsearch.": $!\n");
kill(9, $$);
}
my @result = grep { not /^[\#\.]/ } <SWISH>;
close(SWISH);
my $retval = $? >> 8;
if ($retval == 0) {
if (@result == 0) {
print("No matching files<br>\n");
} else {
if (@result == $maxhits) {
print("<b> Too many hits, displaying first $maxhits</b><br>\n");
}
print("<h1>$searchtext</h1>\n");
foreach my $hit (@result) {
my ($score, $file) =
$hit =~ /^(\d+) \/(\S+) \S+ \d+/;
print("$score ", &fileref("$file", "find-file", "/$file"), "<br>\n");
}
}
}
else {
print("<b>Search failed</b><br>\n@result");
}
}
sub search {
print("<p align=\"center\">\n",
"<form method=\"get\" action=\"search\">\n");
foreach ($config->allvariables) {
if ($config->variable($_) ne $config->vardefault($_)) {
print("<input type=\"hidden\" name=\"",$_, "\" ",
"value=\"", $config->variable($_), "\">\n");
}
}
my $searchtext = $HTTP->{'param'}->{'string'};
print("<b>Search for: </b><input type=\"text\" name=\"string\" ",
"value=\"",$searchtext,"\" size=\"50\">\n",
"<input type=\"submit\" value=\"search\">\n",
"</form>\n");
$| = 1; print('');
if ($searchtext ne "") {
print("<hr>\n");
if ($config->glimpsebin) {
glimpsesearch($searchtext);
}
elsif ($config->swishsearch and $config->swishdir) {
swishsearch($searchtext);
}
}
}
httpinit;
&makeheader('search');
&search;
&makefooter('search');
httpclean;

View File

@@ -0,0 +1,294 @@
#!/usr/bin/perl
# $Id: source,v 1.32 2002/07/29 01:23:03 mbox Exp $
# source -- Present sourcecode as html, complete with references
#
# Arne Georg Gleditsch <argggh@ifi.uio.no>
# Per Kristian Gjermshus <pergj@ifi.uio.no>
#
#
# 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.
######################################################################
$CVSID = '$Id: source,v 1.32 2002/07/29 01:23:03 mbox Exp $ ';
use strict;
use lib do { $0 =~ m{(.*)/} ? "$1/lib" : "lib" };
use LXR::Common qw(:html);
use Local;
sub diricon {
my ($templ, $node, $dir) = @_;
my $img;
if ($node eq '../') {
$img = "/icons/back.gif";
} else {
# $img = "/icons/folder.gif";
$img = "internal-gopher-menu";
}
return fileref("<img align=\"bottom\" border=\"0\" src=\"$img\" alt=\"folder\">", "",
$dir.$node);
}
sub dirname {
my ($templ, $node, $dir) = @_;
if ($node eq '../') {
return fileref("Parent directory", "dirfolder", $dir.$node);
} else {
return fileref($node, "dirfolder", $dir.$node);
}
}
sub fileicon {
my ($templ, $node, $dir) = @_;
my $img;
if ($node =~ /^.*\.[ch]$/) {
# $img = "/icons/c.gif";
$img = "internal-gopher-text";
} elsif ($node =~ /^.*\.(cpp|cc|java)$/) {
# TODO: Find a nice icon for c++ files (KDE?)
# $img = "/icons/c.gif";
$img = "internal-gopher-text";
} else {
# $img = "/icons/text.gif";
$img = "internal-gopher-unknown";
}
return fileref("<img align=\"bottom\" border=\"0\" src=\"$img\" alt=\"\">",
"", $dir.$node);
}
sub filename {
my ($templ, $node, $dir) = @_;
return fileref($node, "dirfile", $dir.$node);
}
sub filesize {
my ($templ, $node, $dir) = @_;
my $s = $files->getfilesize($dir.$node, $release);
my $str;
if ($s < 1<<10) {
$str = "$s";
} else {
# if ($s < 1<<20) {
$str = ($s>>10) . "k";
# } else {
# $str = ($s>>20) . "M";
# }
}
return expandtemplate($templ,
('bytes' => sub { return $str },
'kbytes' => sub { return $str },
'mbytes' => sub { return $str }));
}
sub modtime {
my ($templ, $node, $dir) = @_;
my $current_time = time;
my $file_time = $files->getfiletime($dir.$node, $release);
return '-' unless defined($file_time);
my @t = gmtime($file_time);
my ($sec, $min, $hour, $mday, $mon, $year) = @t;
return sprintf("%04d-%02d-%02d %02d:%02d:%02d",
$year + 1900,
$mon + 1, $mday, $hour, $min, $sec);
}
sub bgcolor {
my ($templ, $line) = @_;
return ((($line - 1) / 3) % 2) ? "#FFFFFF" : "#EEEEEE";
}
sub rowclass {
my ($templ, $line) = @_;
return ((($line - 1) / 3) % 2) ? "dirrow2" : "dirrow1";
}
sub direxpand {
my ($templ, $dir) = @_;
my $direx = '';
my $line = 1;
my %index;
my @nodes;
my $node;
@nodes = $files->getdir($dir, $release);
unless (@nodes) {
print("<p align=\"center\">\n<i>The directory ".
$files->toreal($dir, $release).
" does not exist.</i>\n");
#FIXME what does this do?
if ($files->toreal($dir, $release) =~ m#(.+[^/])[/]*$# ) {
if (-e $1) {
warning("Unable to open ".
$files->toreal($dir, $release));
}
}
return;
}
%index = $files->getindex($dir, $release);
unshift(@nodes, '../') unless $dir eq '/';
#CSS checked _PH_
foreach $node (@nodes) {
if ($node =~ /\/$/) {
$direx .= expandtemplate
($templ,
('iconlink' => sub { diricon(@_, $node, $dir) },
'namelink' => sub { dirname(@_, $node, $dir) },
'filesize' => sub { '-' },
'modtime' => sub { modtime(@_, $node, $dir) },
'bgcolor' => sub { bgcolor(@_, $line++) },
'css' => sub { rowclass(@_, $line++) },
'description' => sub { descexpand(@_, $node, $dir, \%index) }
));
}
else {
next if $node =~ /^.*\.[oa]$|^core$|^00-INDEX$/;
$direx .= expandtemplate
($templ,
('iconlink' => sub { fileicon(@_, $node, $dir) },
'namelink' => sub { filename(@_, $node, $dir) },
'filesize' => sub { filesize(@_, $node, $dir) },
'modtime' => sub { modtime(@_, $node, $dir) },
'bgcolor' => sub { bgcolor(@_, $line++) },
'css' => sub { rowclass(@_, $line++) },
'description' => sub { descexpand(@_, $node, $dir, \%index) }
));
}
}
return($direx);
}
sub printdir {
my $dir = shift;
my $templ;
$templ = "<ul>\n\$files{\n<li>\$iconlink \$namelink\n}</ul>\n";
if ($config->htmldir) {
unless (open(TEMPL, $config->htmldir)) {
warning("Template ".$config->htmldir." does not exist.");
} else {
local($/) = undef;
$templ = <TEMPL>;
close(TEMPL);
}
}
# print the description of the current directory
dirdesc($dir);
# print the listing itself
print(expandtemplate($templ,
('files' => sub { direxpand(@_, $dir) })));
}
sub printfile {
my $raw = shift;
if ($pathname =~ m|/$|) {
printdir($pathname);
}
else {
my $fileh = $files->getfilehandle($pathname, $release);
if ($fileh) {
if ($raw) {
print($fileh->getlines);
}
# elsif ($node =~ /README$/) {
# print("<pre>",
# markupstring($fileh, $node, $index), # FIXME
# "</pre>");
# }
else {
my @ann = $files->getannotations($pathname, $release);
if (@ann) {
my ($a, $b);
foreach $a (@ann) {
if ($a eq $b) {
$a = ' ' x 16;
next;
}
$b = $a;
$a .= ' ' x (6 - length($a)).
$files->getauthor($pathname, $a);
$a .= ' ' x (16 - length($a));
}
}
my $l;
my $outfun = sub {
$l = shift;
$l =~ s/(\n)/$1.shift(@ann)/ge;
print $l;
};
&$outfun("<pre class=\"file\">\n");
markupfile($fileh, $outfun);
&$outfun("</pre>\n");
}
}
else {
print("\<p align=\"center\">\n<i>The file $pathname does not exist.</i>\n");
if (-f $files->toreal($pathname, $release)) {
warning("Unable to open ".$files->toreal($pathname, $release));
}
}
}
}
httpinit;
if ($config->filter && $pathname !~ $config->filter) {
makeheader('source');
print("\<p align=\"center\">\n<i>The file $pathname does not exist.</i>\n");
makefooter('source');
exit;
}
# If the file is html then simply pump it out.
if ($pathname =~ /\.(html)$/ || $HTTP->{'param'}->{'raw'}) {
printfile(1);
}
else {
my $type = ($pathname !~ m|/$| ? 'source' : 'sourcedir');
makeheader($type);
printfile(0);
makefooter($type);
}
httpclean;

View File

@@ -0,0 +1,17 @@
<table border="0" cellspacing="0" width="100%">
<tr valign="middle">
<th class='dirheader' width="1%">&nbsp;</th>
<th class='dirheader' width="1%" nowrap="nowrap" align="left">Name</th>
<th class='dirheader' width="1%" nowrap="nowrap" align="right">Size</th>
<th class='dirheader' width="1%" nowrap="nowrap" align="left">Date (GMT)</th>
<th class='dirheader' width="96%" nowrap="nowrap" align="left">Description</th>
</tr>
$files{
<tr valign="middle" class="$css">
<td nowrap="nowrap">$iconlink</td>
<td nowrap="nowrap">$namelink</td>
<td nowrap="nowrap" align="right">$filesize{$bytes bytes} </td>
<td nowrap="nowrap" align="right">$modtime </td>
<td>$description{<i>$desctext</i>}</td>
</tr>}
</table>

View File

@@ -0,0 +1,53 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>$title</title>
<base href="$baseurl">
<link href="$stylesheet" rel="STYLESHEET" type="text/css">
</head>
<body>
<table width='100%' border='0' cellpadding='0' cellspacing='0'>
<tr>
<td rowspan='3'>
<img src="pengmini.gif"
alt="Penguin" border="0" width="67" height="92" align="middle">
</td>
<td>
<table width='100%' border='0' cellpadding='0' cellspacing='0'>
<tr>
<td align='center'>
<a href="blurb.html" class="main">The LXR Cross Referencer</a>
</td>
</tr>
<tr>
<td align="center">$banner</td>
</tr>
</table>
<td>
<td align='right'>
$modes{
[&nbsp;$modelink&nbsp;]<br>}
</td>
</tr>
<tr><td colspan='3'>&nbsp</td></tr>
<tr>
<td colspan='3'>
<table width="100%" border="0" cellpadding='0' cellspacing='0'>
$variables{
<tr>
<td align="left">
$varname:
</td>
<td align="right">
$varlinks{
[&nbsp;$varvalue&nbsp;]}
<br>
</td>
</tr>}
</table>
</td>
</tr>
</table>
<hr>

View File

@@ -0,0 +1,7 @@
<p>
<table>
<tr><td colspan='2'><b>References:</b></td></tr>
$uses{<tr>
<td width='30'> &nbsp; </td><td>$fileref</td>
</tr>}
</table>

View File

@@ -0,0 +1,31 @@
Type the full name of an identifier to summarize
(a function name, variable name, typedef, etc).
<p>
Matches are case-sensitive.
<form method="get" action="ident">
$variables
<b>Identifier: </b>
<input type="text" name="i" value='$identifier' size="15">
<input type="submit" value="Find">
</form>
<span class="search-ident">$identifier</span>
<p>
<table>
<tr><td colspan='2'><b>Declarations:</b></td></tr>
$refs{<tr>
<td>$fileref</td><td>$type</td><td>$rel</td>
</tr>}
</table>
<p>
<table>
<tr><td colspan='2'><b>References:</b></td></tr>
$uses{<tr>
<td width='30'> &nbsp; </td><td>$fileref</td>
</tr>}
</table>

View File

@@ -0,0 +1,43 @@
<div align="center">
This searchpage is powered by <a href="http://www.webglimpse.org/">Glimpse</a>
<form method="get" action="http:search">
$variables{<input type="hidden" name="$variable" value="$value">}
<table border="1" cellpadding="5" rules="none">
<tr>
<td colspan="3">
String to search for: <br>
<input type="text" name="string" value="$searchtext" size="60">
<input type="submit" value="Search">
</td>
</tr>
<tr border="0">
<td align="center">
$casecheck Case sensitive
</td>
<td align="center">
$regexpcheck Regular expression
</td>
<td align="center">
$errorselect
Misspellings allowed
</td>
</tr>
<tr>
<td colspan="3" align="center">
Maximum number of files returned:
$maxfilesselect
</td>
</tr>
<tr>
<td colspan="3" align="center">
Maximum number of matches per file returned:
$maxlinesselect
</td>
</tr>
</table>
</form>
<a href="http:search_help.html">Hints</a> making queries
</div>

View File

@@ -0,0 +1,35 @@
<hr>
<table width="100%" cellpadding="0" border="0">
<tr valign="middle">
$modes{
<td align="center" nowrap="nowrap">
[&nbsp;$modelink&nbsp;]</td>}
</tr>
</table>
<hr>
<table width="100%" cellpadding="0" border="0">
<tr>
<td align="left">
This page was automatically generated by the
<a href="http://lxr.sf.net/">LXR engine</a>.
<address>
<a href="mailto:lxr-general@lists.sf.net">
The LXR team</a>
</address>
</td>
<td align="right">
<a href="http://validator.w3.org/check/referer"><img border="0"
src="http://www.w3.org/Icons/valid-html401"
alt="Valid HTML 4.01!" height="31" width="88"></a>
</td>
</tr>
</table>
<hr>
<b>Loaded modules:</b>
<table>$devinfo{
<tr><td>$modpath</td><td>[ $modtime ]</td><td>$moduleid</td></tr>}
</table>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More