Backed out changeset d7692aed054f

This commit is contained in:
Mitchell Field 2011-03-09 12:29:25 +11:00
parent 7580c06786
commit fc1808a1e6
9 changed files with 1349 additions and 483 deletions

View File

@ -117,12 +117,12 @@ $(DIST)/branding:
libs::
@if test -f "$(LOCALE_SRCDIR)/existing-profile-defaults.js"; then \
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
$(PERL) $(topsrcdir)/config/preprocessor.pl $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
$(LOCALE_SRCDIR)/existing-profile-defaults.js > $(FINAL_TARGET)/defaults/existing-profile-defaults.js; \
fi
install::
@if test -f "$(LOCALE_SRCDIR)/existing-profile-defaults.js"; then \
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
$(PERL) $(topsrcdir)/config/preprocessor.pl $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
$(LOCALE_SRCDIR)/existing-profile-defaults.js > $(DESTDIR)$(mozappdir)/defaults/existing-profile-defaults.js; \
fi

View File

@ -123,7 +123,7 @@ endif
ifdef WRAP_SYSTEM_INCLUDES
export::
if test ! -d system_wrappers; then mkdir system_wrappers; fi
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \
$(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) \
-DBUILD_STATIC_LIBS=$(BUILD_STATIC_LIBS) \
-DMOZ_TREE_CAIRO=$(MOZ_TREE_CAIRO) \
-DMOZ_TREE_PIXMAN=$(MOZ_TREE_PIXMAN) \

671
config/preprocessor.pl Normal file
View File

