diff options
Diffstat (limited to '')
-rwxr-xr-x | tools/update-settings-tests | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/tools/update-settings-tests b/tools/update-settings-tests new file mode 100755 index 0000000..bd8e439 --- /dev/null +++ b/tools/update-settings-tests @@ -0,0 +1,349 @@ +#!/usr/bin/env python3 +import os +import sys + +def get_values(entry_dict, entry_type): + values = [] + if '*' == entry_type: + for key in list(entry_dict.keys()): + if entry_type in key: + values += entry_dict[key] + entry_dict.pop(key, None) + elif entry_type in dict(entry_dict): + values = entry_dict[entry_type] + entry_dict.pop(entry_type, None) + if values: + return sorted(values) + return values + +def write_entry(f, entry_dict, entry_type, entry_name): + values = get_values(entry_dict, entry_type) + if not values: + return + + f.write('#define have_' + entry_name.lower() + '_list_indices\n') + f.write('static const size_t ' + entry_name.lower() + '_list_indices[] =\n') + f.write('{\n') + + for val in values: + f.write('\tFreeRDP_' + val + ',\n') + + f.write('};\n\n') + +def write_str_case(f, entry_idx, val): + entry_types = ['BOOL', 'UINT16', 'INT16', 'UINT32', 'INT32', 'UINT64', 'INT64', 'STRING', 'POINTER'] + f.write('\t\t{FreeRDP_' + val + ', FREERDP_SETTINGS_TYPE_' + str(entry_types[entry_idx]) + ', "FreeRDP_' + val + '"},\n') + +def write_str(f, entry_dict): + f.write('typedef enum {\n') + f.write('\tFREERDP_SETTINGS_TYPE_BOOL,\n') + f.write('\tFREERDP_SETTINGS_TYPE_UINT16,\n') + f.write('\tFREERDP_SETTINGS_TYPE_INT16,\n') + f.write('\tFREERDP_SETTINGS_TYPE_UINT32,\n') + f.write('\tFREERDP_SETTINGS_TYPE_INT32,\n') + f.write('\tFREERDP_SETTINGS_TYPE_UINT64,\n') + f.write('\tFREERDP_SETTINGS_TYPE_INT64,\n') + f.write('\tFREERDP_SETTINGS_TYPE_STRING,\n') + f.write('\tFREERDP_SETTINGS_TYPE_POINTER\n') + f.write('} FREERDP_SETTINGS_TYPE;\n') + f.write('\n') + f.write('struct settings_str_entry {\n') + f.write('\tSSIZE_T id;\n') + f.write('\tSSIZE_T type;\n') + f.write('\tconst char* str;\n') + f.write('};\n') + f.write('static const struct settings_str_entry settings_map[] =\n') + f.write('{\n') + + entry_types = ['BOOL', 'UINT16', 'INT16', 'UINT32', 'INT32', 'UINT64', 'INT64', 'char*', '*'] + for entry_type in entry_types: + values = get_values(entry_dict, entry_type) + if values: + for val in values: + write_str_case(f, entry_types.index(entry_type), val) + f.write('};\n\n') + f.write('\n') + +def write_getter_case(f, val): + f.write('\t\tcase FreeRDP_' + val + ':\n') + f.write('\t\t\treturn settings->' + val + ';\n\n') + +def write_getter_body(f, values, ret): + f.write('{\n') + f.write('\tWINPR_ASSERT(settings);\n\n') + f.write('\tswitch (id)\n') + f.write('\t{\n') + if values: + for val in values: + write_getter_case(f, val) + f.write('\t\tdefault:\n') + f.write('\t\t\tWLog_ERR(TAG, "Invalid key index %" PRIuz " [%s|%s]", id, freerdp_settings_get_name_for_key(id), freerdp_settings_get_type_name_for_key(id));\n') + f.write('\t\t\tWINPR_ASSERT(FALSE);\n') + f.write('\t\t\treturn ' + ret + ';\n') + f.write('\t}\n') + f.write('}\n\n') + +def write_getter(f, entry_dict, entry_type, entry_name, postfix): + isString = 'string' in entry_name + isPointer = 'pointer' in entry_name + values = get_values(entry_dict, entry_type) + + typestr = 'FreeRDP_Settings_Keys_' + entry_name.capitalize() + typestr = typestr.replace('_Uint', '_UInt') + + if isPointer: + f.write('void*') + elif isString: + f.write('const ' + entry_type) + else: + f.write(entry_type) + + if isPointer: + f.write(' freerdp_settings_get_pointer_writable(rdpSettings* settings, ' + typestr + ' id)\n') + else: + f.write(' freerdp_settings_get_' + entry_name.lower() + '(const rdpSettings* settings, ' + typestr + ' id)\n') + if isString or isPointer: + ret = 'NULL'; + elif 'bool' in entry_name: + ret = 'FALSE'; + else: + ret = '0'; + + write_getter_body(f, values, ret) + + if isString: + f.write('char* freerdp_settings_get_' + entry_name.lower() + '_writable(rdpSettings* settings, ' + typestr + ' id)\n') + write_getter_body(f, values, ret) + +def write_setter_case(f, val, postfix, isPointer): + f.write('\t\tcase FreeRDP_' + val + ':\n') + if isPointer: + f.write('\t\t\tsettings->' + val + ' = cnv.v;\n') + f.write('\t\t\tbreak;\n\n') + elif not postfix: + f.write('\t\t\tsettings->' + val + ' = cnv.c;\n') + f.write('\t\t\tbreak;\n\n') + elif len(postfix) <= 1: + f.write('\t\t\treturn update_string' + postfix + '(&settings->' + val + ', cnv.c, len);\n\n') + else: + f.write('\t\t\treturn update_string' + postfix + '(&settings->' + val + ', cnv.cc, len, cleanup);\n\n') + +def write_setter(f, entry_dict, entry_type, entry_name, postfix): + isString = 'string' in entry_name + isPointer = 'pointer' in entry_name + values = get_values(entry_dict, entry_type) + + typestr = 'FreeRDP_Settings_Keys_' + entry_name.capitalize() + typestr = typestr.replace('_Uint', '_UInt') + f.write('BOOL freerdp_settings_set_' + entry_name.lower()) + f.write(postfix) + f.write('(rdpSettings* settings, ' + typestr + ' id, ') + if isString and len(postfix) > 1 or isPointer: + f.write('const ') + if not isPointer: + f.write(entry_type + ' val') + else: + f.write('void* val') + if isString and len(postfix) <= 1: + f.write(', size_t len)\n') + elif isString: + f.write(', size_t len, BOOL cleanup)\n') + else: + f.write(')\n') + f.write('{\n') + f.write('\tunion\n') + f.write('\t{\n') + f.write('\t\tvoid* v;\n') + f.write('\t\tconst void* cv;\n') + if not isPointer: + f.write(' ' + entry_type + ' c;\n') + f.write(' const ' + entry_type + ' cc;\n') + f.write('} cnv;\n') + + f.write('\tWINPR_ASSERT(settings);\n\n') + if isPointer: + f.write('\tcnv.cv = val;\n\n') + elif isString: + f.write('\tcnv.cc = val;\n\n') + else: + f.write('\tcnv.c = val;\n\n') + f.write('\tswitch (id)\n') + f.write('\t{\n') + if values: + for val in values: + write_setter_case(f, val, postfix, isPointer) + f.write('\t\tdefault:\n') + f.write('\t\t\tWLog_ERR(TAG, "Invalid key index %" PRIuz " [%s|%s]", id, freerdp_settings_get_name_for_key(id), freerdp_settings_get_type_name_for_key(id));\n') + f.write('\t\t\treturn FALSE;\n') + f.write('\t}\n') + f.write('\treturn TRUE;\n') + f.write('}\n\n') + f.write('\n') + if isString and len(postfix) <= 1: + f.write('BOOL freerdp_settings_set_string_len(rdpSettings* settings, FreeRDP_Settings_Keys_String id, const char* val, size_t len)\n') + f.write('{\n') + f.write('\treturn freerdp_settings_set_string_copy_(settings, id, val, len, TRUE);\n') + f.write('}\n') + f.write('\n') + + f.write('BOOL freerdp_settings_set_string(rdpSettings* settings, FreeRDP_Settings_Keys_String id, const char* val)\n') + f.write('{\n') + f.write('\tsize_t len = 0;\n') + f.write('\tif (val) len = strlen(val);\n') + f.write('\treturn freerdp_settings_set_string_copy_(settings, id, val, len, TRUE);\n') + f.write('}\n') + f.write('\n') + +name = os.path.dirname(os.path.realpath(__file__)) +begin = "WARNING: this data structure is carefully padded for ABI stability!" +end = "WARNING: End of ABI stable zone!" + +print('begin parsing settings header') +try: + type_list = dict() + + with open(name + "/../include/freerdp/settings_types_private.h", "r") as f: + lines = f.readlines() + started = False + for line in lines: + if not started: + if begin in line: + started = True + continue + + if end in line: + break + + sline = line.strip() + if not sline: + continue + if sline.startswith('/'): + continue + if sline.startswith('*'): + continue + if 'padding' in sline: + continue + + if sline.startswith('SETTINGS_DEPRECATED(ALIGN64'): + sline = sline[27:].strip() + + sline = sline[:sline.find(');')] + pair = sline.split() + if pair[0] in type_list: + type_list[pair[0]].append(pair[1]) + else: + type_list[pair[0]] = [pair[1]] + + with open(name + '/../libfreerdp/common/settings_getters.c', 'w+') as f: + f.write('/* Generated by ' + '' + ' */\n\n') + f.write('#include "../core/settings.h"\n\n') + f.write('#include <winpr/assert.h>\n') + f.write('#include <freerdp/settings.h>\n') + f.write('#include <freerdp/log.h>\n\n') + f.write('#define TAG FREERDP_TAG("common.settings")\n\n') + + f.write('static void free_string(char** current, BOOL cleanup)\n') + f.write('{\n') + f.write('\tif (cleanup)\n') + f.write('\t{\n') + f.write('\t\tif (*current)\n') + f.write('\t\t\tmemset(*current, 0, strlen(*current));\n') + f.write('\t\tfree(*current);\n') + f.write('\t\t(*current) = NULL;\n') + f.write('\t}\n') + f.write('}\n\n') + + f.write('static BOOL alloc_empty_string(char** current, const char* next, size_t next_len)\n') + f.write('{\n') + f.write('\tif (!next && (next_len > 0))\n') + f.write('\t{\n') + f.write('\t\t*current = calloc(next_len, 1);\n') + f.write('\t\treturn (*current != NULL);\n') + f.write('\t}\n') + f.write('\treturn FALSE;\n') + f.write('}\n\n') + + + f.write('static BOOL update_string_copy_(char** current, const char* next, size_t next_len, BOOL cleanup)\n') + f.write('{\n') + f.write('\tfree_string(current, cleanup);\n') + f.write('\n') + f.write('\tif (alloc_empty_string(current, next, next_len))\n') + f.write('\t\treturn TRUE;\n') + f.write('\n') + f.write('\t*current = (next ? strndup(next, next_len) : NULL);\n') + f.write('\treturn !next || (*current != NULL);\n') + f.write('}\n\n') + + f.write('static BOOL update_string_(char** current, char* next, size_t next_len)\n') + f.write('{\n') + f.write('\tfree_string(current, TRUE);\n') + f.write('\n') + f.write('\tif (alloc_empty_string(current, next, next_len))\n') + f.write('\t\treturn TRUE;\n') + f.write('\n') + f.write('\t*current = next;\n') + f.write('\treturn !next || (*current != NULL);\n') + f.write('}\n\n') + + getter_list = dict(type_list) + setter_list = dict(type_list) + setter_list2 = dict(type_list) + write_getter(f, getter_list, 'BOOL', 'bool', '') + write_setter(f, setter_list, 'BOOL', 'bool', '') + write_getter(f, getter_list, 'UINT16', 'uint16', '') + write_setter(f, setter_list, 'UINT16', 'uint16', '') + write_getter(f, getter_list, 'INT16', 'int16', '') + write_setter(f, setter_list, 'INT16', 'int16', '') + write_getter(f, getter_list, 'UINT32', 'uint32', '') + write_setter(f, setter_list, 'UINT32', 'uint32', '') + write_getter(f, getter_list, 'INT32', 'int32', '') + write_setter(f, setter_list, 'INT32', 'int32', '') + write_getter(f, getter_list, 'UINT64', 'uint64', '') + write_setter(f, setter_list, 'UINT64', 'uint64', '') + write_getter(f, getter_list, 'INT64', 'int64', '') + write_setter(f, setter_list, 'INT64', 'int64', '') + write_getter(f, getter_list, 'char*', 'string', '_') + write_setter(f, setter_list, 'char*', 'string', '_') + write_setter(f, setter_list2, 'char*', 'string', '_copy_') + write_getter(f, getter_list, '*', 'pointer', '') + write_setter(f, setter_list, '*', 'pointer', '') + + f.write('\n') + + with open(name + '/../libfreerdp/common/settings_str.h', 'w+') as f: + f.write('/* Generated by ' + '' + ' */\n\n') + f.write('#ifndef FREERDP_CORE_SETTINGS_STR_H\n') + f.write('#define FREERDP_CORE_SETTINGS_STR_H\n\n') + f.write('#include "../core/settings.h"\n\n') + f.write('#include <freerdp/settings.h>\n') + f.write('#include <freerdp/log.h>\n\n') + f.write('#define TAG FREERDP_TAG("common.settings")\n\n') + + getter_list = dict(type_list) + write_str(f, getter_list) + f.write('#endif\n') + f.write('\n') + + + with open(name + '/../libfreerdp/core/test/settings_property_lists.h', 'w+') as f: + f.write('#ifndef TEST_SETTINGS_PROPERTY_LISTS\n') + f.write('#define TEST_SETTINGS_PROPERTY_LISTS\n\n') + + write_entry(f, type_list, 'BOOL', 'bool') + write_entry(f, type_list, 'UINT16', 'uint16') + write_entry(f, type_list, 'INT16', 'int16') + write_entry(f, type_list, 'UINT32', 'uint32') + write_entry(f, type_list, 'INT32', 'int32') + write_entry(f, type_list, 'UINT64', 'uint64') + write_entry(f, type_list, 'INT64', 'int64') + write_entry(f, type_list, 'char*', 'string') + write_entry(f, type_list, '*', 'pointer') + + f.write('#endif /* TEST_SETTINGS_PROPERTY_LISTS */\n\n') + + print('remaining:\n' + str(type_list)) +except IOError as e: + print('failed to parse settings header ' + str(e)) + sys.exit(-1) +print('ended parsing settings header') |