xref: /freebsd-src/contrib/libucl/tests/test_basic.c (revision d9f0ce31900a48d1a2bfc1c8c86f79d1e831451a)
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"
26*d9f0ce31SBaptiste Daroussin #include <sys/types.h>
27*d9f0ce31SBaptiste Daroussin #include <fcntl.h>
28*d9f0ce31SBaptiste Daroussin #include <unistd.h>
29*d9f0ce31SBaptiste Daroussin 
30c99fb5f9SBaptiste Daroussin 
31c99fb5f9SBaptiste Daroussin int
32c99fb5f9SBaptiste Daroussin main (int argc, char **argv)
33c99fb5f9SBaptiste Daroussin {
34*d9f0ce31SBaptiste Daroussin 	char *inbuf = NULL;
35c99fb5f9SBaptiste Daroussin 	struct ucl_parser *parser = NULL, *parser2 = NULL;
36*d9f0ce31SBaptiste 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;
41*d9f0ce31SBaptiste Daroussin 	int ret = 0, opt, json = 0, compact = 0, yaml = 0,
42*d9f0ce31SBaptiste Daroussin 			save_comments = 0, skip_macro = 0,
43*d9f0ce31SBaptiste Daroussin 			flags, fd_out, fd_in, use_fd = 0;
44*d9f0ce31SBaptiste Daroussin 	struct ucl_emitter_functions *func;
45c99fb5f9SBaptiste Daroussin 
46*d9f0ce31SBaptiste Daroussin 	while ((opt = getopt(argc, argv, "fjcyCM")) != -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;
54*d9f0ce31SBaptiste Daroussin 		case 'C':
55*d9f0ce31SBaptiste Daroussin 			save_comments = 1;
56*d9f0ce31SBaptiste Daroussin 			break;
573dcf5eb7SBaptiste Daroussin 		case 'y':
583dcf5eb7SBaptiste Daroussin 			yaml = 1;
593dcf5eb7SBaptiste Daroussin 			break;
60*d9f0ce31SBaptiste Daroussin 		case 'M':
61*d9f0ce31SBaptiste Daroussin 			skip_macro = true;
62*d9f0ce31SBaptiste Daroussin 			break;
63*d9f0ce31SBaptiste Daroussin 		case 'f':
64*d9f0ce31SBaptiste Daroussin 			use_fd = true;
65*d9f0ce31SBaptiste Daroussin 			break;
66c99fb5f9SBaptiste Daroussin 		default: /* '?' */
67*d9f0ce31SBaptiste Daroussin 			fprintf (stderr, "Usage: %s [-jcy] [-CM] [-f] [in] [out]\n",
68c99fb5f9SBaptiste Daroussin 					argv[0]);
69c99fb5f9SBaptiste Daroussin 			exit (EXIT_FAILURE);
70c99fb5f9SBaptiste Daroussin 		}
71c99fb5f9SBaptiste Daroussin 	}
72c99fb5f9SBaptiste Daroussin 
73c99fb5f9SBaptiste Daroussin 	argc -= optind;
74c99fb5f9SBaptiste Daroussin 	argv += optind;
75c99fb5f9SBaptiste Daroussin 
76c99fb5f9SBaptiste Daroussin 	switch (argc) {
77c99fb5f9SBaptiste Daroussin 	case 1:
78c99fb5f9SBaptiste Daroussin 		fname_in = argv[0];
79c99fb5f9SBaptiste Daroussin 		break;
80c99fb5f9SBaptiste Daroussin 	case 2:
81c99fb5f9SBaptiste Daroussin 		fname_in = argv[0];
82c99fb5f9SBaptiste Daroussin 		fname_out = argv[1];
83c99fb5f9SBaptiste Daroussin 		break;
84c99fb5f9SBaptiste Daroussin 	}
85c99fb5f9SBaptiste Daroussin 
86*d9f0ce31SBaptiste Daroussin 	if (!use_fd) {
87c99fb5f9SBaptiste Daroussin 		if (fname_in != NULL) {
88c99fb5f9SBaptiste Daroussin 			in = fopen (fname_in, "r");
89c99fb5f9SBaptiste Daroussin 			if (in == NULL) {
90c99fb5f9SBaptiste Daroussin 				exit (-errno);
91c99fb5f9SBaptiste Daroussin 			}
92c99fb5f9SBaptiste Daroussin 		}
93c99fb5f9SBaptiste Daroussin 		else {
94c99fb5f9SBaptiste Daroussin 			in = stdin;
95c99fb5f9SBaptiste Daroussin 		}
96*d9f0ce31SBaptiste Daroussin 	}
97*d9f0ce31SBaptiste Daroussin 	else {
98*d9f0ce31SBaptiste Daroussin 		if (fname_in != NULL) {
99*d9f0ce31SBaptiste Daroussin 			fd_in = open (fname_in, O_RDONLY);
100*d9f0ce31SBaptiste Daroussin 			if (fd_in == -1) {
101*d9f0ce31SBaptiste Daroussin 				exit (-errno);
102*d9f0ce31SBaptiste Daroussin 			}
103*d9f0ce31SBaptiste Daroussin 		}
104*d9f0ce31SBaptiste Daroussin 		else {
105*d9f0ce31SBaptiste Daroussin 			fd_in = STDIN_FILENO;
106*d9f0ce31SBaptiste Daroussin 		}
107*d9f0ce31SBaptiste Daroussin 	}
108*d9f0ce31SBaptiste Daroussin 
109*d9f0ce31SBaptiste Daroussin 	flags = UCL_PARSER_KEY_LOWERCASE;
110*d9f0ce31SBaptiste Daroussin 
111*d9f0ce31SBaptiste Daroussin 	if (save_comments) {
112*d9f0ce31SBaptiste Daroussin 		flags |= UCL_PARSER_SAVE_COMMENTS;
113*d9f0ce31SBaptiste Daroussin 	}
114*d9f0ce31SBaptiste Daroussin 
115*d9f0ce31SBaptiste Daroussin 	if (skip_macro) {
116*d9f0ce31SBaptiste Daroussin 		flags |= UCL_PARSER_DISABLE_MACRO;
117*d9f0ce31SBaptiste Daroussin 	}
118*d9f0ce31SBaptiste Daroussin 
119*d9f0ce31SBaptiste Daroussin 	parser = ucl_parser_new (flags);
120c99fb5f9SBaptiste Daroussin 	ucl_parser_register_variable (parser, "ABI", "unknown");
121c99fb5f9SBaptiste Daroussin 
122c99fb5f9SBaptiste Daroussin 	if (fname_in != NULL) {
123c99fb5f9SBaptiste Daroussin 		ucl_parser_set_filevars (parser, fname_in, true);
124c99fb5f9SBaptiste Daroussin 	}
125c99fb5f9SBaptiste Daroussin 
126*d9f0ce31SBaptiste Daroussin 	if (!use_fd) {
12739ee7a7aSBaptiste Daroussin 		inbuf = malloc (BUFSIZ);
12839ee7a7aSBaptiste Daroussin 		bufsize = BUFSIZ;
12939ee7a7aSBaptiste Daroussin 		r = 0;
13039ee7a7aSBaptiste Daroussin 
13139ee7a7aSBaptiste Daroussin 		while (!feof (in) && !ferror (in)) {
13239ee7a7aSBaptiste Daroussin 			if (r == bufsize) {
13339ee7a7aSBaptiste Daroussin 				inbuf = realloc (inbuf, bufsize * 2);
13439ee7a7aSBaptiste Daroussin 				bufsize *= 2;
13539ee7a7aSBaptiste Daroussin 				if (inbuf == NULL) {
13639ee7a7aSBaptiste Daroussin 					perror ("realloc");
13739ee7a7aSBaptiste Daroussin 					exit (EXIT_FAILURE);
138b04a7a0bSBaptiste Daroussin 				}
139c99fb5f9SBaptiste Daroussin 			}
14039ee7a7aSBaptiste Daroussin 			r += fread (inbuf + r, 1, bufsize - r, in);
14139ee7a7aSBaptiste Daroussin 		}
14239ee7a7aSBaptiste Daroussin 
14339ee7a7aSBaptiste Daroussin 		if (ferror (in)) {
14439ee7a7aSBaptiste Daroussin 			fprintf (stderr, "Failed to read the input file.\n");
14539ee7a7aSBaptiste Daroussin 			exit (EXIT_FAILURE);
14639ee7a7aSBaptiste Daroussin 		}
14739ee7a7aSBaptiste Daroussin 
14839ee7a7aSBaptiste Daroussin 		ucl_parser_add_chunk (parser, (const unsigned char *)inbuf, r);
149c99fb5f9SBaptiste Daroussin 		fclose (in);
150*d9f0ce31SBaptiste Daroussin 	}
151*d9f0ce31SBaptiste Daroussin 	else {
152*d9f0ce31SBaptiste Daroussin 		ucl_parser_add_fd (parser, fd_in);
153*d9f0ce31SBaptiste Daroussin 		close (fd_in);
154*d9f0ce31SBaptiste Daroussin 	}
155c99fb5f9SBaptiste Daroussin 
156*d9f0ce31SBaptiste Daroussin 	if (!use_fd) {
157c99fb5f9SBaptiste Daroussin 		if (fname_out != NULL) {
158c99fb5f9SBaptiste Daroussin 			out = fopen (fname_out, "w");
159c99fb5f9SBaptiste Daroussin 			if (out == NULL) {
160c99fb5f9SBaptiste Daroussin 				exit (-errno);
161c99fb5f9SBaptiste Daroussin 			}
162c99fb5f9SBaptiste Daroussin 		}
163c99fb5f9SBaptiste Daroussin 		else {
164c99fb5f9SBaptiste Daroussin 			out = stdout;
165c99fb5f9SBaptiste Daroussin 		}
166*d9f0ce31SBaptiste Daroussin 	}
167*d9f0ce31SBaptiste Daroussin 	else {
168*d9f0ce31SBaptiste Daroussin 		if (fname_out != NULL) {
169*d9f0ce31SBaptiste Daroussin 			fd_out = open (fname_out, O_WRONLY | O_CREAT, 00644);
170*d9f0ce31SBaptiste Daroussin 			if (fd_out == -1) {
171*d9f0ce31SBaptiste Daroussin 				exit (-errno);
172*d9f0ce31SBaptiste Daroussin 			}
173*d9f0ce31SBaptiste Daroussin 		}
174*d9f0ce31SBaptiste Daroussin 		else {
175*d9f0ce31SBaptiste Daroussin 			fd_out = STDOUT_FILENO;
176*d9f0ce31SBaptiste Daroussin 		}
177*d9f0ce31SBaptiste Daroussin 	}
178*d9f0ce31SBaptiste Daroussin 
17939ee7a7aSBaptiste Daroussin 
180c99fb5f9SBaptiste Daroussin 	if (ucl_parser_get_error (parser) != NULL) {
181*d9f0ce31SBaptiste Daroussin 		fprintf (out, "Error occurred (phase 1): %s\n",
182*d9f0ce31SBaptiste Daroussin 						ucl_parser_get_error(parser));
183c99fb5f9SBaptiste Daroussin 		ret = 1;
184c99fb5f9SBaptiste Daroussin 		goto end;
185c99fb5f9SBaptiste Daroussin 	}
18639ee7a7aSBaptiste Daroussin 
187c99fb5f9SBaptiste Daroussin 	obj = ucl_parser_get_object (parser);
18839ee7a7aSBaptiste Daroussin 
189*d9f0ce31SBaptiste Daroussin 	if (save_comments) {
190*d9f0ce31SBaptiste Daroussin 		comments = ucl_object_ref (ucl_parser_get_comments (parser));
191*d9f0ce31SBaptiste Daroussin 	}
192*d9f0ce31SBaptiste Daroussin 
193c99fb5f9SBaptiste Daroussin 	if (json) {
1943dcf5eb7SBaptiste Daroussin 		if (compact) {
1953dcf5eb7SBaptiste Daroussin 			emitted = ucl_object_emit (obj, UCL_EMIT_JSON_COMPACT);
1963dcf5eb7SBaptiste Daroussin 		}
1973dcf5eb7SBaptiste Daroussin 		else {
198c99fb5f9SBaptiste Daroussin 			emitted = ucl_object_emit (obj, UCL_EMIT_JSON);
199c99fb5f9SBaptiste Daroussin 		}
2003dcf5eb7SBaptiste Daroussin 	}
2013dcf5eb7SBaptiste Daroussin 	else if (yaml) {
2023dcf5eb7SBaptiste Daroussin 		emitted = ucl_object_emit (obj, UCL_EMIT_YAML);
2033dcf5eb7SBaptiste Daroussin 	}
204c99fb5f9SBaptiste Daroussin 	else {
205*d9f0ce31SBaptiste Daroussin 		emitted = NULL;
206*d9f0ce31SBaptiste Daroussin 		func = ucl_object_emit_memory_funcs ((void **)&emitted);
207*d9f0ce31SBaptiste Daroussin 
208*d9f0ce31SBaptiste Daroussin 		if (func != NULL) {
209*d9f0ce31SBaptiste Daroussin 			ucl_object_emit_full (obj, UCL_EMIT_CONFIG, func, comments);
210*d9f0ce31SBaptiste Daroussin 			ucl_object_emit_funcs_free (func);
211c99fb5f9SBaptiste Daroussin 		}
212*d9f0ce31SBaptiste Daroussin 	}
213*d9f0ce31SBaptiste Daroussin 
214*d9f0ce31SBaptiste Daroussin #if 0
215*d9f0ce31SBaptiste Daroussin 	fprintf (out, "%s\n****\n", emitted);
216*d9f0ce31SBaptiste Daroussin #endif
21739ee7a7aSBaptiste Daroussin 
218c99fb5f9SBaptiste Daroussin 	ucl_parser_free (parser);
219c99fb5f9SBaptiste Daroussin 	ucl_object_unref (obj);
220*d9f0ce31SBaptiste Daroussin 	parser2 = ucl_parser_new (flags);
2214bf54857SBaptiste Daroussin 	ucl_parser_add_string (parser2, (const char *)emitted, 0);
222c99fb5f9SBaptiste Daroussin 
223c99fb5f9SBaptiste Daroussin 	if (ucl_parser_get_error(parser2) != NULL) {
224*d9f0ce31SBaptiste Daroussin 		fprintf (out, "Error occurred (phase 2): %s\n",
225*d9f0ce31SBaptiste Daroussin 				ucl_parser_get_error(parser2));
226c99fb5f9SBaptiste Daroussin 		fprintf (out, "%s\n", emitted);
227c99fb5f9SBaptiste Daroussin 		ret = 1;
228c99fb5f9SBaptiste Daroussin 		goto end;
229c99fb5f9SBaptiste Daroussin 	}
23039ee7a7aSBaptiste Daroussin 
231c99fb5f9SBaptiste Daroussin 	if (emitted != NULL) {
232c99fb5f9SBaptiste Daroussin 		free (emitted);
233c99fb5f9SBaptiste Daroussin 	}
234*d9f0ce31SBaptiste Daroussin 	if (comments) {
235*d9f0ce31SBaptiste Daroussin 		ucl_object_unref (comments);
236*d9f0ce31SBaptiste Daroussin 		comments = NULL;
237*d9f0ce31SBaptiste Daroussin 	}
238*d9f0ce31SBaptiste Daroussin 
239*d9f0ce31SBaptiste Daroussin 	if (save_comments) {
240*d9f0ce31SBaptiste Daroussin 		comments = ucl_object_ref (ucl_parser_get_comments (parser2));
241*d9f0ce31SBaptiste Daroussin 	}
24239ee7a7aSBaptiste Daroussin 
243c99fb5f9SBaptiste Daroussin 	obj = ucl_parser_get_object (parser2);
244*d9f0ce31SBaptiste Daroussin 
245*d9f0ce31SBaptiste Daroussin 	if (!use_fd) {
246*d9f0ce31SBaptiste Daroussin 		func = ucl_object_emit_file_funcs (out);
2473dcf5eb7SBaptiste Daroussin 	}
2483dcf5eb7SBaptiste Daroussin 	else {
249*d9f0ce31SBaptiste Daroussin 		func = ucl_object_emit_fd_funcs (fd_out);
250*d9f0ce31SBaptiste Daroussin 	}
251*d9f0ce31SBaptiste Daroussin 
252*d9f0ce31SBaptiste Daroussin 	if (func != NULL) {
253*d9f0ce31SBaptiste Daroussin 		if (json) {
254*d9f0ce31SBaptiste Daroussin 			if (compact) {
255*d9f0ce31SBaptiste Daroussin 				ucl_object_emit_full (obj, UCL_EMIT_JSON_COMPACT,
256*d9f0ce31SBaptiste Daroussin 						func, comments);
257*d9f0ce31SBaptiste Daroussin 			}
258*d9f0ce31SBaptiste Daroussin 			else {
259*d9f0ce31SBaptiste Daroussin 				ucl_object_emit_full (obj, UCL_EMIT_JSON,
260*d9f0ce31SBaptiste Daroussin 						func, comments);
261c99fb5f9SBaptiste Daroussin 			}
2623dcf5eb7SBaptiste Daroussin 		}
2633dcf5eb7SBaptiste Daroussin 		else if (yaml) {
264*d9f0ce31SBaptiste Daroussin 			ucl_object_emit_full (obj, UCL_EMIT_YAML,
265*d9f0ce31SBaptiste Daroussin 					func, comments);
2663dcf5eb7SBaptiste Daroussin 		}
267c99fb5f9SBaptiste Daroussin 		else {
268*d9f0ce31SBaptiste Daroussin 			ucl_object_emit_full (obj, UCL_EMIT_CONFIG,
269*d9f0ce31SBaptiste Daroussin 					func, comments);
270c99fb5f9SBaptiste Daroussin 		}
271c99fb5f9SBaptiste Daroussin 
272*d9f0ce31SBaptiste Daroussin 		ucl_object_emit_funcs_free (func);
273*d9f0ce31SBaptiste Daroussin 	}
274*d9f0ce31SBaptiste Daroussin 
275*d9f0ce31SBaptiste Daroussin 	if (!use_fd) {
276*d9f0ce31SBaptiste Daroussin 		fprintf (out, "\n");
277*d9f0ce31SBaptiste Daroussin 		fclose (out);
278*d9f0ce31SBaptiste Daroussin 	}
279*d9f0ce31SBaptiste Daroussin 	else {
280*d9f0ce31SBaptiste Daroussin 		write (fd_out, "\n", 1);
281*d9f0ce31SBaptiste Daroussin 		close (fd_out);
282*d9f0ce31SBaptiste Daroussin 	}
283*d9f0ce31SBaptiste Daroussin 
284c99fb5f9SBaptiste Daroussin 	ucl_object_unref (obj);
285c99fb5f9SBaptiste Daroussin 
286c99fb5f9SBaptiste Daroussin end:
287c99fb5f9SBaptiste Daroussin 	if (parser2 != NULL) {
288c99fb5f9SBaptiste Daroussin 		ucl_parser_free (parser2);
289c99fb5f9SBaptiste Daroussin 	}
290*d9f0ce31SBaptiste Daroussin 	if (comments) {
291*d9f0ce31SBaptiste Daroussin 		ucl_object_unref (comments);
292*d9f0ce31SBaptiste Daroussin 	}
29339ee7a7aSBaptiste Daroussin 	if (inbuf != NULL) {
29439ee7a7aSBaptiste Daroussin 		free (inbuf);
295c99fb5f9SBaptiste Daroussin 	}
296c99fb5f9SBaptiste Daroussin 
297c99fb5f9SBaptiste Daroussin 	return ret;
298c99fb5f9SBaptiste Daroussin }
299