xref: /src/contrib/libucl/tests/test_basic.c (revision a0409676120c1e558d0ade943019934e0f15118d) !
1337c43ffSBaptiste Daroussin /* Copyright (c) 2013, Vsevolod Stakhov
2337c43ffSBaptiste Daroussin  * All rights reserved.
3337c43ffSBaptiste Daroussin  *
4337c43ffSBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
5337c43ffSBaptiste Daroussin  * modification, are permitted provided that the following conditions are met:
6337c43ffSBaptiste Daroussin  *       * Redistributions of source code must retain the above copyright
7337c43ffSBaptiste Daroussin  *         notice, this list of conditions and the following disclaimer.
8337c43ffSBaptiste Daroussin  *       * Redistributions in binary form must reproduce the above copyright
9337c43ffSBaptiste Daroussin  *         notice, this list of conditions and the following disclaimer in the
10337c43ffSBaptiste Daroussin  *         documentation and/or other materials provided with the distribution.
11337c43ffSBaptiste Daroussin  *
12337c43ffSBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13337c43ffSBaptiste Daroussin  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14337c43ffSBaptiste Daroussin  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15337c43ffSBaptiste Daroussin  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16337c43ffSBaptiste Daroussin  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17337c43ffSBaptiste Daroussin  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18337c43ffSBaptiste Daroussin  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19337c43ffSBaptiste Daroussin  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20337c43ffSBaptiste Daroussin  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21337c43ffSBaptiste Daroussin  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22337c43ffSBaptiste Daroussin  */
23337c43ffSBaptiste Daroussin 
24337c43ffSBaptiste Daroussin #include "ucl.h"
25bfc6d683SBaptiste Daroussin #include "ucl_internal.h"
2694f2b741SBaptiste Daroussin #include <sys/types.h>
2794f2b741SBaptiste Daroussin #include <fcntl.h>
2894f2b741SBaptiste Daroussin #include <unistd.h>
2994f2b741SBaptiste Daroussin 
30337c43ffSBaptiste Daroussin 
31337c43ffSBaptiste Daroussin int
main(int argc,char ** argv)32337c43ffSBaptiste Daroussin main (int argc, char **argv)
33337c43ffSBaptiste Daroussin {
3494f2b741SBaptiste Daroussin 	char *inbuf = NULL;
35337c43ffSBaptiste Daroussin 	struct ucl_parser *parser = NULL, *parser2 = NULL;
3694f2b741SBaptiste Daroussin 	ucl_object_t *obj, *comments = NULL;
374e2fa78eSBaptiste Daroussin 	ssize_t bufsize, r;
38337c43ffSBaptiste Daroussin 	FILE *in, *out;
39337c43ffSBaptiste Daroussin 	unsigned char *emitted = NULL;
40337c43ffSBaptiste Daroussin 	const char *fname_in = NULL, *fname_out = NULL;
4194f2b741SBaptiste Daroussin 	int ret = 0, opt, json = 0, compact = 0, yaml = 0,
4294f2b741SBaptiste Daroussin 			save_comments = 0, skip_macro = 0,
433c319408SBaptiste Daroussin 			flags, fd_out, fd_in, use_fd = 0, msgpack_input = 0;
4494f2b741SBaptiste Daroussin 	struct ucl_emitter_functions *func;
45337c43ffSBaptiste Daroussin 
463c319408SBaptiste Daroussin 	while ((opt = getopt(argc, argv, "fjcyCMm")) != -1) {
47337c43ffSBaptiste Daroussin 		switch (opt) {
48337c43ffSBaptiste Daroussin 		case 'j':
49337c43ffSBaptiste Daroussin 			json = 1;
50337c43ffSBaptiste Daroussin 			break;
51f4dd0993SBaptiste Daroussin 		case 'c':
52f4dd0993SBaptiste Daroussin 			compact = 1;
53f4dd0993SBaptiste Daroussin 			break;
5494f2b741SBaptiste Daroussin 		case 'C':
5594f2b741SBaptiste Daroussin 			save_comments = 1;
5694f2b741SBaptiste Daroussin 			break;
57f4dd0993SBaptiste Daroussin 		case 'y':
58f4dd0993SBaptiste Daroussin 			yaml = 1;
59f4dd0993SBaptiste Daroussin 			break;
6094f2b741SBaptiste Daroussin 		case 'M':
6194f2b741SBaptiste Daroussin 			skip_macro = true;
6294f2b741SBaptiste Daroussin 			break;
633c319408SBaptiste Daroussin 		case 'm':
643c319408SBaptiste Daroussin 			msgpack_input = 1;
653c319408SBaptiste Daroussin 			break;
6694f2b741SBaptiste Daroussin 		case 'f':
6794f2b741SBaptiste Daroussin 			use_fd = true;
6894f2b741SBaptiste Daroussin 			break;
69337c43ffSBaptiste Daroussin 		default: /* '?' */
7094f2b741SBaptiste Daroussin 			fprintf (stderr, "Usage: %s [-jcy] [-CM] [-f] [in] [out]\n",
71337c43ffSBaptiste Daroussin 					argv[0]);
72337c43ffSBaptiste Daroussin 			exit (EXIT_FAILURE);
73337c43ffSBaptiste Daroussin 		}
74337c43ffSBaptiste Daroussin 	}
75337c43ffSBaptiste Daroussin 
76337c43ffSBaptiste Daroussin 	argc -= optind;
77337c43ffSBaptiste Daroussin 	argv += optind;
78337c43ffSBaptiste Daroussin 
79337c43ffSBaptiste Daroussin 	switch (argc) {
80337c43ffSBaptiste Daroussin 	case 1:
81337c43ffSBaptiste Daroussin 		fname_in = argv[0];
82337c43ffSBaptiste Daroussin 		break;
83337c43ffSBaptiste Daroussin 	case 2:
84337c43ffSBaptiste Daroussin 		fname_in = argv[0];
85337c43ffSBaptiste Daroussin 		fname_out = argv[1];
86337c43ffSBaptiste Daroussin 		break;
87337c43ffSBaptiste Daroussin 	}
88337c43ffSBaptiste Daroussin 
8994f2b741SBaptiste Daroussin 	if (!use_fd) {
90337c43ffSBaptiste Daroussin 		if (fname_in != NULL) {
91337c43ffSBaptiste Daroussin 			in = fopen (fname_in, "r");
92337c43ffSBaptiste Daroussin 			if (in == NULL) {
93337c43ffSBaptiste Daroussin 				exit (-errno);
94337c43ffSBaptiste Daroussin 			}
95337c43ffSBaptiste Daroussin 		}
96337c43ffSBaptiste Daroussin 		else {
97337c43ffSBaptiste Daroussin 			in = stdin;
98337c43ffSBaptiste Daroussin 		}
9994f2b741SBaptiste Daroussin 	}
10094f2b741SBaptiste Daroussin 	else {
10194f2b741SBaptiste Daroussin 		if (fname_in != NULL) {
10294f2b741SBaptiste Daroussin 			fd_in = open (fname_in, O_RDONLY);
10394f2b741SBaptiste Daroussin 			if (fd_in == -1) {
10494f2b741SBaptiste Daroussin 				exit (-errno);
10594f2b741SBaptiste Daroussin 			}
10694f2b741SBaptiste Daroussin 		}
10794f2b741SBaptiste Daroussin 		else {
10894f2b741SBaptiste Daroussin 			fd_in = STDIN_FILENO;
10994f2b741SBaptiste Daroussin 		}
11094f2b741SBaptiste Daroussin 	}
11194f2b741SBaptiste Daroussin 
11294f2b741SBaptiste Daroussin 	flags = UCL_PARSER_KEY_LOWERCASE;
11394f2b741SBaptiste Daroussin 
11494f2b741SBaptiste Daroussin 	if (save_comments) {
11594f2b741SBaptiste Daroussin 		flags |= UCL_PARSER_SAVE_COMMENTS;
11694f2b741SBaptiste Daroussin 	}
11794f2b741SBaptiste Daroussin 
11894f2b741SBaptiste Daroussin 	if (skip_macro) {
11994f2b741SBaptiste Daroussin 		flags |= UCL_PARSER_DISABLE_MACRO;
12094f2b741SBaptiste Daroussin 	}
12194f2b741SBaptiste Daroussin 
12294f2b741SBaptiste Daroussin 	parser = ucl_parser_new (flags);
123337c43ffSBaptiste Daroussin 	ucl_parser_register_variable (parser, "ABI", "unknown");
124337c43ffSBaptiste Daroussin 
125337c43ffSBaptiste Daroussin 	if (fname_in != NULL) {
126337c43ffSBaptiste Daroussin 		ucl_parser_set_filevars (parser, fname_in, true);
127337c43ffSBaptiste Daroussin 	}
128337c43ffSBaptiste Daroussin 
12994f2b741SBaptiste Daroussin 	if (!use_fd) {
1304e2fa78eSBaptiste Daroussin 		inbuf = malloc (BUFSIZ);
1314e2fa78eSBaptiste Daroussin 		bufsize = BUFSIZ;
1324e2fa78eSBaptiste Daroussin 		r = 0;
1334e2fa78eSBaptiste Daroussin 
1344e2fa78eSBaptiste Daroussin 		while (!feof (in) && !ferror (in)) {
1354e2fa78eSBaptiste Daroussin 			if (r == bufsize) {
1364e2fa78eSBaptiste Daroussin 				inbuf = realloc (inbuf, bufsize * 2);
1374e2fa78eSBaptiste Daroussin 				bufsize *= 2;
1384e2fa78eSBaptiste Daroussin 				if (inbuf == NULL) {
1394e2fa78eSBaptiste Daroussin 					perror ("realloc");
1404e2fa78eSBaptiste Daroussin 					exit (EXIT_FAILURE);
141d4fc17b1SBaptiste Daroussin 				}
142337c43ffSBaptiste Daroussin 			}
1434e2fa78eSBaptiste Daroussin 			r += fread (inbuf + r, 1, bufsize - r, in);
1444e2fa78eSBaptiste Daroussin 		}
1454e2fa78eSBaptiste Daroussin 
1464e2fa78eSBaptiste Daroussin 		if (ferror (in)) {
1474e2fa78eSBaptiste Daroussin 			fprintf (stderr, "Failed to read the input file.\n");
1484e2fa78eSBaptiste Daroussin 			exit (EXIT_FAILURE);
1494e2fa78eSBaptiste Daroussin 		}
1504e2fa78eSBaptiste Daroussin 
1513c319408SBaptiste Daroussin 		ucl_parser_add_chunk_full (parser, (const unsigned char *)inbuf, r,
1523c319408SBaptiste Daroussin 				0, UCL_DUPLICATE_APPEND,
1533c319408SBaptiste Daroussin 				msgpack_input ? UCL_PARSE_MSGPACK : UCL_PARSE_UCL);
154337c43ffSBaptiste Daroussin 		fclose (in);
15594f2b741SBaptiste Daroussin 	}
15694f2b741SBaptiste Daroussin 	else {
15794f2b741SBaptiste Daroussin 		ucl_parser_add_fd (parser, fd_in);
15894f2b741SBaptiste Daroussin 		close (fd_in);
15994f2b741SBaptiste Daroussin 	}
160337c43ffSBaptiste Daroussin 
16194f2b741SBaptiste Daroussin 	if (!use_fd) {
162337c43ffSBaptiste Daroussin 		if (fname_out != NULL) {
163337c43ffSBaptiste Daroussin 			out = fopen (fname_out, "w");
164337c43ffSBaptiste Daroussin 			if (out == NULL) {
165337c43ffSBaptiste Daroussin 				exit (-errno);
166337c43ffSBaptiste Daroussin 			}
167337c43ffSBaptiste Daroussin 		}
168337c43ffSBaptiste Daroussin 		else {
169337c43ffSBaptiste Daroussin 			out = stdout;
170337c43ffSBaptiste Daroussin 		}
17194f2b741SBaptiste Daroussin 	}
17294f2b741SBaptiste Daroussin 	else {
17394f2b741SBaptiste Daroussin 		if (fname_out != NULL) {
17494f2b741SBaptiste Daroussin 			fd_out = open (fname_out, O_WRONLY | O_CREAT, 00644);
17594f2b741SBaptiste Daroussin 			if (fd_out == -1) {
17694f2b741SBaptiste Daroussin 				exit (-errno);
17794f2b741SBaptiste Daroussin 			}
17894f2b741SBaptiste Daroussin 		}
17994f2b741SBaptiste Daroussin 		else {
18094f2b741SBaptiste Daroussin 			fd_out = STDOUT_FILENO;
18194f2b741SBaptiste Daroussin 		}
18294f2b741SBaptiste Daroussin 	}
18394f2b741SBaptiste Daroussin 
1844e2fa78eSBaptiste Daroussin 
185337c43ffSBaptiste Daroussin 	if (ucl_parser_get_error (parser) != NULL) {
18694f2b741SBaptiste Daroussin 		fprintf (out, "Error occurred (phase 1): %s\n",
18794f2b741SBaptiste Daroussin 						ucl_parser_get_error(parser));
188337c43ffSBaptiste Daroussin 		ret = 1;
189337c43ffSBaptiste Daroussin 		goto end;
190337c43ffSBaptiste Daroussin 	}
1914e2fa78eSBaptiste Daroussin 
192337c43ffSBaptiste Daroussin 	obj = ucl_parser_get_object (parser);
1934e2fa78eSBaptiste Daroussin 
19494f2b741SBaptiste Daroussin 	if (save_comments) {
19594f2b741SBaptiste Daroussin 		comments = ucl_object_ref (ucl_parser_get_comments (parser));
19694f2b741SBaptiste Daroussin 	}
19794f2b741SBaptiste Daroussin 
198337c43ffSBaptiste Daroussin 	if (json) {
199f4dd0993SBaptiste Daroussin 		if (compact) {
200f4dd0993SBaptiste Daroussin 			emitted = ucl_object_emit (obj, UCL_EMIT_JSON_COMPACT);
201f4dd0993SBaptiste Daroussin 		}
202f4dd0993SBaptiste Daroussin 		else {
203337c43ffSBaptiste Daroussin 			emitted = ucl_object_emit (obj, UCL_EMIT_JSON);
204337c43ffSBaptiste Daroussin 		}
205f4dd0993SBaptiste Daroussin 	}
206f4dd0993SBaptiste Daroussin 	else if (yaml) {
207f4dd0993SBaptiste Daroussin 		emitted = ucl_object_emit (obj, UCL_EMIT_YAML);
208f4dd0993SBaptiste Daroussin 	}
209337c43ffSBaptiste Daroussin 	else {
21094f2b741SBaptiste Daroussin 		emitted = NULL;
21194f2b741SBaptiste Daroussin 		func = ucl_object_emit_memory_funcs ((void **)&emitted);
21294f2b741SBaptiste Daroussin 
21394f2b741SBaptiste Daroussin 		if (func != NULL) {
21494f2b741SBaptiste Daroussin 			ucl_object_emit_full (obj, UCL_EMIT_CONFIG, func, comments);
21594f2b741SBaptiste Daroussin 			ucl_object_emit_funcs_free (func);
216337c43ffSBaptiste Daroussin 		}
21794f2b741SBaptiste Daroussin 	}
21894f2b741SBaptiste Daroussin 
21994f2b741SBaptiste Daroussin #if 0
22094f2b741SBaptiste Daroussin 	fprintf (out, "%s\n****\n", emitted);
22194f2b741SBaptiste Daroussin #endif
2224e2fa78eSBaptiste Daroussin 
223337c43ffSBaptiste Daroussin 	ucl_parser_free (parser);
224337c43ffSBaptiste Daroussin 	ucl_object_unref (obj);
22594f2b741SBaptiste Daroussin 	parser2 = ucl_parser_new (flags);
2261eea9004SBaptiste Daroussin 	ucl_parser_add_string (parser2, (const char *)emitted, 0);
227337c43ffSBaptiste Daroussin 
228337c43ffSBaptiste Daroussin 	if (ucl_parser_get_error(parser2) != NULL) {
22994f2b741SBaptiste Daroussin 		fprintf (out, "Error occurred (phase 2): %s\n",
23094f2b741SBaptiste Daroussin 				ucl_parser_get_error(parser2));
231337c43ffSBaptiste Daroussin 		fprintf (out, "%s\n", emitted);
232337c43ffSBaptiste Daroussin 		ret = 1;
233337c43ffSBaptiste Daroussin 		goto end;
234337c43ffSBaptiste Daroussin 	}
2354e2fa78eSBaptiste Daroussin 
236337c43ffSBaptiste Daroussin 	if (emitted != NULL) {
237337c43ffSBaptiste Daroussin 		free (emitted);
238337c43ffSBaptiste Daroussin 	}
23994f2b741SBaptiste Daroussin 	if (comments) {
24094f2b741SBaptiste Daroussin 		ucl_object_unref (comments);
24194f2b741SBaptiste Daroussin 		comments = NULL;
24294f2b741SBaptiste Daroussin 	}
24394f2b741SBaptiste Daroussin 
24494f2b741SBaptiste Daroussin 	if (save_comments) {
24594f2b741SBaptiste Daroussin 		comments = ucl_object_ref (ucl_parser_get_comments (parser2));
24694f2b741SBaptiste Daroussin 	}
2474e2fa78eSBaptiste Daroussin 
248337c43ffSBaptiste Daroussin 	obj = ucl_parser_get_object (parser2);
24994f2b741SBaptiste Daroussin 
25094f2b741SBaptiste Daroussin 	if (!use_fd) {
25194f2b741SBaptiste Daroussin 		func = ucl_object_emit_file_funcs (out);
252f4dd0993SBaptiste Daroussin 	}
253f4dd0993SBaptiste Daroussin 	else {
25494f2b741SBaptiste Daroussin 		func = ucl_object_emit_fd_funcs (fd_out);
25594f2b741SBaptiste Daroussin 	}
25694f2b741SBaptiste Daroussin 
25794f2b741SBaptiste Daroussin 	if (func != NULL) {
25894f2b741SBaptiste Daroussin 		if (json) {
25994f2b741SBaptiste Daroussin 			if (compact) {
26094f2b741SBaptiste Daroussin 				ucl_object_emit_full (obj, UCL_EMIT_JSON_COMPACT,
26194f2b741SBaptiste Daroussin 						func, comments);
26294f2b741SBaptiste Daroussin 			}
26394f2b741SBaptiste Daroussin 			else {
26494f2b741SBaptiste Daroussin 				ucl_object_emit_full (obj, UCL_EMIT_JSON,
26594f2b741SBaptiste Daroussin 						func, comments);
266337c43ffSBaptiste Daroussin 			}
267f4dd0993SBaptiste Daroussin 		}
268f4dd0993SBaptiste Daroussin 		else if (yaml) {
26994f2b741SBaptiste Daroussin 			ucl_object_emit_full (obj, UCL_EMIT_YAML,
27094f2b741SBaptiste Daroussin 					func, comments);
271f4dd0993SBaptiste Daroussin 		}
272337c43ffSBaptiste Daroussin 		else {
27394f2b741SBaptiste Daroussin 			ucl_object_emit_full (obj, UCL_EMIT_CONFIG,
27494f2b741SBaptiste Daroussin 					func, comments);
275337c43ffSBaptiste Daroussin 		}
276337c43ffSBaptiste Daroussin 
27794f2b741SBaptiste Daroussin 		ucl_object_emit_funcs_free (func);
27894f2b741SBaptiste Daroussin 	}
27994f2b741SBaptiste Daroussin 
28094f2b741SBaptiste Daroussin 	if (!use_fd) {
28194f2b741SBaptiste Daroussin 		fprintf (out, "\n");
28294f2b741SBaptiste Daroussin 		fclose (out);
28394f2b741SBaptiste Daroussin 	}
28494f2b741SBaptiste Daroussin 	else {
28594f2b741SBaptiste Daroussin 		write (fd_out, "\n", 1);
28694f2b741SBaptiste Daroussin 		close (fd_out);
28794f2b741SBaptiste Daroussin 	}
28894f2b741SBaptiste Daroussin 
289337c43ffSBaptiste Daroussin 	ucl_object_unref (obj);
290337c43ffSBaptiste Daroussin 
291337c43ffSBaptiste Daroussin end:
292337c43ffSBaptiste Daroussin 	if (parser2 != NULL) {
293337c43ffSBaptiste Daroussin 		ucl_parser_free (parser2);
294337c43ffSBaptiste Daroussin 	}
29594f2b741SBaptiste Daroussin 	if (comments) {
29694f2b741SBaptiste Daroussin 		ucl_object_unref (comments);
29794f2b741SBaptiste Daroussin 	}
2984e2fa78eSBaptiste Daroussin 	if (inbuf != NULL) {
2994e2fa78eSBaptiste Daroussin 		free (inbuf);
300337c43ffSBaptiste Daroussin 	}
301337c43ffSBaptiste Daroussin 
302337c43ffSBaptiste Daroussin 	return ret;
303337c43ffSBaptiste Daroussin }
304