Merge b-s to m-c.

This commit is contained in:
Kyle Huey 2011-08-10 11:12:30 -04:00
commit 0dbd15635f
12 changed files with 839 additions and 42 deletions

View File

@ -1,3 +1,4 @@
# -*- makefile -*-
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -21,6 +22,7 @@
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Joey Armstrong <joey@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
@ -49,7 +51,15 @@ ifdef USE_ELF_HACK
DIRS = elfhack
endif
ifdef ENABLE_TESTS
ifeq (,$(filter WINNT OS2,$(OS_ARCH)))
DIRS += test
endif # WIN
endif # ENABLE_TESTS
include $(topsrcdir)/config/rules.mk
libs:: $(srcdir)/run-mozilla.sh
$(INSTALL) $< $(DIST)/bin
# EOF

View File

@ -0,0 +1,76 @@
# -*- makefile -*-
#
# ***** 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.org code.
#
# The Initial Developer of the Original Code is Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Joey Armstrong <joey@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of 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 *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
##################################################
## Gather a list of tests, generate timestamp deps
##################################################
TS=.ts
ifneq (,$(findstring check,$(MAKECMDGOALS)))
allsrc = $(wildcard $(srcdir)/*)
tests2run = $(notdir $(filter %.tpl,$(allsrc)))
check_targets += $(addprefix $(TS)/,$(tests2run))
endif
check:: $(TS) $(check_targets)
#############################################
# Only invoke tests when sources have changed
#############################################
$(TS)/%: $(srcdir)/%
$(PERL) $(srcdir)/runtest $<
@touch $@
#####################################################
## Extra dep needed to synchronize parallel execution
#####################################################
$(TS): $(TS)/.done
$(TS)/.done:
$(MKDIR) -p $(dir $@)
touch $@
GARBAGE_DIRS += $(TS)
# EOF

95
build/unix/test/runtest Normal file
View File

@ -0,0 +1,95 @@
#!/usr/bin/env perl
###########################################################################
## Intent:
## Test::Harness is a testing wrapper that will process output
## from Test.pm module tests. Sumarize results, report stats
## and exit with overall status for the testing suites.
##
## Run testing suite:
## % make clean test
## % perl runtest
##
## Run Individual tests
## % perl tUtils0
###########################################################################
##----------------------------##
##---] CORE/CPAN INCLUDES [---##
##----------------------------##
use strict;
use warnings;
use Getopt::Long;
use Test::Harness;
##-------------------##
##---] EXPORTS [---##
##-------------------##
our $VERSION = qw(1.0);
use FindBin;
##-------------------##
##---] GLOBALS [---##
##-------------------##
my %argv;
##----------------##
##---] MAIN [---##
##----------------##
unless(GetOptions(\%argv,
qw(debug|d)
))
{
print "Usage: $0\n";
print " --debug Enable debug mode\n";
exit 1;
}
if (2 > $Test::Harness::VERSION)
{
print "Unit tests will not be run, Test::Harness is too old\n"
if ($argv{debug});
exit 0;
}
my @tests;
########################################
## Gather a list of tests if none passed
########################################
unless (@tests = @ARGV)
{
local *D;
opendir(D, '.');
while($_ = readdir(D)) {
next unless /.t\S+$/;
next if (/\.ts$/);
push(@tests, $_);
}
closedir(D);
}
###############################################
## Glob a list of tests when directories passed
###############################################
my @tmp;
foreach (@tests)
{
local *D;
if (-d $_ && (my $dir = $_))
{
opendir(D, $_) || die "opendir(D) failed: $!";
my @tests = grep(/\.t[^\.\s]+/o, readdir(D));
closedir(D);
push(@tmp, map{ join('/', $dir, $_); } @tests);
} else {
push(@tmp, $_);
}
}
@tests = @tmp;
print "$0: @ARGV\n" if ($argv{debug});
runtests(@tests);
# EOF

151
build/unix/test/uniq.tpl Normal file
View File

@ -0,0 +1,151 @@
#!/usr/bin/env perl
###########################################################################
## Intent: Unit test to verify uniq.pl
###########################################################################
##----------------------------##
##---] CORE/CPAN INCLUDES [---##
##----------------------------##
use strict;
use warnings;
use Cwd;
use Getopt::Long; # GetOptions
use Test;
sub BEGIN { plan tests => 12 }
##-------------------##
##---] EXPORTS [---##
##-------------------##
our $VERSION = qw(1.0);
##------------------##
##---] INCLUDES [---##
##------------------##
use FindBin;
##-------------------##
##---] GLOBALS [---##
##-------------------##
my %argv;
###########################################################################
## Intent: Run the arch command for output
##
## Returns:
## 0 on success
## $? command shell exit status
###########################################################################
sub uniq_pl
{
my $cmd = "perl $FindBin::RealBin/../uniq.pl @_";
print "Running: $cmd\n" if ($argv{debug});
my @tmp = `$cmd 2>&1`;
my @output = map{ split(/\s+/o); } @tmp;
wantarray ? @output : "@output";
} # uniq_pl
###########################################################################
## Intent:
##
## Returns:
## 0 on success
###########################################################################
sub check_uniq
{
print STDERR "Running test: check_uniq\n" if ($argv{debug});
# TODO: improve test, uniq.pl regexpr handling not quite right
my @todo =
(
[ '', qw(a a/b a/b/c) ] => [ qw(a a/b a/b/c) ],
[ '', qw(a/b a a/b/c) ] => [ qw(a/b a a/b/c) ],
[ '', qw(a/b/c a/b a) ] => [ qw(a/b/c a/b a) ],
[ '', qw(a a/b a/b/c a/b a) ] => [ qw(a a/b a/b/c) ], # dup removal
[ '-s', qw(a a/b a/b/c) ] => [ qw(a a/b a/b/c) ],
[ '-s', qw(a/b a a/b/c) ] => [ qw(a a/b a/b/c) ],
[ '-s', qw(a/b/c a/b a) ] => [ qw(a a/b a/b/c) ],
[ '-r', qw(a a/b a/b/c) ] => [ qw(a) ],
[ '-r', qw(a/b a a/b/c) ] => [ qw(a/b a) ],
[ '-r', qw(a/b/c a/b a) ] => [ qw(a/b/c a/b a) ],
[ '-r', qw(. .. a/b ../a aa/bb) ] => [ qw(. .. a/b aa/bb) ],
[ '-r', qw(.. a/b ../a . aa/bb) ] => [ qw(.. a/b . aa/bb) ],
);
my $ct=1;
while (@todo)
{
my ($a, $b) = splice(@todo, 0, 2);
my @args = @{ $a };
my @exp = @{ $b };
my @out = uniq_pl(@args);
# compareExp(\@out, \@exp, 'Failed on line ' . __LINE__ . ", dataset $ct");
if (0 && 7 == $ct)
{
print STDERR "\n";
print STDERR map{ "args> $_\n" }@args;
print STDERR "\n";
print STDERR map{ "exp> $_\n" }@exp;
print STDERR "\n";
print STDERR map{ "out> $_\n" }@out;
}
ok("@out", "@exp", 'Failed on line ' . __LINE__ . ", dataset $ct");
$ct++;
}
} # check_uniq
###########################################################################
## Intent: Smoke tests for the unittests module
###########################################################################
sub smoke
{
print STDERR "Running test: smoke()\n" if ($argv{debug});
} # smoke()
###########################################################################
## Intent: Intitialize global test objects and consts
###########################################################################
sub init
{
print "Running: init()\n" if ($argv{debug});
# testplan(24, 0);
} # init()
##----------------##
##---] MAIN [---##
##----------------##
unless(GetOptions(\%argv,
qw(
debug|d
manual
test=s@
verbose
)))
{
print "USAGE: $0\n";
print " --debug Enable script debug mode\n";
print " --fail Force a testing failure condition\n";
print " --manual Also run disabled tests\n";
print " --smoke Run smoke tests then exit\n";
print " --test Run a list of tests by function name\n";
print " --verbose Enable script verbose mode\n";
exit 1;
}
init();
testbyname(@{ $argv{test} }) if ($argv{test});
smoke();
check_uniq();
ok(1, 0, 'Forced failure by command line arg --fail') if ($argv{fail});
# EOF

View File

@ -22,6 +22,7 @@
#
# Contributor(s):
# Christopher Seawood <cls@seawood.org>
# Joey Armstrong <joey@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
@ -37,27 +38,88 @@
#
# ***** END LICENSE BLOCK *****
use Getopt::Std;
##----------------------------##
##---] CORE/CPAN INCLUDES [---##
##----------------------------##
use strict;
use warnings;
use Getopt::Long;
getopts('rs');
$regexp = 1 if (defined($opt_r));
$sort = 1 if (defined($opt_s));
##-------------------##
##---] EXPORTS [---##
##-------------------##
our $VERSION = qw(1.1);
undef @out;
if ($sort) {
@in = sort @ARGV;
} else {
@in = @ARGV;
##-------------------##
##---] GLOBALS [---##
##-------------------##
my %argv;
my $modver = $Getopt::Long::VERSION || 0;
my $isOldGetopt = ($modver eq '2.25') ? 1 : 0;
###########################################################################
## Intent: Script init function
###########################################################################
sub init
{
if ($isOldGetopt)
{
# mozilla.build/mingw perl in need of an upgrade
# emulate Getopt::Long switch|short:init
foreach (qw(debug regex sort))
{
if (defined($argv{$_}))
{
$argv{$_} ||= 1;
}
}
}
} # init
##----------------##
##---] MAIN [---##
##----------------##
my @args = ($isOldGetopt)
? qw(debug|d regex|r sort|s)
: qw(debug|d:1 regex|r:1 sort|s:1)
;
unless(GetOptions(\%argv, @args))
{
print "Usage: $0\n";
print " --sort Sort list elements early\n";
print " --regex Exclude subdirs by pattern\n";
}
foreach $d (@in) {
if ($regexp) {
$found = 0;
foreach $dir (@out) {
$found++, last if ($d =~ m/^$dir\// || $d eq $dir);
init();
my $debug = $argv{debug} || 0;
my %seen;
my @out;
my @in = ($argv{sort}) ? sort @ARGV : @ARGV;
foreach my $d (@in)
{
next if ($seen{$d}++);
print " arg is $d\n" if ($debug);
if ($argv{regex})
{
my $found = 0;
foreach my $dir (@out)
{
my $dirM = quotemeta($dir);
$found++, last if ($d eq $dir || $d =~ m!^${dirM}\/!);
}
print "Adding $d\n" if ($debug && !$found);
push @out, $d if (!$found);
} else {
push @out, $d if (!grep(/^$d$/, @out));
print "Adding: $d\n" if ($debug);
push(@out, $d);
}
}
print "@out\n"
# EOF

View File

@ -1532,6 +1532,7 @@ $(XPIDL_GEN_DIR)/.done:
XPIDL_DEPS = \
$(topsrcdir)/xpcom/idl-parser/header.py \
$(topsrcdir)/xpcom/idl-parser/typelib.py \
$(topsrcdir)/xpcom/idl-parser/xpidl.py \
$(NULL)
@ -1547,9 +1548,13 @@ $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
ifndef NO_GEN_XPT
# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
$(REPORT_BUILD)
$(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$(@F).pp $(_VPATH_SRCS)
$(PYTHON_PATH) \
-I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \
-I$(topsrcdir)/xpcom/typelib/xpt/tools \
$(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(topsrcdir)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
# no need to link together if XPIDLSRCS contains only XPIDL_MODULE
ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))

View File

@ -22,6 +22,7 @@
#
# Contributor(s):
# Christopher Seawood <cls@seawood.org>
# Joey Armstrong <joey@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
@ -37,27 +38,88 @@
#
# ***** END LICENSE BLOCK *****
use Getopt::Std;
##----------------------------##
##---] CORE/CPAN INCLUDES [---##
##----------------------------##
use strict;
use warnings;
use Getopt::Long;
getopts('rs');
$regexp = 1 if (defined($opt_r));
$sort = 1 if (defined($opt_s));
##-------------------##
##---] EXPORTS [---##
##-------------------##
our $VERSION = qw(1.1);
undef @out;
if ($sort) {
@in = sort @ARGV;
} else {
@in = @ARGV;
##-------------------##
##---] GLOBALS [---##
##-------------------##
my %argv;
my $modver = $Getopt::Long::VERSION || 0;
my $isOldGetopt = ($modver eq '2.25') ? 1 : 0;
###########################################################################
## Intent: Script init function
###########################################################################
sub init
{
if ($isOldGetopt)
{
# mozilla.build/mingw perl in need of an upgrade
# emulate Getopt::Long switch|short:init
foreach (qw(debug regex sort))
{
if (defined($argv{$_}))
{
$argv{$_} ||= 1;
}
}
}
} # init
##----------------##
##---] MAIN [---##
##----------------##
my @args = ($isOldGetopt)
? qw(debug|d regex|r sort|s)
: qw(debug|d:1 regex|r:1 sort|s:1)
;
unless(GetOptions(\%argv, @args))
{
print "Usage: $0\n";
print " --sort Sort list elements early\n";
print " --regex Exclude subdirs by pattern\n";
}
foreach $d (@in) {
if ($regexp) {
$found = 0;
foreach $dir (@out) {
$found++, last if ($d =~ m/^$dir\// || $d eq $dir);
init();
my $debug = $argv{debug} || 0;
my %seen;
my @out;
my @in = ($argv{sort}) ? sort @ARGV : @ARGV;
foreach my $d (@in)
{
next if ($seen{$d}++);
print " arg is $d\n" if ($debug);
if ($argv{regex})
{
my $found = 0;
foreach my $dir (@out)
{
my $dirM = quotemeta($dir);
$found++, last if ($d eq $dir || $d =~ m!^${dirM}\/!);
}
print "Adding $d\n" if ($debug && !$found);
push @out, $d if (!$found);
} else {
push @out, $d if (!grep(/^$d$/, @out));
print "Adding: $d\n" if ($debug);
push(@out, $d);
}
}
print "@out\n"
# EOF

View File

@ -1532,6 +1532,7 @@ $(XPIDL_GEN_DIR)/.done:
XPIDL_DEPS = \
$(topsrcdir)/xpcom/idl-parser/header.py \
$(topsrcdir)/xpcom/idl-parser/typelib.py \
$(topsrcdir)/xpcom/idl-parser/xpidl.py \
$(NULL)
@ -1547,9 +1548,13 @@ $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
ifndef NO_GEN_XPT
# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
$(REPORT_BUILD)
$(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$(@F).pp $(_VPATH_SRCS)
$(PYTHON_PATH) \
-I$(topsrcdir)/other-licenses/ply \
-I$(topsrcdir)/xpcom/idl-parser \
-I$(topsrcdir)/xpcom/typelib/xpt/tools \
$(topsrcdir)/xpcom/idl-parser/typelib.py --cachedir=$(topsrcdir)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
# no need to link together if XPIDLSRCS contains only XPIDL_MODULE
ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))

View File

@ -141,10 +141,14 @@ struct RuleValue : RuleSelectorPair {
// Uses any of the sets of ops below.
struct RuleHashTableEntry : public PLDHashEntryHdr {
// If you add members that have heap allocated memory be sure to change the
// logic in RuleHashTableSizeOfEnumerator.
nsTArray<RuleValue> mRules;
};
struct RuleHashTagTableEntry : public RuleHashTableEntry {
// If you add members that have heap allocated memory be sure to change the
// logic in RuleHash::SizeOf.
nsCOMPtr<nsIAtom> mTag;
};
@ -734,6 +738,12 @@ RuleHash::SizeOf() const
n += mUniversalRules.SizeOf();
const PLArena* current = &mArena.first;
while (current) {
n += current->limit - current->base;
current = current->next;
}
return n;
}

314
xpcom/idl-parser/typelib.py Normal file
View File

@ -0,0 +1,314 @@
#!/usr/bin/env python
# typelib.py - Generate XPCOM typelib files from IDL.
#
# ***** 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 pyxpidl.
#
# The Initial Developer of the Original Code is the Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2011
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Kyle Huey <khuey@kylehuey.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of 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 *****
"""Generate an XPIDL typelib for the IDL files specified on the command line"""
import xpidl, xpt
# A map of xpidl.py types to xpt.py types
TypeMap = {
# nsresult is not strictly an xpidl.py type, but it's useful here
'nsresult': xpt.Type.Tags.uint32,
# builtins
'boolean': xpt.Type.Tags.boolean,
'void': xpt.Type.Tags.void,
'octet': xpt.Type.Tags.uint8,
'short': xpt.Type.Tags.int16,
'long': xpt.Type.Tags.int32,
'long long': xpt.Type.Tags.int64,
'unsigned short': xpt.Type.Tags.uint16,
'unsigned long': xpt.Type.Tags.uint32,
'unsigned long long': xpt.Type.Tags.uint64,
'float': xpt.Type.Tags.float,
'double': xpt.Type.Tags.double,
'char': xpt.Type.Tags.char,
'string': xpt.Type.Tags.char_ptr,
'wchar': xpt.Type.Tags.wchar_t,
'wstring': xpt.Type.Tags.wchar_t_ptr,
# special types
'nsid': xpt.Type.Tags.nsIID,
'domstring': xpt.Type.Tags.DOMString,
'astring': xpt.Type.Tags.AString,
'utf8string': xpt.Type.Tags.UTF8String,
'cstring': xpt.Type.Tags.CString,
'jsval': xpt.Type.Tags.jsval
}
# XXXkhuey dipper types should go away (bug 677784)
def isDipperType(type):
return type == xpt.Type.Tags.DOMString or type == xpt.Type.Tags.AString or type == xpt.Type.Tags.CString or type == xpt.Type.Tags.UTF8String
def build_interface(iface, ifaces):
def get_type(type, calltype, iid_is=None, size_is=None):
""" Return the appropriate xpt.Type object for this param """
if isinstance(type, xpidl.Typedef):
type = type.realtype
if isinstance(type, xpidl.Builtin):
if type.name == 'string' and size_is != None:
return xpt.StringWithSizeType(size_is, size_is)
elif type.name == 'wstring' and size_is != None:
return xpt.WideStringWithSizeType(size_is, size_is)
else:
tag = TypeMap[type.name]
isPtr = (tag == xpt.Type.Tags.char_ptr or tag == xpt.Type.Tags.wchar_t_ptr)
return xpt.SimpleType(tag,
pointer=isPtr,
#XXXkhuey unique_pointer is completely unused (bug 677787.)
reference=False)
if isinstance(type, xpidl.Array):
return xpt.ArrayType(get_type(type.type, calltype), size_is,
#XXXkhuey length_is duplicates size_is (bug 677788),
size_is)
if isinstance(type, xpidl.Interface) or isinstance(type, xpidl.Forward):
xptiface = None
for i in ifaces:
if i.name == type.name:
xptiface = i
if not xptiface:
xptiface = xpt.Interface(name=type.name)
ifaces.append(xptiface)
return xpt.InterfaceType(xptiface)
if isinstance(type, xpidl.Native):
if type.specialtype:
# XXXkhuey jsval is marked differently in the typelib and in the headers :-(
isPtr = (type.isPtr(calltype) or type.isRef(calltype)) and not type.specialtype == 'jsval'
isRef = type.isRef(calltype) and not type.specialtype == 'jsval'
return xpt.SimpleType(TypeMap[type.specialtype],
pointer=isPtr,
#XXXkhuey unique_pointer is completely unused
reference=isRef)
elif iid_is != None:
return xpt.InterfaceIsType(iid_is)
else:
# void ptr
return xpt.SimpleType(TypeMap['void'],
pointer=True,
#XXXkhuey unique_pointer is completely unused
reference=False)
raise Exception("Unknown type!")
def get_nsresult():
return xpt.SimpleType(TypeMap['nsresult'])
def build_nsresult_param():
return xpt.Param(get_nsresult())
def get_result_type(m):
if not m.notxpcom:
return get_nsresult()
return get_type(m.realtype, '')
def build_result_param(m):
return xpt.Param(get_result_type(m))
def build_retval_param(m):
type = get_type(m.realtype, 'out')
if isDipperType(type.tag):
# NB: The retval bit needs to be set here, contrary to what the
# xpt spec says.
return xpt.Param(type, in_=True, retval=True, dipper=True)
return xpt.Param(type, in_=False, out=True, retval=True)
def build_attr_param(a, getter=False, setter=False):
if not (getter or setter):
raise Exception("Attribute param must be for a getter or a setter!")
type = get_type(a.realtype, getter and 'out' or 'in')
if setter:
return xpt.Param(type)
else:
if isDipperType(type.tag):
# NB: The retval bit needs to be set here, contrary to what the
# xpt spec says.
return xpt.Param(type, in_=True, retval=True, dipper=True)
return xpt.Param(type, in_=False, out=True, retval=True)
if iface.namemap is None:
raise Exception("Interface was not resolved.")
consts = []
methods = []
def build_const(c):
consts.append(xpt.Constant(c.name, get_type(c.basetype, ''), c.getValue()))
def build_method(m):
params = []
def build_param(p):
def findattr(p, attr):
if hasattr(p, attr) and getattr(p, attr):
for i, param in enumerate(m.params):
if param.name == getattr(p, attr):
return i
return None
iid_is = findattr(p, 'iid_is')
size_is = findattr(p, 'size_is')
in_ = p.paramtype.count("in")
out = p.paramtype.count("out")
dipper = False
type = get_type(p.realtype, p.paramtype, iid_is=iid_is, size_is=size_is)
if out and isDipperType(type.tag):
out = False
dipper = True
return xpt.Param(type, in_, out, p.retval, p.shared, dipper, p.optional)
for p in m.params:
params.append(build_param(p))
if not m.notxpcom and m.realtype.name != 'void':
params.append(build_retval_param(m))
methods.append(xpt.Method(m.name, build_result_param(m), params,
getter=False, setter=False, notxpcom=m.notxpcom,
constructor=False, hidden=m.noscript,
optargc=m.optional_argc,
implicit_jscontext=m.implicit_jscontext))
def build_attr(a):
# Write the getter
methods.append(xpt.Method(a.name, build_nsresult_param(),
[build_attr_param(a, getter=True)],
getter=True, setter=False, notxpcom=a.notxpcom,
constructor=False, hidden=a.noscript,
optargc=False,
implicit_jscontext=a.implicit_jscontext))
# And maybe the setter
if not a.readonly:
methods.append(xpt.Method(a.name, build_nsresult_param(),
[build_attr_param(a, setter=True)],
getter=False, setter=True, notxpcom=a.notxpcom,
constructor=False, hidden=a.noscript,
optargc=False,
implicit_jscontext=a.implicit_jscontext))
for member in iface.members:
if isinstance(member, xpidl.ConstMember):
build_const(member)
elif isinstance(member, xpidl.Attribute):
build_attr(member)
elif isinstance(member, xpidl.Method):
build_method(member)
elif isinstance(member, xpidl.CDATA):
pass
else:
raise Exception("Unexpected interface member: %s" % member)
parent = None
if iface.base:
for i in ifaces:
if i.name == iface.base:
parent = i
if not parent:
parent = xpt.Interface(name=iface.base)
ifaces.append(parent)
return xpt.Interface(iface.name, iface.attributes.uuid, methods=methods,
constants=consts, resolved=True, parent=parent,
scriptable=iface.attributes.scriptable,
function=iface.attributes.function,
builtinclass=iface.attributes.builtinclass)
def write_typelib(idl, fd, filename):
""" Generate the typelib. """
# We only care about interfaces
ifaces = []
for p in idl.productions:
if p.kind == 'interface':
ifaces.append(build_interface(p, ifaces))
typelib = xpt.Typelib(interfaces=ifaces)
typelib.writefd(fd)
if __name__ == '__main__':
from optparse import OptionParser
o = OptionParser()
o.add_option('-I', action='append', dest='incdirs', default=['.'],
help="Directory to search for imported files")
o.add_option('--cachedir', dest='cachedir', default=None,
help="Directory in which to cache lex/parse tables.")
o.add_option('-o', dest='outfile', default=None,
help="Output file")
o.add_option('-d', dest='depfile', default=None,
help="Generate a make dependency file")
options, args = o.parse_args()
file, = args
if options.cachedir is not None:
if not os.path.isdir(options.cachedir):
os.mkdir(options.cachedir)
sys.path.append(options.cachedir)
if options.depfile is not None and options.outfile is None:
print >>sys.stderr, "-d requires -o"
sys.exit(1)
if options.outfile is not None:
outfd = open(options.outfile, 'wb')
closeoutfd = True
else:
raise "typelib generation requires an output file"
p = xpidl.IDLParser(outputdir=options.cachedir)
idl = p.parse(open(file).read(), filename=file)
idl.resolve(options.incdirs, p)
write_typelib(idl, outfd, file)
if closeoutfd:
outfd.close()
if options.depfile is not None:
depfd = open(options.depfile, 'w')
deps = [dep.replace('\\', '/') for dep in idl.deps]
print >>depfd, "%s: %s" % (options.outfile, " ".join(deps))

View File

@ -456,6 +456,12 @@ class Native(object):
return self.modifier == 'ref'
def isPtr(self, calltype):
return self.modifier == 'ptr' or (self.modifier == 'ref' and self.specialtype == 'jsval' and calltype == 'out')
def isRef(self, calltype):
return self.modifier == 'ref' and not (self.specialtype == 'jsval' and calltype == 'out')
def nativeType(self, calltype, const=False, shared=False):
if shared:
if calltype != 'out':
@ -465,14 +471,10 @@ class Native(object):
if self.specialtype is not None and calltype == 'in':
const = True
if self.modifier == 'ptr':
m = '*' + (calltype != 'in' and '*' or '')
elif self.modifier == 'ref':
# jsval outparams are odd, for compatibility with existing code
if self.specialtype == 'jsval' and calltype == 'out':
m = '*'
else:
m = '& '
if self.isRef(calltype):
m = '& '
elif self.isPtr(calltype):
m = '*' + ((self.modifier == 'ptr' and calltype != 'in') and '*' or '')
else:
m = calltype != 'in' and '*' or ''
return "%s%s %s" % (const and 'const ' or '', self.nativename, m)

View File

@ -145,6 +145,8 @@ class Type(object):
self.pointer = pointer
self.unique_pointer = unique_pointer
self.reference = reference
if reference and not pointer:
raise Exception("If reference is True pointer must be True too")
@staticmethod
def decodeflags(byte):
@ -517,6 +519,7 @@ class Param(object):
flags. Params default to "in".
"""
self.type = type
self.in_ = in_
self.out = out
@ -642,6 +645,8 @@ class Method(object):
self.optargc = optargc
self.implicit_jscontext = implicit_jscontext
self.params = list(params)
if result and not isinstance(result, Param):
raise Exception("result must be a Param!")
self.result = result
def read_params(self, typelib, map, data_pool, offset, num_args):