blob: dbf1e7afe87776cb8bc9fa1668cf7b412e503fca [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 Dump function generation
30
31Generates dump function files.
32
33"""
34
35import sys
36import of_g
37import loxi_front_end.match as match
38import loxi_front_end.flags as flags
39from generic_utils import *
40import loxi_front_end.type_maps as type_maps
41import loxi_utils.loxi_utils as loxi_utils
42import loxi_front_end.identifiers as identifiers
43from c_test_gen import var_name_map
44
45def gen_obj_dump_h(out, name):
46 loxi_utils.gen_c_copy_license(out)
47 out.write("""
48/**
49 *
50 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
51 *
52 * Header file for object dumping.
53 */
54
55/**
56 * Dump object declarations
57 *
58 * Routines that emit a dump of each object.
59 *
60 */
61
62#if !defined(_LOCI_OBJ_DUMP_H_)
63#define _LOCI_OBJ_DUMP_H_
64
65#include <loci/loci.h>
66#include <stdio.h>
67
68/* g++ requires this to pick up PRI, etc.
69 * See http://gcc.gnu.org/ml/gcc-help/2006-10/msg00223.html
70 */
71#if !defined(__STDC_FORMAT_MACROS)
72#define __STDC_FORMAT_MACROS
73#endif
74#include <inttypes.h>
75
76
77/**
78 * Dump any OF object.
79 */
80int of_object_dump(loci_writer_f writer, void* cookie, of_object_t* obj);
81
82
83
84
85
86
87""")
88
89 type_to_emitter = dict(
90
91 )
92 for version in of_g.of_version_range:
93 for cls in of_g.standard_class_order:
94 if not loxi_utils.class_in_version(cls, version):
95 continue
96 if cls in type_maps.inheritance_map:
97 continue
98 out.write("""\
99int %(cls)s_%(ver_name)s_dump(loci_writer_f writer, void* cookie, %(cls)s_t *obj);
100""" % dict(cls=cls, ver_name=loxi_utils.version_to_name(version)))
101
102 out.write("""
103#endif /* _LOCI_OBJ_DUMP_H_ */
104""")
105
106def gen_obj_dump_c(out, name):
107 loxi_utils.gen_c_copy_license(out)
108 out.write("""
109/**
110 *
111 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
112 *
113 * Source file for object dumping.
114 *
115 */
116
117#define DISABLE_WARN_UNUSED_RESULT
118#include <loci/loci.h>
119#include <loci/loci_dump.h>
120#include <loci/loci_obj_dump.h>
121
122static int
123unknown_dump(loci_writer_f writer, void* cookie, of_object_t *obj)
124{
125 return writer(cookie, "Unable to print object of type %d, version %d\\n",
126 obj->object_id, obj->version);
127}
128""")
129
130 for version in of_g.of_version_range:
131 ver_name = loxi_utils.version_to_name(version)
132 for cls in of_g.standard_class_order:
133 if not loxi_utils.class_in_version(cls, version):
134 continue
135 if cls in type_maps.inheritance_map:
136 continue
137 out.write("""
138int
139%(cls)s_%(ver_name)s_dump(loci_writer_f writer, void* cookie, %(cls)s_t *obj)
140{
141 int out = 0;
142""" % dict(cls=cls, ver_name=ver_name))
143
144 members, member_types = loxi_utils.all_member_types_get(cls, version)
145 for m_type in member_types:
146 if loxi_utils.type_is_scalar(m_type) or m_type in \
147 ["of_match_t", "of_octets_t"]:
148 # Declare instance of these
149 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
150 else:
151 out.write("""
152 %(m_type)s %(v_name)s;
153""" % dict(m_type=m_type, v_name=var_name_map(m_type)))
154 if loxi_utils.class_is_list(m_type):
155 base_type = loxi_utils.list_to_entry_type(m_type)
156 out.write(" %s elt;\n int rv;\n" % base_type)
157 out.write("""
158 out += writer(cookie, "Object of type %(cls)s\\n");
159""" % dict(cls=cls))
160 for member in members:
161 m_type = member["m_type"]
162 m_name = member["name"]
163 emitter = "LOCI_DUMP_" + loxi_utils.type_to_short_name(m_type)
164 if loxi_utils.skip_member_name(m_name):
165 continue
166 if (loxi_utils.type_is_scalar(m_type) or
167 m_type in ["of_match_t", "of_octets_t"]):
168 out.write("""
169 %(cls)s_%(m_name)s_get(obj, &%(v_name)s);
170 out += writer(cookie, " %(m_name)s (%(m_type)s): ");
171 out += %(emitter)s(writer, cookie, %(v_name)s);
172 out += writer(cookie, "\\n");
173""" % dict(cls=cls, m_name=m_name, m_type=m_type,
174 v_name=var_name_map(m_type), emitter=emitter))
175 elif loxi_utils.class_is_list(m_type):
176 sub_cls = m_type[:-2] # Trim _t
177 elt_type = loxi_utils.list_to_entry_type(m_type)
178 out.write("""
179 out += writer(cookie, "List of %(elt_type)s\\n");
180 %(cls)s_%(m_name)s_bind(obj, &%(v_name)s);
181 %(u_type)s_ITER(&%(v_name)s, &elt, rv) {
182 of_object_dump(writer, cookie, (of_object_t *)&elt);
183 }
184""" % dict(sub_cls=sub_cls, u_type=sub_cls.upper(), v_name=var_name_map(m_type),
185 elt_type=elt_type, cls=cls, m_name=m_name, m_type=m_type))
186 else:
187 sub_cls = m_type[:-2] # Trim _t
188 out.write("""
189 %(cls)s_%(m_name)s_bind(obj, &%(v_name)s);
190 out += %(sub_cls)s_%(ver_name)s_dump(writer, cookie, &%(v_name)s);
191""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name,
192 v_name=var_name_map(m_type), ver_name=ver_name))
193
194 out.write("""
195 return out;
196}
197""")
198 out.write("""
199/**
200 * Log a match entry
201 */
202int
203loci_dump_match(loci_writer_f writer, void* cookie, of_match_t *match)
204{
205 int out = 0;
206
207 out += writer(cookie, "Match obj, version %d.\\n", match->version);
208""")
209
210 for key, entry in match.of_match_members.items():
211 m_type = entry["m_type"]
212 emitter = "LOCI_DUMP_" + loxi_utils.type_to_short_name(m_type)
213 out.write("""
214 if (OF_MATCH_MASK_%(ku)s_ACTIVE_TEST(match)) {
215 out += writer(cookie, " %(key)s (%(m_type)s) active: Value ");
216 out += %(emitter)s(writer, cookie, match->fields.%(key)s);
217 out += writer(cookie, "\\n Mask ");
218 out += %(emitter)s(writer, cookie, match->masks.%(key)s);
219 out += writer(cookie, "\\n");
220 }
221""" % dict(key=key, ku=key.upper(), emitter=emitter, m_type=m_type))
222
223 out.write("""
224 return out;
225}
226""")
227
228 # Generate big table indexed by version and object
229 for version in of_g.of_version_range:
230 out.write("""
231static loci_obj_dump_f dump_funs_v%(version)s[OF_OBJECT_COUNT] = {
232""" % dict(version=version))
233 out.write(" unknown_dump, /* of_object, not a valid specific type */\n")
234 for j, cls in enumerate(of_g.all_class_order):
235 comma = ""
236 if j < len(of_g.all_class_order) - 1: # Avoid ultimate comma
237 comma = ","
238
239 if (not loxi_utils.class_in_version(cls, version) or
240 cls in type_maps.inheritance_map):
241 out.write(" unknown_dump%s\n" % comma);
242 else:
243 out.write(" %s_%s_dump%s\n" %
244 (cls, loxi_utils.version_to_name(version), comma))
245 out.write("};\n\n")
246
247 out.write("""
248static loci_obj_dump_f *dump_funs[5] = {
249 NULL,
250 dump_funs_v1,
251 dump_funs_v2,
252 dump_funs_v3,
253 dump_funs_v4
254};
255
256int
257of_object_dump(loci_writer_f writer, void* cookie, of_object_t *obj)
258{
259 if ((obj->object_id > 0) && (obj->object_id < OF_OBJECT_COUNT)) {
260 if (((obj)->version > 0) && ((obj)->version <= OF_VERSION_1_2)) {
261 /* @fixme VERSION */
262 return dump_funs[obj->version][obj->object_id](writer, cookie, (of_object_t *)obj);
263 } else {
264 return writer(cookie, "Bad version %d\\n", obj->version);
265 }
266 }
267 return writer(cookie, "Bad object id %d\\n", obj->object_id);
268}
269""")
270