diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-07-05 17:17:58 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-07-23 12:51:47 +0200 |
commit | af6d4526b1e990a3b64c9c4d8a2905b67a1a8399 (patch) | |
tree | 2e90db87d5486b3943e9abf968fb287fa9ad3aeb /build-aux | |
parent | 5ad07e7bc714dcb66b74deed610a3b61729f7839 (diff) |
qmi-codegen: convert indication messages received into `QmiClient' signals
Diffstat (limited to 'build-aux')
-rw-r--r-- | build-aux/qmi-codegen/Client.py | 110 | ||||
-rw-r--r-- | build-aux/qmi-codegen/Message.py | 84 | ||||
-rw-r--r-- | build-aux/qmi-codegen/MessageList.py | 105 | ||||
-rw-r--r-- | build-aux/qmi-codegen/utils.py | 8 |
4 files changed, 239 insertions, 68 deletions
diff --git a/build-aux/qmi-codegen/Client.py b/build-aux/qmi-codegen/Client.py index 32f5cb4..73674f6 100644 --- a/build-aux/qmi-codegen/Client.py +++ b/build-aux/qmi-codegen/Client.py @@ -48,7 +48,15 @@ class Client: """ Emits the generic GObject class implementation """ - def __emit_class(self, hfile, cfile): + def __emit_class(self, hfile, cfile, message_list): + + # Check if we'll have indications + has_indications = False + for message in message_list.list: + if message.type == 'Indication': + has_indications = True + break + translations = { 'underscore' : utils.build_underscore_name(self.name), 'no_prefix_underscore_upper' : string.upper(utils.build_underscore_name(self.name[4:])), 'camelcase' : utils.build_camelcase_name (self.name) } @@ -81,7 +89,66 @@ class Client: # Emit class source template = ( '\n' - 'G_DEFINE_TYPE (${camelcase}, ${underscore}, QMI_TYPE_CLIENT);\n' + 'G_DEFINE_TYPE (${camelcase}, ${underscore}, QMI_TYPE_CLIENT);\n') + + if has_indications: + template += ( + '\n' + 'enum {\n') + for message in message_list.list: + if message.type == 'Indication': + translations['signal_id'] = utils.build_underscore_uppercase_name(message.name) + inner_template = ( + ' SIGNAL_${signal_id},\n') + template += string.Template(inner_template).substitute(translations) + template += ( + ' SIGNAL_LAST\n' + '};\n' + '\n' + 'static guint signals[SIGNAL_LAST] = { 0 };\n') + + template += ( + '\n' + 'static void\n' + 'process_indication (QmiClient *self,\n' + ' QmiMessage *message)\n' + '{\n' + ' switch (qmi_message_get_message_id (message)) {\n') + + for message in message_list.list: + if message.type == 'Indication': + translations['enum_name'] = message.id_enum_name + translations['message_fullname_underscore'] = utils.build_underscore_name(message.fullname) + translations['message_name'] = message.name + translations['output_camelcase'] = utils.build_camelcase_name(message.output.fullname) + translations['output_underscore'] = utils.build_underscore_name(message.output.fullname) + translations['output_underscore'] = utils.build_underscore_name(message.output.fullname) + translations['signal_id'] = utils.build_underscore_uppercase_name(message.name) + inner_template = ( + ' case ${enum_name}: {\n' + ' ${output_camelcase} *output;\n' + ' GError *error = NULL;\n' + '\n' + ' /* Parse indication */\n' + ' output = ${message_fullname_underscore}_indication_parse (message, &error);\n' + ' if (!output) {\n' + ' g_warning ("Couldn\'t parse \'${message_name}\' indication: %s",\n' + ' error ? error->message : "Unknown error");\n' + ' if (error)\n' + ' g_error_free (error);\n' + ' } else {\n' + ' g_signal_emit (self, signals[SIGNAL_${signal_id}], 0, output);\n' + ' ${output_underscore}_unref (output);\n' + ' }\n' + ' break;\n' + ' }\n') + template += string.Template(inner_template).substitute(translations) + + template += ( + ' default:\n' + ' break;\n' + ' }\n' + '}\n' '\n' 'static void\n' '${underscore}_init (${camelcase} *self)\n' @@ -91,6 +158,39 @@ class Client: 'static void\n' '${underscore}_class_init (${camelcase}Class *klass)\n' '{\n' + ' QmiClientClass *client_class = QMI_CLIENT_CLASS (klass);\n' + '\n' + ' client_class->process_indication = process_indication;\n') + + for message in message_list.list: + if message.type == 'Indication': + translations['output_camelcase'] = utils.build_camelcase_name(message.output.fullname) + translations['signal_name'] = utils.build_dashed_name(message.name) + translations['signal_id'] = utils.build_underscore_uppercase_name(message.name) + translations['bundle_type'] = 'QMI_TYPE_' + utils.remove_prefix(utils.build_underscore_uppercase_name(message.output.fullname), 'QMI_') + inner_template = ( + '\n' + ' /**\n' + ' * ${camelcase}::${signal_name}:\n' + ' * @object: A #${camelcase}.\n' + ' * @output: A #${output_camelcase}.\n' + ' *\n' + ' * The ::${signal_name} signal gets emitted when a \'${message_name}\' indication is received.\n' + ' */\n' + ' signals[SIGNAL_${signal_id}] =\n' + ' g_signal_new ("${signal_name}",\n' + ' G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)),\n' + ' G_SIGNAL_RUN_LAST,\n' + ' 0,\n' + ' NULL,\n' + ' NULL,\n' + ' NULL,\n' + ' G_TYPE_NONE,\n' + ' 1,\n' + ' ${bundle_type});\n') + template += string.Template(inner_template).substitute(translations) + + template += ( '}\n' '\n') cfile.write(string.Template(template).substitute(translations)) @@ -104,6 +204,10 @@ class Client: 'camelcase' : utils.build_camelcase_name (self.name) } for message in message_list.list: + + if message.type == 'Indication': + continue + translations['message_underscore'] = utils.build_underscore_name(message.name) translations['message_fullname_underscore'] = utils.build_underscore_name(message.fullname) translations['input_camelcase'] = utils.build_camelcase_name(message.input.fullname) @@ -227,5 +331,5 @@ class Client: # First, emit common class code utils.add_separator(hfile, 'CLIENT', self.name); utils.add_separator(cfile, 'CLIENT', self.name); - self.__emit_class(hfile, cfile) + self.__emit_class(hfile, cfile, message_list) self.__emit_methods(hfile, cfile, message_list) diff --git a/build-aux/qmi-codegen/Message.py b/build-aux/qmi-codegen/Message.py index bb562aa..a187193 100644 --- a/build-aux/qmi-codegen/Message.py +++ b/build-aux/qmi-codegen/Message.py @@ -32,19 +32,20 @@ class Message: Constructor """ def __init__(self, dictionary, common_objects_dictionary): - # The message prefix - self.prefix = 'Qmi Message' # The message service, e.g. "Ctl" self.service = dictionary['service'] # The name of the specific message, e.g. "Something" self.name = dictionary['name'] # The specific message ID self.id = dictionary['id'] - # The type, which must always be 'Message' + # The type, which must always be 'Message' or 'Indication' self.type = dictionary['type'] # The version info, optional self.version_info = dictionary['version'].split('.') if 'version' in dictionary else [] + # The message prefix + self.prefix = 'Qmi ' + self.type + # Create the composed full name (prefix + service + name), # e.g. "Qmi Message Ctl Something Output Result" self.fullname = self.prefix + ' ' + self.service + ' ' + self.name @@ -55,20 +56,22 @@ class Message: # Build output container. # Every defined message will have its own output container, which # will generate a new Output type and public getters for each output - # field + # field. This applies to both Request/Response and Indications. self.output = Container(self.fullname, 'Output', dictionary['output'], common_objects_dictionary) - # Build input container. - # Every defined message will have its own input container, which - # will generate a new Input type and public getters for each input - # field - self.input = Container(self.fullname, - 'Input', - dictionary['input'] if 'input' in dictionary else None, - common_objects_dictionary) + self.input = None + if self.type == 'Message': + # Build input container (Request/Response only). + # Every defined message will have its own input container, which + # will generate a new Input type and public getters for each input + # field + self.input = Container(self.fullname, + 'Input', + dictionary['input'] if 'input' in dictionary else None, + common_objects_dictionary) """ @@ -176,10 +179,11 @@ class Message: """ - Emit method responsible for parsing a response of the given type + Emit method responsible for parsing a response/indication of the given type """ - def __emit_response_parser(self, hfile, cfile): + def __emit_response_or_indication_parser(self, hfile, cfile): translations = { 'name' : self.name, + 'type' : 'response' if self.type == 'Message' else 'indication', 'container' : utils.build_camelcase_name (self.output.fullname), 'container_underscore' : utils.build_underscore_name (self.output.fullname), 'underscore' : utils.build_underscore_name (self.fullname), @@ -187,7 +191,7 @@ class Message: template = ( '\n' - '${container} *${underscore}_response_parse (\n' + '${container} *${underscore}_${type}_parse (\n' ' QmiMessage *message,\n' ' GError **error);\n') hfile.write(string.Template(template).substitute(translations)) @@ -195,16 +199,16 @@ class Message: template = ( '\n' '/**\n' - ' * ${underscore}_response_parse:\n' - ' * @message: a #QmiMessage response.\n' + ' * ${underscore}_${type}_parse:\n' + ' * @message: a #QmiMessage ${type}.\n' ' * @error: a #GError.\n' ' *\n' - ' * Parse the \'${name}\' response.\n' + ' * Parse the \'${name}\' ${type}.\n' ' *\n' ' * Returns: a #${container} which should be disposed with ${container_underscore}_unref(), or #NULL if @error is set.\n' ' */\n' '${container} *\n' - '${underscore}_response_parse (\n' + '${underscore}_${type}_parse (\n' ' QmiMessage *message,\n' ' GError **error)\n' '{\n' @@ -242,7 +246,7 @@ class Message: """ def __emit_get_printable(self, hfile, cfile): - if self.input.fields is not None: + if self.input is not None and self.input.fields is not None: for field in self.input.fields: field.emit_tlv_get_printable(cfile) for field in self.output.fields: @@ -251,22 +255,23 @@ class Message: translations = { 'name' : self.name, 'service' : self.service, 'id' : self.id, - 'underscore' : utils.build_underscore_name (self.name) } + 'type' : utils.build_underscore_name(self.type), + 'underscore' : utils.build_underscore_name(self.name) } template = ( '\n' - 'struct ${underscore}_context {\n' + 'struct ${type}_${underscore}_context {\n' ' QmiMessage *self;\n' ' const gchar *line_prefix;\n' ' GString *printable;\n' '};\n' '\n' 'static void\n' - '${underscore}_get_tlv_printable (\n' + '${type}_${underscore}_get_tlv_printable (\n' ' guint8 type,\n' ' gsize length,\n' ' gconstpointer value,\n' - ' struct ${underscore}_context *ctx)\n' + ' struct ${type}_${underscore}_context *ctx)\n' '{\n' ' const gchar *tlv_type_str = NULL;\n' ' gchar *translated_value;\n' @@ -274,7 +279,7 @@ class Message: ' if (!qmi_message_is_response (ctx->self)) {\n' ' switch (type) {\n') - if self.input.fields is not None: + if self.input is not None and self.input.fields is not None: for field in self.input.fields: translations['underscore_field'] = utils.build_underscore_name(field.fullname) translations['field_enum'] = field.id_enum_name @@ -345,11 +350,11 @@ class Message: '}\n' '\n' 'static gchar *\n' - '${underscore}_get_printable (\n' + '${type}_${underscore}_get_printable (\n' ' QmiMessage *self,\n' ' const gchar *line_prefix)\n' '{\n' - ' struct ${underscore}_context ctx;\n' + ' struct ${type}_${underscore}_context ctx;\n' ' GString *printable;\n' '\n' ' printable = g_string_new ("");\n' @@ -361,7 +366,7 @@ class Message: ' ctx.line_prefix = line_prefix;\n' ' ctx.printable = printable;\n' ' qmi_message_tlv_foreach (self,\n' - ' (QmiMessageForeachTlvFn)${underscore}_get_tlv_printable,\n' + ' (QmiMessageForeachTlvFn)${type}_${underscore}_get_tlv_printable,\n' ' &ctx);\n' '\n' ' return g_string_free (printable, FALSE);\n' @@ -370,21 +375,26 @@ class Message: """ - Emit request/response handling implementation + Emit request/response/indication handling implementation """ def emit(self, hfile, cfile): - utils.add_separator(hfile, 'REQUEST/RESPONSE', self.fullname); - utils.add_separator(cfile, 'REQUEST/RESPONSE', self.fullname); - - hfile.write('\n/* --- Input -- */\n'); - cfile.write('\n/* --- Input -- */\n'); - self.input.emit(hfile, cfile) - self.__emit_request_creator(hfile, cfile) + if self.type == 'Message': + utils.add_separator(hfile, 'REQUEST/RESPONSE', self.fullname); + utils.add_separator(cfile, 'REQUEST/RESPONSE', self.fullname); + else: + utils.add_separator(hfile, 'INDICATION', self.fullname); + utils.add_separator(cfile, 'INDICATION', self.fullname); + + if self.type == 'Message': + hfile.write('\n/* --- Input -- */\n'); + cfile.write('\n/* --- Input -- */\n'); + self.input.emit(hfile, cfile) + self.__emit_request_creator(hfile, cfile) hfile.write('\n/* --- Output -- */\n'); cfile.write('\n/* --- Output -- */\n'); self.output.emit(hfile, cfile) - self.__emit_response_parser(hfile, cfile) + self.__emit_response_or_indication_parser(hfile, cfile) hfile.write('\n/* --- Printable -- */\n'); cfile.write('\n/* --- Printable -- */\n'); diff --git a/build-aux/qmi-codegen/MessageList.py b/build-aux/qmi-codegen/MessageList.py index a610a31..9cd057c 100644 --- a/build-aux/qmi-codegen/MessageList.py +++ b/build-aux/qmi-codegen/MessageList.py @@ -35,16 +35,20 @@ class MessageList: def __init__(self, objects_dictionary, common_objects_dictionary): self.list = [] self.message_id_enum_name = None + self.indication_id_enum_name = None self.service = None # Loop items in the list, creating Message objects for the messages # and looking for the special 'Message-ID-Enum' type for object_dictionary in objects_dictionary: - if object_dictionary['type'] == 'Message': + if object_dictionary['type'] == 'Message' or \ + object_dictionary['type'] == 'Indication': message = Message(object_dictionary, common_objects_dictionary) self.list.append(message) elif object_dictionary['type'] == 'Message-ID-Enum': self.message_id_enum_name = object_dictionary['name'] + elif object_dictionary['type'] == 'Indication-ID-Enum': + self.indication_id_enum_name = object_dictionary['name'] elif object_dictionary['type'] == 'Service': self.service = object_dictionary['name'] @@ -66,11 +70,33 @@ class MessageList: '\n' 'typedef enum {\n') for message in self.list: - translations['enum_name'] = message.id_enum_name - translations['enum_value'] = message.id - enum_template = ( - ' ${enum_name} = ${enum_value},\n') - template += string.Template(enum_template).substitute(translations) + if message.type == 'Message': + translations['enum_name'] = message.id_enum_name + translations['enum_value'] = message.id + enum_template = ( + ' ${enum_name} = ${enum_value},\n') + template += string.Template(enum_template).substitute(translations) + + template += ( + '} ${enum_type};\n' + '\n') + f.write(string.Template(template).substitute(translations)) + + """ + Emit the enumeration of the indications found in the specific service + """ + def emit_indication_ids_enum(self, f): + translations = { 'enum_type' : utils.build_camelcase_name (self.indication_id_enum_name) } + template = ( + '\n' + 'typedef enum {\n') + for message in self.list: + if message.type == 'Indication': + translations['enum_name'] = message.id_enum_name + translations['enum_value'] = message.id + enum_template = ( + ' ${enum_name} = ${enum_value},\n') + template += string.Template(enum_template).substitute(translations) template += ( '} ${enum_type};\n' @@ -99,20 +125,40 @@ class MessageList: ' QmiMessage *self,\n' ' const gchar *line_prefix)\n' '{\n' - ' switch (qmi_message_get_message_id (self)) {\n') + ' if (qmi_message_is_indication (self)) {\n' + ' switch (qmi_message_get_message_id (self)) {\n') for message in self.list: - translations['enum_name'] = message.id_enum_name - translations['message_underscore'] = utils.build_underscore_name (message.name) - translations['enum_value'] = message.id - inner_template = ( - ' case ${enum_name}:\n' - ' return ${message_underscore}_get_printable (self, line_prefix);\n') - template += string.Template(inner_template).substitute(translations) + if message.type == 'Indication': + translations['enum_name'] = message.id_enum_name + translations['message_underscore'] = utils.build_underscore_name (message.name) + translations['enum_value'] = message.id + inner_template = ( + ' case ${enum_name}:\n' + ' return indication_${message_underscore}_get_printable (self, line_prefix);\n') + template += string.Template(inner_template).substitute(translations) template += ( - ' default:\n' - ' return NULL;\n' + ' default:\n' + ' return NULL;\n' + ' }\n' + ' } else {\n' + ' switch (qmi_message_get_message_id (self)) {\n') + + for message in self.list: + if message.type == 'Message': + translations['enum_name'] = message.id_enum_name + translations['message_underscore'] = utils.build_underscore_name (message.name) + translations['enum_value'] = message.id + inner_template = ( + ' case ${enum_name}:\n' + ' return message_${message_underscore}_get_printable (self, line_prefix);\n') + template += string.Template(inner_template).substitute(translations) + + template += ( + ' default:\n' + ' return NULL;\n' + ' }\n' ' }\n' '}\n') cfile.write(string.Template(template).substitute(translations)) @@ -144,17 +190,18 @@ class MessageList: ' switch (qmi_message_get_message_id (self)) {\n') for message in self.list: - # Only add if we know the version info - if message.version_info != []: - translations['enum_name'] = message.id_enum_name - translations['message_major'] = message.version_info[0] - translations['message_minor'] = message.version_info[1] - inner_template = ( - ' case ${enum_name}:\n' - ' *major = ${message_major};\n' - ' *minor = ${message_minor};\n' - ' return TRUE;\n') - template += string.Template(inner_template).substitute(translations) + if message.type == 'Message': + # Only add if we know the version info + if message.version_info != []: + translations['enum_name'] = message.id_enum_name + translations['message_major'] = message.version_info[0] + translations['message_minor'] = message.version_info[1] + inner_template = ( + ' case ${enum_name}:\n' + ' *major = ${message_major};\n' + ' *minor = ${message_minor};\n' + ' return TRUE;\n') + template += string.Template(inner_template).substitute(translations) template += ( ' default:\n' @@ -168,8 +215,10 @@ class MessageList: Emit the message list handling implementation """ def emit(self, hfile, cfile): - # First, emit the message IDs enum + # First, emit the message/indication IDs enum self.emit_message_ids_enum(cfile) + if self.indication_id_enum_name is not None: + self.emit_indication_ids_enum(cfile) # Then, emit all message handlers for message in self.list: diff --git a/build-aux/qmi-codegen/utils.py b/build-aux/qmi-codegen/utils.py index 1969d4a..ebea84b 100644 --- a/build-aux/qmi-codegen/utils.py +++ b/build-aux/qmi-codegen/utils.py @@ -157,6 +157,14 @@ def build_camelcase_name(name): """ +Build a dashed lowercase name from the given full name +e.g.: "This is a message" --> "this-is-a-message" +""" +def build_dashed_name(name): + return string.replace(string.lower(name), ' ', '-') + + +""" Remove the given prefix from the string """ def remove_prefix(line, prefix): |