3
* Copyright Ā© 2009 Scott James Remnant <scott@netsplit.com>.
4
* Copyright Ā© 2009 Canonical Ltd.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2, as
8
* published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
#endif /* HAVE_CONFIG_H */
25
#include <sys/types.h>
35
#include <nih/macros.h>
36
#include <nih/alloc.h>
37
#include <nih/string.h>
39
#include <nih/option.h>
40
#include <nih/logging.h>
41
#include <nih/error.h>
44
#include "interface.h"
49
/* Prototypes for option functions */
50
int mode_option (NihOption *option, const char *arg);
52
/* Prototypes for local functions */
53
char *source_file_path (const void *parent, const char *output_path,
55
__attribute__ ((warn_unused_result, malloc));
56
char *header_file_path (const void *parent, const char *output_path,
58
__attribute__ ((warn_unused_result, malloc));
63
* @option: NihOption invoked,
64
* @arg: argument to parse.
66
* This option setter parses the output mode argument @arg and sets
67
* the value member of @option, which must be a pointer to an integer.
69
* The arg_name member of @option must not be NULL.
72
mode_option (NihOption * option,
77
nih_assert (option != NULL);
78
nih_assert (option->value != NULL);
79
nih_assert (arg != NULL);
81
value = (int *)option->value;
83
if (! strcmp (arg, "proxy")) {
85
} else if (! strcmp (arg, "object")) {
88
fprintf (stderr, _("%s: illegal output mode: %s\n"),
90
nih_main_suggest_help ();
100
* @parent: parent object for new string,
101
* @output_path: output path,
102
* @filename: input filename.
104
* Generates a path to the output source (.c) file from either the output
105
* path given in @output_path or the input filename given in @filename,
106
* depending on which one is not NULL.
108
* If @parent is not NULL, it should be a pointer to another object which
109
* will be used as a parent for the returned string. When all parents
110
* of the returned string are freed, the returned string will also be
113
* Returns: newly allocated string or NULL if insufficient memory.
116
source_file_path (const void *parent,
117
const char *output_path,
118
const char *filename)
122
nih_assert ((output_path != NULL) || (filename != NULL));
127
/* When the output path is given, return it; but allow for
128
* the output path being the header to make Makefile rules
129
* easier, and replace extension with .c when given one.
131
ptr = strrchr (output_path, '.');
132
if (ptr && (! strcmp (ptr, ".h"))) {
133
path = nih_strndup (parent, output_path,
138
if (! nih_strcat (&path, parent, ".c")) {
143
path = nih_strdup (parent, output_path);
146
} else if (filename) {
149
/* Always output to the current directory */
150
ptr = strrchr (filename, '/');
154
/* When the input filename is given, strip the extension off
155
* and replace with .c unless the extension is .c or .h in
156
* which case we append the .c extension instead
158
ptr = strrchr (filename, '.');
159
if (ptr && strcmp (ptr, ".c") && strcmp (ptr, ".h")) {
160
path = nih_strndup (parent, filename, ptr - filename);
164
path = nih_strdup (parent, filename);
169
if (! nih_strcat (&path, parent, ".c")) {
180
* @parent: parent object for new string,
181
* @output_path: output path,
182
* @filename: input filename.
184
* Generates a path to the output header (.h) file from either the output
185
* path given in @output_path or the input filename given in @filename,
186
* depending on which one is not NULL.
188
* If @parent is not NULL, it should be a pointer to another object which
189
* will be used as a parent for the returned string. When all parents
190
* of the returned string are freed, the returned string will also be
193
* Returns: newly allocated string or NULL if insufficient memory.
196
header_file_path (const void *parent,
197
const char *output_path,
198
const char *filename)
202
nih_assert ((output_path != NULL) || (filename != NULL));
207
/* When the output path is given, and is the header file,
208
* return it; otherwise replace the extension with .h or
209
* append it if there was no extension
211
ptr = strrchr (output_path, '.');
212
if (ptr && (! strcmp (ptr, ".h"))) {
213
path = nih_strdup (parent, output_path);
215
path = nih_strndup (parent, output_path,
220
if (! nih_strcat (&path, parent, ".h")) {
225
path = nih_strdup (parent, output_path);
229
if (! nih_strcat (&path, parent, ".h")) {
236
} else if (filename) {
239
/* Always output to the current directory */
240
ptr = strrchr (filename, '/');
244
/* When the input filename is given, strip the extension off
245
* and replace with .h unless the extension is .c or .h in
246
* which case we append the .h extension instead
248
ptr = strrchr (filename, '.');
249
if (ptr && strcmp (ptr, ".c") && strcmp (ptr, ".h")) {
250
path = nih_strndup (parent, filename, ptr - filename);
254
path = nih_strdup (parent, filename);
259
if (! nih_strcat (&path, parent, ".h")) {
273
* Set to TRUE to output code for a remote object with C access methods or
274
* FALSE for a local object implementation wrapping existing C functions.
276
static int object = FALSE;
281
* Prefix of expected and generated functions.
283
static const char *prefix = NULL;
288
* Interface which should not have the last component of its name included
289
* in generated symbol names.
291
static const char *default_interface = NULL;
296
* Path to output C code to, header is automatically placed alongside.
298
static const char *output_path = NULL;
304
* Command-line options accepted by this tool.
306
static NihOption options[] = {
307
{ 0, "mode", N_("output mode: object, or proxy [default: proxy]"),
308
NULL, "MODE", &object, mode_option },
309
{ 0, "prefix", N_("prefix for C functions [default: dbus]"),
310
NULL, "PREFIX", &prefix, NULL },
311
{ 0, "default-interface", N_("interface name not included in symbols"),
312
NULL, "INTERFACE", &default_interface, NULL },
313
{ 'o', "output", N_("write C source to FILENAME, header alongside"),
314
NULL, "FILENAME", &output_path, NULL },
326
nih_local char *source_path = NULL;
327
nih_local char *header_path = NULL;
332
nih_main_init (argv[0]);
334
nih_option_set_usage (_("[XMLFILE]"));
335
nih_option_set_synopsis (_("Generate C bindings for D-Bus objects"));
336
nih_option_set_help (_("Fill this in later"));
338
args = nih_option_parser (NULL, argc, argv, options, FALSE);
342
/* Filename defaults to standard input when not specified, or when
346
if (filename && (! strcmp (filename, "-")))
349
/* Output path must be specified when we're using standard input */
350
if ((! filename) && (! output_path)) {
351
fprintf (stderr, _("%s: --output must be specified when using standard input\n"),
353
nih_main_suggest_help ();
357
/* Calculate output paths */
358
source_path = source_file_path (NULL, output_path, filename);
360
nih_error ("%s", strerror (ENOMEM));
364
header_path = header_file_path (NULL, output_path, filename);
366
nih_error ("%s", strerror (ENOMEM));
370
/* Set default prefix if not set */
375
/* Parse the input file, which may be standard input */
379
fd = open (filename, O_RDONLY);
381
nih_error ("%s: %s", filename, strerror (errno));
385
node = parse_xml (NULL, fd, filename);
389
if (close (fd) < 0) {
390
nih_error ("%s: %s", filename, strerror (errno));
394
node = parse_xml (NULL, STDIN_FILENO, "(standard input)");
399
/* Remove the symbol from the default interface */
400
if (default_interface) {
403
NIH_LIST_FOREACH (&node->interfaces, iter) {
404
Interface *interface = (Interface *)iter;
406
if (! strcmp (interface->name, default_interface)) {
407
nih_unref (interface->symbol, interface);
408
interface->symbol = NULL;
414
nih_error ("%s: %s", _("No such interface"),
420
/* Write the output files */
421
source_fd = open (source_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
423
nih_error ("%s: %s", source_path, strerror (errno));
427
header_fd = open (header_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
429
nih_error ("%s: %s", header_path, strerror (errno));
433
if (output (source_path, source_fd, header_path, header_fd,
434
prefix, node, object) < 0) {
437
err = nih_error_get ();
438
nih_error ("%s", err->message);
444
if ((fsync (source_fd) < 0)
445
|| (close (source_fd) < 0)) {
446
nih_error ("%s: %s", source_path, strerror (errno));
450
if ((fsync (header_fd) < 0)
451
|| (close (header_fd) < 0)) {
452
nih_error ("%s: %s", header_path, strerror (errno));