xref: /aosp_15_r20/external/perfetto/tools/update_sql_parsers.py (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6dbdd20aSAndroid Build Coastguard Worker# Copyright (C) 2020 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker#
4*6dbdd20aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker#
8*6dbdd20aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker#
10*6dbdd20aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker# limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker
16*6dbdd20aSAndroid Build Coastguard Workerimport argparse
17*6dbdd20aSAndroid Build Coastguard Workerimport os
18*6dbdd20aSAndroid Build Coastguard Workerimport subprocess
19*6dbdd20aSAndroid Build Coastguard Workerimport shutil
20*6dbdd20aSAndroid Build Coastguard Workerimport sys
21*6dbdd20aSAndroid Build Coastguard Workerimport tempfile
22*6dbdd20aSAndroid Build Coastguard Worker
23*6dbdd20aSAndroid Build Coastguard WorkerGRAMMAR_FOOTER = '''
24*6dbdd20aSAndroid Build Coastguard Worker%token SPACE ILLEGAL.
25*6dbdd20aSAndroid Build Coastguard Worker'''
26*6dbdd20aSAndroid Build Coastguard Worker
27*6dbdd20aSAndroid Build Coastguard WorkerKEYWORDHASH_HEADER = '''
28*6dbdd20aSAndroid Build Coastguard Worker#include "src/trace_processor/perfetto_sql/grammar/perfettosql_keywordhash_helper.h"
29*6dbdd20aSAndroid Build Coastguard Worker'''
30*6dbdd20aSAndroid Build Coastguard Worker
31*6dbdd20aSAndroid Build Coastguard WorkerKEYWORD_END = '''
32*6dbdd20aSAndroid Build Coastguard Worker  { "WITHOUT",          "TK_WITHOUT",      ALWAYS,           1      },
33*6dbdd20aSAndroid Build Coastguard Worker};'''
34*6dbdd20aSAndroid Build Coastguard Worker
35*6dbdd20aSAndroid Build Coastguard WorkerKEYWORD_END_REPLACE = '''
36*6dbdd20aSAndroid Build Coastguard Worker  { "WITHOUT",          "TK_WITHOUT",      ALWAYS,           1      },
37*6dbdd20aSAndroid Build Coastguard Worker  { "PERFETTO",         "TK_PERFETTO",     ALWAYS,           1      },
38*6dbdd20aSAndroid Build Coastguard Worker  { "MACRO",            "TK_MACRO",        ALWAYS,           1      },
39*6dbdd20aSAndroid Build Coastguard Worker  { "INCLUDE",          "TK_INCLUDE",      ALWAYS,           1      },
40*6dbdd20aSAndroid Build Coastguard Worker  { "MODULE",           "TK_MODULE",       ALWAYS,           1      },
41*6dbdd20aSAndroid Build Coastguard Worker  { "RETURNS",          "TK_RETURNS",      ALWAYS,           1      },
42*6dbdd20aSAndroid Build Coastguard Worker  { "FUNCTION",         "TK_FUNCTION",     ALWAYS,           1      },
43*6dbdd20aSAndroid Build Coastguard Worker};'''
44*6dbdd20aSAndroid Build Coastguard Worker
45*6dbdd20aSAndroid Build Coastguard Worker
46*6dbdd20aSAndroid Build Coastguard Workerdef copy_tokenizer(args: argparse.Namespace):
47*6dbdd20aSAndroid Build Coastguard Worker  shutil.copy(args.sqlite_tokenize, args.sqlite_tokenize_out)
48*6dbdd20aSAndroid Build Coastguard Worker
49*6dbdd20aSAndroid Build Coastguard Worker  with open(args.sqlite_tokenize_out, 'r+', encoding='utf-8') as fp:
50*6dbdd20aSAndroid Build Coastguard Worker    res: str = fp.read()
51*6dbdd20aSAndroid Build Coastguard Worker    idx = res.find('/*\n** Run the parser on the given SQL string.')
52*6dbdd20aSAndroid Build Coastguard Worker    assert idx != -1
53*6dbdd20aSAndroid Build Coastguard Worker    res = res[0:idx]
54*6dbdd20aSAndroid Build Coastguard Worker    res = res.replace(
55*6dbdd20aSAndroid Build Coastguard Worker        '#include "sqliteInt.h"',
56*6dbdd20aSAndroid Build Coastguard Worker        '#include "src/trace_processor/perfetto_sql/tokenizer/tokenize_internal_helper.h"',
57*6dbdd20aSAndroid Build Coastguard Worker    )
58*6dbdd20aSAndroid Build Coastguard Worker    res = res.replace('#include "keywordhash.h"\n', '')
59*6dbdd20aSAndroid Build Coastguard Worker    fp.seek(0)
60*6dbdd20aSAndroid Build Coastguard Worker    fp.write(res)
61*6dbdd20aSAndroid Build Coastguard Worker    fp.truncate()
62*6dbdd20aSAndroid Build Coastguard Worker
63*6dbdd20aSAndroid Build Coastguard Worker
64*6dbdd20aSAndroid Build Coastguard Workerdef main():
65*6dbdd20aSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser()
66*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
67*6dbdd20aSAndroid Build Coastguard Worker      '--lemon', default=os.path.normpath('buildtools/sqlite_src/tool/lemon.c'))
68*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
69*6dbdd20aSAndroid Build Coastguard Worker      '--mkkeywordhash',
70*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.normpath('buildtools/sqlite_src/tool/mkkeywordhash.c'))
71*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
72*6dbdd20aSAndroid Build Coastguard Worker      '--lemon-template',
73*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.normpath('buildtools/sqlite_src/tool/lempar.c'))
74*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
75*6dbdd20aSAndroid Build Coastguard Worker      '--clang', default=os.path.normpath('buildtools/linux64/clang/bin/clang'))
76*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
77*6dbdd20aSAndroid Build Coastguard Worker      '--preprocessor-grammar',
78*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.normpath(
79*6dbdd20aSAndroid Build Coastguard Worker          'src/trace_processor/perfetto_sql/preprocessor/preprocessor_grammar.y'
80*6dbdd20aSAndroid Build Coastguard Worker      ),
81*6dbdd20aSAndroid Build Coastguard Worker  )
82*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
83*6dbdd20aSAndroid Build Coastguard Worker      '--sqlite-grammar',
84*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.normpath('buildtools/sqlite_src/src/parse.y'),
85*6dbdd20aSAndroid Build Coastguard Worker  )
86*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
87*6dbdd20aSAndroid Build Coastguard Worker      '--perfettosql-grammar-include',
88*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.normpath(
89*6dbdd20aSAndroid Build Coastguard Worker          'src/trace_processor/perfetto_sql/grammar/perfettosql_include.y'),
90*6dbdd20aSAndroid Build Coastguard Worker  )
91*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
92*6dbdd20aSAndroid Build Coastguard Worker      '--grammar-out',
93*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.join(
94*6dbdd20aSAndroid Build Coastguard Worker          os.path.normpath('src/trace_processor/perfetto_sql/grammar/')),
95*6dbdd20aSAndroid Build Coastguard Worker  )
96*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
97*6dbdd20aSAndroid Build Coastguard Worker      '--sqlite-tokenize',
98*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.normpath('buildtools/sqlite_src/src/tokenize.c'),
99*6dbdd20aSAndroid Build Coastguard Worker  )
100*6dbdd20aSAndroid Build Coastguard Worker  parser.add_argument(
101*6dbdd20aSAndroid Build Coastguard Worker      '--sqlite-tokenize-out',
102*6dbdd20aSAndroid Build Coastguard Worker      default=os.path.join(
103*6dbdd20aSAndroid Build Coastguard Worker          os.path.normpath(
104*6dbdd20aSAndroid Build Coastguard Worker              'src/trace_processor/perfetto_sql/tokenizer/tokenize_internal.c')
105*6dbdd20aSAndroid Build Coastguard Worker      ),
106*6dbdd20aSAndroid Build Coastguard Worker  )
107*6dbdd20aSAndroid Build Coastguard Worker  args = parser.parse_args()
108*6dbdd20aSAndroid Build Coastguard Worker
109*6dbdd20aSAndroid Build Coastguard Worker  with tempfile.TemporaryDirectory() as tmp:
110*6dbdd20aSAndroid Build Coastguard Worker    # Preprocessor grammar
111*6dbdd20aSAndroid Build Coastguard Worker    subprocess.check_call([
112*6dbdd20aSAndroid Build Coastguard Worker        args.clang,
113*6dbdd20aSAndroid Build Coastguard Worker        os.path.join(args.lemon), '-o',
114*6dbdd20aSAndroid Build Coastguard Worker        os.path.join(tmp, 'lemon')
115*6dbdd20aSAndroid Build Coastguard Worker    ])
116*6dbdd20aSAndroid Build Coastguard Worker    shutil.copy(args.lemon_template, tmp)
117*6dbdd20aSAndroid Build Coastguard Worker    subprocess.check_call([
118*6dbdd20aSAndroid Build Coastguard Worker        os.path.join(tmp, 'lemon'),
119*6dbdd20aSAndroid Build Coastguard Worker        args.preprocessor_grammar,
120*6dbdd20aSAndroid Build Coastguard Worker        '-q',
121*6dbdd20aSAndroid Build Coastguard Worker        '-l',
122*6dbdd20aSAndroid Build Coastguard Worker        '-s',
123*6dbdd20aSAndroid Build Coastguard Worker    ])
124*6dbdd20aSAndroid Build Coastguard Worker
125*6dbdd20aSAndroid Build Coastguard Worker    # PerfettoSQL keywords
126*6dbdd20aSAndroid Build Coastguard Worker    keywordhash_tmp = os.path.join(tmp, 'mkkeywordhash.c')
127*6dbdd20aSAndroid Build Coastguard Worker    shutil.copy(args.mkkeywordhash, keywordhash_tmp)
128*6dbdd20aSAndroid Build Coastguard Worker
129*6dbdd20aSAndroid Build Coastguard Worker    with open(keywordhash_tmp, "r+") as fp:
130*6dbdd20aSAndroid Build Coastguard Worker      keyword_source = fp.read()
131*6dbdd20aSAndroid Build Coastguard Worker      assert keyword_source.find(KEYWORD_END) != -1
132*6dbdd20aSAndroid Build Coastguard Worker      fp.seek(0)
133*6dbdd20aSAndroid Build Coastguard Worker      fp.write(keyword_source.replace(KEYWORD_END, KEYWORD_END_REPLACE))
134*6dbdd20aSAndroid Build Coastguard Worker      fp.truncate()
135*6dbdd20aSAndroid Build Coastguard Worker
136*6dbdd20aSAndroid Build Coastguard Worker    subprocess.check_call([
137*6dbdd20aSAndroid Build Coastguard Worker        args.clang,
138*6dbdd20aSAndroid Build Coastguard Worker        os.path.join(keywordhash_tmp), '-o',
139*6dbdd20aSAndroid Build Coastguard Worker        os.path.join(tmp, 'mkkeywordhash')
140*6dbdd20aSAndroid Build Coastguard Worker    ])
141*6dbdd20aSAndroid Build Coastguard Worker    keywordhash_res = subprocess.check_output(
142*6dbdd20aSAndroid Build Coastguard Worker        [os.path.join(tmp, 'mkkeywordhash')]).decode()
143*6dbdd20aSAndroid Build Coastguard Worker
144*6dbdd20aSAndroid Build Coastguard Worker    with open(os.path.join(args.grammar_out, "perfettosql_keywordhash.h"),
145*6dbdd20aSAndroid Build Coastguard Worker              "w") as g:
146*6dbdd20aSAndroid Build Coastguard Worker      idx = keywordhash_res.find('#define SQLITE_N_KEYWORD')
147*6dbdd20aSAndroid Build Coastguard Worker      assert idx != -1
148*6dbdd20aSAndroid Build Coastguard Worker      keywordhash_res = keywordhash_res[0:idx]
149*6dbdd20aSAndroid Build Coastguard Worker      g.write(KEYWORDHASH_HEADER)
150*6dbdd20aSAndroid Build Coastguard Worker      g.write(keywordhash_res)
151*6dbdd20aSAndroid Build Coastguard Worker
152*6dbdd20aSAndroid Build Coastguard Worker    # PerfettoSQL grammar
153*6dbdd20aSAndroid Build Coastguard Worker    sqlite_grammar = subprocess.check_output([
154*6dbdd20aSAndroid Build Coastguard Worker        os.path.join(tmp, 'lemon'),
155*6dbdd20aSAndroid Build Coastguard Worker        args.sqlite_grammar,
156*6dbdd20aSAndroid Build Coastguard Worker        '-g',
157*6dbdd20aSAndroid Build Coastguard Worker    ]).decode()
158*6dbdd20aSAndroid Build Coastguard Worker    with open(os.path.join(args.grammar_out, "perfettosql_grammar.y"),
159*6dbdd20aSAndroid Build Coastguard Worker              "w") as g:
160*6dbdd20aSAndroid Build Coastguard Worker      with open(args.perfettosql_grammar_include, 'r') as i:
161*6dbdd20aSAndroid Build Coastguard Worker        g.write(i.read())
162*6dbdd20aSAndroid Build Coastguard Worker      g.write(sqlite_grammar)
163*6dbdd20aSAndroid Build Coastguard Worker      g.write(GRAMMAR_FOOTER)
164*6dbdd20aSAndroid Build Coastguard Worker    subprocess.check_call([
165*6dbdd20aSAndroid Build Coastguard Worker        os.path.join(tmp, 'lemon'),
166*6dbdd20aSAndroid Build Coastguard Worker        os.path.join(args.grammar_out, "perfettosql_grammar.y"),
167*6dbdd20aSAndroid Build Coastguard Worker        '-q',
168*6dbdd20aSAndroid Build Coastguard Worker        '-l',
169*6dbdd20aSAndroid Build Coastguard Worker        '-s',
170*6dbdd20aSAndroid Build Coastguard Worker    ])
171*6dbdd20aSAndroid Build Coastguard Worker
172*6dbdd20aSAndroid Build Coastguard Worker  copy_tokenizer(args)
173*6dbdd20aSAndroid Build Coastguard Worker
174*6dbdd20aSAndroid Build Coastguard Worker  return 0
175*6dbdd20aSAndroid Build Coastguard Worker
176*6dbdd20aSAndroid Build Coastguard Worker
177*6dbdd20aSAndroid Build Coastguard Workerif __name__ == '__main__':
178*6dbdd20aSAndroid Build Coastguard Worker  sys.exit(main())
179