loci: move per-class declarations to loci_classes.h

The goal is to free loci.h of dynamically generated code and turn it into a
static template.

Needed to move some declarations out of loci.h and into of_object.h, where they
really belonged anyway.
diff --git a/c_gen/c_code_gen.py b/c_gen/c_code_gen.py
index cce4d09..5cfba39 100644
--- a/c_gen/c_code_gen.py
+++ b/c_gen/c_code_gen.py
@@ -430,18 +430,9 @@
 
     # gen_base_types(out)
 
-    gen_struct_typedefs(out)
-    gen_acc_pointer_typedefs(out)
-    gen_new_function_declarations(out)
-    if config_check("gen_unified_fns"):
-        gen_accessor_declarations(out)
-
-    gen_common_struct_definitions(out)
     gen_flow_add_setup_function_declarations(out)
     if config_check("gen_fn_ptrs"): # Otherwise, all classes are from generic cls
         gen_struct_definitions(out)
-    gen_generic_union(out)
-    gen_generics(out)
     gen_top_static_functions(out)
     out.write("""
 /****************************************************************
@@ -789,7 +780,7 @@
 #include <loci/of_message.h>
 #include <loci/of_match.h>
 #include <loci/of_object.h>
-#include <loci/of_wire_buf.h>
+#include <loci/loci_classes.h>
 
 /****************************************************************
  *
@@ -1224,20 +1215,6 @@
         out.write("    %s_t %s;\n" % (cls, cls))
     out.write("};\n")
 
-def gen_common_struct_definitions(out):
-    out.write("""
-/****************************************************************
- *
- * Unified structure definitions
- *
- ****************************************************************/
-
-struct of_object_s {
-    /* Common members */
-%(common)s
-};
-""" % dict(common=of_g.base_object_members))
-
 def gen_flow_add_setup_function_declarations(out):
     """
     Add the declarations for functions that can be initialized
@@ -2080,94 +2057,6 @@
             out.write("%s\n%s_%s_set(\n    %s)\n" % (ret_type, cls, m_name, params))
             gen_unified_acc_body(out, cls, m_name, ver_type_map, "set", m_type)
 
-def gen_acc_pointer_typedefs(out):
-    """
-    Generate the function pointer typedefs for in-struct accessors
-    @param out The file to which to write the typedefs
-    """
-
-    out.write("""
-/****************************************************************
- *
- * Accessor function pointer typedefs
- *
- ****************************************************************/
-
-/*
- * Generic accessors:
- *
- * Many objects have a length represented in the wire buffer
- * wire_length_get and wire_length_set access these values directly on the
- * wire.
- *
- * Many objects have a length represented in the wire buffer
- * wire_length_get and wire_length_set access these values directly on the
- * wire.
- *
- * FIXME: TBD if wire_length_set and wire_type_set are required.
- */
-typedef void (*of_wire_length_get_f)(of_object_t *obj, int *bytes);
-typedef void (*of_wire_length_set_f)(of_object_t *obj, int bytes);
-typedef void (*of_wire_type_get_f)(of_object_t *obj, of_object_id_t *id);
-typedef void (*of_wire_type_set_f)(of_object_t *obj);
-""")
-    # If not using function pointers in classes, don't gen typedefs below
-    if not config_check("gen_fn_ptrs"):
-        return
-
-    # For each class, for each type it uses, generate a typedef
-    for cls in of_g.standard_class_order:
-        if cls in type_maps.inheritance_map:
-            continue
-        out.write("\n/* Accessor function pointer typedefs for %s */\n" % cls)
-        types_done = list()
-        for m_name in of_g.ordered_members[cls]:
-            (m_type, get_rv) = get_acc_rv(cls, m_name)
-            if (m_type, get_rv) in types_done:
-                continue
-            types_done.append((m_type, get_rv))
-            fn = "%s_%s" % (cls, m_type)
-            params = ", ".join(param_list(cls, m_name, "get"))
-            out.write("typedef int (*%s_get_f)(\n    %s);\n" %
-                      (fn, params))
-
-            params = ", ".join(param_list(cls, m_name, "set"))
-            out.write("typedef int (*%s_set_f)(\n    %s);\n" %
-                      (fn, params))
-        if loxi_utils.class_is_list(cls):
-            obj_type = loxi_utils.list_to_entry_type(cls)
-            out.write("""typedef int (*%(cls)s_first_f)(
-    %(cls)s_t *list,
-    %(obj_type)s_t *obj);
-typedef int (*%(cls)s_next_f)(
-    %(cls)s_t *list,
-    %(obj_type)s_t *obj);
-typedef int (*%(cls)s_append_bind_f)(
-    %(cls)s_t *list,
-    %(obj_type)s_t *obj);
-typedef int (*%(cls)s_append_f)(
-    %(cls)s_t *list,
-    %(obj_type)s_t *obj);
-""" % {"cls":cls, "obj_type":obj_type})
-
-#             out.write("""
-# typedef int (*%(cls)s_get_f)(
-#     %(cls)s_t *list,
-#     %(obj_type)s_t *obj, int index);
-# typedef int (*%(cls)s_set_f)(
-#     %(cls)s_t *list,
-#     %(obj_type)s_t *obj, int index);
-# typedef int (*%(cls)s_append_f)(
-#     %(cls)s_t *list,
-#     %(obj_type)s_t *obj, int index);
-# typedef int (*%(cls)s_insert_f)(
-#     %(cls)s_t *list,
-#     %(obj_type)s_t *obj, int index);
-# typedef int (*%(cls)s_remove_f)(
-#     %(cls)s_t *list,
-#     int index);
-# """ % {"cls":cls, "obj_type":obj_type})
-
 ################################################################
 #
 # New/Delete Function Definitions
diff --git a/c_gen/codegen.py b/c_gen/codegen.py
index 158d9ce..3f8aaf4 100644
--- a/c_gen/codegen.py
+++ b/c_gen/codegen.py
@@ -33,6 +33,7 @@
 
 from collections import namedtuple
 from itertools import groupby
+from StringIO import StringIO
 import template_utils
 import loxi_globals
 import loxi_ir.ir as ir
@@ -94,6 +95,19 @@
             c_code_gen.gen_new_function_definitions(out, cls)
             c_code_gen.gen_accessor_definitions(out, cls)
 
+def generate_classes_header(install_dir):
+    # Collect legacy code
+    tmp = StringIO()
+    c_code_gen.gen_struct_typedefs(tmp)
+    c_code_gen.gen_new_function_declarations(tmp)
+    c_code_gen.gen_accessor_declarations(tmp)
+    c_code_gen.gen_generic_union(tmp)
+    c_code_gen.gen_generics(tmp)
+
+    with template_utils.open_output(install_dir, "loci/inc/loci/loci_classes.h") as out:
+        util.render_template(out, "loci_classes.h",
+            legacy_code=tmp.getvalue())
+
 def generate_lists(install_dir):
     for cls in of_g.ordered_list_objects:
         with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out:
diff --git a/c_gen/of_g_legacy.py b/c_gen/of_g_legacy.py
index 80d922c..fde46fb 100644
--- a/c_gen/of_g_legacy.py
+++ b/c_gen/of_g_legacy.py
@@ -236,46 +236,6 @@
                    "of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
                    "of_ipv6_t", "of_ipv4_t", "of_bitmap_128_t"]
 
