#include "db_codegen.h"
static enum
{ PS_UNSET, PS_ENV_SET, PS_DB_SET } parse_status;
static ENV_OBJ *cur_env;
static DB_OBJ *cur_db;
static int parse_line __P((char *, int));
int
parse_input(fp)
FILE *fp;
{
int lc;
char *p, *t, buf[256];
parse_status = PS_UNSET;
for (lc = 1; fgets(buf, sizeof(buf), fp) != NULL; ++lc) {
if ((p = strchr(buf, '\n')) != NULL)
*p = '\0';
else if (strlen(buf) + 1 == sizeof(buf)) {
fprintf(stderr, "%s: %d: line too long", progname, lc);
return (1);
}
for (p = buf; *p != '\0' && isspace((int)*p); ++p)
;
if (*p == '\0' || *p == '#')
continue;
for (t = p; *t != '\0' && *t != '#'; ++t)
;
*t = '\0';
if (parse_line(p, lc))
return (1);
}
(void)fclose(fp);
return (0);
}
#undef CONFIG_SLOTS
#define CONFIG_SLOTS 10
#undef CONFIG_GET_UINT32
#define CONFIG_GET_UINT32(s, vp) do { \
if (__db_getulong(NULL, progname, s, 0, UINT32_MAX, vp) != 0) \
return (EINVAL); \
} while (0)
static int
parse_line(s, lc)
char *s;
int lc;
{
u_long uv;
int nf;
char *argv[CONFIG_SLOTS], *p;
nf = __config_split(s, argv);
if (strcasecmp(argv[0], "environment") == 0) {
if (nf != 3 ||
strcmp(argv[2], "{") != 0 || parse_status != PS_UNSET)
goto format;
if (__os_calloc(NULL, 1, sizeof(*cur_env), &cur_env) ||
__os_strdup(NULL, argv[1], &cur_env->prefix))
goto memory;
TAILQ_INIT(&cur_env->dbq);
TAILQ_INSERT_TAIL(&env_tree, cur_env, q);
cur_env->home = ".";
parse_status = PS_ENV_SET;
return (0);
}
if (strcasecmp(argv[0], "home") == 0) {
if (nf != 2 || parse_status != PS_ENV_SET)
goto format;
if (__os_strdup(NULL, argv[1], &cur_env->home))
goto memory;
return (0);
}
if (strcasecmp(argv[0], "cachesize") == 0) {
if (nf != 4 || parse_status != PS_ENV_SET)
goto format;
CONFIG_GET_UINT32(argv[1], &uv);
cur_env->gbytes = uv;
CONFIG_GET_UINT32(argv[1], &uv);
cur_env->bytes = uv;
CONFIG_GET_UINT32(argv[1], &uv);
cur_env->ncache = uv;
return (0);
}
if (strcasecmp(argv[0], "private") == 0) {
if (nf != 1 || parse_status != PS_ENV_SET)
goto format;
cur_env->private = 1;
return (0);
}
if (strcasecmp(argv[0], "database") == 0) {
if (nf != 3 ||
strcmp(argv[2], "{") != 0 || parse_status == PS_DB_SET)
goto format;
if (parse_status == PS_UNSET) {
if (__os_calloc(NULL, 1, sizeof(*cur_env), &cur_env))
goto memory;
TAILQ_INIT(&cur_env->dbq);
cur_env->standalone = 1;
TAILQ_INSERT_TAIL(&env_tree, cur_env, q);
}
if (__os_calloc(NULL, 1, sizeof(*cur_db), &cur_db) ||
__os_strdup(NULL, argv[1], &cur_db->name))
goto memory;
TAILQ_INSERT_TAIL(&cur_env->dbq, cur_db, q);
cur_db->dbtype = "DB_BTREE";
parse_status = PS_DB_SET;
return (0);
}
if (strcasecmp(argv[0], "custom") == 0) {
if (nf != 1 || parse_status != PS_DB_SET)
goto format;
cur_db->custom = 1;
return (0);
}
if (strcasecmp(argv[0], "dupsort") == 0) {
if (nf != 1 || parse_status != PS_DB_SET)
goto format;
cur_db->dupsort = 1;
return (0);
}
if (strcasecmp(argv[0], "extentsize") == 0) {
if (nf != 2 || parse_status != PS_DB_SET)
goto format;
CONFIG_GET_UINT32(argv[1], &uv);
cur_db->extentsize = uv;
return (0);
}
if (strcasecmp(argv[0], "key_type") == 0) {
if (nf != 2 || parse_status != PS_DB_SET)
goto format;
if (__os_strdup(NULL, argv[1], &cur_db->key_type))
goto memory;
return (0);
}
if (strcasecmp(argv[0], "pagesize") == 0) {
if (nf != 2 || parse_status != PS_DB_SET)
goto format;
CONFIG_GET_UINT32(argv[1], &uv);
cur_db->pagesize = uv;
return (0);
}
if (strcasecmp(argv[0], "primary") == 0) {
if (nf != 2 || parse_status != PS_DB_SET)
goto format;
if (__os_strdup(NULL, argv[1], &cur_db->primary))
goto memory;
return (0);
}
if (strcasecmp(argv[0], "recnum") == 0) {
if (nf != 1 || parse_status != PS_DB_SET)
goto format;
cur_db->recnum = 1;
return (0);
}
if (strcasecmp(argv[0], "re_len") == 0) {
if (nf != 2 || parse_status != PS_DB_SET)
goto format;
CONFIG_GET_UINT32(argv[1], &uv);
cur_db->re_len = uv;
return (0);
}
if (strcasecmp(argv[0], "secondary_offset") == 0) {
if (nf != 3 || parse_status != PS_DB_SET)
goto format;
CONFIG_GET_UINT32(argv[1], &uv);
cur_db->secondary_off = uv;
CONFIG_GET_UINT32(argv[2], &uv);
cur_db->secondary_len = uv;
return (0);
}
if (strcasecmp(argv[0], "transaction") == 0) {
if (nf != 1 || parse_status != PS_DB_SET)
goto format;
cur_env->transaction = cur_db->transaction = 1;
return (0);
}
if (strcasecmp(argv[0], "type") == 0) {
if (nf != 2 || parse_status != PS_DB_SET)
goto format;
if (strcasecmp(argv[1], "btree") == 0)
p = "DB_BTREE";
else if (strcasecmp(argv[1], "hash") == 0)
p = "DB_HASH";
else if (strcasecmp(argv[1], "queue") == 0)
p = "DB_QUEUE";
else if (strcasecmp(argv[1], "recno") == 0)
p = "DB_RECNO";
else
goto format;
if (__os_strdup(NULL, p, &cur_db->dbtype))
goto memory;
return (0);
}
if (strcmp(argv[0], "}") == 0) {
if (nf != 1)
goto format;
switch (parse_status) {
case PS_UNSET:
goto format;
case PS_DB_SET:
parse_status =
cur_env->standalone ? PS_UNSET : PS_ENV_SET;
break;
case PS_ENV_SET:
parse_status = PS_UNSET;
}
return (0);
}
format: fprintf(stderr,
"%s: line %d: %s: invalid input\n", progname, lc, s);
return (1);
memory: fprintf(stderr, "%s: %s\n", progname, db_strerror(errno));
return (1);
}
#ifdef DEBUG
int
parse_dump()
{
TAILQ_FOREACH(cur_env, &env_tree, q) {
printf("environment: %s\n",
cur_env->standalone ? "standalone" : cur_env->prefix);
if (cur_env->home != NULL)
printf("\thome: %s\n", cur_env->home);
if (cur_env->gbytes != 0 || cur_env->bytes != 0)
printf("\tcachesize: %luGB, %luB, %lu\n",
(u_long)cur_env->gbytes,
(u_long)cur_env->bytes,
(u_long)cur_env->ncache);
if (cur_env->private)
printf("\tprivate: yes\n");
if (cur_env->transaction)
printf("\ttransaction: yes\n");
TAILQ_FOREACH(cur_db, &cur_env->dbq, q) {
printf("\tdatabase: %s\n", cur_db->name);
printf("\t\tdbtype: %s\n", cur_db->dbtype);
if (cur_db->extentsize)
printf("\t\textentsize: %lu\n",
(u_long)cur_db->extentsize);
if (cur_db->pagesize)
printf("\t\tpagesize: %lu\n",
(u_long)cur_db->pagesize);
if (cur_db->re_len)
printf("\t\tre_len: %lu\n",
(u_long)cur_db->re_len);
if (cur_db->key_type != NULL)
printf("\t\tkey_type: %s\n",
cur_db->key_type);
if (cur_db->primary != NULL)
printf("\t\tprimary: %s\n",
cur_db->primary);
if (cur_db->custom)
printf("\t\tcustom: yes\n");
if (cur_db->secondary_off)
printf("\t\tsecondary_offset: %lu/%lu\n",
(u_long)cur_db->secondary_off,
(u_long)cur_db->secondary_len);
if (cur_db->dupsort)
printf("\t\tdupsort: yes\n");
if (cur_db->recnum)
printf("\t\trecnum: yes\n");
if (cur_db->transaction)
printf("\t\ttransaction: yes\n");
}
}
return (0);
}
#endif