import os.path
-
OCCURRENCE__REQUIRED_ITEM = "r"
OCCURRENCE__REQUIRED_LIST = "rl"
OCCURRENCE__OPTIONAL_ITEM = "o"
separator = "/* " + ("* " * 37) + "*\n"
-
def aligned(left, right, length=59):
return left.ljust(length, ' ') + right
-
class Member:
def __init__(self, type, occurrence):
self.type = type
self.occurrence = occurrence
-
def is_enum(self):
return self.type in predefined_enums or self.type in enums_by_name
-
def is_object(self):
return self.type in predefined_objects or self.type in objects_by_name
-
def is_type_generated(self):
return self.type in enums_by_name or self.type in objects_by_name
-
def get_occurrence_comment(self):
occurrence_map = {
OCCURRENCE__REQUIRED_ITEM: "/* required */",
raise ValueError("unknown occurrence value '%s'" % self.occurrence)
-
-
class Parameter(Member):
def __init__(self, type, name, occurrence):
Member.__init__(self, type, occurrence)
self.name = name
self.autobind_name = None
-
def generate_parameter(self, is_last=False, is_header=True, offset=0):
if self.occurrence == OCCURRENCE__IGNORED:
raise ValueError("invalid function parameter occurrence value '%s'"
return aligned(string, self.get_occurrence_comment() + "\n")
-
def generate_return(self, offset=0, end_of_line=";"):
if self.occurrence == OCCURRENCE__IGNORED:
raise ValueError("invalid function parameter occurrence value '%s'"
return aligned(string, self.get_occurrence_comment() + "\n")
-
def generate_require_code(self):
if self.occurrence in [OCCURRENCE__REQUIRED_ITEM,
OCCURRENCE__REQUIRED_LIST]:
else:
return ""
-
def generate_serialize_code(self):
if self.occurrence in [OCCURRENCE__REQUIRED_LIST,
OCCURRENCE__OPTIONAL_LIST]:
return " ESX_VI__METHOD__PARAMETER__SERIALIZE(%s, %s)\n" \
% (self.type, self.name)
-
def get_type_string(self, as_return_value=False):
string = ""
return string
-
def get_occurrence_short_enum(self):
if self.occurrence == OCCURRENCE__REQUIRED_ITEM:
return "RequiredItem"
raise ValueError("unknown occurrence value '%s'" % self.occurrence)
-
class Method:
def __init__(self, name, parameters, returns):
self.name = name
else:
self.autobind_parameter = parameter
-
def generate_header(self):
header = "int esxVI_%s\n" % self.name
header += " (esxVI_Context *ctx"
return header
-
def generate_source(self):
source = "/* esxVI_%s */\n" % self.name
source += "ESX_VI__METHOD(%s," % self.name
return source
-
class Property(Member):
def __init__(self, type, name, occurrence):
Member.__init__(self, type, occurrence)
self.name = name
-
def generate_struct_member(self):
if self.occurrence == OCCURRENCE__IGNORED:
return " /* FIXME: %s is currently ignored */\n" % self.name
return aligned(string, self.get_occurrence_comment() + "\n")
-
def generate_free_code(self):
if self.type == "String" and \
self.occurrence not in [OCCURRENCE__REQUIRED_LIST,
else:
return " esxVI_%s_Free(&item->%s);\n" % (self.type, self.name)
-
def generate_validate_code(self, managed=False):
if managed:
macro = "ESX_VI__TEMPLATE__PROPERTY__MANAGED_REQUIRE"
else:
return ""
-
def generate_deep_copy_code(self):
if self.occurrence == OCCURRENCE__IGNORED:
return " /* FIXME: %s is currently ignored */\n" % self.name
return " ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY(%s, %s)\n" \
% (self.type, self.name)
-
def generate_serialize_code(self):
if self.occurrence == OCCURRENCE__IGNORED:
return " /* FIXME: %s is currently ignored */\n" % self.name
return " ESX_VI__TEMPLATE__PROPERTY__SERIALIZE(%s, %s)\n" \
% (self.type, self.name)
-
def generate_deserialize_code(self):
if self.occurrence == OCCURRENCE__IGNORED:
return " ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_IGNORE(%s) /* FIXME */\n" \
return " ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE(%s, %s)\n" \
% (self.type, self.name)
-
def generate_lookup_code(self):
if self.occurrence == OCCURRENCE__IGNORED:
return " ESX_VI__TEMPLATE__PROPERTY__CAST_FROM_ANY_TYPE_IGNORE(%s) /* FIXME */\n" \
return " ESX_VI__TEMPLATE__PROPERTY__CAST_FROM_ANY_TYPE(%s, %s)\n" \
% (self.type, self.name)
-
def get_type_string(self):
if self.type == "String" and \
self.occurrence not in [OCCURRENCE__REQUIRED_LIST,
return "esxVI_%s *" % self.type
-
class Type:
def __init__(self, kind, name):
self.kind = kind
self.name = name
-
def generate_typedef(self):
return "typedef %s _esxVI_%s esxVI_%s;\n" \
% (self.kind, self.name, self.name)
-
def generate_typeenum(self):
return " esxVI_Type_%s,\n" % self.name
-
def generate_typetostring(self):
string = " case esxVI_Type_%s:\n" % self.name
string += " return \"%s\";\n\n" % self.name
return string
-
def generate_typefromstring(self):
string = " if (STREQ(type, \"%s\"))\n" % self.name
string += " return esxVI_Type_%s;\n" % self.name
FEATURE__SERIALIZE = (1 << 5)
FEATURE__DESERIALIZE = (1 << 6)
-
def __init__(self, name, category, managed, generic_objects_by_name):
Type.__init__(self, "struct", name)
self.category = category
self.managed = managed
self.generic_objects_by_name = generic_objects_by_name
-
def generate_comment(self):
comment = separator
comment += " * %s: %s\n" % (self.category, self.name)
return comment
-
def generate_struct_members(self, add_banner=False, struct_gap=False):
members = ""
return members
-
def generate_dispatch(self, suffix, is_first=True):
source = ""
return source
-
def generate_free_code(self, add_banner=False):
source = ""
return source
-
def generate_validate_code(self, add_banner=False):
source = ""
return source
-
class Object(GenericObject):
def __init__(self, name, extends, properties, features=0, extended_by=None):
GenericObject.__init__(self, name, 'VI Object', False, objects_by_name)
if self.extended_by is not None:
self.extended_by.sort()
-
def generate_dynamic_cast_code(self, is_first=True):
source = ""
return source
-
def generate_deep_copy_code(self, add_banner=False):
source = ""
return source
-
def generate_serialize_code(self, add_banner=False):
source = ""
return source
-
def generate_deserialize_code(self, add_banner=False):
source = ""
return source
-
def generate_header(self):
header = self.generate_comment()
return header
-
def generate_source(self):
source = separator
source += " * VI Object: %s\n" % self.name
return source
-
class ManagedObject(GenericObject):
def __init__(self, name, extends, properties, features=0, extended_by=None):
GenericObject.__init__(self, name, 'VI Managed Object', True,
if self.extended_by is not None:
self.extended_by.sort()
-
def generate_lookup_code1(self, add_banner=False):
source = ""
return source
-
def generate_lookup_code2(self, add_banner=False):
source = ""
return source
-
def generate_header(self):
header = self.generate_comment()
return header
-
def generate_helper_header(self):
# functions
return (
% {"name": self.name}
)
-
def generate_source(self):
source = self.generate_comment()
return source
-
def generate_helper_source(self):
# lookup
return (
FEATURE__SERIALIZE = (1 << 2)
FEATURE__DESERIALIZE = (1 << 3)
-
def __init__(self, name, values, features=0):
Type.__init__(self, "enum", name)
self.values = values
self.features = features
-
def generate_header(self):
header = separator
header += " * VI Enum: %s\n" % self.name
return header
-
def generate_source(self):
source = separator
source += " * VI Enum: %s\n" % self.name
return source
-
def report_error(message):
print("error: " + message)
sys.exit(1)
-
def capitalize_first(string):
return string[:1].upper() + string[1:]
-
def parse_object(block):
# expected format: [managed] object <name> [extends <name>]
header_items = block[0][1].split()
return Object(name=name, extends=extends, properties=properties)
-
def parse_enum(block):
# expected format: enum <name>
header_items = block[0][1].split()
return Enum(name=name, values=values)
-
def parse_method(block):
# expected format: method <name> [returns <type> <occurrence>]
header_items = block[0][1].split()
return Method(name=name, parameters=parameters, returns=returns)
-
def is_known_type(type):
return type in predefined_objects or \
type in predefined_enums or \
type in enums_by_name
-
def open_and_print(filename):
if filename.startswith("./"):
print(" GEN " + filename[2:])
return open(filename, "wt")
-
predefined_enums = ["Boolean"]
predefined_objects = ["AnyType",
output_dirname = os.path.join(sys.argv[2], "esx")
-
types_typedef = open_and_print(os.path.join(output_dirname, "esx_vi_types.generated.typedef"))
types_typeenum = open_and_print(os.path.join(output_dirname, "esx_vi_types.generated.typeenum"))
types_typetostring = open_and_print(os.path.join(output_dirname, "esx_vi_types.generated.typetostring"))
helpers_source = open_and_print(os.path.join(output_dirname, "esx_vi.generated.c"))
-
number = 0
objects_by_name = {}
managed_objects_by_name = {}
block = None
-
# parse input file
for line in open(input_filename, "rt").readlines():
number += 1
block.append((number, line))
-
for method in methods_by_name.values():
# method parameter types must be serializable
for parameter in method.parameters:
objects_by_name[method.returns.type].features |= Object.FEATURE__LIST
-
for enum in enums_by_name.values():
# apply additional features
if enum.name in additional_enum_features:
enum.features |= Enum.FEATURE__DESERIALIZE
-
for obj in objects_by_name.values():
for property in obj.properties:
if property.occurrence != OCCURRENCE__IGNORED and \
extended_obj.extended_by.sort()
-
for obj in objects_by_name.values():
# if an object is a candidate (it is used directly as parameter or return
# type or is a member of another object) and it is extended by another
obj.features |= Object.FEATURE__DYNAMIC_CAST
-
def propagate_feature(obj, feature):
global features_have_changed
propagate_feature(objects_by_name[property.type], feature)
-
def inherit_features(obj):
global features_have_changed
inherit_features(objects_by_name[extended_by])
-
# there are two directions to spread features:
# 1) up and down the inheritance chain
# 2) from object types to their member property types
inherit_features(obj)
-
for obj in managed_objects_by_name.values():
for property in obj.properties:
if property.occurrence != OCCURRENCE__IGNORED and \
extended_obj.extended_by.sort()
-
notice = "/* Generated by esx_vi_generator.py */\n\n\n\n"
types_typedef.write(notice)
helpers_source.write(notice)
-
# output enums
types_typedef.write(separator +
" * VI Enums\n" +
types_source.write(enums_by_name[name].generate_source())
-
# output objects
types_typedef.write("\n\n\n" +
separator +
types_source.write(objects_by_name[name].generate_source())
-
# output managed objects
types_typedef.write("\n\n\n" +
separator +
types_source.write(managed_objects_by_name[name].generate_source())
-
# output methods
names = sorted(methods_by_name.keys())
methods_macro.write(string)
-
# output helpers
names = sorted(managed_objects_by_name.keys())
wmi_version_separator = "/"
wmi_classes_by_name = {}
+
class WmiClass:
"""Represents WMI class and provides methods to generate C code.
self.versions = versions if versions else list()
self.common = None
-
def prepare(self):
"""Prepares the class for code generation
# are in the same order - to ensure C struct member alignment
self._align_property_members()
-
def generate_classes_header(self):
"""Generate C header code and return it as string
return header
-
def generate_classes_source(self):
"""Returns a C code string defining wsman data structs
source += ' { "", "", 0 },\n' # null terminated
source += '};\n\n'
-
source += self._define_WmiInfo_struct()
source += "\n\n"
return source
-
def generate_classes_typedef(self):
"""Returns C string for typdefs"""
return typedef
-
-
def _declare_data_structs(self):
"""Returns string C code declaring data structs.
return header
-
def _declare_hypervObject_struct(self):
"""Return string for C code declaring hypervObject instance"""
return header
-
def _define_WmiInfo_struct(self):
"""Return string for C code defining *_WmiInfo struct
return source
-
def _align_property_members(self):
"""Identifies common properties in all class versions.
self.common.append(x[0])
-
class ClassUriInfo:
"""Prepares URI information needed for wsman requests."""
self.resourceUri = "%s/%s" % (baseUri, wmi_name)
-
class WmiClassVersion:
"""Represents specific version of WMI class."""
self.uri_info = uri_info
-
class Property:
typemap = {
"boolean": "BOOL",
"uint64": "UINT64"
}
-
def __init__(self, type, name, is_array):
if type not in Property.typemap:
report_error("unhandled property type %s" % type)
self.name = name
self.is_array = is_array
-
def generate_classes_header(self):
if self.is_array:
return " XML_TYPE_DYN_ARRAY %s;\n" % self.name
return " XML_TYPE_%s %s;\n" \
% (Property.typemap[self.type], self.name)
-
def generate_classes_source(self, class_name):
if self.is_array:
return " SER_NS_DYN_ARRAY(%s_RESOURCE_URI, \"%s\", 0, 0, %s),\n" \
return " SER_NS_%s(%s_RESOURCE_URI, \"%s\", 1),\n" \
% (Property.typemap[self.type], class_name.upper(), self.name)
-
def generate_typemap(self):
return ' { "%s", "%s", %s },\n' % (self.name, self.type.lower(), str(self.is_array).lower())
-
def open_and_print(filename):
if filename.startswith("./"):
print(" GEN " + filename[2:])
return open(filename, "wt")
-
def report_error(message):
print("error: " + message)
sys.exit(1)
-
def parse_class(block, number):
# expected format: class <name>
header_items = block[0][1].split()
wmi_classes_by_name[wmi_name] = WmiClass(wmi_name, [cls])
-
def main():
if len(sys.argv) != 3:
report_error("usage: %s srcdir builddir" % sys.argv[0])
classes_source.write(cls.generate_classes_source())
-
if __name__ == "__main__":
main()