1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <unistd.h>
#include <stdarg.h>
#include <t3config/config.h>
#define STRING_DFLT(x, dflt) ((x) != NULL ? (x) : (dflt))
static t3_config_t *config;
static t3_config_schema_t *schema;
/* Alert the user of a fatal error and quit. */
static void fatal(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(EXIT_FAILURE);
}
/* Cleanup memory used by config and schema. */
static void cleanup(void) {
/* Both t3_config_delete and t3_config_delete_schema allow NULL pointers to be passed. */
t3_config_delete(config);
t3_config_delete_schema(schema);
}
int main(int argc, char *argv[]) {
t3_config_error_t error;
FILE *file = stdin;
t3_config_opts_t opts;
t3_config_t *foo;
const char *path[2] = { NULL, NULL };
const char *name = "<stdin>";
int c;
/* Set locale */
setlocale(LC_ALL, "");
/* Request as much information about errors as possible. */
opts.flags = T3_CONFIG_VERBOSE_ERROR | T3_CONFIG_ERROR_FILE_NAME;
/* Make sure we free memory on exit (useful for debugging purposes). */
atexit(cleanup);
while ((c = getopt(argc, argv, "s:hi::")) >= 0) {
switch (c) {
case 's': {
/* Load a schema. */
FILE *schema_file;
if (schema != NULL)
fatal("more than one schema option\n");
if ((schema_file = fopen(optarg, "r")) == NULL)
fatal("error opening schema '%s': %m\n", optarg);
if ((schema = t3_config_read_schema_file(schema_file, &error, &opts)) == NULL)
fatal("%s:%d: error loading schema '%s': %s: %s\n", STRING_DFLT(error.file_name, optarg),
error.line_number, optarg, t3_config_strerror(error.error), STRING_DFLT(error.extra, ""));
fclose(schema_file);
break;
}
case 'h':
printf("Usage: test [-s <schema>] [-i[<include dir>]] [<input>]\n");
exit(EXIT_SUCCESS);
case 'i':
/* Configure the options for allowing the include mechanism. */
opts.flags |= T3_CONFIG_INCLUDE_DFLT;
path[0] = optarg == 0 ? "." : optarg;
opts.include_callback.dflt.path = path;
opts.include_callback.dflt.flags = 0;
break;
default:
break;
}
}
/* Open the input file if necessary. */
if (argc - optind == 1) {
if ((file = fopen(argv[optind], "r")) == NULL)
fatal("could not open input '%s': %m\n");
name = argv[optind];
} else if (argc != optind) {
fatal("more than one input specified\n");
}
/* Read the configuration. */
if ((config = t3_config_read_file(file, &error, &opts)) == NULL)
fatal("%s:%d: error loading input: %s: %s\n", STRING_DFLT(error.file_name, name), error.line_number,
t3_config_strerror(error.error), STRING_DFLT(error.extra, ""));
/* Close the file now that we are done with it. */
fclose(file);
/* Use the schema (if any) to validate the input. */
if (schema != NULL && !t3_config_validate(config, schema, &error, T3_CONFIG_VERBOSE_ERROR | T3_CONFIG_ERROR_FILE_NAME))
fatal("%s:%d: error validating input: %s: %s\n", STRING_DFLT(error.file_name, name), error.line_number,
t3_config_strerror(error.error), STRING_DFLT(error.extra, ""));
/* Retrieve the section named "foo". */
foo = t3_config_get(config, "foo");
if (foo != NULL) {
/* Retrieve the integer "bar", with default value of 0. This verifies
that bar has type int, which can already be checked through the schema. */
int bar_int = -1;
t3_config_t *bar = t3_config_get(foo, "bar");
if (t3_config_get_type(bar), T3_CONFIG_INT) {
bar_int = t3_config_get_int(bar);
}
}
/* Add a boolean value named "xxx" with value true. */
t3_config_add_bool(config, "xxx", t3_true);
/* Write the input to screen for checking the result. */
t3_config_write_file(config, stdout);
return EXIT_SUCCESS;
}
|