@ -0,0 +1,671 @@
#!/usr/bin/perl -w
# -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*-
#
# Preprocessor
# Version 1.1
#
# Copyright (c) 2002, 2003, 2004 by Ian Hickson
#
# 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
# Thanks to bryner and bsmedberg for suggestions.
# Thanks to jon rekai for a patch to not require File::Spec 0.8.
use strict;
# takes as arguments the files to process
# defaults to stdin
# output to stdout
my $stack = new stack;
my $marker = '#';
# command line arguments
my @includes;
while ($_ = $ARGV[0], defined($_) && /^-./) {
shift;
last if /^--$/os;
if (/^-D(.*)$/os) {
for ($1) {
if (/^([\w\.]+)=(.*)$/os) {
$stack->define($1, $2);
} elsif (/^([\w\.]+)$/os) {
$stack->define($1, 1);
} else {
die "$0: invalid argument to -D: $_\n";
}
}
} elsif (/^-F(.*)$/os) {
for ($1) {
if (/^(\w+)$/os) {
$stack->filter($1, 1);
} else {
die "$0: invalid argument to -F: $_\n";
}
}
} elsif (/^-I(.*)$/os) {
push(@includes, $1);
} elsif (/^-E$/os) {
foreach (keys %ENV) {
# define all variables that have valid names
$stack->define($_, $ENV{$_}) unless m/\W/;
}
} elsif (/^-d$/os) {
$stack->{'dependencies'} = 1;
} elsif (/^--line-endings=crlf$/os) {
$stack->{'lineEndings'} = "\x0D\x0A";
} elsif (/^--line-endings=cr$/os) {
$stack->{'lineEndings'} = "\x0D";
} elsif (/^--line-endings=lf$/os) {
$stack->{'lineEndings'} = "\x0A";
} elsif (/^--line-endings=(.+)$/os) {
die "$0: unrecognised line ending: $1\n";
} elsif (/^--marker=(.)$/os) {
$marker = $1;
} else {
die "$0: invalid argument: $_\n";
}
}
unshift(@ARGV, '-') unless @ARGV;
unshift(@ARGV, @includes);
# do the work
foreach (@ARGV) { include($stack, $_); }
exit(0);
########################################################################
package main;
use File::Spec;
use File::Spec::Unix; # on all platforms, because the #include syntax is unix-based
# Note: Ideally we would use File::Spec 0.8. When this becomes
# possible, add "0.8" to the first "use" line above, then replace
# occurrences of "::_0_8::" with "->" below. And remove the code for
# File::Spec 0.8 much lower down the file.
sub include {
my($stack, $filename) = @_;
my $directory = $stack->{'variables'}->{'DIRECTORY'};
if ($filename ne '-') {
$filename = File::Spec::_0_8::rel2abs($filename, $directory);
# splitpath expects forward-slash paths on windows, so we have to
# change the slashes if using Activestate Perl.
$filename =~ s?\\?/?g if "$^O" eq "MSWin32";
my($volume, $path) = File::Spec::_0_8::splitpath($filename);
$directory = File::Spec::_0_8::catpath($volume, $path, '');
}
local $stack->{'variables'}->{'DIRECTORY'} = $directory;
local $stack->{'variables'}->{'FILE'} = $filename;
local $stack->{'variables'}->{'LINE'} = 0;
local *FILE;
open(FILE, $filename) or die "Couldn't open $filename: $!\n";
my $lineout = 0;
while (<FILE>) {
# on cygwin, line endings are screwed up, so normalise them.
s/[\x0D\x0A]+$/\n/os if ($^O eq 'msys' || $^O eq 'cygwin' || "$^O" eq "MSWin32");
$stack->newline;
if (/^\Q$marker\E([a-z]+)\n?$/os) { # argumentless processing instruction
process($stack, $1);
} elsif (/^\Q$marker\E([a-z]+)\s(.*?)\n?$/os) { # processing instruction with arguments
process($stack, $1, $2);
} elsif (/^\Q$marker\E/os) { # comment
# ignore it
} elsif ($stack->enabled) {
next if $stack->{'dependencies'};
# set the current line number in JavaScript if necessary
my $linein = $stack->{'variables'}->{'LINE'};
if (++$lineout != $linein) {
if ($filename =~ /\.js(|\.in)$/o) {
$stack->print("//\@line $linein \"$filename\"\n")
}
$lineout = $linein;
}
# print it, including any newlines
$stack->print(filtered($stack, $_));
}
}
close(FILE);
}
sub process {
my($stack, $instruction, @arguments) = @_;
my $method = 'preprocessor'->can($instruction);
if (not defined($method)) {
fatal($stack, 'unknown instruction', $instruction);
}
eval { &$method($stack, @arguments) };
if ($@) {
fatal($stack, "error evaluating $instruction:", $@);
}
}
sub filtered {
my($stack, $text) = @_;
foreach my $filter (sort keys %{$stack->{'filters'}}) {
next unless $stack->{'filters'}->{$filter};
my $method = 'filter'->can($filter);
if (not defined($method)) {
fatal($stack, 'unknown filter', $filter);
}
$text = eval { &$method($stack, $text) };
if ($@) {
fatal($stack, "error using $filter:", $@);
}
}
return $text;
}
sub fatal {
my $stack = shift;
my $filename = $stack->{'variables'}->{'FILE'};
local $" = ' ';
print STDERR "$0:$filename:$.: @_\n";
exit(1);
}
########################################################################
package stack;
# condition evaluated just prior to this context was false
use constant COND_FALSE => 0;
# condition evaluated just prior to this context was true
use constant COND_TRUE => 1;
# some prior condition at this level already evaluated to true (or a
# parent condition evaluated to false or must be ignored), so we're
# ignoring all remaining conditions at current level (and nested
# conditions, too)
use constant COND_COMPLETED => 2;
sub new {
return bless {
'variables' => {
# %ENV,
'LINE' => 0, # the line number in the source file
'DIRECTORY' => '', # current directory
'FILE' => '', # source filename
'1' => 1, # for convenience (the constant '1' is thus true)
},
'filters' => {
# filters
},
'values' => [], # the value of the last condition evaluated at the nth level
'lastConditionState' => [], # whether the condition in the nth-level context was true, false, or not applicable
'conditionState' => COND_TRUE,
'dependencies' => 0, # whether we are showing dependencies
'lineEndings' => "\n", # default to platform conventions
};
}
sub newline {
my $self = shift;
$self->{'variables'}->{'LINE'}++;
}
sub define {
my $self = shift;
my($variable, $value) = @_;
die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
$self->{'variables'}->{$variable} = $value;
}
sub defined {
my $self = shift;
my($variable) = @_;
die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
return defined($self->{'variables'}->{$variable});
}
sub undefine {
my $self = shift;
my($variable) = @_;
die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
delete($self->{'variables'}->{$variable});
}
sub get {
my $self = shift;
my($variable, $required) = @_;
die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
my $value = $self->{'variables'}->{$variable};
if (defined($value)) {
return $value;
} else {
die "variable '$variable' is not defined\n" if $required;
return '';
}
}
sub replace {
my $self = shift;
my ($value) = @_;
${$self->{'values'}}[-1] = $value;
$self->{'conditionState'} = $self->{'conditionState'} != COND_FALSE
? COND_COMPLETED
: $value ? COND_TRUE : COND_FALSE;
}
sub push {
my $self = shift;
my($value) = @_;
push(@{$self->{'values'}}, $value);
my $lastCondition = $self->{'conditionState'};
push(@{$self->{'lastConditionState'}}, $lastCondition);
$self->{'conditionState'} = $lastCondition != COND_TRUE
? COND_COMPLETED
: $value ? COND_TRUE : COND_FALSE;
}
sub pop {
my $self = shift;
$self->{'conditionState'} = pop(@{$self->{'lastConditionState'}});
return pop(@{$self->{'values'}});
}
sub enabled {
my $self = shift;
return $self->{'conditionState'} == COND_TRUE;
}
sub disabled {
my $self = shift;
return $self->{'conditionState'} != COND_TRUE;
}
sub filter {
my $self = shift;
my($filter, $value) = @_;
die "not a valid filter name: '$filter'\n" if $filter =~ m/\W/;
$self->{'filters'}->{$filter} = $value;
}
sub expand {
my $self = shift;
my($line) = @_;
$line =~ s/__(\w+)__/$self->get($1)/gose;
return $line;
}
sub print {
my $self = shift;
return if $self->{'dependencies'};
foreach my $line (@_) {
if (chomp $line) {
CORE::print("$line$self->{'lineEndings'}");
} else {
CORE::print($line);
}
}
}
sub visit {
my $self = shift;
my($filename) = @_;
my $directory = $stack->{'variables'}->{'DIRECTORY'};
$filename = File::Spec::_0_8::abs2rel(File::Spec::_0_8::rel2abs($filename, $directory));
CORE::print("$filename\n");
}
########################################################################
package preprocessor;
sub define {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
my $argument = shift;
for ($argument) {
/^(\w+)\s(.*)$/os && do {
return $stack->define($1, $2);
};
/^(\w+)$/os && do {
return $stack->define($1, 1);
};
die "invalid argument: '$_'\n";
}
}
sub undef {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
$stack->undefine(@_);
}
sub ifdef {
my $stack = shift;
my $variable = shift;
my $replace = defined(shift);
die "argument expected\n" unless defined($variable);
if ($replace) {
$stack->replace($stack->defined($variable));
} else {
$stack->push($stack->defined($variable));
}
}
sub ifndef {
my $stack = shift;
my $variable = shift;
my $replace = defined(shift);
die "argument expected\n" unless defined($variable);
if ($replace) {
$stack->replace(not $stack->defined($variable));
} else {
$stack->push(not $stack->defined($variable));
}
}
sub if {
my $stack = shift;
die "argument expected\n" unless @_;
my $argument = shift;
my $replace = defined(shift);
for ($argument) {
/^(\w+)==(.*)$/os && do {
# equality
if ($replace) {
return $stack->replace($stack->get($1) eq $2);
} else {
return $stack->push($stack->get($1) eq $2);
}
};
/^(\w+)!=(.*)$/os && do {
# inequality
if ($replace) {
return $stack->replace($stack->get($1) ne $2);
} else {
return $stack->push($stack->get($1) ne $2);
}
};
/^(\w+)$/os && do {
# true value
if ($replace) {
return $stack->replace($stack->get($1));
} else {
return $stack->push($stack->get($1));
}
};
/^!(\w+)$/os && do {
# false value
if ($replace) {
return $stack->replace(not $stack->get($1));
} else {
return $stack->push(not $stack->get($1));
}
};
die "invalid argument: '$_'\n";
}
}
sub else {
my $stack = shift;
die "argument unexpected\n" if @_;
$stack->replace(1);
}
sub elif {
my $stack = shift;
die "argument expected\n" unless @_;
&if($stack, @_, 1);
}
sub elifdef {
my $stack = shift;
die "argument expected\n" unless @_;
&ifdef($stack, @_, 1);
}
sub elifndef {
my $stack = shift;
die "argument expected\n" unless @_;
&ifndef($stack, @_, 1);
}
sub endif {
my $stack = shift;
die "argument unexpected\n" if @_;
$stack->pop;
}
sub error {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
my $line = $stack->expand(@_);
die "$line\n";
}
sub expand {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
my $line = $stack->expand(@_);
$stack->print("$line\n");
}
sub literal {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
my $line = shift;
$stack->print("$line\n");
}
sub include {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
my $filename = File::Spec::_0_8::catpath(File::Spec::_0_8::splitpath(@_));
if ($stack->{'dependencies'}) {
$stack->visit($filename);
} else {
main::include($stack, $filename);
}
}
sub includesubst {
my ($stack, $filename) = @_;
return if $stack->disabled;
die "argument expected\n" unless $filename;
$filename =~ s/@(\w+)@/$stack->get($1, 1)/gose;
$filename = File::Spec::_0_8::catpath(File::Spec::_0_8::splitpath($filename));
if ($stack->{'dependencies'}) {
$stack->visit($filename);
} else {
main::include($stack, $filename);
}
}
sub filter {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
foreach (split(/\s/os, shift)) {
$stack->filter($_, 1);
}
}
sub unfilter {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
foreach (split(/\s/os, shift)) {
$stack->filter($_, 0);
}
}
########################################################################
package filter;
sub emptyLines {
my($stack, $text) = @_;
$text = "" if $text eq "\n";
return $text;
}
sub spaces {
my($stack, $text) = @_;
$text =~ s/ +/ /gos; # middle spaces
$text =~ s/^ //gos; # start spaces
$text =~ s/ (\n?)$/$1/gos; # end spaces
return $text;
}
sub slashslash {
my($stack, $text) = @_;
$text =~ s|//.*?(\n?)$|$1|gos;
return $text;
}
sub substitution {
my($stack, $text) = @_;
$text =~ s/@(\w+)@/$stack->get($1, 1)/gose;
return $text;
}
sub attemptSubstitution {
my($stack, $text) = @_;
$text =~ s/@(\w+)@/$stack->get($1, 0)/gose;
return $text;
}
########################################################################
########################################################################
# This code is from File::Spec::Unix 0.8.
# It is not considered a part of the preprocessor.pl source file
# This code is licensed under the same license as File::Spec itself.
package File::Spec::_0_8;
use Cwd;
sub rel2abs {
my ($path, $base) = @_;
if ( ! File::Spec->file_name_is_absolute( $path ) ) {
if ( !defined( $base ) || $base eq '' ) {
$base = cwd() ;
} elsif ( ! File::Spec->file_name_is_absolute( $base ) ) {
$base = rel2abs( $base );
} else {
$base = File::Spec->canonpath( $base );
}
$path = File::Spec->catdir( $base, $path );
}
return File::Spec->canonpath( $path );
}
sub splitdir {
return split m|/|, $_[1], -1; # Preserve trailing fields
}
sub splitpath {
my ($path, $nofile) = @_;
my ($volume,$directory,$file) = ('','','');
if ( $nofile ) {
$directory = $path;
}
else {
$path =~ m|^ ( (?: .* / (?: \.\.?\Z(?!\n) )? )? ) ([^/]*) |xs;
$directory = $1;
$file = $2;
}
return ($volume,$directory,$file);
}
sub catpath {
my ($volume,$directory,$file) = @_;
if ( $directory ne '' &&
$file ne '' &&
substr( $directory, -1 ) ne '/' &&
substr( $file, 0, 1 ) ne '/'
) {
$directory .= "/$file" ;
}
else {
$directory .= $file ;
}
return $directory ;
}
sub abs2rel {
my($path,$base) = @_;
# Clean up $path
if ( ! File::Spec->file_name_is_absolute( $path ) ) {
$path = rel2abs( $path ) ;
}
else {
$path = File::Spec->canonpath( $path ) ;
}
# Figure out the effective $base and clean it up.
if ( !defined( $base ) || $base eq '' ) {
$base = cwd();
}
elsif ( ! File::Spec->file_name_is_absolute( $base ) ) {
$base = rel2abs( $base ) ;
}
else {
$base = File::Spec->canonpath( $base ) ;
}
# Now, remove all leading components that are the same
my @pathchunks = File::Spec::_0_8::splitdir( $path);
my @basechunks = File::Spec::_0_8::splitdir( $base);
while (@pathchunks && @basechunks && $pathchunks[0] eq $basechunks[0]) {
shift @pathchunks ;
shift @basechunks ;
}
$path = CORE::join( '/', @pathchunks );
$base = CORE::join( '/', @basechunks );
# $base now contains the directories the resulting relative path
# must ascend out of before it can descend to $path_directory. So,
# replace all names with $parentDir
$base =~ s|[^/]+|..|g ;
# Glue the two together, using a separator if necessary, and preventing an
# empty result.
if ( $path ne '' && $base ne '' ) {
$path = "$base/$path" ;
} else {
$path = "$base$path" ;
}
return File::Spec->canonpath( $path ) ;
}
# End code from File::Spec::Unix 0.8.
########################################################################

