blob: 1259a904049030d0adac61b43d2efa3893c4da9b [file] [log] [blame]
Rich Lanea06d0c32013-03-25 08:52:03 -07001# Copyright 2013, Big Switch Networks, Inc.
2#
3# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4# the following special exception:
5#
6# LOXI Exception
7#
8# As a special exception to the terms of the EPL, you may distribute libraries
9# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10# that copyright and licensing notices generated by LoxiGen are not altered or removed
11# from the LoxiGen Libraries and the notice provided below is (i) included in
12# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13# documentation for the LoxiGen Libraries, if distributed in binary form.
14#
15# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16#
17# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18# a copy of the EPL at:
19#
20# http://www.eclipse.org/legal/epl-v10.html
21#
22# Unless required by applicable law or agreed to in writing, software
23# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25# EPL for the specific language governing permissions and limitations
26# under the EPL.
27
28##
29# @brief Utilities related to processing OF header files
30#
31
32import re
33import sys
34import os
35import c_parse_utils
36import loxi_utils.py_utils as py_utils
37import translation
38from generic_utils import *
39import copy
40
41# Silently ignore idents matching any of these
42ignore_idents = [
43 "OFPXMT_OFB_", "OFPFMF_", "OXM_OF_", "OFPXMT_",
44 "OPENFLOW_OPENFLOW_H", "OFP_ASSERT", "OFP_PACKED", "OFP_VERSION"
45 ]
46
47def warn_unmapped_ident(ident, t_name="enum"):
48 for ignore_ident in ignore_idents:
49 if re.match(ignore_ident, ident):
50 return
51 log("Skipping ident %s. Did not map %s identifier to LOXI" %
52 (ident, t_name))
53
54def fixup_values(ident, value, version, ident_list):
55 """
56 Fix up values for LOXI reasons
57
58 Translate defintions that refer to other identifiers
59 This is really just needed for the special case of OFPFW in 1.0 and 1.1.
60
61 Also, LOXI is aware of the change in type of port numbers, so
62 translate those here.
63 """
64 value_string = str(value).strip()
65 if ident.find("OFPP_") == 0 and version == of_g.VERSION_1_0:
66 value_string = "0x%x" % (int(value, 0) + 0xffff0000)
67
68 # Otherwise, if no reference to a wildcard value, all done
69 if value_string.find("OFPFW") < 0:
70 return value_string
71 for ident, id_value in ident_list.items():
72 id_value_string = "(" + str(id_value).strip() + ")"
73 # If the identifier has (, etc., ignore it; not handling params
74 if ident.find("(") >= 0:
75 continue
76 value_string = re.sub(ident, id_value_string, value_string)
77 return value_string
78
79def get_enum_dict(version, contents):
80 """
81 Given openflow.h input, create a dict for its enums
82 @param contents The raw contents of the C file
83
84 The dict returned is indexed by LOXI identifier. Each entry is a
85 DotDict with three keys, value, ofp_name and ofp_group. The value is an
86 int value when possible, otherwise a string. The ofp_name is the original
87 name from the openflow header file. The ofp_group is the enum type.
88 """
89 rv_list = {}
90
91 version_ref = of_g.short_version_names[version]
92 enum_list = c_parse_utils.extract_enums(contents)
93 defines_list = c_parse_utils.extract_defines(contents)
94
95 # First generate a list of all original idents and values for translation
96 full_ident_list = {}
97
98 for enum in enum_list:
99 (name, values) = c_parse_utils.extract_enum_vals(enum)
100 for (ident, value) in values:
101 full_ident_list[ident] = str(value).strip()
102 for ident, value in defines_list:
103 full_ident_list[ident] = str(value).strip()
104
105 # Process enum idents
106 for enum in enum_list:
107 (name, values) = c_parse_utils.extract_enum_vals(enum)
108 for (ident, value) in values:
109 loxi_name = translation.loxi_name(ident)
110 if not loxi_name:
111 warn_unmapped_ident(ident)
112 continue
113 if loxi_name in rv_list:
114 sys.stderr.write("\nError: %s in ident list already\n" %
115 loxi_name)
116 sys.exit(1)
117
118 value_str = fixup_values(ident, value, version, full_ident_list)
119 log("Adding LOXI identifier %s from name %s" % (loxi_name, ident))
120 rv_list[loxi_name] = py_utils.DotDict(dict(
121 ofp_name = ident,
122 ofp_group = name,
123 value = value_str))
124
125 for ident, value in defines_list:
126 loxi_name = translation.loxi_name(ident)
127 if not loxi_name:
128 warn_unmapped_ident(ident, "macro defn")
129 continue
130
131 value_str = fixup_values(ident, value, version, full_ident_list)
132 if loxi_name in rv_list:
133 if value_str != rv_list[loxi_name].value:
134 sys.stderr.write("""
135ERROR: IDENT COLLISION. Version %s, LOXI Ident %s.
136New ofp_name %s, value %s.
137Previous ofp_name %s, value %s,
138""" % (version_ref, loxi_name, ident, value_str,
139 rv_list[loxi_name].ofp_name), rv_list[loxi_name].value)
140 sys.exit(1)
141 else:
142 log("Ignoring redundant entry %s, mapping to %s" %
143 (ident, loxi_name))
144
145 rv_list[loxi_name] = py_utils.DotDict(dict(
146 ofp_name = ident,
147 ofp_group = "macro_definitions",
148 value = value_str))
149
150 return rv_list
151
152
153
154