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 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;
136 /* --- functions --- */
138 put_marshal_value_getters (void)
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
);
190 complete_in_arg (InArgument
*iarg
)
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"},
215 { "NONE", "VOID", "void", "void", NULL
, },
216 { "BOOL", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
220 g_return_val_if_fail (iarg
!= NULL
, FALSE
);
222 for (i
= 0; i
< G_N_ELEMENTS (args
); i
++)
223 if (strcmp (args
[i
].keyword
, iarg
->keyword
) == 0)
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
;
240 complete_out_arg (OutArgument
*oarg
)
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", },
265 { "NONE", "VOID", "void", NULL
, },
266 { "BOOL", "BOOLEAN", "gboolean", "g_value_set_boolean", },
270 g_return_val_if_fail (oarg
!= NULL
, FALSE
);
272 for (i
= 0; i
< G_N_ELEMENTS (args
); i
++)
273 if (strcmp (args
[i
].keyword
, oarg
->keyword
) == 0)
275 oarg
->sig_name
= args
[i
].sig_name
;
276 oarg
->ctype
= args
[i
].ctype
;
277 oarg
->setter
= args
[i
].setter
;
285 pad (const gchar
*string
)
287 #define PAD_LENGTH 12
288 static gchar
*buffer
= NULL
;
291 g_return_val_if_fail (string
!= NULL
, NULL
);
294 buffer
= g_new (gchar
, PAD_LENGTH
+ 1);
297 if (strlen (string
) >= PAD_LENGTH
)
300 buffer
= g_strdup_printf ("%s ", string
);
301 g_warning ("overfull string (%u bytes) for padspace",
302 (guint
) strlen (string
));
308 for (i
= 0; i
< PAD_LENGTH
; i
++)
310 gboolean done
= *string
== 0;
312 buffer
[i
] = done
? ' ' : *string
++;
320 indent (guint n_spaces
)
322 static gchar
*buffer
= NULL
;
323 static guint blength
= 0;
325 if (blength
<= n_spaces
)
327 blength
= n_spaces
+ 1;
329 buffer
= g_new (gchar
, blength
);
331 memset (buffer
, ' ', n_spaces
);
332 buffer
[n_spaces
] = 0;
338 generate_marshal (const gchar
*signame
,
343 gchar
*tmp
= g_strconcat (marshaller_prefix
, "_", signame
, NULL
);
344 gboolean have_std_marshaller
= FALSE
;
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.
351 if (g_hash_table_lookup (marshallers
, tmp
))
353 /* done, marshaller already generated */
359 /* need to alias/generate marshaller, register name */
360 g_hash_table_insert (marshallers
, tmp
, tmp
);
363 /* can we revert to a standard marshaller? */
366 tmp
= g_strconcat (std_marshaller_prefix
, "_", signame
, NULL
);
367 have_std_marshaller
= g_hash_table_lookup (marshallers
, tmp
) != NULL
;
371 /* GValue marshaller */
372 if (gen_cheader
&& have_std_marshaller
)
374 g_fprintf (fout
, "#define %s_%s\t%s_%s\n", marshaller_prefix
, signame
, std_marshaller_prefix
, signame
);
376 if (gen_cheader
&& !have_std_marshaller
)
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",
389 if (gen_cbody
&& !have_std_marshaller
)
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");
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
)
407 InArgument
*iarg
= node
->data
;
410 g_fprintf (fout
, "%s%s arg_%d,\n", indent (ind
), pad (iarg
->ctype
), a
++);
412 g_fprintf (fout
, "%s%s data2);\n", indent (ind
), pad ("gpointer"));
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
);
421 if (sig
->args
|| sig
->rarg
->setter
)
423 g_fprintf (fout
, "\n");
425 if (sig
->rarg
->setter
)
426 g_fprintf (fout
, " g_return_if_fail (return_value != NULL);\n");
429 for (a
= 0, node
= sig
->args
; node
; node
= node
->next
)
431 InArgument
*iarg
= node
->data
;
436 g_fprintf (fout
, " g_return_if_fail (n_param_values == %u);\n", 1 + a
);
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
);
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
)
457 InArgument
*iarg
= node
->data
;
460 g_fprintf (fout
, "%s%s (param_values + %d),\n", indent (ind
), iarg
->getter
, a
++);
462 g_fprintf (fout
, "%sdata2);\n", indent (ind
));
464 /* cfile marshal return value storage */
465 if (sig
->rarg
->setter
)
467 g_fprintf (fout
, "\n");
468 g_fprintf (fout
, " %s (return_value, v_return);\n", sig
->rarg
->setter
);
471 /* cfile marshal footer */
472 g_fprintf (fout
, "}\n");
476 /* vararg marshaller */
477 if (gen_cheader
&& gen_valist
&& have_std_marshaller
)
479 g_fprintf (fout
, "#define %s_%sv\t%s_%sv\n", marshaller_prefix
, signame
, std_marshaller_prefix
, signame
);
481 if (gen_cheader
&& gen_valist
&& !have_std_marshaller
)
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
));
494 if (gen_cbody
&& gen_valist
&& !have_std_marshaller
)
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");
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
)
514 InArgument
*iarg
= node
->data
;
517 g_fprintf (fout
, ",\n%s%s arg_%d", indent (ind
), pad (iarg
->ctype
), a
++);
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
);
526 for (node
= sig
->args
; node
; node
= node
->next
)
528 InArgument
*iarg
= node
->data
;
532 g_fprintf (fout
, " %s arg%i;\n", iarg
->ctype
, i
++);
537 g_fprintf (fout
, " va_list args_copy;\n");
539 if (sig
->rarg
->setter
)
540 g_fprintf (fout
, " %s v_return;\n", sig
->rarg
->ctype
);
542 if (sig
->rarg
->setter
)
544 g_fprintf (fout
, "\n");
545 g_fprintf (fout
, " g_return_if_fail (return_value != NULL);\n");
548 /* cfile marshal data1, data2 and callback setup */
551 g_fprintf (fout
, "\n");
552 g_fprintf (fout
, " G_VA_COPY (args_copy, args);\n");
554 for (node
= sig
->args
; node
; node
= node
->next
)
556 InArgument
*iarg
= node
->data
;
560 g_fprintf (fout
, " arg%i = (%s) va_arg (args_copy, %s);\n",
561 i
, iarg
->ctype
, iarg
->promoted_ctype
);
563 if (iarg
->box
!= NULL
)
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
)
571 " arg%i = %s (param_types[%i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg%i);\n",
575 " arg%i = %s (arg%i);\n",
581 g_fprintf (fout
, " va_end (args_copy);\n");
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
);
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");
601 for (node
= sig
->args
; node
; node
= node
->next
)
603 InArgument
*iarg
= node
->data
;
606 g_fprintf (fout
, ",\n%sarg%i", indent (ind
), i
++);
608 g_fprintf (fout
, ",\n%sdata2);\n", indent (ind
));
611 for (node
= sig
->args
; node
; node
= node
->next
)
613 InArgument
*iarg
= node
->data
;
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
)
623 " %s (param_types[%i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg%i);\n",
633 /* cfile marshal return value storage */
634 if (sig
->rarg
->setter
)
636 g_fprintf (fout
, "\n");
637 g_fprintf (fout
, " %s (return_value, v_return);\n", sig
->rarg
->setter
);
640 g_fprintf (fout
, "}\n\n");
645 process_signature (Signature
*sig
)
647 gchar
*pname
, *sname
, *tmp
;
650 /* lookup and complete info on arguments */
651 if (!complete_out_arg (sig
->rarg
))
653 g_warning ("unknown type: %s", sig
->rarg
->keyword
);
657 for (node
= sig
->args
; node
; node
= node
->next
)
659 InArgument
*iarg
= node
->data
;
661 if (!complete_in_arg (iarg
))
663 g_warning ("unknown type: %s", iarg
->keyword
);
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
)
674 InArgument
*iarg
= node
->data
;
678 sname
= g_strconcat (tmp
, "_", iarg
->sig_name
, NULL
);
681 pname
= g_strconcat (tmp
, "_", iarg
->keyword
, NULL
);
685 /* introductionary comment */
686 g_fprintf (fout
, "\n/* %s", sig
->rarg
->keyword
);
687 for (node
= sig
->args
; node
; node
= node
->next
)
689 InArgument
*iarg
= node
->data
;
691 g_fprintf (fout
, "%c%s", node
->prev
? ',' : ':', iarg
->keyword
);
694 g_fprintf (fout
, " (%s)", sig
->ploc
);
695 g_fprintf (fout
, " */\n");
697 /* ensure technical marshaller exists (<marshaller_prefix>_<sname>) */
698 generate_marshal (sname
, sig
);
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
))
704 g_fprintf (fout
, "#define %s_%s\t%s_%s\n", marshaller_prefix
, pname
, marshaller_prefix
, sname
);
706 g_hash_table_insert (marshallers
, tmp
, tmp
);
716 new_in_arg (const gchar
*pname
)
718 InArgument
*iarg
= g_new0 (InArgument
, 1);
720 iarg
->keyword
= g_strdup (pname
);
726 new_out_arg (const gchar
*pname
)
728 OutArgument
*oarg
= g_new0 (OutArgument
, 1);
730 oarg
->keyword
= g_strdup (pname
);
736 parse_line (GScanner
*scanner
,
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
);
744 /* keep a note on the location */
745 sig
->ploc
= g_strdup_printf ("%s:%u", scanner
->input_name
, scanner
->line
);
748 if (g_scanner_get_next_token (scanner
) != ':')
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
));
756 /* parse rest of argument list */
757 while (g_scanner_peek_next_token (scanner
) == ',')
760 g_scanner_get_next_token (scanner
);
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
));
768 /* expect end of line, done */
769 if (g_scanner_get_next_token (scanner
) != '\n')
777 string_key_destroy (gpointer key
,
790 const gchar
*gobject_marshallers
[] = {
791 #include "gmarshal.strings"
794 GSList
*slist
, *files
= NULL
;
797 /* parse args and do fast exits */
798 parse_args (&argc
, &argv
);
800 /* list input files */
801 for (i
= 1; i
< argc
; i
++)
802 files
= g_slist_prepend (files
, argv
[i
]);
804 files
= g_slist_reverse (files
);
806 files
= g_slist_prepend (files
, "/dev/stdin");
808 /* setup auxiliary structs */
809 scanner
= g_scanner_new (&scanner_config_template
);
811 marshallers
= g_hash_table_new (g_str_hash
, g_str_equal
);
813 /* add standard marshallers of the GObject library */
815 for (i
= 0; i
< G_N_ELEMENTS (gobject_marshallers
); i
++)
817 gchar
*tmp
= g_strdup (gobject_marshallers
[i
]);
819 g_hash_table_insert (marshallers
, tmp
, tmp
);
822 /* put out initial heading */
823 g_fprintf (fout
, "\n");
825 if (gen_cheader
&& std_includes
)
827 g_fprintf (fout
, "#ifndef __%s_MARSHAL_H__\n", marshaller_prefix
);
828 g_fprintf (fout
, "#define __%s_MARSHAL_H__\n\n", marshaller_prefix
);
831 if ((gen_cheader
|| gen_cbody
) && std_includes
)
832 g_fprintf (fout
, "#include\t<glib-object.h>\n\n");
835 g_fprintf (fout
, "G_BEGIN_DECLS\n");
837 /* generate necessary preprocessor directives */
839 put_marshal_value_getters ();
841 /* process input files */
842 for (slist
= files
; slist
; slist
= slist
->next
)
844 gchar
*file
= slist
->data
;
847 if (strcmp (file
, "/dev/stdin") == 0)
848 /* Mostly for Win32. This is equivalent to opening /dev/stdin */
851 fd
= g_open (file
, O_RDONLY
, 0);
855 g_warning ("failed to open \"%s\": %s", file
, g_strerror (errno
));
860 /* set file name for error reports */
861 scanner
->input_name
= file
;
863 /* parse & process file */
864 g_scanner_input_file (scanner
, fd
);
866 /* scanning loop, we parse the input until its end is reached,
867 * or our sub routine came across invalid syntax
871 guint expected_token
= G_TOKEN_NONE
;
873 switch ((guint
) g_scanner_peek_next_token (scanner
))
876 /* eat newline and restart */
877 g_scanner_get_next_token (scanner
);
883 /* parse and process signatures */
885 Signature signature
= { NULL
, NULL
, NULL
};
888 expected_token
= parse_line (scanner
, &signature
);
890 /* once we got a valid signature, process it */
891 if (expected_token
== G_TOKEN_NONE
)
892 process_signature (&signature
);
894 /* clean up signature contents */
895 g_free (signature
.ploc
);
897 g_free (signature
.rarg
->keyword
);
898 g_free (signature
.rarg
);
899 for (node
= signature
.args
; node
; node
= node
->next
)
901 InArgument
*iarg
= node
->data
;
903 g_free (iarg
->keyword
);
906 g_list_free (signature
.args
);
911 /* bail out on errors */
912 if (expected_token
!= G_TOKEN_NONE
)
914 g_scanner_unexp_token (scanner
, expected_token
, "type name", NULL
, NULL
, NULL
, TRUE
);
919 g_scanner_peek_next_token (scanner
);
921 while (scanner
->next_token
!= G_TOKEN_EOF
);
926 /* put out trailer */
929 g_fprintf (fout
, "\nG_END_DECLS\n");
932 g_fprintf (fout
, "\n#endif /* __%s_MARSHAL_H__ */\n", marshaller_prefix
);
934 g_fprintf (fout
, "\n");
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
);
946 parse_args (gint
*argc_p
,
949 guint argc
= *argc_p
;
950 gchar
**argv
= *argv_p
;
953 for (i
= 1; i
< argc
; i
++)
955 if (strcmp ("--header", argv
[i
]) == 0)
960 else if (strcmp ("--body", argv
[i
]) == 0)
965 else if (strcmp ("--skip-source", argv
[i
]) == 0)
970 else if (strcmp ("--nostdinc", argv
[i
]) == 0)
972 std_includes
= FALSE
;
975 else if (strcmp ("--stdinc", argv
[i
]) == 0)
980 else if (strcmp ("--internal", argv
[i
]) == 0)
985 else if (strcmp ("--valist-marshallers", argv
[i
]) == 0)
990 else if ((strcmp ("--prefix", argv
[i
]) == 0) ||
991 (strncmp ("--prefix=", argv
[i
], 9) == 0))
993 gchar
*equal
= argv
[i
] + 8;
996 marshaller_prefix
= equal
+ 1;
997 else if (i
+ 1 < argc
)
999 marshaller_prefix
= argv
[i
+ 1];
1005 else if (strcmp ("-h", argv
[i
]) == 0 ||
1006 strcmp ("-?", argv
[i
]) == 0 ||
1007 strcmp ("--help", argv
[i
]) == 0)
1009 print_blurb (stderr
, TRUE
);
1013 else if (strcmp ("-v", argv
[i
]) == 0 ||
1014 strcmp ("--version", argv
[i
]) == 0)
1016 print_blurb (stderr
, FALSE
);
1020 else if (strcmp (argv
[i
], "--g-fatal-warnings") == 0)
1022 GLogLevelFlags fatal_mask
;
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
);
1033 for (i
= 1; i
< argc
; i
++)
1039 argv
[e
++] = argv
[i
];
1051 print_blurb (FILE *bout
,
1052 gboolean print_help
)
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
);
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");