postgresql/contrib/tsearch2/prs_dcfg.c

178 lines
3.7 KiB
C
Raw Normal View History

2003-08-04 08:43:34 +08:00
/*
* Simple config parser
2003-07-21 18:27:44 +08:00
* Teodor Sigaev <teodor@sigaev.ru>
*/
#include "postgres.h"
#include <ctype.h>
2003-07-21 18:27:44 +08:00
#include "dict.h"
#include "common.h"
#define CS_WAITKEY 0
#define CS_INKEY 1
#define CS_WAITEQ 2
#define CS_WAITVALUE 3
#define CS_INVALUE 4
2003-08-04 08:43:34 +08:00
#define CS_IN2VALUE 5
2003-07-21 18:27:44 +08:00
#define CS_WAITDELIM 6
#define CS_INESC 7
#define CS_IN2ESC 8
static char *
2003-08-04 08:43:34 +08:00
nstrdup(char *ptr, int len)
{
char *res = palloc(len + 1),
*cptr;
memcpy(res, ptr, len);
res[len] = '\0';
2003-07-21 18:27:44 +08:00
cptr = ptr = res;
2003-08-04 08:43:34 +08:00
while (*ptr)
{
if (*ptr == '\\')
2003-07-21 18:27:44 +08:00
ptr++;
2003-08-04 08:43:34 +08:00
*cptr = *ptr;
ptr++;
cptr++;
2003-07-21 18:27:44 +08:00
}
2003-08-04 08:43:34 +08:00
*cptr = '\0';
2003-07-21 18:27:44 +08:00
return res;
}
void
2003-08-04 08:43:34 +08:00
parse_cfgdict(text *in, Map ** m)
{
Map *mptr;
char *ptr = VARDATA(in),
*begin = NULL;
char num = 0;
int state = CS_WAITKEY;
2003-07-21 18:27:44 +08:00
2003-08-04 08:43:34 +08:00
while (ptr - VARDATA(in) < VARSIZE(in) - VARHDRSZ)
{
if (*ptr == ',')
num++;
2003-07-21 18:27:44 +08:00
ptr++;
}
2003-08-04 08:43:34 +08:00
*m = mptr = (Map *) palloc(sizeof(Map) * (num + 2));
memset(mptr, 0, sizeof(Map) * (num + 2));
ptr = VARDATA(in);
while (ptr - VARDATA(in) < VARSIZE(in) - VARHDRSZ)
{
if (state == CS_WAITKEY)
{
if (isalpha((unsigned char) *ptr))
2003-08-04 08:43:34 +08:00
{
begin = ptr;
state = CS_INKEY;
}
else if (!isspace((unsigned char) *ptr))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("syntax error"),
2003-08-04 08:43:34 +08:00
errdetail("Syntax error in position %d near \"%c\"",
(int) (ptr - VARDATA(in)), *ptr)));
}
else if (state == CS_INKEY)
{
if (isspace((unsigned char) *ptr))
2003-08-04 08:43:34 +08:00
{
mptr->key = nstrdup(begin, ptr - begin);
state = CS_WAITEQ;
}
else if (*ptr == '=')
{
mptr->key = nstrdup(begin, ptr - begin);
state = CS_WAITVALUE;
}
else if (!isalpha((unsigned char) *ptr))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("syntax error"),
2003-08-04 08:43:34 +08:00
errdetail("Syntax error in position %d near \"%c\"",
(int) (ptr - VARDATA(in)), *ptr)));
}
else if (state == CS_WAITEQ)
{
if (*ptr == '=')
state = CS_WAITVALUE;
else if (!isspace((unsigned char) *ptr))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("syntax error"),
2003-08-04 08:43:34 +08:00
errdetail("Syntax error in position %d near \"%c\"",
(int) (ptr - VARDATA(in)), *ptr)));
}
else if (state == CS_WAITVALUE)
{
if (*ptr == '"')
{
begin = ptr + 1;
state = CS_INVALUE;
}
else if (!isspace((unsigned char) *ptr))
2003-08-04 08:43:34 +08:00
{
begin = ptr;
state = CS_IN2VALUE;
2003-07-21 18:27:44 +08:00
}
2003-08-04 08:43:34 +08:00
}
else if (state == CS_INVALUE)
{
if (*ptr == '"')
{
mptr->value = nstrdup(begin, ptr - begin);
2003-07-21 18:27:44 +08:00
mptr++;
2003-08-04 08:43:34 +08:00
state = CS_WAITDELIM;
}
else if (*ptr == '\\')
state = CS_INESC;
}
else if (state == CS_IN2VALUE)
{
if (isspace((unsigned char) *ptr) || *ptr == ',')
2003-08-04 08:43:34 +08:00
{
mptr->value = nstrdup(begin, ptr - begin);
2003-07-21 18:27:44 +08:00
mptr++;
2003-08-04 08:43:34 +08:00
state = (*ptr == ',') ? CS_WAITKEY : CS_WAITDELIM;
}
else if (*ptr == '\\')
state = CS_INESC;
}
else if (state == CS_WAITDELIM)
{
if (*ptr == ',')
state = CS_WAITKEY;
else if (!isspace((unsigned char) *ptr))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("syntax error"),
2003-08-04 08:43:34 +08:00
errdetail("Syntax error in position %d near \"%c\"",
(int) (ptr - VARDATA(in)), *ptr)));
}
else if (state == CS_INESC)
state = CS_INVALUE;
else if (state == CS_IN2ESC)
state = CS_IN2VALUE;
else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("bad parser state"),
errdetail("%d at position %d near \"%c\"",
2003-08-04 08:43:34 +08:00
state, (int) (ptr - VARDATA(in)), *ptr)));
2003-07-21 18:27:44 +08:00
ptr++;
}
2003-08-04 08:43:34 +08:00
if (state == CS_IN2VALUE)
{
mptr->value = nstrdup(begin, ptr - begin);
2003-07-21 18:27:44 +08:00
mptr++;
2003-08-04 08:43:34 +08:00
}
else if (!(state == CS_WAITDELIM || state == CS_WAITKEY))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("unexpected end of line")));
2003-07-21 18:27:44 +08:00
}