File indexing completed on 2024-05-05 05:04:07

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)