From 7b29353fdd93d062ff944785ef46fce4dd8d07c7 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 4 Sep 2024 13:18:18 +0200 Subject: qapi: Smarter camel_to_upper() to reduce need for 'prefix' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit camel_to_upper() converts its argument from camel case to upper case with '_' between words. Used for generated enumeration constant prefixes. When some of the words are spelled all caps, where exactly to insert '_' is guesswork. camel_to_upper()'s guesses are bad enough in places to make people override them with a 'prefix' in the schema. Rewrite it to guess better: 1. Insert '_' after a non-upper case character followed by an upper case character: OneTwo -> ONE_TWO One2Three -> ONE2_THREE 2. Insert '_' before the last upper case character followed by a non-upper case character: ACRONYMWord -> ACRONYM_Word Except at the beginning (as in OneTwo above), or when there is already one: AbCd -> AB_CD This changes the default enumeration constant prefix for a number of enums. Generated enumeration constants change only where the default is not overridden with 'prefix'. The following enumerations without a 'prefix' change: enum old camel_to_upper() new camel_to_upper() ------------------------------------------------------------------ DisplayGLMode DISPLAYGL_MODE DISPLAY_GL_MODE EbpfProgramID EBPF_PROGRAMID EBPF_PROGRAM_ID HmatLBDataType HMATLB_DATA_TYPE HMAT_LB_DATA_TYPE HmatLBMemoryHierarchy HMATLB_MEMORY_HIERARCHY HMAT_LB_MEMORY_HIERARCHY MultiFDCompression MULTIFD_COMPRESSION MULTI_FD_COMPRESSION OffAutoPCIBAR OFF_AUTOPCIBAR OFF_AUTO_PCIBAR QCryptoBlockFormat Q_CRYPTO_BLOCK_FORMAT QCRYPTO_BLOCK_FORMAT QCryptoBlockLUKSKeyslotState Q_CRYPTO_BLOCKLUKS_KEYSLOT_STATE QCRYPTO_BLOCK_LUKS_KEYSLOT_STATE QKeyCode Q_KEY_CODE QKEY_CODE XDbgBlockGraphNodeType X_DBG_BLOCK_GRAPH_NODE_TYPE XDBG_BLOCK_GRAPH_NODE_TYPE TestUnionEnumA TEST_UNION_ENUMA TEST_UNION_ENUM_A Add a 'prefix' so generated code doesn't change now. Subsequent commits will remove most of them again. Two will remain: MULTIFD_COMPRESSION, because migration code generally spells "multifd" that way, and Q_KEY_CODE, because that one is baked into subprojects/keycodemapdb/tools/keymap-gen. The following enumerations with a 'prefix' change so that the prefix is now superfluous: enum old camel_to_upper() new camel_to_upper() [equal to prefix] ------------------------------------------------------------------ BlkdebugIOType BLKDEBUGIO_TYPE BLKDEBUG_IO_TYPE QCryptoTLSCredsEndpoint Q_CRYPTOTLS_CREDS_ENDPOINT QCRYPTO_TLS_CREDS_ENDPOINT QCryptoSecretFormat Q_CRYPTO_SECRET_FORMAT QCRYPTO_SECRET_FORMAT QCryptoCipherMode Q_CRYPTO_CIPHER_MODE QCRYPTO_CIPHER_MODE QCryptodevBackendType Q_CRYPTODEV_BACKEND_TYPE QCRYPTODEV_BACKEND_TYPE QType [builtin] Q_TYPE QTYPE Drop these prefixes. The following enumerations with a 'prefix' change without making the 'prefix' superfluous: enum old camel_to_upper() new camel_to_upper() [equal to prefix] prefix ------------------------------------------------------------------ CpuS390Entitlement CPUS390_ENTITLEMENT CPU_S390_ENTITLEMENT S390_CPU_ENTITLEMENT CpuS390Polarization CPUS390_POLARIZATION CPU_S390_POLARIZATION S390_CPU_POLARIZATION CpuS390State CPUS390_STATE CPU_S390_STATE S390_CPU_STATE QAuthZListFormat Q_AUTHZ_LIST_FORMAT QAUTH_Z_LIST_FORMAT QAUTHZ_LIST_FORMAT QAuthZListPolicy Q_AUTHZ_LIST_POLICY QAUTH_Z_LIST_POLICY QAUTHZ_LIST_POLICY QCryptoAkCipherAlgorithm Q_CRYPTO_AK_CIPHER_ALGORITHM QCRYPTO_AK_CIPHER_ALGORITHM QCRYPTO_AKCIPHER_ALG QCryptoAkCipherKeyType Q_CRYPTO_AK_CIPHER_KEY_TYPE QCRYPTO_AK_CIPHER_KEY_TYPE QCRYPTO_AKCIPHER_KEY_TYPE QCryptoCipherAlgorithm Q_CRYPTO_CIPHER_ALGORITHM QCRYPTO_CIPHER_ALGORITHM QCRYPTO_CIPHER_ALG QCryptoHashAlgorithm Q_CRYPTO_HASH_ALGORITHM QCRYPTO_HASH_ALGORITHM QCRYPTO_HASH_ALG QCryptoIVGenAlgorithm Q_CRYPTOIV_GEN_ALGORITHM QCRYPTO_IV_GEN_ALGORITHM QCRYPTO_IVGEN_ALG QCryptoRSAPaddingAlgorithm Q_CRYPTORSA_PADDING_ALGORITHM QCRYPTO_RSA_PADDING_ALGORITHM QCRYPTO_RSA_PADDING_ALG QCryptodevBackendAlgType Q_CRYPTODEV_BACKEND_ALG_TYPE QCRYPTODEV_BACKEND_ALG_TYPE QCRYPTODEV_BACKEND_ALG QCryptodevBackendServiceType Q_CRYPTODEV_BACKEND_SERVICE_TYPE QCRYPTODEV_BACKEND_SERVICE_TYPE QCRYPTODEV_BACKEND_SERVICE Subsequent commits will tweak things to remove most of these prefixes. Only QAUTHZ_LIST_FORMAT and QAUTHZ_LIST_POLICY will remain. Signed-off-by: Markus Armbruster Reviewed-by: Daniel P. Berrangé Message-ID: <20240904111836.3273842-2-armbru@redhat.com> --- scripts/qapi/common.py | 44 +++++++++++++++++++++++++------------------- scripts/qapi/schema.py | 2 +- 2 files changed, 26 insertions(+), 20 deletions(-) (limited to 'scripts') diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 737b059e62..d7c8aa3365 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -40,22 +40,28 @@ def camel_to_upper(value: str) -> str: ENUM_Name2 -> ENUM_NAME2 ENUM24_Name -> ENUM24_NAME """ - c_fun_str = c_name(value, False) - if value.isupper(): - return c_fun_str - - new_name = '' - length = len(c_fun_str) - for i in range(length): - char = c_fun_str[i] - # When char is upper case and no '_' appears before, do more checks - if char.isupper() and (i > 0) and c_fun_str[i - 1] != '_': - if i < length - 1 and c_fun_str[i + 1].islower(): - new_name += '_' - elif c_fun_str[i - 1].isdigit(): - new_name += '_' - new_name += char - return new_name.lstrip('_').upper() + ret = value[0] + upc = value[0].isupper() + + # Copy remainder of ``value`` to ``ret`` with '_' inserted + for ch in value[1:]: + if ch.isupper() == upc: + pass + elif upc: + # ``ret`` ends in upper case, next char isn't: insert '_' + # before the last upper case char unless there is one + # already, or it's at the beginning + if len(ret) > 2 and ret[-2].isalnum(): + ret = ret[:-1] + '_' + ret[-1] + else: + # ``ret`` doesn't end in upper case, next char is: insert + # '_' before it + if ret[-1].isalnum(): + ret += '_' + ret += ch + upc = ch.isupper() + + return c_name(ret.upper()).lstrip('_') def c_enum_const(type_name: str, @@ -68,9 +74,9 @@ def c_enum_const(type_name: str, :param const_name: The name of this constant. :param prefix: Optional, prefix that overrides the type_name. """ - if prefix is not None: - type_name = prefix - return camel_to_upper(type_name) + '_' + c_name(const_name, False).upper() + if prefix is None: + prefix = camel_to_upper(type_name) + return prefix + '_' + c_name(const_name, False).upper() def c_name(name: str, protect: bool = True) -> str: diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index d65c35f6ee..e97c978d38 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -1249,7 +1249,7 @@ class QAPISchema: [{'name': n} for n in qtypes], None) self._def_definition(QAPISchemaEnumType( - 'QType', None, None, None, None, qtype_values, 'QTYPE')) + 'QType', None, None, None, None, qtype_values, None)) def _make_features( self, -- cgit v1.2.3