/ external / libucl / utils / ucl-tool.c
ucl-tool.c
  1  /* Copyright (c) 2015, Cesanta Software
  2   *
  3   * Redistribution and use in source and binary forms, with or without
  4   * modification, are permitted provided that the following conditions are met:
  5   *       * Redistributions of source code must retain the above copyright
  6   *         notice, this list of conditions and the following disclaimer.
  7   *       * Redistributions in binary form must reproduce the above copyright
  8   *         notice, this list of conditions and the following disclaimer in the
  9   *         documentation and/or other materials provided with the distribution.
 10   *
 11   * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
 12   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 13   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 14   * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
 15   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 16   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 17   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 18   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 19   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 20   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 21   */
 22  
 23  #include "ucl.h"
 24  
 25  void usage(const char *name, FILE *out) {
 26    fprintf(out, "Usage: %s [--help] [-i|--in file] [-o|--out file]\n", name);
 27    fprintf(out, "    [-s|--schema file] [-f|--format format]\n\n");
 28    fprintf(out, "  --help   - print this message and exit\n");
 29    fprintf(out, "  --in     - specify input filename "
 30            "(default: standard input)\n");
 31    fprintf(out, "  --out    - specify output filename "
 32            "(default: standard output)\n");
 33    fprintf(out, "  --schema - specify schema file for validation\n");
 34    fprintf(out, "  --format - output format. Options: ucl (default), "
 35            "json, compact_json, yaml, msgpack\n");
 36  }
 37  
 38  int main(int argc, char **argv) {
 39    int i;
 40    char ch;
 41    FILE *in = stdin, *out = stdout;
 42    const char *schema = NULL, *parm, *val;
 43    unsigned char *buf = NULL;
 44    size_t size = 0, r = 0;
 45    struct ucl_parser *parser = NULL;
 46    ucl_object_t *obj = NULL;
 47    ucl_emitter_t emitter = UCL_EMIT_CONFIG;
 48  
 49    for (i = 1; i < argc; ++i) {
 50      parm = argv[i];
 51      val = ((i + 1) < argc) ? argv[++i] : NULL;
 52  
 53      if ((strcmp(parm, "--help") == 0) || (strcmp(parm, "-h") == 0)) {
 54        usage(argv[0], stdout);
 55        exit(0);
 56  
 57      } else if ((strcmp(parm, "--in") == 0) || (strcmp(parm, "-i") == 0)) {
 58        if (!val)
 59          goto err_val;
 60  
 61        in = fopen(val, "r");
 62        if (in == NULL) {
 63          perror("fopen on input file");
 64          exit(EXIT_FAILURE);
 65        }
 66      } else if ((strcmp(parm, "--out") == 0) || (strcmp(parm, "-o") == 0)) {
 67        if (!val)
 68          goto err_val;
 69  
 70        out = fopen(val, "w");
 71        if (out == NULL) {
 72          perror("fopen on output file");
 73          exit(EXIT_FAILURE);
 74        }
 75      } else if ((strcmp(parm, "--schema") == 0) || (strcmp(parm, "-s") == 0)) {
 76        if (!val)
 77          goto err_val;
 78        schema = val;
 79  
 80      } else if ((strcmp(parm, "--format") == 0) || (strcmp(parm, "-f") == 0)) {
 81          if (!val)
 82            goto err_val;
 83  
 84          if (strcmp(val, "ucl") == 0) {
 85            emitter = UCL_EMIT_CONFIG;
 86          } else if (strcmp(val, "json") == 0) {
 87            emitter = UCL_EMIT_JSON;
 88          } else if (strcmp(val, "yaml") == 0) {
 89            emitter = UCL_EMIT_YAML;
 90          } else if (strcmp(val, "compact_json") == 0) {
 91            emitter = UCL_EMIT_JSON_COMPACT;
 92          } else if (strcmp(val, "msgpack") == 0) {
 93            emitter = UCL_EMIT_MSGPACK;
 94          } else {
 95            fprintf(stderr, "Unknown output format: %s\n", val);
 96            exit(EXIT_FAILURE);
 97          }
 98      } else {
 99        usage(argv[0], stderr);
100        exit(EXIT_FAILURE);
101      }
102    }
103  
104    parser = ucl_parser_new(0);
105    buf = malloc(BUFSIZ);
106    size = BUFSIZ;
107    while (!feof(in) && !ferror(in)) {
108      if (r == size) {
109        buf = realloc(buf, size*2);
110        size *= 2;
111        if (buf == NULL) {
112          perror("realloc");
113          exit(EXIT_FAILURE);
114        }
115      }
116      r += fread(buf + r, 1, size - r, in);
117    }
118    if (ferror(in)) {
119      fprintf(stderr, "Failed to read the input file.\n");
120      exit(EXIT_FAILURE);
121    }
122    fclose(in);
123    if (!ucl_parser_add_chunk(parser, buf, r)) {
124      fprintf(stderr, "Failed to parse input file: %s\n",
125              ucl_parser_get_error(parser));
126      exit(EXIT_FAILURE);
127    }
128    if ((obj = ucl_parser_get_object(parser)) == NULL) {
129      fprintf(stderr, "Failed to get root object: %s\n",
130              ucl_parser_get_error(parser));
131      exit(EXIT_FAILURE);
132    }
133    if (schema != NULL) {
134      struct ucl_parser *schema_parser = ucl_parser_new(0);
135      ucl_object_t *schema_obj = NULL;
136      struct ucl_schema_error error;
137  
138      if (!ucl_parser_add_file(schema_parser, schema)) {
139        fprintf(stderr, "Failed to parse schema file: %s\n",
140                ucl_parser_get_error(schema_parser));
141        exit(EXIT_FAILURE);
142      }
143      if ((schema_obj = ucl_parser_get_object(schema_parser)) == NULL) {
144        fprintf(stderr, "Failed to get root object: %s\n",
145                ucl_parser_get_error(schema_parser));
146        exit(EXIT_FAILURE);
147      }
148      if (!ucl_object_validate(schema_obj, obj, &error)) {
149        fprintf(stderr, "Validation failed: %s\n", error.msg);
150        exit(EXIT_FAILURE);
151      }
152    }
153  
154    if (emitter != UCL_EMIT_MSGPACK) {
155      fprintf(out, "%s\n", ucl_object_emit(obj, emitter));
156    } else {
157      size_t len;
158      unsigned char *res;
159  
160      res = ucl_object_emit_len(obj, emitter, &len);
161      fwrite(res, 1, len, out);
162    }
163  
164    return 0;
165  
166  err_val:
167      fprintf(stderr, "Parameter %s is missing mandatory value\n", parm);
168      usage(argv[0], stderr);
169      exit(EXIT_FAILURE);
170  }