File indexing completed on 2024-05-12 12:57:37
0001 #!/usr/bin/python 0002 0003 # manager-file.py: generate .manager files and TpCMParamSpec arrays from the 0004 # same data (should be suitable for all connection managers that don't have 0005 # plugins) 0006 # 0007 # The master copy of this program is in the telepathy-glib repository - 0008 # please make any changes there. 0009 # 0010 # Copyright (c) Collabora Ltd. <http://www.collabora.co.uk/> 0011 # 0012 # This library is free software; you can redistribute it and/or 0013 # modify it under the terms of the GNU Lesser General Public 0014 # License as published by the Free Software Foundation; either 0015 # version 2.1 of the License, or (at your option) any later version. 0016 # 0017 # This library is distributed in the hope that it will be useful, 0018 # but WITHOUT ANY WARRANTY; without even the implied warranty of 0019 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0020 # Lesser General Public License for more details. 0021 # 0022 # You should have received a copy of the GNU Lesser General Public 0023 # License along with this library; if not, write to the Free Software 0024 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0025 0026 import re 0027 import sys 0028 import os 0029 0030 _NOT_C_STR = re.compile(r'[^A-Za-z0-9_-]') 0031 0032 def c_string(x): 0033 # whitelist-based brute force and ignorance - escape nearly all punctuation 0034 return '"' + _NOT_C_STR.sub(lambda c: r'\x%02x' % ord(c), x) + '"' 0035 0036 def desktop_string(x): 0037 return x.replace(' ', r'\s').replace('\n', r'\n').replace('\r', r'\r').replace('\t', r'\t') 0038 0039 supported = list('sbuiqn') 0040 0041 fdefaultencoders = { 0042 's': desktop_string, 0043 'b': (lambda b: b and '1' or '0'), 0044 'u': (lambda n: '%u' % n), 0045 'i': (lambda n: '%d' % n), 0046 'q': (lambda n: '%u' % n), 0047 'n': (lambda n: '%d' % n), 0048 } 0049 for x in supported: assert x in fdefaultencoders 0050 0051 gtypes = { 0052 's': 'G_TYPE_STRING', 0053 'b': 'G_TYPE_BOOLEAN', 0054 'u': 'G_TYPE_UINT', 0055 'i': 'G_TYPE_INT', 0056 'q': 'G_TYPE_UINT', 0057 'n': 'G_TYPE_INT', 0058 } 0059 for x in supported: assert x in gtypes 0060 0061 gdefaultencoders = { 0062 's': c_string, 0063 'b': (lambda b: b and 'GINT_TO_POINTER (TRUE)' or 'GINT_TO_POINTER (FALSE)'), 0064 'u': (lambda n: 'GUINT_TO_POINTER (%u)' % n), 0065 'i': (lambda n: 'GINT_TO_POINTER (%d)' % n), 0066 'q': (lambda n: 'GUINT_TO_POINTER (%u)' % n), 0067 'n': (lambda n: 'GINT_TO_POINTER (%d)' % n), 0068 } 0069 for x in supported: assert x in gdefaultencoders 0070 0071 gdefaultdefaults = { 0072 's': 'NULL', 0073 'b': 'GINT_TO_POINTER (FALSE)', 0074 'u': 'GUINT_TO_POINTER (0)', 0075 'i': 'GINT_TO_POINTER (0)', 0076 'q': 'GUINT_TO_POINTER (0)', 0077 'n': 'GINT_TO_POINTER (0)', 0078 } 0079 for x in supported: assert x in gdefaultdefaults 0080 0081 gflags = { 0082 'has-default': 'TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT', 0083 'register': 'TP_CONN_MGR_PARAM_FLAG_REGISTER', 0084 'required': 'TP_CONN_MGR_PARAM_FLAG_REQUIRED', 0085 'secret': 'TP_CONN_MGR_PARAM_FLAG_SECRET', 0086 'dbus-property': 'TP_CONN_MGR_PARAM_FLAG_DBUS_PROPERTY', 0087 } 0088 0089 def write_manager(f, manager, protos): 0090 # pointless backwards compat section 0091 print('[ConnectionManager]', file=f) 0092 print('BusName=org.freedesktop.Telepathy.ConnectionManager.' + manager, file=f) 0093 print('ObjectPath=/org/freedesktop/Telepathy/ConnectionManager/' + manager, file=f) 0094 0095 # protocols 0096 for proto, params in protos.items(): 0097 print(file=f) 0098 print('[Protocol %s]' % proto, file=f) 0099 0100 defaults = {} 0101 0102 for param, info in params.items(): 0103 dtype = info['dtype'] 0104 flags = info.get('flags', '').split() 0105 struct_field = info.get('struct_field', param.replace('-', '_')) 0106 filter = info.get('filter', 'NULL') 0107 filter_data = info.get('filter_data', 'NULL') 0108 setter_data = 'NULL' 0109 0110 if 'default' in info: 0111 default = fdefaultencoders[dtype](info['default']) 0112 defaults[param] = default 0113 0114 if flags: 0115 flags = ' ' + ' '.join(flags) 0116 else: 0117 flags = '' 0118 0119 print('param-%s=%s%s' % (param, desktop_string(dtype), flags), file=f) 0120 0121 for param, default in defaults.items(): 0122 print('default-%s=%s' % (param, default), file=f) 0123 0124 def write_c_params(f, manager, proto, struct, params): 0125 print("static const TpCMParamSpec %s_%s_params[] = {" % (manager, proto), file=f) 0126 0127 for param, info in params.items(): 0128 dtype = info['dtype'] 0129 flags = info.get('flags', '').split() 0130 struct_field = info.get('struct_field', param.replace('-', '_')) 0131 filter = info.get('filter', 'NULL') 0132 filter_data = info.get('filter_data', 'NULL') 0133 setter_data = 'NULL' 0134 0135 if 'default' in info: 0136 default = gdefaultencoders[dtype](info['default']) 0137 else: 0138 default = gdefaultdefaults[dtype] 0139 0140 if flags: 0141 flags = ' | '.join([gflags[flag] for flag in flags]) 0142 else: 0143 flags = '0' 0144 0145 if struct is None or struct_field is None: 0146 struct_offset = '0' 0147 else: 0148 struct_offset = 'G_STRUCT_OFFSET (%s, %s)' % (struct, struct_field) 0149 0150 print((''' { %s, %s, %s, 0151 %s, 0152 %s, /* default */ 0153 %s, /* struct offset */ 0154 %s, /* filter */ 0155 %s, /* filter data */ 0156 %s /* setter data */ },''' % 0157 (c_string(param), c_string(dtype), gtypes[dtype], flags, 0158 default, struct_offset, filter, filter_data, setter_data)), file=f) 0159 0160 print(" { NULL }", file=f) 0161 print("};", file=f) 0162 0163 if __name__ == '__main__': 0164 environment = {} 0165 exec(compile(open(sys.argv[1], "rb").read(), sys.argv[1], 'exec'), environment) 0166 0167 filename = '%s/%s.manager' % (sys.argv[2], environment['MANAGER']) 0168 try: 0169 os.remove(filename) 0170 except OSError: 0171 pass 0172 f = open(filename + '.tmp', 'w') 0173 write_manager(f, environment['MANAGER'], environment['PARAMS']) 0174 f.close() 0175 os.rename(filename + '.tmp', filename) 0176 0177 filename = '%s/param-spec-struct.h' % sys.argv[2] 0178 try: 0179 os.remove(filename) 0180 except OSError: 0181 pass 0182 f = open(filename + '.tmp', 'w') 0183 for protocol in environment['PARAMS']: 0184 write_c_params(f, environment['MANAGER'], protocol, 0185 environment['STRUCTS'][protocol], 0186 environment['PARAMS'][protocol]) 0187 f.close() 0188 os.rename(filename + '.tmp', filename)