blob: 26a7bb302336232631098921a56c0e31113cb96e [file] [log] [blame]
#!/usr/bin/python
#
# Copyright (C) 2009 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Copyright (c) 2009 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# usage: rule_bison.py INPUT_FILE OUTPUT_DIR BISON_EXE
# INPUT_FILE is a path to *.y such as xpath_grammar.y.
# OUTPUT_DIR is where the bison-generated .cc and .h files should be placed.
import errno
import os
import os.path
import subprocess
import sys
from blinkbuild.name_style_converter import NameStyleConverter
def modify_file(path, prefix_lines, suffix_lines, replace_list=[]):
prefix_lines = map(lambda s: s + '\n', prefix_lines)
suffix_lines = map(lambda s: s + '\n', suffix_lines)
with open(path, 'r') as f:
old_lines = f.readlines()
for i in range(len(old_lines)):
for src, dest in replace_list:
old_lines[i] = old_lines[i].replace(src, dest)
new_lines = prefix_lines + old_lines + suffix_lines
with open(path, 'w') as f:
f.writelines(new_lines)
def main():
assert len(sys.argv) == 4
input_file = sys.argv[1]
output_dir = sys.argv[2]
bison_exe = sys.argv[3]
path_to_bison = os.path.split(bison_exe)[0]
if path_to_bison:
# Make sure this path is in the path so that it can find its auxiliary
# binaries (in particular, m4). To avoid other 'm4's being found, insert
# at head, rather than tail.
os.environ['PATH'] = path_to_bison + os.pathsep + os.environ['PATH']
input_name = os.path.basename(input_file)
# Output name without directory and extension.
output_basename = os.path.splitext(input_name)[0] + '_generated'
output_cc = os.path.join(output_dir, output_basename + '.cc')
BISON_HEADER_EXT = '.hh'
original_output_h = os.path.join(output_dir,
output_basename + BISON_HEADER_EXT)
return_code = subprocess.call(
[bison_exe, '-d', input_file, '-o', output_cc])
assert return_code == 0
# If the file doesn't exist, this raise an OSError.
os.stat(original_output_h)
# The generated files contain references to the original "foo.hh" for
# #include and #line. We replace them with "foo.h".
common_replace_list = [(output_basename + BISON_HEADER_EXT,
output_basename + '.h')]
# Rewrite the generated header with #include guards.
CLANG_FORMAT_DISABLE_LINE = "// clang-format off"
output_h = os.path.join(output_dir, output_basename + '.h')
header_guard = NameStyleConverter(output_h).to_header_guard()
modify_file(
original_output_h, [
CLANG_FORMAT_DISABLE_LINE,
'#ifndef %s' % header_guard,
'#define %s' % header_guard
], ['#endif // %s' % header_guard],
replace_list=common_replace_list)
os.rename(original_output_h, output_h)
modify_file(
output_cc, [CLANG_FORMAT_DISABLE_LINE], [],
replace_list=common_replace_list)
if __name__ == '__main__':
main()