Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/compiler/generate_parser_tools.py
1693 views
1
#!/usr/bin/python3
2
# Copyright 2019 The ANGLE Project Authors. All rights reserved.
3
# Use of this source code is governed by a BSD-style license that can be
4
# found in the LICENSE file.
5
#
6
# generate_parser_tools.py:
7
# Common functionality to call flex and bison to generate lexer and parser of
8
# the translator and preprocessor.
9
10
import os
11
import platform
12
import subprocess
13
import sys
14
15
is_linux = platform.system() == 'Linux'
16
is_windows = platform.system() == 'Windows'
17
18
19
def get_tool_path_platform(tool_name, platform):
20
exe_path = os.path.join(sys.path[0], '..', '..', '..', 'tools', 'flex-bison', platform)
21
22
return os.path.join(exe_path, tool_name)
23
24
25
def get_tool_path(tool_name):
26
if is_linux:
27
platform = 'linux'
28
ext = ''
29
else:
30
assert (is_windows)
31
platform = 'windows'
32
ext = '.exe'
33
34
return get_tool_path_platform(tool_name + ext, platform)
35
36
37
def get_tool_file_sha1s():
38
files = [
39
get_tool_path_platform('flex', 'linux'),
40
get_tool_path_platform('bison', 'linux'),
41
get_tool_path_platform('flex.exe', 'windows'),
42
get_tool_path_platform('bison.exe', 'windows'),
43
get_tool_path_platform('m4.exe', 'windows')
44
]
45
46
files += [
47
get_tool_path_platform(dll, 'windows')
48
for dll in ['msys-2.0.dll', 'msys-iconv-2.dll', 'msys-intl-8.dll']
49
]
50
51
return [f + '.sha1' for f in files]
52
53
54
def run_flex(basename):
55
flex = get_tool_path('flex')
56
input_file = basename + '.l'
57
output_source = basename + '_lex_autogen.cpp'
58
59
flex_args = [flex, '--noline', '--nounistd', '--outfile=' + output_source, input_file]
60
61
flex_env = os.environ.copy()
62
if is_windows:
63
flex_env['M4'] = get_tool_path_platform('m4.exe', 'windows')
64
65
process = subprocess.Popen(flex_args, env=flex_env, cwd=sys.path[0])
66
process.communicate()
67
if process.returncode != 0:
68
return process.returncode
69
70
# Patch flex output for 64-bit. The patch is simple enough that we could do a string
71
# replacement. More importantly, the location of the line of code that needs to be substituted
72
# can vary based on flex version, and the string substitution will find the correct place
73
# automatically.
74
75
patch_in = """\n\t\tYY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),\n\t\t\tyyg->yy_n_chars, num_to_read );"""
76
patch_out = """
77
yy_size_t ret = 0;
78
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
79
ret, num_to_read );
80
yyg->yy_n_chars = static_cast<int>(ret);"""
81
82
with open(output_source, 'r') as flex_output:
83
output = flex_output.read()
84
85
# If flex's output changes such that this line no longer exists, the patch needs to be
86
# updated, or possibly removed.
87
assert (output.find(patch_in) != -1)
88
89
patched = output.replace(patch_in, patch_out)
90
91
# Remove all tab characters from output. WebKit does not allow any tab characters in source
92
# files.
93
patched = patched.replace('\t', ' ')
94
95
with open(output_source, 'w') as flex_output_patched:
96
flex_output_patched.write(patched)
97
98
return 0
99
100
101
def run_bison(basename, generate_header):
102
bison = get_tool_path('bison')
103
input_file = basename + '.y'
104
output_header = basename + '_tab_autogen.h'
105
output_source = basename + '_tab_autogen.cpp'
106
107
bison_args = [bison, '--no-lines', '--skeleton=yacc.c']
108
if generate_header:
109
bison_args += ['--defines=' + output_header]
110
bison_args += ['--output=' + output_source, input_file]
111
112
bison_env = os.environ.copy()
113
bison_env['BISON_PKGDATADIR'] = get_tool_path_platform('', 'third_party')
114
if is_windows:
115
bison_env['M4'] = get_tool_path_platform('m4.exe', 'windows')
116
117
process = subprocess.Popen(bison_args, env=bison_env, cwd=sys.path[0])
118
process.communicate()
119
return process.returncode
120
121
122
def get_input_files(basename):
123
files = [basename + '.l', basename + '.y']
124
return [os.path.join(sys.path[0], f) for f in files]
125
126
127
def get_output_files(basename, generate_header):
128
optional_header = [basename + '_tab_autogen.h'] if generate_header else []
129
files = [basename + '_lex_autogen.cpp', basename + '_tab_autogen.cpp'] + optional_header
130
return [os.path.join(sys.path[0], f) for f in files]
131
132
133
def generate_parser(basename, generate_header):
134
# Handle inputs/outputs for run_code_generation.py's auto_script
135
if len(sys.argv) > 1:
136
if sys.argv[1] == 'inputs':
137
inputs = get_tool_file_sha1s()
138
inputs += get_input_files(basename)
139
current_file = __file__
140
if current_file.endswith('.pyc'):
141
current_file = current_file[:-1]
142
inputs += [current_file]
143
print(','.join(inputs))
144
if sys.argv[1] == 'outputs':
145
print(','.join(get_output_files(basename, generate_header)))
146
return 0
147
148
# Call flex and bison to generate the lexer and parser.
149
flex_result = run_flex(basename)
150
if flex_result != 0:
151
print('Failed to run flex. Error %s' % str(flex_result))
152
return 1
153
154
bison_result = run_bison(basename, generate_header)
155
if bison_result != 0:
156
print('Failed to run bison. Error %s' % str(bison_result))
157
return 2
158
159
return 0
160
161