pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Merged pidgin/main into default
2017-06-30, Arkadiy Illarionov
5f88ba22172b
Merged pidgin/main into default
from
__future__
import
absolute_import
,
division
,
print_function
import
argparse
import
fileinput
import
re
import
sys
# types translated into "int"
simpletypes
=
[
"int"
,
"gint"
,
"guint"
,
"gboolean"
,
"size_t"
,
"gssize"
,
"time_t"
]
# List "excluded" contains functions that shouldn't be exported via
# DBus. If you remove a function from this list, please make sure
# that it does not break "make" with the configure option
# "--enable-dbus" turned on.
excluded
=
[
# I don't remember why this function is excluded; something to do
# with the fact that it takes a (const) GList as a parameter.
"purple_presence_add_list"
,
# These functions are excluded because they involve value of the
# type PurpleConvPlacementFunc, which is a pointer to a function and
# (currently?) can't be translated into a DBus type. Normally,
# functions with untranslatable types are skipped, but this script
# assumes that all non-pointer type names beginning with "Purple"
# are enums, which is not true in this case.
"purple_conversation_placement_add_fnc"
,
"purple_conversation_placement_get_fnc"
,
"purple_conversation_placement_get_current_func"
,
"purple_conversation_placement_set_current_func"
,
# Similar to the above:
"purple_account_set_register_callback"
,
"purple_account_unregister"
,
# Similar to the above:
"purple_protocol_server_iface_unregister_user"
,
# Similar to the above, again
"purple_menu_action_new"
,
"purple_menu_action_set_callback"
,
"purple_menu_action_get_callback"
,
# These functions are excluded because they involve setting arbitrary
# data via pointers for protocols and UIs. This just won't work.
"purple_blist_get_ui_data"
,
"purple_blist_set_ui_data"
,
"purple_blist_node_get_ui_data"
,
"purple_blist_node_set_ui_data"
,
"purple_buddy_get_protocol_data"
,
"purple_buddy_set_protocol_data"
,
# This is excluded because this script treats PurpleLogReadFlags*
# as pointer to a struct, instead of a pointer to an enum. This
# causes a compilation error. Someone should fix this script.
"purple_log_read"
,
# Similiar to the above:
"purple_notify_is_valid_ui_handle"
,
]
# This is a list of functions that return a GList* or GSList * whose elements
# are strings, not pointers to objects.
stringlists
=
[
"purple_prefs_get_path_list"
,
"purple_prefs_get_string_list"
,
"purple_uri_list_extract_filenames"
,
"purple_uri_list_extract_uris"
,
"purple_prefs_get_children_names"
,
]
# This is a list of functions that return a GList* or GSList* that should
# not be freed. Ideally, this information should be obtained from the gtk-doc
# documentation at some point.
constlists
=
[
"purple_account_get_status_types"
,
"purple_accounts_get_all"
,
"purple_account_option_get_list"
,
"purple_connections_get_all"
,
"purple_connections_get_connecting"
,
"purple_conversations_get_all"
,
"purple_conversations_get_ims"
,
"purple_conversations_get_chats"
,
"purple_chat_conversation_get_users"
,
"purple_chat_conversation_get_ignored"
,
"purple_mime_document_get_fields"
,
"purple_mime_document_get_parts"
,
"purple_mime_part_get_fields"
,
"purple_notify_user_info_get_entries"
,
"purple_request_fields_get_required"
,
"purple_request_field_list_get_selected"
,
"purple_request_field_list_get_items"
,
"purple_savedstatuses_get_all"
,
"purple_status_type_get_attrs"
,
"purple_presence_get_statuses"
,
"purple_conversation_get_message_history"
,
]
pointer
=
"#pointer#"
class
MyException
(
Exception
):
pass
def
ctopascal
(
name
):
newname
=
""
for
word
in
name
.
split
(
"_"
):
newname
+=
word
.
capitalize
()
return
newname
class
Parameter
(
object
):
def
__init__
(
self
,
type
,
name
):
self
.
name
=
name
self
.
type
=
type
def
fromtokens
(
tokens
,
parameternumber
=-
1
):
if
len
(
tokens
)
==
0
:
raise
MyException
()
if
len
(
tokens
)
==
1
or
tokens
[
-
1
]
==
pointer
:
if
parameternumber
>=
0
:
return
Parameter
(
tokens
,
"param
%i
"
%
(
parameternumber
,
))
else
:
raise
MyException
()
else
:
return
Parameter
(
tokens
[:
-
1
],
tokens
[
-
1
])
fromtokens
=
staticmethod
(
fromtokens
)
class
Binding
(
object
):
def
__init__
(
self
,
functiontext
,
paramtexts
,
output
=
None
):
self
.
function
=
Parameter
.
fromtokens
(
functiontext
.
split
())
if
self
.
function
.
name
in
excluded
:
raise
MyException
()
self
.
params
=
[]
for
i
in
range
(
len
(
paramtexts
)):
self
.
params
.
append
(
Parameter
.
fromtokens
(
paramtexts
[
i
]
.
split
(),
i
))
self
.
call
=
"
%s
(
%s
)"
%
(
self
.
function
.
name
,
", "
.
join
(
param
.
name
for
param
in
self
.
params
))
self
.
output
=
output
def
process
(
self
):
for
param
in
self
.
params
:
self
.
processinput
(
param
.
type
,
param
.
name
)
self
.
processoutput
(
self
.
function
.
type
,
"RESULT"
)
self
.
flush
()
def
processinput
(
self
,
type
,
name
):
const
=
False
unsigned
=
False
if
type
[
0
]
==
"const"
:
type
=
type
[
1
:]
const
=
True
if
type
[
0
]
==
"unsigned"
:
type
=
type
[
1
:]
unsigned
=
True
if
len
(
type
)
==
1
:
# simple types (int, gboolean, etc.) and enums
if
type
[
0
]
in
simpletypes
or
(
type
[
0
]
.
startswith
(
"Purple"
)
and
not
type
[
0
]
.
endswith
(
"Callback"
)):
return
self
.
inputsimple
(
type
,
name
,
unsigned
)
# pointers ...
if
len
(
type
)
==
2
and
type
[
1
]
==
pointer
:
# strings
if
type
[
0
]
in
[
"char"
,
"gchar"
]:
if
const
:
return
self
.
inputstring
(
type
,
name
,
unsigned
)
else
:
raise
MyException
()
elif
type
[
0
]
==
"GHashTable"
:
return
self
.
inputhash
(
type
,
name
)
# known object types are transformed to integer handles
elif
type
[
0
]
.
startswith
(
"Purple"
):
return
self
.
inputpurplestructure
(
type
,
name
)
# special case for *_get_data functions, be careful here...
elif
(
type
[
0
]
==
"size_t"
or
type
[
0
]
==
"gsize"
)
and
name
==
"len"
:
return
self
.
inputgetdata
(
type
,
name
)
# unknown pointers are always replaced with NULL
else
:
return
self
.
inputpointer
(
type
,
name
)
raise
MyException
()
def
processoutput
(
self
,
type
,
name
):
const
=
False
unsigned
=
False
# the "void" type is simple ...
if
type
==
[
"void"
]:
return
self
.
outputvoid
(
type
,
name
)
if
type
[
0
]
==
"const"
:
type
=
type
[
1
:]
const
=
True
if
type
[
0
]
==
"unsigned"
:
type
=
type
[
1
:]
unsigned
=
True
# a string
if
type
==
[
"char"
,
pointer
]
or
type
==
[
"gchar"
,
pointer
]:
return
self
.
outputstring
(
type
,
name
,
const
)
# simple types (ints, booleans, enums, ...)
if
(
len
(
type
)
==
1
and
(
type
[
0
]
in
simpletypes
or
type
[
0
]
.
startswith
(
"Purple"
))):
return
self
.
outputsimple
(
type
,
name
,
unsigned
)
# pointers ...
if
len
(
type
)
==
2
and
type
[
1
]
==
pointer
:
# handles
if
type
[
0
]
.
startswith
(
"Purple"
):
return
self
.
outputpurplestructure
(
type
,
name
)
if
type
[
0
]
in
[
"GList"
,
"GSList"
]:
return
self
.
outputlist
(
type
,
name
)
# Special case for *_get_data functions
if
type
[
0
]
==
"gconstpointer"
:
return
self
.
outputgetdata
(
type
,
name
)
raise
MyException
()
class
ClientBinding
(
Binding
):
def
__init__
(
self
,
functiontext
,
paramtexts
,
knowntypes
,
headersonly
,
**
kwargs
):
Binding
.
__init__
(
self
,
functiontext
,
paramtexts
,
**
kwargs
)
self
.
knowntypes
=
knowntypes
self
.
headersonly
=
headersonly
self
.
paramshdr
=
[]
self
.
decls
=
[]
self
.
inputparams
=
[]
self
.
outputparams
=
[]
self
.
returncode
=
[]
def
flush
(
self
):
paramslist
=
", "
.
join
(
self
.
paramshdr
)
if
paramslist
==
""
:
paramslist
=
"void"
print
(
"
%s
%s
(
%s
)"
%
(
self
.
functiontype
,
self
.
function
.
name
,
paramslist
),
end
=
' '
,
file
=
self
.
output
)
if
self
.
headersonly
:
print
(
";"
,
file
=
self
.
output
)
return
print
(
"{"
,
file
=
self
.
output
)
for
decl
in
self
.
decls
:
print
(
decl
,
file
=
self
.
output
)
print
(
'dbus_g_proxy_call(purple_proxy, "
%s
", NULL,'
%
(
ctopascal
(
self
.
function
.
name
),
),
file
=
self
.
output
)
for
type_name
in
self
.
inputparams
:
print
(
"
\t
%s
,
%s
, "
%
type_name
,
end
=
' '
,
file
=
self
.
output
)
print
(
"G_TYPE_INVALID,"
,
file
=
self
.
output
)
for
type_name
in
self
.
outputparams
:
print
(
"
\t
%s
, &
%s
, "
%
type_name
,
end
=
' '
,
file
=
self
.
output
)
print
(
"G_TYPE_INVALID);"
,
file
=
self
.
output
)
for
code
in
self
.
returncode
:
print
(
code
,
file
=
self
.
output
)
print
(
"}
\n
"
,
file
=
self
.
output
)
def
definepurplestructure
(
self
,
type
):
if
self
.
headersonly
and
type
[
0
]
not
in
self
.
knowntypes
:
print
(
"struct _
%s
;"
%
(
type
[
0
],
),
file
=
self
.
output
)
print
(
"typedef struct _
%s
%s
;"
%
(
type
[
0
],
type
[
0
]),
file
=
self
.
output
)
self
.
knowntypes
.
append
(
type
[
0
])
def
inputsimple
(
self
,
type
,
name
,
us
):
self
.
paramshdr
.
append
(
"
%s
%s
"
%
(
type
[
0
],
name
))
if
us
:
self
.
inputparams
.
append
((
"G_TYPE_UINT"
,
name
))
else
:
self
.
inputparams
.
append
((
"G_TYPE_INT"
,
name
))
def
inputstring
(
self
,
type
,
name
,
us
):
if
us
:
self
.
paramshdr
.
append
(
"const unsigned char *
%s
"
%
(
name
,
))
else
:
self
.
paramshdr
.
append
(
"const char *
%s
"
%
(
name
,
))
self
.
inputparams
.
append
((
"G_TYPE_STRING"
,
name
))
def
inputpurplestructure
(
self
,
type
,
name
):
self
.
paramshdr
.
append
(
"const
%s
*
%s
"
%
(
type
[
0
],
name
))
self
.
inputparams
.
append
((
"G_TYPE_INT"
,
"GPOINTER_TO_INT(
%s
)"
%
(
name
,
)))
self
.
definepurplestructure
(
type
)
def
inputpointer
(
self
,
type
,
name
):
name
+=
"_NULL"
self
.
paramshdr
.
append
(
"const
%s
*
%s
"
%
(
type
[
0
],
name
))
self
.
inputparams
.
append
((
"G_TYPE_INT"
,
"0"
))
def
inputhash
(
self
,
type
,
name
):
self
.
paramshdr
.
append
(
"const GHashTable *
%s
"
%
(
name
,
))
self
.
inputparams
.
append
(
(
'dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_STRING)'
,
name
))
def
outputvoid
(
self
,
type
,
name
):
self
.
functiontype
=
"void"
def
outputstring
(
self
,
type
,
name
,
const
):
self
.
functiontype
=
"char*"
self
.
decls
.
append
(
"char *
%s
= NULL;"
%
(
name
,
))
self
.
outputparams
.
append
((
"G_TYPE_STRING"
,
name
))
# self.returncode.append("NULLIFY(%s);" % (name, ))
self
.
returncode
.
append
(
"return
%s
;"
%
(
name
,
))
def
outputsimple
(
self
,
type
,
name
,
us
):
self
.
functiontype
=
type
[
0
]
self
.
decls
.
append
(
"
%s
%s
= 0;"
%
(
type
[
0
],
name
))
if
us
:
self
.
outputparams
.
append
((
"G_TYPE_UINT"
,
name
))
else
:
self
.
outputparams
.
append
((
"G_TYPE_INT"
,
name
))
self
.
returncode
.
append
(
"return
%s
;"
%
(
name
,
))
# we could add "const" to the return type but this would probably
# be a nuisance
def
outputpurplestructure
(
self
,
type
,
name
):
name
=
name
+
"_ID"
self
.
functiontype
=
"
%s
*"
%
(
type
[
0
],
)
self
.
decls
.
append
(
"int
%s
= 0;"
%
(
name
,
))
self
.
outputparams
.
append
((
"G_TYPE_INT"
,
"
%s
"
%
(
name
,
)))
self
.
returncode
.
append
(
"return (
%s
*) GINT_TO_POINTER(
%s
);"
%
(
type
[
0
],
name
))
self
.
definepurplestructure
(
type
)
def
outputlist
(
self
,
type
,
name
):
self
.
functiontype
=
"
%s
*"
%
(
type
[
0
],
)
self
.
decls
.
append
(
"GArray *
%s
;"
%
(
name
,
))
self
.
outputparams
.
append
(
(
'dbus_g_type_get_collection("GArray", G_TYPE_INT)'
,
name
))
self
.
returncode
.
append
(
"return garray_int_to_
%s
(
%s
);"
%
(
type
[
0
]
.
lower
(),
name
))
# Special case for *_get_data functions, don't need client bindings,
# but do need the name so it doesn't crash
def
inputgetdata
(
self
,
type
,
name
):
raise
MyException
()
def
outputgetdata
(
self
,
type
,
name
):
raise
MyException
()
class
ServerBinding
(
Binding
):
def
__init__
(
self
,
functiontext
,
paramtexts
,
**
kwargs
):
Binding
.
__init__
(
self
,
functiontext
,
paramtexts
,
**
kwargs
)
self
.
dparams
=
""
self
.
cparams
=
[]
self
.
cdecls
=
[]
self
.
ccode
=
[]
self
.
cparamsout
=
[]
self
.
ccodeout
=
[]
self
.
argfunc
=
"dbus_message_get_args"
def
flush
(
self
):
print
(
"static DBusMessage*"
,
file
=
self
.
output
)
print
(
"
%s
_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {"
%
self
.
function
.
name
,
file
=
self
.
output
)
print
(
"
\t
DBusMessage *reply_DBUS;"
,
file
=
self
.
output
)
for
decl
in
self
.
cdecls
:
print
(
decl
,
file
=
self
.
output
)
print
(
"
\t
%s
(message_DBUS, error_DBUS,"
%
(
self
.
argfunc
,
),
end
=
' '
,
file
=
self
.
output
)
for
param
in
self
.
cparams
:
print
(
"DBUS_TYPE_
%s
, &
%s
,"
%
param
,
end
=
' '
,
file
=
self
.
output
)
print
(
"DBUS_TYPE_INVALID);"
,
file
=
self
.
output
)
print
(
"
\t
CHECK_ERROR(error_DBUS);"
,
file
=
self
.
output
)
for
code
in
self
.
ccode
:
print
(
code
,
file
=
self
.
output
)
print
(
"
\t
reply_DBUS = dbus_message_new_method_return (message_DBUS);"
,
file
=
self
.
output
)
print
(
"
\t
dbus_message_append_args(reply_DBUS,"
,
end
=
' '
,
file
=
self
.
output
)
for
param
in
self
.
cparamsout
:
if
type
(
param
)
is
str
:
print
(
"
%s
,"
%
(
param
,
),
end
=
' '
,
file
=
self
.
output
)
else
:
print
(
"DBUS_TYPE_
%s
, &
%s
,"
%
param
,
end
=
' '
,
file
=
self
.
output
)
print
(
"DBUS_TYPE_INVALID);"
,
file
=
self
.
output
)
for
code
in
self
.
ccodeout
:
print
(
code
,
file
=
self
.
output
)
print
(
"
\t
return reply_DBUS;
\n
}
\n
"
,
file
=
self
.
output
)
def
addstring
(
self
,
*
items
):
for
item
in
items
:
self
.
dparams
+=
item
+
r
"\0"
def
addintype
(
self
,
type
,
name
):
self
.
addstring
(
"in"
,
type
,
name
)
def
addouttype
(
self
,
type
,
name
):
self
.
addstring
(
"out"
,
type
,
name
)
# input parameters
def
inputsimple
(
self
,
type
,
name
,
us
):
if
us
:
self
.
cdecls
.
append
(
"
\t
dbus_uint32_t
%s
;"
%
(
name
,
))
self
.
cparams
.
append
((
"UINT32"
,
name
))
self
.
addintype
(
"u"
,
name
)
else
:
self
.
cdecls
.
append
(
"
\t
dbus_int32_t
%s
;"
%
(
name
,
))
self
.
cparams
.
append
((
"INT32"
,
name
))
self
.
addintype
(
"i"
,
name
)
def
inputstring
(
self
,
type
,
name
,
us
):
if
us
:
self
.
cdecls
.
append
(
"
\t
const unsigned char *
%s
;"
%
(
name
,
))
else
:
self
.
cdecls
.
append
(
"
\t
const char *
%s
;"
%
(
name
,
))
self
.
cparams
.
append
((
"STRING"
,
name
))
self
.
ccode
.
append
(
"
\t
%s
= (
%s
&&
%s
[0]) ?
%s
: NULL;"
%
(
name
,
name
,
name
,
name
))
self
.
addintype
(
"s"
,
name
)
def
inputhash
(
self
,
type
,
name
):
self
.
argfunc
=
"purple_dbus_message_get_args"
self
.
cdecls
.
append
(
"
\t
DBusMessageIter
%s
_ITER;"
%
(
name
,
))
self
.
cdecls
.
append
(
"
\t
GHashTable *
%s
;"
%
(
name
,
))
self
.
cparams
.
append
((
"ARRAY"
,
"
%s
_ITER"
%
(
name
,
)))
self
.
ccode
.
append
(
"
\t
%s
= purple_dbus_iter_hash_table(&
%s
_ITER, error_DBUS);"
%
(
name
,
name
))
self
.
ccode
.
append
(
"
\t
CHECK_ERROR(error_DBUS);"
)
self
.
ccodeout
.
append
(
"
\t
g_hash_table_destroy(
%s
);"
%
(
name
,
))
self
.
addintype
(
"a
{ss}
"
,
name
)
def
inputpurplestructure
(
self
,
type
,
name
):
self
.
cdecls
.
append
(
"
\t
dbus_int32_t
%s
_ID;"
%
(
name
,
))
self
.
cdecls
.
append
(
"
\t
%s
*
%s
;"
%
(
type
[
0
],
name
))
self
.
cparams
.
append
((
"INT32"
,
name
+
"_ID"
))
self
.
ccode
.
append
(
"
\t
PURPLE_DBUS_ID_TO_POINTER(
%s
,
%s
_ID,
%s
, error_DBUS);"
%
(
name
,
name
,
type
[
0
]))
self
.
addintype
(
"i"
,
name
)
def
inputpointer
(
self
,
type
,
name
):
self
.
cdecls
.
append
(
"
\t
dbus_int32_t
%s
_NULL;"
%
(
name
,
))
self
.
cdecls
.
append
(
"
\t
%s
*
%s
;"
%
(
type
[
0
],
name
))
self
.
cparams
.
append
((
"INT32"
,
name
+
"_NULL"
))
self
.
ccode
.
append
(
"
\t
%s
= NULL;"
%
(
name
,
))
self
.
addintype
(
"i"
,
name
)
# output parameters
def
outputvoid
(
self
,
type
,
name
):
self
.
ccode
.
append
(
"
\t
%s
;"
%
(
self
.
call
,
))
# just call the function
def
outputstring
(
self
,
type
,
name
,
const
):
if
const
:
self
.
cdecls
.
append
(
"
\t
const char *
%s
;"
%
(
name
,
))
else
:
self
.
cdecls
.
append
(
"
\t
char *
%s
;"
%
(
name
,
))
self
.
ccode
.
append
(
"
\t
if ((
%s
=
%s
) == NULL)"
%
(
name
,
self
.
call
))
self
.
ccode
.
append
(
"
\t\t
%s
=
\"\"
;"
%
(
name
,
))
self
.
cparamsout
.
append
((
"STRING"
,
name
))
self
.
addouttype
(
"s"
,
name
)
if
not
const
:
self
.
ccodeout
.
append
(
"
\t
g_free(
%s
);"
%
(
name
,
))
def
outputsimple
(
self
,
type
,
name
,
us
):
if
us
:
self
.
cdecls
.
append
(
"
\t
dbus_uint32_t
%s
;"
%
(
name
,
))
self
.
cparamsout
.
append
((
"UINT32"
,
name
))
self
.
addouttype
(
"u"
,
name
)
else
:
self
.
cdecls
.
append
(
"
\t
dbus_int32_t
%s
;"
%
(
name
,
))
self
.
cparamsout
.
append
((
"INT32"
,
name
))
self
.
addouttype
(
"i"
,
name
)
self
.
ccode
.
append
(
"
\t
%s
=
%s
;"
%
(
name
,
self
.
call
))
def
outputpurplestructure
(
self
,
type
,
name
):
self
.
cdecls
.
append
(
"
\t
dbus_int32_t
%s
;"
%
(
name
,
))
self
.
ccode
.
append
(
"
\t
PURPLE_DBUS_POINTER_TO_ID(
%s
,
%s
, error_DBUS);"
%
(
name
,
self
.
call
))
self
.
cparamsout
.
append
((
"INT32"
,
name
))
self
.
addouttype
(
"i"
,
name
)
# GList*, GSList*, assume that list is a list of objects
# unless the function is in stringlists
def
outputlist
(
self
,
type
,
name
):
self
.
cdecls
.
append
(
"
\t
dbus_int32_t
%s
_LEN;"
%
(
name
,
))
self
.
ccodeout
.
append
(
"
\t
g_free(
%s
);"
%
(
name
,
))
self
.
cdecls
.
append
(
"
\t
%s
*list;"
%
(
type
[
0
],
))
if
self
.
function
.
name
in
stringlists
:
self
.
cdecls
.
append
(
"
\t
char **
%s
;"
%
(
name
,
))
self
.
ccode
.
append
(
"
\t
list =
%s
;"
%
(
self
.
call
,
))
self
.
ccode
.
append
(
"
\t
%s
= (char **)purple_
%s
_to_array(list, &
%s
_LEN);"
%
(
name
,
type
[
0
],
name
))
self
.
cparamsout
.
append
(
"DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &
%s
,
%s
_LEN"
%
(
name
,
name
))
if
self
.
function
.
name
not
in
constlists
:
type_name
=
type
[
0
]
.
lower
()[
1
:]
self
.
ccodeout
.
append
(
"
\t
g_
%s
_foreach(list, (GFunc)g_free, NULL);"
%
(
type_name
,
))
self
.
ccodeout
.
append
(
"
\t
g_
%s
_free(list);"
%
(
type_name
,
))
self
.
addouttype
(
"as"
,
name
)
else
:
self
.
cdecls
.
append
(
"
\t
dbus_int32_t *
%s
;"
%
(
name
,
))
self
.
ccode
.
append
(
"
\t
list =
%s
;"
%
(
self
.
call
,
))
self
.
ccode
.
append
(
"
\t
%s
= purple_dbusify_
%s
(list, &
%s
_LEN);"
%
(
name
,
type
[
0
],
name
))
if
self
.
function
.
name
not
in
constlists
:
type_name
=
type
[
0
]
.
lower
()[
1
:]
self
.
ccode
.
append
(
"
\t
g_
%s
_free(list);"
%
(
type_name
,
))
self
.
cparamsout
.
append
(
"DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &
%s
,
%s
_LEN"
%
(
name
,
name
))
self
.
addouttype
(
"ai"
,
name
)
# Special case for *_get_data functions
def
inputgetdata
(
self
,
type
,
name
):
self
.
cdecls
.
append
(
"
\t
size_t
%s
= 0;"
%
(
name
,
))
return
True
def
outputgetdata
(
self
,
type
,
name
):
# This is a total hack, but self.call is set up before the parameters
# are processed, so we can't tell it to pass a parameter by reference.
params
=
', '
.
join
(
'&len'
if
param
.
name
==
'len'
else
param
.
name
for
param
in
self
.
params
)
self
.
call
=
"
%s
(
%s
)"
%
(
self
.
function
.
name
,
params
)
self
.
cdecls
.
append
(
"
\t
gconstpointer
%s
;"
%
(
name
,
))
self
.
ccode
.
append
(
"
\t
%s
=
%s
;"
%
(
name
,
self
.
call
))
self
.
cparamsout
.
append
(
"DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &
%s
,
%s
"
%
(
name
,
"len"
))
self
.
addouttype
(
"ay"
,
name
)
class
BindingSet
(
object
):
regexp
=
r
"^(\w[^()]*)\(([^()]*)\)\s*;\s*$"
def
__init__
(
self
,
inputfile
,
fprefix
,
output
=
None
):
self
.
inputiter
=
iter
(
inputfile
)
self
.
functionregexp
=
re
.
compile
(
"^
%s
(\w[^()]*)\(([^()]*)\)\s*;\s*$"
%
(
fprefix
,
))
self
.
typeregexp
=
re
.
compile
(
"^\w+\s*\*?\s*$"
)
self
.
output
=
output
def
process
(
self
):
print
(
"/* Generated by
%s
. Do not edit! */"
%
(
sys
.
argv
[
0
],
),
file
=
self
.
output
)
for
line
in
self
.
inputiter
:
words
=
line
.
split
()
if
len
(
words
)
==
0
:
# empty line
continue
if
line
[
0
]
==
"#"
:
# preprocessor directive
continue
if
words
[
0
]
in
[
"typedef"
,
"struct"
,
"enum"
,
"static"
]:
continue
# accumulate lines until the parentheses are balance or an
# empty line has been encountered
myline
=
line
.
strip
()
while
(
myline
.
count
(
"("
)
>
myline
.
count
(
")"
)
or
self
.
typeregexp
.
match
(
myline
)):
newline
=
next
(
self
.
inputiter
)
.
strip
()
if
len
(
newline
)
==
0
:
break
myline
+=
" "
+
newline
# is this a function declaration?
thematch
=
self
.
functionregexp
.
match
(
myline
.
replace
(
"*"
,
" "
+
pointer
+
" "
))
if
thematch
is
None
:
continue
functiontext
=
thematch
.
group
(
1
)
paramstext
=
thematch
.
group
(
2
)
.
strip
()
if
(
paramstext
==
"void"
)
or
(
paramstext
==
""
):
paramtexts
=
[]
else
:
paramtexts
=
paramstext
.
split
(
","
)
try
:
self
.
processfunction
(
functiontext
,
paramtexts
)
except
MyException
:
pass
except
:
raise
self
.
flush
()
class
ServerBindingSet
(
BindingSet
):
def
__init__
(
self
,
inputfile
,
fprefix
,
**
kwargs
):
BindingSet
.
__init__
(
self
,
inputfile
,
fprefix
,
**
kwargs
)
self
.
functions
=
[]
def
processfunction
(
self
,
functiontext
,
paramtexts
):
binding
=
ServerBinding
(
functiontext
,
paramtexts
,
output
=
self
.
output
)
binding
.
process
()
self
.
functions
.
append
((
binding
.
function
.
name
,
binding
.
dparams
))
def
flush
(
self
):
print
(
"static PurpleDBusBinding bindings_DBUS[] = { "
,
file
=
self
.
output
)
for
function
,
params
in
self
.
functions
:
print
(
'{"
%s
", "
%s
",
%s
_DBUS},'
%
(
ctopascal
(
function
),
params
,
function
),
file
=
self
.
output
)
print
(
"{NULL, NULL, NULL}"
,
file
=
self
.
output
)
print
(
"};"
,
file
=
self
.
output
)
print
(
"#define PURPLE_DBUS_REGISTER_BINDINGS(handle) "
"purple_dbus_register_bindings(handle, bindings_DBUS)"
,
file
=
self
.
output
)
class
ClientBindingSet
(
BindingSet
):
def
__init__
(
self
,
inputfile
,
fprefix
,
headersonly
,
**
kwargs
):
BindingSet
.
__init__
(
self
,
inputfile
,
fprefix
,
**
kwargs
)
self
.
functions
=
[]
self
.
knowntypes
=
[]
self
.
headersonly
=
headersonly
def
processfunction
(
self
,
functiontext
,
paramtexts
):
binding
=
ClientBinding
(
functiontext
,
paramtexts
,
self
.
knowntypes
,
self
.
headersonly
,
output
=
self
.
output
)
binding
.
process
()
def
flush
(
self
):
pass
# Main program
parser
=
argparse
.
ArgumentParser
()
parser
.
add_argument
(
'input'
,
nargs
=
'*'
,
help
=
'Input files (or stdin if not specified)'
)
parser
.
add_argument
(
'-o'
,
'--output'
,
help
=
'Output to file instead of stdout'
)
parser
.
add_argument
(
'-a'
,
'--append'
,
action
=
'store_true'
,
help
=
'Append to file instead of overwriting it'
)
parser
.
add_argument
(
'-e'
,
'--export-only'
,
action
=
'store_true'
,
help
=
'Prefix functions for export'
)
parser
.
add_argument
(
'-c'
,
'--client'
,
action
=
'store_true'
,
help
=
'Produce client bindings instead of server bindings'
)
parser
.
add_argument
(
'-H'
,
'--headers'
,
action
=
'store_true'
,
help
=
'Produce headers only'
)
args
=
parser
.
parse_args
()
if
args
.
export_only
:
fprefix
=
"DBUS_EXPORT\s+"
else
:
fprefix
=
""
myinput
=
fileinput
.
input
(
args
.
input
)
if
args
.
output
is
not
None
:
output
=
open
(
args
.
output
,
'a'
if
args
.
append
else
'w'
)
else
:
output
=
None
if
args
.
client
:
bindings
=
ClientBindingSet
(
myinput
,
fprefix
,
args
.
headers
,
output
=
output
)
else
:
bindings
=
ServerBindingSet
(
myinput
,
fprefix
,
output
=
output
)
bindings
.
process
()