mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-04 00:02:52 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			180 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			3.7 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((unsigned char) *ptr))
 | 
						|
			{
 | 
						|
				begin = ptr;
 | 
						|
				state = CS_INKEY;
 | 
						|
			}
 | 
						|
			else if (!isspace((unsigned char) *ptr))
 | 
						|
				ereport(ERROR,
 | 
						|
						(errcode(ERRCODE_SYNTAX_ERROR),
 | 
						|
						 errmsg("syntax error"),
 | 
						|
					 errdetail("Syntax error in position %d near \"%c\"",
 | 
						|
							   (int) (ptr - VARDATA(in)), *ptr)));
 | 
						|
		}
 | 
						|
		else if (state == CS_INKEY)
 | 
						|
		{
 | 
						|
			if (isspace((unsigned char) *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((unsigned char) *ptr))
 | 
						|
				ereport(ERROR,
 | 
						|
						(errcode(ERRCODE_SYNTAX_ERROR),
 | 
						|
						 errmsg("syntax error"),
 | 
						|
					 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"),
 | 
						|
					 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))
 | 
						|
			{
 | 
						|
				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((unsigned char) *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((unsigned char) *ptr))
 | 
						|
				ereport(ERROR,
 | 
						|
						(errcode(ERRCODE_SYNTAX_ERROR),
 | 
						|
						 errmsg("syntax error"),
 | 
						|
					 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\"",
 | 
						|
							   state, (int) (ptr - VARDATA(in)), *ptr)));
 | 
						|
		ptr++;
 | 
						|
	}
 | 
						|
 | 
						|
	if (state == CS_IN2VALUE)
 | 
						|
	{
 | 
						|
		mptr->value = nstrdup(begin, ptr - begin);
 | 
						|
		mptr++;
 | 
						|
	}
 | 
						|
	else if (!(state == CS_WAITDELIM || state == CS_WAITKEY))
 | 
						|
		ereport(ERROR,
 | 
						|
				(errcode(ERRCODE_SYNTAX_ERROR),
 | 
						|
				 errmsg("unexpected end of line")));
 | 
						|
}
 |