1#!/usr/bin/env python3 2# 3# Copyright (C) 2009 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17""" 18Usage: java-event-log-tags.py [-o output_file] <input_file> <merged_tags_file> 19 20Generate a java class containing constants for each of the event log 21tags in the given input file. 22 23-h to display this usage message and exit. 24""" 25 26from io import StringIO 27import getopt 28import os 29import os.path 30import re 31import sys 32 33import event_log_tags 34 35output_file = None 36 37try: 38 opts, args = getopt.getopt(sys.argv[1:], "ho:") 39except getopt.GetoptError as err: 40 print(str(err)) 41 print(__doc__) 42 sys.exit(2) 43 44for o, a in opts: 45 if o == "-h": 46 print(__doc__) 47 sys.exit(2) 48 elif o == "-o": 49 output_file = a 50 else: 51 print("unhandled option %s" % (o,), file=sys.stderr) 52 sys.exit(1) 53 54if len(args) != 1 and len(args) != 2: 55 print("need one or two input files, not %d" % (len(args),)) 56 print(__doc__) 57 sys.exit(1) 58 59fn = args[0] 60tagfile = event_log_tags.TagFile(fn) 61 62if len(args) > 1: 63 # Load the merged tag file (which should have numbers assigned for all 64 # tags. Use the numbers from the merged file to fill in any missing 65 # numbers from the input file. 66 merged_fn = args[1] 67 merged_tagfile = event_log_tags.TagFile(merged_fn) 68 merged_by_name = dict([(t.tagname, t) for t in merged_tagfile.tags]) 69 for t in tagfile.tags: 70 if t.tagnum is None: 71 if t.tagname in merged_by_name: 72 t.tagnum = merged_by_name[t.tagname].tagnum 73 else: 74 # We're building something that's not being included in the 75 # product, so its tags don't appear in the merged file. Assign 76 # them all an arbitrary number so we can emit the java and 77 # compile the (unused) package. 78 t.tagnum = 999999 79else: 80 # Not using the merged tag file, so all tags must have manually assigned 81 # numbers 82 for t in tagfile.tags: 83 if t.tagnum is None: 84 tagfilef.AddError("tag \"%s\" has no number" % (tagname,), tag.linenum) 85 86if "java_package" not in tagfile.options: 87 tagfile.AddError("java_package option not specified", linenum=0) 88 89hide = True 90if "javadoc_hide" in tagfile.options: 91 hide = event_log_tags.BooleanFromString(tagfile.options["javadoc_hide"][0]) 92 93if tagfile.errors: 94 for fn, ln, msg in tagfile.errors: 95 print("%s:%d: error: %s" % (fn, ln, msg), file=sys.stderr) 96 sys.exit(1) 97 98buffer = StringIO() 99buffer.write("/* This file is auto-generated. DO NOT MODIFY.\n" 100 " * Source file: %s\n" 101 " */\n\n" % (fn,)) 102 103# .rstrip(";") to avoid an empty top-level statement errorprone error 104buffer.write("package %s;\n\n" % (tagfile.options["java_package"][0].rstrip(";"),)) 105 106basename, _ = os.path.splitext(os.path.basename(fn)) 107 108if hide: 109 buffer.write("/**\n" 110 " * @hide\n" 111 " */\n") 112buffer.write("public class %s {\n" % (basename,)) 113buffer.write(" private %s() { } // don't instantiate\n" % (basename,)) 114 115for t in tagfile.tags: 116 if t.description: 117 buffer.write("\n /** %d %s %s */\n" % (t.tagnum, t.tagname, t.description)) 118 else: 119 buffer.write("\n /** %d %s */\n" % (t.tagnum, t.tagname)) 120 121 buffer.write(" public static final int %s = %d;\n" % 122 (t.tagname.upper(), t.tagnum)) 123 124keywords = frozenset(["abstract", "continue", "for", "new", "switch", "assert", 125 "default", "goto", "package", "synchronized", "boolean", 126 "do", "if", "private", "this", "break", "double", 127 "implements", "protected", "throw", "byte", "else", 128 "import", "public", "throws", "case", "enum", 129 "instanceof", "return", "transient", "catch", "extends", 130 "int", "short", "try", "char", "final", "interface", 131 "static", "void", "class", "finally", "long", "strictfp", 132 "volatile", "const", "float", "native", "super", "while"]) 133 134def javaName(name): 135 out = name[0].lower() + re.sub(r"[^A-Za-z0-9]", "", name.title())[1:] 136 if out in keywords: 137 out += "_" 138 return out 139 140javaTypes = ["ERROR", "int", "long", "String", "Object[]", "float"] 141for t in tagfile.tags: 142 methodName = javaName("write_" + t.tagname) 143 if t.description: 144 args = [arg.strip("() ").split("|") for arg in t.description.split(",")] 145 else: 146 args = [] 147 argTypesNames = ", ".join([javaTypes[int(arg[1])] + " " + javaName(arg[0]) for arg in args]) 148 argNames = "".join([", " + javaName(arg[0]) for arg in args]) 149 buffer.write("\n public static void %s(%s) {" % (methodName, argTypesNames)) 150 buffer.write("\n android.util.EventLog.writeEvent(%s%s);" % (t.tagname.upper(), argNames)) 151 buffer.write("\n }\n") 152 153 154buffer.write("}\n"); 155 156output_dir = os.path.dirname(output_file) 157if not os.path.exists(output_dir): 158 os.makedirs(output_dir) 159 160event_log_tags.WriteOutput(output_file, buffer) 161