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>
33 #define G_LOG_DOMAIN "GLib-Genmarshal"
35 #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
*getter
; /* value getter function [g_value_get_string] */
57 gchar
*keyword
; /* marhaller list keyword [MY_STRING] */
58 const gchar
*sig_name
; /* signature name [STRING] */
59 const gchar
*ctype
; /* C type name [gchar*] */
60 const gchar
*setter
; /* value setter function [g_value_set_string] */
66 GList
*args
; /* of type InArgument* */
70 /* --- prototypes --- */
71 static void parse_args (gint
*argc_p
,
73 static void print_blurb (FILE *bout
,
77 /* --- variables --- */
78 static const GScannerConfig scanner_config_template
=
81 " \t\r" /* "\n" is statement delimiter */
82 ) /* cset_skip_characters */,
87 ) /* cset_identifier_first */,
92 ) /* cset_identifier_nth */,
93 ( "#\n" ) /* cpair_comment_single */,
95 FALSE
/* case_sensitive */,
97 TRUE
/* skip_comment_multi */,
98 TRUE
/* skip_comment_single */,
99 TRUE
/* scan_comment_multi */,
100 TRUE
/* scan_identifier */,
101 FALSE
/* scan_identifier_1char */,
102 FALSE
/* scan_identifier_NULL */,
103 TRUE
/* scan_symbols */,
104 FALSE
/* scan_binary */,
105 TRUE
/* scan_octal */,
106 TRUE
/* scan_float */,
108 FALSE
/* scan_hex_dollar */,
109 TRUE
/* scan_string_sq */,
110 TRUE
/* scan_string_dq */,
111 TRUE
/* numbers_2_int */,
112 FALSE
/* int_2_float */,
113 FALSE
/* identifier_2_string */,
114 TRUE
/* char_2_token */,
115 FALSE
/* symbol_2_token */,
116 FALSE
/* scope_0_fallback */,
118 static gchar
* const std_marshaller_prefix
= "g_cclosure_marshal";
119 static gchar
*marshaller_prefix
= "g_cclosure_user_marshal";
120 static GHashTable
*marshallers
= NULL
;
121 static FILE *fout
= NULL
;
122 static gboolean gen_cheader
= FALSE
;
123 static gboolean gen_cbody
= FALSE
;
124 static gboolean gen_internal
= FALSE
;
125 static gboolean skip_ploc
= FALSE
;
126 static gboolean std_includes
= TRUE
;
127 static gint exit_status
= 0;
130 /* --- functions --- */
132 put_marshal_value_getters (void)
135 fputs ("#ifdef G_ENABLE_DEBUG\n", fout
);
136 fputs ("#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)\n", fout
);
137 fputs ("#define g_marshal_value_peek_char(v) g_value_get_char (v)\n", fout
);
138 fputs ("#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)\n", fout
);
139 fputs ("#define g_marshal_value_peek_int(v) g_value_get_int (v)\n", fout
);
140 fputs ("#define g_marshal_value_peek_uint(v) g_value_get_uint (v)\n", fout
);
141 fputs ("#define g_marshal_value_peek_long(v) g_value_get_long (v)\n", fout
);
142 fputs ("#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)\n", fout
);
143 fputs ("#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)\n", fout
);
144 fputs ("#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)\n", fout
);
145 fputs ("#define g_marshal_value_peek_enum(v) g_value_get_enum (v)\n", fout
);
146 fputs ("#define g_marshal_value_peek_flags(v) g_value_get_flags (v)\n", fout
);
147 fputs ("#define g_marshal_value_peek_float(v) g_value_get_float (v)\n", fout
);
148 fputs ("#define g_marshal_value_peek_double(v) g_value_get_double (v)\n", fout
);
149 fputs ("#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)\n", fout
);
150 fputs ("#define g_marshal_value_peek_param(v) g_value_get_param (v)\n", fout
);
151 fputs ("#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)\n", fout
);
152 fputs ("#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)\n", fout
);
153 fputs ("#define g_marshal_value_peek_object(v) g_value_get_object (v)\n", fout
);
154 fputs ("#define g_marshal_value_peek_variant(v) g_value_get_variant (v)\n", fout
);
155 fputs ("#else /* !G_ENABLE_DEBUG */\n", fout
);
156 fputs ("/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.\n", fout
);
157 fputs (" * Do not access GValues directly in your code. Instead, use the\n", fout
);
158 fputs (" * g_value_get_*() functions\n", fout
);
159 fputs (" */\n", fout
);
160 fputs ("#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int\n", fout
);
161 fputs ("#define g_marshal_value_peek_char(v) (v)->data[0].v_int\n", fout
);
162 fputs ("#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint\n", fout
);
163 fputs ("#define g_marshal_value_peek_int(v) (v)->data[0].v_int\n", fout
);
164 fputs ("#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint\n", fout
);
165 fputs ("#define g_marshal_value_peek_long(v) (v)->data[0].v_long\n", fout
);
166 fputs ("#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong\n", fout
);
167 fputs ("#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64\n", fout
);
168 fputs ("#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64\n", fout
);
169 fputs ("#define g_marshal_value_peek_enum(v) (v)->data[0].v_long\n", fout
);
170 fputs ("#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong\n", fout
);
171 fputs ("#define g_marshal_value_peek_float(v) (v)->data[0].v_float\n", fout
);
172 fputs ("#define g_marshal_value_peek_double(v) (v)->data[0].v_double\n", fout
);
173 fputs ("#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer\n", fout
);
174 fputs ("#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer\n", fout
);
175 fputs ("#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer\n", fout
);
176 fputs ("#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer\n", fout
);
177 fputs ("#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer\n", fout
);
178 fputs ("#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer\n", fout
);
179 fputs ("#endif /* !G_ENABLE_DEBUG */\n", fout
);
184 complete_in_arg (InArgument
*iarg
)
186 static const InArgument args
[] = {
187 /* keyword sig_name ctype getter */
188 { "VOID", "VOID", "void", NULL
, },
189 { "BOOLEAN", "BOOLEAN", "gboolean", "g_marshal_value_peek_boolean", },
190 { "CHAR", "CHAR", "gchar", "g_marshal_value_peek_char", },
191 { "UCHAR", "UCHAR", "guchar", "g_marshal_value_peek_uchar", },
192 { "INT", "INT", "gint", "g_marshal_value_peek_int", },
193 { "UINT", "UINT", "guint", "g_marshal_value_peek_uint", },
194 { "LONG", "LONG", "glong", "g_marshal_value_peek_long", },
195 { "ULONG", "ULONG", "gulong", "g_marshal_value_peek_ulong", },
196 { "INT64", "INT64", "gint64", "g_marshal_value_peek_int64", },
197 { "UINT64", "UINT64", "guint64", "g_marshal_value_peek_uint64", },
198 { "ENUM", "ENUM", "gint", "g_marshal_value_peek_enum", },
199 { "FLAGS", "FLAGS", "guint", "g_marshal_value_peek_flags", },
200 { "FLOAT", "FLOAT", "gfloat", "g_marshal_value_peek_float", },
201 { "DOUBLE", "DOUBLE", "gdouble", "g_marshal_value_peek_double", },
202 { "STRING", "STRING", "gpointer", "g_marshal_value_peek_string", },
203 { "PARAM", "PARAM", "gpointer", "g_marshal_value_peek_param", },
204 { "BOXED", "BOXED", "gpointer", "g_marshal_value_peek_boxed", },
205 { "POINTER", "POINTER", "gpointer", "g_marshal_value_peek_pointer", },
206 { "OBJECT", "OBJECT", "gpointer", "g_marshal_value_peek_object", },
207 { "VARIANT", "VARIANT", "gpointer", "g_marshal_value_peek_variant", },
209 { "NONE", "VOID", "void", NULL
, },
210 { "BOOL", "BOOLEAN", "gboolean", "g_marshal_value_peek_boolean", },
214 g_return_val_if_fail (iarg
!= NULL
, FALSE
);
216 for (i
= 0; i
< G_N_ELEMENTS (args
); i
++)
217 if (strcmp (args
[i
].keyword
, iarg
->keyword
) == 0)
219 iarg
->sig_name
= args
[i
].sig_name
;
220 iarg
->ctype
= args
[i
].ctype
;
221 iarg
->getter
= args
[i
].getter
;
229 complete_out_arg (OutArgument
*oarg
)
231 static const OutArgument args
[] = {
232 /* keyword sig_name ctype setter */
233 { "VOID", "VOID", "void", NULL
, },
234 { "BOOLEAN", "BOOLEAN", "gboolean", "g_value_set_boolean", },
235 { "CHAR", "CHAR", "gchar", "g_value_set_char", },
236 { "UCHAR", "UCHAR", "guchar", "g_value_set_uchar", },
237 { "INT", "INT", "gint", "g_value_set_int", },
238 { "UINT", "UINT", "guint", "g_value_set_uint", },
239 { "LONG", "LONG", "glong", "g_value_set_long", },
240 { "ULONG", "ULONG", "gulong", "g_value_set_ulong", },
241 { "INT64", "INT64", "gint64", "g_value_set_int64", },
242 { "UINT64", "UINT64", "guint64", "g_value_set_uint64", },
243 { "ENUM", "ENUM", "gint", "g_value_set_enum", },
244 { "FLAGS", "FLAGS", "guint", "g_value_set_flags", },
245 { "FLOAT", "FLOAT", "gfloat", "g_value_set_float", },
246 { "DOUBLE", "DOUBLE", "gdouble", "g_value_set_double", },
247 { "STRING", "STRING", "gchar*", "g_value_take_string", },
248 { "PARAM", "PARAM", "GParamSpec*", "g_value_take_param", },
249 { "BOXED", "BOXED", "gpointer", "g_value_take_boxed", },
250 { "POINTER", "POINTER", "gpointer", "g_value_set_pointer", },
251 { "OBJECT", "OBJECT", "GObject*", "g_value_take_object", },
252 { "VARIANT", "VARIANT", "GVariant*", "g_value_take_variant", },
254 { "NONE", "VOID", "void", NULL
, },
255 { "BOOL", "BOOLEAN", "gboolean", "g_value_set_boolean", },
259 g_return_val_if_fail (oarg
!= NULL
, FALSE
);
261 for (i
= 0; i
< G_N_ELEMENTS (args
); i
++)
262 if (strcmp (args
[i
].keyword
, oarg
->keyword
) == 0)
264 oarg
->sig_name
= args
[i
].sig_name
;
265 oarg
->ctype
= args
[i
].ctype
;
266 oarg
->setter
= args
[i
].setter
;
274 pad (const gchar
*string
)
276 #define PAD_LENGTH 12
277 static gchar
*buffer
= NULL
;
280 g_return_val_if_fail (string
!= NULL
, NULL
);
283 buffer
= g_new (gchar
, PAD_LENGTH
+ 1);
286 if (strlen (string
) >= PAD_LENGTH
)
289 buffer
= g_strdup_printf ("%s ", string
);
290 g_warning ("overfull string (%u bytes) for padspace",
291 (guint
) strlen (string
));
297 for (i
= 0; i
< PAD_LENGTH
; i
++)
299 gboolean done
= *string
== 0;
301 buffer
[i
] = done
? ' ' : *string
++;
309 indent (guint n_spaces
)
311 static gchar
*buffer
= NULL
;
312 static guint blength
= 0;
314 if (blength
<= n_spaces
)
316 blength
= n_spaces
+ 1;
318 buffer
= g_new (gchar
, blength
);
320 memset (buffer
, ' ', n_spaces
);
321 buffer
[n_spaces
] = 0;
327 generate_marshal (const gchar
*signame
,
332 gchar
*tmp
= g_strconcat (marshaller_prefix
, "_", signame
, NULL
);
333 gboolean have_std_marshaller
= FALSE
;
335 /* here we have to make sure a marshaller named <marshaller_prefix>_<signame>
336 * exists. we might have put it out already, can revert to a standard
337 * marshaller provided by glib, or need to generate one.
340 if (g_hash_table_lookup (marshallers
, tmp
))
342 /* done, marshaller already generated */
348 /* need to alias/generate marshaller, register name */
349 g_hash_table_insert (marshallers
, tmp
, tmp
);
352 /* can we revert to a standard marshaller? */
355 tmp
= g_strconcat (std_marshaller_prefix
, "_", signame
, NULL
);
356 have_std_marshaller
= g_hash_table_lookup (marshallers
, tmp
) != NULL
;
360 if (gen_cheader
&& have_std_marshaller
)
362 g_fprintf (fout
, "#define %s_%s\t%s_%s\n", marshaller_prefix
, signame
, std_marshaller_prefix
, signame
);
364 if (gen_cheader
&& !have_std_marshaller
)
366 ind
= g_fprintf (fout
, gen_internal
? "G_GNUC_INTERNAL " : "extern ");
367 ind
+= g_fprintf (fout
, "void ");
368 ind
+= g_fprintf (fout
, "%s_%s (", marshaller_prefix
, signame
);
369 g_fprintf (fout
, "GClosure *closure,\n");
370 g_fprintf (fout
, "%sGValue *return_value,\n", indent (ind
));
371 g_fprintf (fout
, "%sguint n_param_values,\n", indent (ind
));
372 g_fprintf (fout
, "%sconst GValue *param_values,\n", indent (ind
));
373 g_fprintf (fout
, "%sgpointer invocation_hint,\n", indent (ind
));
374 g_fprintf (fout
, "%sgpointer marshal_data);\n",
377 if (gen_cbody
&& !have_std_marshaller
)
379 /* cfile marshal header */
380 g_fprintf (fout
, "void\n");
381 ind
= g_fprintf (fout
, "%s_%s (", marshaller_prefix
, signame
);
382 g_fprintf (fout
, "GClosure *closure,\n");
383 g_fprintf (fout
, "%sGValue *return_value G_GNUC_UNUSED,\n", indent (ind
));
384 g_fprintf (fout
, "%sguint n_param_values,\n", indent (ind
));
385 g_fprintf (fout
, "%sconst GValue *param_values,\n", indent (ind
));
386 g_fprintf (fout
, "%sgpointer invocation_hint G_GNUC_UNUSED,\n", indent (ind
));
387 g_fprintf (fout
, "%sgpointer marshal_data)\n", indent (ind
));
388 g_fprintf (fout
, "{\n");
390 /* cfile GMarshalFunc typedef */
391 ind
= g_fprintf (fout
, " typedef %s (*GMarshalFunc_%s) (", sig
->rarg
->ctype
, signame
);
392 g_fprintf (fout
, "%s data1,\n", pad ("gpointer"));
393 for (a
= 1, node
= sig
->args
; node
; node
= node
->next
)
395 InArgument
*iarg
= node
->data
;
398 g_fprintf (fout
, "%s%s arg_%d,\n", indent (ind
), pad (iarg
->ctype
), a
++);
400 g_fprintf (fout
, "%s%s data2);\n", indent (ind
), pad ("gpointer"));
402 /* cfile marshal variables */
403 g_fprintf (fout
, " register GMarshalFunc_%s callback;\n", signame
);
404 g_fprintf (fout
, " register GCClosure *cc = (GCClosure*) closure;\n");
405 g_fprintf (fout
, " register gpointer data1, data2;\n");
406 if (sig
->rarg
->setter
)
407 g_fprintf (fout
, " %s v_return;\n", sig
->rarg
->ctype
);
409 if (sig
->args
|| sig
->rarg
->setter
)
411 g_fprintf (fout
, "\n");
413 if (sig
->rarg
->setter
)
414 g_fprintf (fout
, " g_return_if_fail (return_value != NULL);\n");
417 for (a
= 0, node
= sig
->args
; node
; node
= node
->next
)
419 InArgument
*iarg
= node
->data
;
424 g_fprintf (fout
, " g_return_if_fail (n_param_values == %u);\n", 1 + a
);
428 /* cfile marshal data1, data2 and callback setup */
429 g_fprintf (fout
, "\n");
430 g_fprintf (fout
, " if (G_CCLOSURE_SWAP_DATA (closure))\n {\n");
431 g_fprintf (fout
, " data1 = closure->data;\n");
432 g_fprintf (fout
, " data2 = g_value_peek_pointer (param_values + 0);\n");
433 g_fprintf (fout
, " }\n else\n {\n");
434 g_fprintf (fout
, " data1 = g_value_peek_pointer (param_values + 0);\n");
435 g_fprintf (fout
, " data2 = closure->data;\n");
436 g_fprintf (fout
, " }\n");
437 g_fprintf (fout
, " callback = (GMarshalFunc_%s) (marshal_data ? marshal_data : cc->callback);\n", signame
);
439 /* cfile marshal callback action */
440 g_fprintf (fout
, "\n");
441 ind
= g_fprintf (fout
, " %s callback (", sig
->rarg
->setter
? " v_return =" : "");
442 g_fprintf (fout
, "data1,\n");
443 for (a
= 1, node
= sig
->args
; node
; node
= node
->next
)
445 InArgument
*iarg
= node
->data
;
448 g_fprintf (fout
, "%s%s (param_values + %d),\n", indent (ind
), iarg
->getter
, a
++);
450 g_fprintf (fout
, "%sdata2);\n", indent (ind
));
452 /* cfile marshal return value storage */
453 if (sig
->rarg
->setter
)
455 g_fprintf (fout
, "\n");
456 g_fprintf (fout
, " %s (return_value, v_return);\n", sig
->rarg
->setter
);
459 /* cfile marshal footer */
460 g_fprintf (fout
, "}\n");
465 process_signature (Signature
*sig
)
467 gchar
*pname
, *sname
, *tmp
;
470 /* lookup and complete info on arguments */
471 if (!complete_out_arg (sig
->rarg
))
473 g_warning ("unknown type: %s", sig
->rarg
->keyword
);
477 for (node
= sig
->args
; node
; node
= node
->next
)
479 InArgument
*iarg
= node
->data
;
481 if (!complete_in_arg (iarg
))
483 g_warning ("unknown type: %s", iarg
->keyword
);
489 /* construct requested marshaller name and technical marshaller name */
490 pname
= g_strconcat (sig
->rarg
->keyword
, "_", NULL
);
491 sname
= g_strconcat (sig
->rarg
->sig_name
, "_", NULL
);
492 for (node
= sig
->args
; node
; node
= node
->next
)
494 InArgument
*iarg
= node
->data
;
498 sname
= g_strconcat (tmp
, "_", iarg
->sig_name
, NULL
);
501 pname
= g_strconcat (tmp
, "_", iarg
->keyword
, NULL
);
505 /* introductionary comment */
506 g_fprintf (fout
, "\n/* %s", sig
->rarg
->keyword
);
507 for (node
= sig
->args
; node
; node
= node
->next
)
509 InArgument
*iarg
= node
->data
;
511 g_fprintf (fout
, "%c%s", node
->prev
? ',' : ':', iarg
->keyword
);
514 g_fprintf (fout
, " (%s)", sig
->ploc
);
515 g_fprintf (fout
, " */\n");
517 /* ensure technical marshaller exists (<marshaller_prefix>_<sname>) */
518 generate_marshal (sname
, sig
);
520 /* put out marshaller alias for requested name if required (<marshaller_prefix>_<pname>) */
521 tmp
= g_strconcat (marshaller_prefix
, "_", pname
, NULL
);
522 if (gen_cheader
&& !g_hash_table_lookup (marshallers
, tmp
))
524 g_fprintf (fout
, "#define %s_%s\t%s_%s\n", marshaller_prefix
, pname
, marshaller_prefix
, sname
);
526 g_hash_table_insert (marshallers
, tmp
, tmp
);
536 new_in_arg (const gchar
*pname
)
538 InArgument
*iarg
= g_new0 (InArgument
, 1);
540 iarg
->keyword
= g_strdup (pname
);
546 new_out_arg (const gchar
*pname
)
548 OutArgument
*oarg
= g_new0 (OutArgument
, 1);
550 oarg
->keyword
= g_strdup (pname
);
556 parse_line (GScanner
*scanner
,
559 /* parse identifier for return value */
560 if (g_scanner_get_next_token (scanner
) != G_TOKEN_IDENTIFIER
)
561 return G_TOKEN_IDENTIFIER
;
562 sig
->rarg
= new_out_arg (scanner
->value
.v_identifier
);
564 /* keep a note on the location */
565 sig
->ploc
= g_strdup_printf ("%s:%u", scanner
->input_name
, scanner
->line
);
568 if (g_scanner_get_next_token (scanner
) != ':')
571 /* parse first argument */
572 if (g_scanner_get_next_token (scanner
) != G_TOKEN_IDENTIFIER
)
573 return G_TOKEN_IDENTIFIER
;
574 sig
->args
= g_list_append (sig
->args
, new_in_arg (scanner
->value
.v_identifier
));
576 /* parse rest of argument list */
577 while (g_scanner_peek_next_token (scanner
) == ',')
580 g_scanner_get_next_token (scanner
);
582 /* parse arg identifier */
583 if (g_scanner_get_next_token (scanner
) != G_TOKEN_IDENTIFIER
)
584 return G_TOKEN_IDENTIFIER
;
585 sig
->args
= g_list_append (sig
->args
, new_in_arg (scanner
->value
.v_identifier
));
588 /* expect end of line, done */
589 if (g_scanner_get_next_token (scanner
) != '\n')
597 string_key_destroy (gpointer key
,
610 const gchar
*gobject_marshallers
[] = {
611 #include "gmarshal.strings"
614 GSList
*slist
, *files
= NULL
;
617 /* parse args and do fast exits */
618 parse_args (&argc
, &argv
);
620 /* list input files */
621 for (i
= 1; i
< argc
; i
++)
622 files
= g_slist_prepend (files
, argv
[i
]);
624 files
= g_slist_reverse (files
);
626 files
= g_slist_prepend (files
, "/dev/stdin");
628 /* setup auxiliary structs */
629 scanner
= g_scanner_new (&scanner_config_template
);
631 marshallers
= g_hash_table_new (g_str_hash
, g_str_equal
);
633 /* add standard marshallers of the GObject library */
635 for (i
= 0; i
< G_N_ELEMENTS (gobject_marshallers
); i
++)
637 gchar
*tmp
= g_strdup (gobject_marshallers
[i
]);
639 g_hash_table_insert (marshallers
, tmp
, tmp
);
642 /* put out initial heading */
643 g_fprintf (fout
, "\n");
645 if (gen_cheader
&& std_includes
)
647 g_fprintf (fout
, "#ifndef __%s_MARSHAL_H__\n", marshaller_prefix
);
648 g_fprintf (fout
, "#define __%s_MARSHAL_H__\n\n", marshaller_prefix
);
651 if ((gen_cheader
|| gen_cbody
) && std_includes
)
652 g_fprintf (fout
, "#include\t<glib-object.h>\n\n");
655 g_fprintf (fout
, "G_BEGIN_DECLS\n");
657 /* generate necessary preprocessor directives */
659 put_marshal_value_getters ();
661 /* process input files */
662 for (slist
= files
; slist
; slist
= slist
->next
)
664 gchar
*file
= slist
->data
;
667 if (strcmp (file
, "/dev/stdin") == 0)
668 /* Mostly for Win32. This is equivalent to opening /dev/stdin */
671 fd
= open (file
, O_RDONLY
);
675 g_warning ("failed to open \"%s\": %s", file
, g_strerror (errno
));
680 /* set file name for error reports */
681 scanner
->input_name
= file
;
683 /* parse & process file */
684 g_scanner_input_file (scanner
, fd
);
686 /* scanning loop, we parse the input until its end is reached,
687 * or our sub routine came across invalid syntax
691 guint expected_token
= G_TOKEN_NONE
;
693 switch ((guint
) g_scanner_peek_next_token (scanner
))
696 /* eat newline and restart */
697 g_scanner_get_next_token (scanner
);
703 /* parse and process signatures */
705 Signature signature
= { NULL
, NULL
, NULL
};
708 expected_token
= parse_line (scanner
, &signature
);
710 /* once we got a valid signature, process it */
711 if (expected_token
== G_TOKEN_NONE
)
712 process_signature (&signature
);
714 /* clean up signature contents */
715 g_free (signature
.ploc
);
717 g_free (signature
.rarg
->keyword
);
718 g_free (signature
.rarg
);
719 for (node
= signature
.args
; node
; node
= node
->next
)
721 InArgument
*iarg
= node
->data
;
723 g_free (iarg
->keyword
);
726 g_list_free (signature
.args
);
731 /* bail out on errors */
732 if (expected_token
!= G_TOKEN_NONE
)
734 g_scanner_unexp_token (scanner
, expected_token
, "type name", NULL
, NULL
, NULL
, TRUE
);
739 g_scanner_peek_next_token (scanner
);
741 while (scanner
->next_token
!= G_TOKEN_EOF
);
746 /* put out trailer */
749 g_fprintf (fout
, "\nG_END_DECLS\n");
752 g_fprintf (fout
, "\n#endif /* __%s_MARSHAL_H__ */\n", marshaller_prefix
);
754 g_fprintf (fout
, "\n");
757 g_slist_free (files
);
758 g_scanner_destroy (scanner
);
759 g_hash_table_foreach_remove (marshallers
, string_key_destroy
, NULL
);
760 g_hash_table_destroy (marshallers
);
766 parse_args (gint
*argc_p
,
769 guint argc
= *argc_p
;
770 gchar
**argv
= *argv_p
;
773 for (i
= 1; i
< argc
; i
++)
775 if (strcmp ("--header", argv
[i
]) == 0)
780 else if (strcmp ("--body", argv
[i
]) == 0)
785 else if (strcmp ("--skip-source", argv
[i
]) == 0)
790 else if (strcmp ("--nostdinc", argv
[i
]) == 0)
792 std_includes
= FALSE
;
795 else if (strcmp ("--stdinc", argv
[i
]) == 0)
800 else if (strcmp ("--internal", argv
[i
]) == 0)
805 else if ((strcmp ("--prefix", argv
[i
]) == 0) ||
806 (strncmp ("--prefix=", argv
[i
], 9) == 0))
808 gchar
*equal
= argv
[i
] + 8;
811 marshaller_prefix
= g_strdup (equal
+ 1);
812 else if (i
+ 1 < argc
)
814 marshaller_prefix
= g_strdup (argv
[i
+ 1]);
820 else if (strcmp ("-h", argv
[i
]) == 0 ||
821 strcmp ("-?", argv
[i
]) == 0 ||
822 strcmp ("--help", argv
[i
]) == 0)
824 print_blurb (stderr
, TRUE
);
828 else if (strcmp ("-v", argv
[i
]) == 0 ||
829 strcmp ("--version", argv
[i
]) == 0)
831 print_blurb (stderr
, FALSE
);
835 else if (strcmp (argv
[i
], "--g-fatal-warnings") == 0)
837 GLogLevelFlags fatal_mask
;
839 fatal_mask
= g_log_set_always_fatal (G_LOG_FATAL_MASK
);
840 fatal_mask
|= G_LOG_LEVEL_WARNING
| G_LOG_LEVEL_CRITICAL
;
841 g_log_set_always_fatal (fatal_mask
);
848 for (i
= 1; i
< argc
; i
++)
866 print_blurb (FILE *bout
,
871 g_fprintf (bout
, "%s version ", PRG_NAME
);
872 g_fprintf (bout
, "%u.%u.%u", GLIB_MAJOR_VERSION
, GLIB_MINOR_VERSION
, GLIB_MICRO_VERSION
);
873 g_fprintf (bout
, "\n");
874 g_fprintf (bout
, "%s comes with ABSOLUTELY NO WARRANTY.\n", PRG_NAME
);
875 g_fprintf (bout
, "You may redistribute copies of %s under the terms of\n", PRG_NAME
);
876 g_fprintf (bout
, "the GNU General Public License which can be found in the\n");
877 g_fprintf (bout
, "%s source package. Sources, examples and contact\n", PKG_NAME
);
878 g_fprintf (bout
, "information are available at %s\n", PKG_HTTP_HOME
);
882 g_fprintf (bout
, "Usage:\n");
883 g_fprintf (bout
, " %s [OPTION...] [FILES...]\n\n", PRG_NAME
);
884 g_fprintf (bout
, "Help Options:\n");
885 g_fprintf (bout
, " -h, --help Show this help message\n\n");
886 g_fprintf (bout
, "Utility Options:\n");
887 g_fprintf (bout
, " --header Generate C headers\n");
888 g_fprintf (bout
, " --body Generate C code\n");
889 g_fprintf (bout
, " --prefix=string Specify marshaller prefix\n");
890 g_fprintf (bout
, " --skip-source Skip source location comments\n");
891 g_fprintf (bout
, " --stdinc, --nostdinc Include/use standard marshallers\n");
892 g_fprintf (bout
, " --internal Mark generated functions as internal\n");
893 g_fprintf (bout
, " -v, --version Print version informations\n");
894 g_fprintf (bout
, " --g-fatal-warnings Make warnings fatal (abort)\n");