/*
* Copyright (c) 2004 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: demo-union.c,v 1.4 2005/09/26 23:26:41 ca Exp $")
#if SM_LIBCONF_ALONE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include "sm-conf.h"
#else /* SM_LIBCONF_ALONE */
#include "sm/string.h"
#include "sm/sm-conf.h"
#include "sm/net.h"
#include <stdio.h>
#endif /* SM_LIBCONF_ALONE */
/* DEMO-UNION.C -- demo of unions. */
#ifndef offsetof
#define offsetof(type, member) ((char *)&((type *)0)->member - (char *)0)
#endif
typedef union vehicle_U
{
enum vehicle_type
{
AIRPLANE = 1,
BOAT = 2,
CAR = 3
} type;
struct
{
enum vehicle_type air_type;
char *air_flight;
int air_passengers;
} airplane;
struct
{
enum vehicle_type boat_type;
int boat_knots;
char *boat_name;
} boat;
struct
{
enum vehicle_type 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 }
};
/*
** Vehicles are distinguished by section label.
*/
static sm_conf_definition_T
vehicle_red_definitions[] =
{
{ SM_CONF_DEF_MAGIC,
"",
sm_conf_type_union_type,
offsetof(vehicle_T, type),
sizeof(enum vehicle_type)
},
{ SM_CONF_DEF_MAGIC,
"",
sm_conf_type_union_choice,
AIRPLANE,
sizeof(vehicle_T), "airplane", 0,
air_definitions
},
{ SM_CONF_DEF_MAGIC,
"",
sm_conf_type_union_choice,
BOAT,
sizeof(vehicle_T), "boat", 0,
boat_definitions
},
{ SM_CONF_DEF_MAGIC,
"",
sm_conf_type_union_choice,
CAR,
sizeof(vehicle_T), "car", 0,
car_definitions
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
#if 0
static sm_conf_definition_T
vehicle_definitions[] =
{
{ SM_CONF_DEF_MAGIC,
"airplane",
sm_conf_type_union_choice,
AIRPLANE,
sizeof(vehicle_T), NULL, 0,
air_definitions
},
{ SM_CONF_DEF_MAGIC,
"boat",
sm_conf_type_union_choice,
BOAT,
sizeof(vehicle_T), NULL, 0,
boat_definitions
},
{ SM_CONF_DEF_MAGIC,
"car",
sm_conf_type_union_choice,
CAR,
sizeof(vehicle_T), NULL, 0,
car_definitions
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
#endif /* 0 */
typedef struct
{
vehicle_T red;
} structure;
static sm_conf_definition_T const
definitions[] =
{
{ SM_CONF_DEF_MAGIC, "red",
sm_conf_type_union,
offsetof(structure, red),
sizeof(vehicle_T),
NULL,
0,
vehicle_red_definitions,
NULL, NULL,
"A red vehicle."
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static void
print_vehicle(vehicle_T const *v)
{
switch (v->type)
{
case AIRPLANE:
printf("airplane { flight=%s passengers=%d }\n",
v->airplane.air_flight == NULL
? "(null)" : v->airplane.air_flight,
v->airplane.air_passengers);
break;
case BOAT:
printf("boat { knots=%d name=%s }\n",
v->boat.boat_knots,
v->boat.boat_name == NULL
? "(null)" : v->boat.boat_name);
break;
case CAR:
printf("car { mpg=%d plate=%s }\n",
v->car.car_mpg,
v->car.car_plate == NULL ? "(null)" : v->car.car_plate);
break;
default:
printf("<unexpected type %d>\n", (int)v->type);
break;
}
}
static void
print_structure(structure *s)
{
print_vehicle(&s->red);
}
static int
process(char const *name, FILE *fp)
{
sm_conf_T *stream;
int err;
structure s;
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)
{
char buf[SM_CONF_ERROR_BUFFER_SIZE];
char const *e = NULL;
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;
}
memset(&s, 0, sizeof(s));
err = sm_conf_scan(stream, definitions, 0, &s);
if (err != 0)
{
char buf[SM_CONF_ERROR_BUFFER_SIZE];
char const *e = NULL;
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_structure(&s);
sm_conf_destroy(stream);
return 0;
}
int
main(int ac, char **av)
{
int ai;
if (ac == 1)
return process("*stdin*", stdin);
for (ai = 1; ai < ac; ai++)
{
int ret = process(av[ai], NULL);
if (ret != 0)
return ret;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1