-base_object_members = """\
-    /* The control block for the underlying data buffer */
-    of_wire_object_t wire_object;
-    /* The LOCI type enum value of the object */
-    of_object_id_t object_id;
-
-    /*
-     * Objects need to track their "parent" so that updates to the
-     * object that affect its length can be pushed to the parent.
-     * Treat as private.
-     */
-    of_object_t *parent;
-
-    /*
-     * Not all objects have length and version on the wire so we keep
-     * them here.  NOTE: Infrastructure manages length and version.
-     * Treat length as private and version as read only.
-     */
-    int length;
-    of_version_t version;
-
-    /*
-     * Many objects have a length and/or type represented in the wire buffer
-     * These accessors get and set those value when present.  Treat as private.
-     */
-    of_wire_length_get_f wire_length_get;
-    of_wire_length_set_f wire_length_set;
-    of_wire_type_get_f wire_type_get;
-    of_wire_type_set_f wire_type_set;
-
-    of_object_track_info_t track_info;
-
-    /*
-     * Metadata available for applications.  Ensure 8-byte alignment, but
-     * that buffer is at least as large as requested.  This data is not used
-     * or inspected by LOCI.
-     */
-    uint64_t metadata[(OF_OBJECT_METADATA_BYTES + 7) / 8];
-"""
-
 ##
 # LOXI identifiers
 #
