aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-arg-collector.c
blob: 44b9e2d99b28602a41785b781ab21c45a06b86a7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/* GTK - The GIMP Toolkit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/*
 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

/*
 * included in camel because it is not exported 
 * by gtk
 *
 * Bertrand Guiheneuf <bertrand@helixcode.com>
 */

/* 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 corresponding prototype would be:
 * static inline gchar*
 * gtk_arg_collect_value (GtkArg  *arg,
 *                va_list  var_args);
 */
#define CAMEL_ARG_COLLECT_VALUE(arg, var_args, _error)  \
G_STMT_START { \
  gchar *error_msg; \
  GtkType fundamental_type; \
  \
  fundamental_type = GTK_FUNDAMENTAL_TYPE (arg->type); \
  if (fundamental_type > GTK_TYPE_FUNDAMENTAL_LAST) \
    { \
      fundamental_type = gtk_type_get_varargs_type (fundamental_type); \
      if (!fundamental_type) \
        fundamental_type = GTK_FUNDAMENTAL_TYPE (arg->type); \
    } \
 \
  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