class ModuleGenerator: # Class initializer def __init__(self, model, baseName, noid, friendlyName, actionLocation, bGenerateDOMSchemas, bGenerateMethods, bClient, bADIReport): self._model = model # Options self._baseName = baseName self._noid = noid self._friendlyName = friendlyName self._bGenerateMethods = bGenerateMethods self._bADIReport = bADIReport # Generator state self._out = None # Module self._module = HDKModule(model, baseName, actionLocation, bGenerateDOMSchemas) # Generation options self._bGenerateActions = not bClient and self._module.actions self._bGenerateServices = not bClient and self._module.services self._bGenerateModule = self._module.actions or self._module.events self._bGenerateModuleDynamic = not bClient and self._bGenerateModule # # Generate code # def generate(self, dir, fhReport): for file, fn, bGenerate in \ [(os.path.join(dir, self._module.filename('.h')), self._generate_h, not self._bGenerateMethods), (os.path.join(dir, self._module.filename('.c')), self._generate_c, not self._bGenerateMethods), (os.path.join(dir, self._module.filename('_methods.c')), self._generate_methods_c, self._bGenerateMethods), (os.path.join(dir, self._module.filename('_adi.txt')), self._generate_adi_txt, self._bADIReport)]: if bGenerate: if fhReport is not None: print >> fhReport, 'Generating "%s" ...' % file self._out = open(file, "w") try: fn() except: raise finally: self._out.close() # # Output helper methods # # Output def _write(self, s): self._out.write(s) # Write .c file header def _write_header_c(self): self._write('''\ /* * Copyright (c) 2008-2010 Cisco Systems, Inc. All rights reserved. * * Cisco Systems, Inc. retains all right, title and interest (including all * intellectual property rights) in and to this computer program, which is * protected by applicable intellectual property laws. Unless you have obtained * a separate written license from Cisco Systems, Inc., you are not authorized * to utilize all or a part of this computer program for any purpose (including * reproduction, distribution, modification, and compilation into object code), * and you must immediately destroy or return to Cisco Systems, Inc. all copies * of this computer program. If you are licensed by Cisco Systems, Inc., your * rights to utilize this computer program are limited by the terms of that * license. To obtain a license, please contact Cisco Systems, Inc. * * This computer program contains trade secrets owned by Cisco Systems, Inc. * and, unless unauthorized by Cisco Systems, Inc. in writing, you agree to * maintain the confidentiality of this computer program and related information * and to not disclose this computer program and related information to any * other person or entity. * * THIS COMPUTER PROGRAM IS PROVIDED AS IS WITHOUT ANY WARRANTIES, AND CISCO * SYSTEMS, INC. EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, * INCLUDING THE WARRANTIES OF MERCHANTIBILITY, FITNESS FOR A PARTICULAR * PURPOSE, TITLE, AND NONINFRINGEMENT. */ ''') # Write .h file header def _write_header_h(self): self._write_header_c() self._write('''\ #ifndef %s #define %s ''' % (self._module.header_sentinel('.h'), self._module.header_sentinel('.h'))) # Write .h file footer def _write_footer_h(self): self._write('''\ #endif /* %s */ ''' % (self._module.header_sentinel('.h'))) # Write a section comment def _write_section(self, comment): self._write('''\ /* * %s */ ''' % (comment)) # Write enumeration definition def _write_enumeration(self, name, values, ix_start=0, ix_delta=1, value_symbols={}): # Enum header self._write('''\ typedef enum _%s { ''' % (name)) # Write enum values ix_value = ix_start ix_value_last = ix_start + ix_delta * (len(values) - 1) sep = "," for value in values: # Does the value have a symbol? if value_symbols.has_key(value): str_value = value_symbols[value] else: str_value = str(ix_value) # Don't separate the last value if ix_value == ix_value_last: sep = "" # Write the enum value self._write('''\ %s = %s%s ''' % (value, str_value, sep)) ix_value += ix_delta # Enum footer self._write('''\ } %s; ''' % (name)) # Write schema definition def _write_schema(self, schema_nodes_static, schema_static, nodes, element_path_static=None, element_path=None): # Schema nodes header self._write('''\ static const HDK_XML_SchemaNode %s[] = { ''' % (schema_nodes_static)) # Write the schema nodes ix = 0 for node in nodes: # Compute the parent index if node.parent: ix_parent = nodes.index(node.parent) else: ix_parent = 0 # Compute the options options = [] if node.is_optional: options.append("HDK_XML_SchemaNodeProperty_Optional") if node.is_unbounded: options.append("HDK_XML_SchemaNodeProperty_Unbounded") if node.is_any_element: options.append("HDK_XML_SchemaNodeProperty_AnyElement") if node.is_error: options.append("HDK_XML_SchemaNodeProperty_ErrorOutput") if node.is_csv: options.append("HDK_XML_SchemaNodeProperty_CSV") if options: options = " | ".join(options) else: options = "0" # Write the schema node self._write('''\ /* %d */ { %d, %s, %s, %s }, ''' % (ix, ix_parent, self._module.element_value( node.element()), self._module.type_value(node.type), options)) ix += 1 # Schema nodes footer self._write('''\ HDK_XML_Schema_SchemaNodesEnd }; ''') # Schema struct element path if element_path_static and element_path: self._write('''\ static const HDK_XML_Element %s[] = { ''' % (element_path_static)) for element in element_path: self._write('''\ %s, ''' % (self._module.element_value(element))) self._write('''\ HDK_MOD_ElementPathEnd }; ''') # Schema self._write('''\ static const HDK_XML_Schema %s = { s_namespaces, s_elements, %s, %s }; ''' % (schema_static, schema_nodes_static, "s_enumTypes" if self._module.schema.enums else "0")) # Write action definition def _write_action(self, action_loc): http_method, http_location, action, noauth = \ (action_loc.http_method, action_loc.http_location, action_loc.action, action_loc.noauth) # Compute the SOAP action is_get = (http_method.lower() == "get") if is_get: soap_action = "0" else: soap_action = '"' + action.uri + '"' # Compute the action function name if self._bGenerateActions: action_fn = self._module.action_fn(action) else: action_fn = "0" # Compute the schema struct element path symbols if not is_get and self._module.schema.struct_nodes_envelope( action.inputMember, soap=True): input_element_path = self._module.schema_element_path_static( action, "_Input") else: input_element_path = "0" if self._module.schema.struct_nodes_envelope(action.outputMember, soap=True): output_element_path = self._module.schema_element_path_static( action, "_Output") else: output_element_path = "0" # Compute the method options options = [] if noauth: options.append("HDK_MOD_MethodOption_NoBasicAuth") if is_get: options.append("HDK_MOD_MethodOption_NoInputStruct") if options: options = " | ".join(options) else: options = "0" # Compute the OK and REBOOT values result_member = action.outputMember.type.members[0] if "REBOOT" in action.resultEnum.enumValues: result_reboot = "REBOOT" else: result_reboot = "OK" # Write the method struct self._write('''\ { "%s", "%s", %s, %s, &%s, &%s, %s, %s, %s, %s, %s, %s, %s }, ''' % (http_method, http_location, soap_action, action_fn, self._module.schema_static(action, suffix="_Input"), self._module.schema_static(action, suffix="_Output"), input_element_path, output_element_path, options, self._module.element_value( (result_member.namespace, result_member.name)), self._module.type_value(result_member.type), self._module.enum_value(result_member.type, "OK"), self._module.enum_value(result_member.type, result_reboot))) # Write event definition def _write_event(self, event): # Write the method struct self._write('''\ { "%s", &%s }, ''' % (event.uri, self._module.schema_static(event))) # # *.h code generator # def _generate_h(self): # File header self._write_header_h() # Includes self._write('''\ #include "hdk_mod.h" /* * Macro to control public exports */ #ifdef __cplusplus # define %s_PREFIX extern "C" #else # define %s_PREFIX extern #endif #ifdef HDK_MOD_STATIC # define %s %s_PREFIX #else /* ndef HDK_MOD_STATIC */ # ifdef _MSC_VER # ifdef %s # define %s %s_PREFIX __declspec(dllexport) # else # define %s %s_PREFIX __declspec(dllimport) # endif # else /* ndef _MSC_VER */ # ifdef %s # define %s %s_PREFIX __attribute__ ((visibility("default"))) # else # define %s %s_PREFIX # endif # endif /*def _MSC_VER */ #endif /* def HDK_MOD_STATIC */ ''' % (self._module.export_macro(), self._module.export_macro(), self._module.export_macro(), self._module.export_macro(), self._module.build_macro(), self._module.export_macro(), self._module.export_macro(), self._module.export_macro(), self._module.export_macro(), self._module.build_macro(), self._module.export_macro(), self._module.export_macro(), self._module.export_macro(), self._module.export_macro())) # Element enumeration self._write_section("Elements") self._write_enumeration(self._module.element_enum(), [ self._module.element_value(element) for element in self._module.schema.elements ]) # Enumeration type definition if self._module.schema.enums: self._write_section("Enum types enumeration") self._write_enumeration(self._module.enum_type_enum(), [ self._module.enum_type_value(enum) for enum in self._module.schema.enums ], ix_start=-1, ix_delta=-1) # Enumeration declarations for enum in self._module.schema.enums: # Enumeration type definition self._write_section("Enumeration %s" % (enum.uri)) value_unknown = self._module.enum_value(enum, None, is_unknown=True) values = [value_unknown] values.extend([ self._module.enum_value(enum, value) for value in enum.enumValues ]) self._write_enumeration( self._module.enum_enum(enum), values, ix_start=-1, value_symbols={value_unknown: "HDK_XML_Enum_Unknown"}) # Enumeration accessor declarations self._write('''\ #define %s(pStruct, element, value) HDK_XML_Set_Enum(pStruct, element, %s, 0 ? %s : (value)) #define %s(pStruct, element, value) HDK_XML_Append_Enum(pStruct, element, %s, 0 ? %s : (value)) #define %s(pStruct, element) (%s*)HDK_XML_Get_Enum(pStruct, element, %s) #define %s(pStruct, element, value) (%s)HDK_XML_GetEx_Enum(pStruct, element, %s, 0 ? %s : (value)) #define %s(pMember) (%s*)HDK_XML_GetMember_Enum(pMember, %s) ''' % (self._module.enum_accessor(enum, "Set"), self._module.enum_type_value(enum), self._module.enum_value( enum, enum.enumValues[0]), self._module.enum_accessor( enum, "Append"), self._module.enum_type_value(enum), self._module.enum_value( enum, enum.enumValues[0]), self._module.enum_accessor(enum, "Get"), self._module.enum_enum(enum), self._module.enum_type_value(enum), self._module.enum_accessor(enum, "GetEx"), self._module.enum_enum(enum), self._module.enum_type_value(enum), self._module.enum_value(enum, enum.enumValues[0]), self._module.enum_accessor(enum, "GetMember"), self._module.enum_enum(enum), self._module.enum_type_value(enum))) # Action enumeration if self._module.actions: self._write_section("Method enumeration") self._write_enumeration(self._module.action_enum(), [ self._module.action_value(action_loc) for action_loc in self._module.action_locations() ]) # Action sentinels if self._bGenerateActions: self._write_section("Method sentinels") for action in self._module.actions: self._write('''\ #define %s ''' % (self._module.action_sentinel(action))) # Action declarations if self._bGenerateActions: self._write_section("Methods") for action in self._module.actions: self._write('''\ extern void %s(HDK_MOD_MethodContext* pMethodCtx, HDK_XML_Struct* pInput, HDK_XML_Struct* pOutput); ''' % (self._module.action_fn(action))) # Event enumeration if self._module.events: self._write_section("Event enumeration") self._write_enumeration(self._module.event_enum(), [ self._module.event_value(event) for event in self._module.events ]) # DOM (struct) schema accessor declarations if self._module.schema.structs: self._write_section("DOM Schemas") for struct in self._module.schema.structs: self._write('''\ %s const HDK_XML_Schema* %s(); ''' % (self._module.export_macro(), self._module.dom_schema_fn(struct))) # State declarations if self._module.states: self._write_section("ADI") self._write_enumeration(self._module.state_enum(), [ self._module.state_value(state) for state in self._module.states ], ix_start=1) self._write_section("ADI sentinels") for state in self._module.states: # Determine get/set usages = {} for actionState in self._model.actionStates: if state.uri in actionState.stateMembers: stateMember = actionState.stateMembers[state.uri] if stateMember.isGet: usages["get"] = None if stateMember.isSet: usages["set"] = None for usage in sorted(usages.iterkeys()): self._write('''\ #define %s ''' % (self._module.state_value_sentinel(state, usage))) # Module declaration if self._bGenerateModule: self._write_section("Module") self._write('''\ %s const HDK_MOD_Module* %s(void); ''' % (self._module.export_macro(), self._module.module_fn())) if self._bGenerateModuleDynamic: self._write('''\ /* Dynamic server module export */ %s const HDK_MOD_Module* HDK_SRV_Module(void); ''' % (self._module.export_macro())) # File footer self._write_footer_h() # # *.c code generator # def _generate_c(self): # File header self._write_header_c() self._write('''\ #include "%s" #include <string.h> ''' % (self._module.filename('.h'))) # Namespace table self._write_section("Namespaces") self._write('''\ static const HDK_XML_Namespace s_namespaces[] = { ''') for namespace in self._module.schema.namespaces: self._write('''\ /* %d */ "%s", ''' % (self._module.schema.namespace_index(namespace), namespace)) self._write('''\ HDK_XML_Schema_NamespacesEnd }; ''') # Elements table self._write_section("Elements") self._write('''\ static const HDK_XML_ElementNode s_elements[] = { ''') for element in self._module.schema.elements: self._write('''\ /* %s = %d */ { %d, "%s" }, ''' % (self._module.element_value(element), self._module.schema.element_index(element), self._module.schema.namespace_index(element[0]), element[1])) self._write('''\ HDK_XML_Schema_ElementsEnd }; ''') # Enumerations definitions for enum in self._module.schema.enums: # Enumeration string table self._write_section("Enumeration %s" % (enum.uri)) self._write('''\ static const HDK_XML_EnumValue %s[] = { ''' % (self._module.enum_type_strings_static(enum))) for value in enum.enumValues: self._write('''\ "%s", ''' % (value)) self._write('''\ HDK_XML_Schema_EnumTypeValuesEnd }; ''') # Enum types array if self._module.schema.enums: self._write_section("Enumeration types array") self._write('''\ static const HDK_XML_EnumType s_enumTypes[] = { ''') sep = ',' for enum in self._module.schema.enums: if enum is self._module.schema.enums[-1]: sep = "" self._write('''\ %s%s ''' % (self._module.enum_type_strings_static(enum), sep)) self._write('''\ }; ''') # Action definitions for action in self._module.actions: self._write_section("Method %s" % (action.uri)) # Input schema self._write_schema( self._module.schema_nodes_static(action, suffix="_Input"), self._module.schema_static(action, suffix="_Input"), self._module.schema.struct_nodes(action.inputMember, soap=True), element_path_static=self._module.schema_element_path_static( action, suffix="_Input"), element_path=self._module.schema.struct_nodes_envelope( action.inputMember, soap=True)) # Output schema self._write('''\ ''') self._write_schema( self._module.schema_nodes_static(action, suffix="_Output"), self._module.schema_static(action, suffix="_Output"), self._module.schema.struct_nodes(action.outputMember, soap=True), element_path_static=self._module.schema_element_path_static( action, suffix="_Output"), element_path=self._module.schema.struct_nodes_envelope( action.outputMember, soap=True)) # Actions table if self._module.actions: self._write_section("Methods") # Actions table header self._write('''\ static const HDK_MOD_Method s_methods[] = { ''') # Write each action node for action_loc in self._module.action_locations(): self._write_action(action_loc) # Actions table footer self._write('''\ HDK_MOD_MethodsEnd }; ''') # Event definitions for event in self._module.events: self._write_section("Event %s" % (event.uri)) self._write_schema(self._module.schema_nodes_static(event), self._module.schema_static(event), self._module.schema.struct_nodes(event.member)) # Events table if self._module.events: self._write_section("Events") # Events table header self._write('''\ static const HDK_MOD_Event s_events[] = { ''') # Write each event node for event in self._module.events: self._write_event(event) # Events table footer self._write('''\ HDK_MOD_EventsEnd }; ''') if self._bGenerateServices: # Services action tables self._write_section("Service Methods") for service in self._module.services: # Service actions header self._write('''\ static const HDK_MOD_Method* %s[] = { ''' % (self._module.service_actions_name(service))) # Service actions for action_uri in service.actions: action_loc = [ a for a in self._module.action_locations() if a.action.uri == action_uri ][0] self._write('''\ &s_methods[%s], ''' % (self._module.action_value(action_loc))) # Service actions footer self._write('''\ 0 }; ''') # Services event tables self._write_section("Service Events") for service in self._module.services: # Service events header self._write('''\ static const HDK_MOD_Event* %s[] = { ''' % (self._module.service_events_name(service))) # Service events for eventURI in service.events: event = [ e for e in self._module.events if e.uri == eventURI ][0] self._write('''\ &s_events[%s], ''' % (self._module.event_value(event))) # Service events footer self._write('''\ 0 }; ''') # Services table self._write_section("Services") # Services table header self._write('''\ static const HDK_MOD_Service s_services[] = { ''') # Write each service node for service in self._module.services: self._write('''\ { "%s", %s, %s }, ''' % (service.uri, self._module.service_actions_name(service), self._module.service_events_name(service))) # Services table footer self._write('''\ HDK_MOD_ServicesEnd }; ''') # State definitions if self._module.states: self._write_section("ADI") self._write_schema("s_schemaNodes_ADI", "s_schema_ADI", self._module.schema.state_nodes()) # Struct schema definitions for struct in self._module.schema.structs: self._write_section("Struct %s" % (struct.uri)) self._write_schema(self._module.schema_nodes_static(struct), self._module.schema_static(struct), self._module.schema.struct_nodes(struct)) self._write('''\ /* extern */ const HDK_XML_Schema* %s() { return &%s; } ''' % (self._module.dom_schema_fn(struct), self._module.schema_static(struct))) # Module definition if self._bGenerateModule: self._write_section("Module") # Network Object ID definition if self._noid is not None: self._write('''\ /* %s */ static const HDK_XML_UUID s_uuid_NOID = { { %s } }; ''' % (self._noid, ", ".join( ["0x%02x" % ord(byte) for byte in self._noid.bytes]))) # Module definition and accessors self._write('''\ static const HDK_MOD_Module s_module = { %s, %s, %s, %s, %s, %s }; const HDK_MOD_Module* %s(void) { return &s_module; } ''' % ("&s_uuid_NOID" if self._noid else "0", '"' + self._friendlyName + '"' if self._friendlyName else "0", "s_services" if self._bGenerateServices else "0", "s_methods" if self._module.actions else "0", "s_events" if self._module.events else "0", "&s_schema_ADI" if self._module.states else "0", self._module.module_fn())) if self._bGenerateModuleDynamic: self._write('''\ const HDK_MOD_Module* HDK_SRV_Module(void) { return &s_module; } ''') # # *_methods.c code generator # def _generate_methods_c(self): # File header self._write_header_c() self._write('''\ #include "%s" #include "hdk_srv.h" /* Helper method for HNAP results */ #define SetHNAPResult(pStruct, prefix, method, result) \\ prefix##_Set_##method##Result(pStruct, prefix##_Element_##method##Result, prefix##_Enum_##method##Result_##result) ''' % (self._module.filename('.h'))) # Action declarations for action in self._module.actions: self._write_section("Method %s" % (action.uri)) self._write('''\ #ifdef %s void %s(HDK_MOD_MethodContext* pMethodCtx, HDK_XML_Struct* pInput, HDK_XML_Struct* pOutput) { /* Unused parameters */ (void)pMethodCtx; (void)pInput; (void)pOutput; } #endif /* %s */ ''' % (self._module.action_sentinel(action), self._module.action_fn(action), self._module.action_sentinel(action))) # # *_adi.txt report generator # def _generate_adi_txt(self): # ADI report title self._write('''\ ====================================================================== ADI Report for the %s Module ====================================================================== ''' % (self._baseName.upper())) # Output the ADI values used (show get/set) self._write('''\ ====================================================================== ADI values ====================================================================== ''') for state in self._model.referenced_states(): # Determine get/set usages = {} for actionState in self._model.actionStates: if state.uri in actionState.stateMembers: stateMember = actionState.stateMembers[state.uri] if stateMember.isGet: usages["get"] = None if stateMember.isSet: usages["set"] = None sUsages = ', '.join(sorted(usages.iterkeys())) # Get the base type type = state.type nArray = 0 while type.isArray: nArray += 1 type = type.arrayType sArray = "[]" * nArray # Get the type description sDesc = "" if type.isEnum: sDesc = "enum" elif type.isStruct: sDesc = "struct" # Get the type string if sDesc: sType = '%s%s (%s, "%s")' % (type.name, sArray, sDesc, type.namespace) else: sType = '%s%s' % (type.name, sArray) self._write('''\ %s Namespace: "%s" Name: "%s" Type: %s Usage: %s ''' % (self._module.state_value(state), state.namespace, state.name, sType, sUsages)) # Output the ADI values used by action self._write('''\ ====================================================================== ADI values by action ====================================================================== ''') for actionState in self._model.actionStates: self._write('''\ %s ''' % (actionState.uri)) for stateMember in sorted(actionState.stateMembers.itervalues()): # Determine usage usages = {} if stateMember.isGet: usages["get"] = None if stateMember.isSet: usages["set"] = None sUsages = ', '.join(sorted(usages.iterkeys())) self._write('''\ [%s] %s ''' % (sUsages, self._module.state_value(stateMember.state)))
class ModuleGenerator: # Class initializer def __init__(self, model, baseName, noid, friendlyName, actionLocation, bGenerateDOMSchemas, bGenerateMethods, bClient, bADIReport): self._model = model # Options self._baseName = baseName self._noid = noid self._friendlyName = friendlyName self._bGenerateMethods = bGenerateMethods self._bADIReport = bADIReport # Generator state self._out = None # Module self._module = HDKModule(model, baseName, actionLocation, bGenerateDOMSchemas) # Generation options self._bGenerateActions = not bClient and self._module.actions self._bGenerateServices = not bClient and self._module.services self._bGenerateModule = self._module.actions or self._module.events self._bGenerateModuleDynamic = not bClient and self._bGenerateModule # # Generate code # def generate(self, dir, fhReport): for file, fn, bGenerate in \ [(os.path.join(dir, self._module.filename('.h')), self._generate_h, not self._bGenerateMethods), (os.path.join(dir, self._module.filename('.c')), self._generate_c, not self._bGenerateMethods), (os.path.join(dir, self._module.filename('_methods.c')), self._generate_methods_c, self._bGenerateMethods), (os.path.join(dir, self._module.filename('_adi.txt')), self._generate_adi_txt, self._bADIReport)]: if bGenerate: if fhReport is not None: print >>fhReport, 'Generating "%s" ...' % file self._out = open(file, "w") try: fn() except: raise finally: self._out.close() # # Output helper methods # # Output def _write(self, s): self._out.write(s) # Write .c file header def _write_header_c(self): self._write('''\ /* * Copyright (c) 2008-2010 Cisco Systems, Inc. All rights reserved. * * Cisco Systems, Inc. retains all right, title and interest (including all * intellectual property rights) in and to this computer program, which is * protected by applicable intellectual property laws. Unless you have obtained * a separate written license from Cisco Systems, Inc., you are not authorized * to utilize all or a part of this computer program for any purpose (including * reproduction, distribution, modification, and compilation into object code), * and you must immediately destroy or return to Cisco Systems, Inc. all copies * of this computer program. If you are licensed by Cisco Systems, Inc., your * rights to utilize this computer program are limited by the terms of that * license. To obtain a license, please contact Cisco Systems, Inc. * * This computer program contains trade secrets owned by Cisco Systems, Inc. * and, unless unauthorized by Cisco Systems, Inc. in writing, you agree to * maintain the confidentiality of this computer program and related information * and to not disclose this computer program and related information to any * other person or entity. * * THIS COMPUTER PROGRAM IS PROVIDED AS IS WITHOUT ANY WARRANTIES, AND CISCO * SYSTEMS, INC. EXPRESSLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, * INCLUDING THE WARRANTIES OF MERCHANTIBILITY, FITNESS FOR A PARTICULAR * PURPOSE, TITLE, AND NONINFRINGEMENT. */ ''') # Write .h file header def _write_header_h(self): self._write_header_c(); self._write('''\ #ifndef %s #define %s ''' % (self._module.header_sentinel('.h'), self._module.header_sentinel('.h'))) # Write .h file footer def _write_footer_h(self): self._write('''\ #endif /* %s */ ''' % (self._module.header_sentinel('.h'))) # Write a section comment def _write_section(self, comment): self._write('''\ /* * %s */ ''' % (comment)) # Write enumeration definition def _write_enumeration(self, name, values, ix_start = 0, ix_delta = 1, value_symbols = {}): # Enum header self._write('''\ typedef enum _%s { ''' % (name)) # Write enum values ix_value = ix_start ix_value_last = ix_start + ix_delta * (len(values) - 1) sep = "," for value in values: # Does the value have a symbol? if value_symbols.has_key(value): str_value = value_symbols[value] else: str_value = str(ix_value) # Don't separate the last value if ix_value == ix_value_last: sep = "" # Write the enum value self._write('''\ %s = %s%s ''' % (value, str_value, sep)) ix_value += ix_delta # Enum footer self._write('''\ } %s; ''' % (name)) # Write schema definition def _write_schema(self, schema_nodes_static, schema_static, nodes, element_path_static = None, element_path = None): # Schema nodes header self._write('''\ static const HDK_XML_SchemaNode %s[] = { ''' % (schema_nodes_static)) # Write the schema nodes ix = 0 for node in nodes: # Compute the parent index if node.parent: ix_parent = nodes.index(node.parent) else: ix_parent = 0 # Compute the options options = [] if node.is_optional: options.append("HDK_XML_SchemaNodeProperty_Optional") if node.is_unbounded: options.append("HDK_XML_SchemaNodeProperty_Unbounded") if node.is_any_element: options.append("HDK_XML_SchemaNodeProperty_AnyElement") if node.is_error: options.append("HDK_XML_SchemaNodeProperty_ErrorOutput") if node.is_csv: options.append("HDK_XML_SchemaNodeProperty_CSV") if options: options = " | ".join(options) else: options = "0" # Write the schema node self._write('''\ /* %d */ { %d, %s, %s, %s }, ''' % (ix, ix_parent, self._module.element_value(node.element()), self._module.type_value(node.type), options)) ix += 1 # Schema nodes footer self._write('''\ HDK_XML_Schema_SchemaNodesEnd }; ''') # Schema struct element path if element_path_static and element_path: self._write('''\ static const HDK_XML_Element %s[] = { ''' % (element_path_static)) for element in element_path: self._write('''\ %s, ''' % (self._module.element_value(element))) self._write('''\ HDK_MOD_ElementPathEnd }; ''') # Schema self._write('''\ static const HDK_XML_Schema %s = { s_namespaces, s_elements, %s, %s }; ''' % (schema_static, schema_nodes_static, "s_enumTypes" if self._module.schema.enums else "0")) # Write action definition def _write_action(self, action_loc): http_method, http_location, action, noauth = \ (action_loc.http_method, action_loc.http_location, action_loc.action, action_loc.noauth) # Compute the SOAP action is_get = (http_method.lower() == "get") if is_get: soap_action = "0" else: soap_action = '"' + action.uri + '"' # Compute the action function name if self._bGenerateActions: action_fn = self._module.action_fn(action) else: action_fn = "0" # Compute the schema struct element path symbols if not is_get and self._module.schema.struct_nodes_envelope(action.inputMember, soap = True): input_element_path = self._module.schema_element_path_static(action, "_Input") else: input_element_path = "0" if self._module.schema.struct_nodes_envelope(action.outputMember, soap = True): output_element_path = self._module.schema_element_path_static(action, "_Output") else: output_element_path = "0" # Compute the method options options = [] if noauth: options.append("HDK_MOD_MethodOption_NoBasicAuth") if is_get: options.append("HDK_MOD_MethodOption_NoInputStruct") if options: options = " | ".join(options) else: options = "0" # Compute the OK and REBOOT values result_member = action.outputMember.type.members[0] if "REBOOT" in action.resultEnum.enumValues: result_reboot = "REBOOT" else: result_reboot = "OK" # Write the method struct self._write('''\ { "%s", "%s", %s, %s, &%s, &%s, %s, %s, %s, %s, %s, %s, %s }, ''' % (http_method, http_location, soap_action, action_fn, self._module.schema_static(action, suffix = "_Input"), self._module.schema_static(action, suffix = "_Output"), input_element_path, output_element_path, options, self._module.element_value((result_member.namespace, result_member.name)), self._module.type_value(result_member.type), self._module.enum_value(result_member.type, "OK"), self._module.enum_value(result_member.type, result_reboot))) # Write event definition def _write_event(self, event): # Write the method struct self._write('''\ { "%s", &%s }, ''' % (event.uri, self._module.schema_static(event))) # # *.h code generator # def _generate_h(self): # File header self._write_header_h() # Includes self._write('''\ #include "hdk_mod.h" /* * Macro to control public exports */ #ifdef __cplusplus # define %s_PREFIX extern "C" #else # define %s_PREFIX extern #endif #ifdef HDK_MOD_STATIC # define %s %s_PREFIX #else /* ndef HDK_MOD_STATIC */ # ifdef _MSC_VER # ifdef %s # define %s %s_PREFIX __declspec(dllexport) # else # define %s %s_PREFIX __declspec(dllimport) # endif # else /* ndef _MSC_VER */ # ifdef %s # define %s %s_PREFIX __attribute__ ((visibility("default"))) # else # define %s %s_PREFIX # endif # endif /*def _MSC_VER */ #endif /* def HDK_MOD_STATIC */ ''' % (self._module.export_macro(), self._module.export_macro(), self._module.export_macro(), self._module.export_macro(), self._module.build_macro(), self._module.export_macro(), self._module.export_macro(), self._module.export_macro(), self._module.export_macro(), self._module.build_macro(), self._module.export_macro(), self._module.export_macro(), self._module.export_macro(), self._module.export_macro())) # Element enumeration self._write_section("Elements") self._write_enumeration(self._module.element_enum(), [ self._module.element_value(element) for element in self._module.schema.elements ]) # Enumeration type definition if self._module.schema.enums: self._write_section("Enum types enumeration") self._write_enumeration(self._module.enum_type_enum(), [ self._module.enum_type_value(enum) for enum in self._module.schema.enums ], ix_start = -1, ix_delta = -1) # Enumeration declarations for enum in self._module.schema.enums: # Enumeration type definition self._write_section("Enumeration %s" % (enum.uri)) value_unknown = self._module.enum_value(enum, None, is_unknown = True) values = [ value_unknown ] values.extend([ self._module.enum_value(enum, value) for value in enum.enumValues ]) self._write_enumeration(self._module.enum_enum(enum), values, ix_start = -1, value_symbols = { value_unknown: "HDK_XML_Enum_Unknown" }) # Enumeration accessor declarations self._write('''\ #define %s(pStruct, element, value) HDK_XML_Set_Enum(pStruct, element, %s, 0 ? %s : (value)) #define %s(pStruct, element, value) HDK_XML_Append_Enum(pStruct, element, %s, 0 ? %s : (value)) #define %s(pStruct, element) (%s*)HDK_XML_Get_Enum(pStruct, element, %s) #define %s(pStruct, element, value) (%s)HDK_XML_GetEx_Enum(pStruct, element, %s, 0 ? %s : (value)) #define %s(pMember) (%s*)HDK_XML_GetMember_Enum(pMember, %s) ''' % (self._module.enum_accessor(enum, "Set"), self._module.enum_type_value(enum), self._module.enum_value(enum, enum.enumValues[0]), self._module.enum_accessor(enum, "Append"), self._module.enum_type_value(enum), self._module.enum_value(enum, enum.enumValues[0]), self._module.enum_accessor(enum, "Get"), self._module.enum_enum(enum), self._module.enum_type_value(enum), self._module.enum_accessor(enum, "GetEx"), self._module.enum_enum(enum), self._module.enum_type_value(enum), self._module.enum_value(enum, enum.enumValues[0]), self._module.enum_accessor(enum, "GetMember"), self._module.enum_enum(enum), self._module.enum_type_value(enum))) # Action enumeration if self._module.actions: self._write_section("Method enumeration") self._write_enumeration(self._module.action_enum(), [ self._module.action_value(action_loc) for action_loc in self._module.action_locations() ]) # Action sentinels if self._bGenerateActions: self._write_section("Method sentinels") for action in self._module.actions: self._write('''\ #define %s ''' % (self._module.action_sentinel(action))) # Action declarations if self._bGenerateActions: self._write_section("Methods") for action in self._module.actions: self._write('''\ extern void %s(HDK_MOD_MethodContext* pMethodCtx, HDK_XML_Struct* pInput, HDK_XML_Struct* pOutput); ''' % (self._module.action_fn(action))) # Event enumeration if self._module.events: self._write_section("Event enumeration") self._write_enumeration(self._module.event_enum(), [ self._module.event_value(event) for event in self._module.events ]) # DOM (struct) schema accessor declarations if self._module.schema.structs: self._write_section("DOM Schemas") for struct in self._module.schema.structs: self._write('''\ %s const HDK_XML_Schema* %s(); ''' % (self._module.export_macro(), self._module.dom_schema_fn(struct))) # State declarations if self._module.states: self._write_section("ADI") self._write_enumeration(self._module.state_enum(), [ self._module.state_value(state) for state in self._module.states ], ix_start = 1) self._write_section("ADI sentinels") for state in self._module.states: # Determine get/set usages = {} for actionState in self._model.actionStates: if state.uri in actionState.stateMembers: stateMember = actionState.stateMembers[state.uri] if stateMember.isGet: usages["get"] = None if stateMember.isSet: usages["set"] = None for usage in sorted(usages.iterkeys()): self._write('''\ #define %s ''' % (self._module.state_value_sentinel(state, usage))) # Module declaration if self._bGenerateModule: self._write_section("Module") self._write('''\ %s const HDK_MOD_Module* %s(void); ''' % (self._module.export_macro(), self._module.module_fn())) if self._bGenerateModuleDynamic: self._write('''\ /* Dynamic server module export */ %s const HDK_MOD_Module* HDK_SRV_Module(void); ''' % (self._module.export_macro())) # File footer self._write_footer_h() # # *.c code generator # def _generate_c(self): # File header self._write_header_c() self._write('''\ #include "%s" #include <string.h> ''' % (self._module.filename('.h'))) # Namespace table self._write_section("Namespaces") self._write('''\ static const HDK_XML_Namespace s_namespaces[] = { ''') for namespace in self._module.schema.namespaces: self._write('''\ /* %d */ "%s", ''' % (self._module.schema.namespace_index(namespace), namespace)) self._write('''\ HDK_XML_Schema_NamespacesEnd }; ''') # Elements table self._write_section("Elements") self._write('''\ static const HDK_XML_ElementNode s_elements[] = { ''') for element in self._module.schema.elements: self._write('''\ /* %s = %d */ { %d, "%s" }, ''' % (self._module.element_value(element), self._module.schema.element_index(element), self._module.schema.namespace_index(element[0]), element[1])) self._write('''\ HDK_XML_Schema_ElementsEnd }; ''') # Enumerations definitions for enum in self._module.schema.enums: # Enumeration string table self._write_section("Enumeration %s" % (enum.uri)) self._write('''\ static const HDK_XML_EnumValue %s[] = { ''' % (self._module.enum_type_strings_static(enum))) for value in enum.enumValues: self._write('''\ "%s", ''' % (value)) self._write('''\ HDK_XML_Schema_EnumTypeValuesEnd }; ''') # Enum types array if self._module.schema.enums: self._write_section("Enumeration types array") self._write('''\ static const HDK_XML_EnumType s_enumTypes[] = { ''') sep = ',' for enum in self._module.schema.enums: if enum is self._module.schema.enums[-1]: sep = "" self._write('''\ %s%s ''' % (self._module.enum_type_strings_static(enum), sep)) self._write('''\ }; ''') # Action definitions for action in self._module.actions: self._write_section("Method %s" % (action.uri)) # Input schema self._write_schema(self._module.schema_nodes_static(action, suffix = "_Input"), self._module.schema_static(action, suffix = "_Input"), self._module.schema.struct_nodes(action.inputMember, soap = True), element_path_static = self._module.schema_element_path_static(action, suffix = "_Input"), element_path = self._module.schema.struct_nodes_envelope(action.inputMember, soap = True)) # Output schema self._write('''\ ''') self._write_schema(self._module.schema_nodes_static(action, suffix = "_Output"), self._module.schema_static(action, suffix = "_Output"), self._module.schema.struct_nodes(action.outputMember, soap = True), element_path_static = self._module.schema_element_path_static(action, suffix = "_Output"), element_path = self._module.schema.struct_nodes_envelope(action.outputMember, soap = True)) # Actions table if self._module.actions: self._write_section("Methods") # Actions table header self._write('''\ static const HDK_MOD_Method s_methods[] = { ''') # Write each action node for action_loc in self._module.action_locations(): self._write_action(action_loc) # Actions table footer self._write('''\ HDK_MOD_MethodsEnd }; ''') # Event definitions for event in self._module.events: self._write_section("Event %s" % (event.uri)) self._write_schema(self._module.schema_nodes_static(event), self._module.schema_static(event), self._module.schema.struct_nodes(event.member)) # Events table if self._module.events: self._write_section("Events") # Events table header self._write('''\ static const HDK_MOD_Event s_events[] = { ''') # Write each event node for event in self._module.events: self._write_event(event) # Events table footer self._write('''\ HDK_MOD_EventsEnd }; ''') if self._bGenerateServices: # Services action tables self._write_section("Service Methods") for service in self._module.services: # Service actions header self._write('''\ static const HDK_MOD_Method* %s[] = { ''' % (self._module.service_actions_name(service))) # Service actions for action_uri in service.actions: action_loc = [a for a in self._module.action_locations() if a.action.uri == action_uri][0] self._write('''\ &s_methods[%s], ''' % (self._module.action_value(action_loc))) # Service actions footer self._write('''\ 0 }; ''') # Services event tables self._write_section("Service Events") for service in self._module.services: # Service events header self._write('''\ static const HDK_MOD_Event* %s[] = { ''' % (self._module.service_events_name(service))) # Service events for eventURI in service.events: event = [e for e in self._module.events if e.uri == eventURI][0] self._write('''\ &s_events[%s], ''' % (self._module.event_value(event))) # Service events footer self._write('''\ 0 }; ''') # Services table self._write_section("Services") # Services table header self._write('''\ static const HDK_MOD_Service s_services[] = { ''') # Write each service node for service in self._module.services: self._write('''\ { "%s", %s, %s }, ''' % (service.uri, self._module.service_actions_name(service), self._module.service_events_name(service))) # Services table footer self._write('''\ HDK_MOD_ServicesEnd }; ''') # State definitions if self._module.states: self._write_section("ADI") self._write_schema("s_schemaNodes_ADI", "s_schema_ADI", self._module.schema.state_nodes()) # Struct schema definitions for struct in self._module.schema.structs: self._write_section("Struct %s" % (struct.uri)) self._write_schema(self._module.schema_nodes_static(struct), self._module.schema_static(struct), self._module.schema.struct_nodes(struct)) self._write('''\ /* extern */ const HDK_XML_Schema* %s() { return &%s; } ''' % (self._module.dom_schema_fn(struct), self._module.schema_static(struct))) # Module definition if self._bGenerateModule: self._write_section("Module"); # Network Object ID definition if self._noid is not None: self._write('''\ /* %s */ static const HDK_XML_UUID s_uuid_NOID = { { %s } }; ''' % (self._noid, ", ".join(["0x%02x" % ord(byte) for byte in self._noid.bytes]))) # Module definition and accessors self._write('''\ static const HDK_MOD_Module s_module = { %s, %s, %s, %s, %s, %s }; const HDK_MOD_Module* %s(void) { return &s_module; } ''' % ( "&s_uuid_NOID" if self._noid else "0", '"' + self._friendlyName + '"' if self._friendlyName else "0", "s_services" if self._bGenerateServices else "0", "s_methods" if self._module.actions else "0", "s_events" if self._module.events else "0", "&s_schema_ADI" if self._module.states else "0", self._module.module_fn() )) if self._bGenerateModuleDynamic: self._write('''\ const HDK_MOD_Module* HDK_SRV_Module(void) { return &s_module; } ''') # # *_methods.c code generator # def _generate_methods_c(self): # File header self._write_header_c() self._write('''\ #include "%s" #include "hdk_srv.h" /* Helper method for HNAP results */ #define SetHNAPResult(pStruct, prefix, method, result) \\ prefix##_Set_##method##Result(pStruct, prefix##_Element_##method##Result, prefix##_Enum_##method##Result_##result) ''' % (self._module.filename('.h'))) # Action declarations for action in self._module.actions: self._write_section("Method %s" % (action.uri)) self._write('''\ #ifdef %s void %s(HDK_MOD_MethodContext* pMethodCtx, HDK_XML_Struct* pInput, HDK_XML_Struct* pOutput) { /* Unused parameters */ (void)pMethodCtx; (void)pInput; (void)pOutput; } #endif /* %s */ ''' % (self._module.action_sentinel(action), self._module.action_fn(action), self._module.action_sentinel(action))) # # *_adi.txt report generator # def _generate_adi_txt(self): # ADI report title self._write('''\ ====================================================================== ADI Report for the %s Module ====================================================================== ''' % (self._baseName.upper())) # Output the ADI values used (show get/set) self._write('''\ ====================================================================== ADI values ====================================================================== ''') for state in self._model.referenced_states(): # Determine get/set usages = {} for actionState in self._model.actionStates: if state.uri in actionState.stateMembers: stateMember = actionState.stateMembers[state.uri] if stateMember.isGet: usages["get"] = None if stateMember.isSet: usages["set"] = None sUsages = ', '.join(sorted(usages.iterkeys())) # Get the base type type = state.type nArray = 0 while type.isArray: nArray += 1 type = type.arrayType sArray = "[]" * nArray # Get the type description sDesc = "" if type.isEnum: sDesc = "enum" elif type.isStruct: sDesc = "struct" # Get the type string if sDesc: sType = '%s%s (%s, "%s")' % (type.name, sArray, sDesc, type.namespace) else: sType = '%s%s' % (type.name, sArray) self._write('''\ %s Namespace: "%s" Name: "%s" Type: %s Usage: %s ''' % (self._module.state_value(state), state.namespace, state.name, sType, sUsages)) # Output the ADI values used by action self._write('''\ ====================================================================== ADI values by action ====================================================================== ''') for actionState in self._model.actionStates: self._write('''\ %s ''' % (actionState.uri)) for stateMember in sorted(actionState.stateMembers.itervalues()): # Determine usage usages = {} if stateMember.isGet: usages["get"] = None if stateMember.isSet: usages["set"] = None sUsages = ', '.join(sorted(usages.iterkeys())) self._write('''\ [%s] %s ''' % (sUsages, self._module.state_value(stateMember.state)))