1*795d594fSAndroid Build Coastguard Worker#!/usr/bin/python3 2*795d594fSAndroid Build Coastguard Worker# 3*795d594fSAndroid Build Coastguard Worker# Copyright 2020, The Android Open Source Project 4*795d594fSAndroid Build Coastguard Worker# 5*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*795d594fSAndroid Build Coastguard Worker# 9*795d594fSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*795d594fSAndroid Build Coastguard Worker# 11*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*795d594fSAndroid Build Coastguard Worker# limitations under the License. 16*795d594fSAndroid Build Coastguard Worker"""Converts a method to a descriptor or vice-versa. 17*795d594fSAndroid Build Coastguard Worker 18*795d594fSAndroid Build Coastguard Workereg: 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker% echo 'void myclass.foobar(long, java.lang.Object)' | method-to-descriptor.py 21*795d594fSAndroid Build Coastguard WorkerLmyclass;->foobar(jLjaga/lang/Object;)V 22*795d594fSAndroid Build Coastguard Worker% echo 'Lmyclass;->foobar(j)V' | method2descriptor.py -r 23*795d594fSAndroid Build Coastguard Workervoid myclass.foobar(long) 24*795d594fSAndroid Build Coastguard Worker""" 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Workerimport argparse 27*795d594fSAndroid Build Coastguard Workerimport sys 28*795d594fSAndroid Build Coastguard Worker 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Workerdef GetStdinLineIter(): 31*795d594fSAndroid Build Coastguard Worker """reads from stdin""" 32*795d594fSAndroid Build Coastguard Worker return map(str.strip, sys.stdin) 33*795d594fSAndroid Build Coastguard Worker 34*795d594fSAndroid Build Coastguard Worker 35*795d594fSAndroid Build Coastguard Workerdef readDescriptor(s): 36*795d594fSAndroid Build Coastguard Worker """Reads a single descriptor and returns the string starting at the point after the descriptor""" 37*795d594fSAndroid Build Coastguard Worker if s[0] == "[": 38*795d594fSAndroid Build Coastguard Worker inner, rest = readDescriptor(s[1:]) 39*795d594fSAndroid Build Coastguard Worker return "[" + inner, rest 40*795d594fSAndroid Build Coastguard Worker elif s[0] == "L": 41*795d594fSAndroid Build Coastguard Worker type_end = s.index(";") 42*795d594fSAndroid Build Coastguard Worker return s[:type_end + 1], s[type_end + 1:] 43*795d594fSAndroid Build Coastguard Worker else: 44*795d594fSAndroid Build Coastguard Worker assert s[0] in {"B", "C", "D", "F", "I", "J", "S", "Z", "V"}, s[0] 45*795d594fSAndroid Build Coastguard Worker return s[0], s[1:] 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker 48*795d594fSAndroid Build Coastguard Worker# Descriptor to name for basic types 49*795d594fSAndroid Build Coastguard WorkerTYPE_MAP = { 50*795d594fSAndroid Build Coastguard Worker "V": "void", 51*795d594fSAndroid Build Coastguard Worker "B": "byte", 52*795d594fSAndroid Build Coastguard Worker "C": "char", 53*795d594fSAndroid Build Coastguard Worker "D": "double", 54*795d594fSAndroid Build Coastguard Worker "F": "float", 55*795d594fSAndroid Build Coastguard Worker "I": "int", 56*795d594fSAndroid Build Coastguard Worker "J": "long", 57*795d594fSAndroid Build Coastguard Worker "S": "short", 58*795d594fSAndroid Build Coastguard Worker "Z": "boolean" 59*795d594fSAndroid Build Coastguard Worker} 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker# Name to descriptor 62*795d594fSAndroid Build Coastguard WorkerDESC_MAP = dict((y, x) for x, y in TYPE_MAP.items()) 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Workerdef TypeDescriptorToName(desc): 65*795d594fSAndroid Build Coastguard Worker """Turn a single type descirptor into a name""" 66*795d594fSAndroid Build Coastguard Worker if desc[0] == "[": 67*795d594fSAndroid Build Coastguard Worker inner = TypeDescriptorToName(desc[1:]) 68*795d594fSAndroid Build Coastguard Worker return inner + "[]" 69*795d594fSAndroid Build Coastguard Worker elif desc[0] == "L": 70*795d594fSAndroid Build Coastguard Worker assert desc[-1] == ";", desc 71*795d594fSAndroid Build Coastguard Worker return desc[1:-1].replace("/", ".") 72*795d594fSAndroid Build Coastguard Worker else: 73*795d594fSAndroid Build Coastguard Worker return TYPE_MAP[desc] 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Workerdef DescriptorToName(desc): 76*795d594fSAndroid Build Coastguard Worker """Turn a method descriptor into a name""" 77*795d594fSAndroid Build Coastguard Worker class_name, rest = readDescriptor(desc) 78*795d594fSAndroid Build Coastguard Worker assert rest[0:2] == "->", desc 79*795d594fSAndroid Build Coastguard Worker rest = rest[2:] 80*795d594fSAndroid Build Coastguard Worker args_start = rest.index("(") 81*795d594fSAndroid Build Coastguard Worker func_name = rest[:args_start] 82*795d594fSAndroid Build Coastguard Worker rest = rest[args_start + 1:] 83*795d594fSAndroid Build Coastguard Worker args = [] 84*795d594fSAndroid Build Coastguard Worker while rest[0] != ")": 85*795d594fSAndroid Build Coastguard Worker cur_arg, rest = readDescriptor(rest) 86*795d594fSAndroid Build Coastguard Worker args.append(cur_arg) 87*795d594fSAndroid Build Coastguard Worker rest = rest[1:] 88*795d594fSAndroid Build Coastguard Worker return_type, rest = readDescriptor(rest) 89*795d594fSAndroid Build Coastguard Worker assert rest.strip() == "", desc 90*795d594fSAndroid Build Coastguard Worker return "{} {}.{}({})".format( 91*795d594fSAndroid Build Coastguard Worker TypeDescriptorToName(return_type), TypeDescriptorToName(class_name), 92*795d594fSAndroid Build Coastguard Worker func_name, ",".join(map(TypeDescriptorToName, args))) 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Workerdef SingleNameToDescriptor(name): 95*795d594fSAndroid Build Coastguard Worker if name in DESC_MAP: 96*795d594fSAndroid Build Coastguard Worker return DESC_MAP[name] 97*795d594fSAndroid Build Coastguard Worker elif name.endswith("[]"): 98*795d594fSAndroid Build Coastguard Worker return "[" + SingleNameToDescriptor(name[:-2]) 99*795d594fSAndroid Build Coastguard Worker elif name == "": 100*795d594fSAndroid Build Coastguard Worker return "" 101*795d594fSAndroid Build Coastguard Worker else: 102*795d594fSAndroid Build Coastguard Worker return "L" + name.replace(".", "/") + ";" 103*795d594fSAndroid Build Coastguard Worker 104*795d594fSAndroid Build Coastguard Worker 105*795d594fSAndroid Build Coastguard Workerdef NameToDescriptor(desc): 106*795d594fSAndroid Build Coastguard Worker return_name = desc.split()[0] 107*795d594fSAndroid Build Coastguard Worker name_and_args = desc.split()[1] 108*795d594fSAndroid Build Coastguard Worker args_start = name_and_args.index("(") 109*795d594fSAndroid Build Coastguard Worker names = name_and_args[0:args_start] 110*795d594fSAndroid Build Coastguard Worker meth_split = names.rfind(".") 111*795d594fSAndroid Build Coastguard Worker class_name = names[:meth_split] 112*795d594fSAndroid Build Coastguard Worker meth_name = names[meth_split + 1:] 113*795d594fSAndroid Build Coastguard Worker args = map(str.strip, name_and_args[args_start + 1:-1].split(",")) 114*795d594fSAndroid Build Coastguard Worker return "{}->{}({}){}".format( 115*795d594fSAndroid Build Coastguard Worker SingleNameToDescriptor(class_name), meth_name, 116*795d594fSAndroid Build Coastguard Worker "".join(map(SingleNameToDescriptor, args)), 117*795d594fSAndroid Build Coastguard Worker SingleNameToDescriptor(return_name)) 118*795d594fSAndroid Build Coastguard Worker 119*795d594fSAndroid Build Coastguard Worker 120*795d594fSAndroid Build Coastguard Workerdef main(): 121*795d594fSAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 122*795d594fSAndroid Build Coastguard Worker "method-to-descriptor.py", 123*795d594fSAndroid Build Coastguard Worker description="Convert a java method-name/stream into it's descriptor or vice-versa." 124*795d594fSAndroid Build Coastguard Worker ) 125*795d594fSAndroid Build Coastguard Worker parser.add_argument( 126*795d594fSAndroid Build Coastguard Worker "-r", 127*795d594fSAndroid Build Coastguard Worker "--reverse", 128*795d594fSAndroid Build Coastguard Worker dest="reverse", 129*795d594fSAndroid Build Coastguard Worker action="store_true", 130*795d594fSAndroid Build Coastguard Worker default=False, 131*795d594fSAndroid Build Coastguard Worker help="reverse. Go from descriptor to method-declaration") 132*795d594fSAndroid Build Coastguard Worker parser.add_argument("method", help="what to change", nargs="*") 133*795d594fSAndroid Build Coastguard Worker args = parser.parse_args() 134*795d594fSAndroid Build Coastguard Worker if args.method != []: 135*795d594fSAndroid Build Coastguard Worker inputs = iter(args.method) 136*795d594fSAndroid Build Coastguard Worker else: 137*795d594fSAndroid Build Coastguard Worker inputs = GetStdinLineIter() 138*795d594fSAndroid Build Coastguard Worker for name in inputs: 139*795d594fSAndroid Build Coastguard Worker if args.reverse: 140*795d594fSAndroid Build Coastguard Worker print(DescriptorToName(name)) 141*795d594fSAndroid Build Coastguard Worker else: 142*795d594fSAndroid Build Coastguard Worker print(NameToDescriptor(name)) 143*795d594fSAndroid Build Coastguard Worker 144*795d594fSAndroid Build Coastguard Worker 145*795d594fSAndroid Build Coastguard Workerif __name__ == "__main__": 146*795d594fSAndroid Build Coastguard Worker main() 147