2004-08-09 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / glib / dbus-glib-tool.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-glib-tool.c Tool used by apps using glib bindings
3  *
4  * Copyright (C) 2003, 2004 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include <config.h>
25 #include "dbus-gidl.h"
26 #include "dbus-gparser.h"
27 #include "dbus-gutils.h"
28 #include <locale.h>
29 #include <libintl.h>
30 #define _(x) dgettext (GETTEXT_PACKAGE, x)
31 #define N_(x) x
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #ifdef DBUS_BUILD_TESTS
37 static void run_all_tests (const char *test_data_dir);
38 #endif
39
40 static void
41 indent (int depth)
42 {
43   depth *= 2; /* 2-space indent */
44   
45   while (depth > 0)
46     {
47       putc (' ', stdout);
48       --depth;
49     }
50 }
51
52 static void pretty_print (BaseInfo *base,
53                           int       depth);
54
55 static void
56 pretty_print_list (GSList *list,
57                    int     depth)
58 {
59   GSList *tmp;
60
61   tmp = list;
62   while (tmp != NULL)
63     {
64       pretty_print (tmp->data, depth);
65       tmp = tmp->next;
66     }
67 }
68
69 static void
70 pretty_print (BaseInfo *base,
71               int       depth)
72 {
73   InfoType t;
74   const char *name;
75
76   t = base_info_get_type (base);
77   name = base_info_get_name (base);
78
79   indent (depth);
80   
81   switch (t)
82     {
83     case INFO_TYPE_NODE:
84       {
85         NodeInfo *n = (NodeInfo*) base;
86         
87         if (name == NULL)
88           printf (_("<anonymous node> {\n"));
89         else
90           printf (_("node \"%s\" {\n"), name);
91
92         pretty_print_list (node_info_get_interfaces (n), depth + 1);
93         pretty_print_list (node_info_get_nodes (n), depth + 1);
94
95         indent (depth);
96         printf ("}\n");
97       }
98       break;
99     case INFO_TYPE_INTERFACE:
100       {
101         InterfaceInfo *i = (InterfaceInfo*) base;
102
103         g_assert (name != NULL);
104
105         printf (_("interface \"%s\" {\n"), name);
106
107         pretty_print_list (interface_info_get_methods (i), depth + 1);
108         pretty_print_list (interface_info_get_signals (i), depth + 1);
109
110         indent (depth);
111         printf ("}\n");
112       }
113       break;
114     case INFO_TYPE_METHOD:
115       {
116         MethodInfo *m = (MethodInfo*) base;
117
118         g_assert (name != NULL);
119
120         printf (_("method \"%s\" (\n"), name);
121
122         pretty_print_list (method_info_get_args (m), depth + 1);
123
124         indent (depth);
125         printf (")\n");
126       }
127       break;
128     case INFO_TYPE_SIGNAL:
129       {
130         SignalInfo *s = (SignalInfo*) base;
131
132         g_assert (name != NULL);
133
134         printf (_("signal \"%s\" (\n"), name);
135
136         pretty_print_list (signal_info_get_args (s), depth + 1);
137
138         indent (depth);
139         printf (")\n");
140       }
141       break;
142     case INFO_TYPE_ARG:
143       {
144         ArgInfo *a = (ArgInfo*) base;
145         int at = arg_info_get_type (a);
146         ArgDirection d = arg_info_get_direction (a);
147
148         printf ("%s %s",
149                 d == ARG_IN ? "in" : "out",
150                 _dbus_gutils_type_to_string (at));
151         if (name)
152           printf (" %s\n", name);
153         else
154           printf ("\n");
155       }
156       break;
157     }
158 }
159
160 static void
161 usage (int ecode)
162 {
163   fprintf (stderr, "dbus-glib-tool [--version] [--help]\n");
164   exit (ecode);
165 }
166
167 static void
168 version (void)
169 {
170   printf ("D-BUS GLib Tool %s\n"
171           "Copyright (C) 2003, 2004 Red Hat, Inc.\n"
172           "This is free software; see the source for copying conditions.\n"
173           "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
174           VERSION);
175   exit (0);
176 }
177
178 int
179 main (int argc, char **argv)
180 {
181   const char *prev_arg;
182   int i;
183   GSList *files;
184   gboolean end_of_args;
185   GSList *tmp;
186   gboolean just_pretty_print;
187
188   setlocale (LC_ALL, "");
189   bindtextdomain (GETTEXT_PACKAGE, DBUS_LOCALEDIR);
190   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
191   textdomain (GETTEXT_PACKAGE); 
192
193   just_pretty_print = FALSE;
194   end_of_args = FALSE;
195   files = NULL;
196   prev_arg = NULL;
197   i = 1;
198   while (i < argc)
199     {
200       const char *arg = argv[i];
201
202       if (!end_of_args)
203         {
204           if (strcmp (arg, "--help") == 0 ||
205               strcmp (arg, "-h") == 0 ||
206               strcmp (arg, "-?") == 0)
207             usage (0);
208           else if (strcmp (arg, "--version") == 0)
209             version ();
210 #ifdef DBUS_BUILD_TESTS
211           else if (strcmp (arg, "--self-test") == 0)
212             run_all_tests (NULL);
213 #endif /* DBUS_BUILD_TESTS */
214           else if (strcmp (arg, "--pretty-print") == 0)
215             just_pretty_print = TRUE;
216           else if (arg[0] == '-' &&
217                    arg[1] == '-' &&
218                    arg[2] == '\0')
219             end_of_args = TRUE;
220           else if (arg[0] == '-')
221             {
222               usage (1);
223             }
224           else
225             {
226               files = g_slist_prepend (files, (char*) arg);
227             }
228         }
229       else
230         files = g_slist_prepend (files, (char*) arg);
231       
232       prev_arg = arg;
233       
234       ++i;
235     }
236
237   files = g_slist_reverse (files);
238
239   tmp = files;
240   while (tmp != NULL)
241     {
242       NodeInfo *node;
243       GError *error;
244       const char *filename;
245
246       filename = tmp->data;
247
248       error = NULL;
249       node = description_load_from_file (filename,
250                                          &error);
251       if (node == NULL)
252         {
253           g_assert (error != NULL);
254           fprintf (stderr, _("Unable to load \"%s\": %s\n"),
255                    filename, error->message);
256           g_error_free (error);
257           exit (1);
258         }
259       else if (just_pretty_print)
260         {
261           pretty_print ((BaseInfo*) node, 0);
262         }
263       else
264         {
265           /* FIXME process the file to generate metadata variable
266            * definition rather than just printing it.
267            * i.e. we want to create DBusGObjectInfo.
268            * This probably requires extending the introspection XML format to
269            * allow a "native function name":
270            *  <method name="Frobate" native="my_object_frobate">
271            */
272           pretty_print ((BaseInfo*) node, 0);
273         }
274
275       if (node)
276         node_info_unref (node);
277       
278       tmp = tmp->next;
279     }
280   
281   return 0;
282 }
283
284
285 #ifdef DBUS_BUILD_TESTS
286 static void
287 test_die (const char *failure)
288 {
289   fprintf (stderr, "Unit test failed: %s\n", failure);
290   exit (1);
291 }
292
293 /**
294  * @ingroup DBusGTool
295  * Unit test for GLib utility tool
296  * @returns #TRUE on success.
297  */
298 static gboolean
299 _dbus_gtool_test (const char *test_data_dir)
300 {
301
302   return TRUE;
303 }
304
305 static void
306 run_all_tests (const char *test_data_dir)
307 {
308   if (test_data_dir == NULL)
309     test_data_dir = g_getenv ("DBUS_TEST_DATA");
310
311   if (test_data_dir != NULL)
312     printf ("Test data in %s\n", test_data_dir);
313   else
314     printf ("No test data!\n");
315
316   printf ("%s: running gtool tests\n", "dbus-glib-tool");
317   if (!_dbus_gtool_test (test_data_dir))
318     test_die ("gtool");
319
320   printf ("%s: completed successfully\n", "dbus-glib-tool");
321 }
322
323 #endif /* DBUS_BUILD_TESTS */