blob: 26dbac1f50a191a9b4d05b7f6fea0ba33946ae63 [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
Rich Lanebbff5562013-03-15 22:55:20 -070068 if ident == 'OFP_VLAN_NONE' and version > of_g.VERSION_1_0:
69 value_string = '0'
70
Rich Lanea06d0c32013-03-25 08:52:03 -070071 # Otherwise, if no reference to a wildcard value, all done
72 if value_string.find("OFPFW") < 0:
73 return value_string
74 for ident, id_value in ident_list.items():
75 id_value_string = "(" + str(id_value).strip() + ")"
76 # If the identifier has (, etc., ignore it; not handling params
77 if ident.find("(") >= 0:
78 continue
79 value_string = re.sub(ident, id_value_string, value_string)
80 return value_string
81
82def get_enum_dict(version, contents):
83 """
84 Given openflow.h input, create a dict for its enums
85 @param contents The raw contents of the C file
86
87 The dict returned is indexed by LOXI identifier. Each entry is a
88 DotDict with three keys, value, ofp_name and ofp_group. The value is an
89 int value when possible, otherwise a string. The ofp_name is the original
90 name from the openflow header file. The ofp_group is the enum type.
91 """
92 rv_list = {}
93
94 version_ref = of_g.short_version_names[version]
95 enum_list = c_parse_utils.extract_enums(contents)
96 defines_list = c_parse_utils.extract_defines(contents)
97
98 # First generate a list of all original idents and values for translation
99 full_ident_list = {}
100
101 for enum in enum_list:
102 (name, values) = c_parse_utils.extract_enum_vals(enum)
103 for (ident, value) in values:
104 full_ident_list[ident] = str(value).strip()
105 for ident, value in defines_list:
106 full_ident_list[ident] = str(value).strip()
107
108 # Process enum idents
109 for enum in enum_list:
110 (name, values) = c_parse_utils.extract_enum_vals(enum)
111 for (ident, value) in values:
112 loxi_name = translation.loxi_name(ident)
113 if not loxi_name:
114 warn_unmapped_ident(ident)
115 continue
116 if loxi_name in rv_list:
117 sys.stderr.write("\nError: %s in ident list already\n" %
118 loxi_name)
119 sys.exit(1)
120
121 value_str = fixup_values(ident, value, version, full_ident_list)
122 log("Adding LOXI identifier %s from name %s" % (loxi_name, ident))
123 rv_list[loxi_name] = py_utils.DotDict(dict(
124 ofp_name = ident,
125 ofp_group = name,
126 value = value_str))
127
128 for ident, value in defines_list:
129 loxi_name = translation.loxi_name(ident)
130 if not loxi_name:
131 warn_unmapped_ident(ident, "macro defn")
132 continue
133
134 value_str = fixup_values(ident, value, version, full_ident_list)
135 if loxi_name in rv_list:
136 if value_str != rv_list[loxi_name].value:
137 sys.stderr.write("""
138ERROR: IDENT COLLISION. Version %s, LOXI Ident %s.
139New ofp_name %s, value %s.
140Previous ofp_name %s, value %s,
141""" % (version_ref, loxi_name, ident, value_str,
142 rv_list[loxi_name].ofp_name), rv_list[loxi_name].value)
143 sys.exit(1)
144 else:
145 log("Ignoring redundant entry %s, mapping to %s" %
146 (ident, loxi_name))
147
148 rv_list[loxi_name] = py_utils.DotDict(dict(
149 ofp_name = ident,
150 ofp_group = "macro_definitions",
151 value = value_str))
152
153 return rv_list
154
155
156
157