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