1643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#!/usr/bin/python
2643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#
3643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# Copyright (C) 2009 Google Inc. All rights reserved.
4643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#
5643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# Redistribution and use in source and binary forms, with or without
6643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# modification, are permitted provided that the following conditions are
7643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# met:
8643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#
9643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#     * Redistributions of source code must retain the above copyright
10643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# notice, this list of conditions and the following disclaimer.
11643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#     * Redistributions in binary form must reproduce the above
12643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# copyright notice, this list of conditions and the following disclaimer
13643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# in the documentation and/or other materials provided with the
14643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# distribution.
15643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#     * Neither the name of Google Inc. nor the names of its
16643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# contributors may be used to endorse or promote products derived from
17643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# this software without specific prior written permission.
18643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#
19643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#
31643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# Copyright (c) 2009 The Chromium Authors. All rights reserved.
32643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# Use of this source code is governed by a BSD-style license that can be
33643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# found in the LICENSE file.
34643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
35643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# usage: rule_bison.py INPUT_FILE OUTPUT_DIR
36643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# INPUT_FILE is a path to either CSSGrammar.y or XPathGrammar.y.
37643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# OUTPUT_DIR is where the bison-generated .cpp and .h files should be placed.
38643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
39643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockimport errno
40643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockimport os
41643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockimport os.path
42643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockimport subprocess
43643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockimport sys
44643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
45643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockassert len(sys.argv) == 3
46643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
47643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockinputFile = sys.argv[1]
48643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockoutputDir = sys.argv[2]
49643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
50643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockinputName = os.path.basename(inputFile)
51643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockassert inputName == 'CSSGrammar.y' or inputName == 'XPathGrammar.y'
52643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockprefix = {'CSSGrammar.y': 'cssyy', 'XPathGrammar.y': 'xpathyy'}[inputName]
53643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
54643ca7872b450ea4efacab6188849e5aac2ba161Steve Block(inputRoot, inputExt) = os.path.splitext(inputName)
55643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
56643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# The generated .h will be in a different location depending on the bison
57643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# version.
58643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockoutputHTries = [
59643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    os.path.join(outputDir, inputRoot + '.cpp.h'),
60643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    os.path.join(outputDir, inputRoot + '.hpp'),
61643ca7872b450ea4efacab6188849e5aac2ba161Steve Block]
62643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
63643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockfor outputHTry in outputHTries:
64643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    try:
65643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        os.unlink(outputHTry)
66643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    except OSError, e:
67643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if e.errno != errno.ENOENT:
68643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            raise
69643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
70643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockoutputCpp = os.path.join(outputDir, inputRoot + '.cpp')
71643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
72643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockreturnCode = subprocess.call(['bison', '-d', '-p', prefix, inputFile, '-o', outputCpp])
73643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockassert returnCode == 0
74643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
75643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# Find the name that bison used for the generated header file.
76643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockoutputHTmp = None
77643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockfor outputHTry in outputHTries:
78643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    try:
79643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        os.stat(outputHTry)
80643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        outputHTmp = outputHTry
81643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        break
82643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    except OSError, e:
83643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if e.errno != errno.ENOENT:
84643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            raise
85643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
86643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockassert outputHTmp != None
87643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
88643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# Read the header file in under the generated name and remove it.
89643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockoutputHFile = open(outputHTmp)
90643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockoutputHContents = outputHFile.read()
91643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockoutputHFile.close()
92643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockos.unlink(outputHTmp)
93643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
94643ca7872b450ea4efacab6188849e5aac2ba161Steve Block# Rewrite the generated header with #include guards.
95643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockoutputH = os.path.join(outputDir, inputRoot + '.h')
96643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
97643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockoutputHFile = open(outputH, 'w')
98643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockprint >>outputHFile, '#ifndef %sH' % inputRoot
99643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockprint >>outputHFile, '#define %sH' % inputRoot
100643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockprint >>outputHFile, outputHContents
101643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockprint >>outputHFile, '#endif'
102643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockoutputHFile.close()
103