1# Copyright (C) 2014-2016 Intel Corporation.   All Rights Reserved.
2#
3# Permission is hereby granted, free of charge, to any person obtaining a
4# copy of this software and associated documentation files (the "Software"),
5# to deal in the Software without restriction, including without limitation
6# the rights to use, copy, modify, merge, publish, distribute, sublicense,
7# and/or sell copies of the Software, and to permit persons to whom the
8# Software is furnished to do so, subject to the following conditions:
9#
10# The above copyright notice and this permission notice (including the next
11# paragraph) shall be included in all copies or substantial portions of the
12# Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20# IN THE SOFTWARE.
21
22# Python source
23from __future__ import print_function
24import os
25import sys
26import re
27from gen_common import ArgumentParser, MakoTemplateWriter
28
29def parse_event_fields(lines, idx, event_dict):
30    field_names = []
31    field_types = []
32    end_of_event = False
33
34    num_fields = 0
35
36    # record all fields in event definition.
37    # note: we don't check if there's a leading brace.
38    while not end_of_event and idx < len(lines):
39        line = lines[idx].rstrip()
40        idx += 1
41
42        field = re.match(r'(\s*)(\w+)(\s*)(\w+)', line)
43
44        if field:
45            field_types.append(field.group(2))
46            field_names.append(field.group(4))
47            num_fields += 1
48
49        end_of_event = re.match(r'(\s*)};', line)
50
51    event_dict['field_types'] = field_types
52    event_dict['field_names'] = field_names
53    event_dict['num_fields'] = num_fields
54
55    return idx
56
57def parse_enums(lines, idx, event_dict):
58    enum_names = []
59    end_of_enum = False
60
61    # record all enum values in enumeration
62    # note: we don't check if there's a leading brace.
63    while not end_of_enum and idx < len(lines):
64        line = lines[idx].rstrip()
65        idx += 1
66
67        preprocessor = re.search(r'#if|#endif', line)
68
69        if not preprocessor:
70            enum = re.match(r'(\s*)(\w+)(\s*)', line)
71
72            if enum:
73                enum_names.append(line)
74
75            end_of_enum = re.match(r'(\s*)};', line)
76
77    event_dict['names'] = enum_names
78    return idx
79
80def parse_protos(filename):
81    protos = {}
82
83    with open(filename, 'r') as f:
84        lines=f.readlines()
85
86        idx = 0
87
88        protos['events'] = {}       # event dictionary containing events with their fields
89        protos['event_names'] = []  # needed to keep events in order parsed. dict is not ordered.
90        protos['enums'] = {}
91        protos['enum_names'] = []
92
93        eventId = 0
94        raw_text = []
95        while idx < len(lines):
96            line = lines[idx].rstrip()
97            idx += 1
98
99            # search for event definitions.
100            match = re.match(r'(\s*)event(\s*)(\w+)', line)
101
102            if match:
103                eventId += 1
104                event_name = match.group(3)
105                protos['event_names'].append(event_name)
106
107                protos['events'][event_name] = {}
108                protos['events'][event_name]['event_id'] = eventId
109                idx = parse_event_fields(lines, idx, protos['events'][event_name])
110
111            # search for enums.
112            match = re.match(r'(\s*)enum(\s*)(\w+)', line)
113
114            if match:
115                enum_name = match.group(3)
116                protos['enum_names'].append(enum_name)
117
118                protos['enums'][enum_name] = {}
119                idx = parse_enums(lines, idx, protos['enums'][enum_name])
120
121    return protos
122
123def main():
124
125    # Parse args...
126    parser = ArgumentParser()
127    parser.add_argument('--proto', '-p', help='Path to proto file', required=True)
128    parser.add_argument('--output', '-o', help='Output filename (i.e. event.hpp)', required=True)
129    parser.add_argument('--gen_event_hpp', help='Generate event header', action='store_true', default=False)
130    parser.add_argument('--gen_event_cpp', help='Generate event cpp', action='store_true', default=False)
131    parser.add_argument('--gen_eventhandler_hpp', help='Generate eventhandler header', action='store_true', default=False)
132    parser.add_argument('--gen_eventhandlerfile_hpp', help='Generate eventhandler header for writing to files', action='store_true', default=False)
133    args = parser.parse_args()
134
135    proto_filename = args.proto
136
137    (output_dir, output_filename) = os.path.split(args.output)
138
139    if not output_dir:
140        output_dir = '.'
141
142    #print('output_dir = %s' % output_dir, file=sys.stderr)
143    #print('output_filename = %s' % output_filename, file=sys.stderr)
144
145    if not os.path.exists(proto_filename):
146        print('Error: Could not find proto file %s' % proto_filename, file=sys.stderr)
147        return 1
148
149    protos = parse_protos(proto_filename)
150
151    # Generate event header
152    if args.gen_event_hpp:
153        curdir = os.path.dirname(os.path.abspath(__file__))
154        template_file = os.sep.join([curdir, 'templates', 'gen_ar_event.hpp'])
155        output_fullpath = os.sep.join([output_dir, output_filename])
156
157        MakoTemplateWriter.to_file(template_file, output_fullpath,
158                cmdline=sys.argv,
159                filename=output_filename,
160                protos=protos)
161
162    # Generate event implementation
163    if args.gen_event_cpp:
164        curdir = os.path.dirname(os.path.abspath(__file__))
165        template_file = os.sep.join([curdir, 'templates', 'gen_ar_event.cpp'])
166        output_fullpath = os.sep.join([output_dir, output_filename])
167
168        MakoTemplateWriter.to_file(template_file, output_fullpath,
169                cmdline=sys.argv,
170                filename=output_filename,
171                protos=protos)
172
173    # Generate event handler header
174    if args.gen_eventhandler_hpp:
175        curdir = os.path.dirname(os.path.abspath(__file__))
176        template_file = os.sep.join([curdir, 'templates', 'gen_ar_eventhandler.hpp'])
177        output_fullpath = os.sep.join([output_dir, output_filename])
178
179        MakoTemplateWriter.to_file(template_file, output_fullpath,
180                cmdline=sys.argv,
181                filename=output_filename,
182                event_header='gen_ar_event.hpp',
183                protos=protos)
184
185    # Generate event handler header
186    if args.gen_eventhandlerfile_hpp:
187        curdir = os.path.dirname(os.path.abspath(__file__))
188        template_file = os.sep.join([curdir, 'templates', 'gen_ar_eventhandlerfile.hpp'])
189        output_fullpath = os.sep.join([output_dir, output_filename])
190
191        MakoTemplateWriter.to_file(template_file, output_fullpath,
192                cmdline=sys.argv,
193                filename=output_filename,
194                event_header='gen_ar_eventhandler.hpp',
195                protos=protos)
196
197    return 0
198
199if __name__ == '__main__':
200    sys.exit(main())
201
202