diff --git a/c_gen/templates/loci_classes.h b/c_gen/templates/loci_classes.h
new file mode 100644
index 0000000..3486055
--- /dev/null
+++ b/c_gen/templates/loci_classes.h
@@ -0,0 +1,35 @@
+:: # Copyright 2013, Big Switch Networks, Inc.
+:: #
+:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+:: # the following special exception:
+:: #
+:: # LOXI Exception
+:: #
+:: # As a special exception to the terms of the EPL, you may distribute libraries
+:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+:: #
+:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+:: #
+:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+:: # a copy of the EPL at:
+:: #
+:: # http://www.eclipse.org/legal/epl-v10.html
+:: #
+:: # Unless required by applicable law or agreed to in writing, software
+:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+:: # EPL for the specific language governing permissions and limitations
+:: # under the EPL.
+::
+:: include('_copyright.c')
+::
+#ifndef __LOCI_CLASSES_H__
+#define __LOCI_CLASSES_H__
+
+${legacy_code}
+
+#endif
diff --git a/c_gen/templates/of_object.h b/c_gen/templates/of_object.h
index ff4c9c5..fee95e1 100644
--- a/c_gen/templates/of_object.h
+++ b/c_gen/templates/of_object.h
@@ -46,6 +46,7 @@
 #include <loci/of_match.h>
 #include <loci/loci_base.h>
 #include <loci/of_message.h>
+#include <loci/of_wire_buf.h>
 
 #if defined(OF_OBJECT_TRACKING)
 #include <BigList/biglist.h>
@@ -57,6 +58,24 @@
  */
 #define OF_OBJECT_METADATA_BYTES 32
 
+/*
+ * Generic accessors:
+ *
+ * Many objects have a length represented in the wire buffer
+ * wire_length_get and wire_length_set access these values directly on the
+ * wire.
+ *
+ * Many objects have a length represented in the wire buffer
+ * wire_length_get and wire_length_set access these values directly on the
+ * wire.
+ *
+ * FIXME: TBD if wire_length_set and wire_type_set are required.
+ */
+typedef void (*of_wire_length_get_f)(of_object_t *obj, int *bytes);
+typedef void (*of_wire_length_set_f)(of_object_t *obj, int bytes);
+typedef void (*of_wire_type_get_f)(of_object_t *obj, of_object_id_t *id);
+typedef void (*of_wire_type_set_f)(of_object_t *obj);
+
 /****************************************************************
  * General list operations: first, next, append_setup, append_advance
  ****************************************************************/
@@ -173,4 +192,44 @@
 
 int of_object_can_grow(of_object_t *obj, int new_len);
 
+struct of_object_s {
+    /* The control block for the underlying data buffer */
+    of_wire_object_t wire_object;
+    /* The LOCI type enum value of the object */
+    of_object_id_t object_id;
+
+    /*
+     * Objects need to track their "parent" so that updates to the
+     * object that affect its length can be pushed to the parent.
+     * Treat as private.
+     */
+    of_object_t *parent;
+
+    /*
+     * Not all objects have length and version on the wire so we keep
+     * them here.  NOTE: Infrastructure manages length and version.
+     * Treat length as private and version as read only.
+     */
+    int length;
+    of_version_t version;
+
+    /*
+     * Many objects have a length and/or type represented in the wire buffer
+     * These accessors get and set those value when present.  Treat as private.
+     */
+    of_wire_length_get_f wire_length_get;
+    of_wire_length_set_f wire_length_set;
+    of_wire_type_get_f wire_type_get;
+    of_wire_type_set_f wire_type_set;
+
+    of_object_track_info_t track_info;
+
+    /*
+     * Metadata available for applications.  Ensure 8-byte alignment, but
+     * that buffer is at least as large as requested.  This data is not used
+     * or inspected by LOCI.
+     */
+    uint64_t metadata[(OF_OBJECT_METADATA_BYTES + 7) / 8];
+};
+
 #endif /* _OF_OBJECT_H_ */
diff --git a/lang_c.py b/lang_c.py
index fbb3b9b..0a31fac 100644
--- a/lang_c.py
+++ b/lang_c.py
@@ -176,6 +176,7 @@
             fn(outfile, os.path.basename(name))
     c_gen.codegen.generate_classes(install_dir)
     c_gen.codegen.generate_header_classes(install_dir)
+    c_gen.codegen.generate_classes_header(install_dir)
     c_gen.codegen.generate_lists(install_dir)
     c_gen.codegen.generate_strings(install_dir)
     c_gen.codegen.generate_init_map(install_dir)