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