Home | History | Annotate | Download | only in scripts
      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
     23 from __future__ import print_function
     24 import os
     25 import sys
     26 import re
     27 import argparse
     28 from mako.template import Template
     29 from mako.exceptions import RichTraceback
     30 
     31 def write_template_to_string(template_filename, **kwargs):
     32     try:
     33         template = Template(filename=template_filename)
     34         # Split + Join fixes line-endings for whatever platform you are using
     35         return '\n'.join(template.render(**kwargs).splitlines())
     36     except:
     37         traceback = RichTraceback()
     38         for (filename, lineno, function, line) in traceback.traceback:
     39             print("File %s, line %s, in %s" % (filename, lineno, function))
     40             print(line, "\n")
     41         print("%s: %s" % (str(traceback.error.__class__.__name__), traceback.error))
     42 
     43 def write_template_to_file(template_filename, output_filename, **kwargs):
     44     with open(output_filename, "w") as outfile:
     45         print(write_template_to_string(template_filename, **kwargs), file=outfile)
     46 
     47 def parse_event_fields(lines, idx, event_dict):
     48     field_names = []
     49     field_types = []
     50     end_of_event = False
     51 
     52     num_fields = 0
     53 
     54     # record all fields in event definition.
     55     # note: we don't check if there's a leading brace.
     56     while not end_of_event and idx < len(lines):
     57         line = lines[idx].rstrip()
     58         idx += 1
     59 
     60         field = re.match(r"(\s*)(\w+)(\s*)(\w+)", line)
     61 
     62         if field:
     63             field_types.append(field.group(2))
     64             field_names.append(field.group(4))
     65             num_fields += 1
     66 
     67         end_of_event = re.match(r"(\s*)};", line)
     68 
     69     event_dict['field_types'] = field_types
     70     event_dict['field_names'] = field_names
     71     event_dict['num_fields'] = num_fields
     72 
     73     return idx
     74 
     75 def parse_enums(lines, idx, event_dict):
     76     enum_names = []
     77     end_of_enum = False
     78 
     79     # record all enum values in enumeration
     80     # note: we don't check if there's a leading brace.
     81     while not end_of_enum and idx < len(lines):
     82         line = lines[idx].rstrip()
     83         idx += 1
     84 
     85         preprocessor = re.search(r"#if|#endif", line)
     86 
     87         if not preprocessor:
     88             enum = re.match(r"(\s*)(\w+)(\s*)", line)
     89 
     90             if enum:
     91                 enum_names.append(line)
     92 
     93             end_of_enum = re.match(r"(\s*)};", line)
     94 
     95     event_dict['names'] = enum_names
     96     return idx
     97 
     98 def parse_protos(filename):
     99     protos = {}
    100 
    101     with open(filename, 'r') as f:
    102         lines=f.readlines()
    103 
    104         idx = 0
    105 
    106         protos['events'] = {}       # event dictionary containing events with their fields
    107         protos['event_names'] = []  # needed to keep events in order parsed. dict is not ordered.
    108         protos['enums'] = {}
    109         protos['enum_names'] = []
    110 
    111         eventId = 0
    112         raw_text = []
    113         while idx < len(lines):
    114             line = lines[idx].rstrip()
    115             idx += 1
    116 
    117             # search for event definitions.
    118             match = re.match(r"(\s*)event(\s*)(\w+)", line)
    119 
    120             if match:
    121                 eventId += 1
    122                 event_name = match.group(3)
    123                 protos['event_names'].append(event_name)
    124 
    125                 protos['events'][event_name] = {}
    126                 protos['events'][event_name]['event_id'] = eventId
    127                 idx = parse_event_fields(lines, idx, protos['events'][event_name])
    128 
    129             # search for enums.
    130             match = re.match(r"(\s*)enum(\s*)(\w+)", line)
    131 
    132             if match:
    133                 enum_name = match.group(3)
    134                 protos['enum_names'].append(enum_name)
    135 
    136                 protos['enums'][enum_name] = {}
    137                 idx = parse_enums(lines, idx, protos['enums'][enum_name])
    138 
    139     return protos
    140 
    141 def main():
    142 
    143     # Parse args...
    144     parser = argparse.ArgumentParser()
    145     parser.add_argument("--proto", "-p", help="Path to proto file", required=True)
    146     parser.add_argument("--output", "-o", help="Output filename (i.e. event.h)", required=True)
    147     parser.add_argument("--gen_event_h", "-geh", help="Generate event header", action="store_true", default=False)
    148     parser.add_argument("--gen_event_cpp", "-gec", help="Generate event cpp", action="store_true", default=False)
    149     parser.add_argument("--gen_eventhandler_h", "-gehh", help="Generate eventhandler header", action="store_true", default=False)
    150     parser.add_argument("--gen_eventhandlerfile_h", "-gehf", help="Generate eventhandler header for writing to files", action="store_true", default=False)
    151     args = parser.parse_args()
    152 
    153     proto_filename = args.proto
    154 
    155     (output_dir, output_filename) = os.path.split(args.output)
    156 
    157     if not output_dir:
    158         output_dir = "."
    159 
    160     #print("output_dir = %s" % output_dir, file=sys.stderr)
    161     #print("output_filename = %s" % output_filename, file=sys.stderr)
    162 
    163     if not os.path.exists(proto_filename):
    164         print("Error: Could not find proto file %s" % proto_filename, file=sys.stderr)
    165         return 1
    166 
    167     protos = parse_protos(proto_filename)
    168 
    169     # Generate event header
    170     if args.gen_event_h:
    171         curdir = os.path.dirname(os.path.abspath(__file__))
    172         template_file = os.sep.join([curdir, 'templates', 'ar_event_h.template'])
    173         output_fullpath = os.sep.join([output_dir, output_filename])
    174 
    175         write_template_to_file(template_file, output_fullpath,
    176                 filename=output_filename,
    177                 protos=protos)
    178 
    179     # Generate event implementation
    180     if args.gen_event_cpp:
    181         curdir = os.path.dirname(os.path.abspath(__file__))
    182         template_file = os.sep.join([curdir, 'templates', 'ar_event_cpp.template'])
    183         output_fullpath = os.sep.join([output_dir, output_filename])
    184 
    185         write_template_to_file(template_file, output_fullpath,
    186                 filename=output_filename,
    187                 protos=protos)
    188 
    189     # Generate event handler header
    190     if args.gen_eventhandler_h:
    191         curdir = os.path.dirname(os.path.abspath(__file__))
    192         template_file = os.sep.join([curdir, 'templates', 'ar_eventhandler_h.template'])
    193         output_fullpath = os.sep.join([output_dir, output_filename])
    194 
    195         write_template_to_file(template_file, output_fullpath,
    196                 filename=output_filename,
    197                 event_header="gen_ar_event.h",   # todo: fix this!
    198                 protos=protos)
    199 
    200     # Generate event handler header
    201     if args.gen_eventhandlerfile_h:
    202         curdir = os.path.dirname(os.path.abspath(__file__))
    203         template_file = os.sep.join([curdir, 'templates', 'ar_eventhandlerfile_h.template'])
    204         output_fullpath = os.sep.join([output_dir, output_filename])
    205 
    206         write_template_to_file(template_file, output_fullpath,
    207                 filename=output_filename,
    208                 event_header="gen_ar_eventhandler.h",   # todo: fix this!
    209                 protos=protos)
    210 
    211     return 0
    212 
    213 if __name__ == '__main__':
    214     sys.exit(main())
    215 
    216