diff --git a/mozilla/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile.in b/mozilla/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile.in index 82b1e67853e..599e32094cb 100644 --- a/mozilla/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile.in +++ b/mozilla/browser/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/Makefile.in @@ -50,7 +50,7 @@ FILES := \ $(NULL) libs:: - $(PERL) $(MOZILLA_DIR)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $(srcdir)/install.rdf.in > install.rdf + $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(srcdir)/install.rdf.in > install.rdf $(INSTALL) $(FILES) $(DIST)/bin/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd} install:: diff --git a/mozilla/browser/branding/unofficial/locales/Makefile.in b/mozilla/browser/branding/unofficial/locales/Makefile.in index cb39c84f3e9..a31208e198a 100755 --- a/mozilla/browser/branding/unofficial/locales/Makefile.in +++ b/mozilla/browser/branding/unofficial/locales/Makefile.in @@ -47,9 +47,9 @@ DEFINES += -DAB_CD=$(AB_CD) -DMOZ_DISTRIBUTION_ID_UNQUOTED=$(MOZ_DISTRIBUTION_ID include $(topsrcdir)/config/rules.mk libs:: - @$(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) \ + @$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \ $(srcdir)/browserconfig.properties > $(FINAL_TARGET)/browserconfig.properties install:: - @$(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) \ + @$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \ $(srcdir)/browserconfig.properties > $(DESTDIR)$(mozappdir)/browserconfig.properties diff --git a/mozilla/config/Expression.py b/mozilla/config/Expression.py new file mode 100644 index 00000000000..f26a8f5cba8 --- /dev/null +++ b/mozilla/config/Expression.py @@ -0,0 +1,208 @@ +# ***** 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 +# +# 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 ***** + +""" +Parses and evaluates simple statements for Preprocessor: + +Expression currently supports the following grammar, whitespace is ignored: + +expression : + unary ( ( '==' | '!=' ) unary ) ? ; +unary : + '!'? value ; +value : + [0-9]+ # integer + | \w+ # string identifier or value; +""" + +import re + +class Expression: + def __init__(self, expression_string): + """ + Create a new expression with this string. + The expression will already be parsed into an Abstract Syntax Tree. + """ + self.content = expression_string + self.offset = 0 + self.__ignore_whitespace() + self.e = self.__get_equality() + if self.content: + raise Expression.ParseError, self + + def __get_equality(self): + """ + Production: unary ( ( '==' | '!=' ) unary ) ? + """ + if not len(self.content): + return None + rv = Expression.__AST("equality") + # unary + rv.append(self.__get_unary()) + self.__ignore_whitespace() + if not re.match('[=!]=', self.content): + # no equality needed, short cut to our prime unary + return rv[0] + # append operator + rv.append(Expression.__ASTLeaf('op', self.content[:2])) + self.__strip(2) + self.__ignore_whitespace() + rv.append(self.__get_unary()) + self.__ignore_whitespace() + return rv + + def __get_unary(self): + """ + Production: '!'? value + """ + # eat whitespace right away, too + not_ws = re.match('!\s*', self.content) + if not not_ws: + return self.__get_value() + rv = Expression.__AST('not') + self.__strip(not_ws.end()) + rv.append(self.__get_value()) + self.__ignore_whitespace() + return rv + + def __get_value(self): + """ + Production: ( [0-9]+ | \w+) + Note that the order is important, and the expression is kind-of + ambiguous as \w includes 0-9. One could make it unambiguous by + removing 0-9 from the first char of a string literal. + """ + rv = None + word_len = re.match('[0-9]*', self.content).end() + if word_len: + rv = Expression.__ASTLeaf('int', int(self.content[:word_len])) + else: + word_len = re.match('\w*', self.content).end() + if word_len: + rv = Expression.__ASTLeaf('string', self.content[:word_len]) + else: + raise Expression.ParseError, self + self.__strip(word_len) + self.__ignore_whitespace() + return rv + + def __ignore_whitespace(self): + ws_len = re.match('\s*', self.content).end() + self.__strip(ws_len) + return + + def __strip(self, length): + """ + Remove a given amount of chars from the input and update + the offset. + """ + self.content = self.content[length:] + self.offset += length + + def evaluate(self, context): + """ + Evaluate the expression with the given context + """ + + # Helper function to evaluate __get_equality results + def eval_equality(tok): + left = opmap[tok[0].type](tok[0]) + right = opmap[tok[2].type](tok[2]) + rv = left == right + if tok[1].value == '!=': + rv = not rv + return rv + # Mapping from token types to evaluator functions + # Apart from (non-)equality, all these can be simple lambda forms. + opmap = { + 'equality': eval_equality, + 'not': lambda tok: not opmap[tok[0].type](tok[0]), + 'string': lambda tok: context[tok.value], + 'int': lambda tok: tok.value} + + return opmap[self.e.type](self.e); + + class __AST(list): + """ + Internal class implementing Abstract Syntax Tree nodes + """ + def __init__(self, type): + self.type = type + super(self.__class__, self).__init__(self) + + class __ASTLeaf: + """ + Internal class implementing Abstract Syntax Tree leafs + """ + def __init__(self, type, value): + self.value = value + self.type = type + def __str__(self): + return self.value.__str__() + def __repr__(self): + return self.value.__repr__() + + class ParseError(StandardError): + """ + Error raised when parsing fails. + It has two members, offset and content, which give the offset of the + error and the offending content. + """ + def __init__(self, expression): + self.offset = expression.offset + self.content = expression.content[:3] + def __str__(self): + return 'Unexpected content at offset %i, "%s"'%(self.offset, self.content) + +class Context(dict): + """ + This class holds variable values by subclassing dict, and while it + truthfully reports True and False on + + name in context + + it returns the variable name itself on + + context["name"] + + to reflect the ambiguity between string literals and preprocessor + variables. + """ + def __getitem__(self, key): + if key in self: + return super(self.__class__, self).__getitem__(key) + return key diff --git a/mozilla/config/Makefile.in b/mozilla/config/Makefile.in index d49b6ac5185..a58860e4a77 100644 --- a/mozilla/config/Makefile.in +++ b/mozilla/config/Makefile.in @@ -165,3 +165,11 @@ ifdef MKDEPEND_DIR clean clobber realclean clobber_all:: cd $(MKDEPEND_DIR); $(MAKE) $@ endif + +PYUNITS := unit-Expression.py unit-Preprocessor.py + +check:: + @$(EXIT_ON_ERROR) \ + for test in $(PYUNITS); do \ + $(PYTHON) $(srcdir)/tests/$$test ; \ + done diff --git a/mozilla/config/Preprocessor.py b/mozilla/config/Preprocessor.py new file mode 100644 index 00000000000..5d50e6457d2 --- /dev/null +++ b/mozilla/config/Preprocessor.py @@ -0,0 +1,465 @@ +""" +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 +# +# 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 os, msvcrt + msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) + +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\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[a-z]+)(?:\s(?P.*))?$'%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) + aLine = aLine.rstrip('\r\n') + self.LE + 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:]. + """ + includes = [] + def handleI(option, opt, value, parser): + includes.append(value) + 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('=') + assert len(vals) < 3 + if len(vals) == 1: + vals.append(1) + self.context[vals[0]] = vals[1] + def handleU(option, opt, value, parser): + del self.context[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='callback', callback=handleI, type="string", + 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('--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 #') + (options, args) = p.parse_args(args=args) + if defaultToStdin and len(args) == 0: + args = [sys.stdin] + includes.extend(args) + for f in includes: + self.do_include(f) + pass + + 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\w+)(?:\s(?P.*))?', args, re.U) + if not m: + raise Preprocessor.Error(self, 'SYNTAX_DEF', args) + val = 1 + if m.group('value'): + val = m.group('value') + try: + if val[0] == '0': + val = int(val, 8) + else: + val = int(val) + except: + pass + self.context[m.group('name')] = val + def do_undef(self, args): + m = re.match('(?P\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) + 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) + 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() diff --git a/mozilla/config/config.mk b/mozilla/config/config.mk index 48460f76cf6..e4d6c415be8 100644 --- a/mozilla/config/config.mk +++ b/mozilla/config/config.mk @@ -777,7 +777,7 @@ endif # Now test variables that might have been set or overridden by $(MY_CONFIG). DEFINES += -DOSTYPE=\"$(OS_CONFIG)\" -DEFINES += -DOSARCH=\"$(OS_ARCH)\" +DEFINES += -DOSARCH=$(OS_ARCH) # For profiling ifdef ENABLE_EAZEL_PROFILER diff --git a/mozilla/config/rules.mk b/mozilla/config/rules.mk index 87d1e3eb8af..b4ff9bdb009 100644 --- a/mozilla/config/rules.mk +++ b/mozilla/config/rules.mk @@ -1436,7 +1436,7 @@ libs:: $(PREF_JS_EXPORTS) for i in $(PREF_JS_EXPORTS); do \ dest=$(FINAL_TARGET)/$(PREF_DIR)/`basename $$i`; \ $(RM) -f $$dest; \ - $(PERL) $(topsrcdir)/config/preprocessor.pl $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ + $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ done endif @@ -1447,7 +1447,7 @@ install:: $(PREF_JS_EXPORTS) for i in $(PREF_JS_EXPORTS); do \ dest=$(DESTDIR)$(mozappdir)/$(PREF_DIR)/`basename $$i`; \ $(RM) -f $$dest; \ - $(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ + $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ done endif endif @@ -1676,7 +1676,7 @@ ifndef NO_DIST_INSTALL for i in $^; do \ dest=$(FINAL_TARGET)/components/`basename $$i`; \ $(RM) -f $$dest; \ - $(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ + $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ done endif @@ -1686,7 +1686,7 @@ ifndef NO_INSTALL for i in $^; do \ dest=$(DESTDIR)$(mozappdir)/components/`basename $$i`; \ $(RM) -f $$dest; \ - $(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ + $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \ done endif endif @@ -1732,7 +1732,7 @@ ifndef NO_DIST_INSTALL if test -f $(JAR_MANIFEST); then \ if test ! -d $(FINAL_TARGET)/chrome; then $(NSINSTALL) -D $(FINAL_TARGET)/chrome; fi; \ if test ! -d $(MAKE_JARS_TARGET)/chrome; then $(NSINSTALL) -D $(MAKE_JARS_TARGET)/chrome; fi; \ - $(PERL) $(MOZILLA_DIR)/config/preprocessor.pl $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \ + $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \ $(JAR_MANIFEST) | \ $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/make-jars.pl \ -d $(MAKE_JARS_TARGET)/chrome -j $(FINAL_TARGET)/chrome \ @@ -1749,7 +1749,7 @@ ifndef NO_INSTALL if test -f $(JAR_MANIFEST); then \ if test ! -d $(DESTDIR)$(mozappdir)/chrome; then $(NSINSTALL) -D $(DESTDIR)$(mozappdir)/chrome; fi; \ if test ! -d $(MAKE_JARS_TARGET)/chrome; then $(NSINSTALL) -D $(MAKE_JARS_TARGET)/chrome; fi; \ - $(PERL) $(MOZILLA_DIR)/config/preprocessor.pl $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \ + $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \ $(JAR_MANIFEST) | \ $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/make-jars.pl \ -d $(MAKE_JARS_TARGET)/chrome -j $(DESTDIR)$(mozappdir)/chrome \ @@ -1763,7 +1763,7 @@ libs:: $(DIST_FILES) for f in $(DIST_FILES); do \ dest=$(FINAL_TARGET)/`basename $$f`; \ $(RM) -f $$dest; \ - $(PERL) $(MOZILLA_DIR)/config/preprocessor.pl \ + $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \ $(srcdir)/$$f > $$dest; \ done @@ -1775,7 +1775,7 @@ libs:: $(DIST_CHROME_FILES) for f in $(DIST_CHROME_FILES); do \ dest=$(FINAL_TARGET)/chrome/`basename $$f`; \ $(RM) -f $$dest; \ - $(PERL) $(MOZILLA_DIR)/config/preprocessor.pl \ + $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \ $(srcdir)/$$f > $$dest; \ done diff --git a/mozilla/config/tests/unit-Expression.py b/mozilla/config/tests/unit-Expression.py new file mode 100644 index 00000000000..cb725448fa9 --- /dev/null +++ b/mozilla/config/tests/unit-Expression.py @@ -0,0 +1,63 @@ +import unittest + +import sys +import os.path +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +from Expression import Expression, Context + +class TestContext(unittest.TestCase): + """ + Unit tests for the Context class + """ + + def setUp(self): + self.c = Context() + self.c['FAIL'] = 'PASS' + + def test_string_literal(self): + """test string literal, fall-through for undefined var in a Context""" + self.assertEqual(self.c['PASS'], 'PASS') + + def test_variable(self): + """test value for defined var in the Context class""" + self.assertEqual(self.c['FAIL'], 'PASS') + + def test_in(self): + """test 'var in context' to not fall for fallback""" + self.assert_('FAIL' in self.c) + self.assert_('PASS' not in self.c) + +class TestExpression(unittest.TestCase): + """ + Unit tests for the Expression class + evaluate() is called with a context {FAIL: 'PASS'} + """ + + def setUp(self): + self.c = Context() + self.c['FAIL'] = 'PASS' + + def test_string_literal(self): + """Test for a string literal in an Expression""" + self.assertEqual(Expression('PASS').evaluate(self.c), 'PASS') + + def test_variable(self): + """Test for variable value in an Expression""" + self.assertEqual(Expression('FAIL').evaluate(self.c), 'PASS') + + def test_not(self): + """Test for the ! operator""" + self.assert_(Expression('!0').evaluate(self.c)) + self.assert_(not Expression('!1').evaluate(self.c)) + + def test_equals(self): + """ Test for the == operator""" + self.assert_(Expression('FAIL == PASS').evaluate(self.c)) + + def test_notequals(self): + """ Test for the != operator""" + self.assert_(Expression('FAIL != 1').evaluate(self.c)) + +if __name__ == '__main__': + unittest.main() diff --git a/mozilla/config/tests/unit-Preprocessor.py b/mozilla/config/tests/unit-Preprocessor.py new file mode 100644 index 00000000000..0dad7b9c195 --- /dev/null +++ b/mozilla/config/tests/unit-Preprocessor.py @@ -0,0 +1,376 @@ +import unittest + +from StringIO import StringIO +import os +import sys +import os.path +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) + +from Preprocessor import Preprocessor + +class NamedIO(StringIO): + def __init__(self, name, content): + self.name = name + StringIO.__init__(self, content) + +class TestPreprocessor(unittest.TestCase): + """ + Unit tests for the Context class + """ + + def setUp(self): + self.pp = Preprocessor() + self.pp.out = StringIO() + + def test_conditional_if_0(self): + f = NamedIO("conditional_if_0.in", """#if 0 +FAIL +#else +PASS +#endif +""") + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_string_value(self): + f = NamedIO("string_value.in", """#define FOO STRING +#if FOO +string value is true +#else +string value is false +#endif +""") + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "string value is false\n") + + def test_number_value(self): + f = NamedIO("string_value.in", """#define FOO 1 +#if FOO +number value is true +#else +number value is false +#endif +""") + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "number value is true\n") + + def test_conditional_if_0_elif_1(self): + f = NamedIO('conditional_if_0_elif_1.in', '''#if 0 +#elif 1 +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_conditional_if_1(self): + f = NamedIO('conditional_if_1.in', '''#if 1 +PASS +#else +FAILE +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_conditional_if_1_elif_1_else(self): + f = NamedIO('conditional_if_1_elif_1_else.in', '''#if 1 +PASS +#elif 1 +FAIL +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_conditional_if_1_if_1(self): + f = NamedIO('conditional_if_1_if_1.in', '''#if 1 +#if 1 +PASS +#else +FAIL +#endif +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_conditional_not_0(self): + f = NamedIO('conditional_not_0.in', '''#if !0 +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_conditional_not_1(self): + f = NamedIO('conditional_not_1.in', '''#if !1 +FAIL +#else +PASS +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_conditional_not_emptyval(self): + f = NamedIO('conditional_not_emptyval.in', '''#define EMPTYVAL +#if !EMPTYVAL +FAIL +#else +PASS +#endif +#if EMPTYVAL +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\nPASS\n") + + def test_conditional_not_nullval(self): + f = NamedIO('conditional_not_nullval.in', '''#define NULLVAL 0 +#if !NULLVAL +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_expand(self): + f = NamedIO('expand.in', '''#define ASVAR AS +#expand P__ASVAR__S +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_undef_defined(self): + f = NamedIO('undef_defined.in', '''#define BAR +#undef BAR +BAR +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "BAR\n") + + def test_undef_undefined(self): + f = NamedIO('undef_undefined.in', '''#undef VAR +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "") + + def test_filter_attemptSubstitution(self): + f = NamedIO('filter_attemptSubstitution.in', '''#filter attemptSubstitution +P@VAR@ASS +#unfilter attemptSubstitution +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_filter_slashslash(self): + f = NamedIO('filter_slashslash.in', '''#filter slashslash +PASS//FAIL // FAIL +#unfilter slashslash +PASS // PASS +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\nPASS // PASS\n") + + def test_filter_spaces(self): + f = NamedIO('filter_spaces.in', '''#filter spaces +You should see two nice ascii tables + +-+-+-+ + | | | | + +-+-+-+ +#unfilter spaces ++-+---+ +| | | ++-+---+ +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), """You should see two nice ascii tables ++-+-+-+ +| | | | ++-+-+-+ ++-+---+ +| | | ++-+---+ +""") + + def test_filter_substitution(self): + f = NamedIO('filter_substitution.in', '''#define VAR ASS +#filter substitution +P@VAR@ +#unfilter substitution +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_error(self): + f = NamedIO('error.in', '''#error spit this message out +''') + caught_msg = None + try: + self.pp.do_include(f) + except Preprocessor.Error, e: + caught_msg = e.args[0][-1] + self.assertEqual(caught_msg, 'spit this message out') + + def test_javascript_line(self): + f = NamedIO('javascript_line.js.in', '''// Line 1 +#if 0 +// line 3 +#endif +// line 5 +# comment +// line 7 +// line 8 +// line 9 +# another comment +// line 11 +#define LINE 1 +// line 13, given line number overwritten with 2 +''') + self.pp.do_include(f) + out = """// Line 1 +//@line 5 "CWDjavascript_line.js.in" +// line 5 +//@line 7 "CWDjavascript_line.js.in" +// line 7 +// line 8 +// line 9 +//@line 11 "CWDjavascript_line.js.in" +// line 11 +//@line 2 "CWDjavascript_line.js.in" +// line 13, given line number overwritten with 2 +""" + out = out.replace('CWD', os.getcwd() + os.path.sep) + self.assertEqual(self.pp.out.getvalue(), out) + + def test_literal(self): + f = NamedIO('literal.in', '''#literal PASS +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_var_directory(self): + f = NamedIO('var_directory.in', '''#ifdef DIRECTORY +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_var_file(self): + f = NamedIO('var_file.in', '''#ifdef FILE +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_var_if_0(self): + f = NamedIO('var_if_0.in', '''#define VAR 0 +#if VAR +FAIL +#else +PASS +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_var_if_0_elifdef(self): + f = NamedIO('var_if_0_elifdef.in', '''#if 0 +#elifdef FILE +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_var_if_0_elifndef(self): + f = NamedIO('var_if_0_elifndef.in', '''#if 0 +#elifndef VAR +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_var_ifdef_0(self): + f = NamedIO('var_ifdef_0.in', '''#define VAR 0 +#ifdef VAR +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_var_ifdef_undef(self): + f = NamedIO('var_ifdef_undef.in', '''#define VAR 0 +#undef VAR +#ifdef VAR +FAIL +#else +PASS +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_var_ifndef_0(self): + f = NamedIO('var_ifndef_0.in', '''#define VAR 0 +#ifndef VAR +FAIL +#else +PASS +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_var_ifndef_undef(self): + f = NamedIO('var_ifndef_undef.in', '''#define VAR 0 +#undef VAR +#ifndef VAR +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + + def test_var_line(self): + f = NamedIO('var_line.in', '''#ifdef LINE +PASS +#else +FAIL +#endif +''') + self.pp.do_include(f) + self.assertEqual(self.pp.out.getvalue(), "PASS\n") + +if __name__ == '__main__': + unittest.main() diff --git a/mozilla/intl/uconv/src/nsUNIXCharset.cpp b/mozilla/intl/uconv/src/nsUNIXCharset.cpp index 351d12a3cbd..39157e9fdc3 100644 --- a/mozilla/intl/uconv/src/nsUNIXCharset.cpp +++ b/mozilla/intl/uconv/src/nsUNIXCharset.cpp @@ -241,7 +241,7 @@ nsPlatformCharset::InitGetCharset(nsACString &oString) nsCAutoString propertyFile; // note: NS_LITERAL_CSTRING("unixcharset." OSARCH ".properties") does not compile on AIX propertyFile.AssignLiteral("unixcharset."); - propertyFile.Append(OSARCH); + propertyFile.AppendLiteral(NS_STRINGIFY(OSARCH)); propertyFile.AppendLiteral(".properties"); nsGREResProperties *info = new nsGREResProperties(propertyFile); NS_ASSERTION(info, "cannot create nsGREResProperties"); diff --git a/mozilla/layout/style/Makefile.in b/mozilla/layout/style/Makefile.in index 5cd055e7e2b..3a84deeed73 100644 --- a/mozilla/layout/style/Makefile.in +++ b/mozilla/layout/style/Makefile.in @@ -182,7 +182,7 @@ _FILES = \ GARBAGE += $(addprefix $(DIST)/bin/res/,$(_FILES)) FORMS_CSS_SRC = $(srcdir)/forms.css -PREPROCESS_FORMS_CSS = $(PERL) $(MOZILLA_DIR)/config/preprocessor.pl --marker=% $(DEFINES) $(ACDEFINES) $(FORMS_CSS_SRC) +PREPROCESS_FORMS_CSS = $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py --marker=% $(DEFINES) $(ACDEFINES) $(FORMS_CSS_SRC) $(DIST)/bin/res/forms.css $(DESTDIR)$(mozappdir)/res/forms.css: $(FORMS_CSS_SRC) Makefile if test ! -d $(@D); then rm -rf $(@D); $(NSINSTALL) -D $(@D); else true; fi diff --git a/mozilla/layout/style/forms.css b/mozilla/layout/style/forms.css index 0f0691bbd6a..3d0e01d1109 100644 --- a/mozilla/layout/style/forms.css +++ b/mozilla/layout/style/forms.css @@ -564,7 +564,7 @@ input[type="file"] > input[type="text"] { input[type="file"] { height: 2em; } } -%if OSARCH=="OS2" +%if OSARCH==OS2 input { font: medium serif; font-family: inherit } diff --git a/mozilla/other-licenses/branding/firefox/locales/Makefile.in b/mozilla/other-licenses/branding/firefox/locales/Makefile.in index 62c2cfacaf6..c46996f7f6d 100755 --- a/mozilla/other-licenses/branding/firefox/locales/Makefile.in +++ b/mozilla/other-licenses/branding/firefox/locales/Makefile.in @@ -47,9 +47,9 @@ DEFINES += -DAB_CD=$(AB_CD) -DMOZ_DISTRIBUTION_ID_UNQUOTED=$(MOZ_DISTRIBUTION_ID include $(topsrcdir)/config/rules.mk libs:: - @$(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) \ + @$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \ $(srcdir)/browserconfig.properties > $(FINAL_TARGET)/browserconfig.properties install:: - @$(PERL) $(topsrcdir)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) \ + @$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \ $(srcdir)/browserconfig.properties > $(DESTDIR)$(mozappdir)/browserconfig.properties diff --git a/mozilla/testing/mochitest/Makefile.in b/mozilla/testing/mochitest/Makefile.in index 5472e9c8140..e6e141ce2a1 100644 --- a/mozilla/testing/mochitest/Makefile.in +++ b/mozilla/testing/mochitest/Makefile.in @@ -81,7 +81,7 @@ TEST_DRIVER_PPARGS = -DBROWSER_PATH=$(browser_path) \ $(NULL) runtests.pl: runtests.pl.in - $(PERL) $(MOZILLA_DIR)/config/preprocessor.pl \ + $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \ $(TEST_DRIVER_PPARGS) $(DEFINES) $(ACDEFINES) $^ > $@ diff --git a/mozilla/toolkit/mozapps/downloads/src/Makefile.in b/mozilla/toolkit/mozapps/downloads/src/Makefile.in index c60451ddb7d..bf0d80f2d80 100644 --- a/mozilla/toolkit/mozapps/downloads/src/Makefile.in +++ b/mozilla/toolkit/mozapps/downloads/src/Makefile.in @@ -50,5 +50,5 @@ GARBAGE += nsHelperAppDlg.js include $(topsrcdir)/config/rules.mk nsHelperAppDlg.js: nsHelperAppDlg.js.in - $(PERL) $(MOZILLA_DIR)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $^ > $@ + $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $^ > $@ diff --git a/mozilla/toolkit/mozapps/extensions/src/Makefile.in b/mozilla/toolkit/mozapps/extensions/src/Makefile.in index b7d46362d9f..df22339cb97 100644 --- a/mozilla/toolkit/mozapps/extensions/src/Makefile.in +++ b/mozilla/toolkit/mozapps/extensions/src/Makefile.in @@ -50,5 +50,5 @@ GARBAGE += nsExtensionManager.js include $(topsrcdir)/config/rules.mk nsExtensionManager.js: nsExtensionManager.js.in - $(PERL) $(MOZILLA_DIR)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $^ > $@ + $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $^ > $@ diff --git a/mozilla/toolkit/mozapps/installer/packager.mk b/mozilla/toolkit/mozapps/installer/packager.mk index 5df607d1c40..5526417bc77 100644 --- a/mozilla/toolkit/mozapps/installer/packager.mk +++ b/mozilla/toolkit/mozapps/installer/packager.mk @@ -246,7 +246,7 @@ ifdef MOZ_PKG_REMOVALS MOZ_PKG_REMOVALS_GEN = removed-files $(MOZ_PKG_REMOVALS_GEN): $(MOZ_PKG_REMOVALS) Makefile Makefile.in - $(PERL) $(topsrcdir)/config/preprocessor.pl -Fsubstitution $(DEFINES) $(ACDEFINES) $(MOZ_PKG_REMOVALS) > $(MOZ_PKG_REMOVALS_GEN) + $(PYTHON) $(topsrcdir)/config/Preprocessor.py -Fsubstitution $(DEFINES) $(ACDEFINES) $(MOZ_PKG_REMOVALS) > $(MOZ_PKG_REMOVALS_GEN) endif GARBAGE += $(DIST)/$(PACKAGE) $(PACKAGE) diff --git a/mozilla/toolkit/mozapps/update/src/Makefile.in b/mozilla/toolkit/mozapps/update/src/Makefile.in index 267c5c7b85e..67deb003b3f 100644 --- a/mozilla/toolkit/mozapps/update/src/Makefile.in +++ b/mozilla/toolkit/mozapps/update/src/Makefile.in @@ -58,7 +58,7 @@ endif include $(topsrcdir)/config/rules.mk nsUpdateService.js: nsUpdateService.js.in - $(PERL) $(MOZILLA_DIR)/config/preprocessor.pl $(DEFINES) $(ACDEFINES) $^ > $@ + $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $^ > $@ ifdef ENABLE_TESTS check:: nsUpdateService.js