blob: 0b86ea17ed0b70acd2f4bb1eb204e808b42e8ed6 [file] [log] [blame]
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Convert Windows-style export files into a single Unix-style linker
# script, applying any necessary preprocessing.
from __future__ import absolute_import
import itertools
import re
import sys
from StringIO import StringIO
from mozbuild.preprocessor import Preprocessor
from mozbuild.util import FileAvoidWrite
def preprocess_file(pp, deffile):
pp.out = StringIO()
with open(deffile, 'rU') as input:
pp.do_include(input, False)
return pp.out.getvalue().splitlines()
# NSS .def files serve multiple masters, as this copied comment indicates:
#
# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
# 1. For all unix platforms, the string ";-" means "remove this line"
# 2. For all unix platforms, the string " DATA " will be removed from any
# line on which it occurs.
# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
# On AIX, lines containing ";+" will be removed.
# 4. For all unix platforms, the string ";;" will have the ";;" removed.
# 5. For all unix platforms, after the above processing has taken place,
# all characters after the first ";" on the line will be removed.
# And for AIX, the first ";" will also be removed.
# This file is passed directly to windows. Since ';' is a comment, all UNIX
# directives are hidden behind ";", ";+", and ";-"
#
# We don't care about rule 1, as that mainly serves to eliminate LIBRARY
# and EXPORTS lines. Our symbol extraction routines handle DATA, so we
# don't need to bother with rule 2. We don't want to enforce rule 3, as
# we know how to eliminate comments. ';+' also tends to hide Unix
# linker-script specific things, which we don't want to deal with here.
# Rule 5 is also unnecessary; later comment-aware processing will deal
# with that.
#
# We need to handle rule 4, since ';;' often hides things marked with DATA.
def nss_preprocess_file(deffile):
with open(deffile, 'r') as input:
for line in input:
yield line.replace(';;', '')
COMMENT = re.compile(';.*')
def extract_symbols(lines):
# Filter comments.
nocomments = iter(COMMENT.sub('', s).strip() for s in lines)
lines = iter(s for s in nocomments if len(s))
exports = itertools.dropwhile(lambda s: 'EXPORTS' not in s, lines)
symbols = set()
for line in exports:
if 'EXPORTS' in line:
# Handle the case where symbols are specified along with EXPORT.
fields = line.split()[1:]
if len(fields) == 0:
continue
else:
fields = line.split()
# We don't support aliases, and we only support the DATA keyword on
# symbols. But since aliases can also be specified as 'SYM=ALIAS'
# with no whitespace, we need extra checks on the original symbol.
if '=' in fields[0]:
raise BaseException, 'aliases are not supported (%s)' % line
if len(fields) == 1:
pass
elif len(fields) != 2 or fields[1] != 'DATA':
raise BaseException, 'aliases and keywords other than DATA are not supported (%s)' % line
symbols.add(fields[0])
return symbols
def main(args):
pp = Preprocessor()
optparser = pp.getCommandLineParser()
optparser.add_option('--nss-file', action='append',
type='string', dest='nss_files', default=[],
help='Specify a .def file that should have NSS\'s processing rules applied to it')
options, deffiles = optparser.parse_args(args)
symbols = set()
for f in options.nss_files:
symbols |= extract_symbols(nss_preprocess_file(f))
for f in deffiles:
# Start each deffile off with a clean slate.
defpp = pp.clone()
symbols |= extract_symbols(preprocess_file(defpp, f))
script = """{
global:
%s
local:
*;
};
"""
with FileAvoidWrite(options.output) as f:
f.write(script % '\n '.join("%s;" % s for s in sorted(symbols)))
if __name__ == '__main__':
main(sys.argv[1:])