mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
120 lines
2.9 KiB
C
120 lines
2.9 KiB
C
/*
|
|
* Simple config parser
|
|
* Teodor Sigaev <teodor@sigaev.ru>
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "postgres.h"
|
|
|
|
#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
|
|
#define CS_IN2VALUE 5
|
|
#define CS_WAITDELIM 6
|
|
#define CS_INESC 7
|
|
#define CS_IN2ESC 8
|
|
|
|
static char *
|
|
nstrdup(char *ptr, int len) {
|
|
char *res=palloc(len+1), *cptr;
|
|
memcpy(res,ptr,len);
|
|
res[len]='\0';
|
|
cptr = ptr = res;
|
|
while(*ptr) {
|
|
if ( *ptr == '\\' )
|
|
ptr++;
|
|
*cptr=*ptr; ptr++; cptr++;
|
|
}
|
|
*cptr='\0';
|
|
|
|
return res;
|
|
}
|
|
|
|
void
|
|
parse_cfgdict(text *in, Map **m) {
|
|
Map *mptr;
|
|
char *ptr=VARDATA(in), *begin=NULL;
|
|
char num=0;
|
|
int state=CS_WAITKEY;
|
|
|
|
while( ptr-VARDATA(in) < VARSIZE(in) - VARHDRSZ ) {
|
|
if ( *ptr==',' ) num++;
|
|
ptr++;
|
|
}
|
|
|
|
*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(*ptr)) {
|
|
begin=ptr;
|
|
state=CS_INKEY;
|
|
} else if ( !isspace(*ptr) )
|
|
elog(ERROR,"Syntax error in position %d near '%c'", ptr-VARDATA(in), *ptr);
|
|
} else if (state==CS_INKEY) {
|
|
if ( isspace(*ptr) ) {
|
|
mptr->key=nstrdup(begin, ptr-begin);
|
|
state=CS_WAITEQ;
|
|
} else if ( *ptr=='=' ) {
|
|
mptr->key=nstrdup(begin, ptr-begin);
|
|
state=CS_WAITVALUE;
|
|
} else if ( !isalpha(*ptr) )
|
|
elog(ERROR,"Syntax error in position %d near '%c'", ptr-VARDATA(in), *ptr);
|
|
} else if ( state==CS_WAITEQ ) {
|
|
if ( *ptr=='=' )
|
|
state=CS_WAITVALUE;
|
|
else if ( !isspace(*ptr) )
|
|
elog(ERROR,"Syntax error in position %d near '%c'", ptr-VARDATA(in), *ptr);
|
|
} else if ( state==CS_WAITVALUE ) {
|
|
if ( *ptr=='"' ) {
|
|
begin=ptr+1;
|
|
state=CS_INVALUE;
|
|
} else if ( !isspace(*ptr) ) {
|
|
begin=ptr;
|
|
state=CS_IN2VALUE;
|
|
}
|
|
} else if ( state==CS_INVALUE ) {
|
|
if ( *ptr=='"' ) {
|
|
mptr->value = nstrdup(begin, ptr-begin);
|
|
mptr++;
|
|
state=CS_WAITDELIM;
|
|
} else if ( *ptr=='\\' )
|
|
state=CS_INESC;
|
|
} else if ( state==CS_IN2VALUE ) {
|
|
if ( isspace(*ptr) || *ptr==',' ) {
|
|
mptr->value = nstrdup(begin, ptr-begin);
|
|
mptr++;
|
|
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(*ptr) )
|
|
elog(ERROR,"Syntax error in position %d near '%c'", ptr-VARDATA(in), *ptr);
|
|
} else if ( state == CS_INESC ) {
|
|
state=CS_INVALUE;
|
|
} else if ( state == CS_IN2ESC ) {
|
|
state=CS_IN2VALUE;
|
|
} else
|
|
elog(ERROR,"Bad parser state: %d at position %d near '%c'", state, ptr-VARDATA(in), *ptr);
|
|
ptr++;
|
|
}
|
|
|
|
if (state==CS_IN2VALUE) {
|
|
mptr->value = nstrdup(begin, ptr-begin);
|
|
mptr++;
|
|
} else if ( !(state==CS_WAITDELIM || state==CS_WAITKEY) )
|
|
elog(ERROR,"Unexpected end of line");
|
|
}
|
|
|
|
|