/*
* Copyright (c) 2005 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: t-conf-6.c,v 1.2 2006/12/24 00:20:24 ca Exp $")
#if SM_LIBCONF_ALONE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sm-conf.h"
#else /* SM_LIBCONF_ALONE */
#include "sm/string.h"
#include "sm/net.h"
#include "sm/sm-conf.h"
#include <stdio.h>
#endif /* SM_LIBCONF_ALONE */
/*
** Just a test program to play around with libconf.
** union_choice
** distinguish union types by a unique element in each part
*/
enum vehicle_type_E
{
AIRPLANE = 1,
BOAT = 2,
CAR = 3
};
typedef enum vehicle_type_E vehicle_type_T;
typedef union vehicle_U
{
vehicle_type_T vehicle_type;
struct
{
vehicle_type_T air_type;
char *air_flight;
int air_passengers;
} airplane;
struct
{
vehicle_type_T boat_type;
int boat_knots;
char *boat_name;
} boat;
struct
{
vehicle_type_T car_type;
int car_mpg;
char *car_plate;
} car;
} vehicle_T;
static sm_conf_definition_T const
air_definitions[] =
{
{ SM_CONF_DEF_MAGIC, "flight", sm_conf_type_string,
offsetof(vehicle_T, airplane.air_flight), 0, NULL
},
{ SM_CONF_DEF_MAGIC, "passengers", sm_conf_type_u32,
offsetof(vehicle_T, airplane.air_passengers),
sizeof(unsigned int), "1"
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T const
boat_definitions[] =
{
{ SM_CONF_DEF_MAGIC, "name", sm_conf_type_string,
offsetof(vehicle_T, boat.boat_name), 0, NULL
},
{ SM_CONF_DEF_MAGIC, "knots", sm_conf_type_u32,
offsetof(vehicle_T, boat.boat_knots),
sizeof(unsigned int), NULL
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T const
car_definitions[] =
{
{ SM_CONF_DEF_MAGIC, "plate", sm_conf_type_string,
offsetof(vehicle_T, car.car_plate), 0, NULL
},
{ SM_CONF_DEF_MAGIC, "mpg", sm_conf_type_u32,
offsetof(vehicle_T, car.car_mpg),
sizeof(unsigned int), NULL
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
sm_conf_definition_T vehicle_definitions[] = {
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_union_type,
offsetof(vehicle_T, vehicle_type),
sizeof(vehicle_type_T)
},
{ SM_CONF_DEF_MAGIC, "flight", sm_conf_type_union_choice, AIRPLANE,
sizeof(vehicle_T), /* default */ NULL, /* flags */ 0,
air_definitions
},
{ SM_CONF_DEF_MAGIC, "name", sm_conf_type_union_choice, BOAT,
sizeof(vehicle_T), /* default */ NULL, /* flags */ 0,
boat_definitions
},
{ SM_CONF_DEF_MAGIC, "plate", sm_conf_type_union_choice, CAR,
sizeof(vehicle_T), /* default */ NULL, /* flags */ 0,
car_definitions
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
typedef struct
{
vehicle_T s_garage;
} mts_T;
sm_conf_definition_T
mts_def[] =
{
{ SM_CONF_DEF_MAGIC, "vehicle", sm_conf_type_union,
offsetof(mts_T, s_garage.vehicle_type),
sizeof(vehicle_type_T),
NULL, 0, vehicle_definitions
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static mts_T mts;
static void
print_mts(mts_T *st)
{
switch (st->s_garage.vehicle_type)
{
case AIRPLANE:
printf("airplane=\"%s\"\n",
st->s_garage.airplane.air_flight);
break;
case BOAT:
printf("boat=\"%s\"\n",
st->s_garage.boat.boat_name);
break;
case CAR:
printf("car=\"%s\"\n",
st->s_garage.car.car_plate);
break;
default:
break;
}
}
static int
process(char const *name, FILE *fp, const char *ssname)
{
sm_conf_T *stream;
int err;
char buf[SM_CONF_ERROR_BUFFER_SIZE];
char const *e = NULL;
if (((stream = sm_conf_new(name ? name : "*stdin*"))) == NULL)
{
fprintf(stderr, "error -- sm_conf_new() returns NULL!\n");
return 1;
}
if ((err = sm_conf_read_FILE(stream, name, fp)) != 0)
{
fprintf(stderr, "%s: %s\n",
name ? name : "*stdin*",
sm_conf_strerror(err, buf, sizeof buf));
while ((e = sm_conf_syntax_error(stream, e)) != NULL)
fprintf(stderr, "%s\n", e);
sm_conf_destroy(stream);
return 2;
}
if ((err = sm_conf_scan(stream, mts_def, 0, &mts)) != 0)
{
fprintf(stderr, "(while scanning) %s: %s\n",
name ? name : "*stdin*",
sm_conf_strerror(err, buf, sizeof buf));
while ((e = sm_conf_syntax_error(stream, e)) != NULL)
fprintf(stderr, "%s\n", e);
sm_conf_destroy(stream);
return 3;
}
print_mts(&mts);
#if 0
sm_conf_destroy(stream);
#endif /* 0 */
return 0;
}
int
main(int ac, char **av)
{
int ai, c, ret, done;
char *ssname;
done = 0;
ssname = NULL;
while ((c = getopt(ac, av, "f:N:o:v:")) != -1)
{
switch (c)
{
case 'f':
ret = process(optarg, NULL, ssname);
if (ret != 0)
return ret;
done = 1;
break;
case 'N':
ssname = strdup(optarg);
if (ssname == NULL)
return ENOMEM;
break;
}
}
ac -= optind;
av += optind;
if (done)
{
print_mts(&mts);
return 0;
}
if (ac == 0)
return process("*stdin*", stdin, ssname);
for (ai = 0; ai < ac; ai++)
{
int ret = process(av[ai], NULL, ssname);
if (ret != 0)
return ret;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1