# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- # # This program 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 of the License, or (at your option) any # later version. # # This program 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 program; if not, write to the Free Software Foundation, Inc., 51 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # Copyright (C) 2012 Lanedo GmbH # Copyright (C) 2012-2022 Aleksander Morgado # import string import re """ Add the common copyright header to the given file """ def add_copyright(f): f.write( "\n" "/* GENERATED CODE... DO NOT EDIT */\n" "\n" "/*\n" " * This library is free software; you can redistribute it and/or\n" " * modify it under the terms of the GNU Lesser General Public\n" " * License as published by the Free Software Foundation; either\n" " * version 2 of the License, or (at your option) any later version.\n" " *\n" " * This library is distributed in the hope that it will be useful,\n" " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" " * Lesser General Public License for more details.\n" " *\n" " * You should have received a copy of the GNU Lesser General Public\n" " * License along with this library; if not, write to the\n" " * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n" " * Boston, MA 02110-1301 USA.\n" " *\n" " * Copyright (C) 2012 Lanedo GmbH\n" " * Copyright (C) 2012-2022 Aleksander Morgado \n" " */\n" "\n"); """ Build a header guard string based on the given filename """ def build_header_guard(output_name): return "__LIBQMI_GLIB_" + output_name.replace('-', '_').upper() + "__" """ Write the common header start chunk """ def add_header_start(f, output_name, service): translations = { 'guard' : build_header_guard(output_name), 'service' : build_underscore_name(service) } template = ( "\n" "#include \n" "#include \n" "#include \n" "\n" "#include \"qmi-enums.h\"\n") # CTL, DPM, GMS, ATR and IMS don't have enums if service not in ('CTL', 'DPM', 'GMS', 'ATR', 'IMS'): template += ( "#include \"qmi-enums-${service}.h\"\n") if service == 'CTL': template += ( "#include \"qmi-enums-private.h\"\n") # DMS, NAS, LOC, DSD and WDS have flags64 if service in ('DMS', 'NAS', 'LOC', 'DSD', 'WDS'): template += ( "#include \"qmi-flags64-${service}.h\"\n") template += ( "#include \"qmi-message.h\"\n" "#include \"qmi-client.h\"\n" "\n" "#ifndef ${guard}\n" "#define ${guard}\n" "\n" "G_BEGIN_DECLS\n" "\n") f.write(string.Template(template).substitute(translations)) """ Write the common header stop chunk """ def add_header_stop(f, output_name): template = string.Template ( "\n" "G_END_DECLS\n" "\n" "#endif /* ${guard} */\n") f.write(template.substitute(guard = build_header_guard(output_name))) """ Write the common source file start chunk """ def add_source_start(f, output_name): template = string.Template ( "\n" "#include \n" "\n" "#include \"${name}.h\"\n" "#include \"qmi-enum-types.h\"\n" "#include \"qmi-flag-types.h\"\n" "#include \"qmi-enum-types-private.h\"\n" "#include \"qmi-flag-types-private.h\"\n" "#include \"qmi-flags64-types.h\"\n" "#include \"qmi-error-types.h\"\n" "#include \"qmi-device.h\"\n" "#include \"qmi-helpers.h\"\n" '\n' '#define QMI_STATUS_SUCCESS 0x0000\n' '#define QMI_STATUS_FAILURE 0x0001\n' "\n") f.write(template.substitute(name = output_name)) """ Write a separator comment in the file """ def add_separator(f, separator_type, separator_name): template = string.Template ( "\n" "/*****************************************************************************/\n" "/* ${type}: ${name} */\n" "\n") f.write(template.substitute(type = separator_type, name = separator_name)) """ Build an underscore name from the given full name e.g.: "This is a message" --> "this_is_a_message" """ def build_underscore_name(name): return name.replace(' ', '_').lower() """ Build an underscore uppercase name from the given full name e.g.: "This is a message" --> "THIS_IS_A_MESSAGE" """ def build_underscore_uppercase_name(name): return name.replace(' ', '_').upper() """ Build an underscore name from the given camelcase name e.g.: "ThisIsAMessage" --> "this_is_a_message" """ def build_underscore_name_from_camelcase(camelcase): s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camelcase) s2 = re.sub('(.)([0-9][a-z]+)', r'\1_\2', s1) return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s2).lower() """ Build a camelcase name from the given full name e.g.: "This is a message" --> "ThisIsAMessage" """ def build_camelcase_name(name): return string.capwords(name).replace(' ', '') """ 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 name.lower().replace(' ', '-') """ Remove the given prefix from the string """ def remove_prefix(line, prefix): return line[len(prefix):] if line.startswith(prefix) else line """ Read the contents of the JSON file, skipping lines prefixed with '//', which are considered comments. """ def read_json_file(path): f = open(path) out = '' for line in f.readlines(): stripped = line.strip() if stripped.startswith('//'): # Skip this line # We add an empty line instead so that errors when parsing the JSON # report the proper line number out += "\n" else: out += line return out """ Returns True if the given format corresponds to a basic unsigned integer type """ def format_is_unsigned_integer(fmt): if fmt == 'guint8' or \ fmt == 'guint16' or \ fmt == 'guint32' or \ fmt == 'guint64' or \ fmt == 'guint-sized' : return True else: return False """ Returns True if the given format corresponds to a basic signed integer type """ def format_is_signed_integer(fmt): if fmt == 'gint8' or \ fmt == 'gint16' or \ fmt == 'gint32' or \ fmt == 'gint64': return True else: return False """ Returns True if the given format corresponds to a basic floating point type """ def format_is_float(fmt): return fmt in ('gfloat', 'gdouble') """ Returns True if the given format corresponds to a basic signed or unsigned integer type """ def format_is_integer(fmt): if format_is_unsigned_integer(fmt) or \ format_is_signed_integer(fmt): return True else: return False """ Compare two version strings given in MAJOR.MINOR[.MICRO] format. Just to avoid needing to include e.g. packaging.version.parse just for this """ def version_compare(v1,v2): v1_split = v1.split(".") v2_split = v2.split(".") major_v1 = int(v1_split[0]) major_v2 = int(v2_split[0]) if major_v2 > major_v1: return 1 if major_v2 < major_v1: return -1 # major_v2 == major_v1 minor_v1 = int(v1_split[1]) minor_v2 = int(v2_split[1]) if minor_v2 > minor_v1: return 1 if minor_v2 < minor_v1: return -1 # minor_v2 == minor_v1 micro_v1 = int(v1_split[2]) if len(v1_split) > 2 else 0 micro_v2 = int(v2_split[2]) if len(v2_split) > 2 else 0 if micro_v2 > micro_v1: return 1 if micro_v2 < micro_v1: return -1 # micro_v2 == micro_v1 return 0