nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* GLIB-GenMarshal - Marshaller generator for GObject library
2 * Copyright (C) 2000-2001 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 */
17  
18 #include "config.h"
19  
20 #include <stdlib.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26  
27 #include <glib/gstdio.h>
28  
29 #undef G_LOG_DOMAIN
30 #define G_LOG_DOMAIN "GLib-Genmarshal"
31 #include <glib.h>
32 #include <glib/gprintf.h>
33  
34 #ifdef G_OS_UNIX
35 #include <unistd.h>
36 #endif
37 #ifdef G_OS_WIN32
38 #include <io.h>
39 #endif
40  
41 /* --- defines --- */
42 #define PRG_NAME "glib-genmarshal"
43 #define PKG_NAME "GLib"
44 #define PKG_HTTP_HOME "http://www.gtk.org"
45  
46  
47 /* --- typedefs & structures --- */
48 typedef struct
49 {
50 gchar *keyword; /* marhaller list keyword [MY_STRING] */
51 const gchar *sig_name; /* signature name [STRING] */
52 const gchar *ctype; /* C type name [gchar*] */
53 const gchar *promoted_ctype; /* promoted C type name [gchar*] */
54 const gchar *getter; /* value getter function [g_value_get_string] */
55 const gchar *box; /* value box function [g_strdup] */
56 const gchar *unbox; /* value unbox function [g_free] */
57 gboolean box_ignores_static; /* Wether the box/unbox functions ignore the static_scope */
58 gboolean box_takes_type; /* Wether the box/unbox functions take a type arg */
59 } InArgument;
60 typedef struct
61 {
62 gchar *keyword; /* marhaller list keyword [MY_STRING] */
63 const gchar *sig_name; /* signature name [STRING] */
64 const gchar *ctype; /* C type name [gchar*] */
65 const gchar *setter; /* value setter function [g_value_set_string] */
66 } OutArgument;
67 typedef struct
68 {
69 gchar *ploc;
70 OutArgument *rarg;
71 GList *args; /* of type InArgument* */
72 } Signature;
73  
74  
75 /* --- prototypes --- */
76 static void parse_args (gint *argc_p,
77 gchar ***argv_p);
78 static void print_blurb (FILE *bout,
79 gboolean print_help);
80  
81  
82 /* --- variables --- */
83 static const GScannerConfig scanner_config_template =
84 {
85 (
86 " \t\r" /* "\n" is statement delimiter */
87 ) /* cset_skip_characters */,
88 (
89 G_CSET_a_2_z
90 "_"
91 G_CSET_A_2_Z
92 ) /* cset_identifier_first */,
93 (
94 G_CSET_a_2_z
95 "_0123456789"
96 G_CSET_A_2_Z
97 ) /* cset_identifier_nth */,
98 ( "#\n" ) /* cpair_comment_single */,
99  
100 FALSE /* case_sensitive */,
101  
102 TRUE /* skip_comment_multi */,
103 TRUE /* skip_comment_single */,
104 TRUE /* scan_comment_multi */,
105 TRUE /* scan_identifier */,
106 FALSE /* scan_identifier_1char */,
107 FALSE /* scan_identifier_NULL */,
108 TRUE /* scan_symbols */,
109 FALSE /* scan_binary */,
110 TRUE /* scan_octal */,
111 TRUE /* scan_float */,
112 TRUE /* scan_hex */,
113 FALSE /* scan_hex_dollar */,
114 TRUE /* scan_string_sq */,
115 TRUE /* scan_string_dq */,
116 TRUE /* numbers_2_int */,
117 FALSE /* int_2_float */,
118 FALSE /* identifier_2_string */,
119 TRUE /* char_2_token */,
120 FALSE /* symbol_2_token */,
121 FALSE /* scope_0_fallback */,
122 };
123 static gchar * const std_marshaller_prefix = "g_cclosure_marshal";
124 static gchar *marshaller_prefix = "g_cclosure_user_marshal";
125 static GHashTable *marshallers = NULL;
126 static FILE *fout = NULL;
127 static gboolean gen_cheader = FALSE;
128 static gboolean gen_cbody = FALSE;
129 static gboolean gen_internal = FALSE;
130 static gboolean gen_valist = FALSE;
131 static gboolean skip_ploc = FALSE;
132 static gboolean std_includes = TRUE;
133 static gint exit_status = 0;
134  
135  
136 /* --- functions --- */
137 static void
138 put_marshal_value_getters (void)
139 {
140 fputs ("\n", fout);
141 fputs ("#ifdef G_ENABLE_DEBUG\n", fout);
142 fputs ("#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)\n", fout);
143 fputs ("#define g_marshal_value_peek_char(v) g_value_get_schar (v)\n", fout);
144 fputs ("#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)\n", fout);
145 fputs ("#define g_marshal_value_peek_int(v) g_value_get_int (v)\n", fout);
146 fputs ("#define g_marshal_value_peek_uint(v) g_value_get_uint (v)\n", fout);
147 fputs ("#define g_marshal_value_peek_long(v) g_value_get_long (v)\n", fout);
148 fputs ("#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)\n", fout);
149 fputs ("#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)\n", fout);
150 fputs ("#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)\n", fout);
151 fputs ("#define g_marshal_value_peek_enum(v) g_value_get_enum (v)\n", fout);
152 fputs ("#define g_marshal_value_peek_flags(v) g_value_get_flags (v)\n", fout);
153 fputs ("#define g_marshal_value_peek_float(v) g_value_get_float (v)\n", fout);
154 fputs ("#define g_marshal_value_peek_double(v) g_value_get_double (v)\n", fout);
155 fputs ("#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)\n", fout);
156 fputs ("#define g_marshal_value_peek_param(v) g_value_get_param (v)\n", fout);
157 fputs ("#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)\n", fout);
158 fputs ("#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)\n", fout);
159 fputs ("#define g_marshal_value_peek_object(v) g_value_get_object (v)\n", fout);
160 fputs ("#define g_marshal_value_peek_variant(v) g_value_get_variant (v)\n", fout);
161 fputs ("#else /* !G_ENABLE_DEBUG */\n", fout);
162 fputs ("/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.\n", fout);
163 fputs (" * Do not access GValues directly in your code. Instead, use the\n", fout);
164 fputs (" * g_value_get_*() functions\n", fout);
165 fputs (" */\n", fout);
166 fputs ("#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int\n", fout);
167 fputs ("#define g_marshal_value_peek_char(v) (v)->data[0].v_int\n", fout);
168 fputs ("#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint\n", fout);
169 fputs ("#define g_marshal_value_peek_int(v) (v)->data[0].v_int\n", fout);
170 fputs ("#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint\n", fout);
171 fputs ("#define g_marshal_value_peek_long(v) (v)->data[0].v_long\n", fout);
172 fputs ("#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong\n", fout);
173 fputs ("#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64\n", fout);
174 fputs ("#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64\n", fout);
175 fputs ("#define g_marshal_value_peek_enum(v) (v)->data[0].v_long\n", fout);
176 fputs ("#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong\n", fout);
177 fputs ("#define g_marshal_value_peek_float(v) (v)->data[0].v_float\n", fout);
178 fputs ("#define g_marshal_value_peek_double(v) (v)->data[0].v_double\n", fout);
179 fputs ("#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer\n", fout);
180 fputs ("#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer\n", fout);
181 fputs ("#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer\n", fout);
182 fputs ("#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer\n", fout);
183 fputs ("#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer\n", fout);
184 fputs ("#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer\n", fout);
185 fputs ("#endif /* !G_ENABLE_DEBUG */\n", fout);
186 fputs ("\n", fout);
187 }
188  
189 static gboolean
190 complete_in_arg (InArgument *iarg)
191 {
192 static const InArgument args[] = {
193 /* keyword sig_name ctype promoted getter */
194 { "VOID", "VOID", "void", "void", NULL, },
195 { "BOOLEAN", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
196 { "CHAR", "CHAR", "gchar", "gint", "g_marshal_value_peek_char", },
197 { "UCHAR", "UCHAR", "guchar", "guint", "g_marshal_value_peek_uchar", },
198 { "INT", "INT", "gint", "gint", "g_marshal_value_peek_int", },
199 { "UINT", "UINT", "guint", "guint", "g_marshal_value_peek_uint", },
200 { "LONG", "LONG", "glong", "glong", "g_marshal_value_peek_long", },
201 { "ULONG", "ULONG", "gulong", "gulong", "g_marshal_value_peek_ulong", },
202 { "INT64", "INT64", "gint64", "gint64", "g_marshal_value_peek_int64", },
203 { "UINT64", "UINT64", "guint64", "guint64", "g_marshal_value_peek_uint64", },
204 { "ENUM", "ENUM", "gint", "gint", "g_marshal_value_peek_enum", },
205 { "FLAGS", "FLAGS", "guint", "guint", "g_marshal_value_peek_flags", },
206 { "FLOAT", "FLOAT", "gfloat", "gdouble", "g_marshal_value_peek_float", },
207 { "DOUBLE", "DOUBLE", "gdouble", "gdouble", "g_marshal_value_peek_double", },
208 { "STRING", "STRING", "gpointer", "gpointer", "g_marshal_value_peek_string", "g_strdup", "g_free"},
209 { "PARAM", "PARAM", "gpointer", "gpointer", "g_marshal_value_peek_param", "g_param_spec_ref", "g_param_spec_unref"},
210 { "BOXED", "BOXED", "gpointer", "gpointer", "g_marshal_value_peek_boxed", "g_boxed_copy", "g_boxed_free", FALSE, TRUE},
211 { "POINTER", "POINTER", "gpointer", "gpointer", "g_marshal_value_peek_pointer", },
212 { "OBJECT", "OBJECT", "gpointer", "gpointer", "g_marshal_value_peek_object", "g_object_ref", "g_object_unref", TRUE},
213 { "VARIANT", "VARIANT", "gpointer", "gpointer", "g_marshal_value_peek_variant", "g_variant_ref_sink", "g_variant_unref"},
214 /* deprecated: */
215 { "NONE", "VOID", "void", "void", NULL, },
216 { "BOOL", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
217 };
218 guint i;
219  
220 g_return_val_if_fail (iarg != NULL, FALSE);
221  
222 for (i = 0; i < G_N_ELEMENTS (args); i++)
223 if (strcmp (args[i].keyword, iarg->keyword) == 0)
224 {
225 iarg->sig_name = args[i].sig_name;
226 iarg->ctype = args[i].ctype;
227 iarg->promoted_ctype = args[i].promoted_ctype;
228 iarg->getter = args[i].getter;
229 iarg->box = args[i].box;
230 iarg->unbox = args[i].unbox;
231 iarg->box_ignores_static = args[i].box_ignores_static;
232 iarg->box_takes_type = args[i].box_takes_type;
233  
234 return TRUE;
235 }
236 return FALSE;
237 }
238  
239 static gboolean
240 complete_out_arg (OutArgument *oarg)
241 {
242 static const OutArgument args[] = {
243 /* keyword sig_name ctype setter */
244 { "VOID", "VOID", "void", NULL, },
245 { "BOOLEAN", "BOOLEAN", "gboolean", "g_value_set_boolean", },
246 { "CHAR", "CHAR", "gchar", "g_value_set_char", },
247 { "UCHAR", "UCHAR", "guchar", "g_value_set_uchar", },
248 { "INT", "INT", "gint", "g_value_set_int", },
249 { "UINT", "UINT", "guint", "g_value_set_uint", },
250 { "LONG", "LONG", "glong", "g_value_set_long", },
251 { "ULONG", "ULONG", "gulong", "g_value_set_ulong", },
252 { "INT64", "INT64", "gint64", "g_value_set_int64", },
253 { "UINT64", "UINT64", "guint64", "g_value_set_uint64", },
254 { "ENUM", "ENUM", "gint", "g_value_set_enum", },
255 { "FLAGS", "FLAGS", "guint", "g_value_set_flags", },
256 { "FLOAT", "FLOAT", "gfloat", "g_value_set_float", },
257 { "DOUBLE", "DOUBLE", "gdouble", "g_value_set_double", },
258 { "STRING", "STRING", "gchar*", "g_value_take_string", },
259 { "PARAM", "PARAM", "GParamSpec*", "g_value_take_param", },
260 { "BOXED", "BOXED", "gpointer", "g_value_take_boxed", },
261 { "POINTER", "POINTER", "gpointer", "g_value_set_pointer", },
262 { "OBJECT", "OBJECT", "GObject*", "g_value_take_object", },
263 { "VARIANT", "VARIANT", "GVariant*", "g_value_take_variant", },
264 /* deprecated: */
265 { "NONE", "VOID", "void", NULL, },
266 { "BOOL", "BOOLEAN", "gboolean", "g_value_set_boolean", },
267 };
268 guint i;
269  
270 g_return_val_if_fail (oarg != NULL, FALSE);
271  
272 for (i = 0; i < G_N_ELEMENTS (args); i++)
273 if (strcmp (args[i].keyword, oarg->keyword) == 0)
274 {
275 oarg->sig_name = args[i].sig_name;
276 oarg->ctype = args[i].ctype;
277 oarg->setter = args[i].setter;
278  
279 return TRUE;
280 }
281 return FALSE;
282 }
283  
284 static const gchar*
285 pad (const gchar *string)
286 {
287 #define PAD_LENGTH 12
288 static gchar *buffer = NULL;
289 gint i;
290  
291 g_return_val_if_fail (string != NULL, NULL);
292  
293 if (!buffer)
294 buffer = g_new (gchar, PAD_LENGTH + 1);
295  
296 /* paranoid check */
297 if (strlen (string) >= PAD_LENGTH)
298 {
299 g_free (buffer);
300 buffer = g_strdup_printf ("%s ", string);
301 g_warning ("overfull string (%u bytes) for padspace",
302 (guint) strlen (string));
303 exit_status |= 2;
304  
305 return buffer;
306 }
307  
308 for (i = 0; i < PAD_LENGTH; i++)
309 {
310 gboolean done = *string == 0;
311  
312 buffer[i] = done ? ' ' : *string++;
313 }
314 buffer[i] = 0;
315  
316 return buffer;
317 }
318  
319 static const gchar*
320 indent (guint n_spaces)
321 {
322 static gchar *buffer = NULL;
323 static guint blength = 0;
324  
325 if (blength <= n_spaces)
326 {
327 blength = n_spaces + 1;
328 g_free (buffer);
329 buffer = g_new (gchar, blength);
330 }
331 memset (buffer, ' ', n_spaces);
332 buffer[n_spaces] = 0;
333  
334 return buffer;
335 }
336  
337 static void
338 generate_marshal (const gchar *signame,
339 Signature *sig)
340 {
341 guint ind, a;
342 GList *node;
343 gchar *tmp = g_strconcat (marshaller_prefix, "_", signame, NULL);
344 gboolean have_std_marshaller = FALSE;
345  
346 /* here we have to make sure a marshaller named <marshaller_prefix>_<signame>
347 * exists. we might have put it out already, can revert to a standard
348 * marshaller provided by glib, or need to generate one.
349 */
350  
351 if (g_hash_table_lookup (marshallers, tmp))
352 {
353 /* done, marshaller already generated */
354 g_free (tmp);
355 return;
356 }
357 else
358 {
359 /* need to alias/generate marshaller, register name */
360 g_hash_table_insert (marshallers, tmp, tmp);
361 }
362  
363 /* can we revert to a standard marshaller? */
364 if (std_includes)
365 {
366 tmp = g_strconcat (std_marshaller_prefix, "_", signame, NULL);
367 have_std_marshaller = g_hash_table_lookup (marshallers, tmp) != NULL;
368 g_free (tmp);
369 }
370  
371 /* GValue marshaller */
372 if (gen_cheader && have_std_marshaller)
373 {
374 g_fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, signame, std_marshaller_prefix, signame);
375 }
376 if (gen_cheader && !have_std_marshaller)
377 {
378 ind = g_fprintf (fout, gen_internal ? "G_GNUC_INTERNAL " : "extern ");
379 ind += g_fprintf (fout, "void ");
380 ind += g_fprintf (fout, "%s_%s (", marshaller_prefix, signame);
381 g_fprintf (fout, "GClosure *closure,\n");
382 g_fprintf (fout, "%sGValue *return_value,\n", indent (ind));
383 g_fprintf (fout, "%sguint n_param_values,\n", indent (ind));
384 g_fprintf (fout, "%sconst GValue *param_values,\n", indent (ind));
385 g_fprintf (fout, "%sgpointer invocation_hint,\n", indent (ind));
386 g_fprintf (fout, "%sgpointer marshal_data);\n",
387 indent (ind));
388 }
389 if (gen_cbody && !have_std_marshaller)
390 {
391 /* cfile marshal header */
392 g_fprintf (fout, "void\n");
393 ind = g_fprintf (fout, "%s_%s (", marshaller_prefix, signame);
394 g_fprintf (fout, "GClosure *closure,\n");
395 g_fprintf (fout, "%sGValue *return_value G_GNUC_UNUSED,\n", indent (ind));
396 g_fprintf (fout, "%sguint n_param_values,\n", indent (ind));
397 g_fprintf (fout, "%sconst GValue *param_values,\n", indent (ind));
398 g_fprintf (fout, "%sgpointer invocation_hint G_GNUC_UNUSED,\n", indent (ind));
399 g_fprintf (fout, "%sgpointer marshal_data)\n", indent (ind));
400 g_fprintf (fout, "{\n");
401  
402 /* cfile GMarshalFunc typedef */
403 ind = g_fprintf (fout, " typedef %s (*GMarshalFunc_%s) (", sig->rarg->ctype, signame);
404 g_fprintf (fout, "%s data1,\n", pad ("gpointer"));
405 for (a = 1, node = sig->args; node; node = node->next)
406 {
407 InArgument *iarg = node->data;
408  
409 if (iarg->getter)
410 g_fprintf (fout, "%s%s arg_%d,\n", indent (ind), pad (iarg->ctype), a++);
411 }
412 g_fprintf (fout, "%s%s data2);\n", indent (ind), pad ("gpointer"));
413  
414 /* cfile marshal variables */
415 g_fprintf (fout, " GMarshalFunc_%s callback;\n", signame);
416 g_fprintf (fout, " GCClosure *cc = (GCClosure*) closure;\n");
417 g_fprintf (fout, " gpointer data1, data2;\n");
418 if (sig->rarg->setter)
419 g_fprintf (fout, " %s v_return;\n", sig->rarg->ctype);
420  
421 if (sig->args || sig->rarg->setter)
422 {
423 g_fprintf (fout, "\n");
424  
425 if (sig->rarg->setter)
426 g_fprintf (fout, " g_return_if_fail (return_value != NULL);\n");
427 if (sig->args)
428 {
429 for (a = 0, node = sig->args; node; node = node->next)
430 {
431 InArgument *iarg = node->data;
432  
433 if (iarg->getter)
434 a++;
435 }
436 g_fprintf (fout, " g_return_if_fail (n_param_values == %u);\n", 1 + a);
437 }
438 }
439  
440 /* cfile marshal data1, data2 and callback setup */
441 g_fprintf (fout, "\n");
442 g_fprintf (fout, " if (G_CCLOSURE_SWAP_DATA (closure))\n {\n");
443 g_fprintf (fout, " data1 = closure->data;\n");
444 g_fprintf (fout, " data2 = g_value_peek_pointer (param_values + 0);\n");
445 g_fprintf (fout, " }\n else\n {\n");
446 g_fprintf (fout, " data1 = g_value_peek_pointer (param_values + 0);\n");
447 g_fprintf (fout, " data2 = closure->data;\n");
448 g_fprintf (fout, " }\n");
449 g_fprintf (fout, " callback = (GMarshalFunc_%s) (marshal_data ? marshal_data : cc->callback);\n", signame);
450  
451 /* cfile marshal callback action */
452 g_fprintf (fout, "\n");
453 ind = g_fprintf (fout, " %s callback (", sig->rarg->setter ? " v_return =" : "");
454 g_fprintf (fout, "data1,\n");
455 for (a = 1, node = sig->args; node; node = node->next)
456 {
457 InArgument *iarg = node->data;
458  
459 if (iarg->getter)
460 g_fprintf (fout, "%s%s (param_values + %d),\n", indent (ind), iarg->getter, a++);
461 }
462 g_fprintf (fout, "%sdata2);\n", indent (ind));
463  
464 /* cfile marshal return value storage */
465 if (sig->rarg->setter)
466 {
467 g_fprintf (fout, "\n");
468 g_fprintf (fout, " %s (return_value, v_return);\n", sig->rarg->setter);
469 }
470  
471 /* cfile marshal footer */
472 g_fprintf (fout, "}\n");
473 }
474  
475  
476 /* vararg marshaller */
477 if (gen_cheader && gen_valist && have_std_marshaller)
478 {
479 g_fprintf (fout, "#define %s_%sv\t%s_%sv\n", marshaller_prefix, signame, std_marshaller_prefix, signame);
480 }
481 if (gen_cheader && gen_valist && !have_std_marshaller)
482 {
483 ind = g_fprintf (fout, gen_internal ? "G_GNUC_INTERNAL " : "extern ");
484 ind += g_fprintf (fout, "void ");
485 ind += g_fprintf (fout, "%s_%sv (", marshaller_prefix, signame);
486 g_fprintf (fout, "GClosure *closure,\n");
487 g_fprintf (fout, "%sGValue *return_value,\n", indent (ind));
488 g_fprintf (fout, "%sgpointer instance,\n", indent (ind));
489 g_fprintf (fout, "%sva_list args,\n", indent (ind));
490 g_fprintf (fout, "%sgpointer marshal_data,\n", indent (ind));
491 g_fprintf (fout, "%sint n_params,\n", indent (ind));
492 g_fprintf (fout, "%sGType *param_types);\n", indent (ind));
493 }
494 if (gen_cbody && gen_valist && !have_std_marshaller)
495 {
496 gint i;
497 gboolean has_arg;
498  
499 g_fprintf (fout, "void\n");
500 ind = g_fprintf (fout, "%s_%sv (", marshaller_prefix, signame);
501 g_fprintf (fout, "GClosure *closure,\n");
502 g_fprintf (fout, "%sGValue *return_value,\n", indent (ind));
503 g_fprintf (fout, "%sgpointer instance,\n", indent (ind));
504 g_fprintf (fout, "%sva_list args,\n", indent (ind));
505 g_fprintf (fout, "%sgpointer marshal_data,\n", indent (ind));
506 g_fprintf (fout, "%sint n_params,\n", indent (ind));
507 g_fprintf (fout, "%sGType *param_types)\n", indent (ind));
508 g_fprintf (fout, "{\n");
509  
510 ind = g_fprintf (fout, " typedef %s (*GMarshalFunc_%s) (", sig->rarg->ctype, signame);
511 g_fprintf (fout, "%s instance", pad ("gpointer"));
512 for (a = 0, node = sig->args; node; node = node->next)
513 {
514 InArgument *iarg = node->data;
515  
516 if (iarg->getter)
517 g_fprintf (fout, ",\n%s%s arg_%d", indent (ind), pad (iarg->ctype), a++);
518 }
519 g_fprintf (fout, ",\n%s%s data);\n", indent (ind), pad ("gpointer"));
520 g_fprintf (fout, " GCClosure *cc = (GCClosure*) closure;\n");
521 g_fprintf (fout, " gpointer data1, data2;\n");
522 g_fprintf (fout, " GMarshalFunc_%s callback;\n", signame);
523 has_arg = FALSE;
524  
525 i = 0;
526 for (node = sig->args; node; node = node->next)
527 {
528 InArgument *iarg = node->data;
529  
530 if (iarg->getter)
531 {
532 g_fprintf (fout, " %s arg%i;\n", iarg->ctype, i++);
533 has_arg = TRUE;
534 }
535 }
536 if (has_arg)
537 g_fprintf (fout, " va_list args_copy;\n");
538  
539 if (sig->rarg->setter)
540 g_fprintf (fout, " %s v_return;\n", sig->rarg->ctype);
541  
542 if (sig->rarg->setter)
543 {
544 g_fprintf (fout, "\n");
545 g_fprintf (fout, " g_return_if_fail (return_value != NULL);\n");
546 }
547  
548 /* cfile marshal data1, data2 and callback setup */
549 if (has_arg)
550 {
551 g_fprintf (fout, "\n");
552 g_fprintf (fout, " G_VA_COPY (args_copy, args);\n");
553 i = 0;
554 for (node = sig->args; node; node = node->next)
555 {
556 InArgument *iarg = node->data;
557  
558 if (iarg->getter)
559 {
560 g_fprintf (fout, " arg%i = (%s) va_arg (args_copy, %s);\n",
561 i, iarg->ctype, iarg->promoted_ctype);
562  
563 if (iarg->box != NULL)
564 {
565 g_fprintf (fout, " if (");
566 if (!iarg->box_ignores_static)
567 g_fprintf (fout, "(param_types[%i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && ", i);
568 g_fprintf (fout, "arg%i != NULL)\n ", i);
569 if (iarg->box_takes_type)
570 g_fprintf (fout,
571 " arg%i = %s (param_types[%i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg%i);\n",
572 i, iarg->box, i, i);
573 else
574 g_fprintf (fout,
575 " arg%i = %s (arg%i);\n",
576 i, iarg->box, i);
577 }
578 }
579 i++;
580 }
581 g_fprintf (fout, " va_end (args_copy);\n");
582 }
583  
584 g_fprintf (fout, "\n");
585 /* cfile marshal data1, data2 and callback setup */
586 g_fprintf (fout, " if (G_CCLOSURE_SWAP_DATA (closure))\n {\n");
587 g_fprintf (fout, " data1 = closure->data;\n");
588 g_fprintf (fout, " data2 = instance;\n");
589 g_fprintf (fout, " }\n else\n {\n");
590 g_fprintf (fout, " data1 = instance;\n");
591 g_fprintf (fout, " data2 = closure->data;\n");
592 g_fprintf (fout, " }\n");
593 g_fprintf (fout, " callback = (GMarshalFunc_%s) (marshal_data ? marshal_data : cc->callback);\n", signame);
594  
595 /* cfile marshal callback action */
596 g_fprintf (fout, "\n");
597 ind = g_fprintf (fout, " %s callback (", sig->rarg->setter ? " v_return =" : "");
598 g_fprintf (fout, "data1");
599  
600 i = 0;
601 for (node = sig->args; node; node = node->next)
602 {
603 InArgument *iarg = node->data;
604  
605 if (iarg->getter)
606 g_fprintf (fout, ",\n%sarg%i", indent (ind), i++);
607 }
608 g_fprintf (fout, ",\n%sdata2);\n", indent (ind));
609  
610 i = 0;
611 for (node = sig->args; node; node = node->next)
612 {
613 InArgument *iarg = node->data;
614  
615 if (iarg->unbox)
616 {
617 g_fprintf (fout, " if (");
618 if (!iarg->box_ignores_static)
619 g_fprintf (fout, "(param_types[%i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && ", i);
620 g_fprintf (fout, "arg%i != NULL)\n ", i);
621 if (iarg->box_takes_type)
622 g_fprintf (fout,
623 " %s (param_types[%i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg%i);\n",
624 iarg->unbox, i, i);
625 else
626 g_fprintf (fout,
627 " %s (arg%i);\n",
628 iarg->unbox, i);
629 }
630 i++;
631 }
632  
633 /* cfile marshal return value storage */
634 if (sig->rarg->setter)
635 {
636 g_fprintf (fout, "\n");
637 g_fprintf (fout, " %s (return_value, v_return);\n", sig->rarg->setter);
638 }
639  
640 g_fprintf (fout, "}\n\n");
641 }
642 }
643  
644 static void
645 process_signature (Signature *sig)
646 {
647 gchar *pname, *sname, *tmp;
648 GList *node;
649  
650 /* lookup and complete info on arguments */
651 if (!complete_out_arg (sig->rarg))
652 {
653 g_warning ("unknown type: %s", sig->rarg->keyword);
654 exit_status |= 1;
655 return;
656 }
657 for (node = sig->args; node; node = node->next)
658 {
659 InArgument *iarg = node->data;
660  
661 if (!complete_in_arg (iarg))
662 {
663 g_warning ("unknown type: %s", iarg->keyword);
664 exit_status |= 1;
665 return;
666 }
667 }
668  
669 /* construct requested marshaller name and technical marshaller name */
670 pname = g_strconcat (sig->rarg->keyword, "_", NULL);
671 sname = g_strconcat (sig->rarg->sig_name, "_", NULL);
672 for (node = sig->args; node; node = node->next)
673 {
674 InArgument *iarg = node->data;
675 gchar *tmp;
676  
677 tmp = sname;
678 sname = g_strconcat (tmp, "_", iarg->sig_name, NULL);
679 g_free (tmp);
680 tmp = pname;
681 pname = g_strconcat (tmp, "_", iarg->keyword, NULL);
682 g_free (tmp);
683 }
684  
685 /* introductionary comment */
686 g_fprintf (fout, "\n/* %s", sig->rarg->keyword);
687 for (node = sig->args; node; node = node->next)
688 {
689 InArgument *iarg = node->data;
690  
691 g_fprintf (fout, "%c%s", node->prev ? ',' : ':', iarg->keyword);
692 }
693 if (!skip_ploc)
694 g_fprintf (fout, " (%s)", sig->ploc);
695 g_fprintf (fout, " */\n");
696  
697 /* ensure technical marshaller exists (<marshaller_prefix>_<sname>) */
698 generate_marshal (sname, sig);
699  
700 /* put out marshaller alias for requested name if required (<marshaller_prefix>_<pname>) */
701 tmp = g_strconcat (marshaller_prefix, "_", pname, NULL);
702 if (gen_cheader && !g_hash_table_lookup (marshallers, tmp))
703 {
704 g_fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, pname, marshaller_prefix, sname);
705  
706 g_hash_table_insert (marshallers, tmp, tmp);
707 }
708 else
709 g_free (tmp);
710  
711 g_free (pname);
712 g_free (sname);
713 }
714  
715 static InArgument*
716 new_in_arg (const gchar *pname)
717 {
718 InArgument *iarg = g_new0 (InArgument, 1);
719  
720 iarg->keyword = g_strdup (pname);
721  
722 return iarg;
723 }
724  
725 static OutArgument*
726 new_out_arg (const gchar *pname)
727 {
728 OutArgument *oarg = g_new0 (OutArgument, 1);
729  
730 oarg->keyword = g_strdup (pname);
731  
732 return oarg;
733 }
734  
735 static guint
736 parse_line (GScanner *scanner,
737 Signature *sig)
738 {
739 /* parse identifier for return value */
740 if (g_scanner_get_next_token (scanner) != G_TOKEN_IDENTIFIER)
741 return G_TOKEN_IDENTIFIER;
742 sig->rarg = new_out_arg (scanner->value.v_identifier);
743  
744 /* keep a note on the location */
745 sig->ploc = g_strdup_printf ("%s:%u", scanner->input_name, scanner->line);
746  
747 /* expect ':' */
748 if (g_scanner_get_next_token (scanner) != ':')
749 return ':';
750  
751 /* parse first argument */
752 if (g_scanner_get_next_token (scanner) != G_TOKEN_IDENTIFIER)
753 return G_TOKEN_IDENTIFIER;
754 sig->args = g_list_append (sig->args, new_in_arg (scanner->value.v_identifier));
755  
756 /* parse rest of argument list */
757 while (g_scanner_peek_next_token (scanner) == ',')
758 {
759 /* eat comma */
760 g_scanner_get_next_token (scanner);
761  
762 /* parse arg identifier */
763 if (g_scanner_get_next_token (scanner) != G_TOKEN_IDENTIFIER)
764 return G_TOKEN_IDENTIFIER;
765 sig->args = g_list_append (sig->args, new_in_arg (scanner->value.v_identifier));
766 }
767  
768 /* expect end of line, done */
769 if (g_scanner_get_next_token (scanner) != '\n')
770 return '\n';
771  
772 /* success */
773 return G_TOKEN_NONE;
774 }
775  
776 static gboolean
777 string_key_destroy (gpointer key,
778 gpointer value,
779 gpointer user_data)
780 {
781 g_free (key);
782  
783 return TRUE;
784 }
785  
786 int
787 main (int argc,
788 char *argv[])
789 {
790 const gchar *gobject_marshallers[] = {
791 #include "gmarshal.strings"
792 };
793 GScanner *scanner;
794 GSList *slist, *files = NULL;
795 gint i;
796  
797 /* parse args and do fast exits */
798 parse_args (&argc, &argv);
799  
800 /* list input files */
801 for (i = 1; i < argc; i++)
802 files = g_slist_prepend (files, argv[i]);
803 if (files)
804 files = g_slist_reverse (files);
805 else
806 files = g_slist_prepend (files, "/dev/stdin");
807  
808 /* setup auxiliary structs */
809 scanner = g_scanner_new (&scanner_config_template);
810 fout = stdout;
811 marshallers = g_hash_table_new (g_str_hash, g_str_equal);
812  
813 /* add standard marshallers of the GObject library */
814 if (std_includes)
815 for (i = 0; i < G_N_ELEMENTS (gobject_marshallers); i++)
816 {
817 gchar *tmp = g_strdup (gobject_marshallers[i]);
818  
819 g_hash_table_insert (marshallers, tmp, tmp);
820 }
821  
822 /* put out initial heading */
823 g_fprintf (fout, "\n");
824  
825 if (gen_cheader && std_includes)
826 {
827 g_fprintf (fout, "#ifndef __%s_MARSHAL_H__\n", marshaller_prefix);
828 g_fprintf (fout, "#define __%s_MARSHAL_H__\n\n", marshaller_prefix);
829 }
830  
831 if ((gen_cheader || gen_cbody) && std_includes)
832 g_fprintf (fout, "#include\t<glib-object.h>\n\n");
833  
834 if (gen_cheader)
835 g_fprintf (fout, "G_BEGIN_DECLS\n");
836  
837 /* generate necessary preprocessor directives */
838 if (gen_cbody)
839 put_marshal_value_getters ();
840  
841 /* process input files */
842 for (slist = files; slist; slist = slist->next)
843 {
844 gchar *file = slist->data;
845 gint fd;
846  
847 if (strcmp (file, "/dev/stdin") == 0)
848 /* Mostly for Win32. This is equivalent to opening /dev/stdin */
849 fd = dup (0);
850 else
851 fd = g_open (file, O_RDONLY, 0);
852  
853 if (fd < 0)
854 {
855 g_warning ("failed to open \"%s\": %s", file, g_strerror (errno));
856 exit_status |= 1;
857 continue;
858 }
859  
860 /* set file name for error reports */
861 scanner->input_name = file;
862  
863 /* parse & process file */
864 g_scanner_input_file (scanner, fd);
865  
866 /* scanning loop, we parse the input until its end is reached,
867 * or our sub routine came across invalid syntax
868 */
869 do
870 {
871 guint expected_token = G_TOKEN_NONE;
872  
873 switch ((guint) g_scanner_peek_next_token (scanner))
874 {
875 case '\n':
876 /* eat newline and restart */
877 g_scanner_get_next_token (scanner);
878 continue;
879 case G_TOKEN_EOF:
880 /* done */
881 break;
882 default:
883 /* parse and process signatures */
884 {
885 Signature signature = { NULL, NULL, NULL };
886 GList *node;
887  
888 expected_token = parse_line (scanner, &signature);
889  
890 /* once we got a valid signature, process it */
891 if (expected_token == G_TOKEN_NONE)
892 process_signature (&signature);
893  
894 /* clean up signature contents */
895 g_free (signature.ploc);
896 if (signature.rarg)
897 g_free (signature.rarg->keyword);
898 g_free (signature.rarg);
899 for (node = signature.args; node; node = node->next)
900 {
901 InArgument *iarg = node->data;
902  
903 g_free (iarg->keyword);
904 g_free (iarg);
905 }
906 g_list_free (signature.args);
907 }
908 break;
909 }
910  
911 /* bail out on errors */
912 if (expected_token != G_TOKEN_NONE)
913 {
914 g_scanner_unexp_token (scanner, expected_token, "type name", NULL, NULL, NULL, TRUE);
915 exit_status |= 1;
916 break;
917 }
918  
919 g_scanner_peek_next_token (scanner);
920 }
921 while (scanner->next_token != G_TOKEN_EOF);
922  
923 close (fd);
924 }
925  
926 /* put out trailer */
927 if (gen_cheader)
928 {
929 g_fprintf (fout, "\nG_END_DECLS\n");
930  
931 if (std_includes)
932 g_fprintf (fout, "\n#endif /* __%s_MARSHAL_H__ */\n", marshaller_prefix);
933 }
934 g_fprintf (fout, "\n");
935  
936 /* clean up */
937 g_slist_free (files);
938 g_scanner_destroy (scanner);
939 g_hash_table_foreach_remove (marshallers, string_key_destroy, NULL);
940 g_hash_table_destroy (marshallers);
941  
942 return exit_status;
943 }
944  
945 static void
946 parse_args (gint *argc_p,
947 gchar ***argv_p)
948 {
949 guint argc = *argc_p;
950 gchar **argv = *argv_p;
951 guint i, e;
952  
953 for (i = 1; i < argc; i++)
954 {
955 if (strcmp ("--header", argv[i]) == 0)
956 {
957 gen_cheader = TRUE;
958 argv[i] = NULL;
959 }
960 else if (strcmp ("--body", argv[i]) == 0)
961 {
962 gen_cbody = TRUE;
963 argv[i] = NULL;
964 }
965 else if (strcmp ("--skip-source", argv[i]) == 0)
966 {
967 skip_ploc = TRUE;
968 argv[i] = NULL;
969 }
970 else if (strcmp ("--nostdinc", argv[i]) == 0)
971 {
972 std_includes = FALSE;
973 argv[i] = NULL;
974 }
975 else if (strcmp ("--stdinc", argv[i]) == 0)
976 {
977 std_includes = TRUE;
978 argv[i] = NULL;
979 }
980 else if (strcmp ("--internal", argv[i]) == 0)
981 {
982 gen_internal = TRUE;
983 argv[i] = NULL;
984 }
985 else if (strcmp ("--valist-marshallers", argv[i]) == 0)
986 {
987 gen_valist = TRUE;
988 argv[i] = NULL;
989 }
990 else if ((strcmp ("--prefix", argv[i]) == 0) ||
991 (strncmp ("--prefix=", argv[i], 9) == 0))
992 {
993 gchar *equal = argv[i] + 8;
994  
995 if (*equal == '=')
996 marshaller_prefix = equal + 1;
997 else if (i + 1 < argc)
998 {
999 marshaller_prefix = argv[i + 1];
1000 argv[i] = NULL;
1001 i += 1;
1002 }
1003 argv[i] = NULL;
1004 }
1005 else if (strcmp ("-h", argv[i]) == 0 ||
1006 strcmp ("-?", argv[i]) == 0 ||
1007 strcmp ("--help", argv[i]) == 0)
1008 {
1009 print_blurb (stderr, TRUE);
1010 argv[i] = NULL;
1011 exit (0);
1012 }
1013 else if (strcmp ("-v", argv[i]) == 0 ||
1014 strcmp ("--version", argv[i]) == 0)
1015 {
1016 print_blurb (stderr, FALSE);
1017 argv[i] = NULL;
1018 exit (0);
1019 }
1020 else if (strcmp (argv[i], "--g-fatal-warnings") == 0)
1021 {
1022 GLogLevelFlags fatal_mask;
1023  
1024 fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
1025 fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
1026 g_log_set_always_fatal (fatal_mask);
1027  
1028 argv[i] = NULL;
1029 }
1030 }
1031  
1032 e = 0;
1033 for (i = 1; i < argc; i++)
1034 {
1035 if (e)
1036 {
1037 if (argv[i])
1038 {
1039 argv[e++] = argv[i];
1040 argv[i] = NULL;
1041 }
1042 }
1043 else if (!argv[i])
1044 e = i;
1045 }
1046 if (e)
1047 *argc_p = e;
1048 }
1049  
1050 static void
1051 print_blurb (FILE *bout,
1052 gboolean print_help)
1053 {
1054 if (!print_help)
1055 {
1056 g_fprintf (bout, "%s version ", PRG_NAME);
1057 g_fprintf (bout, "%u.%u.%u", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
1058 g_fprintf (bout, "\n");
1059 g_fprintf (bout, "%s comes with ABSOLUTELY NO WARRANTY.\n", PRG_NAME);
1060 g_fprintf (bout, "You may redistribute copies of %s under the terms of\n", PRG_NAME);
1061 g_fprintf (bout, "the GNU General Public License which can be found in the\n");
1062 g_fprintf (bout, "%s source package. Sources, examples and contact\n", PKG_NAME);
1063 g_fprintf (bout, "information are available at %s\n", PKG_HTTP_HOME);
1064 }
1065 else
1066 {
1067 g_fprintf (bout, "Usage:\n");
1068 g_fprintf (bout, " %s [OPTION...] [FILES...]\n\n", PRG_NAME);
1069 g_fprintf (bout, "Help Options:\n");
1070 g_fprintf (bout, " -h, --help Show this help message\n\n");
1071 g_fprintf (bout, "Utility Options:\n");
1072 g_fprintf (bout, " --header Generate C headers\n");
1073 g_fprintf (bout, " --body Generate C code\n");
1074 g_fprintf (bout, " --prefix=string Specify marshaller prefix\n");
1075 g_fprintf (bout, " --skip-source Skip source location comments\n");
1076 g_fprintf (bout, " --stdinc, --nostdinc Include/use standard marshallers\n");
1077 g_fprintf (bout, " --internal Mark generated functions as internal\n");
1078 g_fprintf (bout, " --valist-marshallers Generate va_list marshallers\n");
1079 g_fprintf (bout, " -v, --version Print version informations\n");
1080 g_fprintf (bout, " --g-fatal-warnings Make warnings fatal (abort)\n");
1081 }
1082 }