loxi_frontend: move classes only used by c to c_gen

 - flags
 - identifiers
 - match
 - translation
 - type_maps

were only used by the c backend. I'm moving them to c_gen to
unclutter the loxi_front_end space (and updating references
in the c backend)
diff --git a/c_gen/type_maps.py b/c_gen/type_maps.py
new file mode 100644
index 0000000..909ee79
--- /dev/null
+++ b/c_gen/type_maps.py
@@ -0,0 +1,802 @@
+# 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.
+
+#
+# Miscellaneous type information
+#
+# Define the map between sub-class types and wire values.  In each
+# case, an array indexed by wire version gives a hash from identifier
+# to wire value.
+#
+
+import c_gen.of_g_legacy as of_g
+import sys
+from generic_utils import *
+import loxi_utils.loxi_utils as loxi_utils
+import c_gen.loxi_utils_legacy as loxi_utils
+
+invalid_type = "invalid_type"
+invalid_value = "0xeeee"  # Note, as a string
+
+################################################################
+#
+# Define type data for inheritance classes:
+#   instructions, actions, queue properties and OXM
+#
+# Messages are not in this group; they're treated specially for now
+#
+# These are indexed by wire protocol number
+#
+################################################################
+
+instruction_types = {
+    of_g.VERSION_1_0:dict(),
+    of_g.VERSION_1_1:dict(),
+    of_g.VERSION_1_2:dict(),
+    of_g.VERSION_1_3:dict()
+    }
+
+# HACK shared between actions and action_ids
+of_1_3_action_types = dict()
+
+action_types = {
+    of_g.VERSION_1_0:dict(),
+    of_g.VERSION_1_1:dict(),
+    of_g.VERSION_1_2:dict(),
+    of_g.VERSION_1_3:of_1_3_action_types
+    }
+
+action_id_types = {
+    of_g.VERSION_1_0:dict(),
+    of_g.VERSION_1_1:dict(),
+    of_g.VERSION_1_2:dict(),
+    of_g.VERSION_1_3:of_1_3_action_types
+    }
+
+queue_prop_types = {
+    of_g.VERSION_1_0:dict(),
+    of_g.VERSION_1_1:dict(),
+    of_g.VERSION_1_2:dict(),
+    of_g.VERSION_1_3:dict()
+    }
+
+bsn_vport_types = {
+    # version 1.0
+    of_g.VERSION_1_0:dict(
+        q_in_q      = 0,
+        ),
+    # version 1.1
+    of_g.VERSION_1_1:dict(
+        q_in_q      = 0,
+        ),
+    # version 1.2
+    of_g.VERSION_1_2:dict(
+        q_in_q      = 0,
+        ),
+    # version 1.3
+    of_g.VERSION_1_3:dict(
+        q_in_q      = 0,
+        )
+    }
+
+oxm_types = {
+    of_g.VERSION_1_0:dict(),
+    of_g.VERSION_1_1:dict(),
+    of_g.VERSION_1_2:dict(),
+    of_g.VERSION_1_3:dict(),
+    }
+
+hello_elem_types = {
+    of_g.VERSION_1_0:dict(),
+    of_g.VERSION_1_1:dict(),
+    of_g.VERSION_1_2:dict(),
+    of_g.VERSION_1_3:dict(),
+    }
+
+table_feature_prop_types = {
+    of_g.VERSION_1_0:dict(),
+    of_g.VERSION_1_1:dict(),
+    of_g.VERSION_1_2:dict(),
+    of_g.VERSION_1_3:dict(),
+    }
+
+meter_band_types = {
+    of_g.VERSION_1_0:dict(),
+    of_g.VERSION_1_1:dict(),
+    of_g.VERSION_1_2:dict(),
+    of_g.VERSION_1_3:dict(),
+    }
+
+# All inheritance data for non-messages
+inheritance_data = dict(
+    of_instruction = instruction_types,
+    of_action = action_types,
+    of_action_id = action_id_types,
+    of_oxm = oxm_types,
+    of_queue_prop = queue_prop_types,
+    of_hello_elem = hello_elem_types,
+    of_table_feature_prop = table_feature_prop_types,
+    of_meter_band = meter_band_types,
+    # BSN specific inheritance extensions
+    of_bsn_vport = bsn_vport_types
+    )
+
+def class_is_virtual(cls):
+    """
+    Returns True if cls is a virtual class
+    """
+    if cls in inheritance_map:
+        return True
+    if cls.find("header") > 0:
+        return True
+    if loxi_utils.class_is_list(cls):
+        return True
+    # TODO get this from the input file when we have virtual class syntax
+    if cls in ["of_flow_mod", "of_stats_request", "of_stats_reply", "of_error_msg", "of_bsn_header", "of_nicira_header", "of_action_bsn", "of_action_nicira", "of_action_id_bsn", "of_action_id_nicira"]:
+        return True
+    return False
+
+################################################################
+#
+# These are message types
+#
+################################################################
+
+# The hardcoded message types are for inheritance parents
+message_types = {
+    # version 1.0
+    of_g.VERSION_1_0:dict(
+        error_msg               = 1,
+        experimenter            = 4,
+        flow_mod                = 14,
+        stats_request           = 16,
+        stats_reply             = 17,
+        ),
+
+    # version 1.1
+    of_g.VERSION_1_1:dict(
+        error_msg               = 1,
+        experimenter            = 4,
+        flow_mod                = 14,
+        stats_request           = 18,
+        stats_reply             = 19,
+        ),
+
+    # version 1.2
+    of_g.VERSION_1_2:dict(
+        error_msg               = 1,
+        experimenter            = 4,
+        flow_mod                = 14,
+        stats_request           = 18,
+        stats_reply             = 19,
+        ),
+
+    # version 1.3
+    of_g.VERSION_1_3:dict(
+        error_msg               = 1,
+        experimenter            = 4,
+        flow_mod                = 14,
+        stats_request           = 18,  # FIXME Multipart
+        stats_reply             = 19,
+        )
+    }
+
+################################################################
+#
+# These are other objects that have a notion of type but are
+# not (yet) promoted to objects with inheritance
+#
+################################################################
+
+stats_types = {
+    # version 1.0
+    of_g.VERSION_1_0:dict(
+        desc = 0,
+        flow = 1,
+        aggregate = 2,
+        table = 3,
+        port = 4,
+        queue = 5,
+        experimenter = 0xffff
+        ),
+
+    # version 1.1
+    of_g.VERSION_1_1:dict(
+        desc = 0,
+        flow = 1,
+        aggregate = 2,
+        table = 3,
+        port = 4,
+        queue = 5,
+        group = 6,
+        group_desc = 7,
+        experimenter = 0xffff
+        ),
+
+    # version 1.2
+        of_g.VERSION_1_2:dict(
+        desc = 0,
+        flow = 1,
+        aggregate = 2,
+        table = 3,
+        port = 4,
+        queue = 5,
+        group = 6,
+        group_desc = 7,
+        group_features = 8,
+        experimenter = 0xffff
+        ),
+
+    # version 1.3
+        of_g.VERSION_1_3:dict(
+        desc = 0,
+        flow = 1,
+        aggregate = 2,
+        table = 3,
+        port = 4,
+        queue = 5,
+        group = 6,
+        group_desc = 7,
+        group_features = 8,
+        meter = 9,
+        meter_config = 10,
+        meter_features = 11,
+        table_features = 12,
+        port_desc = 13,
+        experimenter = 0xffff
+        )
+    }
+
+common_flow_mod_types = dict(
+    add = 0,
+    modify = 1,
+    modify_strict = 2,
+    delete = 3,
+    delete_strict = 4
+    )
+
+flow_mod_types = {
+    # version 1.0
+    of_g.VERSION_1_0:common_flow_mod_types,
+    of_g.VERSION_1_1:common_flow_mod_types,
+    of_g.VERSION_1_2:common_flow_mod_types,
+    of_g.VERSION_1_3:common_flow_mod_types
+    }
+
+# These do not translate to objects (yet)
+error_types = {
+    # version 1.0
+    of_g.VERSION_1_0:dict(
+        hello_failed        = 0,
+        bad_request         = 1,
+        bad_action          = 2,
+        flow_mod_failed     = 3,
+        port_mod_failed     = 4,
+        queue_op_failed     = 5
+        ),
+
+    # version 1.1
+    of_g.VERSION_1_1:dict(
+        hello_failed         = 0,
+        bad_request          = 1,
+        bad_action           = 2,
+        bad_instruction      = 3,
+        bad_match            = 4,
+        flow_mod_failed      = 5,
+        group_mod_failed     = 6,
+        port_mod_failed      = 7,
+        table_mod_failed     = 8,
+        queue_op_failed      = 9,
+        switch_config_failed = 10
+        ),
+
+    # version 1.2
+    of_g.VERSION_1_2:dict(
+        hello_failed         = 0,
+        bad_request          = 1,
+        bad_action           = 2,
+        bad_instruction      = 3,
+        bad_match            = 4,
+        flow_mod_failed      = 5,
+        group_mod_failed     = 6,
+        port_mod_failed      = 7,
+        table_mod_failed     = 8,
+        queue_op_failed      = 9,
+        switch_config_failed = 10,
+        role_request_failed  = 11,
+        experimenter = 0xffff
+        ),
+
+    # version 1.3
+    of_g.VERSION_1_3:dict(
+        hello_failed         = 0,
+        bad_request          = 1,
+        bad_action           = 2,
+        bad_instruction      = 3,
+        bad_match            = 4,
+        flow_mod_failed      = 5,
+        group_mod_failed     = 6,
+        port_mod_failed      = 7,
+        table_mod_failed     = 8,
+        queue_op_failed      = 9,
+        switch_config_failed = 10,
+        role_request_failed  = 11,
+        meter_mod_failed     = 12,
+        table_features_failed= 13,
+        experimenter = 0xffff
+        )
+    }
+
+##
+# These are the objects whose length is specified by an external
+# reference, specifically another data member in the class.
+#
+#external_length_spec = {
+#    ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
+#    ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
+#    ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
+#    ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
+#}
+
+
+################################################################
+#
+# type_val is the primary data structure that maps an
+# (class_name, version) pair to the wire data type value
+#
+################################################################
+
+type_val = dict()
+inheritance_map = dict()
+
+def generate_maps():
+    for parent, versioned in inheritance_data.items():
+        inheritance_map[parent] = set()
+        for ver, subclasses in versioned.items():
+            for subcls in subclasses:
+                inheritance_map[parent].add(subcls)
+
+    for version, classes in message_types.items():
+        for cls in classes:
+            name = "of_" + cls
+            type_val[(name, version)] = classes[cls]
+
+    for parent, versioned in inheritance_data.items():
+        for version, subclasses in versioned.items():
+            for subcls, value in subclasses.items():
+                name = parent + "_" + subcls
+                type_val[(name, version)] = value
+
+    # Special case OF-1.2 match type
+    type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
+    type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
+
+# Utility function
+def dict_to_array(d, m_val, def_val=-1):
+    """
+    Given a dictionary, d, with each value a small integer,
+    produce an array indexed by the integer whose value is the key.
+    @param d The dictionary
+    @param m_val Ignore values greater than m_val
+    @param def_val The default value (for indices not in range of d)
+    """
+
+    # Get the max value in range for hash
+    max_val = 0
+    for key in d:
+        if (d[key] > max_val) and (d[key] < m_val):
+            max_val = d[key]
+    ar = []
+    for x in range(0, max_val + 1):
+        ar.append(def_val)
+    for key in d:
+        if (d[key] < m_val):
+            ar[d[key]] = key
+    return ar
+
+def type_array_len(version_indexed, max_val):
+    """
+    Given versioned information about a type, calculate how long
+    the unified array should be.
+
+    @param version_indexed A dict indexed by version. Each value is a
+    dict indexed by a name and whose value is an integer
+    @param max_val Ignore values greater than this for length calcs
+    """
+    # First, find the max length of all arrays
+    arr_len = 0
+    for version, val_dict in version_indexed.items():
+        ar = dict_to_array(val_dict, max_val, invalid_type)
+        if arr_len < len(ar):
+            arr_len = len(ar)
+    return arr_len
+
+# FIXME:  Need to move update for multipart messages
+
+stats_reply_list = [
+    "of_aggregate_stats_reply",
+    "of_desc_stats_reply",
+    "of_experimenter_stats_reply",
+    "of_flow_stats_reply",
+    "of_group_stats_reply",
+    "of_group_desc_stats_reply",
+    "of_group_features_stats_reply",
+    "of_meter_stats_reply",
+    "of_meter_config_stats_reply",
+    "of_meter_features_stats_reply",
+    "of_port_stats_reply",
+    "of_port_desc_stats_reply",
+    "of_queue_stats_reply",
+    "of_table_stats_reply",
+    "of_table_features_stats_reply"
+]
+
+stats_request_list = [
+    "of_aggregate_stats_request",
+    "of_desc_stats_request",
+    "of_experimenter_stats_request",
+    "of_flow_stats_request",
+    "of_group_stats_request",
+    "of_group_desc_stats_request",
+    "of_group_features_stats_request",
+    "of_meter_stats_request",
+    "of_meter_config_stats_request",
+    "of_meter_features_stats_request",
+    "of_port_stats_request",
+    "of_port_desc_stats_request",
+    "of_queue_stats_request",
+    "of_table_stats_request",
+    "of_table_features_stats_request"
+]
+
+flow_mod_list = [
+    "of_flow_add",
+    "of_flow_modify",
+    "of_flow_modify_strict",
+    "of_flow_delete",
+    "of_flow_delete_strict"
+]
+
+error_msg_list = [
+    "of_hello_failed_error_msg",
+    "of_bad_request_error_msg",
+    "of_bad_action_error_msg",
+    "of_bad_instruction_error_msg",
+    "of_bad_match_error_msg",
+    "of_flow_mod_failed_error_msg",
+    "of_group_mod_failed_error_msg",
+    "of_port_mod_failed_error_msg",
+    "of_table_mod_failed_error_msg",
+    "of_queue_op_failed_error_msg",
+    "of_switch_config_failed_error_msg",
+    "of_role_request_failed_error_msg",
+    "of_meter_mod_failed_error_msg",
+    "of_table_features_failed_error_msg",
+    "of_experimenter_error_msg"
+]
+
+def sub_class_map(base_type, version):
+    """
+    Returns an iterable object giving the instance nameys and subclass types
+    for the base_type, version values
+    """
+    rv = []
+    if base_type not in inheritance_map:
+        return rv
+
+    for instance in inheritance_map[base_type]:
+        subcls = loxi_utils.instance_to_class(instance, base_type)
+        if not loxi_utils.class_in_version(subcls, version):
+            continue
+        rv.append((instance, subcls))
+
+    return rv
+
+################################################################
+#
+# Extension related data and functions
+#
+################################################################
+
+# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
+# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
+extension_message_subtype = {
+    # version 1.0
+    of_g.VERSION_1_0:dict(  # Version 1.0 extensions
+        bsn = {   # BSN extensions; indexed by class name, value is subtype
+            },
+        nicira = {   # Nicira extensions, value is subtype
+            },
+        ),
+    of_g.VERSION_1_1:dict(  # Version 1.0 extensions
+        bsn = {   # BSN extensions; indexed by class name, value is subtype
+            },
+        ),
+    of_g.VERSION_1_2:dict(  # Version 1.0 extensions
+        bsn = {   # BSN extensions; indexed by class name, value is subtype
+            },
+        ),
+    of_g.VERSION_1_3:dict(  # Version 1.0 extensions
+        bsn = {   # BSN extensions; indexed by class name, value is subtype
+            },
+        ),
+}
+
+# Set to empty dict if no extension actions defined
+# Per OF Version, per experimenter, map actions to subtype
+extension_action_subtype = {
+    # version 1.0
+    of_g.VERSION_1_0:dict(  # Version 1.0 extensions
+        bsn = {   # of_action_bsn_
+            },
+        nicira = {   # of_action_nicira_
+            }
+        ),
+    of_g.VERSION_1_1:dict(  # Version 1.0 extensions
+        bsn = {   # of_action_bsn_
+            },
+        nicira = {   # of_action_nicira_
+            }
+        ),
+    of_g.VERSION_1_2:dict(  # Version 1.0 extensions
+        bsn = {   # of_action_bsn_
+            },
+        nicira = {   # of_action_nicira_
+            }
+        ),
+    of_g.VERSION_1_3:dict(  # Version 1.0 extensions
+        bsn = {   # of_action_bsn_
+            },
+        nicira = {   # of_action_nicira_
+            }
+        ),
+}
+
+# Set to empty dict if no extension actions defined
+# Per OF Version, per experimenter, map actions to subtype
+extension_action_id_subtype = {
+    # version 1.0
+    of_g.VERSION_1_0:dict(),
+    of_g.VERSION_1_1:dict(),
+    of_g.VERSION_1_2:dict(),
+    of_g.VERSION_1_3:dict(  # Version 1.3 extensions
+        bsn = {   # of_action_bsn_
+            },
+        nicira = {   # of_action_nicira_
+            }
+        ),
+}
+
+# Set to empty dict if no extension instructions defined
+extension_instruction_subtype = {}
+
+# Set to empty dict if no extension instructions defined
+extension_queue_prop_subtype = {}
+
+# Set to empty dict if no extension instructions defined
+extension_table_feature_prop_subtype = {}
+
+extension_objects = [
+    extension_message_subtype,
+    extension_action_subtype,
+    extension_action_id_subtype,
+    extension_instruction_subtype,
+    extension_queue_prop_subtype,
+    extension_table_feature_prop_subtype
+]
+
+################################################################
+# These are extension type generic (for messages, actions...)
+################################################################
+
+def extension_to_experimenter_name(cls):
+    """
+    Return the name of the experimenter if class is an
+    extension, else None
+
+    This is brute force; we search all extension data for a match
+    """
+
+    for ext_obj in extension_objects:
+        for version, exp_list in ext_obj.items():
+            for exp_name, classes in exp_list.items():
+                if cls in classes:
+                    return exp_name
+    return None
+
+def extension_to_experimenter_id(cls):
+    """
+    Return the ID of the experimenter if class is an
+    extension, else None
+    """
+    exp_name = extension_to_experimenter_name(cls)
+    if exp_name:
+        return of_g.experimenter_name_to_id[exp_name]
+    return None
+
+def extension_to_experimenter_macro_name(cls):
+    """
+    Return the "macro name" of the ID of the experimenter if class is an
+    extension, else None
+    """
+    exp_name = extension_to_experimenter_name(cls)
+    if exp_name:
+        return "OF_EXPERIMENTER_ID_" + exp_name.upper()
+    return None
+
+def extension_to_subtype(cls, version):
+    """
+    Generic across all extension objects, return subtype identifier
+    """
+    for ext_obj in extension_objects:
+        for version, exp_list in ext_obj.items():
+            for exp_name, classes in exp_list.items():
+                if cls in classes:
+                    return classes[cls]
+
+def class_is_extension(cls, version):
+    """
+    Return True if class, version is recognized as an extension
+    of any type (message, action....)
+
+    Accepts of_g.OF_VERSION_ANY
+    """
+
+    for ext_obj in extension_objects:
+        if cls_is_ext_obj(cls, version, ext_obj):
+            return True
+
+    return False
+
+# Internal
+def cls_is_ext_obj(cls, version, ext_obj):
+    """
+    @brief Return True if cls in an extension of type ext_obj
+    @param cls The class to check
+    @param version The version to check
+    @param ext_obj The extension object dictionary (messages, actions...)
+
+    Accepts of_g.VERSION_ANY
+    """
+
+    # Call with each version if "any" is passed
+    if version == of_g.VERSION_ANY:
+        for v in of_g.of_version_range:
+            if cls_is_ext_obj(cls, v, ext_obj):
+                return True
+    else:   # Version specified
+        if version in ext_obj:
+            for exp, subtype_vals in ext_obj[version].items():
+                if cls in subtype_vals:
+                    return True
+
+    return False
+
+################################################################
+# These are extension message specific
+################################################################
+
+def message_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an  extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version, extension_message_subtype)
+
+def extension_message_to_subtype(cls, version):
+    """
+    Return the subtype of the experimenter message if the class is an
+    extension, else None
+    """
+    if version in extension_message_subtype:
+        for exp, classes in extension_message_subtype[version].items():
+            for ext_class, subtype in classes.items():
+                if cls == ext_class:
+                    return subtype
+    return None
+
+################################################################
+# These are extension action specific
+################################################################
+
+def action_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an action extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version, extension_action_subtype)
+
+def extension_action_to_subtype(cls, version):
+    """
+    Return the ID of the action subtype (for its experimenteer)
+    if class is an action extension, else None
+    """
+    if version in extension_action_subtype:
+        for exp, classes in extension_action_subtype[version].items():
+            if cls in classes:
+                return classes[cls]
+
+    return None
+
+################################################################
+# These are extension action specific
+################################################################
+
+def action_id_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an action ID extension
+    This is brute force, searching records for a match
+    """
+    if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
+        return False
+    return cls_is_ext_obj(cls, version, extension_action_id_subtype)
+
+def extension_action_id_to_subtype(cls, version):
+    """
+    Return the ID of the action ID subtype (for its experimenteer)
+    if class is an action ID extension, else None
+    """
+    if version in extension_action_id_subtype:
+        for exp, classes in extension_action_id_subtype[version].items():
+            if cls in classes:
+                return classes[cls]
+
+    return None
+
+################################################################
+# These are extension instruction specific
+################################################################
+
+def instruction_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an instruction extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version, extension_instruction_subtype)
+
+################################################################
+# These are extension queue_prop specific
+################################################################
+
+def queue_prop_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an instruction extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
+
+################################################################
+# These are extension table_feature_prop specific
+################################################################
+
+def table_feature_prop_is_extension(cls, version):
+    """
+    Return True if cls, version is recognized as an instruction extension
+    This is brute force, searching records for a match
+    """
+    return cls_is_ext_obj(cls, version,
+                          extension_table_feature_prop_subtype)