Initial packaging for Tizen
[profile/ivi/gobject-introspection.git] / tools / compiler.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2  * GObject introspection: Typelib compiler
3  *
4  * Copyright (C) 2005 Matthias Clasen
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <errno.h>
23 #include <string.h>
24
25 #include <glib.h>
26 #include <glib/gstdio.h>
27 #include <gio/gio.h>
28
29 #ifdef G_OS_WIN32
30 #include <io.h>
31 #include <fcntl.h>
32 #endif
33
34 #include "girmodule.h"
35 #include "girnode.h"
36 #include "girparser.h"
37 #include "gitypelib-internal.h"
38
39 gboolean no_init = FALSE;
40 gchar **includedirs = NULL;
41 gchar **input = NULL;
42 gchar *output = NULL;
43 gchar *mname = NULL;
44 gchar *shlib = NULL;
45 gboolean include_cwd = FALSE;
46 gboolean debug = FALSE;
47 gboolean verbose = FALSE;
48
49 static gboolean
50 write_out_typelib (gchar *prefix,
51                    GITypelib *typelib)
52 {
53   FILE *file;
54   gsize written;
55   GFile *file_obj;
56   gchar *filename;
57   GFile *tmp_file_obj;
58   gchar *tmp_filename;
59   GError *error = NULL;
60   gboolean success = FALSE;
61
62   if (output == NULL)
63     {
64       file = stdout;
65       file_obj = NULL;
66       filename = NULL;
67       tmp_filename = NULL;
68       tmp_file_obj = NULL;
69 #ifdef G_OS_WIN32
70       setmode (fileno (file), _O_BINARY);
71 #endif
72     }
73   else
74     {
75       if (prefix)
76         filename = g_strdup_printf ("%s-%s", prefix, output);  
77       else
78         filename = g_strdup (output);
79       file_obj = g_file_new_for_path (filename);
80       tmp_filename = g_strdup_printf ("%s.tmp", filename);
81       tmp_file_obj = g_file_new_for_path (tmp_filename);
82       file = g_fopen (tmp_filename, "wb");
83
84       if (file == NULL)
85         {
86           g_fprintf (stderr, "failed to open '%s': %s\n",
87                      tmp_filename, g_strerror (errno));
88           goto out;
89         }
90     }
91
92   written = fwrite (typelib->data, 1, typelib->len, file);
93   if (written < typelib->len) {
94     g_fprintf (stderr, "ERROR: Could not write the whole output: %s",
95                strerror(errno));
96     goto out;
97   }
98
99   if (output != NULL)
100     fclose (file);
101   if (tmp_filename != NULL)
102     {
103       if (!g_file_move (tmp_file_obj, file_obj, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error))
104         {
105           g_fprintf (stderr, "ERROR: failed to rename %s to %s: %s", tmp_filename, filename, error->message);
106           g_clear_error (&error);
107           goto out;
108         }
109     }
110   success = TRUE;
111 out:
112   g_free (filename);
113   g_free (tmp_filename);
114
115   return success;
116 }
117
118 GLogLevelFlags logged_levels;
119
120 static void log_handler (const gchar *log_domain,
121                          GLogLevelFlags log_level,
122                          const gchar *message,
123                          gpointer user_data)
124 {
125   
126   if (log_level & logged_levels)
127     g_log_default_handler (log_domain, log_level, message, user_data);
128 }
129
130 static GOptionEntry options[] = 
131 {
132   { "no-init", 0, 0, G_OPTION_ARG_NONE, &no_init, "do not create _init() function", NULL },
133   { "includedir", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &includedirs, "include directories in GIR search path", NULL }, 
134   { "output", 'o', 0, G_OPTION_ARG_FILENAME, &output, "output file", "FILE" }, 
135   { "module", 'm', 0, G_OPTION_ARG_STRING, &mname, "module to compile", "NAME" }, 
136   { "shared-library", 'l', 0, G_OPTION_ARG_FILENAME, &shlib, "shared library", "FILE" }, 
137   { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, "show debug messages", NULL }, 
138   { "verbose", 0, 0, G_OPTION_ARG_NONE, &verbose, "show verbose messages", NULL }, 
139   { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &input, NULL, NULL },
140   { NULL, }
141 };
142
143 int
144 main (int argc, char ** argv)
145 {
146   GOptionContext *context;
147   GError *error = NULL;
148   GIrParser *parser;
149   GIrModule *module;
150   gint i;
151   g_typelib_check_sanity ();
152
153   context = g_option_context_new ("");
154   g_option_context_add_main_entries (context, options, NULL);
155   g_option_context_parse (context, &argc, &argv, &error);
156   g_option_context_free (context);
157
158   logged_levels = G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_DEBUG);
159   if (debug)
160     logged_levels = logged_levels | G_LOG_LEVEL_DEBUG;
161   if (verbose)
162     logged_levels = logged_levels | G_LOG_LEVEL_MESSAGE;
163   g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
164
165   g_log_set_default_handler (log_handler, NULL);
166
167   if (!input) 
168     { 
169       g_fprintf (stderr, "no input files\n"); 
170
171       return 1;
172     }
173
174   g_debug ("[parsing] start, %d includes", 
175            includedirs ? g_strv_length (includedirs) : 0);
176
177   g_type_init ();
178
179   if (includedirs != NULL)
180     for (i = 0; includedirs[i]; i++)
181       g_irepository_prepend_search_path (includedirs[i]);
182
183   parser = _g_ir_parser_new ();
184
185   _g_ir_parser_set_includes (parser, (const char*const*) includedirs);
186
187   module = _g_ir_parser_parse_file (parser, input[0], &error);
188   if (module == NULL) 
189     {
190       g_fprintf (stderr, "error parsing file %s: %s\n", 
191                  input[0], error->message);
192       
193       return 1;
194     }
195
196   g_debug ("[parsing] done");
197
198   g_debug ("[building] start");
199
200   {
201       GITypelib *typelib;
202
203       if (shlib)
204         {
205           if (module->shared_library)
206             g_free (module->shared_library);
207           module->shared_library = g_strdup (shlib);
208         }
209
210       g_debug ("[building] module %s", module->name);
211
212       typelib = _g_ir_module_build_typelib (module);
213       if (typelib == NULL)
214         g_error ("Failed to build typelib for module '%s'\n", module->name);
215       if (!g_typelib_validate (typelib, &error))
216         g_error ("Invalid typelib for module '%s': %s", 
217                  module->name, error->message);
218
219       if (!write_out_typelib (NULL, typelib))
220         return 1;
221       g_typelib_free (typelib);
222       typelib = NULL;
223     }
224
225   g_debug ("[building] done");
226
227 #if 0
228   /* No point */
229   _g_ir_parser_free (parser);
230 #endif  
231
232   return 0; 
233 }