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 """ 18 Usage: java-event-log-tags.py [-o output_file] <input_file> <merged_tags_file> 19 20 Generate a java class containing constants for each of the event log 21 tags in the given input file. 22 23 -h to display this usage message and exit. 24 """ 25 26 import cStringIO 27 import getopt 28 import os 29 import os.path 30 import re 31 import sys 32 33 import event_log_tags 34 35 output_file = None 36 37 try: 38 opts, args = getopt.getopt(sys.argv[1:], "ho:") 39 except getopt.GetoptError, err: 40 print str(err) 41 print __doc__ 42 sys.exit(2) 43 44 for 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 54 if 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 59 fn = args[0] 60 tagfile = event_log_tags.TagFile(fn) 61 62 if 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 79 else: 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 86 if "java_package" not in tagfile.options: 87 tagfile.AddError("java_package option not specified", linenum=0) 88 89 hide = True 90 if "javadoc_hide" in tagfile.options: 91 hide = event_log_tags.BooleanFromString(tagfile.options["javadoc_hide"][0]) 92 93 if 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 98 buffer = cStringIO.StringIO() 99 buffer.write("/* This file is auto-generated. DO NOT MODIFY.\n" 100 " * Source file: %s\n" 101 " */\n\n" % (fn,)) 102 103 buffer.write("package %s;\n\n" % (tagfile.options["java_package"][0],)) 104 105 basename, _ = os.path.splitext(os.path.basename(fn)) 106 107 if hide: 108 buffer.write("/**\n" 109 " * @hide\n" 110 " */\n") 111 buffer.write("public class %s {\n" % (basename,)) 112 buffer.write(" private %s() { } // don't instantiate\n" % (basename,)) 113 114 for 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 123 keywords = 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 133 def 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 139 javaTypes = ["ERROR", "int", "long", "String", "Object[]", "float"] 140 for 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 153 buffer.write("}\n"); 154 155 output_dir = os.path.dirname(output_file) 156 if not os.path.exists(output_dir): 157 os.makedirs(output_dir) 158 159 event_log_tags.WriteOutput(output_file, buffer) 160