View File

@ -1,477 +0,0 @@
"""
This is a very primitive line based preprocessor, for times when using
a C preprocessor isn't an option.
"""
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla build system.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <axel@pike.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import sys
import os
import os.path
import re
from optparse import OptionParser
# hack around win32 mangling our line endings
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65443
if sys.platform == "win32":
import msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
os.linesep = '\n'
import Expression
__all__ = ['Preprocessor', 'preprocess']
class Preprocessor:
"""
Class for preprocessing text files.
"""
class Error(RuntimeError):
def __init__(self, cpp, MSG, context):
self.file = cpp.context['FILE']
self.line = cpp.context['LINE']
self.key = MSG
RuntimeError.__init__(self, (self.file, self.line, self.key, context))
def __init__(self):
self.context = Expression.Context()
for k,v in {'FILE': '',
'LINE': 0,
'DIRECTORY': os.path.abspath('.')}.iteritems():
self.context[k] = v
self.disableLevel = 0
# ifStates can be
# 0: hadTrue
# 1: wantsTrue
# 2: #else found
self.ifStates = []
self.checkLineNumbers = False
self.writtenLines = 0
self.filters = []
self.cmds = {}
for cmd, level in {'define': 0,
'undef': 0,
'if': sys.maxint,
'ifdef': sys.maxint,
'ifndef': sys.maxint,
'else': 1,
'elif': 1,
'elifdef': 1,
'elifndef': 1,
'endif': sys.maxint,
'expand': 0,
'literal': 0,
'filter': 0,
'unfilter': 0,
'include': 0,
'includesubst': 0,
'error': 0}.iteritems():
self.cmds[cmd] = (level, getattr(self, 'do_' + cmd))
self.out = sys.stdout
self.setMarker('#')
self.LE = '\n'
self.varsubst = re.compile('@(?P<VAR>\w+)@', re.U)
def setLineEndings(self, aLE):
"""
Set the line endings to be used for output.
"""
self.LE = {'cr': '\x0D', 'lf': '\x0A', 'crlf': '\x0D\x0A'}[aLE]
def setMarker(self, aMarker):
"""
Set the marker to be used for processing directives.
Used for handling CSS files, with pp.setMarker('%'), for example.
"""
self.marker = aMarker
self.instruction = re.compile('%s(?P<cmd>[a-z]+)(?:\s(?P<args>.*))?$'%aMarker, re.U)
self.comment = re.compile(aMarker, re.U)
def clone(self):
"""
Create a clone of the current processor, including line ending
settings, marker, variable definitions, output stream.
"""
rv = Preprocessor()
rv.context.update(self.context)
rv.setMarker(self.marker)
rv.LE = self.LE
rv.out = self.out
return rv
def write(self, aLine):
"""
Internal method for handling output.
"""
if self.checkLineNumbers:
self.writtenLines += 1
ln = self.context['LINE']
if self.writtenLines != ln:
self.out.write('//@line %(line)d "%(file)s"%(le)s'%{'line': ln,
'file': self.context['FILE'],
'le': self.LE})
self.writtenLines = ln
for f in self.filters:
aLine = f[1](aLine)
# ensure our line ending. Only need to handle \n, as we're reading
# with universal line ending support, at least for files.
aLine = re.sub('\n', self.LE, aLine)
self.out.write(aLine)
def handleCommandLine(self, args, defaultToStdin = False):
"""
Parse a commandline into this parser.
Uses OptionParser internally, no args mean sys.argv[1:].
"""
p = self.getCommandLineParser()
(options, args) = p.parse_args(args=args)
includes = options.I
if defaultToStdin and len(args) == 0:
args = [sys.stdin]
includes.extend(args)
for f in includes:
self.do_include(f)
pass
def getCommandLineParser(self, unescapeDefines = False):
escapedValue = re.compile('".*"$')
numberValue = re.compile('\d+$')
def handleE(option, opt, value, parser):
for k,v in os.environ.iteritems():
self.context[k] = v
def handleD(option, opt, value, parser):
vals = value.split('=', 1)
if len(vals) == 1:
vals.append(1)
elif unescapeDefines and escapedValue.match(vals[1]):
# strip escaped string values
vals[1] = vals[1][1:-1]
elif numberValue.match(vals[1]):
vals[1] = int(vals[1])
self.context[vals[0]] = vals[1]
def handleU(option, opt, value, parser):
del self.context[value]
def handleF(option, opt, value, parser):
self.do_filter(value)
def handleLE(option, opt, value, parser):
self.setLineEndings(value)
def handleMarker(option, opt, value, parser):
self.setMarker(value)
p = OptionParser()
p.add_option('-I', action='append', type="string", default = [],
metavar="FILENAME", help='Include file')
p.add_option('-E', action='callback', callback=handleE,
help='Import the environment into the defined variables')
p.add_option('-D', action='callback', callback=handleD, type="string",
metavar="VAR[=VAL]", help='Define a variable')
p.add_option('-U', action='callback', callback=handleU, type="string",
metavar="VAR", help='Undefine a variable')
p.add_option('-F', action='callback', callback=handleF, type="string",
metavar="FILTER", help='Enable the specified filter')
p.add_option('--line-endings', action='callback', callback=handleLE,
type="string", metavar="[cr|lr|crlf]",
help='Use the specified line endings [Default: OS dependent]')
p.add_option('--marker', action='callback', callback=handleMarker,
type="string",
help='Use the specified marker instead of #')
return p
def handleLine(self, aLine):
"""
Handle a single line of input (internal).
"""
m = self.instruction.match(aLine)
if m:
args = None
cmd = m.group('cmd')
try:
args = m.group('args')
except IndexError:
pass
if cmd not in self.cmds:
raise Preprocessor.Error(self, 'INVALID_CMD', aLine)
level, cmd = self.cmds[cmd]
if (level >= self.disableLevel):
cmd(args)
elif self.disableLevel == 0 and not self.comment.match(aLine):
self.write(aLine)
pass
# Instruction handlers
# These are named do_'instruction name' and take one argument
# Variables
def do_define(self, args):
m = re.match('(?P<name>\w+)(?:\s(?P<value>.*))?', args, re.U)
if not m:
raise Preprocessor.Error(self, 'SYNTAX_DEF', args)
val = 1
if m.group('value'):
val = m.group('value')
try:
val = int(val)
except:
pass
self.context[m.group('name')] = val
def do_undef(self, args):
m = re.match('(?P<name>\w+)$', args, re.U)
if not m:
raise Preprocessor.Error(self, 'SYNTAX_DEF', args)
if args in self.context:
del self.context[args]
# Logic
def ensure_not_else(self):
if len(self.ifStates) == 0 or self.ifStates[-1] == 2:
sys.stderr.write('WARNING: bad nesting of #else\n')
def do_if(self, args, replace=False):
if self.disableLevel and not replace:
self.disableLevel += 1
return
val = None
try:
e = Expression.Expression(args)
val = e.evaluate(self.context)
except Exception:
# XXX do real error reporting
raise Preprocessor.Error(self, 'SYNTAX_ERR', args)
if type(val) == str:
# we're looking for a number value, strings are false
val = False
if not val:
self.disableLevel = 1
if replace:
if val:
self.disableLevel = 0
self.ifStates[-1] = self.disableLevel
else:
self.ifStates.append(self.disableLevel)
pass
def do_ifdef(self, args, replace=False):
if self.disableLevel and not replace:
self.disableLevel += 1
return
if re.match('\W', args, re.U):
raise Preprocessor.Error(self, 'INVALID_VAR', args)
if args not in self.context:
self.disableLevel = 1
if replace:
if args in self.context:
self.disableLevel = 0
self.ifStates[-1] = self.disableLevel
else:
self.ifStates.append(self.disableLevel)
pass
def do_ifndef(self, args, replace=False):
if self.disableLevel and not replace:
self.disableLevel += 1
return
if re.match('\W', args, re.U):
raise Preprocessor.Error(self, 'INVALID_VAR', args)
if args in self.context:
self.disableLevel = 1
if replace:
if args not in self.context:
self.disableLevel = 0
self.ifStates[-1] = self.disableLevel
else:
self.ifStates.append(self.disableLevel)
pass
def do_else(self, args, ifState = 2):
self.ensure_not_else()
hadTrue = self.ifStates[-1] == 0
self.ifStates[-1] = ifState # in-else
if hadTrue:
self.disableLevel = 1
return
self.disableLevel = 0
def do_elif(self, args):
if self.disableLevel == 1:
if self.ifStates[-1] == 1:
self.do_if(args, replace=True)
else:
self.do_else(None, self.ifStates[-1])
def do_elifdef(self, args):
if self.disableLevel == 1:
if self.ifStates[-1] == 1:
self.do_ifdef(args, replace=True)
else:
self.do_else(None, self.ifStates[-1])
def do_elifndef(self, args):
if self.disableLevel == 1:
if self.ifStates[-1] == 1:
self.do_ifndef(args, replace=True)
else:
self.do_else(None, self.ifStates[-1])
def do_endif(self, args):
if self.disableLevel > 0:
self.disableLevel -= 1
if self.disableLevel == 0:
self.ifStates.pop()
# output processing
def do_expand(self, args):
lst = re.split('__(\w+)__', args, re.U)
do_replace = False
def vsubst(v):
if v in self.context:
return str(self.context[v])
return ''
for i in range(1, len(lst), 2):
lst[i] = vsubst(lst[i])
lst.append('\n') # add back the newline
self.write(reduce(lambda x, y: x+y, lst, ''))
def do_literal(self, args):
self.write(args + self.LE)
def do_filter(self, args):
filters = [f for f in args.split(' ') if hasattr(self, 'filter_' + f)]
if len(filters) == 0:
return
current = dict(self.filters)
for f in filters:
current[f] = getattr(self, 'filter_' + f)
filterNames = current.keys()
filterNames.sort()
self.filters = [(fn, current[fn]) for fn in filterNames]
return
def do_unfilter(self, args):
filters = args.split(' ')
current = dict(self.filters)
for f in filters:
if f in current:
del current[f]
filterNames = current.keys()
filterNames.sort()
self.filters = [(fn, current[fn]) for fn in filterNames]
return
# Filters
#
# emptyLines
# Strips blank lines from the output.
def filter_emptyLines(self, aLine):
if aLine == '\n':
return ''
return aLine
# slashslash
# Strips everything after //
def filter_slashslash(self, aLine):
[aLine, rest] = aLine.split('//', 1)
if rest:
aLine += '\n'
return aLine
# spaces
# Collapses sequences of spaces into a single space
def filter_spaces(self, aLine):
return re.sub(' +', ' ', aLine).strip(' ')
# substition
# helper to be used by both substition and attemptSubstitution
def filter_substitution(self, aLine, fatal=True):
def repl(matchobj):
varname = matchobj.group('VAR')
if varname in self.context:
return str(self.context[varname])
if fatal:
raise Preprocessor.Error(self, 'UNDEFINED_VAR', varname)
return ''
return self.varsubst.sub(repl, aLine)
def filter_attemptSubstitution(self, aLine):
return self.filter_substitution(aLine, fatal=False)
# File ops
def do_include(self, args):
"""
Preprocess a given file.
args can either be a file name, or a file-like object.
Files should be opened, and will be closed after processing.
"""
isName = type(args) == str or type(args) == unicode
oldWrittenLines = self.writtenLines
oldCheckLineNumbers = self.checkLineNumbers
self.checkLineNumbers = False
if isName:
try:
args = str(args)
if not os.path.isabs(args):
args = os.path.join(self.context['DIRECTORY'], args)
args = open(args, 'rU')
except:
raise Preprocessor.Error(self, 'FILE_NOT_FOUND', str(args))
self.checkLineNumbers = bool(re.search('\.js(?:\.in)?$', args.name))
oldFile = self.context['FILE']
oldLine = self.context['LINE']
oldDir = self.context['DIRECTORY']
if args.isatty():
# we're stdin, use '-' and '' for file and dir
self.context['FILE'] = '-'
self.context['DIRECTORY'] = ''
else:
abspath = os.path.abspath(args.name)
self.context['FILE'] = abspath
self.context['DIRECTORY'] = os.path.dirname(abspath)
self.context['LINE'] = 0
self.writtenLines = 0
for l in args:
self.context['LINE'] += 1
self.handleLine(l)
args.close()
self.context['FILE'] = oldFile
self.checkLineNumbers = oldCheckLineNumbers
self.writtenLines = oldWrittenLines
self.context['LINE'] = oldLine
self.context['DIRECTORY'] = oldDir
def do_includesubst(self, args):
args = self.filter_substitution(args)
self.do_include(args)
def do_error(self, args):
raise Preprocessor.Error(self, 'Error: ', str(args))
def main():
pp = Preprocessor()
pp.handleCommandLine(None, True)
return
def preprocess(includes=[sys.stdin], defines={},
output = sys.stdout,
line_endings='\n', marker='#'):
pp = Preprocessor()
pp.context.update(defines)
pp.setLineEndings(line_endings)
pp.setMarker(marker)
pp.out = output
for f in includes:
pp.do_include(f)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,671 @@
#!/usr/bin/perl -w
# -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*-
#
# Preprocessor
# Version 1.1
#
# Copyright (c) 2002, 2003, 2004 by Ian Hickson
#
# 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
# Thanks to bryner and bsmedberg for suggestions.
# Thanks to jon rekai for a patch to not require File::Spec 0.8.
use strict;
# takes as arguments the files to process
# defaults to stdin
# output to stdout
my $stack = new stack;
my $marker = '#';
# command line arguments
my @includes;
while ($_ = $ARGV[0], defined($_) && /^-./) {
shift;
last if /^--$/os;
if (/^-D(.*)$/os) {
for ($1) {
if (/^([\w\.]+)=(.*)$/os) {
$stack->define($1, $2);
} elsif (/^([\w\.]+)$/os) {
$stack->define($1, 1);
} else {
die "$0: invalid argument to -D: $_\n";
}
}
} elsif (/^-F(.*)$/os) {
for ($1) {
if (/^(\w+)$/os) {
$stack->filter($1, 1);
} else {
die "$0: invalid argument to -F: $_\n";
}
}
} elsif (/^-I(.*)$/os) {
push(@includes, $1);
} elsif (/^-E$/os) {
foreach (keys %ENV) {
# define all variables that have valid names
$stack->define($_, $ENV{$_}) unless m/\W/;
}
} elsif (/^-d$/os) {
$stack->{'dependencies'} = 1;
} elsif (/^--line-endings=crlf$/os) {
$stack->{'lineEndings'} = "\x0D\x0A";
} elsif (/^--line-endings=cr$/os) {
$stack->{'lineEndings'} = "\x0D";
} elsif (/^--line-endings=lf$/os) {
$stack->{'lineEndings'} = "\x0A";
} elsif (/^--line-endings=(.+)$/os) {
die "$0: unrecognised line ending: $1\n";
} elsif (/^--marker=(.)$/os) {
$marker = $1;
} else {
die "$0: invalid argument: $_\n";
}
}
unshift(@ARGV, '-') unless @ARGV;
unshift(@ARGV, @includes);
# do the work
foreach (@ARGV) { include($stack, $_); }
exit(0);
########################################################################
package main;
use File::Spec;
use File::Spec::Unix; # on all platforms, because the #include syntax is unix-based
# Note: Ideally we would use File::Spec 0.8. When this becomes
# possible, add "0.8" to the first "use" line above, then replace
# occurrences of "::_0_8::" with "->" below. And remove the code for
# File::Spec 0.8 much lower down the file.
sub include {
my($stack, $filename) = @_;
my $directory = $stack->{'variables'}->{'DIRECTORY'};
if ($filename ne '-') {
$filename = File::Spec::_0_8::rel2abs($filename, $directory);
# splitpath expects forward-slash paths on windows, so we have to
# change the slashes if using Activestate Perl.
$filename =~ s?\\?/?g if "$^O" eq "MSWin32";
my($volume, $path) = File::Spec::_0_8::splitpath($filename);
$directory = File::Spec::_0_8::catpath($volume, $path, '');
}
local $stack->{'variables'}->{'DIRECTORY'} = $directory;
local $stack->{'variables'}->{'FILE'} = $filename;
local $stack->{'variables'}->{'LINE'} = 0;
local *FILE;
open(FILE, $filename) or die "Couldn't open $filename: $!\n";
my $lineout = 0;
while (<FILE>) {
# on cygwin, line endings are screwed up, so normalise them.
s/[\x0D\x0A]+$/\n/os if ($^O eq 'msys' || $^O eq 'cygwin' || "$^O" eq "MSWin32");
$stack->newline;
if (/^\Q$marker\E([a-z]+)\n?$/os) { # argumentless processing instruction
process($stack, $1);
} elsif (/^\Q$marker\E([a-z]+)\s(.*?)\n?$/os) { # processing instruction with arguments
process($stack, $1, $2);
} elsif (/^\Q$marker\E/os) { # comment
# ignore it
} elsif ($stack->enabled) {
next if $stack->{'dependencies'};
# set the current line number in JavaScript if necessary
my $linein = $stack->{'variables'}->{'LINE'};
if (++$lineout != $linein) {
if ($filename =~ /\.js(|\.in)$/o) {
$stack->print("//\@line $linein \"$filename\"\n")
}
$lineout = $linein;
}
# print it, including any newlines
$stack->print(filtered($stack, $_));
}
}
close(FILE);
}
sub process {
my($stack, $instruction, @arguments) = @_;
my $method = 'preprocessor'->can($instruction);
if (not defined($method)) {
fatal($stack, 'unknown instruction', $instruction);
}
eval { &$method($stack, @arguments) };
if ($@) {
fatal($stack, "error evaluating $instruction:", $@);
}
}
sub filtered {
my($stack, $text) = @_;
foreach my $filter (sort keys %{$stack->{'filters'}}) {
next unless $stack->{'filters'}->{$filter};
my $method = 'filter'->can($filter);
if (not defined($method)) {
fatal($stack, 'unknown filter', $filter);
}
$text = eval { &$method($stack, $text) };
if ($@) {
fatal($stack, "error using $filter:", $@);
}
}
return $text;
}
sub fatal {
my $stack = shift;
my $filename = $stack->{'variables'}->{'FILE'};
local $" = ' ';
print STDERR "$0:$filename:$.: @_\n";
exit(1);
}
########################################################################
package stack;
# condition evaluated just prior to this context was false
use constant COND_FALSE => 0;
# condition evaluated just prior to this context was true
use constant COND_TRUE => 1;
# some prior condition at this level already evaluated to true (or a
# parent condition evaluated to false or must be ignored), so we're
# ignoring all remaining conditions at current level (and nested
# conditions, too)
use constant COND_COMPLETED => 2;
sub new {
return bless {
'variables' => {
# %ENV,
'LINE' => 0, # the line number in the source file
'DIRECTORY' => '', # current directory
'FILE' => '', # source filename
'1' => 1, # for convenience (the constant '1' is thus true)
},
'filters' => {
# filters
},
'values' => [], # the value of the last condition evaluated at the nth level
'lastConditionState' => [], # whether the condition in the nth-level context was true, false, or not applicable
'conditionState' => COND_TRUE,
'dependencies' => 0, # whether we are showing dependencies
'lineEndings' => "\n", # default to platform conventions
};
}
sub newline {
my $self = shift;
$self->{'variables'}->{'LINE'}++;
}
sub define {
my $self = shift;
my($variable, $value) = @_;
die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
$self->{'variables'}->{$variable} = $value;
}
sub defined {
my $self = shift;
my($variable) = @_;
die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
return defined($self->{'variables'}->{$variable});
}
sub undefine {
my $self = shift;
my($variable) = @_;
die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
delete($self->{'variables'}->{$variable});
}
sub get {
my $self = shift;
my($variable, $required) = @_;
die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
my $value = $self->{'variables'}->{$variable};
if (defined($value)) {
return $value;
} else {
die "variable '$variable' is not defined\n" if $required;
return '';
}
}
sub replace {
my $self = shift;
my ($value) = @_;
${$self->{'values'}}[-1] = $value;
$self->{'conditionState'} = $self->{'conditionState'} != COND_FALSE
? COND_COMPLETED
: $value ? COND_TRUE : COND_FALSE;
}
sub push {
my $self = shift;
my($value) = @_;
push(@{$self->{'values'}}, $value);
my $lastCondition = $self->{'conditionState'};
push(@{$self->{'lastConditionState'}}, $lastCondition);
$self->{'conditionState'} = $lastCondition != COND_TRUE
? COND_COMPLETED
: $value ? COND_TRUE : COND_FALSE;
}
sub pop {
my $self = shift;
$self->{'conditionState'} = pop(@{$self->{'lastConditionState'}});
return pop(@{$self->{'values'}});
}
sub enabled {
my $self = shift;
return $self->{'conditionState'} == COND_TRUE;
}
sub disabled {
my $self = shift;
return $self->{'conditionState'} != COND_TRUE;
}
sub filter {
my $self = shift;
my($filter, $value) = @_;
die "not a valid filter name: '$filter'\n" if $filter =~ m/\W/;
$self->{'filters'}->{$filter} = $value;
}
sub expand {
my $self = shift;
my($line) = @_;
$line =~ s/__(\w+)__/$self->get($1)/gose;
return $line;
}
sub print {
my $self = shift;
return if $self->{'dependencies'};
foreach my $line (@_) {
if (chomp $line) {
CORE::print("$line$self->{'lineEndings'}");
} else {
CORE::print($line);
}
}
}
sub visit {
my $self = shift;
my($filename) = @_;
my $directory = $stack->{'variables'}->{'DIRECTORY'};
$filename = File::Spec::_0_8::abs2rel(File::Spec::_0_8::rel2abs($filename, $directory));
CORE::print("$filename\n");
}
########################################################################
package preprocessor;
sub define {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
my $argument = shift;
for ($argument) {
/^(\w+)\s(.*)$/os && do {
return $stack->define($1, $2);
};
/^(\w+)$/os && do {
return $stack->define($1, 1);
};
die "invalid argument: '$_'\n";
}
}
sub undef {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
$stack->undefine(@_);
}
sub ifdef {
my $stack = shift;
my $variable = shift;
my $replace = defined(shift);
die "argument expected\n" unless defined($variable);
if ($replace) {
$stack->replace($stack->defined($variable));
} else {
$stack->push($stack->defined($variable));
}
}
sub ifndef {
my $stack = shift;
my $variable = shift;
my $replace = defined(shift);
die "argument expected\n" unless defined($variable);
if ($replace) {
$stack->replace(not $stack->defined($variable));
} else {
$stack->push(not $stack->defined($variable));
}
}
sub if {
my $stack = shift;
die "argument expected\n" unless @_;
my $argument = shift;
my $replace = defined(shift);
for ($argument) {
/^(\w+)==(.*)$/os && do {
# equality
if ($replace) {
return $stack->replace($stack->get($1) eq $2);
} else {
return $stack->push($stack->get($1) eq $2);
}
};
/^(\w+)!=(.*)$/os && do {
# inequality
if ($replace) {
return $stack->replace($stack->get($1) ne $2);
} else {
return $stack->push($stack->get($1) ne $2);
}
};
/^(\w+)$/os && do {
# true value
if ($replace) {
return $stack->replace($stack->get($1));
} else {
return $stack->push($stack->get($1));
}
};
/^!(\w+)$/os && do {
# false value
if ($replace) {
return $stack->replace(not $stack->get($1));
} else {
return $stack->push(not $stack->get($1));
}
};
die "invalid argument: '$_'\n";
}
}
sub else {
my $stack = shift;
die "argument unexpected\n" if @_;
$stack->replace(1);
}
sub elif {
my $stack = shift;
die "argument expected\n" unless @_;
&if($stack, @_, 1);
}
sub elifdef {
my $stack = shift;
die "argument expected\n" unless @_;
&ifdef($stack, @_, 1);
}
sub elifndef {
my $stack = shift;
die "argument expected\n" unless @_;
&ifndef($stack, @_, 1);
}
sub endif {
my $stack = shift;
die "argument unexpected\n" if @_;
$stack->pop;
}
sub error {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
my $line = $stack->expand(@_);
die "$line\n";
}
sub expand {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
my $line = $stack->expand(@_);
$stack->print("$line\n");
}
sub literal {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
my $line = shift;
$stack->print("$line\n");
}
sub include {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
my $filename = File::Spec::_0_8::catpath(File::Spec::_0_8::splitpath(@_));
if ($stack->{'dependencies'}) {
$stack->visit($filename);
} else {
main::include($stack, $filename);
}
}
sub includesubst {
my ($stack, $filename) = @_;
return if $stack->disabled;
die "argument expected\n" unless $filename;
$filename =~ s/@(\w+)@/$stack->get($1, 1)/gose;
$filename = File::Spec::_0_8::catpath(File::Spec::_0_8::splitpath($filename));
if ($stack->{'dependencies'}) {
$stack->visit($filename);
} else {
main::include($stack, $filename);
}
}
sub filter {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
foreach (split(/\s/os, shift)) {
$stack->filter($_, 1);
}
}
sub unfilter {
my $stack = shift;
return if $stack->disabled;
die "argument expected\n" unless @_;
foreach (split(/\s/os, shift)) {
$stack->filter($_, 0);
}
}
########################################################################
package filter;
sub emptyLines {
my($stack, $text) = @_;
$text = "" if $text eq "\n";
return $text;
}
sub spaces {
my($stack, $text) = @_;
$text =~ s/ +/ /gos; # middle spaces
$text =~ s/^ //gos; # start spaces
$text =~ s/ (\n?)$/$1/gos; # end spaces
return $text;
}
sub slashslash {
my($stack, $text) = @_;
$text =~ s|//.*?(\n?)$|$1|gos;
return $text;
}
sub substitution {
my($stack, $text) = @_;
$text =~ s/@(\w+)@/$stack->get($1, 1)/gose;
return $text;
}
sub attemptSubstitution {
my($stack, $text) = @_;
$text =~ s/@(\w+)@/$stack->get($1, 0)/gose;
return $text;
}
########################################################################
########################################################################
# This code is from File::Spec::Unix 0.8.
# It is not considered a part of the preprocessor.pl source file
# This code is licensed under the same license as File::Spec itself.
package File::Spec::_0_8;
use Cwd;
sub rel2abs {
my ($path, $base) = @_;
if ( ! File::Spec->file_name_is_absolute( $path ) ) {
if ( !defined( $base ) || $base eq '' ) {
$base = cwd() ;
} elsif ( ! File::Spec->file_name_is_absolute( $base ) ) {
$base = rel2abs( $base );
} else {
$base = File::Spec->canonpath( $base );
}
$path = File::Spec->catdir( $base, $path );
}
return File::Spec->canonpath( $path );
}
sub splitdir {
return split m|/|, $_[1], -1; # Preserve trailing fields
}
sub splitpath {
my ($path, $nofile) = @_;
my ($volume,$directory,$file) = ('','','');
if ( $nofile ) {
$directory = $path;
}
else {
$path =~ m|^ ( (?: .* / (?: \.\.?\Z(?!\n) )? )? ) ([^/]*) |xs;
$directory = $1;
$file = $2;
}
return ($volume,$directory,$file);
}
sub catpath {
my ($volume,$directory,$file) = @_;
if ( $directory ne '' &&
$file ne '' &&
substr( $directory, -1 ) ne '/' &&
substr( $file, 0, 1 ) ne '/'
) {
$directory .= "/$file" ;
}
else {
$directory .= $file ;
}
return $directory ;
}
sub abs2rel {
my($path,$base) = @_;
# Clean up $path
if ( ! File::Spec->file_name_is_absolute( $path ) ) {
$path = rel2abs( $path ) ;
}
else {
$path = File::Spec->canonpath( $path ) ;
}
# Figure out the effective $base and clean it up.
if ( !defined( $base ) || $base eq '' ) {
$base = cwd();
}
elsif ( ! File::Spec->file_name_is_absolute( $base ) ) {
$base = rel2abs( $base ) ;
}
else {
$base = File::Spec->canonpath( $base ) ;
}
# Now, remove all leading components that are the same
my @pathchunks = File::Spec::_0_8::splitdir( $path);
my @basechunks = File::Spec::_0_8::splitdir( $base);
while (@pathchunks && @basechunks && $pathchunks[0] eq $basechunks[0]) {
shift @pathchunks ;
shift @basechunks ;
}
$path = CORE::join( '/', @pathchunks );
$base = CORE::join( '/', @basechunks );
# $base now contains the directories the resulting relative path
# must ascend out of before it can descend to $path_directory. So,
# replace all names with $parentDir
$base =~ s|[^/]+|..|g ;
# Glue the two together, using a separator if necessary, and preventing an
# empty result.
if ( $path ne '' && $base ne '' ) {
$path = "$base/$path" ;
} else {
$path = "$base$path" ;
}
return File::Spec->canonpath( $path ) ;
}
# End code from File::Spec::Unix 0.8.
########################################################################

