1 /* GLIB-GenMarshal - Marshaller generator for GObject library
2 * Copyright (C) 2000-2001 Red Hat, Inc.
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.
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.
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/>.
24 #include <sys/types.h>
27 #include <glib/gstdio.h>
30 #define G_LOG_DOMAIN "GLib-Genmarshal"
32 #include <glib/gprintf.h>
42 #define PRG_NAME "glib-genmarshal"
43 #define PKG_NAME "GLib"
44 #define PKG_HTTP_HOME "http://www.gtk.org"
47 /* --- typedefs & structures --- */
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 */
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] */
71 GList
*args
; /* of type InArgument* */
75 /* --- prototypes --- */
76 static void parse_args (gint
*argc_p
,
78 static void print_blurb (FILE *bout
,
82 /* --- variables --- */
83 static const GScannerConfig scanner_config_template
=
86 " \t\r" /* "\n" is statement delimiter */
87 ) /* cset_skip_characters */,
92 ) /* cset_identifier_first */,
97 ) /* cset_identifier_nth */,
98 ( "#\n" ) /* cpair_comment_single */,
100 FALSE
/* case_sensitive */,
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 */,
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 */,
123 static gchar
* const std_marshaller_prefix
= "g_cclosure_marshal";
124 static gchar
*marshaller_prefix
= "g_cclosure_user_marshal";
125 static gchar
*output_fn
= NULL
;
126 static gint output_fd
= -1;
127 static gchar
*output_tmpfn
= NULL
;
128 static GHashTable
*marshallers
= NULL
;
129 static FILE *fout
= NULL
;
130 static gboolean gen_cheader
= FALSE
;
131 static gboolean gen_cbody
= FALSE
;
132 static gboolean gen_internal
= FALSE
;
133 static gboolean gen_valist
= FALSE
;
134 static gboolean skip_ploc
= FALSE
;
135 static gboolean std_includes
= TRUE
;
136 static gint exit_status
= 0;
139 /* --- functions --- */
141 put_marshal_value_getters (void)
144 fputs ("#ifdef G_ENABLE_DEBUG\n", fout
);
145 fputs ("#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)\n", fout
);
146 fputs ("#define g_marshal_value_peek_char(v) g_value_get_schar (v)\n", fout
);
147 fputs ("#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)\n", fout
);
148 fputs ("#define g_marshal_value_peek_int(v) g_value_get_int (v)\n", fout
);
149 fputs ("#define g_marshal_value_peek_uint(v) g_value_get_uint (v)\n", fout
);
150 fputs ("#define g_marshal_value_peek_long(v) g_value_get_long (v)\n", fout
);
151 fputs ("#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)\n", fout
);
152 fputs ("#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)\n", fout
);
153 fputs ("#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)\n", fout
);
154 fputs ("#define g_marshal_value_peek_enum(v) g_value_get_enum (v)\n", fout
);
155 fputs ("#define g_marshal_value_peek_flags(v) g_value_get_flags (v)\n", fout
);
156 fputs ("#define g_marshal_value_peek_float(v) g_value_get_float (v)\n", fout
);
157 fputs ("#define g_marshal_value_peek_double(v) g_value_get_double (v)\n", fout
);
158 fputs ("#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)\n", fout
);
159 fputs ("#define g_marshal_value_peek_param(v) g_value_get_param (v)\n", fout
);
160 fputs ("#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)\n", fout
);
161 fputs ("#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)\n", fout
);
162 fputs ("#define g_marshal_value_peek_object(v) g_value_get_object (v)\n", fout
);
163 fputs ("#define g_marshal_value_peek_variant(v) g_value_get_variant (v)\n", fout
);
164 fputs ("#else /* !G_ENABLE_DEBUG */\n", fout
);
165 fputs ("/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.\n", fout
);
166 fputs (" * Do not access GValues directly in your code. Instead, use the\n", fout
);
167 fputs (" * g_value_get_*() functions\n", fout
);
168 fputs (" */\n", fout
);
169 fputs ("#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int\n", fout
);
170 fputs ("#define g_marshal_value_peek_char(v) (v)->data[0].v_int\n", fout
);
171 fputs ("#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint\n", fout
);
172 fputs ("#define g_marshal_value_peek_int(v) (v)->data[0].v_int\n", fout
);
173 fputs ("#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint\n", fout
);
174 fputs ("#define g_marshal_value_peek_long(v) (v)->data[0].v_long\n", fout
);
175 fputs ("#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong\n", fout
);
176 fputs ("#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64\n", fout
);
177 fputs ("#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64\n", fout
);
178 fputs ("#define g_marshal_value_peek_enum(v) (v)->data[0].v_long\n", fout
);
179 fputs ("#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong\n", fout
);
180 fputs ("#define g_marshal_value_peek_float(v) (v)->data[0].v_float\n", fout
);
181 fputs ("#define g_marshal_value_peek_double(v) (v)->data[0].v_double\n", fout
);
182 fputs ("#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer\n", fout
);
183 fputs ("#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer\n", fout
);
184 fputs ("#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer\n", fout
);
185 fputs ("#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer\n", fout
);
186 fputs ("#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer\n", fout
);
187 fputs ("#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer\n", fout
);
188 fputs ("#endif /* !G_ENABLE_DEBUG */\n", fout
);
193 complete_in_arg (InArgument
*iarg
)
195 static const InArgument args
[] = {
196 /* keyword sig_name ctype promoted getter */
197 { "VOID", "VOID", "void", "void", NULL
, },
198 { "BOOLEAN", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
199 { "CHAR", "CHAR", "gchar", "gint", "g_marshal_value_peek_char", },
200 { "UCHAR", "UCHAR", "guchar", "guint", "g_marshal_value_peek_uchar", },
201 { "INT", "INT", "gint", "gint", "g_marshal_value_peek_int", },
202 { "UINT", "UINT", "guint", "guint", "g_marshal_value_peek_uint", },
203 { "LONG", "LONG", "glong", "glong", "g_marshal_value_peek_long", },
204 { "ULONG", "ULONG", "gulong", "gulong", "g_marshal_value_peek_ulong", },
205 { "INT64", "INT64", "gint64", "gint64", "g_marshal_value_peek_int64", },
206 { "UINT64", "UINT64", "guint64", "guint64", "g_marshal_value_peek_uint64", },
207 { "ENUM", "ENUM", "gint", "gint", "g_marshal_value_peek_enum", },
208 { "FLAGS", "FLAGS", "guint", "guint", "g_marshal_value_peek_flags", },
209 { "FLOAT", "FLOAT", "gfloat", "gdouble", "g_marshal_value_peek_float", },
210 { "DOUBLE", "DOUBLE", "gdouble", "gdouble", "g_marshal_value_peek_double", },
211 { "STRING", "STRING", "gpointer", "gpointer", "g_marshal_value_peek_string", "g_strdup", "g_free"},
212 { "PARAM", "PARAM", "gpointer", "gpointer", "g_marshal_value_peek_param", "g_param_spec_ref", "g_param_spec_unref"},
213 { "BOXED", "BOXED", "gpointer", "gpointer", "g_marshal_value_peek_boxed", "g_boxed_copy", "g_boxed_free", FALSE
, TRUE
},
214 { "POINTER", "POINTER", "gpointer", "gpointer", "g_marshal_value_peek_pointer", },
215 { "OBJECT", "OBJECT", "gpointer", "gpointer", "g_marshal_value_peek_object", "g_object_ref", "g_object_unref", TRUE
},
216 { "VARIANT", "VARIANT", "gpointer", "gpointer", "g_marshal_value_peek_variant", "g_variant_ref_sink", "g_variant_unref"},
218 { "NONE", "VOID", "void", "void", NULL
, },
219 { "BOOL", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
223 g_return_val_if_fail (iarg
!= NULL
, FALSE
);
225 for (i
= 0; i
< G_N_ELEMENTS (args
); i
++)
226 if (strcmp (args
[i
].keyword
, iarg
->keyword
) == 0)
228 iarg
->sig_name
= args
[i
].sig_name
;
229 iarg
->ctype
= args
[i
].ctype
;
230 iarg
->promoted_ctype
= args
[i
].promoted_ctype
;
231 iarg
->getter
= args
[i
].getter
;
232 iarg
->box
= args
[i
].box
;
233 iarg
->unbox
= args
[i
].unbox
;
234 iarg
->box_ignores_static
= args
[i
].box_ignores_static
;
235 iarg
->box_takes_type
= args
[i
].box_takes_type
;
243 complete_out_arg (OutArgument
*oarg
)
245 static const OutArgument args
[] = {
246 /* keyword sig_name ctype setter */
247 { "VOID", "VOID", "void", NULL
, },
248 { "BOOLEAN", "BOOLEAN", "gboolean", "g_value_set_boolean", },
249 { "CHAR", "CHAR", "gchar", "g_value_set_char", },
250 { "UCHAR", "UCHAR", "guchar", "g_value_set_uchar", },
251 { "INT", "INT", "gint", "g_value_set_int", },
252 { "UINT", "UINT", "guint", "g_value_set_uint", },
253 { "LONG", "LONG", "glong", "g_value_set_long", },
254 { "ULONG", "ULONG", "gulong", "g_value_set_ulong", },
255 { "INT64", "INT64", "gint64", "g_value_set_int64", },
256 { "UINT64", "UINT64", "guint64", "g_value_set_uint64", },
257 { "ENUM", "ENUM", "gint", "g_value_set_enum", },
258 { "FLAGS", "FLAGS", "guint", "g_value_set_flags", },
259 { "FLOAT", "FLOAT", "gfloat", "g_value_set_float", },
260 { "DOUBLE", "DOUBLE", "gdouble", "g_value_set_double", },
261 { "STRING", "STRING", "gchar*", "g_value_take_string", },
262 { "PARAM", "PARAM", "GParamSpec*", "g_value_take_param", },
263 { "BOXED", "BOXED", "gpointer", "g_value_take_boxed", },
264 { "POINTER", "POINTER", "gpointer", "g_value_set_pointer", },
265 { "OBJECT", "OBJECT", "GObject*", "g_value_take_object", },
266 { "VARIANT", "VARIANT", "GVariant*", "g_value_take_variant", },
268 { "NONE", "VOID", "void", NULL
, },
269 { "BOOL", "BOOLEAN", "gboolean", "g_value_set_boolean", },
273 g_return_val_if_fail (oarg
!= NULL
, FALSE
);
275 for (i
= 0; i
< G_N_ELEMENTS (args
); i
++)
276 if (strcmp (args
[i
].keyword
, oarg
->keyword
) == 0)
278 oarg
->sig_name
= args
[i
].sig_name
;
279 oarg
->ctype
= args
[i
].ctype
;
280 oarg
->setter
= args
[i
].setter
;
288 pad (const gchar
*string
)
290 #define PAD_LENGTH 12
291 static gchar
*buffer
= NULL
;
294 g_return_val_if_fail (string
!= NULL
, NULL
);
297 buffer
= g_new (gchar
, PAD_LENGTH
+ 1);
300 if (strlen (string
) >= PAD_LENGTH
)
303 buffer
= g_strdup_printf ("%s ", string
);
304 g_warning ("overfull string (%u bytes) for padspace",
305 (guint
) strlen (string
));
311 for (i
= 0; i
< PAD_LENGTH
; i
++)
313 gboolean done
= *string
== 0;
315 buffer
[i
] = done
? ' ' : *string
++;
323 indent (guint n_spaces
)
325 static gchar
*buffer
= NULL
;
326 static guint blength
= 0;
328 if (blength
<= n_spaces
)
330 blength
= n_spaces
+ 1;
332 buffer
= g_new (gchar
, blength
);
334 memset (buffer
, ' ', n_spaces
);
335 buffer
[n_spaces
] = 0;
341 generate_marshal (const gchar
*signame
,
346 gchar
*tmp
= g_strconcat (marshaller_prefix
, "_", signame
, NULL
);
347 gboolean have_std_marshaller
= FALSE
;
349 /* here we have to make sure a marshaller named <marshaller_prefix>_<signame>
350 * exists. we might have put it out already, can revert to a standard
351 * marshaller provided by glib, or need to generate one.
354 if (g_hash_table_lookup (marshallers
, tmp
))
356 /* done, marshaller already generated */
362 /* need to alias/generate marshaller, register name */
363 g_hash_table_insert (marshallers
, tmp
, tmp
);
366 /* can we revert to a standard marshaller? */
369 tmp
= g_strconcat (std_marshaller_prefix
, "_", signame
, NULL
);
370 have_std_marshaller
= g_hash_table_lookup (marshallers
, tmp
) != NULL
;
374 /* GValue marshaller */
375 if (gen_cheader
&& have_std_marshaller
)
377 g_fprintf (fout
, "#define %s_%s\t%s_%s\n", marshaller_prefix
, signame
, std_marshaller_prefix
, signame
);
379 if (gen_cheader
&& !have_std_marshaller
)
381 ind
= g_fprintf (fout
, gen_internal
? "G_GNUC_INTERNAL " : "extern ");
382 ind
+= g_fprintf (fout
, "void ");
383 ind
+= g_fprintf (fout
, "%s_%s (", marshaller_prefix
, signame
);
384 g_fprintf (fout
, "GClosure *closure,\n");
385 g_fprintf (fout
, "%sGValue *return_value,\n", indent (ind
));
386 g_fprintf (fout
, "%sguint n_param_values,\n", indent (ind
));
387 g_fprintf (fout
, "%sconst GValue *param_values,\n", indent (ind
));
388 g_fprintf (fout
, "%sgpointer invocation_hint,\n", indent (ind
));
389 g_fprintf (fout
, "%sgpointer marshal_data);\n",
392 if (gen_cbody
&& !have_std_marshaller
)
394 /* cfile marshal header */
395 g_fprintf (fout
, "void\n");
396 ind
= g_fprintf (fout
, "%s_%s (", marshaller_prefix
, signame
);
397 g_fprintf (fout
, "GClosure *closure,\n");
398 g_fprintf (fout
, "%sGValue *return_value G_GNUC_UNUSED,\n", indent (ind
));
399 g_fprintf (fout
, "%sguint n_param_values,\n", indent (ind
));
400 g_fprintf (fout
, "%sconst GValue *param_values,\n", indent (ind
));
401 g_fprintf (fout
, "%sgpointer invocation_hint G_GNUC_UNUSED,\n", indent (ind
));
402 g_fprintf (fout
, "%sgpointer marshal_data)\n", indent (ind
));
403 g_fprintf (fout
, "{\n");
405 /* cfile GMarshalFunc typedef */
406 ind
= g_fprintf (fout
, " typedef %s (*GMarshalFunc_%s) (", sig
->rarg
->ctype
, signame
);
407 g_fprintf (fout
, "%s data1,\n", pad ("gpointer"));
408 for (a
= 1, node
= sig
->args
; node
; node
= node
->next
)
410 InArgument
*iarg
= node
->data
;
413 g_fprintf (fout
, "%s%s arg_%d,\n", indent (ind
), pad (iarg
->ctype
), a
++);
415 g_fprintf (fout
, "%s%s data2);\n", indent (ind
), pad ("gpointer"));
417 /* cfile marshal variables */
418 g_fprintf (fout
, " GMarshalFunc_%s callback;\n", signame
);
419 g_fprintf (fout
, " GCClosure *cc = (GCClosure*) closure;\n");
420 g_fprintf (fout
, " gpointer data1, data2;\n");
421 if (sig
->rarg
->setter
)
422 g_fprintf (fout
, " %s v_return;\n", sig
->rarg
->ctype
);
424 if (sig
->args
|| sig
->rarg
->setter
)
426 g_fprintf (fout
, "\n");
428 if (sig
->rarg
->setter
)
429 g_fprintf (fout
, " g_return_if_fail (return_value != NULL);\n");
432 for (a
= 0, node
= sig
->args
; node
; node
= node
->next
)
434 InArgument
*iarg
= node
->data
;
439 g_fprintf (fout
, " g_return_if_fail (n_param_values == %u);\n", 1 + a
);
443 /* cfile marshal data1, data2 and callback setup */
444 g_fprintf (fout
, "\n");
445 g_fprintf (fout
, " if (G_CCLOSURE_SWAP_DATA (closure))\n {\n");
446 g_fprintf (fout
, " data1 = closure->data;\n");
447 g_fprintf (fout
, " data2 = g_value_peek_pointer (param_values + 0);\n");
448 g_fprintf (fout
, " }\n else\n {\n");
449 g_fprintf (fout
, " data1 = g_value_peek_pointer (param_values + 0);\n");
450 g_fprintf (fout
, " data2 = closure->data;\n");
451 g_fprintf (fout
, " }\n");
452 g_fprintf (fout
, " callback = (GMarshalFunc_%s) (marshal_data ? marshal_data : cc->callback);\n", signame
);
454 /* cfile marshal callback action */
455 g_fprintf (fout
, "\n");
456 ind
= g_fprintf (fout
, " %s callback (", sig
->rarg
->setter
? " v_return =" : "");
457 g_fprintf (fout
, "data1,\n");
458 for (a
= 1, node
= sig
->args
; node
; node
= node
->next
)
460 InArgument
*iarg
= node
->data
;
463 g_fprintf (fout
, "%s%s (param_values + %d),\n", indent (ind
), iarg
->getter
, a
++);
465 g_fprintf (fout
, "%sdata2);\n", indent (ind
));
467 /* cfile marshal return value storage */
468 if (sig
->rarg
->setter
)
470 g_fprintf (fout
, "\n");
471 g_fprintf (fout
, " %s (return_value, v_return);\n", sig
->rarg
->setter
);
474 /* cfile marshal footer */
475 g_fprintf (fout
, "}\n");
479 /* vararg marshaller */
480 if (gen_cheader
&& gen_valist
&& have_std_marshaller
)
482 g_fprintf (fout
, "#define %s_%sv\t%s_%sv\n", marshaller_prefix
, signame
, std_marshaller_prefix
, signame
);
484 if (gen_cheader
&& gen_valist
&& !have_std_marshaller
)
486 ind
= g_fprintf (fout
, gen_internal
? "G_GNUC_INTERNAL " : "extern ");
487 ind
+= g_fprintf (fout
, "void ");
488 ind
+= g_fprintf (fout
, "%s_%sv (", marshaller_prefix
, signame
);
489 g_fprintf (fout
, "GClosure *closure,\n");
490 g_fprintf (fout
, "%sGValue *return_value,\n", indent (ind
));
491 g_fprintf (fout
, "%sgpointer instance,\n", indent (ind
));
492 g_fprintf (fout
, "%sva_list args,\n", indent (ind
));
493 g_fprintf (fout
, "%sgpointer marshal_data,\n", indent (ind
));
494 g_fprintf (fout
, "%sint n_params,\n", indent (ind
));
495 g_fprintf (fout
, "%sGType *param_types);\n", indent (ind
));
497 if (gen_cbody
&& gen_valist
&& !have_std_marshaller
)
502 g_fprintf (fout
, "void\n");
503 ind
= g_fprintf (fout
, "%s_%sv (", marshaller_prefix
, signame
);
504 g_fprintf (fout
, "GClosure *closure,\n");
505 g_fprintf (fout
, "%sGValue *return_value,\n", indent (ind
));
506 g_fprintf (fout
, "%sgpointer instance,\n", indent (ind
));
507 g_fprintf (fout
, "%sva_list args,\n", indent (ind
));
508 g_fprintf (fout
, "%sgpointer marshal_data,\n", indent (ind
));
509 g_fprintf (fout
, "%sint n_params,\n", indent (ind
));
510 g_fprintf (fout
, "%sGType *param_types)\n", indent (ind
));
511 g_fprintf (fout
, "{\n");
513 ind
= g_fprintf (fout
, " typedef %s (*GMarshalFunc_%s) (", sig
->rarg
->ctype
, signame
);
514 g_fprintf (fout
, "%s instance", pad ("gpointer"));
515 for (a
= 0, node
= sig
->args
; node
; node
= node
->next
)
517 InArgument
*iarg
= node
->data
;
520 g_fprintf (fout
, ",\n%s%s arg_%d", indent (ind
), pad (iarg
->ctype
), a
++);
522 g_fprintf (fout
, ",\n%s%s data);\n", indent (ind
), pad ("gpointer"));
523 g_fprintf (fout
, " GCClosure *cc = (GCClosure*) closure;\n");
524 g_fprintf (fout
, " gpointer data1, data2;\n");
525 g_fprintf (fout
, " GMarshalFunc_%s callback;\n", signame
);
529 for (node
= sig
->args
; node
; node
= node
->next
)
531 InArgument
*iarg
= node
->data
;
535 g_fprintf (fout
, " %s arg%i;\n", iarg
->ctype
, i
++);
540 g_fprintf (fout
, " va_list args_copy;\n");
542 if (sig
->rarg
->setter
)
543 g_fprintf (fout
, " %s v_return;\n", sig
->rarg
->ctype
);
545 if (sig
->rarg
->setter
)
547 g_fprintf (fout
, "\n");
548 g_fprintf (fout
, " g_return_if_fail (return_value != NULL);\n");
551 /* cfile marshal data1, data2 and callback setup */
554 g_fprintf (fout
, "\n");
555 g_fprintf (fout
, " G_VA_COPY (args_copy, args);\n");
557 for (node
= sig
->args
; node
; node
= node
->next
)
559 InArgument
*iarg
= node
->data
;
563 g_fprintf (fout
, " arg%i = (%s) va_arg (args_copy, %s);\n",
564 i
, iarg
->ctype
, iarg
->promoted_ctype
);
566 if (iarg
->box
!= NULL
)
568 g_fprintf (fout
, " if (");
569 if (!iarg
->box_ignores_static
)
570 g_fprintf (fout
, "(param_types[%i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && ", i
);
571 g_fprintf (fout
, "arg%i != NULL)\n ", i
);
572 if (iarg
->box_takes_type
)
574 " arg%i = %s (param_types[%i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg%i);\n",
578 " arg%i = %s (arg%i);\n",
584 g_fprintf (fout
, " va_end (args_copy);\n");
587 g_fprintf (fout
, "\n");
588 /* cfile marshal data1, data2 and callback setup */
589 g_fprintf (fout
, " if (G_CCLOSURE_SWAP_DATA (closure))\n {\n");
590 g_fprintf (fout
, " data1 = closure->data;\n");
591 g_fprintf (fout
, " data2 = instance;\n");
592 g_fprintf (fout
, " }\n else\n {\n");
593 g_fprintf (fout
, " data1 = instance;\n");
594 g_fprintf (fout
, " data2 = closure->data;\n");
595 g_fprintf (fout
, " }\n");
596 g_fprintf (fout
, " callback = (GMarshalFunc_%s) (marshal_data ? marshal_data : cc->callback);\n", signame
);
598 /* cfile marshal callback action */
599 g_fprintf (fout
, "\n");
600 ind
= g_fprintf (fout
, " %s callback (", sig
->rarg
->setter
? " v_return =" : "");
601 g_fprintf (fout
, "data1");
604 for (node
= sig
->args
; node
; node
= node
->next
)
606 InArgument
*iarg
= node
->data
;
609 g_fprintf (fout
, ",\n%sarg%i", indent (ind
), i
++);
611 g_fprintf (fout
, ",\n%sdata2);\n", indent (ind
));
614 for (node
= sig
->args
; node
; node
= node
->next
)
616 InArgument
*iarg
= node
->data
;
620 g_fprintf (fout
, " if (");
621 if (!iarg
->box_ignores_static
)
622 g_fprintf (fout
, "(param_types[%i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && ", i
);
623 g_fprintf (fout
, "arg%i != NULL)\n ", i
);
624 if (iarg
->box_takes_type
)
626 " %s (param_types[%i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg%i);\n",
636 /* cfile marshal return value storage */
637 if (sig
->rarg
->setter
)
639 g_fprintf (fout
, "\n");
640 g_fprintf (fout
, " %s (return_value, v_return);\n", sig
->rarg
->setter
);
643 g_fprintf (fout
, "}\n\n");
648 process_signature (Signature
*sig
)
650 gchar
*pname
, *sname
, *tmp
;
653 /* lookup and complete info on arguments */
654 if (!complete_out_arg (sig
->rarg
))
656 g_warning ("unknown type: %s", sig
->rarg
->keyword
);
660 for (node
= sig
->args
; node
; node
= node
->next
)
662 InArgument
*iarg
= node
->data
;
664 if (!complete_in_arg (iarg
))
666 g_warning ("unknown type: %s", iarg
->keyword
);
672 /* construct requested marshaller name and technical marshaller name */
673 pname
= g_strconcat (sig
->rarg
->keyword
, "_", NULL
);
674 sname
= g_strconcat (sig
->rarg
->sig_name
, "_", NULL
);
675 for (node
= sig
->args
; node
; node
= node
->next
)
677 InArgument
*iarg
= node
->data
;
681 sname
= g_strconcat (tmp
, "_", iarg
->sig_name
, NULL
);
684 pname
= g_strconcat (tmp
, "_", iarg
->keyword
, NULL
);
688 /* introductionary comment */
689 g_fprintf (fout
, "\n/* %s", sig
->rarg
->keyword
);
690 for (node
= sig
->args
; node
; node
= node
->next
)
692 InArgument
*iarg
= node
->data
;
694 g_fprintf (fout
, "%c%s", node
->prev
? ',' : ':', iarg
->keyword
);
697 g_fprintf (fout
, " (%s)", sig
->ploc
);
698 g_fprintf (fout
, " */\n");
700 /* ensure technical marshaller exists (<marshaller_prefix>_<sname>) */
701 generate_marshal (sname
, sig
);
703 /* put out marshaller alias for requested name if required (<marshaller_prefix>_<pname>) */
704 tmp
= g_strconcat (marshaller_prefix
, "_", pname
, NULL
);
705 if (gen_cheader
&& !g_hash_table_lookup (marshallers
, tmp
))
707 g_fprintf (fout
, "#define %s_%s\t%s_%s\n", marshaller_prefix
, pname
, marshaller_prefix
, sname
);
709 g_hash_table_insert (marshallers
, tmp
, tmp
);
719 new_in_arg (const gchar
*pname
)
721 InArgument
*iarg
= g_new0 (InArgument
, 1);
723 iarg
->keyword
= g_strdup (pname
);
729 new_out_arg (const gchar
*pname
)
731 OutArgument
*oarg
= g_new0 (OutArgument
, 1);
733 oarg
->keyword
= g_strdup (pname
);
739 parse_line (GScanner
*scanner
,
742 /* parse identifier for return value */
743 if (g_scanner_get_next_token (scanner
) != G_TOKEN_IDENTIFIER
)
744 return G_TOKEN_IDENTIFIER
;
745 sig
->rarg
= new_out_arg (scanner
->value
.v_identifier
);
747 /* keep a note on the location */
748 sig
->ploc
= g_strdup_printf ("%s:%u", scanner
->input_name
, scanner
->line
);
751 if (g_scanner_get_next_token (scanner
) != ':')
754 /* parse first argument */
755 if (g_scanner_get_next_token (scanner
) != G_TOKEN_IDENTIFIER
)
756 return G_TOKEN_IDENTIFIER
;
757 sig
->args
= g_list_append (sig
->args
, new_in_arg (scanner
->value
.v_identifier
));
759 /* parse rest of argument list */
760 while (g_scanner_peek_next_token (scanner
) == ',')
763 g_scanner_get_next_token (scanner
);
765 /* parse arg identifier */
766 if (g_scanner_get_next_token (scanner
) != G_TOKEN_IDENTIFIER
)
767 return G_TOKEN_IDENTIFIER
;
768 sig
->args
= g_list_append (sig
->args
, new_in_arg (scanner
->value
.v_identifier
));
771 /* expect end of line, done */
772 if (g_scanner_get_next_token (scanner
) != '\n')
780 string_key_destroy (gpointer key
,
793 const gchar
*gobject_marshallers
[] = {
794 #include "gmarshal.strings"
797 GSList
*slist
, *files
= NULL
;
800 /* parse args and do fast exits */
801 parse_args (&argc
, &argv
);
803 /* list input files */
804 for (i
= 1; i
< argc
; i
++)
805 files
= g_slist_prepend (files
, argv
[i
]);
807 files
= g_slist_reverse (files
);
809 files
= g_slist_prepend (files
, "/dev/stdin");
811 /* setup auxiliary structs */
812 scanner
= g_scanner_new (&scanner_config_template
);
813 marshallers
= g_hash_table_new (g_str_hash
, g_str_equal
);
817 output_tmpfn
= g_strconcat (output_fn
, ".XXXXXX", NULL
);
818 if ((output_fd
= g_mkstemp (output_tmpfn
)) == -1)
820 g_printerr ("Failed to create temp file \"%s\": %s\n", output_tmpfn
, g_strerror (errno
));
824 fout
= fdopen (output_fd
, "wb");
825 g_assert (fout
!= NULL
);
830 /* add standard marshallers of the GObject library */
832 for (i
= 0; i
< G_N_ELEMENTS (gobject_marshallers
); i
++)
834 gchar
*tmp
= g_strdup (gobject_marshallers
[i
]);
836 g_hash_table_insert (marshallers
, tmp
, tmp
);
839 /* put out initial heading */
840 g_fprintf (fout
, "\n");
842 if (gen_cheader
&& std_includes
)
844 g_fprintf (fout
, "#ifndef __%s_MARSHAL_H__\n", marshaller_prefix
);
845 g_fprintf (fout
, "#define __%s_MARSHAL_H__\n\n", marshaller_prefix
);
848 if ((gen_cheader
|| gen_cbody
) && std_includes
)
849 g_fprintf (fout
, "#include\t<glib-object.h>\n\n");
852 g_fprintf (fout
, "G_BEGIN_DECLS\n");
854 /* generate necessary preprocessor directives */
856 put_marshal_value_getters ();
858 /* process input files */
859 for (slist
= files
; slist
; slist
= slist
->next
)
861 gchar
*file
= slist
->data
;
864 if (strcmp (file
, "/dev/stdin") == 0)
865 /* Mostly for Win32. This is equivalent to opening /dev/stdin */
868 fd
= g_open (file
, O_RDONLY
, 0);
872 g_warning ("failed to open \"%s\": %s", file
, g_strerror (errno
));
877 /* set file name for error reports */
878 scanner
->input_name
= file
;
880 /* parse & process file */
881 g_scanner_input_file (scanner
, fd
);
883 /* scanning loop, we parse the input until its end is reached,
884 * or our sub routine came across invalid syntax
888 guint expected_token
= G_TOKEN_NONE
;
890 switch ((guint
) g_scanner_peek_next_token (scanner
))
893 /* eat newline and restart */
894 g_scanner_get_next_token (scanner
);
900 /* parse and process signatures */
902 Signature signature
= { NULL
, NULL
, NULL
};
905 expected_token
= parse_line (scanner
, &signature
);
907 /* once we got a valid signature, process it */
908 if (expected_token
== G_TOKEN_NONE
)
909 process_signature (&signature
);
911 /* clean up signature contents */
912 g_free (signature
.ploc
);
914 g_free (signature
.rarg
->keyword
);
915 g_free (signature
.rarg
);
916 for (node
= signature
.args
; node
; node
= node
->next
)
918 InArgument
*iarg
= node
->data
;
920 g_free (iarg
->keyword
);
923 g_list_free (signature
.args
);
928 /* bail out on errors */
929 if (expected_token
!= G_TOKEN_NONE
)
931 g_scanner_unexp_token (scanner
, expected_token
, "type name", NULL
, NULL
, NULL
, TRUE
);
936 g_scanner_peek_next_token (scanner
);
938 while (scanner
->next_token
!= G_TOKEN_EOF
);
943 /* put out trailer */
946 g_fprintf (fout
, "\nG_END_DECLS\n");
949 g_fprintf (fout
, "\n#endif /* __%s_MARSHAL_H__ */\n", marshaller_prefix
);
951 g_fprintf (fout
, "\n");
954 g_slist_free (files
);
955 g_scanner_destroy (scanner
);
956 g_hash_table_foreach_remove (marshallers
, string_key_destroy
, NULL
);
957 g_hash_table_destroy (marshallers
);
962 if (g_rename (output_tmpfn
, output_fn
) != 0)
964 g_printerr ("Failed to rename \"%s\" to \"%s\": %s\n", output_tmpfn
, output_fn
, g_strerror (errno
));
965 g_unlink (output_tmpfn
);
966 exit_status
= EXIT_FAILURE
;
969 g_free (output_tmpfn
);
976 parse_args (gint
*argc_p
,
979 guint argc
= *argc_p
;
980 gchar
**argv
= *argv_p
;
983 for (i
= 1; i
< argc
; i
++)
985 if (strcmp ("--header", argv
[i
]) == 0)
990 else if (strcmp ("--body", argv
[i
]) == 0)
995 else if (strcmp ("--skip-source", argv
[i
]) == 0)
1000 else if (strcmp ("--nostdinc", argv
[i
]) == 0)
1002 std_includes
= FALSE
;
1005 else if (strcmp ("--stdinc", argv
[i
]) == 0)
1007 std_includes
= TRUE
;
1010 else if (strcmp ("--internal", argv
[i
]) == 0)
1012 gen_internal
= TRUE
;
1015 else if (strcmp ("--valist-marshallers", argv
[i
]) == 0)
1020 else if ((strcmp ("--prefix", argv
[i
]) == 0) ||
1021 (strncmp ("--prefix=", argv
[i
], 9) == 0))
1023 gchar
*equal
= argv
[i
] + 8;
1026 marshaller_prefix
= equal
+ 1;
1027 else if (i
+ 1 < argc
)
1029 marshaller_prefix
= argv
[i
+ 1];
1035 else if ((strcmp ("--output", argv
[i
]) == 0) ||
1036 (strncmp ("--output=", argv
[i
], 9) == 0))
1038 gchar
*equal
= argv
[i
] + 8;
1041 output_fn
= equal
+ 1;
1042 else if (i
+ 1 < argc
)
1044 output_fn
= argv
[i
+ 1];
1050 else if (strcmp ("-h", argv
[i
]) == 0 ||
1051 strcmp ("-?", argv
[i
]) == 0 ||
1052 strcmp ("--help", argv
[i
]) == 0)
1054 print_blurb (stderr
, TRUE
);
1058 else if (strcmp ("-v", argv
[i
]) == 0 ||
1059 strcmp ("--version", argv
[i
]) == 0)
1061 print_blurb (stderr
, FALSE
);
1065 else if (strcmp (argv
[i
], "--g-fatal-warnings") == 0)
1067 GLogLevelFlags fatal_mask
;
1069 fatal_mask
= g_log_set_always_fatal (G_LOG_FATAL_MASK
);
1070 fatal_mask
|= G_LOG_LEVEL_WARNING
| G_LOG_LEVEL_CRITICAL
;
1071 g_log_set_always_fatal (fatal_mask
);
1078 for (i
= 1; i
< argc
; i
++)
1084 argv
[e
++] = argv
[i
];
1096 print_blurb (FILE *bout
,
1097 gboolean print_help
)
1101 g_fprintf (bout
, "%s version ", PRG_NAME
);
1102 g_fprintf (bout
, "%u.%u.%u", GLIB_MAJOR_VERSION
, GLIB_MINOR_VERSION
, GLIB_MICRO_VERSION
);
1103 g_fprintf (bout
, "\n");
1104 g_fprintf (bout
, "%s comes with ABSOLUTELY NO WARRANTY.\n", PRG_NAME
);
1105 g_fprintf (bout
, "You may redistribute copies of %s under the terms of\n", PRG_NAME
);
1106 g_fprintf (bout
, "the GNU General Public License which can be found in the\n");
1107 g_fprintf (bout
, "%s source package. Sources, examples and contact\n", PKG_NAME
);
1108 g_fprintf (bout
, "information are available at %s\n", PKG_HTTP_HOME
);
1112 g_fprintf (bout
, "Usage:\n");
1113 g_fprintf (bout
, " %s [OPTION...] [FILES...]\n\n", PRG_NAME
);
1114 g_fprintf (bout
, "Help Options:\n");
1115 g_fprintf (bout
, " -h, --help Show this help message\n\n");
1116 g_fprintf (bout
, "Utility Options:\n");
1117 g_fprintf (bout
, " --header Generate C headers\n");
1118 g_fprintf (bout
, " --body Generate C code\n");
1119 g_fprintf (bout
, " --prefix=string Specify marshaller prefix\n");
1120 g_fprintf (bout
, " --output=file Write output into the specified file\n");
1121 g_fprintf (bout
, " --skip-source Skip source location comments\n");
1122 g_fprintf (bout
, " --stdinc, --nostdinc Include/use standard marshallers\n");
1123 g_fprintf (bout
, " --internal Mark generated functions as internal\n");
1124 g_fprintf (bout
, " --valist-marshallers Generate va_list marshallers\n");
1125 g_fprintf (bout
, " -v, --version Print version informations\n");
1126 g_fprintf (bout
, " --g-fatal-warnings Make warnings fatal (abort)\n");