add named group debug helper

Signed-off-by: Jerry Yu <jerry.h.yu@arm.com>
diff --git a/scripts/generate_ssl_debug_helpers.py b/scripts/generate_ssl_debug_helpers.py
index 42e4fc8..86a54ea 100755
--- a/scripts/generate_ssl_debug_helpers.py
+++ b/scripts/generate_ssl_debug_helpers.py
@@ -234,6 +234,7 @@
                            prototype=self._prototype)
         return body
 
+
 class SignatureAlgorithmDefinition:
     """
         Generate helper functions for signature algorithms.
@@ -267,6 +268,7 @@
 
     def span(self):
         return self._definitions[0].span()
+
     def __str__(self):
         """
             Generate function for translating value to string
@@ -277,7 +279,7 @@
             translation_table.append(
                 '\tcase {}:\n\t    return "{}";'.format(name,
                                                         name[len('MBEDTLS_TLS1_3_SIG_'):].lower())
-                )
+            )
 
         body = textwrap.dedent('''\
             const char *mbedtls_ssl_sig_alg_to_str( uint16_t in )
@@ -292,6 +294,65 @@
         body = body.format(translation_table='\n'.join(translation_table))
         return body
 
+
+class NamedGroupDefinition:
+    """
+        Generate helper functions for named group
+
+        It generates translation function from named group define to string.
+        Signature algorithm definition looks like:
+        #define MBEDTLS_SSL_IANA_TLS_GROUP_[ upper case named group ] [ value(hex) ]
+
+        Known limitation:
+        - the definitions SHOULD  exist in same macro blocks.
+    """
+
+    @classmethod
+    def extract(cls, source_code, start=0, end=-1):
+        sig_alg_pattern = re.compile(r'#define\s+(?P<name>MBEDTLS_SSL_IANA_TLS_GROUP_\w+)\s+' +
+                                     r'(?P<value>0[xX][0-9a-fA-F]+)$',
+                                     re.MULTILINE | re.DOTALL)
+        matches = list(sig_alg_pattern.finditer(source_code, start, end))
+        if matches:
+            yield NamedGroupDefinition(source_code, definitions=matches)
+
+    def __init__(self, source_code, definitions=None):
+        if definitions is None:
+            definitions = []
+        assert isinstance(definitions, list) and definitions
+        self._definitions = definitions
+        self._source = source_code
+
+    def __repr__(self):
+        return 'NamedGroup({})'.format(self._definitions[0].span())
+
+    def span(self):
+        return self._definitions[0].span()
+
+    def __str__(self):
+        """
+            Generate function for translating value to string
+        """
+        translation_table = []
+        for m in self._definitions:
+            name = m.groupdict()['name']
+            iana_name = name[len('MBEDTLS_SSL_IANA_TLS_GROUP_'):].lower()
+            translation_table.append('\tcase {}:\n\t    return "{}";'.format(name, iana_name))
+
+        body = textwrap.dedent('''\
+            const char *mbedtls_ssl_named_group_to_str( uint16_t in )
+            {{
+                switch( in )
+                {{
+            {translation_table}
+                }};
+
+                return "UNKOWN";
+            }}''')
+        body = body.format(translation_table='\n'.join(translation_table))
+        return body
+
+
 OUTPUT_C_TEMPLATE = '''\
 /* Automatically generated by generate_ssl_debug_helpers.py. DO NOT EDIT. */
 
@@ -335,14 +396,16 @@
     """
         Generate functions of debug helps
     """
-    mbedtls_root = os.path.abspath(mbedtls_root or build_tree.guess_mbedtls_root())
+    mbedtls_root = os.path.abspath(
+        mbedtls_root or build_tree.guess_mbedtls_root())
     with open(os.path.join(mbedtls_root, 'include/mbedtls/ssl.h')) as f:
         source_code = remove_c_comments(f.read())
 
     definitions = dict()
     for start, instance in preprocess_c_source_code(source_code,
                                                     EnumDefinition,
-                                                    SignatureAlgorithmDefinition):
+                                                    SignatureAlgorithmDefinition,
+                                                    NamedGroupDefinition):
         if start in definitions:
             continue
         if isinstance(instance, EnumDefinition):