Commit | Line | Data |
---|---|---|
b25c5b37 YB |
1 | #!/usr/bin/python |
2 | # | |
3 | # Copyright (c) 2012 Yannick Brosseau <yannick.brosseau@gmail.com> | |
4 | # | |
5 | # This program is free software; you can redistribute it and/or | |
6 | # modify it under the terms of the GNU General Public License | |
7 | # as published by the Free Software Foundation; only version 2 | |
8 | # of the License. | |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | # GNU General Public License for more details. | |
14 | # | |
15 | # You should have received a copy of the GNU General Public License along | |
16 | # with this program; if not, write to the Free Software Foundation, Inc., | |
17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 | ||
19 | import sys | |
20 | import getopt | |
21 | import re | |
22 | ||
23 | class Usage(Exception): | |
24 | def __init__(self, msg): | |
25 | self.msg = msg | |
26 | ||
27 | class HeaderFile: | |
28 | HEADER_TPL=""" | |
29 | #undef TRACEPOINT_PROVIDER | |
30 | #define TRACEPOINT_PROVIDER {providerName} | |
31 | ||
32 | #undef TRACEPOINT_INCLUDE_FILE | |
33 | #define TRACEPOINT_INCLUDE_FILE ./{headerFilename} | |
34 | ||
35 | #ifdef __cplusplus | |
36 | #extern "C"{{ | |
37 | #endif /*__cplusplus */ | |
38 | ||
39 | ||
40 | #if !defined({includeGuard}) || defined(TRACEPOINT_HEADER_MULTI_READ) | |
41 | #define {includeGuard} | |
42 | ||
43 | #include <lttng/tracepoint.h> | |
44 | ||
45 | """ | |
46 | FOOTER_TPL=""" | |
47 | #endif /* {includeGuard} */ | |
48 | ||
49 | #include <lttng/tracepoint-event.h> | |
50 | ||
51 | #ifdef __cplusplus | |
52 | }} | |
53 | #endif /*__cplusplus */ | |
54 | ||
55 | """ | |
56 | def __init__(self, filename, template): | |
57 | self.outputFilename = filename | |
58 | self.template = template | |
59 | ||
60 | def write(self): | |
61 | outputFile = open(self.outputFilename,"w") | |
62 | includeGuard = "_"+self.outputFilename.upper().replace(".","_") | |
63 | ||
64 | outputFile.write(HeaderFile.HEADER_TPL.format(providerName=self.template.domain, | |
65 | includeGuard = includeGuard, | |
66 | headerFilename = self.outputFilename)) | |
67 | outputFile.write(self.template.text) | |
68 | outputFile.write(HeaderFile.FOOTER_TPL.format(includeGuard = includeGuard)) | |
69 | outputFile.close() | |
70 | ||
71 | class CFile: | |
72 | FILE_TPL=""" | |
73 | #define TRACEPOINT_CREATE_PROBES | |
74 | /* | |
75 | * The header containing our TRACEPOINT_EVENTs. | |
76 | */ | |
77 | #define TRACEPOINT_DEFINE | |
78 | #include "{headerFilename}" | |
79 | """ | |
80 | def __init__(self, filename, template): | |
81 | self.outputFilename = filename | |
82 | self.template = template | |
83 | ||
84 | def write(self): | |
85 | outputFile = open(self.outputFilename,"w") | |
86 | ||
87 | headerFilename = self.outputFilename.replace(".c",".h") | |
88 | ||
89 | outputFile.write(CFile.FILE_TPL.format( | |
90 | headerFilename = headerFilename)) | |
91 | outputFile.close() | |
92 | ||
93 | class TemplateFile: | |
94 | def __init__(self, filename): | |
95 | self.domain = "" | |
96 | self.inputFilename = filename | |
97 | self.parseTemplate() | |
98 | ||
99 | ||
100 | def parseTemplate(self): | |
101 | f = open(self.inputFilename,"r") | |
102 | ||
103 | self.text = f.read() | |
104 | ||
105 | #Remove # comments (from input and output file | |
106 | self.text = re.sub("#.*$","",self.text,flags=re.MULTILINE) | |
107 | #Remove // comments | |
108 | nolinecomment = re.sub("\/\/.*$","",self.text,flags=re.MULTILINE) | |
109 | #Remove all spaces and lines | |
110 | cleantext = re.sub("\s*","",nolinecomment) | |
111 | #Remove multine C style comments | |
112 | nocomment = re.sub("/\*.*?\*/","",cleantext) | |
113 | entries = re.split("TRACEPOINT_.*?",nocomment) | |
114 | ||
115 | for entry in entries: | |
116 | if entry != '': | |
117 | decomp = re.findall("(\w*?)\((\w*?),(\w*?),", entry) | |
118 | typea = decomp[0][0] | |
119 | domain = decomp[0][1] | |
120 | name = decomp[0][2] | |
121 | ||
122 | if self.domain == "": | |
123 | self.domain = domain | |
124 | else: | |
125 | if self.domain != domain: | |
126 | print "Warning: different domain provided (%s,%s)" % (self.domain, domain) | |
127 | ||
128 | usage=""" | |
129 | lttng-gen-tp - Generate the LTTng-UST header and source based on a simple template | |
130 | ||
131 | usage: lttng-gen-tp TEMPLATE_FILE [-o OUTPUT_FILE][-o OUTPUT_FILE] | |
132 | ||
133 | If no OUTPUT_FILE is given, the .h and .c file will be generated. | |
134 | (The basename of the template file with be used for the generated file. | |
135 | for example sample.tp will generate sample.h and sample.c) | |
136 | ||
137 | When using the -o option, the OUTPUT_FILE must end with either .h or .c | |
138 | The -o option can be repeated multiple times. | |
139 | ||
140 | The template file must contains TRACEPOINT_EVENT and TRACEPOINT_LOGLEVEL | |
141 | as per defined in the lttng/tracepoint.h file. | |
142 | See the lttng-ust(3) man page for more details on the format. | |
143 | """ | |
144 | def main(argv=None): | |
145 | if argv is None: | |
146 | argv = sys.argv | |
147 | ||
148 | try: | |
149 | try: | |
150 | opts, args = getopt.gnu_getopt(argv[1:], "ho:a", ["help"]) | |
151 | except getopt.error, msg: | |
152 | raise Usage(msg) | |
153 | ||
154 | except Usage, err: | |
155 | print >>sys.stderr, err.msg | |
156 | print >>sys.stderr, "for help use --help" | |
157 | return 2 | |
158 | ||
159 | outputNames = [] | |
160 | for o, a in opts: | |
161 | if o in ("-h", "--help"): | |
162 | print usage | |
163 | return(0) | |
164 | if o in ("-o",""): | |
165 | outputNames.append(a) | |
166 | if o in ("-a",""): | |
167 | all = True | |
168 | ||
169 | doCFile = None | |
170 | doHeader = None | |
171 | headerFilename = None | |
172 | cFilename = None | |
173 | ||
174 | if len(outputNames) > 0: | |
175 | if len(args) > 1: | |
176 | print "Cannot process more than one input if you specify an output" | |
177 | return(3) | |
178 | ||
179 | for outputName in outputNames: | |
180 | if outputName[-2:] == ".h": | |
181 | doHeader = True | |
182 | headerFilename = outputName | |
183 | elif outputName[-2:] == ".c": | |
184 | doCFile = True | |
185 | cFilename = outputName | |
186 | elif outputName[-2:] == ".o": | |
187 | print "Not yet implemented, sorry" | |
188 | else: | |
189 | print "output file type unsupported" | |
190 | return(4) | |
191 | else: | |
192 | doHeader = True | |
193 | doCFile = True | |
194 | ||
195 | # process arguments | |
196 | for arg in args: | |
197 | ||
198 | tpl = TemplateFile(arg) | |
199 | if doHeader: | |
200 | if headerFilename: | |
201 | curFilename = headerFilename | |
202 | else: | |
203 | curFilename = re.sub("\.tp$",".h",arg) | |
204 | doth = HeaderFile(curFilename, tpl) | |
205 | doth.write() | |
206 | if doCFile: | |
207 | if cFilename: | |
208 | curFilename = cFilename | |
209 | else: | |
210 | curFilename = re.sub("\.tp$",".c",arg) | |
211 | dotc = CFile(curFilename, tpl) | |
212 | dotc.write() | |
213 | ||
214 | if __name__ == "__main__": | |
215 | sys.exit(main()) |