blob: bc3092fed96c823a353e6ae6f0036883092d8745 [file] [log] [blame]
Andreas Wundsam542a13c2013-11-15 13:28:55 -08001import c_gen.of_g_legacy as of_g
2
3def class_signature(members):
4 """
5 Generate a signature string for a class in canonical form
6
7 @param cls The class whose signature is to be generated
8 """
9 return ";".join([",".join([x["m_type"], x["name"], str(x["offset"])])
10 for x in members])
11
12def type_dec_to_count_base(m_type):
13 """
14 Resolve a type declaration like uint8_t[4] to a count (4) and base_type
15 (uint8_t)
16
17 @param m_type The string type declaration to process
18 """
19 count = 1
20 chk_ar = m_type.split('[')
21 if len(chk_ar) > 1:
22 count_str = chk_ar[1].split(']')[0]
23 if count_str in of_g.ofp_constants:
24 count = of_g.ofp_constants[count_str]
25 else:
26 count = int(count_str)
27 base_type = chk_ar[0]
28 else:
29 base_type = m_type
30 return count, base_type
31
32def list_to_entry_type(cls):
33 """
34 Return the entry type for a list
35 """
36 slen = len("of_list_")
37 return "of_" + cls[slen:]
38
39def type_to_short_name(m_type):
40 if m_type in of_g.of_base_types:
41 tname = of_g.of_base_types[m_type]["short_name"]
42 elif m_type in of_g.of_mixed_types:
43 tname = of_g.of_mixed_types[m_type]["short_name"]
44 else:
45 tname = "unknown"
46 return tname
47
48def type_to_name_type(cls, member_name):
49 """
50 Generate the root name of a member for accessor functions, etc
51 @param cls The class name
52 @param member_name The member name
53 """
54 members = of_g.unified[cls]["union"]
55 if not member_name in members:
56 debug("Error: %s is not in class %s for acc_name defn" %
57 (member_name, cls))
58 os.exit()
59
60 mem = members[member_name]
61 m_type = mem["m_type"]
62 id = mem["memid"]
63 tname = type_to_short_name(m_type)
64
65 return "o%d_m%d_%s" % (of_g.unified[cls]["object_id"], id, tname)
66
67
68def member_to_index(m_name, members):
69 """
70 Given a member name, return the index in the members dict
71 @param m_name The name of the data member to search for
72 @param members The dict of members
73 @return Index if found, -1 not found
74
75 Note we could generate an index when processing the original input
76 """
77 count = 0
78 for d in members:
79 if d["name"] == m_name:
80 return count
81 count += 1
82 return -1
83
84def member_base_type(cls, m_name):
85 """
86 Map a member to its of_ type
87 @param cls The class name
88 @param m_name The name of the member being gotten
89 @return The of_ type of the member
90 """
91 rv = of_g.unified[cls]["union"][m_name]["m_type"]
92 if rv[-2:] == "_t":
93 return rv
94 return rv + "_t"
95
96def member_type_is_octets(cls, m_name):
97 return member_base_type(cls, m_name) == "of_octets_t"
98
99def member_returns_val(cls, m_name):
100 """
101 Should get accessor return a value rather than void
102 @param cls The class name
103 @param m_name The member name
104 @return True if of_g config and the specific member allow a
105 return value. Otherwise False
106 """
107 m_type = of_g.unified[cls]["union"][m_name]["m_type"]
108 return (config_check("get_returns") =="value" and
109 m_type in of_g.of_scalar_types)
110
111def config_check(str, dictionary = of_g.code_gen_config):
112 """
113 Return config value if in dictionary; else return False.
114 @param str The lookup index
115 @param dictionary The dict to check; use code_gen_config if None
116 """
117
118 if str in dictionary:
119 return dictionary[str]
120
121 return False
122
123def h_file_to_define(name):
124 """
125 Convert a .h file name to the define used for the header
126 """
127 h_name = name[:-2].upper()
128 h_name = "_" + h_name + "_H_"
129 return h_name
130
131def type_to_cof_type(m_type):
132 if m_type in of_g.of_base_types:
133 if "cof_type" in of_g.of_base_types[m_type]:
134 return of_g.of_base_types[m_type]["cof_type"]
135 return m_type
136
137
138def member_is_scalar(cls, m_name):
139 return of_g.unified[cls]["union"][m_name]["m_type"] in of_g.of_scalar_types
140
141def type_is_scalar(m_type):
142 return m_type in of_g.of_scalar_types
143
144def skip_member_name(name):
145 return name.find("pad") == 0 or name in of_g.skip_members
146
147def enum_name(cls):
148 """
149 Return the name used for an enum identifier for the given class
150 @param cls The class name
151 """
152 return cls.upper()
153
154def class_in_version(cls, ver):
155 """
156 Return boolean indicating if cls is defined for wire version ver
157 """
158
159 return (cls, ver) in of_g.base_length
160
161def instance_to_class(instance, parent):
162 """
163 Return the name of the class for an instance of inheritance type parent
164 """
165 return parent + "_" + instance
166
167def sub_class_to_var_name(cls):
168 """
169 Given a subclass name like of_action_output, generate the
170 name of a variable like 'output'
171 @param cls The class name
172 """
173 pass
174
175def class_is_var_len(cls, version):
176 # Match is special case. Only version 1.2 (wire version 3) is var
177 if cls == "of_match":
178 return version == 3
179
180 return not (cls, version) in of_g.is_fixed_length
181
182def base_type_to_length(base_type, version):
183 if base_type + "_t" in of_g.of_base_types:
184 inst_len = of_g.of_base_types[base_type + "_t"]["bytes"]
185 else:
186 inst_len = of_g.base_length[(base_type, version)]
187
188def version_to_name(version):
189 """
190 Convert an integer version to the C macro name
191 """
192 return "OF_" + of_g.version_names[version]
193
194##
195# Is class a flow modify of some sort?
196
197def cls_is_flow_mod(cls):
198 return cls in ["of_flow_mod", "of_flow_modify", "of_flow_add", "of_flow_delete",
199 "of_flow_modify_strict", "of_flow_delete_strict"]
200
201def all_member_types_get(cls, version):
202 """
203 Get the members and list of types for members of a given class
204 @param cls The class name to process
205 @param version The version for the class
206 """
207 member_types = []
208
209 if not version in of_g.unified[cls]:
210 return ([], [])
211
212 if "use_version" in of_g.unified[cls][version]:
213 v = of_g.unified[cls][version]["use_version"]
214 members = of_g.unified[cls][v]["members"]
215 else:
216 members = of_g.unified[cls][version]["members"]
217 # Accumulate variables that are supported
218 for member in members:
219 m_type = member["m_type"]
220 m_name = member["name"]
221 if skip_member_name(m_name):
222 continue
223 if not m_type in member_types:
224 member_types.append(m_type)
225
226 return (members, member_types)
227
228def list_name_extract(list_type):
229 """
230 Return the base name for a list object of the given type
231 @param list_type The type of the list as appears in the input,
232 for example list(of_port_desc_t).
233 @return A pair, (list-name, base-type) where list-name is the
234 base name for the list, for example of_list_port_desc, and base-type
235 is the type of list elements like of_port_desc_t
236 """
237 base_type = list_type[5:-1]
238 list_name = base_type
239 if list_name.find("of_") == 0:
240 list_name = list_name[3:]
241 if list_name[-2:] == "_t":
242 list_name = list_name[:-2]
243 list_name = "of_list_" + list_name
244 return (list_name, base_type)
245
246def version_to_name(version):
247 """
248 Convert an integer version to the C macro name
249 """
250 return "OF_" + of_g.version_names[version]
251
252def gen_c_copy_license(out):
253 """
254 Generate the top comments for copyright and license
255 """
256 import c_gen.util
257 c_gen.util.render_template(out, '_copyright.c')
258
259def accessor_returns_error(a_type, m_type):
260 is_var_len = (not type_is_scalar(m_type)) and \
261 [x for x in of_g.of_version_range if class_is_var_len(m_type[:-2], x)] != []
262 if a_type == "set" and is_var_len:
263 return True
264 elif m_type == "of_match_t":
265 return True
266 else:
267 return False