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, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
29 #include <sys/types.h>
32 #include <glib/gstdio.h>
35 #define G_LOG_DOMAIN "GLib-Genmarshal"
37 #include <glib/gprintf.h>
44 #define PRG_NAME "glib-genmarshal"
45 #define PKG_NAME "GLib"
46 #define PKG_HTTP_HOME "http://www.gtk.org"
49 /* --- typedefs & structures --- */
52 gchar
*keyword
; /* marhaller list keyword [MY_STRING] */
53 const gchar
*sig_name
; /* signature name [STRING] */
54 const gchar
*ctype
; /* C type name [gchar*] */
55 const gchar
*promoted_ctype
; /* promoted C type name [gchar*] */
56 const gchar
*getter
; /* value getter function [g_value_get_string] */
57 const gchar
*box
; /* value box function [g_strdup] */
58 const gchar
*unbox
; /* value unbox function [g_free] */
59 gboolean box_ignores_static
; /* Wether the box/unbox functions ignore the static_scope */
60 gboolean box_takes_type
; /* Wether the box/unbox functions take a type arg */
64 gchar
*keyword
; /* marhaller list keyword [MY_STRING] */
65 const gchar
*sig_name
; /* signature name [STRING] */
66 const gchar
*ctype
; /* C type name [gchar*] */
67 const gchar
*setter
; /* value setter function [g_value_set_string] */
73 GList
*args
; /* of type InArgument* */
77 /* --- prototypes --- */
78 static void parse_args (gint
*argc_p
,
80 static void print_blurb (FILE *bout
,
84 /* --- variables --- */
85 static const GScannerConfig scanner_config_template
=
88 " \t\r" /* "\n" is statement delimiter */
89 ) /* cset_skip_characters */,
94 ) /* cset_identifier_first */,
99 ) /* cset_identifier_nth */,
100 ( "#\n" ) /* cpair_comment_single */,
102 FALSE
/* case_sensitive */,
104 TRUE
/* skip_comment_multi */,
105 TRUE
/* skip_comment_single */,
106 TRUE
/* scan_comment_multi */,
107 TRUE
/* scan_identifier */,
108 FALSE
/* scan_identifier_1char */,
109 FALSE
/* scan_identifier_NULL */,
110 TRUE
/* scan_symbols */,
111 FALSE
/* scan_binary */,
112 TRUE
/* scan_octal */,
113 TRUE
/* scan_float */,
115 FALSE
/* scan_hex_dollar */,
116 TRUE
/* scan_string_sq */,
117 TRUE
/* scan_string_dq */,
118 TRUE
/* numbers_2_int */,
119 FALSE
/* int_2_float */,
120 FALSE
/* identifier_2_string */,
121 TRUE
/* char_2_token */,
122 FALSE
/* symbol_2_token */,
123 FALSE
/* scope_0_fallback */,
125 static gchar
* const std_marshaller_prefix
= "g_cclosure_marshal";
126 static gchar
*marshaller_prefix
= "g_cclosure_user_marshal";
127 static GHashTable
*marshallers
= NULL
;
128 static FILE *fout
= NULL
;
129 static gboolean gen_cheader
= FALSE
;
130 static gboolean gen_cbody
= FALSE
;
131 static gboolean gen_internal
= FALSE
;
132 static gboolean gen_valist
= FALSE
;
133 static gboolean skip_ploc
= FALSE
;
134 static gboolean std_includes
= TRUE
;
135 static gint exit_status
= 0;
138 /* --- functions --- */
140 put_marshal_value_getters (void)
143 fputs ("#ifdef G_ENABLE_DEBUG\n", fout
);
144 fputs ("#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)\n", fout
);
145 fputs ("#define g_marshal_value_peek_char(v) g_value_get_schar (v)\n", fout
);
146 fputs ("#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)\n", fout
);
147 fputs ("#define g_marshal_value_peek_int(v) g_value_get_int (v)\n", fout
);
148 fputs ("#define g_marshal_value_peek_uint(v) g_value_get_uint (v)\n", fout
);
149 fputs ("#define g_marshal_value_peek_long(v) g_value_get_long (v)\n", fout
);
150 fputs ("#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)\n", fout
);
151 fputs ("#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)\n", fout
);
152 fputs ("#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)\n", fout
);
153 fputs ("#define g_marshal_value_peek_enum(v) g_value_get_enum (v)\n", fout
);
154 fputs ("#define g_marshal_value_peek_flags(v) g_value_get_flags (v)\n", fout
);
155 fputs ("#define g_marshal_value_peek_float(v) g_value_get_float (v)\n", fout
);
156 fputs ("#define g_marshal_value_peek_double(v) g_value_get_double (v)\n", fout
);
157 fputs ("#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)\n", fout
);
158 fputs ("#define g_marshal_value_peek_param(v) g_value_get_param (v)\n", fout
);
159 fputs ("#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)\n", fout
);
160 fputs ("#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)\n", fout
);
161 fputs ("#define g_marshal_value_peek_object(v) g_value_get_object (v)\n", fout
);
162 fputs ("#define g_marshal_value_peek_variant(v) g_value_get_variant (v)\n", fout
);
163 fputs ("#else /* !G_ENABLE_DEBUG */\n", fout
);
164 fputs ("/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.\n", fout
);
165 fputs (" * Do not access GValues directly in your code. Instead, use the\n", fout
);
166 fputs (" * g_value_get_*() functions\n", fout
);
167 fputs (" */\n", fout
);
168 fputs ("#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int\n", fout
);
169 fputs ("#define g_marshal_value_peek_char(v) (v)->data[0].v_int\n", fout
);
170 fputs ("#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint\n", fout
);
171 fputs ("#define g_marshal_value_peek_int(v) (v)->data[0].v_int\n", fout
);
172 fputs ("#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint\n", fout
);
173 fputs ("#define g_marshal_value_peek_long(v) (v)->data[0].v_long\n", fout
);
174 fputs ("#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong\n", fout
);
175 fputs ("#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64\n", fout
);
176 fputs ("#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64\n", fout
);
177 fputs ("#define g_marshal_value_peek_enum(v) (v)->data[0].v_long\n", fout
);
178 fputs ("#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong\n", fout
);
179 fputs ("#define g_marshal_value_peek_float(v) (v)->data[0].v_float\n", fout
);
180 fputs ("#define g_marshal_value_peek_double(v) (v)->data[0].v_double\n", fout
);
181 fputs ("#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer\n", fout
);
182 fputs ("#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer\n", fout
);
183 fputs ("#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer\n", fout
);
184 fputs ("#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer\n", fout
);
185 fputs ("#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer\n", fout
);
186 fputs ("#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer\n", fout
);
187 fputs ("#endif /* !G_ENABLE_DEBUG */\n", fout
);
192 complete_in_arg (InArgument
*iarg
)
194 static const InArgument args
[] = {
195 /* keyword sig_name ctype promoted getter */
196 { "VOID", "VOID", "void", "void", NULL
, },
197 { "BOOLEAN", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
198 { "CHAR", "CHAR", "gchar", "gint", "g_marshal_value_peek_char", },
199 { "UCHAR", "UCHAR", "guchar", "guint", "g_marshal_value_peek_uchar", },
200 { "INT", "INT", "gint", "gint", "g_marshal_value_peek_int", },
201 { "UINT", "UINT", "guint", "guint", "g_marshal_value_peek_uint", },
202 { "LONG", "LONG", "glong", "glong", "g_marshal_value_peek_long", },
203 { "ULONG", "ULONG", "gulong", "gulong", "g_marshal_value_peek_ulong", },
204 { "INT64", "INT64", "gint64", "gint64", "g_marshal_value_peek_int64", },
205 { "UINT64", "UINT64", "guint64", "guint64", "g_marshal_value_peek_uint64", },
206 { "ENUM", "ENUM", "gint", "gint", "g_marshal_value_peek_enum", },
207 { "FLAGS", "FLAGS", "guint", "guint", "g_marshal_value_peek_flags", },
208 { "FLOAT", "FLOAT", "gfloat", "gdouble", "g_marshal_value_peek_float", },
209 { "DOUBLE", "DOUBLE", "gdouble", "gdouble", "g_marshal_value_peek_double", },
210 { "STRING", "STRING", "gpointer", "gpointer", "g_marshal_value_peek_string", "g_strdup", "g_free"},
211 { "PARAM", "PARAM", "gpointer", "gpointer", "g_marshal_value_peek_param", "g_param_spec_ref", "g_param_spec_unref"},
212 { "BOXED", "BOXED", "gpointer", "gpointer", "g_marshal_value_peek_boxed", "g_boxed_copy", "g_boxed_free", FALSE
, TRUE
},
213 { "POINTER", "POINTER", "gpointer", "gpointer", "g_marshal_value_peek_pointer", },
214 { "OBJECT", "OBJECT", "gpointer", "gpointer", "g_marshal_value_peek_object", "g_object_ref", "g_object_unref", TRUE
},
215 { "VARIANT", "VARIANT", "gpointer", "gpointer", "g_marshal_value_peek_variant", "g_variant_ref_sink", "g_variant_unref"},
217 { "NONE", "VOID", "void", "void", NULL
, },
218 { "BOOL", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
222 g_return_val_if_fail (iarg
!= NULL
, FALSE
);
224 for (i
= 0; i
< G_N_ELEMENTS (args
); i
++)
225 if (strcmp (args
[i
].keyword
, iarg
->keyword
) == 0)
227 iarg
->sig_name
= args
[i
].sig_name
;
228 iarg
->ctype
= args
[i
].ctype
;
229 iarg
->promoted_ctype
= args
[i
].promoted_ctype
;
230 iarg
->getter
= args
[i
].getter
;
231 iarg
->box
= args
[i
].box
;
232 iarg
->unbox
= args
[i
].unbox
;
233 iarg
->box_ignores_static
= args
[i
].box_ignores_static
;
234 iarg
->box_takes_type
= args
[i
].box_takes_type
;
242 complete_out_arg (OutArgument
*oarg
)
244 static const OutArgument args
[] = {
245 /* keyword sig_name ctype setter */
246 { "VOID", "VOID", "void", NULL
, },
247 { "BOOLEAN", "BOOLEAN", "gboolean", "g_value_set_boolean", },
248 { "CHAR", "CHAR", "gchar", "g_value_set_char", },
249 { "UCHAR", "UCHAR", "guchar", "g_value_set_uchar", },
250 { "INT", "INT", "gint", "g_value_set_int", },
251 { "UINT", "UINT", "guint", "g_value_set_uint", },
252 { "LONG", "LONG", "glong", "g_value_set_long", },
253 { "ULONG", "ULONG", "gulong", "g_value_set_ulong", },
254 { "INT64", "INT64", "gint64", "g_value_set_int64", },
255 { "UINT64", "UINT64", "guint64", "g_value_set_uint64", },
256 { "ENUM", "ENUM", "gint", "g_value_set_enum", },
257 { "FLAGS", "FLAGS", "guint", "g_value_set_flags", },
258 { "FLOAT", "FLOAT", "gfloat", "g_value_set_float", },
259 { "DOUBLE", "DOUBLE", "gdouble", "g_value_set_double", },
260 { "STRING", "STRING", "gchar*", "g_value_take_string", },
261 { "PARAM", "PARAM", "GParamSpec*", "g_value_take_param", },
262 { "BOXED", "BOXED", "gpointer", "g_value_take_boxed", },
263 { "POINTER", "POINTER", "gpointer", "g_value_set_pointer", },
264 { "OBJECT", "OBJECT", "GObject*", "g_value_take_object", },
265 { "VARIANT", "VARIANT", "GVariant*", "g_value_take_variant", },
267 { "NONE", "VOID", "void", NULL
, },
268 { "BOOL", "BOOLEAN", "gboolean", "g_value_set_boolean", },
272 g_return_val_if_fail (oarg
!= NULL
, FALSE
);
274 for (i
= 0; i
< G_N_ELEMENTS (args
); i
++)
275 if (strcmp (args
[i
].keyword
, oarg
->keyword
) == 0)
277 oarg
->sig_name
= args
[i
].sig_name
;
278 oarg
->ctype
= args
[i
].ctype
;
279 oarg
->setter
= args
[i
].setter
;
287 pad (const gchar
*string
)
289 #define PAD_LENGTH 12
290 static gchar
*buffer
= NULL
;
293 g_return_val_if_fail (string
!= NULL
, NULL
);
296 buffer
= g_new (gchar
, PAD_LENGTH
+ 1);
299 if (strlen (string
) >= PAD_LENGTH
)
302 buffer
= g_strdup_printf ("%s ", string
);
303 g_warning ("overfull string (%u bytes) for padspace",
304 (guint
) strlen (string
));
310 for (i
= 0; i
< PAD_LENGTH
; i
++)
312 gboolean done
= *string
== 0;
314 buffer
[i
] = done
? ' ' : *string
++;
322 indent (guint n_spaces
)
324 static gchar
*buffer
= NULL
;
325 static guint blength
= 0;
327 if (blength
<= n_spaces
)
329 blength
= n_spaces
+ 1;
331 buffer
= g_new (gchar
, blength
);
333 memset (buffer
, ' ', n_spaces
);
334 buffer
[n_spaces
] = 0;
340 generate_marshal (const gchar
*signame
,
345 gchar
*tmp
= g_strconcat (marshaller_prefix
, "_", signame
, NULL
);
346 gboolean have_std_marshaller
= FALSE
;
348 /* here we have to make sure a marshaller named <marshaller_prefix>_<signame>
349 * exists. we might have put it out already, can revert to a standard
350 * marshaller provided by glib, or need to generate one.
353 if (g_hash_table_lookup (marshallers
, tmp
))
355 /* done, marshaller already generated */
361 /* need to alias/generate marshaller, register name */
362 g_hash_table_insert (marshallers
, tmp
, tmp
);
365 /* can we revert to a standard marshaller? */
368 tmp
= g_strconcat (std_marshaller_prefix
, "_", signame
, NULL
);
369 have_std_marshaller
= g_hash_table_lookup (marshallers
, tmp
) != NULL
;
373 /* GValue marshaller */
374 if (gen_cheader
&& have_std_marshaller
)
376 g_fprintf (fout
, "#define %s_%s\t%s_%s\n", marshaller_prefix
, signame
, std_marshaller_prefix
, signame
);
378 if (gen_cheader
&& !have_std_marshaller
)
380 ind
= g_fprintf (fout
, gen_internal
? "G_GNUC_INTERNAL " : "extern ");
381 ind
+= g_fprintf (fout
, "void ");
382 ind
+= g_fprintf (fout
, "%s_%s (", marshaller_prefix
, signame
);
383 g_fprintf (fout
, "GClosure *closure,\n");
384 g_fprintf (fout
, "%sGValue *return_value,\n", indent (ind
));
385 g_fprintf (fout
, "%sguint n_param_values,\n", indent (ind
));
386 g_fprintf (fout
, "%sconst GValue *param_values,\n", indent (ind
));
387 g_fprintf (fout
, "%sgpointer invocation_hint,\n", indent (ind
));
388 g_fprintf (fout
, "%sgpointer marshal_data);\n",
391 if (gen_cbody
&& !have_std_marshaller
)
393 /* cfile marshal header */
394 g_fprintf (fout
, "void\n");
395 ind
= g_fprintf (fout
, "%s_%s (", marshaller_prefix
, signame
);
396 g_fprintf (fout
, "GClosure *closure,\n");
397 g_fprintf (fout
, "%sGValue *return_value G_GNUC_UNUSED,\n", indent (ind
));
398 g_fprintf (fout
, "%sguint n_param_values,\n", indent (ind
));
399 g_fprintf (fout
, "%sconst GValue *param_values,\n", indent (ind
));
400 g_fprintf (fout
, "%sgpointer invocation_hint G_GNUC_UNUSED,\n", indent (ind
));
401 g_fprintf (fout
, "%sgpointer marshal_data)\n", indent (ind
));
402 g_fprintf (fout
, "{\n");
404 /* cfile GMarshalFunc typedef */
405 ind
= g_fprintf (fout
, " typedef %s (*GMarshalFunc_%s) (", sig
->rarg
->ctype
, signame
);
406 g_fprintf (fout
, "%s data1,\n", pad ("gpointer"));
407 for (a
= 1, node
= sig
->args
; node
; node
= node
->next
)
409 InArgument
*iarg
= node
->data
;
412 g_fprintf (fout
, "%s%s arg_%d,\n", indent (ind
), pad (iarg
->ctype
), a
++);
414 g_fprintf (fout
, "%s%s data2);\n", indent (ind
), pad ("gpointer"));
416 /* cfile marshal variables */
417 g_fprintf (fout
, " register GMarshalFunc_%s callback;\n", signame
);
418 g_fprintf (fout
, " register GCClosure *cc = (GCClosure*) closure;\n");
419 g_fprintf (fout
, " register gpointer data1, data2;\n");
420 if (sig
->rarg
->setter
)
421 g_fprintf (fout
, " %s v_return;\n", sig
->rarg
->ctype
);
423 if (sig
->args
|| sig
->rarg
->setter
)
425 g_fprintf (fout
, "\n");
427 if (sig
->rarg
->setter
)
428 g_fprintf (fout
, " g_return_if_fail (return_value != NULL);\n");
431 for (a
= 0, node
= sig
->args
; node
; node
= node
->next
)
433 InArgument
*iarg
= node
->data
;
438 g_fprintf (fout
, " g_return_if_fail (n_param_values == %u);\n", 1 + a
);
442 /* cfile marshal data1, data2 and callback setup */
443 g_fprintf (fout
, "\n");
444 g_fprintf (fout
, " if (G_CCLOSURE_SWAP_DATA (closure))\n {\n");
445 g_fprintf (fout
, " data1 = closure->data;\n");
446 g_fprintf (fout
, " data2 = g_value_peek_pointer (param_values + 0);\n");
447 g_fprintf (fout
, " }\n else\n {\n");
448 g_fprintf (fout
, " data1 = g_value_peek_pointer (param_values + 0);\n");
449 g_fprintf (fout
, " data2 = closure->data;\n");
450 g_fprintf (fout
, " }\n");
451 g_fprintf (fout
, " callback = (GMarshalFunc_%s) (marshal_data ? marshal_data : cc->callback);\n", signame
);
453 /* cfile marshal callback action */
454 g_fprintf (fout
, "\n");
455 ind
= g_fprintf (fout
, " %s callback (", sig
->rarg
->setter
? " v_return =" : "");
456 g_fprintf (fout
, "data1,\n");
457 for (a
= 1, node
= sig
->args
; node
; node
= node
->next
)
459 InArgument
*iarg
= node
->data
;
462 g_fprintf (fout
, "%s%s (param_values + %d),\n", indent (ind
), iarg
->getter
, a
++);
464 g_fprintf (fout
, "%sdata2);\n", indent (ind
));
466 /* cfile marshal return value storage */
467 if (sig
->rarg
->setter
)
469 g_fprintf (fout
, "\n");
470 g_fprintf (fout
, " %s (return_value, v_return);\n", sig
->rarg
->setter
);
473 /* cfile marshal footer */
474 g_fprintf (fout
, "}\n");
478 /* vararg marshaller */
479 if (gen_cheader
&& gen_valist
&& have_std_marshaller
)
481 g_fprintf (fout
, "#define %s_%sv\t%s_%sv\n", marshaller_prefix
, signame
, std_marshaller_prefix
, signame
);
483 if (gen_cheader
&& gen_valist
&& !have_std_marshaller
)
485 ind
= g_fprintf (fout
, gen_internal
? "G_GNUC_INTERNAL " : "extern ");
486 ind
+= g_fprintf (fout
, "void ");
487 ind
+= g_fprintf (fout
, "%s_%sv (", marshaller_prefix
, signame
);
488 g_fprintf (fout
, "GClosure *closure,\n");
489 g_fprintf (fout
, "%sGValue *return_value,\n", indent (ind
));
490 g_fprintf (fout
, "%sgpointer instance,\n", indent (ind
));
491 g_fprintf (fout
, "%sva_list args,\n", indent (ind
));
492 g_fprintf (fout
, "%sgpointer marshal_data,\n", indent (ind
));
493 g_fprintf (fout
, "%sint n_params,\n", indent (ind
));
494 g_fprintf (fout
, "%sGType *param_types);\n", indent (ind
));
496 if (gen_cbody
&& gen_valist
&& !have_std_marshaller
)
501 g_fprintf (fout
, "void\n");
502 ind
= g_fprintf (fout
, "%s_%sv (", marshaller_prefix
, signame
);
503 g_fprintf (fout
, "GClosure *closure,\n");
504 g_fprintf (fout
, "%sGValue *return_value,\n", indent (ind
));
505 g_fprintf (fout
, "%sgpointer instance,\n", indent (ind
));
506 g_fprintf (fout
, "%sva_list args,\n", indent (ind
));
507 g_fprintf (fout
, "%sgpointer marshal_data,\n", indent (ind
));
508 g_fprintf (fout
, "%sint n_params,\n", indent (ind
));
509 g_fprintf (fout
, "%sGType *param_types)\n", indent (ind
));
510 g_fprintf (fout
, "{\n");
512 ind
= g_fprintf (fout
, " typedef %s (*GMarshalFunc_%s) (", sig
->rarg
->ctype
, signame
);
513 g_fprintf (fout
, "%s instance", pad ("gpointer"));
514 for (a
= 0, node
= sig
->args
; node
; node
= node
->next
)
516 InArgument
*iarg
= node
->data
;
519 g_fprintf (fout
, ",\n%s%s arg_%d", indent (ind
), pad (iarg
->ctype
), a
++);
521 g_fprintf (fout
, ",\n%s%s data);\n", indent (ind
), pad ("gpointer"));
522 g_fprintf (fout
, " GCClosure *cc = (GCClosure*) closure;\n");
523 g_fprintf (fout
, " gpointer data1, data2;\n");
524 g_fprintf (fout
, " GMarshalFunc_%s callback;\n", signame
);
528 for (node
= sig
->args
; node
; node
= node
->next
)
530 InArgument
*iarg
= node
->data
;
534 g_fprintf (fout
, " %s arg%i;\n", iarg
->ctype
, i
++);
539 g_fprintf (fout
, " va_list args_copy;\n");
541 if (sig
->rarg
->setter
)
542 g_fprintf (fout
, " %s v_return;\n", sig
->rarg
->ctype
);
544 if (sig
->rarg
->setter
)
546 g_fprintf (fout
, "\n");
547 g_fprintf (fout
, " g_return_if_fail (return_value != NULL);\n");
550 /* cfile marshal data1, data2 and callback setup */
553 g_fprintf (fout
, "\n");
554 g_fprintf (fout
, " G_VA_COPY (args_copy, args);\n");
556 for (node
= sig
->args
; node
; node
= node
->next
)
558 InArgument
*iarg
= node
->data
;
562 g_fprintf (fout
, " arg%i = (%s) va_arg (args_copy, %s);\n",
563 i
, iarg
->ctype
, iarg
->promoted_ctype
);
565 if (iarg
->box
!= NULL
)
567 g_fprintf (fout
, " if (");
568 if (!iarg
->box_ignores_static
)
569 g_fprintf (fout
, "(param_types[%i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && ", i
);
570 g_fprintf (fout
, "arg%i != NULL)\n ", i
);
571 if (iarg
->box_takes_type
)
573 " arg%i = %s (param_types[%i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg%i);\n",
577 " arg%i = %s (arg%i);\n",
583 g_fprintf (fout
, " va_end (args_copy);\n");
586 g_fprintf (fout
, "\n");
587 /* cfile marshal data1, data2 and callback setup */
588 g_fprintf (fout
, " if (G_CCLOSURE_SWAP_DATA (closure))\n {\n");
589 g_fprintf (fout
, " data1 = closure->data;\n");
590 g_fprintf (fout
, " data2 = instance;\n");
591 g_fprintf (fout
, " }\n else\n {\n");
592 g_fprintf (fout
, " data1 = instance;\n");
593 g_fprintf (fout
, " data2 = closure->data;\n");
594 g_fprintf (fout
, " }\n");
595 g_fprintf (fout
, " callback = (GMarshalFunc_%s) (marshal_data ? marshal_data : cc->callback);\n", signame
);
597 /* cfile marshal callback action */
598 g_fprintf (fout
, "\n");
599 ind
= g_fprintf (fout
, " %s callback (", sig
->rarg
->setter
? " v_return =" : "");
600 g_fprintf (fout
, "data1");
603 for (node
= sig
->args
; node
; node
= node
->next
)
605 InArgument
*iarg
= node
->data
;
608 g_fprintf (fout
, ",\n%sarg%i", indent (ind
), i
++);
610 g_fprintf (fout
, ",\n%sdata2);\n", indent (ind
));
613 for (node
= sig
->args
; node
; node
= node
->next
)
615 InArgument
*iarg
= node
->data
;
619 g_fprintf (fout
, " if (");
620 if (!iarg
->box_ignores_static
)
621 g_fprintf (fout
, "(param_types[%i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && ", i
);
622 g_fprintf (fout
, "arg%i != NULL)\n ", i
);
623 if (iarg
->box_takes_type
)
625 " %s (param_types[%i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg%i);\n",
635 /* cfile marshal return value storage */
636 if (sig
->rarg
->setter
)
638 g_fprintf (fout
, "\n");
639 g_fprintf (fout
, " %s (return_value, v_return);\n", sig
->rarg
->setter
);
642 g_fprintf (fout
, "}\n\n");
647 process_signature (Signature
*sig
)
649 gchar
*pname
, *sname
, *tmp
;
652 /* lookup and complete info on arguments */
653 if (!complete_out_arg (sig
->rarg
))
655 g_warning ("unknown type: %s", sig
->rarg
->keyword
);
659 for (node
= sig
->args
; node
; node
= node
->next
)
661 InArgument
*iarg
= node
->data
;
663 if (!complete_in_arg (iarg
))
665 g_warning ("unknown type: %s", iarg
->keyword
);
671 /* construct requested marshaller name and technical marshaller name */
672 pname
= g_strconcat (sig
->rarg
->keyword
, "_", NULL
);
673 sname
= g_strconcat (sig
->rarg
->sig_name
, "_", NULL
);
674 for (node
= sig
->args
; node
; node
= node
->next
)
676 InArgument
*iarg
= node
->data
;
680 sname
= g_strconcat (tmp
, "_", iarg
->sig_name
, NULL
);
683 pname
= g_strconcat (tmp
, "_", iarg
->keyword
, NULL
);
687 /* introductionary comment */
688 g_fprintf (fout
, "\n/* %s", sig
->rarg
->keyword
);
689 for (node
= sig
->args
; node
; node
= node
->next
)
691 InArgument
*iarg
= node
->data
;
693 g_fprintf (fout
, "%c%s", node
->prev
? ',' : ':', iarg
->keyword
);
696 g_fprintf (fout
, " (%s)", sig
->ploc
);
697 g_fprintf (fout
, " */\n");
699 /* ensure technical marshaller exists (<marshaller_prefix>_<sname>) */
700 generate_marshal (sname
, sig
);
702 /* put out marshaller alias for requested name if required (<marshaller_prefix>_<pname>) */
703 tmp
= g_strconcat (marshaller_prefix
, "_", pname
, NULL
);
704 if (gen_cheader
&& !g_hash_table_lookup (marshallers
, tmp
))
706 g_fprintf (fout
, "#define %s_%s\t%s_%s\n", marshaller_prefix
, pname
, marshaller_prefix
, sname
);
708 g_hash_table_insert (marshallers
, tmp
, tmp
);
718 new_in_arg (const gchar
*pname
)
720 InArgument
*iarg
= g_new0 (InArgument
, 1);
722 iarg
->keyword
= g_strdup (pname
);
728 new_out_arg (const gchar
*pname
)
730 OutArgument
*oarg
= g_new0 (OutArgument
, 1);
732 oarg
->keyword
= g_strdup (pname
);
738 parse_line (GScanner
*scanner
,
741 /* parse identifier for return value */
742 if (g_scanner_get_next_token (scanner
) != G_TOKEN_IDENTIFIER
)
743 return G_TOKEN_IDENTIFIER
;
744 sig
->rarg
= new_out_arg (scanner
->value
.v_identifier
);
746 /* keep a note on the location */
747 sig
->ploc
= g_strdup_printf ("%s:%u", scanner
->input_name
, scanner
->line
);
750 if (g_scanner_get_next_token (scanner
) != ':')
753 /* parse first argument */
754 if (g_scanner_get_next_token (scanner
) != G_TOKEN_IDENTIFIER
)
755 return G_TOKEN_IDENTIFIER
;
756 sig
->args
= g_list_append (sig
->args
, new_in_arg (scanner
->value
.v_identifier
));
758 /* parse rest of argument list */
759 while (g_scanner_peek_next_token (scanner
) == ',')
762 g_scanner_get_next_token (scanner
);
764 /* parse arg identifier */
765 if (g_scanner_get_next_token (scanner
) != G_TOKEN_IDENTIFIER
)
766 return G_TOKEN_IDENTIFIER
;
767 sig
->args
= g_list_append (sig
->args
, new_in_arg (scanner
->value
.v_identifier
));
770 /* expect end of line, done */
771 if (g_scanner_get_next_token (scanner
) != '\n')
779 string_key_destroy (gpointer key
,
792 const gchar
*gobject_marshallers
[] = {
793 #include "gmarshal.strings"
796 GSList
*slist
, *files
= NULL
;
799 /* parse args and do fast exits */
800 parse_args (&argc
, &argv
);
802 /* list input files */
803 for (i
= 1; i
< argc
; i
++)
804 files
= g_slist_prepend (files
, argv
[i
]);
806 files
= g_slist_reverse (files
);
808 files
= g_slist_prepend (files
, "/dev/stdin");
810 /* setup auxiliary structs */
811 scanner
= g_scanner_new (&scanner_config_template
);
813 marshallers
= g_hash_table_new (g_str_hash
, g_str_equal
);
815 /* add standard marshallers of the GObject library */
817 for (i
= 0; i
< G_N_ELEMENTS (gobject_marshallers
); i
++)
819 gchar
*tmp
= g_strdup (gobject_marshallers
[i
]);
821 g_hash_table_insert (marshallers
, tmp
, tmp
);
824 /* put out initial heading */
825 g_fprintf (fout
, "\n");
827 if (gen_cheader
&& std_includes
)
829 g_fprintf (fout
, "#ifndef __%s_MARSHAL_H__\n", marshaller_prefix
);
830 g_fprintf (fout
, "#define __%s_MARSHAL_H__\n\n", marshaller_prefix
);
833 if ((gen_cheader
|| gen_cbody
) && std_includes
)
834 g_fprintf (fout
, "#include\t<glib-object.h>\n\n");
837 g_fprintf (fout
, "G_BEGIN_DECLS\n");
839 /* generate necessary preprocessor directives */
841 put_marshal_value_getters ();
843 /* process input files */
844 for (slist
= files
; slist
; slist
= slist
->next
)
846 gchar
*file
= slist
->data
;
849 if (strcmp (file
, "/dev/stdin") == 0)
850 /* Mostly for Win32. This is equivalent to opening /dev/stdin */
853 fd
= g_open (file
, O_RDONLY
, 0);
857 g_warning ("failed to open \"%s\": %s", file
, g_strerror (errno
));
862 /* set file name for error reports */
863 scanner
->input_name
= file
;
865 /* parse & process file */
866 g_scanner_input_file (scanner
, fd
);
868 /* scanning loop, we parse the input until its end is reached,
869 * or our sub routine came across invalid syntax
873 guint expected_token
= G_TOKEN_NONE
;
875 switch ((guint
) g_scanner_peek_next_token (scanner
))
878 /* eat newline and restart */
879 g_scanner_get_next_token (scanner
);
885 /* parse and process signatures */
887 Signature signature
= { NULL
, NULL
, NULL
};
890 expected_token
= parse_line (scanner
, &signature
);
892 /* once we got a valid signature, process it */
893 if (expected_token
== G_TOKEN_NONE
)
894 process_signature (&signature
);
896 /* clean up signature contents */
897 g_free (signature
.ploc
);
899 g_free (signature
.rarg
->keyword
);
900 g_free (signature
.rarg
);
901 for (node
= signature
.args
; node
; node
= node
->next
)
903 InArgument
*iarg
= node
->data
;
905 g_free (iarg
->keyword
);
908 g_list_free (signature
.args
);
913 /* bail out on errors */
914 if (expected_token
!= G_TOKEN_NONE
)
916 g_scanner_unexp_token (scanner
, expected_token
, "type name", NULL
, NULL
, NULL
, TRUE
);
921 g_scanner_peek_next_token (scanner
);
923 while (scanner
->next_token
!= G_TOKEN_EOF
);
928 /* put out trailer */
931 g_fprintf (fout
, "\nG_END_DECLS\n");
934 g_fprintf (fout
, "\n#endif /* __%s_MARSHAL_H__ */\n", marshaller_prefix
);
936 g_fprintf (fout
, "\n");
939 g_slist_free (files
);
940 g_scanner_destroy (scanner
);
941 g_hash_table_foreach_remove (marshallers
, string_key_destroy
, NULL
);
942 g_hash_table_destroy (marshallers
);
948 parse_args (gint
*argc_p
,
951 guint argc
= *argc_p
;
952 gchar
**argv
= *argv_p
;
955 for (i
= 1; i
< argc
; i
++)
957 if (strcmp ("--header", argv
[i
]) == 0)
962 else if (strcmp ("--body", argv
[i
]) == 0)
967 else if (strcmp ("--skip-source", argv
[i
]) == 0)
972 else if (strcmp ("--nostdinc", argv
[i
]) == 0)
974 std_includes
= FALSE
;
977 else if (strcmp ("--stdinc", argv
[i
]) == 0)
982 else if (strcmp ("--internal", argv
[i
]) == 0)
987 else if (strcmp ("--valist-marshallers", argv
[i
]) == 0)
992 else if ((strcmp ("--prefix", argv
[i
]) == 0) ||
993 (strncmp ("--prefix=", argv
[i
], 9) == 0))
995 gchar
*equal
= argv
[i
] + 8;
998 marshaller_prefix
= g_strdup (equal
+ 1);
999 else if (i
+ 1 < argc
)
1001 marshaller_prefix
= g_strdup (argv
[i
+ 1]);
1007 else if (strcmp ("-h", argv
[i
]) == 0 ||
1008 strcmp ("-?", argv
[i
]) == 0 ||
1009 strcmp ("--help", argv
[i
]) == 0)
1011 print_blurb (stderr
, TRUE
);
1015 else if (strcmp ("-v", argv
[i
]) == 0 ||
1016 strcmp ("--version", argv
[i
]) == 0)
1018 print_blurb (stderr
, FALSE
);
1022 else if (strcmp (argv
[i
], "--g-fatal-warnings") == 0)
1024 GLogLevelFlags fatal_mask
;
1026 fatal_mask
= g_log_set_always_fatal (G_LOG_FATAL_MASK
);
1027 fatal_mask
|= G_LOG_LEVEL_WARNING
| G_LOG_LEVEL_CRITICAL
;
1028 g_log_set_always_fatal (fatal_mask
);
1035 for (i
= 1; i
< argc
; i
++)
1041 argv
[e
++] = argv
[i
];
1053 print_blurb (FILE *bout
,
1054 gboolean print_help
)
1058 g_fprintf (bout
, "%s version ", PRG_NAME
);
1059 g_fprintf (bout
, "%u.%u.%u", GLIB_MAJOR_VERSION
, GLIB_MINOR_VERSION
, GLIB_MICRO_VERSION
);
1060 g_fprintf (bout
, "\n");
1061 g_fprintf (bout
, "%s comes with ABSOLUTELY NO WARRANTY.\n", PRG_NAME
);
1062 g_fprintf (bout
, "You may redistribute copies of %s under the terms of\n", PRG_NAME
);
1063 g_fprintf (bout
, "the GNU General Public License which can be found in the\n");
1064 g_fprintf (bout
, "%s source package. Sources, examples and contact\n", PKG_NAME
);
1065 g_fprintf (bout
, "information are available at %s\n", PKG_HTTP_HOME
);
1069 g_fprintf (bout
, "Usage:\n");
1070 g_fprintf (bout
, " %s [OPTION...] [FILES...]\n\n", PRG_NAME
);
1071 g_fprintf (bout
, "Help Options:\n");
1072 g_fprintf (bout
, " -h, --help Show this help message\n\n");
1073 g_fprintf (bout
, "Utility Options:\n");
1074 g_fprintf (bout
, " --header Generate C headers\n");
1075 g_fprintf (bout
, " --body Generate C code\n");
1076 g_fprintf (bout
, " --prefix=string Specify marshaller prefix\n");
1077 g_fprintf (bout
, " --skip-source Skip source location comments\n");
1078 g_fprintf (bout
, " --stdinc, --nostdinc Include/use standard marshallers\n");
1079 g_fprintf (bout
, " --internal Mark generated functions as internal\n");
1080 g_fprintf (bout
, " --valist-marshallers Generate va_list marshallers\n");
1081 g_fprintf (bout
, " -v, --version Print version informations\n");
1082 g_fprintf (bout
, " --g-fatal-warnings Make warnings fatal (abort)\n");