diff options
Diffstat (limited to 'gtk/gtkargcollector.c')
-rw-r--r-- | gtk/gtkargcollector.c | 285 |
1 files changed, 145 insertions, 140 deletions
diff --git a/gtk/gtkargcollector.c b/gtk/gtkargcollector.c index 3067738062..32a0ec7847 100644 --- a/gtk/gtkargcollector.c +++ b/gtk/gtkargcollector.c @@ -17,144 +17,149 @@ * Boston, MA 02111-1307, USA. */ -/* collect a single argument value from a va_list +/* collect a single argument value from a va_list. + * this is implemented as a huge macro <shrug>, because we can't + * pass va_list variables by reference on some systems. + * the former prototype was: + * static inline gchar* + * gtk_arg_collect_value (GtkType fundamental_type, + * GtkArg *arg, + * va_list var_args); */ -static inline gchar* -gtk_arg_collect_value (GtkType fundamental_type, - GtkArg *arg, - va_list *var_args) -{ - gchar *error_msg; - - error_msg = NULL; - switch (fundamental_type) - { - case GTK_TYPE_INVALID: - error_msg = g_strdup ("invalid untyped argument"); - break; - - case GTK_TYPE_NONE: - /* we just ignore this type, since it arithmetically just requires - * us to not move the var_args pointer any further. callers need to - * check for the validity of GTK_TYPE_NONE themselves. - * - * error_msg = g_strdup ("invalid argument type `void'"); - */ - break; - - /* everything smaller than an int is guarranteed to be - * passed as an int - */ - case GTK_TYPE_CHAR: - GTK_VALUE_CHAR (*arg) = va_arg (*var_args, gint); - break; - case GTK_TYPE_UCHAR: - GTK_VALUE_UCHAR (*arg) = va_arg (*var_args, guint); - break; - case GTK_TYPE_BOOL: - GTK_VALUE_BOOL (*arg) = va_arg (*var_args, gint); - break; - case GTK_TYPE_INT: - GTK_VALUE_INT (*arg) = va_arg (*var_args, gint); - break; - case GTK_TYPE_UINT: - GTK_VALUE_UINT (*arg) = va_arg (*var_args, guint); - break; - case GTK_TYPE_ENUM: - GTK_VALUE_ENUM (*arg) = va_arg (*var_args, gint); - break; - case GTK_TYPE_FLAGS: - GTK_VALUE_FLAGS (*arg) = va_arg (*var_args, guint); - break; - - /* we collect longs as glongs since they differ in size with - * integers on some platforms - */ - case GTK_TYPE_LONG: - GTK_VALUE_LONG (*arg) = va_arg (*var_args, glong); - break; - case GTK_TYPE_ULONG: - GTK_VALUE_ULONG (*arg) = va_arg (*var_args, gulong); - break; - - /* floats are always passed as doubles - */ - case GTK_TYPE_FLOAT: - /* GTK_VALUE_FLOAT (*arg) = va_arg (*var_args, gfloat); */ - GTK_VALUE_FLOAT (*arg) = va_arg (*var_args, gdouble); - break; - case GTK_TYPE_DOUBLE: - GTK_VALUE_DOUBLE (*arg) = va_arg (*var_args, gdouble); - break; - - /* collect pointer values - */ - case GTK_TYPE_STRING: - GTK_VALUE_STRING (*arg) = va_arg (*var_args, gchar*); - break; - case GTK_TYPE_POINTER: - GTK_VALUE_POINTER (*arg) = va_arg (*var_args, gpointer); - break; - case GTK_TYPE_BOXED: - GTK_VALUE_BOXED (*arg) = va_arg (*var_args, gpointer); - break; - - /* structured types - */ - case GTK_TYPE_SIGNAL: - GTK_VALUE_SIGNAL (*arg).f = va_arg (*var_args, GtkSignalFunc); - GTK_VALUE_SIGNAL (*arg).d = va_arg (*var_args, gpointer); - break; - case GTK_TYPE_ARGS: - GTK_VALUE_ARGS (*arg).n_args = va_arg (*var_args, gint); - GTK_VALUE_ARGS (*arg).args = va_arg (*var_args, GtkArg*); - break; - case GTK_TYPE_FOREIGN: - GTK_VALUE_FOREIGN (*arg).data = va_arg (*var_args, gpointer); - GTK_VALUE_FOREIGN (*arg).notify = va_arg (*var_args, GtkDestroyNotify); - break; - case GTK_TYPE_CALLBACK: - GTK_VALUE_CALLBACK (*arg).marshal = va_arg (*var_args, GtkCallbackMarshal); - GTK_VALUE_CALLBACK (*arg).data = va_arg (*var_args, gpointer); - GTK_VALUE_CALLBACK (*arg).notify = va_arg (*var_args, GtkDestroyNotify); - break; - case GTK_TYPE_C_CALLBACK: - GTK_VALUE_C_CALLBACK (*arg).func = va_arg (*var_args, GtkFunction); - GTK_VALUE_C_CALLBACK (*arg).func_data = va_arg (*var_args, gpointer); - break; - - /* we do some extra sanity checking when collecting objects, - * i.e. if the object pointer is not NULL, we check whether we - * actually got an object pointer within the desired class branch. - */ - case GTK_TYPE_OBJECT: - GTK_VALUE_OBJECT (*arg) = va_arg (*var_args, GtkObject*); - if (GTK_VALUE_OBJECT (*arg) != NULL) - { - register GtkObject *object = GTK_VALUE_OBJECT (*arg); - - if (object->klass == NULL) - error_msg = g_strconcat ("invalid unclassed object pointer for argument type `", - gtk_type_name (arg->type), - "'", - NULL); - else if (!gtk_type_is_a (GTK_OBJECT_TYPE (object), arg->type)) - error_msg = g_strconcat ("invalid object `", - gtk_type_name (GTK_OBJECT_TYPE (object)), - "' for argument type `", - gtk_type_name (arg->type), - "'", - NULL); - } - break; - - default: - error_msg = g_strconcat ("unsupported argument type `", - gtk_type_name (arg->type), - "'", - NULL); - break; - } - - return error_msg; -} +#define GTK_ARG_COLLECT_VALUE(_ft, arg, var_args, _error) \ +G_STMT_START { \ + GtkType fundamental_type = _ft; \ + gchar *error_msg; \ + \ + error_msg = NULL; \ + switch (fundamental_type) \ + { \ + case GTK_TYPE_INVALID: \ + error_msg = g_strdup ("invalid untyped argument"); \ + break; \ + \ + case GTK_TYPE_NONE: \ + /* we just ignore this type, since it arithmetically just requires \ + * us to not move the var_args pointer any further. callers need to \ + * check for the validity of GTK_TYPE_NONE themselves. \ + * \ + * error_msg = g_strdup ("invalid argument type `void'"); \ + */ \ + break; \ + \ + /* everything smaller than an int is guarranteed to be \ + * passed as an int \ + */ \ + case GTK_TYPE_CHAR: \ + GTK_VALUE_CHAR (*arg) = va_arg (var_args, gint); \ + break; \ + case GTK_TYPE_UCHAR: \ + GTK_VALUE_UCHAR (*arg) = va_arg (var_args, guint); \ + break; \ + case GTK_TYPE_BOOL: \ + GTK_VALUE_BOOL (*arg) = va_arg (var_args, gint); \ + break; \ + case GTK_TYPE_INT: \ + GTK_VALUE_INT (*arg) = va_arg (var_args, gint); \ + break; \ + case GTK_TYPE_UINT: \ + GTK_VALUE_UINT (*arg) = va_arg (var_args, guint); \ + break; \ + case GTK_TYPE_ENUM: \ + GTK_VALUE_ENUM (*arg) = va_arg (var_args, gint); \ + break; \ + case GTK_TYPE_FLAGS: \ + GTK_VALUE_FLAGS (*arg) = va_arg (var_args, guint); \ + break; \ + \ + /* we collect longs as glongs since they differ in size with \ + * integers on some platforms \ + */ \ + case GTK_TYPE_LONG: \ + GTK_VALUE_LONG (*arg) = va_arg (var_args, glong); \ + break; \ + case GTK_TYPE_ULONG: \ + GTK_VALUE_ULONG (*arg) = va_arg (var_args, gulong); \ + break; \ + \ + /* floats are always passed as doubles \ + */ \ + case GTK_TYPE_FLOAT: \ + /* GTK_VALUE_FLOAT (*arg) = va_arg (var_args, gfloat); */ \ + GTK_VALUE_FLOAT (*arg) = va_arg (var_args, gdouble); \ + break; \ + case GTK_TYPE_DOUBLE: \ + GTK_VALUE_DOUBLE (*arg) = va_arg (var_args, gdouble); \ + break; \ + \ + /* collect pointer values \ + */ \ + case GTK_TYPE_STRING: \ + GTK_VALUE_STRING (*arg) = va_arg (var_args, gchar*); \ + break; \ + case GTK_TYPE_POINTER: \ + GTK_VALUE_POINTER (*arg) = va_arg (var_args, gpointer); \ + break; \ + case GTK_TYPE_BOXED: \ + GTK_VALUE_BOXED (*arg) = va_arg (var_args, gpointer); \ + break; \ + \ + /* structured types \ + */ \ + case GTK_TYPE_SIGNAL: \ + GTK_VALUE_SIGNAL (*arg).f = va_arg (var_args, GtkSignalFunc); \ + GTK_VALUE_SIGNAL (*arg).d = va_arg (var_args, gpointer); \ + break; \ + case GTK_TYPE_ARGS: \ + GTK_VALUE_ARGS (*arg).n_args = va_arg (var_args, gint); \ + GTK_VALUE_ARGS (*arg).args = va_arg (var_args, GtkArg*); \ + break; \ + case GTK_TYPE_FOREIGN: \ + GTK_VALUE_FOREIGN (*arg).data = va_arg (var_args, gpointer); \ + GTK_VALUE_FOREIGN (*arg).notify = va_arg (var_args, GtkDestroyNotify); \ + break; \ + case GTK_TYPE_CALLBACK: \ + GTK_VALUE_CALLBACK (*arg).marshal = va_arg (var_args, GtkCallbackMarshal); \ + GTK_VALUE_CALLBACK (*arg).data = va_arg (var_args, gpointer); \ + GTK_VALUE_CALLBACK (*arg).notify = va_arg (var_args, GtkDestroyNotify); \ + break; \ + case GTK_TYPE_C_CALLBACK: \ + GTK_VALUE_C_CALLBACK (*arg).func = va_arg (var_args, GtkFunction); \ + GTK_VALUE_C_CALLBACK (*arg).func_data = va_arg (var_args, gpointer); \ + break; \ + \ + /* we do some extra sanity checking when collecting objects, \ + * i.e. if the object pointer is not NULL, we check whether we \ + * actually got an object pointer within the desired class branch. \ + */ \ + case GTK_TYPE_OBJECT: \ + GTK_VALUE_OBJECT (*arg) = va_arg (var_args, GtkObject*); \ + if (GTK_VALUE_OBJECT (*arg) != NULL) \ + { \ + register GtkObject *object = GTK_VALUE_OBJECT (*arg); \ + \ + if (object->klass == NULL) \ + error_msg = g_strconcat ("invalid unclassed object pointer for argument type `", \ + gtk_type_name (arg->type), \ + "'", \ + NULL); \ + else if (!gtk_type_is_a (GTK_OBJECT_TYPE (object), arg->type)) \ + error_msg = g_strconcat ("invalid object `", \ + gtk_type_name (GTK_OBJECT_TYPE (object)), \ + "' for argument type `", \ + gtk_type_name (arg->type), \ + "'", \ + NULL); \ + } \ + break; \ + \ + default: \ + error_msg = g_strconcat ("unsupported argument type `", \ + gtk_type_name (arg->type), \ + "'", \ + NULL); \ + break; \ + } \ + \ + _error = error_msg; /* return error_msg; */ \ +} G_STMT_END |