author Seth Fowler <seth@mozilla.com>
Sun, 11 Jan 2015 05:34:20 -0800
changeset 223150 3dd5401f359cd1d442c2ebb800c9a4938396aba6
parent 96331 b7f3236f127b6f8d455efa6ad75f82a3a3c5f3d4
child 318992 7ae23ee055f527372579e69ecefedef05e604941
permissions -rw-r--r--
Bug 1079627 (Part 1) - Make image decoders hold a strong reference to their image. r=tn

# 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/.

__all__ = [ 'gencxx', 'genipdl', 'parse', 'typecheck', 'writeifmodified' ]

import os, sys
from cStringIO import StringIO

from ipdl.cgen import IPDLCodeGen
from ipdl.lower import LowerToCxx
from ipdl.parser import Parser
from ipdl.type import TypeCheck

from ipdl.cxx.cgen import CxxCodeGen

def parse(specstring, filename='/stdin', includedirs=[ ], errout=sys.stderr):
    '''Return an IPDL AST if parsing was successful.  Print errors to |errout|
    if it is not.'''
    # The file type and name are later enforced by the type checker.
    # This is just a hint to the parser.
    prefix, ext = os.path.splitext(filename)
    name = os.path.basename(prefix)
    if ext == '.ipdlh':
        type = 'header'
        type = 'protocol'
    return Parser(type, name).parse(specstring, os.path.abspath(filename), includedirs, errout)

def typecheck(ast, errout=sys.stderr):
    '''Return True iff |ast| is well typed.  Print errors to |errout| if
    it is not.'''
    return TypeCheck().check(ast, errout)

def gencxx(ipdlfilename, ast, outheadersdir, outcppdir):
    headers, cpps = LowerToCxx().lower(ast)

    def resolveHeader(hdr):
        return [
                *([ns.name for ns in ast.namespaces] + [hdr.name]))
    def resolveCpp(cpp):
        return [ cpp, os.path.join(outcppdir, cpp.name) ]

    for ast, filename in ([ resolveHeader(hdr) for hdr in headers ]
                          + [ resolveCpp(cpp) for cpp in cpps ]):
        tempfile = StringIO()
        writeifmodified(tempfile.getvalue(), filename)

def genipdl(ast, outdir):
    return IPDLCodeGen().cgen(ast)

def writeifmodified(contents, file):
    dir = os.path.dirname(file)
    os.path.exists(dir) or os.makedirs(dir)

    oldcontents = None
    if os.path.exists(file):
        fd = open(file, 'rb')
        oldcontents = fd.read()
    if oldcontents != contents:
        fd = open(file, 'wb')