/*
* Copyright (c) 2004, 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: demo-array.c,v 1.3 2005/12/26 04:45:09 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 "sm/io.h"
#include "sm/sm-conf-prt.h"
#include <stdio.h>
#endif /* SM_LIBCONF_ALONE */
/* DEMO-ARRAY.C -- demo of arrays and arrays of unions. */
#ifndef offsetof
#define offsetof(type, member) ((char *)&((type *)0)->member - (char *)0)
#endif
static int Verbose = 0;
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 }
};
static sm_conf_definition_T
vehicle_definitions[] =
{
{ SM_CONF_DEF_MAGIC,
"",
sm_conf_type_union_type,
offsetof(vehicle_T, type),
sizeof(enum vehicle_type),
NULL,
0,
NULL
},
{ SM_CONF_DEF_MAGIC,
"",
sm_conf_type_union_choice,
/* offset = type tag */ AIRPLANE,
sizeof(vehicle_T), "airplane", 0,
air_definitions
},
{ SM_CONF_DEF_MAGIC,
"",
sm_conf_type_union_choice,
/* offset = type tag */ BOAT,
sizeof(vehicle_T), "boat", 0,
boat_definitions
},
{ SM_CONF_DEF_MAGIC,
"",
sm_conf_type_union_choice,
/* offset = type tag */ CAR,
sizeof(vehicle_T), "car", 0,
car_definitions
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
typedef struct
{
char *flavor;
char *color;
} icecream_T;
static sm_conf_definition_T
icecream_definitions[] =
{
{ SM_CONF_DEF_MAGIC,
/* name */ "color",
/* type */ sm_conf_type_string,
/* off */ offsetof(icecream_T, color),
/* size */ 0,
/* dflt */ NULL,
/* flag */ SM_CONF_FLAG_STRICTLY_REQUIRED,
/* cont */ NULL,
/* chkf */ NULL,
/* chkd */ NULL,
/* desc */ "ice cream color"
},
{ SM_CONF_DEF_MAGIC,
/* name */ "flavor",
/* type */ sm_conf_type_string,
/* off */ offsetof(icecream_T, flavor),
/* size */ 0,
/* dflt */ NULL,
/* flag */ SM_CONF_FLAG_STRICTLY_REQUIRED,
/* cont */ 0,
/* chkf */ NULL,
/* chkd */ NULL,
/* desc */ "ice cream flavor"
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
typedef struct
{
char name[20];
int price;
} candy_T;
static sm_conf_definition_T
candy_definitions[] =
{
{ SM_CONF_DEF_MAGIC,
/* name */ "name",
/* type */ sm_conf_type_string,
/* off */ offsetof(candy_T, name),
/* size */ 20,
/* dflt */ NULL,
/* flag */ SM_CONF_FLAG_STRICTLY_REQUIRED
| SM_CONF_FLAG_FLAT,
/* cont */ NULL,
/* chkf */ NULL,
/* chkd */ NULL,
/* desc */ "name of candy"
},
{ SM_CONF_DEF_MAGIC,
/* name */ "price",
/* type */ sm_conf_type_u32,
/* off */ offsetof(candy_T, price),
/* size */ sizeof(int),
/* dflt */ NULL,
/* flag */ SM_CONF_FLAG_STRICTLY_REQUIRED,
/* cont */ 0,
/* chkf */ NULL,
/* chkd */ NULL,
/* desc */ "price of candy"
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
typedef struct
{
long *fib;
unsigned int fib_n;
char pi[13];
unsigned int pi_n;
icecream_T *icecream;
unsigned int icecream_n;
candy_T candy[4];
unsigned int candy_n;
vehicle_T garage[2];
unsigned int garage_n;
vehicle_T *fleet;
unsigned int fleet_n;
} structure;
/*
** GARAGE_DEFINITIONS -- a two-element fixed array
*/
static sm_conf_definition_T
garage_definitions[] =
{
{
SM_CONF_DEF_MAGIC,
"vehicle",
sm_conf_type_union,
offsetof(structure, garage),
/* size = max # of elements */ 2,
NULL,
0,
vehicle_definitions,
NULL,
NULL,
"vehicle parked in a garage"
},
{
SM_CONF_DEF_MAGIC,
"",
sm_conf_type_array_n,
offsetof(structure, garage_n),
sizeof(unsigned int),
NULL,
/* flags */ 0,
NULL,
NULL,
NULL,
"number of vehicles parked in the garge"
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T
garage_outer_definitions[] =
{
{
SM_CONF_DEF_MAGIC,
"vehicle",
sm_conf_type_array,
0,
sizeof(vehicle_T),
NULL,
SM_CONF_FLAG_FLAT,
garage_definitions,
NULL,
NULL,
"garage section"
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T
fleet_definitions[] =
{
{
SM_CONF_DEF_MAGIC,
"fleet vehicle",
sm_conf_type_union,
offsetof(structure, fleet),
sizeof(vehicle_T),
NULL,
0,
vehicle_definitions,
NULL,
NULL,
"fleet of vehicles"
},
{
SM_CONF_DEF_MAGIC,
"n",
sm_conf_type_array_n,
offsetof(structure, fleet_n),
sizeof(unsigned int),
NULL,
0,
vehicle_definitions,
NULL,
NULL,
"number of vehicles in the fleet (implicit)"
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T
fib_definitions[] =
{
/* numbers: long */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_u32,
offsetof(structure, fib), sizeof(long), NULL, 0, NULL
},
/* counter: unsigned int */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_array_n,
offsetof(structure, fib_n),
sizeof(unsigned int), NULL, 0, NULL
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T
pi_definitions[] =
{
/* numbers: char */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_u32,
offsetof(structure, pi), sizeof(char), NULL, 0, NULL
},
/* counter: unsigned int */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_array_n,
offsetof(structure, pi_n), sizeof(unsigned int), NULL, 0, NULL
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T
icecreams_definitions[] =
{
/* flavors: icecream_T */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_section,
offsetof(structure, icecream),
sizeof(icecream_T),
NULL, 0,
icecream_definitions
},
/* counter: unsigned int */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_array_n,
offsetof(structure, icecream_n),
sizeof(unsigned int)
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T
candies_definitions[] =
{
/* candy: candy_T */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_section,
offsetof(structure, candy),
sizeof(candy_T),
NULL, 0,
candy_definitions
},
/* counter: unsigned int */
{ SM_CONF_DEF_MAGIC, "", sm_conf_type_array_n,
offsetof(structure, candy_n),
sizeof(unsigned int)
},
/* sentinel */
{ SM_CONF_DEF_MAGIC, NULL }
};
static sm_conf_definition_T const
definitions[] =
{
{ SM_CONF_DEF_MAGIC, "fibonacci",
sm_conf_type_array,
0, /* offset (n/a; see contents) */
0, /* unlimited size */
NULL,
0,
fib_definitions,
NULL, NULL, "fibonacci numbers"
},
{ SM_CONF_DEF_MAGIC, "pi",
sm_conf_type_array,
0, /* offset (n/a; see contents) */
12, /* size: maximum number of elements */
NULL,
SM_CONF_FLAG_FLAT,
pi_definitions,
NULL, NULL, "digits of pi"
},
{ SM_CONF_DEF_MAGIC, "icecream",
sm_conf_type_array,
0, /* offset (n/a; see contents) */
10, /* size: maximum number of elements */
NULL,
SM_CONF_FLAG_MULTIPLE,
icecreams_definitions,
NULL, NULL, "icecream flavor(s)"
},
{ SM_CONF_DEF_MAGIC, "candy",
sm_conf_type_array,
0, /* offset (n/a; see contents) */
4, /* size: maximum number of elements */
NULL,
SM_CONF_FLAG_MULTIPLE
| SM_CONF_FLAG_FLAT,
candies_definitions,
NULL, NULL, "brands of candy"
},
{ SM_CONF_DEF_MAGIC, "garage",
sm_conf_type_section,
0, /* offset */
2, /* size (# of elements) */
NULL, /* default */
0,
garage_outer_definitions,
NULL, NULL,
"A garage with up to two vehicles."
},
{ SM_CONF_DEF_MAGIC,
"vehicle",
sm_conf_type_array,
0,
0,
NULL,
SM_CONF_FLAG_MULTIPLE,
fleet_definitions,
NULL,
NULL,
"A fleet with an arbitrary number of vehicles."
},
/* 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;
case 0:
printf("(empty)\n");
break;
default:
printf("<unexpected type %d>\n", (int)v->type);
break;
}
}
static void
print_structure(structure *s)
{
size_t i;
printf("fibonacci: [%lu]", (unsigned long)s->fib_n);
for (i = 0; i < s->fib_n; i++)
printf(" %lu", s->fib[i]);
putchar('\n');
printf("pi: [%lu]", (unsigned long)s->pi_n);
for (i = 0; i < s->pi_n; i++)
printf(" %d", (int)s->pi[i]);
putchar('\n');
printf("icecream: [%lu]\n", (unsigned long)s->icecream_n);
for (i = 0; i < s->icecream_n; i++)
printf("[%lu] { flavor=%s; color=%s; }\n",
(unsigned long)i,
s->icecream[i].flavor
? s->icecream[i].flavor
: "(null)",
s->icecream[i].color
? s->icecream[i].color
: "(null)");
printf("candy: [%lu]\n", (unsigned long)s->candy_n);
for (i = 0; i < s->candy_n; i++)
printf("[%lu] { name=%s; price=%lu; }\n",
(unsigned long)i,
s->candy[i].name
? s->candy[i].name
: "(null)",
(unsigned long)s->candy[i].price);
printf("garage: [%d]\n", s->garage_n);
for (i = 0; i < 2; i++)
{
printf("[%d] ", (int)i);
print_vehicle(s->garage + i);
}
printf("fleet: [%d]\n", s->fleet_n);
for (i = 0; i < s->fleet_n; i++)
{
printf("[%d] ", (int)i);
print_vehicle(s->fleet + i);
}
putchar('\n');
}
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;
}
if (Verbose > 0)
{
sm_io_fprintf(smioout, "configuration\n");
sm_conf_prt_conf(definitions, &s, smioout);
sm_io_flush(smioout);
}
print_structure(&s);
sm_conf_destroy(stream);
return 0;
}
int
main(int ac, char **av)
{
int ai, r;
while ((r = getopt(ac, av, "V")) != -1)
{
switch (r)
{
case 'V':
Verbose++;
break;
default:
/* usage(av[0]); */
return 1;
}
}
ac -= optind;
av += optind;
if (ac == 0)
return process("*stdin*", stdin);
for (ai = 0; ai < ac; ai++)
{
int ret = process(av[ai], NULL);
if (ret != 0)
return ret;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1