xref: /freebsd-src/contrib/libucl/tests/test_basic.c (revision a0409676120c1e558d0ade943019934e0f15118d)
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