1#!/usr/bin/env python 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 26import cStringIO 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, 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 >> sys.stderr, "unhandled option %s" % (o,) 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 >> sys.stderr, "%s:%d: error: %s" % (fn, ln, msg) 96 sys.exit(1) 97 98buffer = cStringIO.StringIO() 99buffer.write("/* This file is auto-generated. DO NOT MODIFY.\n" 100 " * Source file: %s\n" 101 " */\n\n" % (fn,)) 102 103buffer.write("package %s;\n\n" % (tagfile.options["java_package"][0],)) 104 105basename, _ = os.path.splitext(os.path.basename(fn)) 106 107if hide: 108 buffer.write("/**\n" 109 " * @hide\n" 110 " */\n") 111buffer.write("public class %s {\n" % (basename,)) 112buffer.write(" private %s() { } // don't instantiate\n" % (basename,)) 113 114for t in tagfile.tags: 115 if t.description: 116 buffer.write("\n /** %d %s %s */\n" % (t.tagnum, t.tagname, t.description)) 117 else: 118 buffer.write("\n /** %d %s */\n" % (t.tagnum, t.tagname)) 119 120 buffer.write(" public static final int %s = %d;\n" % 121 (t.tagname.upper(), t.tagnum)) 122 123keywords = frozenset(["abstract", "continue", "for", "new", "switch", "assert", 124 "default", "goto", "package", "synchronized", "boolean", 125 "do", "if", "private", "this", "break", "double", 126 "implements", "protected", "throw", "byte", "else", 127 "import", "public", "throws", "case", "enum", 128 "instanceof", "return", "transient", "catch", "extends", 129 "int", "short", "try", "char", "final", "interface", 130 "static", "void", "class", "finally", "long", "strictfp", 131 "volatile", "const", "float", "native", "super", "while"]) 132 133def javaName(name): 134 out = name[0].lower() + re.sub(r"[^A-Za-z0-9]", "", name.title())[1:] 135 if out in keywords: 136 out += "_" 137 return out 138 139javaTypes = ["ERROR", "int", "long", "String", "Object[]", "float"] 140for t in tagfile.tags: 141 methodName = javaName("write_" + t.tagname) 142 if t.description: 143 args = [arg.strip("() ").split("|") for arg in t.description.split(",")] 144 else: 145 args = [] 146 argTypesNames = ", ".join([javaTypes[int(arg[1])] + " " + javaName(arg[0]) for arg in args]) 147 argNames = "".join([", " + javaName(arg[0]) for arg in args]) 148 buffer.write("\n public static void %s(%s) {" % (methodName, argTypesNames)) 149 buffer.write("\n android.util.EventLog.writeEvent(%s%s);" % (t.tagname.upper(), argNames)) 150 buffer.write("\n }\n") 151 152 153buffer.write("}\n"); 154 155output_dir = os.path.dirname(output_file) 156if not os.path.exists(output_dir): 157 os.makedirs(output_dir) 158 159event_log_tags.WriteOutput(output_file, buffer) 160