Bug 578478: Switch to pyxpidl for header generation. Parts by bsmedberg, with r=jorendorff,khuey, and parts by me, with r=bsmedberg
authorKyle Huey <khuey@kylehuey.com>
Tue, 19 Jul 2011 14:46:25 -0700
changeset 73175 85f7679fd5eb481ea62fa3a047136969c3660586
parent 73174 398402eabdb09416fb7d9755f5cb06af15e73c1d
child 73176 e5a6f94154c746e05dbd9404595a6746467e257b
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjorendorff, khuey, and, bsmedberg
bugs578478
milestone8.0a1
Bug 578478: Switch to pyxpidl for header generation. Parts by bsmedberg, with r=jorendorff,khuey, and parts by me, with r=bsmedberg
config/rules.mk
embedding/browser/webBrowser/nsIWebBrowserChrome3.idl
js/src/config/rules.mk
xpcom/idl-parser/header.py
xpcom/idl-parser/xpidl.py
xpcom/idl-parser/xpidllex.py
xpcom/idl-parser/xpidlyacc.py
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -377,17 +377,17 @@ endif
 
 LIBOBJS			:= $(addprefix \", $(OBJS))
 LIBOBJS			:= $(addsuffix \", $(LIBOBJS))
 
 ifndef MOZ_AUTO_DEPS
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
 MDDEPFILES		= $(addprefix $(MDDEPDIR)/,$(OBJS:.$(OBJ_SUFFIX)=.pp))
 ifndef NO_GEN_XPT
-MDDEPFILES		+= $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.xpt))
+MDDEPFILES		+= $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp))
 endif
 endif
 endif
 
 ALL_TRASH = \
 	$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
 	$(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \
 	$(OBJS:.$(OBJ_SUFFIX)=.i) \
@@ -1525,28 +1525,36 @@ endif
 # warn against overriding existing .h file. 
 $(XPIDL_GEN_DIR)/.done:
 	$(MKDIR) -p $(XPIDL_GEN_DIR)
 	@$(TOUCH) $@
 
 # don't depend on $(XPIDL_GEN_DIR), because the modification date changes
 # with any addition to the directory, regenerating all .h files -> everything.
 
-$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
+XPIDL_DEPS = \
+  $(topsrcdir)/xpcom/idl-parser/header.py \
+  $(topsrcdir)/xpcom/idl-parser/xpidl.py \
+  $(NULL)
+
+$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
 	$(REPORT_BUILD)
-	$(ELOG) $(XPIDL_COMPILE) -m header -w $(XPIDL_FLAGS) -o $(XPIDL_GEN_DIR)/$* $(_VPATH_SRCS)
+	$(PYTHON) $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/other-licenses/ply \
+	  -I$(topsrcdir)/xpcom/idl-parser \
+	  $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(topsrcdir)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
 	  then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
 
 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
 	$(REPORT_BUILD)
-	$(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$*.pp $(_VPATH_SRCS)
+	$(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$(@F).pp $(_VPATH_SRCS)
 
 # no need to link together if XPIDLSRCS contains only XPIDL_MODULE
 ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
 $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) $(GLOBAL_DEPS)
 	$(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS))
 endif # XPIDL_MODULE.xpt != XPIDLSRCS
 
 libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt
--- a/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl
+++ b/embedding/browser/webBrowser/nsIWebBrowserChrome3.idl
@@ -1,65 +1,66 @@
-/* ***** 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) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Margaret Leibovic <margaret.leibovic@gmail.com>
- *
- * 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 ***** */
-#include "nsIWebBrowserChrome2.idl"
-#include "nsIURI.idl"
-#include "nsIDOMNode.idl"
-
-/**
- * nsIWebBrowserChrome3 is an extension to nsIWebBrowserChrome2.
- */
-[scriptable, uuid(7f2aa813-b250-4e46-afeb-97b1e91bc9a5)]
-interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2
-{
-  /**
-   * Determines the appropriate target for a link.
-   *
-   * @param originalTarget
-   *        The original link target.
-   * @param linkURI
-   *        Link destination URI.
-   * @param aDOMNode
-   *        Link DOM node.
-   * @param isAppTab
-   *        Whether or not the link is in an app tab.
-   * @returns A new link target, if appropriate.
-   *          Otherwise returns originalTarget.
-   */
-  AString onBeforeLinkTraversal(in AString originalTarget,
-                                in nsIURI linkURI,
-                                in nsIDOMNode linkNode,
-                                in PRBool isAppTab);
-};
+/* ***** 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) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Margaret Leibovic <margaret.leibovic@gmail.com>
+ *
+ * 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 ***** */
+
+#include "nsIWebBrowserChrome2.idl"
+#include "nsIURI.idl"
+#include "nsIDOMNode.idl"
+
+/**
+ * nsIWebBrowserChrome3 is an extension to nsIWebBrowserChrome2.
+ */
+[scriptable, uuid(7f2aa813-b250-4e46-afeb-97b1e91bc9a5)]
+interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2
+{
+  /**
+   * Determines the appropriate target for a link.
+   *
+   * @param originalTarget
+   *        The original link target.
+   * @param linkURI
+   *        Link destination URI.
+   * @param aDOMNode
+   *        Link DOM node.
+   * @param isAppTab
+   *        Whether or not the link is in an app tab.
+   * @returns A new link target, if appropriate.
+   *          Otherwise returns originalTarget.
+   */
+  AString onBeforeLinkTraversal(in AString originalTarget,
+                                in nsIURI linkURI,
+                                in nsIDOMNode linkNode,
+                                in PRBool isAppTab);
+};
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -377,17 +377,17 @@ endif
 
 LIBOBJS			:= $(addprefix \", $(OBJS))
 LIBOBJS			:= $(addsuffix \", $(LIBOBJS))
 
 ifndef MOZ_AUTO_DEPS
 ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS))
 MDDEPFILES		= $(addprefix $(MDDEPDIR)/,$(OBJS:.$(OBJ_SUFFIX)=.pp))
 ifndef NO_GEN_XPT
-MDDEPFILES		+= $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.xpt))
+MDDEPFILES		+= $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp))
 endif
 endif
 endif
 
 ALL_TRASH = \
 	$(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
 	$(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \
 	$(OBJS:.$(OBJ_SUFFIX)=.i) \
@@ -1525,28 +1525,36 @@ endif
 # warn against overriding existing .h file. 
 $(XPIDL_GEN_DIR)/.done:
 	$(MKDIR) -p $(XPIDL_GEN_DIR)
 	@$(TOUCH) $@
 
 # don't depend on $(XPIDL_GEN_DIR), because the modification date changes
 # with any addition to the directory, regenerating all .h files -> everything.
 
-$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
+XPIDL_DEPS = \
+  $(topsrcdir)/xpcom/idl-parser/header.py \
+  $(topsrcdir)/xpcom/idl-parser/xpidl.py \
+  $(NULL)
+
+$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
 	$(REPORT_BUILD)
-	$(ELOG) $(XPIDL_COMPILE) -m header -w $(XPIDL_FLAGS) -o $(XPIDL_GEN_DIR)/$* $(_VPATH_SRCS)
+	$(PYTHON) $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/other-licenses/ply \
+	  -I$(topsrcdir)/xpcom/idl-parser \
+	  $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(DEPTH)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
 	  then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
 
 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
 	$(REPORT_BUILD)
-	$(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$*.pp $(_VPATH_SRCS)
+	$(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$(@F).pp $(_VPATH_SRCS)
 
 # no need to link together if XPIDLSRCS contains only XPIDL_MODULE
 ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
 $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS)) $(GLOBAL_DEPS)
 	$(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS))
 endif # XPIDL_MODULE.xpt != XPIDLSRCS
 
 libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt
--- a/xpcom/idl-parser/header.py
+++ b/xpcom/idl-parser/header.py
@@ -53,38 +53,50 @@ else:
         pass
 
 def firstCap(str):
     return str[0].upper() + str[1:]
 
 def attributeParamName(a):
     return "a" + firstCap(a.name)
 
+def attributeParamNames(a):
+    l = [attributeParamName(a)]
+    if a.implicit_jscontext:
+        l.insert(0, "cx")
+    return ", ".join(l)
+
 def attributeNativeName(a, getter):
     binaryname = a.binaryname is not None and a.binaryname or firstCap(a.name)
     return "%s%s" % (getter and 'Get' or 'Set', binaryname)
 
 def attributeReturnType(a, macro):
     """macro should be NS_IMETHOD or NS_IMETHODIMP"""
     if (a.nostdcall):
         return macro == "NS_IMETHOD" and "virtual nsresult" or "nsresult"
     else:
         return macro
 
 def attributeParamlist(a, getter):
-    return "%s%s" % (a.realtype.nativeType(getter and 'out' or 'in'),
-                     attributeParamName(a))
+    l = ["%s%s" % (a.realtype.nativeType(getter and 'out' or 'in'),
+                   attributeParamName(a))]
+    if a.implicit_jscontext:
+        l.insert(0, "JSContext* cx")
+
+    return ", ".join(l)
 
 def attributeAsNative(a, getter):
         scriptable = a.isScriptable() and "NS_SCRIPTABLE " or ""
+        deprecated = a.deprecated and "NS_DEPRECATED " or ""
         params = {'scriptable': scriptable,
+                  'deprecated': deprecated,
                   'returntype': attributeReturnType(a, 'NS_IMETHOD'),
                   'binaryname': attributeNativeName(a, getter),
                   'paramlist': attributeParamlist(a, getter)}
-        return "%(scriptable)s%(returntype)s %(binaryname)s(%(paramlist)s)" % params
+        return "%(deprecated)s%(scriptable)s%(returntype)s %(binaryname)s(%(paramlist)s)" % params
 
 def methodNativeName(m):
     return m.binaryname is not None and m.binaryname or firstCap(m.name)
 
 def methodReturnType(m, macro):
     """macro should be NS_IMETHOD or NS_IMETHODIMP"""
     if m.nostdcall and m.notxpcom:
         return "%s%s" % (macro == "NS_IMETHOD" and "virtual " or "",
@@ -97,49 +109,62 @@ def methodReturnType(m, macro):
         return macro
 
 def methodAsNative(m):
     scriptable = m.isScriptable() and "NS_SCRIPTABLE " or ""
 
     return "%s%s %s(%s)" % (scriptable,
                             methodReturnType(m, 'NS_IMETHOD'),
                             methodNativeName(m),
-                            paramlistAsNative(m.params,
-                                              m.realtype,
-                                              notxpcom=m.notxpcom))
+                            paramlistAsNative(m))
+
+def paramlistAsNative(m, empty='void'):
+    l = [paramAsNative(p) for p in m.params]
+
+    if m.implicit_jscontext:
+        l.append("JSContext* cx")
 
-def paramlistAsNative(l, rettype, notxpcom, empty='void'):
-    l = list(l)
-    if not notxpcom and rettype.name != 'void':
-        l.append(xpidl.Param(paramtype='out',
-                             type=None,
-                             name='_retval',
-                             attlist=[],
-                             location=None,
-                             realtype=rettype))
+    if m.optional_argc:
+        l.append('PRUint8 _argc')
+
+    if not m.notxpcom and m.realtype.name != 'void':
+        l.append(paramAsNative(xpidl.Param(paramtype='out',
+                                           type=None,
+                                           name='_retval',
+                                           attlist=[],
+                                           location=None,
+                                           realtype=m.realtype)))
 
     if len(l) == 0:
         return empty
 
-    return ", ".join([paramAsNative(p) for p in l])
+    return ", ".join(l)
 
 def paramAsNative(p):
     if p.paramtype == 'in':
         typeannotate = ''
     else:
         typeannotate = ' NS_%sPARAM' % p.paramtype.upper()
 
     return "%s%s%s" % (p.nativeType(),
                        p.name,
                        typeannotate)
 
-def paramlistNames(l, rettype, notxpcom):
-    names = [p.name for p in l]
-    if not notxpcom and rettype.name != 'void':
+def paramlistNames(m):
+    names = [p.name for p in m.params]
+
+    if m.implicit_jscontext:
+        names.append('cx')
+
+    if m.optional_argc:
+        names.append('_argc')
+
+    if not m.notxpcom and m.realtype.name != 'void':
         names.append('_retval')
+
     if len(names) == 0:
         return ''
     return ', '.join(names)
 
 header = """/*
  * DO NOT EDIT.  THIS FILE IS GENERATED FROM %(filename)s
  */
 
@@ -391,25 +416,25 @@ def write_interface(iface, fd):
 
     fd.write(iface_forward % names)
 
     def emitTemplate(tmpl):
         for member in iface.members:
             if isinstance(member, xpidl.Attribute):
                 fd.write(tmpl % {'asNative': attributeAsNative(member, True),
                                  'nativeName': attributeNativeName(member, True),
-                                 'paramList': attributeParamName(member)})
+                                 'paramList': attributeParamNames(member)})
                 if not member.readonly:
                     fd.write(tmpl % {'asNative': attributeAsNative(member, False),
                                      'nativeName': attributeNativeName(member, False),
-                                     'paramList': attributeParamName(member)})
+                                     'paramList': attributeParamNames(member)})
             elif isinstance(member, xpidl.Method):
                 fd.write(tmpl % {'asNative': methodAsNative(member),
                                  'nativeName': methodNativeName(member),
-                                 'paramList': paramlistNames(member.params, member.realtype, member.notxpcom)})
+                                 'paramList': paramlistNames(member)})
         if len(iface.members) == 0:
             fd.write('\\\n  /* no methods! */')
         elif not member.kind in ('attribute', 'method'):
             fd.write('\\')
 
     emitTemplate("\\\n  %(asNative)s { return _to %(nativeName)s(%(paramList)s); } ")
 
     fd.write(iface_forward_safe % names)
@@ -430,28 +455,56 @@ def write_interface(iface, fd):
                 fd.write(example_tmpl % {'implclass': implclass,
                                          'returntype': attributeReturnType(member, 'NS_IMETHODIMP'),
                                          'nativeName': attributeNativeName(member, False),
                                          'paramList': attributeParamlist(member, False)})
         elif isinstance(member, xpidl.Method):
             fd.write(example_tmpl % {'implclass': implclass,
                                      'returntype': methodReturnType(member, 'NS_IMETHODIMP'),
                                      'nativeName': methodNativeName(member),
-                                     'paramList': paramlistAsNative(member.params, member.realtype, notxpcom=member.notxpcom, empty='')})
+                                     'paramList': paramlistAsNative(member, empty='')})
         fd.write('\n')
 
     fd.write(iface_template_epilog)
 
 if __name__ == '__main__':
     from optparse import OptionParser
     o = OptionParser()
-    o.add_option('-I', action='append', dest='incdirs', help="Directory to search for imported files", default=[])
-    o.add_option('--cachedir', dest='cachedir', help="Directory in which to cache lex/parse tables.", default='')
+    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 (default is stdout)")
+    o.add_option('-d', dest='depfile', default=None,
+                 help="Generate a make dependency file")
     options, args = o.parse_args()
     file, = args
 
-    if options.cachedir != '':
+    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, 'w')
+        closeoutfd = True
+    else:
+        outfd = sys.stdout
+        closeoutfd = False
+
     p = xpidl.IDLParser(outputdir=options.cachedir)
     idl = p.parse(open(file).read(), filename=file)
     idl.resolve(options.incdirs, p)
-    print_header(idl, sys.stdout, file)
+    print_header(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))
--- a/xpcom/idl-parser/xpidl.py
+++ b/xpcom/idl-parser/xpidl.py
@@ -277,23 +277,25 @@ class Include(object):
 
         for file in incfiles():
             if not os.path.exists(file): continue
 
             self.IDL = parent.parser.parse(open(file).read(), filename=file)
             self.IDL.resolve(parent.incdirs, parent.parser)
             for type in self.IDL.getNames():
                 parent.setName(type)
+            parent.deps.extend(self.IDL.deps)
             return
 
         raise IDLError("File '%s' not found" % self.filename, self.location)
 
 class IDL(object):
     def __init__(self, productions):
         self.productions = productions
+        self.deps = []
 
     def setName(self, object):
         self.namemap.set(object)
 
     def getName(self, id, location):
         try:
             return self.namemap[id]
         except KeyError:
@@ -455,17 +457,21 @@ class Native(object):
             const = True
 
         if self.specialtype is not None and calltype == 'in':
             const = True
 
         if self.modifier == 'ptr':
             m = '*' + (calltype != 'in' and '*' or '')
         elif self.modifier == 'ref':
-            m = '& '
+            # jsval outparams are odd, for compatibility with existing code
+            if self.specialtype == 'jsval' and calltype == 'out':
+                m = '*'
+            else:
+                m = '& '
         else:
             m = calltype != 'in' and '*' or ''
         return "%s%s %s" % (const and 'const ' or '', self.nativename, m)
 
     def __str__(self):
         return "native %s(%s)\n" % (self.name, self.nativename)
 
 class Interface(object):
@@ -647,16 +653,17 @@ class Attribute(object):
     noscript = False
     notxpcom = False
     readonly = False
     implicit_jscontext = False
     nostdcall = False
     binaryname = None
     null = None
     undefined = None
+    deprecated = False
 
     def __init__(self, type, name, attlist, readonly, location, doccomments):
         self.type = type
         self.name = name
         self.attlist = attlist
         self.readonly = readonly
         self.location = location
         self.doccomments = doccomments
@@ -695,16 +702,18 @@ class Attribute(object):
                     raise IDLError("Unexpected attribute value", aloc)
 
                 if name == 'noscript':
                     self.noscript = True
                 elif name == 'notxpcom':
                     self.notxpcom = True
                 elif name == 'implicit_jscontext':
                     self.implicit_jscontext = True
+                elif name == 'deprecated':
+                    self.deprecated = True
                 elif name == 'nostdcall':
                     self.nostdcall = True
                 else:
                     raise IDLError("Unexpected attribute '%s'" % name, aloc)
 
     def resolve(self, iface):
         self.iface = iface
         self.realtype = iface.idl.getName(self.type, self.location)
@@ -733,16 +742,17 @@ class Attribute(object):
 class Method(object):
     kind = 'method'
     noscript = False
     notxpcom = False
     binaryname = None
     implicit_jscontext = False
     nostdcall = False
     optional_argc = False
+    deprecated = False
 
     def __init__(self, type, name, attlist, paramlist, location, doccomments, raises):
         self.type = type
         self.name = name
         self.attlist = attlist
         self.params = paramlist
         self.location = location
         self.doccomments = doccomments
@@ -763,16 +773,18 @@ class Method(object):
             if name == 'noscript':
                 self.noscript = True
             elif name == 'notxpcom':
                 self.notxpcom = True
             elif name == 'implicit_jscontext':
                 self.implicit_jscontext = True
             elif name == 'optional_argc':
                 self.optional_argc = True
+            elif name == 'deprecated':
+                self.deprecated = True
             elif name == 'nostdcall':
                 self.nostdcall = True
             else:
                 raise IDLError("Unexpected attribute '%s'" % name, aloc)
 
         self.namemap = NameMap()
         for p in paramlist:
             self.namemap.set(p)
@@ -1322,17 +1334,20 @@ class IDLParser(object):
             self._doccomments = []
         return t
 
     def parse(self, data, filename=None):
         if filename is not None:
             self.lexer.filename = filename
         self.lexer.lineno = 1
         self.lexer.input(data)
-        return self.parser.parse(lexer=self)
+        idl = self.parser.parse(lexer=self)
+        if filename is not None:
+            idl.deps.append(filename)
+        return idl
 
     def getLocation(self, p, i):
         return Location(self.lexer, p.lineno(i), p.lexpos(i))
 
 if __name__ == '__main__':
     p = IDLParser()
     for f in sys.argv[1:]:
         print "Parsing %s" % f
new file mode 100644
--- /dev/null
+++ b/xpcom/idl-parser/xpidllex.py
@@ -0,0 +1,9 @@
+# xpidllex.py. This file automatically created by PLY (version 3.3). Don't edit!
+_tabversion   = '3.3'
+_lextokens    = {'TYPEDEF': 1, 'INCLUDE': 1, 'RSHIFT': 1, 'LSHIFT': 1, 'ATTRIBUTE': 1, 'NATIVEID': 1, 'NUMBER': 1, 'NATIVE': 1, 'IID': 1, 'READONLY': 1, 'RAISES': 1, 'CDATA': 1, 'IN': 1, 'INTERFACE': 1, 'CONST': 1, 'IDENTIFIER': 1, 'OUT': 1, 'INOUT': 1, 'HEXNUM': 1}
+_lexreflags   = 0
+_lexliterals  = '"(){}[],;:=|+-*'
+_lexstateinfo = {'nativeid': 'exclusive', 'INITIAL': 'inclusive'}
+_lexstatere   = {'nativeid': [('(?P<t_nativeid_NATIVEID>[^()\\n]+(?=\\)))', [None, ('t_nativeid_NATIVEID', 'NATIVEID')])], 'INITIAL': [('(?P<t_multilinecomment>/\\*(?s).*?\\*/)|(?P<t_singlelinecomment>(?m)//.*?$)|(?P<t_IID>[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})|(?P<t_IDENTIFIER>unsigned\\ long\\ long|unsigned\\ short|unsigned\\ long|long\\ long|[A-Za-z][A-Za-z_0-9]*)|(?P<t_LCDATA>(?s)%\\{[ ]*C\\+\\+[ ]*\\n(?P<cdata>.*?\\n?)%\\}[ ]*(C\\+\\+)?)|(?P<t_INCLUDE>\\#include[ \\t]+"[^"\\n]+")|(?P<t_directive>\\#(?P<directive>[a-zA-Z]+)[^\\n]+)|(?P<t_newline>\\n+)|(?P<t_HEXNUM>0x[a-fA-F0-9]+)|(?P<t_NUMBER>-?\\d+)|(?P<t_LSHIFT><<)|(?P<t_RSHIFT>>>)', [None, ('t_multilinecomment', 'multilinecomment'), ('t_singlelinecomment', 'singlelinecomment'), ('t_IID', 'IID'), ('t_IDENTIFIER', 'IDENTIFIER'), ('t_LCDATA', 'LCDATA'), None, None, ('t_INCLUDE', 'INCLUDE'), ('t_directive', 'directive'), None, ('t_newline', 'newline'), (None, 'HEXNUM'), (None, 'NUMBER'), (None, 'LSHIFT'), (None, 'RSHIFT')])]}
+_lexstateignore = {'nativeid': '', 'INITIAL': ' \t'}
+_lexstateerrorf = {'nativeid': 't_ANY_error', 'INITIAL': 't_ANY_error'}
new file mode 100644
--- /dev/null
+++ b/xpcom/idl-parser/xpidlyacc.py
@@ -0,0 +1,85 @@
+
+# /home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidlyacc.py
+# This file is automatically generated. Do not edit.
+_tabversion = '3.2'
+
+_lr_method = 'LALR'
+
+_lr_signature = ',Q\xe7:m\xcf|\xa4\x8ad\x0f\x06\xc1Q\x1f\x99'
+    
+_lr_action_items = {'CONST':([6,25,42,47,48,82,84,104,],[14,14,45,45,-28,-29,-41,-42,]),'NATIVEID':([43,],[50,]),'NUMBER':([62,65,66,77,78,79,80,81,83,],[68,68,68,68,68,68,68,68,68,]),'LSHIFT':([67,68,69,70,75,76,92,93,94,95,96,97,98,],[80,-30,-32,-31,80,-34,-33,-35,-37,-36,-38,-39,80,]),'RSHIFT':([67,68,69,70,75,76,92,93,94,95,96,97,98,],[81,-30,-32,-31,81,-34,-33,-35,-37,-36,-38,-39,81,]),'INOUT':([28,64,74,85,],[-13,-14,90,-14,]),'NATIVE':([0,2,5,7,8,9,10,28,31,44,61,],[-14,-14,-14,-14,-14,-14,23,-13,-8,-21,-9,]),')':([33,34,50,64,68,69,70,72,73,75,76,86,92,93,94,95,96,97,98,99,103,106,107,108,111,],[38,39,57,-44,-30,-32,-31,-45,87,92,-34,-43,-33,-35,-37,-36,-38,-39,-40,-45,-46,-47,109,-55,-56,]),'(':([14,16,17,30,37,60,62,65,66,77,78,79,80,81,83,101,],[-12,27,-11,-10,43,64,65,65,65,65,65,65,65,65,65,105,]),'+':([67,68,69,70,75,76,92,93,94,95,96,97,98,],[77,-30,-32,-31,77,-34,-33,-35,-37,-36,77,77,77,]),'*':([67,68,69,70,75,76,92,93,94,95,96,97,98,],[78,-30,-32,-31,78,-34,-33,78,-37,78,78,78,78,]),'-':([62,65,66,67,68,69,70,75,76,77,78,79,80,81,83,92,93,94,95,96,97,98,],[66,66,66,79,-30,-32,-31,79,-34,66,66,66,66,66,66,-33,-35,-37,-36,79,79,79,]),',':([14,15,16,17,26,38,39,72,99,106,108,],[-12,25,-20,-11,-17,-18,-19,85,85,-47,110,]),'IID':([27,],[34,]),'READONLY':([28,42,47,48,49,82,84,104,],[-13,-14,-14,-28,55,-29,-41,-42,]),';':([24,29,36,40,41,52,57,67,68,69,70,71,76,87,92,93,94,95,96,97,98,100,109,],[31,-25,-23,-24,44,-22,61,82,-30,-32,-31,84,-34,-54,-33,-35,-37,-36,-38,-39,-40,104,-53,]),'IDENTIFIER':([3,6,12,22,23,25,27,28,35,42,45,47,48,49,51,56,59,62,63,65,66,77,78,79,80,81,82,83,84,88,89,90,91,102,104,105,110,],[12,17,24,29,30,17,33,-13,40,-14,51,-14,-28,56,58,60,63,69,71,69,69,69,69,69,69,69,-29,69,-41,102,-48,-49,-50,106,-42,108,108,]),'=':([58,],[62,]),'OUT':([28,64,74,85,],[-13,-14,91,-14,]),'TYPEDEF':([0,2,5,7,8,9,31,44,61,],[3,3,3,3,3,3,-8,-21,-9,]),'RAISES':([87,],[101,]),'IN':([28,64,74,85,],[-13,-14,89,-14,]),'[':([0,2,5,7,8,9,31,42,44,47,48,61,64,82,84,85,104,],[6,6,6,6,6,6,-8,6,-21,6,-28,-9,6,-29,-41,6,-42,]),'INCLUDE':([0,2,5,7,8,9,31,44,61,],[7,7,7,7,7,7,-8,-21,-9,]),']':([14,15,16,17,18,26,32,38,39,],[-12,-15,-20,-11,28,-17,-16,-18,-19,]),':':([29,],[35,]),'ATTRIBUTE':([28,42,47,48,49,54,55,82,84,104,],[-13,-14,-14,-28,-52,59,-51,-29,-41,-42,]),'CDATA':([0,2,5,7,8,9,31,42,44,47,48,61,82,84,104,],[9,9,9,9,9,9,-8,48,-21,48,-28,-9,-29,-41,-42,]),'INTERFACE':([0,2,5,7,8,9,10,28,31,44,61,],[-14,-14,-14,-14,-14,-14,22,-13,-8,-21,-9,]),'{':([29,36,40,],[-25,42,-24,]),'$end':([0,1,2,4,5,7,8,9,11,13,19,20,21,31,44,61,],[-2,-1,-2,0,-2,-2,-2,-2,-6,-5,-4,-7,-3,-8,-21,-9,]),'}':([42,46,47,48,53,82,84,104,],[-26,52,-26,-28,-27,-29,-41,-42,]),'|':([67,68,69,70,75,76,92,93,94,95,96,97,98,],[83,-30,-32,-31,83,-34,-33,-35,-37,-36,-38,-39,-40,]),'HEXNUM':([62,65,66,77,78,79,80,81,83,],[70,70,70,70,70,70,70,70,70,]),}
+
+_lr_action = { }
+for _k, _v in _lr_action_items.items():
+   for _x,_y in zip(_v[0],_v[1]):
+      if not _x in _lr_action:  _lr_action[_x] = { }
+      _lr_action[_x][_k] = _y
+del _lr_action_items
+
+_lr_goto_items = {'members':([42,47,],[46,53,]),'attribute':([6,25,],[15,15,]),'number':([62,65,66,77,78,79,80,81,83,],[67,75,76,93,94,95,96,97,98,]),'productions':([0,2,5,7,8,9,],[1,11,13,19,20,21,]),'raises':([87,],[100,]),'ifacebody':([36,],[41,]),'attlist':([6,25,],[18,32,]),'native':([0,2,5,7,8,9,],[8,8,8,8,8,8,]),'typedef':([0,2,5,7,8,9,],[2,2,2,2,2,2,]),'attributeval':([16,],[26,]),'optreadonly':([49,],[54,]),'ifacebase':([29,],[36,]),'afternativeid':([30,],[37,]),'param':([64,85,],[72,99,]),'member':([42,47,],[47,47,]),'idlfile':([0,],[4,]),'paramlist':([64,],[73,]),'moreparams':([72,99,],[86,103,]),'interface':([0,2,5,7,8,9,],[5,5,5,5,5,5,]),'idlist':([105,110,],[107,111,]),'paramtype':([74,],[88,]),'anyident':([6,25,],[16,16,]),'attributes':([0,2,5,7,8,9,42,47,64,85,],[10,10,10,10,10,10,49,49,74,74,]),}
+
+_lr_goto = { }
+for _k, _v in _lr_goto_items.items():
+   for _x,_y in zip(_v[0],_v[1]):
+       if not _x in _lr_goto: _lr_goto[_x] = { }
+       _lr_goto[_x][_k] = _y
+del _lr_goto_items
+_lr_productions = [
+  ("S' -> idlfile","S'",1,None,None,None),
+  ('idlfile -> productions','idlfile',1,'p_idlfile','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1028),
+  ('productions -> <empty>','productions',0,'p_productions_start','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1032),
+  ('productions -> CDATA productions','productions',2,'p_productions_cdata','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1036),
+  ('productions -> INCLUDE productions','productions',2,'p_productions_include','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1041),
+  ('productions -> interface productions','productions',2,'p_productions_interface','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1046),
+  ('productions -> typedef productions','productions',2,'p_productions_interface','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1047),
+  ('productions -> native productions','productions',2,'p_productions_interface','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1048),
+  ('typedef -> TYPEDEF IDENTIFIER IDENTIFIER ;','typedef',4,'p_typedef','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1053),
+  ('native -> attributes NATIVE IDENTIFIER afternativeid ( NATIVEID ) ;','native',8,'p_native','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1060),
+  ('afternativeid -> <empty>','afternativeid',0,'p_afternativeid','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1067),
+  ('anyident -> IDENTIFIER','anyident',1,'p_anyident','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1073),
+  ('anyident -> CONST','anyident',1,'p_anyident','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1074),
+  ('attributes -> [ attlist ]','attributes',3,'p_attributes','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1079),
+  ('attributes -> <empty>','attributes',0,'p_attributes','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1080),
+  ('attlist -> attribute','attlist',1,'p_attlist_start','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1088),
+  ('attlist -> attribute , attlist','attlist',3,'p_attlist_continue','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1092),
+  ('attribute -> anyident attributeval','attribute',2,'p_attribute','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1097),
+  ('attributeval -> ( IDENTIFIER )','attributeval',3,'p_attributeval','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1101),
+  ('attributeval -> ( IID )','attributeval',3,'p_attributeval','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1102),
+  ('attributeval -> <empty>','attributeval',0,'p_attributeval','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1103),
+  ('interface -> attributes INTERFACE IDENTIFIER ifacebase ifacebody ;','interface',6,'p_interface','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1108),
+  ('ifacebody -> { members }','ifacebody',3,'p_ifacebody','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1137),
+  ('ifacebody -> <empty>','ifacebody',0,'p_ifacebody','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1138),
+  ('ifacebase -> : IDENTIFIER','ifacebase',2,'p_ifacebase','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1143),
+  ('ifacebase -> <empty>','ifacebase',0,'p_ifacebase','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1144),
+  ('members -> <empty>','members',0,'p_members_start','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1149),
+  ('members -> member members','members',2,'p_members_continue','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1153),
+  ('member -> CDATA','member',1,'p_member_cdata','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1158),
+  ('member -> CONST IDENTIFIER IDENTIFIER = number ;','member',6,'p_member_const','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1162),
+  ('number -> NUMBER','number',1,'p_number_decimal','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1170),
+  ('number -> HEXNUM','number',1,'p_number_hex','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1175),
+  ('number -> IDENTIFIER','number',1,'p_number_identifier','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1180),
+  ('number -> ( number )','number',3,'p_number_paren','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1186),
+  ('number -> - number','number',2,'p_number_neg','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1190),
+  ('number -> number + number','number',3,'p_number_add','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1195),
+  ('number -> number - number','number',3,'p_number_add','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1196),
+  ('number -> number * number','number',3,'p_number_add','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1197),
+  ('number -> number LSHIFT number','number',3,'p_number_shift','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1208),
+  ('number -> number RSHIFT number','number',3,'p_number_shift','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1209),
+  ('number -> number | number','number',3,'p_number_bitor','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1218),
+  ('member -> attributes optreadonly ATTRIBUTE IDENTIFIER IDENTIFIER ;','member',6,'p_member_att','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1224),
+  ('member -> attributes IDENTIFIER IDENTIFIER ( paramlist ) raises ;','member',8,'p_member_method','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1240),
+  ('paramlist -> param moreparams','paramlist',2,'p_paramlist','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1255),
+  ('paramlist -> <empty>','paramlist',0,'p_paramlist','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1256),
+  ('moreparams -> <empty>','moreparams',0,'p_moreparams_start','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1264),
+  ('moreparams -> , param moreparams','moreparams',3,'p_moreparams_continue','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1268),
+  ('param -> attributes paramtype IDENTIFIER IDENTIFIER','param',4,'p_param','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1273),
+  ('paramtype -> IN','paramtype',1,'p_paramtype','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1281),
+  ('paramtype -> INOUT','paramtype',1,'p_paramtype','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1282),
+  ('paramtype -> OUT','paramtype',1,'p_paramtype','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1283),
+  ('optreadonly -> READONLY','optreadonly',1,'p_optreadonly','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1287),
+  ('optreadonly -> <empty>','optreadonly',0,'p_optreadonly','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1288),
+  ('raises -> RAISES ( idlist )','raises',4,'p_raises','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1295),
+  ('raises -> <empty>','raises',0,'p_raises','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1296),
+  ('idlist -> IDENTIFIER','idlist',1,'p_idlist','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1303),
+  ('idlist -> IDENTIFIER , idlist','idlist',3,'p_idlist_continue','/home/khuey/dev/mozilla-central/xpcom/idl-parser/xpidl.py',1307),
+]