1262395Sbapt/* Copyright (c) 2013, Vsevolod Stakhov 2262395Sbapt * All rights reserved. 3262395Sbapt * 4262395Sbapt * Redistribution and use in source and binary forms, with or without 5262395Sbapt * modification, are permitted provided that the following conditions are met: 6262395Sbapt * * Redistributions of source code must retain the above copyright 7262395Sbapt * notice, this list of conditions and the following disclaimer. 8262395Sbapt * * Redistributions in binary form must reproduce the above copyright 9262395Sbapt * notice, this list of conditions and the following disclaimer in the 10262395Sbapt * documentation and/or other materials provided with the distribution. 11262395Sbapt * 12262395Sbapt * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13262395Sbapt * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14262395Sbapt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15262395Sbapt * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16262395Sbapt * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17262395Sbapt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18262395Sbapt * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19262395Sbapt * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20262395Sbapt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21262395Sbapt * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22262395Sbapt */ 23262395Sbapt 24262395Sbapt#include "ucl.h" 25263648Sbapt#include "ucl_internal.h" 26298166Sbapt#include <sys/types.h> 27298166Sbapt#include <fcntl.h> 28298166Sbapt#include <unistd.h> 29262395Sbapt 30298166Sbapt 31262395Sbaptint 32262395Sbaptmain (int argc, char **argv) 33262395Sbapt{ 34298166Sbapt char *inbuf = NULL; 35262395Sbapt struct ucl_parser *parser = NULL, *parser2 = NULL; 36298166Sbapt ucl_object_t *obj, *comments = NULL; 37290071Sbapt ssize_t bufsize, r; 38262395Sbapt FILE *in, *out; 39262395Sbapt unsigned char *emitted = NULL; 40262395Sbapt const char *fname_in = NULL, *fname_out = NULL; 41298166Sbapt int ret = 0, opt, json = 0, compact = 0, yaml = 0, 42298166Sbapt save_comments = 0, skip_macro = 0, 43298166Sbapt flags, fd_out, fd_in, use_fd = 0; 44298166Sbapt struct ucl_emitter_functions *func; 45262395Sbapt 46298166Sbapt while ((opt = getopt(argc, argv, "fjcyCM")) != -1) { 47262395Sbapt switch (opt) { 48262395Sbapt case 'j': 49262395Sbapt json = 1; 50262395Sbapt break; 51268831Sbapt case 'c': 52268831Sbapt compact = 1; 53268831Sbapt break; 54298166Sbapt case 'C': 55298166Sbapt save_comments = 1; 56298166Sbapt break; 57268831Sbapt case 'y': 58268831Sbapt yaml = 1; 59268831Sbapt break; 60298166Sbapt case 'M': 61298166Sbapt skip_macro = true; 62298166Sbapt break; 63298166Sbapt case 'f': 64298166Sbapt use_fd = true; 65298166Sbapt break; 66262395Sbapt default: /* '?' */ 67298166Sbapt fprintf (stderr, "Usage: %s [-jcy] [-CM] [-f] [in] [out]\n", 68262395Sbapt argv[0]); 69262395Sbapt exit (EXIT_FAILURE); 70262395Sbapt } 71262395Sbapt } 72262395Sbapt 73262395Sbapt argc -= optind; 74262395Sbapt argv += optind; 75262395Sbapt 76262395Sbapt switch (argc) { 77262395Sbapt case 1: 78262395Sbapt fname_in = argv[0]; 79262395Sbapt break; 80262395Sbapt case 2: 81262395Sbapt fname_in = argv[0]; 82262395Sbapt fname_out = argv[1]; 83262395Sbapt break; 84262395Sbapt } 85262395Sbapt 86298166Sbapt if (!use_fd) { 87298166Sbapt if (fname_in != NULL) { 88298166Sbapt in = fopen (fname_in, "r"); 89298166Sbapt if (in == NULL) { 90298166Sbapt exit (-errno); 91298166Sbapt } 92262395Sbapt } 93298166Sbapt else { 94298166Sbapt in = stdin; 95298166Sbapt } 96262395Sbapt } 97262395Sbapt else { 98298166Sbapt if (fname_in != NULL) { 99298166Sbapt fd_in = open (fname_in, O_RDONLY); 100298166Sbapt if (fd_in == -1) { 101298166Sbapt exit (-errno); 102298166Sbapt } 103298166Sbapt } 104298166Sbapt else { 105298166Sbapt fd_in = STDIN_FILENO; 106298166Sbapt } 107262395Sbapt } 108298166Sbapt 109298166Sbapt flags = UCL_PARSER_KEY_LOWERCASE; 110298166Sbapt 111298166Sbapt if (save_comments) { 112298166Sbapt flags |= UCL_PARSER_SAVE_COMMENTS; 113298166Sbapt } 114298166Sbapt 115298166Sbapt if (skip_macro) { 116298166Sbapt flags |= UCL_PARSER_DISABLE_MACRO; 117298166Sbapt } 118298166Sbapt 119298166Sbapt parser = ucl_parser_new (flags); 120262395Sbapt ucl_parser_register_variable (parser, "ABI", "unknown"); 121262395Sbapt 122262395Sbapt if (fname_in != NULL) { 123262395Sbapt ucl_parser_set_filevars (parser, fname_in, true); 124262395Sbapt } 125262395Sbapt 126298166Sbapt if (!use_fd) { 127298166Sbapt inbuf = malloc (BUFSIZ); 128298166Sbapt bufsize = BUFSIZ; 129298166Sbapt r = 0; 130290071Sbapt 131298166Sbapt while (!feof (in) && !ferror (in)) { 132298166Sbapt if (r == bufsize) { 133298166Sbapt inbuf = realloc (inbuf, bufsize * 2); 134298166Sbapt bufsize *= 2; 135298166Sbapt if (inbuf == NULL) { 136298166Sbapt perror ("realloc"); 137298166Sbapt exit (EXIT_FAILURE); 138298166Sbapt } 139290071Sbapt } 140298166Sbapt r += fread (inbuf + r, 1, bufsize - r, in); 141264789Sbapt } 142290071Sbapt 143298166Sbapt if (ferror (in)) { 144298166Sbapt fprintf (stderr, "Failed to read the input file.\n"); 145298166Sbapt exit (EXIT_FAILURE); 146298166Sbapt } 147298166Sbapt 148298166Sbapt ucl_parser_add_chunk (parser, (const unsigned char *)inbuf, r); 149298166Sbapt fclose (in); 150290071Sbapt } 151298166Sbapt else { 152298166Sbapt ucl_parser_add_fd (parser, fd_in); 153298166Sbapt close (fd_in); 154298166Sbapt } 155290071Sbapt 156298166Sbapt if (!use_fd) { 157298166Sbapt if (fname_out != NULL) { 158298166Sbapt out = fopen (fname_out, "w"); 159298166Sbapt if (out == NULL) { 160298166Sbapt exit (-errno); 161298166Sbapt } 162262395Sbapt } 163298166Sbapt else { 164298166Sbapt out = stdout; 165298166Sbapt } 166262395Sbapt } 167262395Sbapt else { 168298166Sbapt if (fname_out != NULL) { 169298166Sbapt fd_out = open (fname_out, O_WRONLY | O_CREAT, 00644); 170298166Sbapt if (fd_out == -1) { 171298166Sbapt exit (-errno); 172298166Sbapt } 173298166Sbapt } 174298166Sbapt else { 175298166Sbapt fd_out = STDOUT_FILENO; 176298166Sbapt } 177262395Sbapt } 178290071Sbapt 179298166Sbapt 180263648Sbapt if (ucl_parser_get_error (parser) != NULL) { 181298166Sbapt fprintf (out, "Error occurred (phase 1): %s\n", 182298166Sbapt ucl_parser_get_error(parser)); 183262395Sbapt ret = 1; 184262395Sbapt goto end; 185262395Sbapt } 186290071Sbapt 187262395Sbapt obj = ucl_parser_get_object (parser); 188290071Sbapt 189298166Sbapt if (save_comments) { 190298166Sbapt comments = ucl_object_ref (ucl_parser_get_comments (parser)); 191298166Sbapt } 192298166Sbapt 193262395Sbapt if (json) { 194268831Sbapt if (compact) { 195268831Sbapt emitted = ucl_object_emit (obj, UCL_EMIT_JSON_COMPACT); 196268831Sbapt } 197268831Sbapt else { 198268831Sbapt emitted = ucl_object_emit (obj, UCL_EMIT_JSON); 199268831Sbapt } 200262395Sbapt } 201268831Sbapt else if (yaml) { 202268831Sbapt emitted = ucl_object_emit (obj, UCL_EMIT_YAML); 203268831Sbapt } 204262395Sbapt else { 205298166Sbapt emitted = NULL; 206298166Sbapt func = ucl_object_emit_memory_funcs ((void **)&emitted); 207298166Sbapt 208298166Sbapt if (func != NULL) { 209298166Sbapt ucl_object_emit_full (obj, UCL_EMIT_CONFIG, func, comments); 210298166Sbapt ucl_object_emit_funcs_free (func); 211298166Sbapt } 212262395Sbapt } 213290071Sbapt 214298166Sbapt#if 0 215298166Sbapt fprintf (out, "%s\n****\n", emitted); 216298166Sbapt#endif 217298166Sbapt 218262395Sbapt ucl_parser_free (parser); 219262395Sbapt ucl_object_unref (obj); 220298166Sbapt parser2 = ucl_parser_new (flags); 221275223Sbapt ucl_parser_add_string (parser2, (const char *)emitted, 0); 222262395Sbapt 223262395Sbapt if (ucl_parser_get_error(parser2) != NULL) { 224298166Sbapt fprintf (out, "Error occurred (phase 2): %s\n", 225298166Sbapt ucl_parser_get_error(parser2)); 226262395Sbapt fprintf (out, "%s\n", emitted); 227262395Sbapt ret = 1; 228262395Sbapt goto end; 229262395Sbapt } 230290071Sbapt 231262395Sbapt if (emitted != NULL) { 232262395Sbapt free (emitted); 233262395Sbapt } 234298166Sbapt if (comments) { 235298166Sbapt ucl_object_unref (comments); 236298166Sbapt comments = NULL; 237298166Sbapt } 238290071Sbapt 239298166Sbapt if (save_comments) { 240298166Sbapt comments = ucl_object_ref (ucl_parser_get_comments (parser2)); 241298166Sbapt } 242298166Sbapt 243262395Sbapt obj = ucl_parser_get_object (parser2); 244298166Sbapt 245298166Sbapt if (!use_fd) { 246298166Sbapt func = ucl_object_emit_file_funcs (out); 247298166Sbapt } 248298166Sbapt else { 249298166Sbapt func = ucl_object_emit_fd_funcs (fd_out); 250298166Sbapt } 251298166Sbapt 252298166Sbapt if (func != NULL) { 253298166Sbapt if (json) { 254298166Sbapt if (compact) { 255298166Sbapt ucl_object_emit_full (obj, UCL_EMIT_JSON_COMPACT, 256298166Sbapt func, comments); 257298166Sbapt } 258298166Sbapt else { 259298166Sbapt ucl_object_emit_full (obj, UCL_EMIT_JSON, 260298166Sbapt func, comments); 261298166Sbapt } 262268831Sbapt } 263298166Sbapt else if (yaml) { 264298166Sbapt ucl_object_emit_full (obj, UCL_EMIT_YAML, 265298166Sbapt func, comments); 266298166Sbapt } 267268831Sbapt else { 268298166Sbapt ucl_object_emit_full (obj, UCL_EMIT_CONFIG, 269298166Sbapt func, comments); 270268831Sbapt } 271298166Sbapt 272298166Sbapt ucl_object_emit_funcs_free (func); 273262395Sbapt } 274298166Sbapt 275298166Sbapt if (!use_fd) { 276298166Sbapt fprintf (out, "\n"); 277298166Sbapt fclose (out); 278268831Sbapt } 279262395Sbapt else { 280298166Sbapt write (fd_out, "\n", 1); 281298166Sbapt close (fd_out); 282262395Sbapt } 283262395Sbapt 284262395Sbapt ucl_object_unref (obj); 285262395Sbapt 286262395Sbaptend: 287262395Sbapt if (parser2 != NULL) { 288262395Sbapt ucl_parser_free (parser2); 289262395Sbapt } 290298166Sbapt if (comments) { 291298166Sbapt ucl_object_unref (comments); 292298166Sbapt } 293290071Sbapt if (inbuf != NULL) { 294290071Sbapt free (inbuf); 295262395Sbapt } 296262395Sbapt 297262395Sbapt return ret; 298262395Sbapt} 299