1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2024-12-22 17:34:18 +03:00
libvirt/src/esx/esx_vi_generator.py

1827 lines
63 KiB
Python
Raw Normal View History

#!/usr/bin/env python
#
# esx_vi_generator.py: generates most of the SOAP type mapping code
#
# Copyright (C) 2010-2011 Matthias Bolte <matthias.bolte@googlemail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys
import os
import os.path
OCCURRENCE__REQUIRED_ITEM = "r"
OCCURRENCE__REQUIRED_LIST = "rl"
OCCURRENCE__OPTIONAL_ITEM = "o"
OCCURRENCE__OPTIONAL_LIST = "ol"
OCCURRENCE__IGNORED = "i"
valid_occurrences = [OCCURRENCE__REQUIRED_ITEM,
OCCURRENCE__REQUIRED_LIST,
OCCURRENCE__OPTIONAL_ITEM,
OCCURRENCE__OPTIONAL_LIST,
OCCURRENCE__IGNORED]
autobind_map = { "FileManager" : "fileManager",
"PerformanceManager" : "perfManager",
"PropertyCollector" : "propertyCollector",
"SearchIndex" : "searchIndex",
"SessionManager" : "sessionManager",
"VirtualDiskManager" : "virtualDiskManager" }
autobind_map_usage = set()
def aligned(left, right, length=59):
while len(left) < length:
2011-04-10 15:26:47 +04:00
left += " "
return left + right
class Parameter:
def __init__(self, type, name, occurrence):
self.type = type
self.occurrence = occurrence
if ':' in name and name.startswith("_this"):
self.name, self.autobind_type = name.split(":")
else:
self.name = name
self.autobind_type = None
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 generate_parameter(self, is_last = False, is_header = True, offset = 0):
if self.occurrence == OCCURRENCE__IGNORED:
raise ValueError("invalid function parameter occurrence value '%s'" % self.occurrence)
elif self.autobind_type is not None:
return ""
else:
string = " "
string += " " * offset
string += "%s%s" % (self.get_type_string(), self.name)
if is_last:
if is_header:
string += "); "
else:
string += "), "
else:
string += ", "
2011-04-10 15:26:47 +04:00
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'" % self.occurrence)
else:
string = " "
string += " " * offset
string += "%s%s)%s" % (self.get_type_string(True), self.name, end_of_line)
2011-04-10 15:26:47 +04:00
return aligned(string, self.get_occurrence_comment() + "\n")
def generate_require_code(self):
if self.occurrence in [OCCURRENCE__REQUIRED_ITEM,
OCCURRENCE__REQUIRED_LIST]:
return " ESX_VI__METHOD__PARAMETER__REQUIRE(%s)\n" % self.name
else:
return ""
def generate_serialize_code(self):
if self.occurrence in [OCCURRENCE__REQUIRED_LIST,
OCCURRENCE__OPTIONAL_LIST]:
return " ESX_VI__METHOD__PARAMETER__SERIALIZE_LIST(%s, %s)\n" % (self.type, self.name)
elif self.type == "String":
return " ESX_VI__METHOD__PARAMETER__SERIALIZE_VALUE(String, %s)\n" % self.name
else:
return " ESX_VI__METHOD__PARAMETER__SERIALIZE(%s, %s)\n" % (self.type, self.name)
def get_type_string(self, as_return_value = False):
string = ""
if self.type == "String" and \
self.occurrence not in [OCCURRENCE__REQUIRED_LIST,
OCCURRENCE__OPTIONAL_LIST]:
if as_return_value:
string += "char *"
else:
string += "const char *"
elif self.is_enum():
string += "esxVI_%s " % self.type
else:
string += "esxVI_%s *" % self.type
if as_return_value:
string += "*"
return string
def get_occurrence_comment(self):
if self.occurrence == OCCURRENCE__REQUIRED_ITEM:
return "/* required */"
elif self.occurrence == OCCURRENCE__REQUIRED_LIST:
return "/* required, list */"
elif self.occurrence == OCCURRENCE__OPTIONAL_ITEM:
return "/* optional */"
elif self.occurrence == OCCURRENCE__OPTIONAL_LIST:
return "/* optional, list */"
raise ValueError("unknown occurrence value '%s'" % self.occurrence)
def get_occurrence_short_enum(self):
if self.occurrence == OCCURRENCE__REQUIRED_ITEM:
return "RequiredItem"
elif self.occurrence == OCCURRENCE__REQUIRED_LIST:
return "RequiredList"
elif self.occurrence == OCCURRENCE__OPTIONAL_ITEM:
return "OptionalItem"
elif self.occurrence == OCCURRENCE__OPTIONAL_LIST:
return "OptionalList"
raise ValueError("unknown occurrence value '%s'" % self.occurrence)
class Method:
def __init__(self, name, parameters, returns):
self.name = name
self.parameters = []
self.autobind_parameter = None
self.returns = returns
for parameter in parameters:
if parameter.autobind_type is None:
self.parameters.append(parameter)
else:
self.autobind_parameter = parameter
def generate_header(self):
header = "int esxVI_%s\n" % self.name
header += " (esxVI_Context *ctx"
if len(self.parameters) > 0 or self.returns is not None:
header += ",\n"
for parameter in self.parameters[:-1]:
header += parameter.generate_parameter()
if self.returns is None:
header += self.parameters[-1].generate_parameter(is_last = True)
else:
header += self.parameters[-1].generate_parameter()
header += self.returns.generate_return()
else:
header += ");\n"
header += "\n"
return header
def generate_source(self):
source = "/* esxVI_%s */\n" % self.name
source += "ESX_VI__METHOD(%s," % self.name
if self.autobind_parameter is not None:
autobind_map_usage.add(self.autobind_parameter.autobind_type)
source += " %s,\n" % autobind_map[self.autobind_parameter.autobind_type]
else:
source += " /* explicit _this */,\n"
source += " (esxVI_Context *ctx"
if len(self.parameters) > 0 or self.returns is not None:
source += ",\n"
for parameter in self.parameters[:-1]:
source += parameter.generate_parameter(is_header = False, offset = 9)
if self.returns is None:
source += self.parameters[-1].generate_parameter(is_last = True, is_header = False, offset = 9)
else:
source += self.parameters[-1].generate_parameter(is_header = False, offset = 9)
source += self.returns.generate_return(offset = 9, end_of_line = ",")
else:
source += "),\n"
if self.returns is None:
source += " void, /* nothing */, None,\n"
elif self.returns.type == "String":
source += " String, Value, %s,\n" % self.returns.get_occurrence_short_enum()
else:
source += " %s, /* nothing */, %s,\n" % (self.returns.type, self.returns.get_occurrence_short_enum())
source += "{\n"
if self.autobind_parameter is not None:
source += self.autobind_parameter.generate_require_code()
for parameter in self.parameters:
source += parameter.generate_require_code()
source += "},\n"
source += "{\n"
if self.autobind_parameter is not None:
source += self.autobind_parameter.generate_serialize_code()
for parameter in self.parameters:
source += parameter.generate_serialize_code()
source += "})\n\n\n\n"
return source
class Property:
def __init__(self, type, name, occurrence):
self.type = type
self.name = name
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 generate_struct_member(self):
if self.occurrence == OCCURRENCE__IGNORED:
return " /* FIXME: %s is currently ignored */\n" % self.name
else:
string = " %s%s; " % (self.get_type_string(), self.name)
2011-04-10 15:26:47 +04:00
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,
OCCURRENCE__OPTIONAL_LIST,
OCCURRENCE__IGNORED]:
return " VIR_FREE(item->%s);\n" % self.name
elif self.is_enum():
return ""
else:
if self.occurrence == OCCURRENCE__IGNORED:
return " /* FIXME: %s is currently ignored */\n" % self.name
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:
macro = "ESX_VI__TEMPLATE__PROPERTY__REQUIRE"
if self.occurrence in [OCCURRENCE__REQUIRED_ITEM,
OCCURRENCE__REQUIRED_LIST]:
return " %s(%s)\n" % (macro, self.name)
elif self.occurrence == OCCURRENCE__IGNORED:
return " /* FIXME: %s is currently ignored */\n" % self.name
else:
return ""
def generate_deep_copy_code(self):
if self.occurrence == OCCURRENCE__IGNORED:
return " /* FIXME: %s is currently ignored */\n" % self.name
elif self.occurrence in [OCCURRENCE__REQUIRED_LIST,
OCCURRENCE__OPTIONAL_LIST]:
return " ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_LIST(%s, %s)\n" % (self.type, self.name)
elif self.type == "String":
return " ESX_VI__TEMPLATE__PROPERTY__DEEP_COPY_VALUE(String, %s)\n" % self.name
elif self.is_enum():
return " (*dest)->%s = src->%s;\n" % (self.name, self.name)
else:
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
elif self.occurrence in [OCCURRENCE__REQUIRED_LIST,
OCCURRENCE__OPTIONAL_LIST]:
return " ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_LIST(%s, %s)\n" % (self.type, self.name)
elif self.type == "String":
return " ESX_VI__TEMPLATE__PROPERTY__SERIALIZE_VALUE(String, %s)\n" % self.name
else:
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" % self.name
elif self.occurrence in [OCCURRENCE__REQUIRED_LIST,
OCCURRENCE__OPTIONAL_LIST]:
return " ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_LIST(%s, %s)\n" % (self.type, self.name)
elif self.type == "String":
return " ESX_VI__TEMPLATE__PROPERTY__DESERIALIZE_VALUE(String, %s)\n" % self.name
else:
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" % self.name
elif self.occurrence in [OCCURRENCE__REQUIRED_LIST,
OCCURRENCE__OPTIONAL_LIST]:
return " ESX_VI__TEMPLATE__PROPERTY__CAST_LIST_FROM_ANY_TYPE(%s, %s)\n" % (self.type, self.name)
elif self.type == "String":
return " ESX_VI__TEMPLATE__PROPERTY__CAST_VALUE_FROM_ANY_TYPE(String, %s)\n" % self.name
else:
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,
OCCURRENCE__OPTIONAL_LIST]:
return "char *"
elif self.is_enum():
return "esxVI_%s " % self.type
else:
return "esxVI_%s *" % self.type
def get_occurrence_comment(self):
if self.occurrence == OCCURRENCE__REQUIRED_ITEM:
return "/* required */"
elif self.occurrence == OCCURRENCE__REQUIRED_LIST:
return "/* required, list */"
elif self.occurrence == OCCURRENCE__OPTIONAL_ITEM:
return "/* optional */"
elif self.occurrence == OCCURRENCE__OPTIONAL_LIST:
return "/* optional, list */"
raise ValueError("unknown occurrence value '%s'" % self.occurrence)
2011-04-10 15:26:47 +04:00
class Base:
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 = " else if (STREQ(type, \"%s\")) {\n" % self.name
string += " return esxVI_Type_%s;\n" % self.name
string += " }\n"
return string
class Object(Base):
FEATURE__DYNAMIC_CAST = (1 << 1)
FEATURE__LIST = (1 << 2)
FEATURE__DEEP_COPY = (1 << 3)
FEATURE__ANY_TYPE = (1 << 4)
FEATURE__SERIALIZE = (1 << 5)
FEATURE__DESERIALIZE = (1 << 6)
def __init__(self, name, extends, properties, features = 0, extended_by = None):
2011-04-10 15:26:47 +04:00
Base.__init__(self, "struct", name)
self.extends = extends
self.features = features
self.properties = properties
self.extended_by = extended_by
self.candidate_for_dynamic_cast = False
if self.extended_by is not None:
2011-04-10 15:26:47 +04:00
self.extended_by.sort()
2011-04-10 15:26:47 +04:00
def generate_struct_members(self, add_banner=False, struct_gap=False):
members = ""
2011-04-10 15:26:47 +04:00
if struct_gap:
members += "\n"
if self.extends is not None:
2011-04-10 15:26:47 +04:00
members += objects_by_name[self.extends].generate_struct_members(add_banner=True, struct_gap=False) + "\n"
if self.extends is not None or add_banner:
members += " /* %s */\n" % self.name
for property in self.properties:
members += property.generate_struct_member()
if len(self.properties) < 1:
members += " /* no properties */\n"
return members
2011-04-10 15:26:47 +04:00
def generate_free_code(self, add_banner=False):
source = ""
if self.extends is not None:
2011-04-10 15:26:47 +04:00
source += objects_by_name[self.extends].generate_free_code(add_banner=True) + "\n"
if self.extends is not None or add_banner:
source += " /* %s */\n" % self.name
if len(self.properties) < 1:
source += " /* no properties */\n"
else:
string = ""
for property in self.properties:
string += property.generate_free_code()
if len(string) < 1:
source += " /* no properties to be freed */\n"
else:
source += string
return source
2011-04-10 15:26:47 +04:00
def generate_validate_code(self, add_banner=False):
source = ""
if self.extends is not None:
2011-04-10 15:26:47 +04:00
source += objects_by_name[self.extends].generate_validate_code(add_banner=True) + "\n"
if self.extends is not None or add_banner:
source += " /* %s */\n" % self.name
if len(self.properties) < 1:
source += " /* no properties */\n"
else:
string = ""
for property in self.properties:
string += property.generate_validate_code()
if len(string) < 1:
source += " /* no required properties */\n"
else:
source += string
return source
def generate_dynamic_cast_code(self, is_first = True):
source = ""
if self.extended_by is not None:
if not is_first:
source += "\n"
source += " /* %s */\n" % self.name
for extended_by in self.extended_by:
source += " ESX_VI__TEMPLATE__DYNAMIC_CAST__ACCEPT(%s)\n" % extended_by
for extended_by in self.extended_by:
source += objects_by_name[extended_by].generate_dynamic_cast_code(False)
return source
def generate_deep_copy_code(self, add_banner = False):
source = ""
if self.extends is not None:
source += objects_by_name[self.extends].generate_deep_copy_code(add_banner = True) + "\n"
if self.extends is not None or add_banner:
source += " /* %s */\n" % self.name
if len(self.properties) < 1:
source += " /* no properties */\n"
else:
string = ""
for property in self.properties:
string += property.generate_deep_copy_code()
if len(string) < 1:
source += " /* no properties to be deep copied */\n"
else:
source += string
return source
def generate_serialize_code(self, add_banner = False):
source = ""
if self.extends is not None:
source += objects_by_name[self.extends].generate_serialize_code(add_banner = True) + "\n"
if self.extends is not None or add_banner:
source += " /* %s */\n" % self.name
if len(self.properties) < 1:
source += " /* no properties */\n"
else:
for property in self.properties:
source += property.generate_serialize_code()
return source
def generate_deserialize_code(self, add_banner = False):
source = ""
if self.extends is not None:
2011-04-10 15:26:47 +04:00
source += objects_by_name[self.extends].generate_deserialize_code(add_banner=True) + "\n"
if self.extends is not None or add_banner:
source += " /* %s */\n" % self.name
if len(self.properties) < 1:
source += " /* no properties */\n"
else:
for property in self.properties:
source += property.generate_deserialize_code()
return source
def generate_header(self):
header = "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
header += " * VI Object: %s\n" % self.name
if self.extends is not None:
header += " * extends %s\n" % self.extends
first = True
if self.extended_by is not None:
for extended_by in self.extended_by:
if first:
header += " * extended by %s\n" % extended_by
first = False
else:
header += " * %s\n" % extended_by
header += " */\n\n"
# struct
header += "struct _esxVI_%s {\n" % self.name
if self.features & Object.FEATURE__LIST:
2011-04-10 15:26:47 +04:00
header += aligned(" esxVI_%s *_next; " % self.name, "/* optional */\n")
else:
2011-04-10 15:26:47 +04:00
header += aligned(" esxVI_%s *_unused; " % self.name, "/* optional */\n")
2011-04-10 15:26:47 +04:00
header += aligned(" esxVI_Type _type; ", "/* required */\n")
header += self.generate_struct_members(struct_gap=True)
header += "};\n\n"
# functions
header += "int esxVI_%s_Alloc(esxVI_%s **item);\n" % (self.name, self.name)
header += "void esxVI_%s_Free(esxVI_%s **item);\n" % (self.name, self.name)
header += "int esxVI_%s_Validate(esxVI_%s *item);\n" % (self.name, self.name)
if self.features & Object.FEATURE__DYNAMIC_CAST:
if self.extended_by is not None or self.extends is not None:
header += "esxVI_%s *esxVI_%s_DynamicCast(void *item);\n" % (self.name, self.name)
else:
report_error("cannot add dynamic cast support for an untyped object")
if self.features & Object.FEATURE__LIST:
header += "int esxVI_%s_AppendToList(esxVI_%s **list, esxVI_%s *item);\n" % (self.name, self.name, self.name)
if self.features & Object.FEATURE__DEEP_COPY:
header += "int esxVI_%s_DeepCopy(esxVI_%s **dst, esxVI_%s *src);\n" % (self.name, self.name, self.name)
if self.features & Object.FEATURE__LIST:
header += "int esxVI_%s_DeepCopyList(esxVI_%s **dstList, esxVI_%s *srcList);\n" % (self.name, self.name, self.name)
if self.features & Object.FEATURE__ANY_TYPE:
header += "int esxVI_%s_CastFromAnyType(esxVI_AnyType *anyType, esxVI_%s **item);\n" % (self.name, self.name)
if self.features & Object.FEATURE__LIST:
header += "int esxVI_%s_CastListFromAnyType(esxVI_AnyType *anyType, esxVI_%s **list);\n" % (self.name, self.name)
if self.features & Object.FEATURE__SERIALIZE:
header += "int esxVI_%s_Serialize(esxVI_%s *item, const char *element, virBufferPtr output);\n" % (self.name, self.name)
if self.features & Object.FEATURE__LIST:
header += "int esxVI_%s_SerializeList(esxVI_%s *list, const char *element, virBufferPtr output);\n" % (self.name, self.name)
if self.features & Object.FEATURE__DESERIALIZE:
header += "int esxVI_%s_Deserialize(xmlNodePtr node, esxVI_%s **item);\n" % (self.name, self.name)
if self.features & Object.FEATURE__LIST:
header += "int esxVI_%s_DeserializeList(xmlNodePtr node, esxVI_%s **list);\n" % (self.name, self.name)
header += "\n\n\n"
return header
def generate_source(self):
source = "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
source += " * VI Object: %s\n" % self.name
if self.extends is not None:
source += " * extends %s\n" % self.extends
first = True
if self.extended_by is not None:
for extended_by in self.extended_by:
if first:
source += " * extended by %s\n" % extended_by
first = False
else:
source += " * %s\n" % extended_by
source += " */\n\n"
# functions
source += "/* esxVI_%s_Alloc */\n" % self.name
source += "ESX_VI__TEMPLATE__ALLOC(%s)\n\n" % self.name
# free
if self.extended_by is None:
source += "/* esxVI_%s_Free */\n" % self.name
source += "ESX_VI__TEMPLATE__FREE(%s,\n" % self.name
source += "{\n"
if self.features & Object.FEATURE__LIST:
if self.extends is not None:
# avoid "dereferencing type-punned pointer will break strict-aliasing rules" warnings
source += " esxVI_%s *next = (esxVI_%s *)item->_next;\n\n" % (self.extends, self.extends)
source += " esxVI_%s_Free(&next);\n" % self.extends
source += " item->_next = (esxVI_%s *)next;\n\n" % self.name
else:
source += " esxVI_%s_Free(&item->_next);\n\n" % self.name
source += self.generate_free_code()
source += "})\n\n"
else:
source += "/* esxVI_%s_Free */\n" % self.name
source += "ESX_VI__TEMPLATE__DYNAMIC_FREE(%s,\n" % self.name
source += "{\n"
for extended_by in self.extended_by:
source += " ESX_VI__TEMPLATE__DISPATCH__FREE(%s)\n" % extended_by
source += "},\n"
source += "{\n"
if self.features & Object.FEATURE__LIST:
if self.extends is not None:
# avoid "dereferencing type-punned pointer will break strict-aliasing rules" warnings
source += " esxVI_%s *next = (esxVI_%s *)item->_next;\n\n" % (self.extends, self.extends)
source += " esxVI_%s_Free(&next);\n" % self.extends
source += " item->_next = (esxVI_%s *)next;\n\n" % self.name
else:
source += " esxVI_%s_Free(&item->_next);\n\n" % self.name
source += self.generate_free_code()
source += "})\n\n"
# validate
source += "/* esxVI_%s_Validate */\n" % self.name
source += "ESX_VI__TEMPLATE__VALIDATE(%s,\n" % self.name
source += "{\n"
source += self.generate_validate_code()
source += "})\n\n"
# dynamic cast
if self.features & Object.FEATURE__DYNAMIC_CAST:
if self.extended_by is not None or self.extends is not None:
source += "/* esxVI_%s_DynamicCast */\n" % self.name
source += "ESX_VI__TEMPLATE__DYNAMIC_CAST(%s,\n" % self.name
source += "{\n"
source += self.generate_dynamic_cast_code()
source += "})\n\n"
else:
report_error("cannot add dynamic cast support for an untyped object")
# append to list
if self.features & Object.FEATURE__LIST:
source += "/* esxVI_%s_AppendToList */\n" % self.name
source += "ESX_VI__TEMPLATE__LIST__APPEND(%s)\n\n" % self.name
# deep copy
if self.extended_by is None:
if self.features & Object.FEATURE__DEEP_COPY:
source += "/* esxVI_%s_DeepCopy */\n" % self.name
source += "ESX_VI__TEMPLATE__DEEP_COPY(%s,\n" % self.name
source += "{\n"
source += self.generate_deep_copy_code()
source += "})\n\n"
if self.features & Object.FEATURE__LIST:
source += "/* esxVI_%s_DeepCopyList */\n" % self.name
source += "ESX_VI__TEMPLATE__LIST__DEEP_COPY(%s)\n\n" % self.name
else:
if self.features & Object.FEATURE__DEEP_COPY:
source += "/* esxVI_%s_DeepCopy */\n" % self.name
source += "ESX_VI__TEMPLATE__DYNAMIC_DEEP_COPY(%s)\n" % self.name
source += "{\n"
for extended_by in self.extended_by:
source += " ESX_VI__TEMPLATE__DISPATCH__DEEP_COPY(%s)\n" % extended_by
source += "},\n"
source += "{\n"
source += self.generate_deep_copy_code()
source += "})\n\n"
if self.features & Object.FEATURE__LIST:
source += "/* esxVI_%s_DeepCopyList */\n" % self.name
source += "ESX_VI__TEMPLATE__LIST__DEEP_COPY(%s)\n\n" % self.name
# cast from any type
if self.features & Object.FEATURE__ANY_TYPE:
source += "/* esxVI_%s_CastFromAnyType */\n" % self.name
if self.extended_by is None:
source += "ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(%s)\n\n" % self.name
else:
source += "ESX_VI__TEMPLATE__DYNAMIC_CAST_FROM_ANY_TYPE(%s,\n" % self.name
source += "{\n"
for extended_by in self.extended_by:
source += " ESX_VI__TEMPLATE__DISPATCH__CAST_FROM_ANY_TYPE(%s)\n" % extended_by
source += "})\n\n"
if self.features & Object.FEATURE__LIST:
source += "/* esxVI_%s_CastListFromAnyType */\n" % self.name
source += "ESX_VI__TEMPLATE__LIST__CAST_FROM_ANY_TYPE(%s)\n\n" % self.name
# serialize
if self.extended_by is None:
if self.features & Object.FEATURE__SERIALIZE:
source += "/* esxVI_%s_Serialize */\n" % self.name
source += "ESX_VI__TEMPLATE__SERIALIZE(%s,\n" % self.name
source += "{\n"
source += self.generate_serialize_code()
source += "})\n\n"
if self.features & Object.FEATURE__LIST:
source += "/* esxVI_%s_SerializeList */\n" % self.name
source += "ESX_VI__TEMPLATE__LIST__SERIALIZE(%s)\n\n" % self.name
else:
if self.features & Object.FEATURE__SERIALIZE:
source += "/* esxVI_%s_Serialize */\n" % self.name
source += "ESX_VI__TEMPLATE__DYNAMIC_SERIALIZE(%s,\n" % self.name
source += "{\n"
for extended_by in self.extended_by:
source += " ESX_VI__TEMPLATE__DISPATCH__SERIALIZE(%s)\n" % extended_by
source += "},\n"
source += "{\n"
source += self.generate_serialize_code()
source += "})\n\n"
if self.features & Object.FEATURE__LIST:
source += "/* esxVI_%s_SerializeList */\n" % self.name
source += "ESX_VI__TEMPLATE__LIST__SERIALIZE(%s)\n\n" % self.name
# deserilaize
if self.extended_by is None:
if self.features & Object.FEATURE__DESERIALIZE:
source += "/* esxVI_%s_Deserialize */\n" % self.name
source += "ESX_VI__TEMPLATE__DESERIALIZE(%s,\n" % self.name
source += "{\n"
source += self.generate_deserialize_code()
source += "})\n\n"
if self.features & Object.FEATURE__LIST:
source += "/* esxVI_%s_DeserializeList */\n" % self.name
source += "ESX_VI__TEMPLATE__LIST__DESERIALIZE(%s)\n\n" % self.name
else:
if self.features & Object.FEATURE__DESERIALIZE:
source += "/* esxVI_%s_Deserialize */\n" % self.name
source += "ESX_VI__TEMPLATE__DYNAMIC_DESERIALIZE(%s,\n" % self.name
source += "{\n"
for extended_by in self.extended_by:
source += " ESX_VI__TEMPLATE__DISPATCH__DESERIALIZE(%s)\n" % extended_by
source += "},\n"
source += "{\n"
source += self.generate_deserialize_code()
source += "})\n\n"
if self.features & Object.FEATURE__LIST:
source += "/* esxVI_%s_DeserializeList */\n" % self.name
source += "ESX_VI__TEMPLATE__LIST__DESERIALIZE(%s)\n\n" % self.name
source += "\n\n"
return source
class ManagedObject(Base):
FEATURE__LIST = (1 << 2)
def __init__(self, name, extends, properties, features=0, extended_by=None):
Base.__init__(self, "struct", name)
self.extends = extends
self.features = features
self.properties = properties
self.extended_by = extended_by
if self.extended_by is not None:
self.extended_by.sort()
def generate_struct_members(self, add_banner=False, struct_gap=False):
members = ""
if struct_gap:
members += "\n"
if self.extends is not None:
members += managed_objects_by_name[self.extends].generate_struct_members(add_banner=True) + "\n"
if self.extends is not None or add_banner:
members += " /* %s */\n" % self.name
for property in self.properties:
members += property.generate_struct_member()
if len(self.properties) < 1:
members += " /* no properties */\n"
return members
def generate_free_code(self, add_banner=False):
source = ""
if self.extends is not None:
source += managed_objects_by_name[self.extends].generate_free_code(add_banner=True) + "\n"
if self.extends is not None or add_banner:
source += " /* %s */\n" % self.name
if len(self.properties) < 1:
source += " /* no properties */\n"
else:
string = ""
for property in self.properties:
string += property.generate_free_code()
if len(string) < 1:
source += " /* no properties to be freed */\n"
else:
source += string
return source
def generate_validate_code(self, add_banner=False):
source = ""
if self.extends is not None:
source += managed_objects_by_name[self.extends].generate_validate_code(add_banner=True) + "\n"
if self.extends is not None or add_banner:
source += " /* %s */\n" % self.name
if len(self.properties) < 1:
source += " /* no properties */\n"
else:
string = ""
for property in self.properties:
string += property.generate_validate_code(managed=True)
if len(string) < 1:
source += " /* no required properties */\n"
else:
source += string
return source
def generate_lookup_code1(self, add_banner=False):
source = ""
if self.extends is not None:
source += managed_objects_by_name[self.extends].generate_lookup_code1(add_banner=True) + "\n"
if self.extends is not None or add_banner:
source += " /* %s */\n" % self.name
if len(self.properties) < 1:
source += " /* no properties */\n"
else:
string = ""
for property in self.properties:
string += " \"%s\\0\"\n" % property.name
if len(string) < 1:
source += " /* no properties */\n"
else:
source += string
return source
def generate_lookup_code2(self, add_banner=False):
source = ""
if self.extends is not None:
source += managed_objects_by_name[self.extends].generate_lookup_code2(add_banner=True) + "\n"
if self.extends is not None or add_banner:
source += " /* %s */\n" % self.name
if len(self.properties) < 1:
source += " /* no properties */\n"
else:
string = ""
for property in self.properties:
string += property.generate_lookup_code()
if len(string) < 1:
source += " /* no properties */\n"
else:
source += string
return source
def generate_comment(self):
comment = "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
comment += " * VI Managed Object: %s\n" % self.name
if self.extends is not None:
comment += " * extends %s\n" % self.extends
first = True
if self.extended_by is not None:
for extended_by in self.extended_by:
if first:
comment += " * extended by %s\n" % extended_by
first = False
else:
comment += " * %s\n" % extended_by
comment += " */\n\n"
return comment
def generate_header(self):
header = self.generate_comment()
# struct
header += "struct _esxVI_%s {\n" % self.name
if self.features & Object.FEATURE__LIST:
header += aligned(" esxVI_%s *_next; " % self.name, "/* optional */\n")
else:
header += aligned(" esxVI_%s *_unused; " % self.name, "/* optional */\n")
header += aligned(" esxVI_Type _type; ", "/* required */\n")
header += aligned(" esxVI_ManagedObjectReference *_reference; ", "/* required */\n")
header += "\n"
header += self.generate_struct_members()
header += "};\n\n"
# functions
header += "int esxVI_%s_Alloc(esxVI_%s **item);\n" % (self.name, self.name)
header += "void esxVI_%s_Free(esxVI_%s **item);\n" % (self.name, self.name)
header += "int esxVI_%s_Validate(esxVI_%s *item, esxVI_String *selectedPropertyNameList);\n" % (self.name, self.name)
if self.features & Object.FEATURE__LIST:
header += "int esxVI_%s_AppendToList(esxVI_%s **list, esxVI_%s *item);\n" % (self.name, self.name, self.name)
header += "\n\n\n"
return header
def generate_helper_header(self):
header = ""
# functions
header += ("int esxVI_Lookup%s(esxVI_Context *ctx, " +
"const char *name, " +
"esxVI_ManagedObjectReference *root, " +
"esxVI_String *selectedPropertyNameList, " +
"esxVI_%s **item, " +
"esxVI_Occurrence occurrence);\n") % (self.name, self.name)
header += "\n"
return header
def generate_source(self):
source = self.generate_comment()
# functions
source += "/* esxVI_%s_Alloc */\n" % self.name
source += "ESX_VI__TEMPLATE__ALLOC(%s)\n\n" % self.name
# free
if self.extended_by is None:
source += "/* esxVI_%s_Free */\n" % self.name
source += "ESX_VI__TEMPLATE__FREE(%s,\n" % self.name
source += "{\n"
if self.features & ManagedObject.FEATURE__LIST:
if self.extends is not None:
# avoid "dereferencing type-punned pointer will break strict-aliasing rules" warnings
source += " esxVI_%s *next = (esxVI_%s *)item->_next;\n\n" % (self.extends, self.extends)
source += " esxVI_%s_Free(&next);\n" % self.extends
source += " item->_next = (esxVI_%s *)next;\n\n" % self.name
else:
source += " esxVI_%s_Free(&item->_next);\n" % self.name
source += " esxVI_ManagedObjectReference_Free(&item->_reference);\n\n"
source += self.generate_free_code()
source += "})\n\n"
else:
source += "/* esxVI_%s_Free */\n" % self.name
source += "ESX_VI__TEMPLATE__DYNAMIC_FREE(%s,\n" % self.name
source += "{\n"
for extended_by in self.extended_by:
source += " ESX_VI__TEMPLATE__DISPATCH__FREE(%s)\n" % extended_by
source += "},\n"
source += "{\n"
if self.features & Object.FEATURE__LIST:
if self.extends is not None:
# avoid "dereferencing type-punned pointer will break strict-aliasing rules" warnings
source += " esxVI_%s *next = (esxVI_%s *)item->_next;\n\n" % (self.extends, self.extends)
source += " esxVI_%s_Free(&next);\n" % self.extends
source += " item->_next = (esxVI_%s *)next;\n\n" % self.name
else:
source += " esxVI_%s_Free(&item->_next);\n" % self.name
source += " esxVI_ManagedObjectReference_Free(&item->_reference);\n\n"
source += self.generate_free_code()
source += "})\n\n"
# validate
source += "/* esxVI_%s_Validate */\n" % self.name
source += "ESX_VI__TEMPLATE__MANAGED_VALIDATE(%s,\n" % self.name
source += "{\n"
source += self.generate_validate_code()
source += "})\n\n"
# append to list
if self.features & ManagedObject.FEATURE__LIST:
source += "/* esxVI_%s_AppendToList */\n" % self.name
source += "ESX_VI__TEMPLATE__LIST__APPEND(%s)\n\n" % self.name
source += "\n\n"
return source
def generate_helper_source(self):
source = ""
# lookup
source += "/* esxVI_Lookup%s */\n" % self.name
source += "ESX_VI__TEMPLATE__LOOKUP(%s,\n" % self.name
source += "{\n"
source += self.generate_lookup_code1()
source += "},\n"
source += "{\n"
source += self.generate_lookup_code2()
source += "})\n\n"
source += "\n\n"
return source
2011-04-10 15:26:47 +04:00
class Enum(Base):
FEATURE__ANY_TYPE = (1 << 1)
FEATURE__SERIALIZE = (1 << 2)
FEATURE__DESERIALIZE = (1 << 3)
def __init__(self, name, values, features=0):
Base.__init__(self, "enum", name)
self.values = values
self.features = features
def generate_header(self):
header = "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
header += " * VI Enum: %s\n" % self.name
header += " */\n\n"
# enum
header += "enum _esxVI_%s {\n" % self.name
header += " esxVI_%s_Undefined = 0,\n" % self.name
for value in self.values:
header += " esxVI_%s_%s,\n" % (self.name, capitalize_first(value))
header += "};\n\n"
# functions
if self.features & Enum.FEATURE__ANY_TYPE:
header += "int esxVI_%s_CastFromAnyType(esxVI_AnyType *anyType, esxVI_%s *item);\n" % (self.name, self.name)
if self.features & Enum.FEATURE__SERIALIZE:
header += "int esxVI_%s_Serialize(esxVI_%s item, const char *element, virBufferPtr output);\n" % (self.name, self.name)
if self.features & Enum.FEATURE__DESERIALIZE:
header += "int esxVI_%s_Deserialize(xmlNodePtr node, esxVI_%s *item);\n" % (self.name, self.name)
header += "\n\n\n"
return header
def generate_source(self):
source = "/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n"
source += " * VI Enum: %s\n" % self.name
source += " */\n\n"
source += "static const esxVI_Enumeration _esxVI_%s_Enumeration = {\n" % self.name
source += " esxVI_Type_%s, {\n" % self.name
for value in self.values:
source += " { \"%s\", esxVI_%s_%s },\n" % (value, self.name, capitalize_first(value))
source += " { NULL, -1 },\n"
source += " },\n"
source += "};\n\n"
# functions
if self.features & Enum.FEATURE__ANY_TYPE:
source += "/* esxVI_%s_CastFromAnyType */\n" % self.name
source += "ESX_VI__TEMPLATE__ENUMERATION__CAST_FROM_ANY_TYPE(%s)\n\n" % self.name
if self.features & Enum.FEATURE__SERIALIZE:
source += "/* esxVI_%s_Serialize */\n" % self.name
source += "ESX_VI__TEMPLATE__ENUMERATION__SERIALIZE(%s)\n\n" % self.name
if self.features & Enum.FEATURE__DESERIALIZE:
source += "/* esxVI_%s_Deserialize */\n" % self.name
source += "ESX_VI__TEMPLATE__ENUMERATION__DESERIALIZE(%s)\n\n" % self.name
source += "\n\n"
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()
managed = False
if header_items[0] == "managed":
managed = True
del header_items[0]
if len(header_items) < 2:
report_error("line %d: invalid block header" % (number))
assert header_items[0] == "object"
name = header_items[1]
extends = None
if len(header_items) > 2:
if header_items[2] != "extends":
report_error("line %d: invalid block header" % (number))
else:
extends = header_items[3]
properties = []
for line in block[1:]:
# expected format: <type> <name> <occurrence>
items = line[1].split()
if len(items) != 3:
report_error("line %d: invalid property" % line[0])
if items[2] not in valid_occurrences:
report_error("line %d: invalid occurrence" % line[0])
2011-04-10 15:26:47 +04:00
properties.append(Property(type=items[0], name=items[1],
occurrence=items[2]))
if managed:
return ManagedObject(name=name, extends=extends, properties=properties)
else:
return Object(name=name, extends=extends, properties=properties)
def parse_enum(block):
# expected format: enum <name>
header_items = block[0][1].split()
if len(header_items) < 2:
report_error("line %d: invalid block header" % (number))
assert header_items[0] == "enum"
name = header_items[1]
values = []
for line in block[1:]:
# expected format: <value>
values.append(line[1])
2011-04-10 15:26:47 +04:00
return Enum(name=name, values=values)
def parse_method(block):
# expected format: method <name> [returns <type> <occurrence>]
header_items = block[0][1].split()
if len(header_items) < 2:
report_error("line %d: invalid block header" % (number))
assert header_items[0] == "method"
name = header_items[1]
returns = None
if len(header_items) > 2:
if header_items[2] != "returns":
report_error("line %d: invalid block header" % (number))
else:
2011-04-10 15:26:47 +04:00
returns = Parameter(type=header_items[3], name="output",
occurrence=header_items[4])
parameters = []
for line in block[1:]:
# expected format: <type> <name> <occurrence>
items = line[1].split()
if len(items) != 3:
report_error("line %d: invalid property" % line[0])
if items[2] not in valid_occurrences:
report_error("line %d: invalid occurrence" % line[0])
2011-04-10 15:26:47 +04:00
parameters.append(Parameter(type=items[0], name=items[1],
occurrence=items[2]))
2011-04-10 15:26:47 +04:00
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 objects_by_name or \
type in managed_objects_by_name or \
type in enums_by_name
def open_and_print(filename):
if filename.startswith("./"):
print " GEN " + filename[2:]
else:
print " GEN " + filename
return open(filename, "wb")
predefined_enums = ["Boolean"]
predefined_objects = ["AnyType",
"Int",
"Long",
"String",
"DateTime",
"MethodFault",
"ManagedObjectReference"]
additional_enum_features = { "ManagedEntityStatus" : Enum.FEATURE__ANY_TYPE,
"TaskInfoState" : Enum.FEATURE__ANY_TYPE,
"VirtualMachinePowerState" : Enum.FEATURE__ANY_TYPE }
2010-12-30 03:36:31 +03:00
additional_object_features = { "AutoStartDefaults" : Object.FEATURE__ANY_TYPE,
"AutoStartPowerInfo" : Object.FEATURE__ANY_TYPE,
2010-12-30 03:36:31 +03:00
"DatastoreHostMount" : Object.FEATURE__DEEP_COPY | Object.FEATURE__LIST | Object.FEATURE__ANY_TYPE,
"DatastoreInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__DYNAMIC_CAST,
2010-12-30 03:36:31 +03:00
"HostConfigManager" : Object.FEATURE__ANY_TYPE,
"HostCpuIdInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST,
"HostDatastoreBrowserSearchResults" : Object.FEATURE__LIST | Object.FEATURE__ANY_TYPE,
"ManagedObjectReference" : Object.FEATURE__ANY_TYPE,
"ObjectContent" : Object.FEATURE__DEEP_COPY,
"ResourcePoolResourceUsage" : Object.FEATURE__ANY_TYPE,
"ServiceContent" : Object.FEATURE__DESERIALIZE,
"SharesInfo" : Object.FEATURE__ANY_TYPE,
"TaskInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST,
"UserSession" : Object.FEATURE__ANY_TYPE,
"VirtualMachineQuestionInfo" : Object.FEATURE__ANY_TYPE,
"VirtualMachineSnapshotTree" : Object.FEATURE__DEEP_COPY | Object.FEATURE__ANY_TYPE,
"VmEventArgument" : Object.FEATURE__DESERIALIZE }
removed_object_features = {}
if "srcdir" in os.environ:
input_filename = os.path.join(os.environ["srcdir"], "esx/esx_vi_generator.input")
output_dirname = os.path.join(os.environ["srcdir"], "esx")
else:
input_filename = os.path.join(os.getcwd(), "esx_vi_generator.input")
output_dirname = os.getcwd()
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"))
types_typefromstring = open_and_print(os.path.join(output_dirname, "esx_vi_types.generated.typefromstring"))
types_header = open_and_print(os.path.join(output_dirname, "esx_vi_types.generated.h"))
types_source = open_and_print(os.path.join(output_dirname, "esx_vi_types.generated.c"))
methods_header = open_and_print(os.path.join(output_dirname, "esx_vi_methods.generated.h"))
methods_source = open_and_print(os.path.join(output_dirname, "esx_vi_methods.generated.c"))
methods_macro = open_and_print(os.path.join(output_dirname, "esx_vi_methods.generated.macro"))
helpers_header = open_and_print(os.path.join(output_dirname, "esx_vi.generated.h"))
helpers_source = open_and_print(os.path.join(output_dirname, "esx_vi.generated.c"))
number = 0
objects_by_name = {}
managed_objects_by_name = {}
enums_by_name = {}
methods_by_name = {}
block = None
# parse input file
for line in file(input_filename, "rb").readlines():
number += 1
if "#" in line:
line = line[:line.index("#")]
line = line.lstrip().rstrip()
if len(line) < 1:
continue
if line.startswith("object") or line.startswith("managed object") or \
line.startswith("enum") or line.startswith("method"):
if block is not None:
report_error("line %d: nested block found" % (number))
else:
block = []
if block is not None:
if line == "end":
if block[0][1].startswith("object"):
obj = parse_object(block)
objects_by_name[obj.name] = obj
elif block[0][1].startswith("managed object"):
obj = parse_object(block)
managed_objects_by_name[obj.name] = obj
elif block[0][1].startswith("enum"):
enum = parse_enum(block)
enums_by_name[enum.name] = enum
else:
method = parse_method(block)
methods_by_name[method.name] = method
block = None
else:
block.append((number, line))
for method in methods_by_name.values():
# method parameter types must be serializable
for parameter in method.parameters:
if not parameter.is_type_generated():
continue
if parameter.is_enum():
enums_by_name[parameter.type].features |= Enum.FEATURE__SERIALIZE
else:
objects_by_name[parameter.type].features |= Object.FEATURE__SERIALIZE
objects_by_name[parameter.type].candidate_for_dynamic_cast = True
# detect list usage
if parameter.occurrence == OCCURRENCE__REQUIRED_LIST or \
parameter.occurrence == OCCURRENCE__OPTIONAL_LIST:
if parameter.is_enum():
report_error("unsupported usage of enum '%s' as list in '%s'"
% (parameter.type, method.name))
else:
objects_by_name[parameter.type].features |= Object.FEATURE__LIST
# method return types must be deserializable
if method.returns and method.returns.is_type_generated():
if method.returns.is_enum():
enums_by_name[method.returns.type].features |= Enum.FEATURE__DESERIALIZE
else:
objects_by_name[method.returns.type].features |= Object.FEATURE__DESERIALIZE
objects_by_name[method.returns.type].candidate_for_dynamic_cast = True
# detect list usage
if method.returns.occurrence == OCCURRENCE__REQUIRED_LIST or \
method.returns.occurrence == OCCURRENCE__OPTIONAL_LIST:
if method.returns.is_enum():
report_error("unsupported usage of enum '%s' as list in '%s'"
% (method.returns.type, method.name))
else:
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 |= additional_enum_features[enum.name]
if additional_enum_features[enum.name] & Enum.FEATURE__ANY_TYPE:
enum.features |= Enum.FEATURE__DESERIALIZE
for obj in objects_by_name.values():
for property in obj.properties:
if property.occurrence != OCCURRENCE__IGNORED and \
not is_known_type(property.type):
report_error("object '%s' contains unknown property type '%s'" % (obj.name, property.type))
if obj.extends is not None:
if not is_known_type(obj.extends):
report_error("object '%s' extends unknown object '%s'" % (obj.name, obj.extends))
for property in obj.properties:
if not property.is_type_generated():
continue
if property.is_enum():
enums_by_name[property.type].candidate_for_dynamic_cast = True
else:
objects_by_name[property.type].candidate_for_dynamic_cast = True
# detect list usage
if property.occurrence == OCCURRENCE__REQUIRED_LIST or \
property.occurrence == OCCURRENCE__OPTIONAL_LIST:
if property.is_enum():
report_error("unsupported usage of enum '%s' as list in '%s'"
% (property.type, obj.type))
else:
objects_by_name[property.type].features |= Object.FEATURE__LIST
# apply/remove additional features
if obj.name in additional_object_features:
obj.features |= additional_object_features[obj.name]
if additional_object_features[obj.name] & Object.FEATURE__ANY_TYPE:
obj.features |= Object.FEATURE__DESERIALIZE
if obj.name in removed_object_features:
obj.features &= ~removed_object_features[obj.name]
# detect extended_by relation
if obj.extends is not None:
extended_obj = objects_by_name[obj.extends]
if extended_obj.extended_by is None:
extended_obj.extended_by = [obj.name]
else:
extended_obj.extended_by.append(obj.name)
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
# object then this type needs the dynamic cast feature
if obj.candidate_for_dynamic_cast and obj.extended_by:
obj.features |= Object.FEATURE__DYNAMIC_CAST
def propagate_feature(obj, feature):
global features_have_changed
if not (obj.features & feature):
return
for property in obj.properties:
if property.occurrence == OCCURRENCE__IGNORED or \
not property.is_type_generated():
continue
if property.is_enum():
if feature == Object.FEATURE__SERIALIZE and \
not (enums_by_name[property.type].features & Enum.FEATURE__SERIALIZE):
enums_by_name[property.type].features |= Enum.FEATURE__SERIALIZE
features_have_changed = True
elif feature == Object.FEATURE__DESERIALIZE and \
not (enums_by_name[property.type].features & Enum.FEATURE__DESERIALIZE):
enums_by_name[property.type].features |= Enum.FEATURE__DESERIALIZE
features_have_changed = True
elif property.is_object():
if not (objects_by_name[property.type].features & feature):
objects_by_name[property.type].features |= feature
features_have_changed = True
if obj.name != property.type:
propagate_feature(objects_by_name[property.type], feature)
def inherit_features(obj):
global features_have_changed
if obj.extended_by is not None:
for extended_by in obj.extended_by:
previous = objects_by_name[extended_by].features
objects_by_name[extended_by].features |= obj.features
if objects_by_name[extended_by].features != previous:
features_have_changed = True
if obj.extends is not None:
previous = objects_by_name[obj.extends].features
objects_by_name[obj.extends].features |= obj.features
if objects_by_name[obj.extends].features != previous:
features_have_changed = True
if obj.extended_by is not None:
for extended_by in obj.extended_by:
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
# spreading needs to be done alternating on both directions because they can
# affect each other
features_have_changed = True
while features_have_changed:
features_have_changed = False
for obj in objects_by_name.values():
propagate_feature(obj, Object.FEATURE__DEEP_COPY)
propagate_feature(obj, Object.FEATURE__SERIALIZE)
propagate_feature(obj, Object.FEATURE__DESERIALIZE)
for obj in objects_by_name.values():
inherit_features(obj)
for obj in managed_objects_by_name.values():
for property in obj.properties:
if property.occurrence != OCCURRENCE__IGNORED and \
not is_known_type(property.type):
report_error("object '%s' contains unknown property type '%s'" % (obj.name, property.type))
if obj.extends is not None:
if not is_known_type(obj.extends):
report_error("object '%s' extends unknown object '%s'" % (obj.name, obj.extends))
# detect extended_by relation
if obj.extends is not None:
extended_obj = managed_objects_by_name[obj.extends]
if extended_obj.extended_by is None:
extended_obj.extended_by = [obj.name]
else:
extended_obj.extended_by.append(obj.name)
extended_obj.extended_by.sort()
types_typedef.write("/* Generated by esx_vi_generator.py */\n\n\n\n")
types_typeenum.write("/* Generated by esx_vi_generator.py */\n\n")
types_typetostring.write("/* Generated by esx_vi_generator.py */\n\n")
types_typefromstring.write("/* Generated by esx_vi_generator.py */\n\n")
types_header.write("/* Generated by esx_vi_generator.py */\n\n\n\n")
types_source.write("/* Generated by esx_vi_generator.py */\n\n\n\n")
methods_header.write("/* Generated by esx_vi_generator.py */\n\n\n\n")
methods_source.write("/* Generated by esx_vi_generator.py */\n\n\n\n")
methods_macro.write("/* Generated by esx_vi_generator.py */\n\n\n\n")
helpers_header.write("/* Generated by esx_vi_generator.py */\n\n\n\n")
helpers_source.write("/* Generated by esx_vi_generator.py */\n\n\n\n")
# output enums
types_typedef.write("/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" +
" * VI Enums\n" +
" */\n\n")
names = enums_by_name.keys()
names.sort()
for name in names:
types_typedef.write(enums_by_name[name].generate_typedef())
types_typeenum.write(enums_by_name[name].generate_typeenum())
types_typetostring.write(enums_by_name[name].generate_typetostring())
types_typefromstring.write(enums_by_name[name].generate_typefromstring())
types_header.write(enums_by_name[name].generate_header())
types_source.write(enums_by_name[name].generate_source())
# output objects
types_typedef.write("\n\n\n" +
"/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" +
" * VI Objects\n" +
" */\n\n")
types_typeenum.write("\n")
types_typetostring.write("\n")
types_typefromstring.write("\n")
names = objects_by_name.keys()
names.sort()
for name in names:
types_typedef.write(objects_by_name[name].generate_typedef())
types_typeenum.write(objects_by_name[name].generate_typeenum())
types_typetostring.write(objects_by_name[name].generate_typetostring())
types_typefromstring.write(objects_by_name[name].generate_typefromstring())
types_header.write(objects_by_name[name].generate_header())
types_source.write(objects_by_name[name].generate_source())
# output managed objects
types_typedef.write("\n\n\n" +
"/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n" +
" * VI Managed Objects\n" +
" */\n\n")
types_typeenum.write("\n")
types_typetostring.write("\n")
types_typefromstring.write("\n")
names = managed_objects_by_name.keys()
names.sort()
for name in names:
types_typedef.write(managed_objects_by_name[name].generate_typedef())
types_typeenum.write(managed_objects_by_name[name].generate_typeenum())
types_typetostring.write(managed_objects_by_name[name].generate_typetostring())
types_typefromstring.write(managed_objects_by_name[name].generate_typefromstring())
types_header.write(managed_objects_by_name[name].generate_header())
types_source.write(managed_objects_by_name[name].generate_source())
# output methods
names = methods_by_name.keys()
names.sort()
for name in names:
methods_header.write(methods_by_name[name].generate_header())
methods_source.write(methods_by_name[name].generate_source())
sorted_usage = list(autobind_map_usage)
sorted_usage.sort()
for usage in sorted_usage:
name = autobind_map[usage]
string = aligned("#define ESX_VI__METHOD__PARAMETER__THIS__%s " % name, "\\\n", 78)
string += " ESX_VI__METHOD__PARAMETER__THIS_FROM_SERVICE(ManagedObjectReference, \\\n"
string += aligned("", "%s)\n\n\n\n" % name, 49)
methods_macro.write(string)
# output helpers
names = managed_objects_by_name.keys()
names.sort()
for name in names:
helpers_header.write(managed_objects_by_name[name].generate_helper_header())
helpers_source.write(managed_objects_by_name[name].generate_helper_source())