1c99fb5f9SBaptiste Daroussin /* Copyright (c) 2013, Vsevolod Stakhov
2c99fb5f9SBaptiste Daroussin * All rights reserved.
3c99fb5f9SBaptiste Daroussin *
4c99fb5f9SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without
5c99fb5f9SBaptiste Daroussin * modification, are permitted provided that the following conditions are met:
6c99fb5f9SBaptiste Daroussin * * Redistributions of source code must retain the above copyright
7c99fb5f9SBaptiste Daroussin * notice, this list of conditions and the following disclaimer.
8c99fb5f9SBaptiste Daroussin * * Redistributions in binary form must reproduce the above copyright
9c99fb5f9SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the
10c99fb5f9SBaptiste Daroussin * documentation and/or other materials provided with the distribution.
11c99fb5f9SBaptiste Daroussin *
12c99fb5f9SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13c99fb5f9SBaptiste Daroussin * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14c99fb5f9SBaptiste Daroussin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15c99fb5f9SBaptiste Daroussin * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16c99fb5f9SBaptiste Daroussin * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17c99fb5f9SBaptiste Daroussin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18c99fb5f9SBaptiste Daroussin * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19c99fb5f9SBaptiste Daroussin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20c99fb5f9SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21c99fb5f9SBaptiste Daroussin * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22c99fb5f9SBaptiste Daroussin */
23c99fb5f9SBaptiste Daroussin
24c99fb5f9SBaptiste Daroussin #include "ucl.h"
2597bd480fSBaptiste Daroussin #include "ucl_internal.h"
26d9f0ce31SBaptiste Daroussin #include <sys/types.h>
27d9f0ce31SBaptiste Daroussin #include <fcntl.h>
28d9f0ce31SBaptiste Daroussin #include <unistd.h>
29d9f0ce31SBaptiste Daroussin
30c99fb5f9SBaptiste Daroussin
31c99fb5f9SBaptiste Daroussin int
main(int argc,char ** argv)32c99fb5f9SBaptiste Daroussin main (int argc, char **argv)
33c99fb5f9SBaptiste Daroussin {
34d9f0ce31SBaptiste Daroussin char *inbuf = NULL;
35c99fb5f9SBaptiste Daroussin struct ucl_parser *parser = NULL, *parser2 = NULL;
36d9f0ce31SBaptiste Daroussin ucl_object_t *obj, *comments = NULL;
3739ee7a7aSBaptiste Daroussin ssize_t bufsize, r;
38c99fb5f9SBaptiste Daroussin FILE *in, *out;
39c99fb5f9SBaptiste Daroussin unsigned char *emitted = NULL;
40c99fb5f9SBaptiste Daroussin const char *fname_in = NULL, *fname_out = NULL;
41d9f0ce31SBaptiste Daroussin int ret = 0, opt, json = 0, compact = 0, yaml = 0,
42d9f0ce31SBaptiste Daroussin save_comments = 0, skip_macro = 0,
43*a0409676SBaptiste Daroussin flags, fd_out, fd_in, use_fd = 0, msgpack_input = 0;
44d9f0ce31SBaptiste Daroussin struct ucl_emitter_functions *func;
45c99fb5f9SBaptiste Daroussin
46*a0409676SBaptiste Daroussin while ((opt = getopt(argc, argv, "fjcyCMm")) != -1) {
47c99fb5f9SBaptiste Daroussin switch (opt) {
48c99fb5f9SBaptiste Daroussin case 'j':
49c99fb5f9SBaptiste Daroussin json = 1;
50c99fb5f9SBaptiste Daroussin break;
513dcf5eb7SBaptiste Daroussin case 'c':
523dcf5eb7SBaptiste Daroussin compact = 1;
533dcf5eb7SBaptiste Daroussin break;
54d9f0ce31SBaptiste Daroussin case 'C':
55d9f0ce31SBaptiste Daroussin save_comments = 1;
56d9f0ce31SBaptiste Daroussin break;
573dcf5eb7SBaptiste Daroussin case 'y':
583dcf5eb7SBaptiste Daroussin yaml = 1;
593dcf5eb7SBaptiste Daroussin break;
60d9f0ce31SBaptiste Daroussin case 'M':
61d9f0ce31SBaptiste Daroussin skip_macro = true;
62d9f0ce31SBaptiste Daroussin break;
63*a0409676SBaptiste Daroussin case 'm':
64*a0409676SBaptiste Daroussin msgpack_input = 1;
65*a0409676SBaptiste Daroussin break;
66d9f0ce31SBaptiste Daroussin case 'f':
67d9f0ce31SBaptiste Daroussin use_fd = true;
68d9f0ce31SBaptiste Daroussin break;
69c99fb5f9SBaptiste Daroussin default: /* '?' */
70d9f0ce31SBaptiste Daroussin fprintf (stderr, "Usage: %s [-jcy] [-CM] [-f] [in] [out]\n",
71c99fb5f9SBaptiste Daroussin argv[0]);
72c99fb5f9SBaptiste Daroussin exit (EXIT_FAILURE);
73c99fb5f9SBaptiste Daroussin }
74c99fb5f9SBaptiste Daroussin }
75c99fb5f9SBaptiste Daroussin
76c99fb5f9SBaptiste Daroussin argc -= optind;
77c99fb5f9SBaptiste Daroussin argv += optind;
78c99fb5f9SBaptiste Daroussin
79c99fb5f9SBaptiste Daroussin switch (argc) {
80c99fb5f9SBaptiste Daroussin case 1:
81c99fb5f9SBaptiste Daroussin fname_in = argv[0];
82c99fb5f9SBaptiste Daroussin break;
83c99fb5f9SBaptiste Daroussin case 2:
84c99fb5f9SBaptiste Daroussin fname_in = argv[0];
85c99fb5f9SBaptiste Daroussin fname_out = argv[1];
86c99fb5f9SBaptiste Daroussin break;
87c99fb5f9SBaptiste Daroussin }
88c99fb5f9SBaptiste Daroussin
89d9f0ce31SBaptiste Daroussin if (!use_fd) {
90c99fb5f9SBaptiste Daroussin if (fname_in != NULL) {
91c99fb5f9SBaptiste Daroussin in = fopen (fname_in, "r");
92c99fb5f9SBaptiste Daroussin if (in == NULL) {
93c99fb5f9SBaptiste Daroussin exit (-errno);
94c99fb5f9SBaptiste Daroussin }
95c99fb5f9SBaptiste Daroussin }
96c99fb5f9SBaptiste Daroussin else {
97c99fb5f9SBaptiste Daroussin in = stdin;
98c99fb5f9SBaptiste Daroussin }
99d9f0ce31SBaptiste Daroussin }
100d9f0ce31SBaptiste Daroussin else {
101d9f0ce31SBaptiste Daroussin if (fname_in != NULL) {
102d9f0ce31SBaptiste Daroussin fd_in = open (fname_in, O_RDONLY);
103d9f0ce31SBaptiste Daroussin if (fd_in == -1) {
104d9f0ce31SBaptiste Daroussin exit (-errno);
105d9f0ce31SBaptiste Daroussin }
106d9f0ce31SBaptiste Daroussin }
107d9f0ce31SBaptiste Daroussin else {
108d9f0ce31SBaptiste Daroussin fd_in = STDIN_FILENO;
109d9f0ce31SBaptiste Daroussin }
110d9f0ce31SBaptiste Daroussin }
111d9f0ce31SBaptiste Daroussin
112d9f0ce31SBaptiste Daroussin flags = UCL_PARSER_KEY_LOWERCASE;
113d9f0ce31SBaptiste Daroussin
114d9f0ce31SBaptiste Daroussin if (save_comments) {
115d9f0ce31SBaptiste Daroussin flags |= UCL_PARSER_SAVE_COMMENTS;
116d9f0ce31SBaptiste Daroussin }
117d9f0ce31SBaptiste Daroussin
118d9f0ce31SBaptiste Daroussin if (skip_macro) {
119d9f0ce31SBaptiste Daroussin flags |= UCL_PARSER_DISABLE_MACRO;
120d9f0ce31SBaptiste Daroussin }
121d9f0ce31SBaptiste Daroussin
122d9f0ce31SBaptiste Daroussin parser = ucl_parser_new (flags);
123c99fb5f9SBaptiste Daroussin ucl_parser_register_variable (parser, "ABI", "unknown");
124c99fb5f9SBaptiste Daroussin
125c99fb5f9SBaptiste Daroussin if (fname_in != NULL) {
126c99fb5f9SBaptiste Daroussin ucl_parser_set_filevars (parser, fname_in, true);
127c99fb5f9SBaptiste Daroussin }
128c99fb5f9SBaptiste Daroussin
129d9f0ce31SBaptiste Daroussin if (!use_fd) {
13039ee7a7aSBaptiste Daroussin inbuf = malloc (BUFSIZ);
13139ee7a7aSBaptiste Daroussin bufsize = BUFSIZ;
13239ee7a7aSBaptiste Daroussin r = 0;
13339ee7a7aSBaptiste Daroussin
13439ee7a7aSBaptiste Daroussin while (!feof (in) && !ferror (in)) {
13539ee7a7aSBaptiste Daroussin if (r == bufsize) {
13639ee7a7aSBaptiste Daroussin inbuf = realloc (inbuf, bufsize * 2);
13739ee7a7aSBaptiste Daroussin bufsize *= 2;
13839ee7a7aSBaptiste Daroussin if (inbuf == NULL) {
13939ee7a7aSBaptiste Daroussin perror ("realloc");
14039ee7a7aSBaptiste Daroussin exit (EXIT_FAILURE);
141b04a7a0bSBaptiste Daroussin }
142c99fb5f9SBaptiste Daroussin }
14339ee7a7aSBaptiste Daroussin r += fread (inbuf + r, 1, bufsize - r, in);
14439ee7a7aSBaptiste Daroussin }
14539ee7a7aSBaptiste Daroussin
14639ee7a7aSBaptiste Daroussin if (ferror (in)) {
14739ee7a7aSBaptiste Daroussin fprintf (stderr, "Failed to read the input file.\n");
14839ee7a7aSBaptiste Daroussin exit (EXIT_FAILURE);
14939ee7a7aSBaptiste Daroussin }
15039ee7a7aSBaptiste Daroussin
151*a0409676SBaptiste Daroussin ucl_parser_add_chunk_full (parser, (const unsigned char *)inbuf, r,
152*a0409676SBaptiste Daroussin 0, UCL_DUPLICATE_APPEND,
153*a0409676SBaptiste Daroussin msgpack_input ? UCL_PARSE_MSGPACK : UCL_PARSE_UCL);
154c99fb5f9SBaptiste Daroussin fclose (in);
155d9f0ce31SBaptiste Daroussin }
156d9f0ce31SBaptiste Daroussin else {
157d9f0ce31SBaptiste Daroussin ucl_parser_add_fd (parser, fd_in);
158d9f0ce31SBaptiste Daroussin close (fd_in);
159d9f0ce31SBaptiste Daroussin }
160c99fb5f9SBaptiste Daroussin
161d9f0ce31SBaptiste Daroussin if (!use_fd) {
162c99fb5f9SBaptiste Daroussin if (fname_out != NULL) {
163c99fb5f9SBaptiste Daroussin out = fopen (fname_out, "w");
164c99fb5f9SBaptiste Daroussin if (out == NULL) {
165c99fb5f9SBaptiste Daroussin exit (-errno);
166c99fb5f9SBaptiste Daroussin }
167c99fb5f9SBaptiste Daroussin }
168c99fb5f9SBaptiste Daroussin else {
169c99fb5f9SBaptiste Daroussin out = stdout;
170c99fb5f9SBaptiste Daroussin }
171d9f0ce31SBaptiste Daroussin }
172d9f0ce31SBaptiste Daroussin else {
173d9f0ce31SBaptiste Daroussin if (fname_out != NULL) {
174d9f0ce31SBaptiste Daroussin fd_out = open (fname_out, O_WRONLY | O_CREAT, 00644);
175d9f0ce31SBaptiste Daroussin if (fd_out == -1) {
176d9f0ce31SBaptiste Daroussin exit (-errno);
177d9f0ce31SBaptiste Daroussin }
178d9f0ce31SBaptiste Daroussin }
179d9f0ce31SBaptiste Daroussin else {
180d9f0ce31SBaptiste Daroussin fd_out = STDOUT_FILENO;
181d9f0ce31SBaptiste Daroussin }
182d9f0ce31SBaptiste Daroussin }
183d9f0ce31SBaptiste Daroussin
18439ee7a7aSBaptiste Daroussin
185c99fb5f9SBaptiste Daroussin if (ucl_parser_get_error (parser) != NULL) {
186d9f0ce31SBaptiste Daroussin fprintf (out, "Error occurred (phase 1): %s\n",
187d9f0ce31SBaptiste Daroussin ucl_parser_get_error(parser));
188c99fb5f9SBaptiste Daroussin ret = 1;
189c99fb5f9SBaptiste Daroussin goto end;
190c99fb5f9SBaptiste Daroussin }
19139ee7a7aSBaptiste Daroussin
192c99fb5f9SBaptiste Daroussin obj = ucl_parser_get_object (parser);
19339ee7a7aSBaptiste Daroussin
194d9f0ce31SBaptiste Daroussin if (save_comments) {
195d9f0ce31SBaptiste Daroussin comments = ucl_object_ref (ucl_parser_get_comments (parser));
196d9f0ce31SBaptiste Daroussin }
197d9f0ce31SBaptiste Daroussin
198c99fb5f9SBaptiste Daroussin if (json) {
1993dcf5eb7SBaptiste Daroussin if (compact) {
2003dcf5eb7SBaptiste Daroussin emitted = ucl_object_emit (obj, UCL_EMIT_JSON_COMPACT);
2013dcf5eb7SBaptiste Daroussin }
2023dcf5eb7SBaptiste Daroussin else {
203c99fb5f9SBaptiste Daroussin emitted = ucl_object_emit (obj, UCL_EMIT_JSON);
204c99fb5f9SBaptiste Daroussin }
2053dcf5eb7SBaptiste Daroussin }
2063dcf5eb7SBaptiste Daroussin else if (yaml) {
2073dcf5eb7SBaptiste Daroussin emitted = ucl_object_emit (obj, UCL_EMIT_YAML);
2083dcf5eb7SBaptiste Daroussin }
209c99fb5f9SBaptiste Daroussin else {
210d9f0ce31SBaptiste Daroussin emitted = NULL;
211d9f0ce31SBaptiste Daroussin func = ucl_object_emit_memory_funcs ((void **)&emitted);
212d9f0ce31SBaptiste Daroussin
213d9f0ce31SBaptiste Daroussin if (func != NULL) {
214d9f0ce31SBaptiste Daroussin ucl_object_emit_full (obj, UCL_EMIT_CONFIG, func, comments);
215d9f0ce31SBaptiste Daroussin ucl_object_emit_funcs_free (func);
216c99fb5f9SBaptiste Daroussin }
217d9f0ce31SBaptiste Daroussin }
218d9f0ce31SBaptiste Daroussin
219d9f0ce31SBaptiste Daroussin #if 0
220d9f0ce31SBaptiste Daroussin fprintf (out, "%s\n****\n", emitted);
221d9f0ce31SBaptiste Daroussin #endif
22239ee7a7aSBaptiste Daroussin
223c99fb5f9SBaptiste Daroussin ucl_parser_free (parser);
224c99fb5f9SBaptiste Daroussin ucl_object_unref (obj);
225d9f0ce31SBaptiste Daroussin parser2 = ucl_parser_new (flags);
2264bf54857SBaptiste Daroussin ucl_parser_add_string (parser2, (const char *)emitted, 0);
227c99fb5f9SBaptiste Daroussin
228c99fb5f9SBaptiste Daroussin if (ucl_parser_get_error(parser2) != NULL) {
229d9f0ce31SBaptiste Daroussin fprintf (out, "Error occurred (phase 2): %s\n",
230d9f0ce31SBaptiste Daroussin ucl_parser_get_error(parser2));
231c99fb5f9SBaptiste Daroussin fprintf (out, "%s\n", emitted);
232c99fb5f9SBaptiste Daroussin ret = 1;
233c99fb5f9SBaptiste Daroussin goto end;
234c99fb5f9SBaptiste Daroussin }
23539ee7a7aSBaptiste Daroussin
236c99fb5f9SBaptiste Daroussin if (emitted != NULL) {
237c99fb5f9SBaptiste Daroussin free (emitted);
238c99fb5f9SBaptiste Daroussin }
239d9f0ce31SBaptiste Daroussin if (comments) {
240d9f0ce31SBaptiste Daroussin ucl_object_unref (comments);
241d9f0ce31SBaptiste Daroussin comments = NULL;
242d9f0ce31SBaptiste Daroussin }
243d9f0ce31SBaptiste Daroussin
244d9f0ce31SBaptiste Daroussin if (save_comments) {
245d9f0ce31SBaptiste Daroussin comments = ucl_object_ref (ucl_parser_get_comments (parser2));
246d9f0ce31SBaptiste Daroussin }
24739ee7a7aSBaptiste Daroussin
248c99fb5f9SBaptiste Daroussin obj = ucl_parser_get_object (parser2);
249d9f0ce31SBaptiste Daroussin
250d9f0ce31SBaptiste Daroussin if (!use_fd) {
251d9f0ce31SBaptiste Daroussin func = ucl_object_emit_file_funcs (out);
2523dcf5eb7SBaptiste Daroussin }
2533dcf5eb7SBaptiste Daroussin else {
254d9f0ce31SBaptiste Daroussin func = ucl_object_emit_fd_funcs (fd_out);
255d9f0ce31SBaptiste Daroussin }
256d9f0ce31SBaptiste Daroussin
257d9f0ce31SBaptiste Daroussin if (func != NULL) {
258d9f0ce31SBaptiste Daroussin if (json) {
259d9f0ce31SBaptiste Daroussin if (compact) {
260d9f0ce31SBaptiste Daroussin ucl_object_emit_full (obj, UCL_EMIT_JSON_COMPACT,
261d9f0ce31SBaptiste Daroussin func, comments);
262d9f0ce31SBaptiste Daroussin }
263d9f0ce31SBaptiste Daroussin else {
264d9f0ce31SBaptiste Daroussin ucl_object_emit_full (obj, UCL_EMIT_JSON,
265d9f0ce31SBaptiste Daroussin func, comments);
266c99fb5f9SBaptiste Daroussin }
2673dcf5eb7SBaptiste Daroussin }
2683dcf5eb7SBaptiste Daroussin else if (yaml) {
269d9f0ce31SBaptiste Daroussin ucl_object_emit_full (obj, UCL_EMIT_YAML,
270d9f0ce31SBaptiste Daroussin func, comments);
2713dcf5eb7SBaptiste Daroussin }
272c99fb5f9SBaptiste Daroussin else {
273d9f0ce31SBaptiste Daroussin ucl_object_emit_full (obj, UCL_EMIT_CONFIG,
274d9f0ce31SBaptiste Daroussin func, comments);
275c99fb5f9SBaptiste Daroussin }
276c99fb5f9SBaptiste Daroussin
277d9f0ce31SBaptiste Daroussin ucl_object_emit_funcs_free (func);
278d9f0ce31SBaptiste Daroussin }
279d9f0ce31SBaptiste Daroussin
280d9f0ce31SBaptiste Daroussin if (!use_fd) {
281d9f0ce31SBaptiste Daroussin fprintf (out, "\n");
282d9f0ce31SBaptiste Daroussin fclose (out);
283d9f0ce31SBaptiste Daroussin }
284d9f0ce31SBaptiste Daroussin else {
285d9f0ce31SBaptiste Daroussin write (fd_out, "\n", 1);
286d9f0ce31SBaptiste Daroussin close (fd_out);
287d9f0ce31SBaptiste Daroussin }
288d9f0ce31SBaptiste Daroussin
289c99fb5f9SBaptiste Daroussin ucl_object_unref (obj);
290c99fb5f9SBaptiste Daroussin
291c99fb5f9SBaptiste Daroussin end:
292c99fb5f9SBaptiste Daroussin if (parser2 != NULL) {
293c99fb5f9SBaptiste Daroussin ucl_parser_free (parser2);
294c99fb5f9SBaptiste Daroussin }
295d9f0ce31SBaptiste Daroussin if (comments) {
296d9f0ce31SBaptiste Daroussin ucl_object_unref (comments);
297d9f0ce31SBaptiste Daroussin }
29839ee7a7aSBaptiste Daroussin if (inbuf != NULL) {
29939ee7a7aSBaptiste Daroussin free (inbuf);
300c99fb5f9SBaptiste Daroussin }
301c99fb5f9SBaptiste Daroussin
302c99fb5f9SBaptiste Daroussin return ret;
303c99fb5f9SBaptiste Daroussin }
304