diff -r e4d67989cc36 -r 47c74d1534e1 glib/gobject/glib-genmarshal.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glib/gobject/glib-genmarshal.c Fri Apr 16 16:46:38 2010 +0300 @@ -0,0 +1,912 @@ +/* GLIB-GenMarshal - Marshaller generator for GObject library + * Copyright (C) 2000-2001 Red Hat, Inc. + * Portions copyright (c) 2006-2009 Nokia Corporation. All rights reserved. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "GLib-Genmarshal" +#include +#include + +#ifdef G_OS_WIN32 +#include +#endif +#ifdef __SYMBIAN32__ +#include "mrt2_glib2_test.h" +#endif /*__SYMBIAN32__*/ + +/* --- defines --- */ +#define PRG_NAME "glib-genmarshal" +#define PKG_NAME "GLib" +#define PKG_HTTP_HOME "http://www.gtk.org" + + +/* --- typedefs & structures --- */ +typedef struct +{ + gchar *keyword; /* marhaller list keyword [MY_STRING] */ + const gchar *sig_name; /* signature name [STRING] */ + const gchar *ctype; /* C type name [gchar*] */ + const gchar *getter; /* value getter function [g_value_get_string] */ +} InArgument; +typedef struct +{ + gchar *keyword; /* marhaller list keyword [MY_STRING] */ + const gchar *sig_name; /* signature name [STRING] */ + const gchar *ctype; /* C type name [gchar*] */ + const gchar *setter; /* value setter function [g_value_set_string] */ +} OutArgument; +typedef struct +{ + gchar *ploc; + OutArgument *rarg; + GList *args; /* of type InArgument* */ +} Signature; + + +/* --- prototypes --- */ +static void parse_args (gint *argc_p, + gchar ***argv_p); +static void print_blurb (FILE *bout, + gboolean print_help); + + +/* --- variables --- */ +static const GScannerConfig scanner_config_template = +{ + ( + " \t\r" /* "\n" is statement delimiter */ + ) /* cset_skip_characters */, + ( + G_CSET_a_2_z + "_" + G_CSET_A_2_Z + ) /* cset_identifier_first */, + ( + G_CSET_a_2_z + "_0123456789" + G_CSET_A_2_Z + ) /* cset_identifier_nth */, + ( "#\n" ) /* cpair_comment_single */, + + FALSE /* case_sensitive */, + + TRUE /* skip_comment_multi */, + TRUE /* skip_comment_single */, + TRUE /* scan_comment_multi */, + TRUE /* scan_identifier */, + FALSE /* scan_identifier_1char */, + FALSE /* scan_identifier_NULL */, + TRUE /* scan_symbols */, + FALSE /* scan_binary */, + TRUE /* scan_octal */, + TRUE /* scan_float */, + TRUE /* scan_hex */, + FALSE /* scan_hex_dollar */, + TRUE /* scan_string_sq */, + TRUE /* scan_string_dq */, + TRUE /* numbers_2_int */, + FALSE /* int_2_float */, + FALSE /* identifier_2_string */, + TRUE /* char_2_token */, + FALSE /* symbol_2_token */, + FALSE /* scope_0_fallback */, +}; +static gchar * const std_marshaller_prefix = "g_cclosure_marshal"; +static gchar *marshaller_prefix = "g_cclosure_user_marshal"; +static GHashTable *marshallers = NULL; +static FILE *fout = NULL; +static gboolean gen_cheader = FALSE; +static gboolean gen_cbody = FALSE; +static gboolean gen_internal = FALSE; +static gboolean skip_ploc = FALSE; +static gboolean std_includes = TRUE; +static gint exit_status = 0; + + +/* --- functions --- */ +static void +put_marshal_value_getters (void) +{ + fputs ("\n", fout); + fputs ("#ifdef G_ENABLE_DEBUG\n", fout); + fputs ("#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)\n", fout); + fputs ("#define g_marshal_value_peek_char(v) g_value_get_char (v)\n", fout); + fputs ("#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)\n", fout); + fputs ("#define g_marshal_value_peek_int(v) g_value_get_int (v)\n", fout); + fputs ("#define g_marshal_value_peek_uint(v) g_value_get_uint (v)\n", fout); + fputs ("#define g_marshal_value_peek_long(v) g_value_get_long (v)\n", fout); + fputs ("#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)\n", fout); + fputs ("#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)\n", fout); + fputs ("#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)\n", fout); + fputs ("#define g_marshal_value_peek_enum(v) g_value_get_enum (v)\n", fout); + fputs ("#define g_marshal_value_peek_flags(v) g_value_get_flags (v)\n", fout); + fputs ("#define g_marshal_value_peek_float(v) g_value_get_float (v)\n", fout); + fputs ("#define g_marshal_value_peek_double(v) g_value_get_double (v)\n", fout); + fputs ("#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)\n", fout); + fputs ("#define g_marshal_value_peek_param(v) g_value_get_param (v)\n", fout); + fputs ("#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)\n", fout); + fputs ("#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)\n", fout); + fputs ("#define g_marshal_value_peek_object(v) g_value_get_object (v)\n", fout); + fputs ("#else /* !G_ENABLE_DEBUG */\n", fout); + fputs ("/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.\n", fout); + fputs (" * Do not access GValues directly in your code. Instead, use the\n", fout); + fputs (" * g_value_get_*() functions\n", fout); + fputs (" */\n", fout); + fputs ("#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int\n", fout); + fputs ("#define g_marshal_value_peek_char(v) (v)->data[0].v_int\n", fout); + fputs ("#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint\n", fout); + fputs ("#define g_marshal_value_peek_int(v) (v)->data[0].v_int\n", fout); + fputs ("#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint\n", fout); + fputs ("#define g_marshal_value_peek_long(v) (v)->data[0].v_long\n", fout); + fputs ("#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong\n", fout); + fputs ("#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64\n", fout); + fputs ("#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64\n", fout); + fputs ("#define g_marshal_value_peek_enum(v) (v)->data[0].v_long\n", fout); + fputs ("#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong\n", fout); + fputs ("#define g_marshal_value_peek_float(v) (v)->data[0].v_float\n", fout); + fputs ("#define g_marshal_value_peek_double(v) (v)->data[0].v_double\n", fout); + fputs ("#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer\n", fout); + fputs ("#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer\n", fout); + fputs ("#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer\n", fout); + fputs ("#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer\n", fout); + fputs ("#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer\n", fout); + fputs ("#endif /* !G_ENABLE_DEBUG */\n", fout); + fputs ("\n", fout); +} + +static gboolean +complete_in_arg (InArgument *iarg) +{ + static const InArgument args[] = { + /* keyword sig_name ctype getter */ + { "VOID", "VOID", "void", NULL, }, + { "BOOLEAN", "BOOLEAN", "gboolean", "g_marshal_value_peek_boolean", }, + { "CHAR", "CHAR", "gchar", "g_marshal_value_peek_char", }, + { "UCHAR", "UCHAR", "guchar", "g_marshal_value_peek_uchar", }, + { "INT", "INT", "gint", "g_marshal_value_peek_int", }, + { "UINT", "UINT", "guint", "g_marshal_value_peek_uint", }, + { "LONG", "LONG", "glong", "g_marshal_value_peek_long", }, + { "ULONG", "ULONG", "gulong", "g_marshal_value_peek_ulong", }, + { "INT64", "INT64", "gint64", "g_marshal_value_peek_int64", }, + { "UINT64", "UINT64", "guint64", "g_marshal_value_peek_uint64", }, + { "ENUM", "ENUM", "gint", "g_marshal_value_peek_enum", }, + { "FLAGS", "FLAGS", "guint", "g_marshal_value_peek_flags", }, + { "FLOAT", "FLOAT", "gfloat", "g_marshal_value_peek_float", }, + { "DOUBLE", "DOUBLE", "gdouble", "g_marshal_value_peek_double", }, + { "STRING", "STRING", "gpointer", "g_marshal_value_peek_string", }, + { "PARAM", "PARAM", "gpointer", "g_marshal_value_peek_param", }, + { "BOXED", "BOXED", "gpointer", "g_marshal_value_peek_boxed", }, + { "POINTER", "POINTER", "gpointer", "g_marshal_value_peek_pointer", }, + { "OBJECT", "OBJECT", "gpointer", "g_marshal_value_peek_object", }, + /* deprecated: */ + { "NONE", "VOID", "void", NULL, }, + { "BOOL", "BOOLEAN", "gboolean", "g_marshal_value_peek_boolean", }, + }; + guint i; + + g_return_val_if_fail (iarg != NULL, FALSE); + + for (i = 0; i < G_N_ELEMENTS (args); i++) + if (strcmp (args[i].keyword, iarg->keyword) == 0) + { + iarg->sig_name = args[i].sig_name; + iarg->ctype = args[i].ctype; + iarg->getter = args[i].getter; + + return TRUE; + } + return FALSE; +} + +static gboolean +complete_out_arg (OutArgument *oarg) +{ + static const OutArgument args[] = { + /* keyword sig_name ctype setter */ + { "VOID", "VOID", "void", NULL, }, + { "BOOLEAN", "BOOLEAN", "gboolean", "g_value_set_boolean", }, + { "CHAR", "CHAR", "gchar", "g_value_set_char", }, + { "UCHAR", "UCHAR", "guchar", "g_value_set_uchar", }, + { "INT", "INT", "gint", "g_value_set_int", }, + { "UINT", "UINT", "guint", "g_value_set_uint", }, + { "LONG", "LONG", "glong", "g_value_set_long", }, + { "ULONG", "ULONG", "gulong", "g_value_set_ulong", }, + { "INT64", "INT64", "gint64", "g_value_set_int64", }, + { "UINT64", "UINT64", "guint64", "g_value_set_uint64", }, + { "ENUM", "ENUM", "gint", "g_value_set_enum", }, + { "FLAGS", "FLAGS", "guint", "g_value_set_flags", }, + { "FLOAT", "FLOAT", "gfloat", "g_value_set_float", }, + { "DOUBLE", "DOUBLE", "gdouble", "g_value_set_double", }, + { "STRING", "STRING", "gchar*", "g_value_take_string", }, + { "PARAM", "PARAM", "GParamSpec*", "g_value_take_param", }, + { "BOXED", "BOXED", "gpointer", "g_value_take_boxed", }, + { "POINTER", "POINTER", "gpointer", "g_value_set_pointer", }, + { "OBJECT", "OBJECT", "GObject*", "g_value_take_object", }, + /* deprecated: */ + { "NONE", "VOID", "void", NULL, }, + { "BOOL", "BOOLEAN", "gboolean", "g_value_set_boolean", }, + }; + guint i; + + g_return_val_if_fail (oarg != NULL, FALSE); + + for (i = 0; i < G_N_ELEMENTS (args); i++) + if (strcmp (args[i].keyword, oarg->keyword) == 0) + { + oarg->sig_name = args[i].sig_name; + oarg->ctype = args[i].ctype; + oarg->setter = args[i].setter; + + return TRUE; + } + return FALSE; +} + +static const gchar* +pad (const gchar *string) +{ +#define PAD_LENGTH 12 + static gchar *buffer = NULL; + gint i; + + g_return_val_if_fail (string != NULL, NULL); + + if (!buffer) + buffer = g_new (gchar, PAD_LENGTH + 1); + + /* paranoid check */ + if (strlen (string) >= PAD_LENGTH) + { + g_free (buffer); + buffer = g_strdup_printf ("%s ", string); + g_warning ("overfull string (%u bytes) for padspace", + (guint) strlen (string)); + exit_status |= 2; + + return buffer; + } + + for (i = 0; i < PAD_LENGTH; i++) + { + gboolean done = *string == 0; + + buffer[i] = done ? ' ' : *string++; + } + buffer[i] = 0; + + return buffer; +} + +static const gchar* +indent (guint n_spaces) +{ + static gchar *buffer = NULL; + static guint blength = 0; + + if (blength <= n_spaces) + { + blength = n_spaces + 1; + g_free (buffer); + buffer = g_new (gchar, blength); + } + memset (buffer, ' ', n_spaces); + buffer[n_spaces] = 0; + + return buffer; +} + +static void +generate_marshal (const gchar *signame, + Signature *sig) +{ + guint ind, a; + GList *node; + gchar *tmp = g_strconcat (marshaller_prefix, "_", signame, NULL); + gboolean have_std_marshaller = FALSE; + + /* here we have to make sure a marshaller named _ + * exists. we might have put it out already, can revert to a standard + * marshaller provided by glib, or need to generate one. + */ + + if (g_hash_table_lookup (marshallers, tmp)) + { + /* done, marshaller already generated */ + g_free (tmp); + return; + } + else + { + /* need to alias/generate marshaller, register name */ + g_hash_table_insert (marshallers, tmp, tmp); + } + + /* can we revert to a standard marshaller? */ + if (std_includes) + { + tmp = g_strconcat (std_marshaller_prefix, "_", signame, NULL); + have_std_marshaller = g_hash_table_lookup (marshallers, tmp) != NULL; + g_free (tmp); + } + + if (gen_cheader && have_std_marshaller) + { + g_fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, signame, std_marshaller_prefix, signame); + } + if (gen_cheader && !have_std_marshaller) + { + ind = g_fprintf (fout, gen_internal ? "G_GNUC_INTERNAL " : "extern "); + ind += g_fprintf (fout, "void "); + ind += g_fprintf (fout, "%s_%s (", marshaller_prefix, signame); + g_fprintf (fout, "GClosure *closure,\n"); + g_fprintf (fout, "%sGValue *return_value,\n", indent (ind)); + g_fprintf (fout, "%sguint n_param_values,\n", indent (ind)); + g_fprintf (fout, "%sconst GValue *param_values,\n", indent (ind)); + g_fprintf (fout, "%sgpointer invocation_hint,\n", indent (ind)); + g_fprintf (fout, "%sgpointer marshal_data);\n", + indent (ind)); + } + if (gen_cbody && !have_std_marshaller) + { + /* cfile marshal header */ + g_fprintf (fout, "void\n"); + ind = g_fprintf (fout, "%s_%s (", marshaller_prefix, signame); + g_fprintf (fout, "GClosure *closure,\n"); + g_fprintf (fout, "%sGValue *return_value G_GNUC_UNUSED,\n", indent (ind)); + g_fprintf (fout, "%sguint n_param_values,\n", indent (ind)); + g_fprintf (fout, "%sconst GValue *param_values,\n", indent (ind)); + g_fprintf (fout, "%sgpointer invocation_hint G_GNUC_UNUSED,\n", indent (ind)); + g_fprintf (fout, "%sgpointer marshal_data)\n", indent (ind)); + g_fprintf (fout, "{\n"); + + /* cfile GMarshalFunc typedef */ + ind = g_fprintf (fout, " typedef %s (*GMarshalFunc_%s) (", sig->rarg->ctype, signame); + g_fprintf (fout, "%s data1,\n", pad ("gpointer")); + for (a = 1, node = sig->args; node; node = node->next) + { + InArgument *iarg = node->data; + + if (iarg->getter) + g_fprintf (fout, "%s%s arg_%d,\n", indent (ind), pad (iarg->ctype), a++); + } + g_fprintf (fout, "%s%s data2);\n", indent (ind), pad ("gpointer")); + + /* cfile marshal variables */ + g_fprintf (fout, " register GMarshalFunc_%s callback;\n", signame); + g_fprintf (fout, " register GCClosure *cc = (GCClosure*) closure;\n"); + g_fprintf (fout, " register gpointer data1, data2;\n"); + if (sig->rarg->setter) + g_fprintf (fout, " %s v_return;\n", sig->rarg->ctype); + + if (sig->args || sig->rarg->setter) + { + g_fprintf (fout, "\n"); + + if (sig->rarg->setter) + g_fprintf (fout, " g_return_if_fail (return_value != NULL);\n"); + if (sig->args) + { + for (a = 0, node = sig->args; node; node = node->next) + { + InArgument *iarg = node->data; + + if (iarg->getter) + a++; + } + g_fprintf (fout, " g_return_if_fail (n_param_values == %u);\n", 1 + a); + } + } + + /* cfile marshal data1, data2 and callback setup */ + g_fprintf (fout, "\n"); + g_fprintf (fout, " if (G_CCLOSURE_SWAP_DATA (closure))\n {\n"); + g_fprintf (fout, " data1 = closure->data;\n"); + g_fprintf (fout, " data2 = g_value_peek_pointer (param_values + 0);\n"); + g_fprintf (fout, " }\n else\n {\n"); + g_fprintf (fout, " data1 = g_value_peek_pointer (param_values + 0);\n"); + g_fprintf (fout, " data2 = closure->data;\n"); + g_fprintf (fout, " }\n"); + g_fprintf (fout, " callback = (GMarshalFunc_%s) (marshal_data ? marshal_data : cc->callback);\n", signame); + + /* cfile marshal callback action */ + g_fprintf (fout, "\n"); + ind = g_fprintf (fout, " %s callback (", sig->rarg->setter ? " v_return =" : ""); + g_fprintf (fout, "data1,\n"); + for (a = 1, node = sig->args; node; node = node->next) + { + InArgument *iarg = node->data; + + if (iarg->getter) + g_fprintf (fout, "%s%s (param_values + %d),\n", indent (ind), iarg->getter, a++); + } + g_fprintf (fout, "%sdata2);\n", indent (ind)); + + /* cfile marshal return value storage */ + if (sig->rarg->setter) + { + g_fprintf (fout, "\n"); + g_fprintf (fout, " %s (return_value, v_return);\n", sig->rarg->setter); + } + + /* cfile marshal footer */ + g_fprintf (fout, "}\n"); + } +} + +static void +process_signature (Signature *sig) +{ + gchar *pname, *sname, *tmp; + GList *node; + + /* lookup and complete info on arguments */ + if (!complete_out_arg (sig->rarg)) + { + g_warning ("unknown type: %s", sig->rarg->keyword); + exit_status |= 1; + return; + } + for (node = sig->args; node; node = node->next) + { + InArgument *iarg = node->data; + + if (!complete_in_arg (iarg)) + { + g_warning ("unknown type: %s", iarg->keyword); + exit_status |= 1; + return; + } + } + + /* construct requested marshaller name and technical marshaller name */ + pname = g_strconcat (sig->rarg->keyword, "_", NULL); + sname = g_strconcat (sig->rarg->sig_name, "_", NULL); + for (node = sig->args; node; node = node->next) + { + InArgument *iarg = node->data; + gchar *tmp; + + tmp = sname; + sname = g_strconcat (tmp, "_", iarg->sig_name, NULL); + g_free (tmp); + tmp = pname; + pname = g_strconcat (tmp, "_", iarg->keyword, NULL); + g_free (tmp); + } + + /* introductionary comment */ + g_fprintf (fout, "\n/* %s", sig->rarg->keyword); + for (node = sig->args; node; node = node->next) + { + InArgument *iarg = node->data; + + g_fprintf (fout, "%c%s", node->prev ? ',' : ':', iarg->keyword); + } + if (!skip_ploc) + g_fprintf (fout, " (%s)", sig->ploc); + g_fprintf (fout, " */\n"); + + /* ensure technical marshaller exists (_) */ + generate_marshal (sname, sig); + + /* put out marshaller alias for requested name if required (_) */ + tmp = g_strconcat (marshaller_prefix, "_", pname, NULL); + if (gen_cheader && !g_hash_table_lookup (marshallers, tmp)) + { + g_fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, pname, marshaller_prefix, sname); + + g_hash_table_insert (marshallers, tmp, tmp); + } + else + g_free (tmp); + + g_free (pname); + g_free (sname); +} + +static InArgument* +new_in_arg (const gchar *pname) +{ + InArgument *iarg = g_new0 (InArgument, 1); + + iarg->keyword = g_strdup (pname); + + return iarg; +} + +static OutArgument* +new_out_arg (const gchar *pname) +{ + OutArgument *oarg = g_new0 (OutArgument, 1); + + oarg->keyword = g_strdup (pname); + + return oarg; +} + +static guint +parse_line (GScanner *scanner, + Signature *sig) +{ + /* parse identifier for return value */ + if (g_scanner_get_next_token (scanner) != G_TOKEN_IDENTIFIER) + return G_TOKEN_IDENTIFIER; + sig->rarg = new_out_arg (scanner->value.v_identifier); + + /* keep a note on the location */ + sig->ploc = g_strdup_printf ("%s:%u", scanner->input_name, scanner->line); + + /* expect ':' */ + if (g_scanner_get_next_token (scanner) != ':') + return ':'; + + /* parse first argument */ + if (g_scanner_get_next_token (scanner) != G_TOKEN_IDENTIFIER) + return G_TOKEN_IDENTIFIER; + sig->args = g_list_append (sig->args, new_in_arg (scanner->value.v_identifier)); + + /* parse rest of argument list */ + while (g_scanner_peek_next_token (scanner) == ',') + { + /* eat comma */ + g_scanner_get_next_token (scanner); + + /* parse arg identifier */ + if (g_scanner_get_next_token (scanner) != G_TOKEN_IDENTIFIER) + return G_TOKEN_IDENTIFIER; + sig->args = g_list_append (sig->args, new_in_arg (scanner->value.v_identifier)); + } + + /* expect end of line, done */ + if (g_scanner_get_next_token (scanner) != '\n') + return '\n'; + + /* success */ + return G_TOKEN_NONE; +} + +static gboolean +string_key_destroy (gpointer key, + gpointer value, + gpointer user_data) +{ + g_free (key); + + return TRUE; +} + +int +main (int argc, + char *argv[]) +{ + const gchar *gobject_marshallers[] = { +#include "gmarshal.strings" + }; + GScanner *scanner; + GSList *slist, *files = NULL; + gint i; +#ifdef __SYMBIAN32__ + gint fd1; + g_log_set_handler (NULL, G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG, &mrtLogHandler, NULL); + g_set_print_handler(mrtPrintHandler); + #endif /*__SYMBIAN32__*/ + /* parse args and do fast exits */ + parse_args (&argc, &argv); + + /* list input files */ + for (i = 1; i < argc; i++) + files = g_slist_prepend (files, argv[i]); + if (files) + files = g_slist_reverse (files); + else +#ifdef __SYMBIAN32__ + fd1 = open("c:\\genmarshaltest.txt", O_CREAT, 0666); + close(fd1); + files = g_slist_prepend (files, "c:\\genmarshaltest.txt"); +#else + files = g_slist_prepend (files, "/dev/stdin"); +#endif//__SYMBIAN32__ + + /* setup auxillary structs */ + scanner = g_scanner_new (&scanner_config_template); + fout = stdout; + marshallers = g_hash_table_new (g_str_hash, g_str_equal); + + /* add standard marshallers of the GObject library */ + if (std_includes) + for (i = 0; i < G_N_ELEMENTS (gobject_marshallers); i++) + { + gchar *tmp = g_strdup (gobject_marshallers[i]); + + g_hash_table_insert (marshallers, tmp, tmp); + } + + /* put out initial heading */ + g_fprintf (fout, "\n"); + + if (gen_cheader && std_includes) + { + g_fprintf (fout, "#ifndef __%s_MARSHAL_H__\n", marshaller_prefix); + g_fprintf (fout, "#define __%s_MARSHAL_H__\n\n", marshaller_prefix); + } + + if ((gen_cheader || gen_cbody) && std_includes) + g_fprintf (fout, "#include\t\n\n"); + + if (gen_cheader) + g_fprintf (fout, "G_BEGIN_DECLS\n"); + + /* generate necessary preprocessor directives */ + if (gen_cbody) + put_marshal_value_getters (); + + /* process input files */ + for (slist = files; slist; slist = slist->next) + { + gchar *file = slist->data; + gint fd; + +#ifdef __SYMBIAN32__ + if (strcmp (file, "c:\\genmarshaltest.txt") == 0) +#else + if (strcmp (file, "/dev/stdin") == 0) + /* Mostly for Win32. This is equivalent to opening /dev/stdin */ + fd = dup (0); + else +#endif//__SYMBIAN32__ + fd = open (file, O_RDONLY); + + if (fd < 0) + { + g_warning ("failed to open \"%s\": %s", file, g_strerror (errno)); + exit_status |= 1; + continue; + } + + /* set file name for error reports */ + scanner->input_name = file; + + /* parse & process file */ + g_scanner_input_file (scanner, fd); + + /* scanning loop, we parse the input until its end is reached, + * or our sub routine came across invalid syntax + */ + do + { + guint expected_token = G_TOKEN_NONE; + + switch (g_scanner_peek_next_token (scanner)) + { + case '\n': + /* eat newline and restart */ + g_scanner_get_next_token (scanner); + continue; + case G_TOKEN_EOF: + /* done */ + break; + default: + /* parse and process signatures */ + { + Signature signature = { NULL, NULL, NULL }; + GList *node; + + expected_token = parse_line (scanner, &signature); + + /* once we got a valid signature, process it */ + if (expected_token == G_TOKEN_NONE) + process_signature (&signature); + + /* clean up signature contents */ + g_free (signature.ploc); + if (signature.rarg) + g_free (signature.rarg->keyword); + g_free (signature.rarg); + for (node = signature.args; node; node = node->next) + { + InArgument *iarg = node->data; + + g_free (iarg->keyword); + g_free (iarg); + } + g_list_free (signature.args); + } + break; + } + + /* bail out on errors */ + if (expected_token != G_TOKEN_NONE) + { + g_scanner_unexp_token (scanner, expected_token, "type name", NULL, NULL, NULL, TRUE); + exit_status |= 1; + break; + } + + g_scanner_peek_next_token (scanner); + } + while (scanner->next_token != G_TOKEN_EOF); + + close (fd); + } + + /* put out trailer */ + if (gen_cheader) + { + g_fprintf (fout, "\nG_END_DECLS\n"); + + if (std_includes) + g_fprintf (fout, "\n#endif /* __%s_MARSHAL_H__ */\n", marshaller_prefix); + } + g_fprintf (fout, "\n"); + + /* clean up */ + g_slist_free (files); + g_scanner_destroy (scanner); + g_hash_table_foreach_remove (marshallers, string_key_destroy, NULL); + g_hash_table_destroy (marshallers); +#ifdef __SYMBIAN32__ + testResultXml("glib-genmarshall"); + remove("c:\\genmarshaltest.txt"); +#endif /* EMULATOR */ + return exit_status; +} + +static void +parse_args (gint *argc_p, + gchar ***argv_p) +{ + guint argc = *argc_p; + gchar **argv = *argv_p; + guint i, e; + + for (i = 1; i < argc; i++) + { + if (strcmp ("-header", argv[i]) == 0) + { + gen_cheader = TRUE; + argv[i] = NULL; + } + else if (strcmp ("-body", argv[i]) == 0) + { + gen_cbody = TRUE; + argv[i] = NULL; + } + else if (strcmp ("-skip-source", argv[i]) == 0) + { + skip_ploc = TRUE; + argv[i] = NULL; + } + else if (strcmp ("-nostdinc", argv[i]) == 0) + { + std_includes = FALSE; + argv[i] = NULL; + } + else if (strcmp ("-stdinc", argv[i]) == 0) + { + std_includes = TRUE; + argv[i] = NULL; + } + else if (strcmp ("-internal", argv[i]) == 0) + { + gen_internal = TRUE; + argv[i] = NULL; + } + else if ((strcmp ("-prefix", argv[i]) == 0) || + (strncmp ("-prefix=", argv[i], 9) == 0)) + { + gchar *equal = argv[i] + 8; + + if (*equal == '=') + marshaller_prefix = g_strdup (equal + 1); + else if (i + 1 < argc) + { + marshaller_prefix = g_strdup (argv[i + 1]); + argv[i] = NULL; + i += 1; + } + argv[i] = NULL; + } + else if (strcmp ("-h", argv[i]) == 0 || + strcmp ("-?", argv[i]) == 0 || + strcmp ("-help", argv[i]) == 0) + { + print_blurb (stderr, TRUE); + argv[i] = NULL; + exit (0); + } + else if (strcmp ("-v", argv[i]) == 0 || + strcmp ("-version", argv[i]) == 0) + { + print_blurb (stderr, FALSE); + argv[i] = NULL; + exit (0); + } + else if (strcmp (argv[i], "-g-fatal-warnings") == 0) + { + GLogLevelFlags fatal_mask; + + fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); + fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; + g_log_set_always_fatal (fatal_mask); + + argv[i] = NULL; + } + } + + e = 0; + for (i = 1; i < argc; i++) + { + if (e) + { + if (argv[i]) + { + argv[e++] = argv[i]; + argv[i] = NULL; + } + } + else if (!argv[i]) + e = i; + } + if (e) + *argc_p = e; +} + +static void +print_blurb (FILE *bout, + gboolean print_help) +{ + if (!print_help) + { + g_fprintf (bout, "%s version ", PRG_NAME); + g_fprintf (bout, "%u.%u.%u", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); + g_fprintf (bout, "\n"); + g_fprintf (bout, "%s comes with ABSOLUTELY NO WARRANTY.\n", PRG_NAME); + g_fprintf (bout, "You may redistribute copies of %s under the terms of\n", PRG_NAME); + g_fprintf (bout, "the GNU General Public License which can be found in the\n"); + g_fprintf (bout, "%s source package. Sources, examples and contact\n", PKG_NAME); + g_fprintf (bout, "information are available at %s\n", PKG_HTTP_HOME); + } + else + { + g_fprintf (bout, "Usage:\n"); + g_fprintf (bout, " %s [OPTION...] [FILES...]\n\n", PRG_NAME); + g_fprintf (bout, "Help Options:\n"); + g_fprintf (bout, " -h, -help Show this help message\n\n"); + g_fprintf (bout, "Utility Options:\n"); + g_fprintf (bout, " -header Generate C headers\n"); + g_fprintf (bout, " -body Generate C code\n"); + g_fprintf (bout, " -prefix=string Specify marshaller prefix\n"); + g_fprintf (bout, " -skip-source Skip source location comments\n"); + g_fprintf (bout, " -stdinc, -nostdinc Include/use standard marshallers\n"); + g_fprintf (bout, " -internal Mark generated functions as internal\n"); + g_fprintf (bout, " -v, -version Print version informations\n"); + g_fprintf (bout, " -g-fatal-warnings Make warnings fatal (abort)\n"); + } +}