mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
401 lines
12 KiB
Plaintext
401 lines
12 KiB
Plaintext
|
#!/usr/bin/perl
|
||
|
|
||
|
=begin nd
|
||
|
|
||
|
Script: NaturalDocs
|
||
|
___________________________________________________________________________
|
||
|
|
||
|
Version 1.4
|
||
|
|
||
|
Copyright (C) 2003-2008 Greg Valure
|
||
|
|
||
|
http://www.naturaldocs.org
|
||
|
|
||
|
|
||
|
About: License
|
||
|
|
||
|
Licensed under the GNU General Public License
|
||
|
|
||
|
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, visit http://www.gnu.org/licenses/gpl.txt
|
||
|
or write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||
|
Boston, MA 02111-1307 USA.
|
||
|
|
||
|
|
||
|
Topic: Code Conventions
|
||
|
|
||
|
- Every package function is called with an arrow operator. It's needed for inheritance in some places, and consistency
|
||
|
when it's not.
|
||
|
|
||
|
- No constant will ever be zero or undef. Those are reserved so any piece of code can allow a "none of the above" option
|
||
|
and not worry about conflicts with an existing value.
|
||
|
|
||
|
- Existence hashes are hashes where the value doesn't matter. It acts more as a set, where the existence of the key is
|
||
|
the significant part.
|
||
|
|
||
|
|
||
|
Topic: File Format Conventions
|
||
|
|
||
|
- All integers appear in big-endian format. So a UInt16 should be handled with a 'n' in pack and unpack, not with a 'S'.
|
||
|
|
||
|
- AString16's are a big-endian UInt16 followed by that many ASCII characters. A null-terminator is not stored.
|
||
|
|
||
|
- If a higher-level type is described in a file format, that means the loading and saving format is handled by that package.
|
||
|
For example, if you see <SymbolString> in the format, that means <NaturalDocs::SymbolString->ToBinaryFile()> and
|
||
|
<NaturalDocs::SymbolString->FromBinaryFile()> are used to manipulate it, and the underlying format should be treated
|
||
|
as opaque.
|
||
|
|
||
|
=cut
|
||
|
|
||
|
|
||
|
use strict;
|
||
|
use integer;
|
||
|
|
||
|
use 5.005; # When File::Spec was included by default
|
||
|
|
||
|
use English '-no_match_vars';
|
||
|
|
||
|
use FindBin;
|
||
|
use lib "$FindBin::RealBin/Modules";
|
||
|
|
||
|
sub INIT
|
||
|
{
|
||
|
# This function is just here so that when I start the debugger, it doesn't open a new file. Normally it would jump to an INIT
|
||
|
# function in some other file since that's the first piece of code to execute.
|
||
|
};
|
||
|
|
||
|
|
||
|
use NaturalDocs::Constants;
|
||
|
use NaturalDocs::Version;
|
||
|
use NaturalDocs::File;
|
||
|
use NaturalDocs::Error;
|
||
|
|
||
|
use NaturalDocs::ConfigFile;
|
||
|
use NaturalDocs::BinaryFile;
|
||
|
use NaturalDocs::StatusMessage;
|
||
|
use NaturalDocs::SymbolString;
|
||
|
use NaturalDocs::ReferenceString;
|
||
|
use NaturalDocs::NDMarkup;
|
||
|
|
||
|
use NaturalDocs::Settings;
|
||
|
use NaturalDocs::Topics;
|
||
|
use NaturalDocs::Languages;
|
||
|
use NaturalDocs::Project;
|
||
|
use NaturalDocs::Menu;
|
||
|
use NaturalDocs::SymbolTable;
|
||
|
use NaturalDocs::ClassHierarchy;
|
||
|
use NaturalDocs::SourceDB;
|
||
|
use NaturalDocs::ImageReferenceTable;
|
||
|
use NaturalDocs::Parser;
|
||
|
use NaturalDocs::Builder;
|
||
|
|
||
|
|
||
|
|
||
|
###############################################################################
|
||
|
#
|
||
|
# Group: Basic Types
|
||
|
#
|
||
|
# Types used throughout the program. As Perl is a weakly-typed language unless you box things into objects, these types are
|
||
|
# for documentation purposes and are not enforced.
|
||
|
#
|
||
|
#
|
||
|
# Type: FileName
|
||
|
#
|
||
|
# A string representing the absolute, platform-dependent path to a file. Relative file paths are no longer in use anywhere in the
|
||
|
# program. All path manipulation should be done through <NaturalDocs::File>.
|
||
|
#
|
||
|
#
|
||
|
# Type: VersionInt
|
||
|
#
|
||
|
# A comparable integer representing a version number. Converting them to and from text and binary should be handled by
|
||
|
# <NaturalDocs::Version>.
|
||
|
#
|
||
|
#
|
||
|
# Type: SymbolString
|
||
|
#
|
||
|
# A scalar which encodes a normalized array of identifier strings representing a full or partially-resolved symbol. All symbols
|
||
|
# must be retrieved from plain text via <NaturalDocs::SymbolString->FromText()> so that the separation and normalization is
|
||
|
# always consistent. SymbolStrings are comparable via string compare functions and are sortable.
|
||
|
#
|
||
|
#
|
||
|
# Type: ReferenceString
|
||
|
#
|
||
|
# All the information about a reference that makes it unique encoded into a string. This includes the <SymbolString> of the
|
||
|
# reference, the scope <SymbolString> it appears in, the scope <SymbolStrings> it has access to via "using", and the
|
||
|
# <ReferenceType>. This is done because if any of those parameters change, it needs to be treated as a completely separate
|
||
|
# reference.
|
||
|
#
|
||
|
|
||
|
|
||
|
|
||
|
###############################################################################
|
||
|
# Group: Support Functions
|
||
|
# General functions that are used throughout the program, and that don't really fit anywhere else.
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: StringCompare
|
||
|
#
|
||
|
# Compares two strings so that the result is good for proper sorting. A proper sort orders the characters as
|
||
|
# follows:
|
||
|
#
|
||
|
# - End of string.
|
||
|
# - Whitespace. Line break-tab-space.
|
||
|
# - Symbols, which is anything not included in the other entries.
|
||
|
# - Numbers, 0-9.
|
||
|
# - Letters, case insensitive except to break ties.
|
||
|
#
|
||
|
# If you use cmp instead of this function, the result would go by ASCII/Unicode values which would place certain symbols
|
||
|
# between letters and numbers instead of having them all grouped together. Also, you would have to choose between case
|
||
|
# sensitivity or complete case insensitivity, in which ties are broken arbitrarily.
|
||
|
#
|
||
|
# Returns:
|
||
|
#
|
||
|
# Like cmp, it returns zero if A and B are equal, a positive value if A is greater than B, and a negative value if A is less than B.
|
||
|
#
|
||
|
sub StringCompare #(a, b)
|
||
|
{
|
||
|
my ($a, $b) = @_;
|
||
|
|
||
|
if (!defined $a)
|
||
|
{
|
||
|
if (!defined $b)
|
||
|
{ return 0; }
|
||
|
else
|
||
|
{ return -1; };
|
||
|
}
|
||
|
elsif (!defined $b)
|
||
|
{
|
||
|
return 1;
|
||
|
};
|
||
|
|
||
|
my $translatedA = lc($a);
|
||
|
my $translatedB = lc($b);
|
||
|
|
||
|
$translatedA =~ tr/\n\r\t 0-9a-z/\x01\x02\x03\x04\xDB-\xFE/;
|
||
|
$translatedB =~ tr/\n\r\t 0-9a-z/\x01\x02\x03\x04\xDB-\xFE/;
|
||
|
|
||
|
my $result = $translatedA cmp $translatedB;
|
||
|
|
||
|
if ($result == 0)
|
||
|
{
|
||
|
# Break the tie by comparing their case. Lowercase before uppercase.
|
||
|
|
||
|
# If statement just to keep everything theoretically kosher, even though in practice we don't need this.
|
||
|
if (ord('A') > ord('a'))
|
||
|
{ return ($a cmp $b); }
|
||
|
else
|
||
|
{ return ($b cmp $a); };
|
||
|
}
|
||
|
else
|
||
|
{ return $result; };
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: ShortenToMatchStrings
|
||
|
#
|
||
|
# Compares two arrayrefs and shortens the first array to only contain shared entries. Assumes all entries are strings.
|
||
|
#
|
||
|
# Parameters:
|
||
|
#
|
||
|
# sharedArrayRef - The arrayref that will be shortened to only contain common elements.
|
||
|
# compareArrayRef - The arrayref to match.
|
||
|
#
|
||
|
sub ShortenToMatchStrings #(sharedArrayRef, compareArrayRef)
|
||
|
{
|
||
|
my ($sharedArrayRef, $compareArrayRef) = @_;
|
||
|
|
||
|
my $index = 0;
|
||
|
|
||
|
while ($index < scalar @$sharedArrayRef && $index < scalar @$compareArrayRef &&
|
||
|
$sharedArrayRef->[$index] eq $compareArrayRef->[$index])
|
||
|
{ $index++; };
|
||
|
|
||
|
if ($index < scalar @$sharedArrayRef)
|
||
|
{ splice(@$sharedArrayRef, $index); };
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: XChomp
|
||
|
#
|
||
|
# A cross-platform chomp function. Regular chomp fails when parsing Windows-format line breaks on a Unix platform. It
|
||
|
# leaves the /r on, which screws everything up. This does not.
|
||
|
#
|
||
|
# Parameters:
|
||
|
#
|
||
|
# lineRef - A *reference* to the line to chomp.
|
||
|
#
|
||
|
sub XChomp #(lineRef)
|
||
|
{
|
||
|
my $lineRef = shift;
|
||
|
$$lineRef =~ s/[\n\r]+$//;
|
||
|
};
|
||
|
|
||
|
|
||
|
#
|
||
|
# Function: FindFirstSymbol
|
||
|
#
|
||
|
# Searches a string for a number of symbols to see which appears first.
|
||
|
#
|
||
|
# Parameters:
|
||
|
#
|
||
|
# string - The string to search.
|
||
|
# symbols - An arrayref of symbols to look for.
|
||
|
# index - The index to start at, if any.
|
||
|
#
|
||
|
# Returns:
|
||
|
#
|
||
|
# The array ( index, symbol ).
|
||
|
#
|
||
|
# index - The index the first symbol appears at, or -1 if none appear.
|
||
|
# symbol - The symbol that appeared, or undef if none.
|
||
|
#
|
||
|
sub FindFirstSymbol #(string, symbols, index)
|
||
|
{
|
||
|
my ($string, $symbols, $index) = @_;
|
||
|
|
||
|
if (!defined $index)
|
||
|
{ $index = 0; };
|
||
|
|
||
|
my $lowestIndex = -1;
|
||
|
my $lowestSymbol;
|
||
|
|
||
|
foreach my $symbol (@$symbols)
|
||
|
{
|
||
|
my $testIndex = index($string, $symbol, $index);
|
||
|
|
||
|
if ($testIndex != -1 && ($lowestIndex == -1 || $testIndex < $lowestIndex))
|
||
|
{
|
||
|
$lowestIndex = $testIndex;
|
||
|
$lowestSymbol = $symbol;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
return ($lowestIndex, $lowestSymbol);
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
###############################################################################
|
||
|
#
|
||
|
# Main Code
|
||
|
#
|
||
|
# The order in which functions are called here is critically important. Read the "Usage and Dependencies" sections of all the
|
||
|
# packages before even thinking about rearranging these.
|
||
|
#
|
||
|
|
||
|
|
||
|
eval {
|
||
|
|
||
|
# Check that our required packages are okay.
|
||
|
|
||
|
NaturalDocs::File->CheckCompatibility();
|
||
|
|
||
|
|
||
|
# Almost everything requires Settings to be initialized.
|
||
|
|
||
|
NaturalDocs::Settings->Load();
|
||
|
|
||
|
|
||
|
NaturalDocs::Project->LoadConfigFileInfo();
|
||
|
|
||
|
NaturalDocs::Topics->Load();
|
||
|
NaturalDocs::Languages->Load();
|
||
|
|
||
|
|
||
|
# Migrate from the old file names that were used prior to 1.14.
|
||
|
|
||
|
NaturalDocs::Project->MigrateOldFiles();
|
||
|
|
||
|
|
||
|
if (!NaturalDocs::Settings->IsQuiet())
|
||
|
{ print "Finding files and detecting changes...\n"; };
|
||
|
|
||
|
NaturalDocs::Project->LoadSourceFileInfo();
|
||
|
NaturalDocs::Project->LoadImageFileInfo();
|
||
|
|
||
|
# Register SourceDB extensions. Order is important.
|
||
|
NaturalDocs::ImageReferenceTable->Register();
|
||
|
|
||
|
NaturalDocs::SymbolTable->Load();
|
||
|
NaturalDocs::ClassHierarchy->Load();
|
||
|
NaturalDocs::SourceDB->Load();
|
||
|
|
||
|
NaturalDocs::SymbolTable->Purge();
|
||
|
NaturalDocs::ClassHierarchy->Purge();
|
||
|
NaturalDocs::SourceDB->PurgeDeletedSourceFiles();
|
||
|
|
||
|
|
||
|
# Parse any supported files that have changed.
|
||
|
|
||
|
my $filesToParse = NaturalDocs::Project->FilesToParse();
|
||
|
my $amount = scalar keys %$filesToParse;
|
||
|
|
||
|
if ($amount > 0)
|
||
|
{
|
||
|
NaturalDocs::StatusMessage->Start('Parsing ' . $amount . ' file' . ($amount > 1 ? 's' : '') . '...', $amount);
|
||
|
|
||
|
foreach my $file (keys %$filesToParse)
|
||
|
{
|
||
|
NaturalDocs::Parser->ParseForInformation($file);
|
||
|
NaturalDocs::StatusMessage->CompletedItem();
|
||
|
};
|
||
|
};
|
||
|
|
||
|
|
||
|
# The symbol table is now fully resolved, so we can reduce its memory footprint.
|
||
|
|
||
|
NaturalDocs::SymbolTable->PurgeResolvingInfo();
|
||
|
|
||
|
|
||
|
# Load and update the menu file. We need to do this after parsing so when it is updated, it will detect files where the
|
||
|
# default menu title has changed and files that have added or deleted Natural Docs content.
|
||
|
|
||
|
NaturalDocs::Menu->LoadAndUpdate();
|
||
|
|
||
|
|
||
|
# Build any files that need it. This needs to be run regardless of whether there are any files to build. It will handle its own
|
||
|
# output messages.
|
||
|
|
||
|
NaturalDocs::Builder->Run();
|
||
|
|
||
|
|
||
|
# Write the changes back to disk.
|
||
|
|
||
|
NaturalDocs::Menu->Save();
|
||
|
NaturalDocs::Project->SaveImageFileInfo();
|
||
|
NaturalDocs::Project->SaveSourceFileInfo();
|
||
|
NaturalDocs::SymbolTable->Save();
|
||
|
NaturalDocs::ClassHierarchy->Save();
|
||
|
NaturalDocs::SourceDB->Save();
|
||
|
NaturalDocs::Settings->Save();
|
||
|
NaturalDocs::Topics->Save();
|
||
|
NaturalDocs::Languages->Save();
|
||
|
|
||
|
# Must be done last.
|
||
|
NaturalDocs::Project->SaveConfigFileInfo();
|
||
|
|
||
|
if (!NaturalDocs::Settings->IsQuiet())
|
||
|
{ print "Done.\n"; };
|
||
|
|
||
|
};
|
||
|
|
||
|
if ($EVAL_ERROR) # Oops.
|
||
|
{
|
||
|
NaturalDocs::Error->HandleDeath();
|
||
|
};
|
||
|
|