mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
This new CMake option (ON by default) allows building the library with all symbols deprecated during 3.x release cycle disabled. This allows compatibility testing external applications for future FreeRDP 4.x support
413 lines
16 KiB
Python
Executable File
413 lines
16 KiB
Python
Executable File
#!/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 get_keys(entry_dict, entry_type, values):
|
|
l = list()
|
|
if '*' == entry_type:
|
|
dval = dict()
|
|
for key in list(entry_dict.keys()):
|
|
if entry_type in key:
|
|
xval = entry_dict[key]
|
|
for val in xval:
|
|
dval[val] = key
|
|
|
|
for val in list(values):
|
|
key = dval[val]
|
|
l.append(key)
|
|
return l
|
|
|
|
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, cast, typestr):
|
|
f.write('\t\tcase ')
|
|
if typestr:
|
|
f.write('(' + typestr + ')')
|
|
f.write('FreeRDP_' + val + ':\n')
|
|
f.write('\t\t\treturn ' + cast + 'settings->' + val + ';\n\n')
|
|
|
|
def write_getter_body(f, values, ret, keys, isPointer, compat_values, typestr, entry_type):
|
|
f.write('{\n')
|
|
f.write('\tWINPR_ASSERT(settings);\n\n')
|
|
f.write('\tswitch (id)\n')
|
|
f.write('\t{\n')
|
|
if values:
|
|
for i in range(len(values)):
|
|
val = values[i]
|
|
cast = ''
|
|
if isPointer and keys:
|
|
key = keys[i]
|
|
if key != 'void*':
|
|
cast = '(void*)'
|
|
write_getter_case(f, val, cast, None)
|
|
if compat_values:
|
|
f.write('#if defined(WITH_FREERDP_3x_DEPRECATED)\n')
|
|
for i in range(len(compat_values)):
|
|
val = compat_values[i]
|
|
cast = '(' + entry_type + ')'
|
|
f.write('\t\t// API Compatibility section, remove with FreeRDP 4.x\n')
|
|
write_getter_case(f, val, cast, typestr)
|
|
f.write('#endif\n')
|
|
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, compat_dict):
|
|
isString = 'string' in entry_name
|
|
isPointer = 'pointer' in entry_name
|
|
copy = dict(entry_dict)
|
|
values = get_values(entry_dict, entry_type)
|
|
compat_values = get_values(compat_dict, entry_type)
|
|
keys = get_keys(copy, entry_type, values)
|
|
|
|
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() + '(WINPR_ATTR_UNUSED const rdpSettings* settings, WINPR_ATTR_UNUSED ' + 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, keys, isPointer, compat_values, typestr, entry_type)
|
|
|
|
if isString:
|
|
f.write('char* freerdp_settings_get_' + entry_name.lower() + '_writable(rdpSettings* settings, ' + typestr + ' id)\n')
|
|
write_getter_body(f, values, ret, keys, isPointer, compat_values, typestr, entry_type)
|
|
|
|
def write_setter_case(f, val, postfix, isPointer, cast):
|
|
f.write('\t\tcase FreeRDP_' + val + ':\n')
|
|
if isPointer:
|
|
f.write('\t\t\tsettings->' + val + ' = ' + cast + ' cnv.v;\n')
|
|
f.write('\t\t\tbreak;\n\n')
|
|
elif not postfix:
|
|
f.write('\t\t\tsettings->' + val + ' = ' + cast + ' 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, compat_dict):
|
|
isString = 'string' in entry_name
|
|
isPointer = 'pointer' in entry_name
|
|
copy = dict(entry_dict)
|
|
values = get_values(entry_dict, entry_type)
|
|
compat_values = get_values(compat_dict, entry_type)
|
|
keys = get_keys(copy, entry_type, values)
|
|
|
|
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('(WINPR_ATTR_UNUSED rdpSettings* settings, WINPR_ATTR_UNUSED ' + typestr + ' id, ')
|
|
if isString 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:
|
|
count = 0
|
|
for val in values:
|
|
index = count
|
|
count += 1
|
|
cast = ''
|
|
if isPointer:
|
|
k = keys[index];
|
|
if k != 'void*' and len(k) > 0:
|
|
cast = '(' + k + ')'
|
|
write_setter_case(f, val, postfix, isPointer, cast)
|
|
if compat_values:
|
|
f.write('#if defined(WITH_FREERDP_3x_DEPRECATED)\n')
|
|
for val in compat_values:
|
|
cast = '(int32_t)'
|
|
f.write('\t\t// API Compatibility section, remove with FreeRDP 4.x\n')
|
|
write_setter_case(f, val, postfix, isPointer, cast)
|
|
f.write('#endif\n')
|
|
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 'version' 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)
|
|
# Compatibility with older 3.x releases where the value was wrongly an unsigned type
|
|
compat_getter_list = dict()
|
|
compat_getter_list['UINT32'] = list()
|
|
compat_getter_list['UINT32'].append('MonitorLocalShiftX')
|
|
compat_getter_list['UINT32'].append('MonitorLocalShiftY')
|
|
|
|
compat_setter_list = dict(compat_getter_list)
|
|
|
|
write_getter(f, getter_list, 'BOOL', 'bool', '', compat_getter_list)
|
|
write_setter(f, setter_list, 'BOOL', 'bool', '', compat_setter_list)
|
|
write_getter(f, getter_list, 'UINT16', 'uint16', '', compat_getter_list)
|
|
write_setter(f, setter_list, 'UINT16', 'uint16', '', compat_setter_list)
|
|
write_getter(f, getter_list, 'INT16', 'int16', '', compat_getter_list)
|
|
write_setter(f, setter_list, 'INT16', 'int16', '', compat_setter_list)
|
|
write_getter(f, getter_list, 'UINT32', 'uint32', '', compat_getter_list)
|
|
write_setter(f, setter_list, 'UINT32', 'uint32', '', compat_setter_list)
|
|
write_getter(f, getter_list, 'INT32', 'int32', '', compat_getter_list)
|
|
write_setter(f, setter_list, 'INT32', 'int32', '', compat_setter_list)
|
|
write_getter(f, getter_list, 'UINT64', 'uint64', '', compat_getter_list)
|
|
write_setter(f, setter_list, 'UINT64', 'uint64', '', compat_setter_list)
|
|
write_getter(f, getter_list, 'INT64', 'int64', '', compat_getter_list)
|
|
write_setter(f, setter_list, 'INT64', 'int64', '', compat_setter_list)
|
|
write_getter(f, getter_list, 'char*', 'string', '_', compat_getter_list)
|
|
write_setter(f, setter_list, 'char*', 'string', '_', compat_setter_list)
|
|
write_setter(f, setter_list2, 'char*', 'string', '_copy_', compat_setter_list)
|
|
write_getter(f, getter_list, '*', 'pointer', '', compat_getter_list)
|
|
write_setter(f, setter_list, '*', 'pointer', '', compat_setter_list)
|
|
|
|
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')
|