View File

@ -190,7 +190,7 @@ langpack-%: XPI_NAME=locale-$*
langpack-%: libs-%
@echo "Making langpack $(LANGPACK_FILE)"
$(NSINSTALL) -D $(DIST)/$(PKG_LANGPACK_PATH)
$(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) -I$(TK_DEFINES) -I$(APP_DEFINES) $(srcdir)/generic/install.rdf > $(FINAL_TARGET)/install.rdf
$(PERL) $(MOZILLA_DIR)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) -I$(TK_DEFINES) -I$(APP_DEFINES) $(srcdir)/generic/install.rdf > $(FINAL_TARGET)/install.rdf
cd $(DIST)/xpi-stage/locale-$(AB_CD) && \
$(ZIP) -r9D $(LANGPACK_FILE) install.rdf chrome chrome.manifest -x chrome/$(AB_CD).manifest

View File

@ -197,6 +197,7 @@ _g_skip_files = [
"netwerk/streamconv/public/mozITXTToHTMLConv.idl",
# GPLed build tools
"config/preprocessor.pl",
"intl/uconv/tools/parse-mozilla-encoding-table.pl",
"intl/uconv/tools/gen-big5hkscs-2001-mozilla.pl",
"js2/missing",

View File

@ -234,7 +234,7 @@ endif
# XXX applications would need to supply this file
#export:: brand.dtd.in
# $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $^ > brand.dtd
# $(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $^ > brand.dtd
export::
$(NSINSTALL) -D $(DIST)/branding

View File

@ -61,7 +61,7 @@ include $(topsrcdir)/config/rules.mk
libs:: stage-package
%.plist: %.plist.in
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $< > $@
$(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $< > $@
PACKAGER_NO_LIBS=1
_APPNAME = XUL.framework