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