/* * 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 #include #include #include #include "sm-conf.h" #else /* SM_LIBCONF_ALONE */ #include "sm/string.h" #include "sm/sm-conf.h" #include "sm/net.h" #include #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("\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; }