]> granicus.if.org Git - postgresql/blob - contrib/tsearch2/prs_dcfg.c
6b553e4525671721cc27e00652b92603ceba1881
[postgresql] / contrib / tsearch2 / prs_dcfg.c
1 /*
2  * Simple config parser
3  * Teodor Sigaev <teodor@sigaev.ru>
4  */
5 #include <stdlib.h>
6 #include <string.h>
7 #include <ctype.h>
8
9 #include "postgres.h"
10
11 #include "dict.h"
12 #include "common.h"
13
14 #define CS_WAITKEY      0
15 #define CS_INKEY        1
16 #define CS_WAITEQ       2
17 #define CS_WAITVALUE    3
18 #define CS_INVALUE      4
19 #define CS_IN2VALUE 5
20 #define CS_WAITDELIM    6
21 #define CS_INESC        7
22 #define CS_IN2ESC       8
23
24 static char *
25 nstrdup(char *ptr, int len)
26 {
27         char       *res = palloc(len + 1),
28                            *cptr;
29
30         memcpy(res, ptr, len);
31         res[len] = '\0';
32         cptr = ptr = res;
33         while (*ptr)
34         {
35                 if (*ptr == '\\')
36                         ptr++;
37                 *cptr = *ptr;
38                 ptr++;
39                 cptr++;
40         }
41         *cptr = '\0';
42
43         return res;
44 }
45
46 void
47 parse_cfgdict(text *in, Map ** m)
48 {
49         Map                *mptr;
50         char       *ptr = VARDATA(in),
51                            *begin = NULL;
52         char            num = 0;
53         int                     state = CS_WAITKEY;
54
55         while (ptr - VARDATA(in) < VARSIZE(in) - VARHDRSZ)
56         {
57                 if (*ptr == ',')
58                         num++;
59                 ptr++;
60         }
61
62         *m = mptr = (Map *) palloc(sizeof(Map) * (num + 2));
63         memset(mptr, 0, sizeof(Map) * (num + 2));
64         ptr = VARDATA(in);
65         while (ptr - VARDATA(in) < VARSIZE(in) - VARHDRSZ)
66         {
67                 if (state == CS_WAITKEY)
68                 {
69                         if (isalpha(*ptr))
70                         {
71                                 begin = ptr;
72                                 state = CS_INKEY;
73                         }
74                         else if (!isspace(*ptr))
75                                 ereport(ERROR,
76                                                 (errcode(ERRCODE_SYNTAX_ERROR),
77                                                  errmsg("syntax error"),
78                                          errdetail("Syntax error in position %d near \"%c\"",
79                                                            (int) (ptr - VARDATA(in)), *ptr)));
80                 }
81                 else if (state == CS_INKEY)
82                 {
83                         if (isspace(*ptr))
84                         {
85                                 mptr->key = nstrdup(begin, ptr - begin);
86                                 state = CS_WAITEQ;
87                         }
88                         else if (*ptr == '=')
89                         {
90                                 mptr->key = nstrdup(begin, ptr - begin);
91                                 state = CS_WAITVALUE;
92                         }
93                         else if (!isalpha(*ptr))
94                                 ereport(ERROR,
95                                                 (errcode(ERRCODE_SYNTAX_ERROR),
96                                                  errmsg("syntax error"),
97                                          errdetail("Syntax error in position %d near \"%c\"",
98                                                            (int) (ptr - VARDATA(in)), *ptr)));
99                 }
100                 else if (state == CS_WAITEQ)
101                 {
102                         if (*ptr == '=')
103                                 state = CS_WAITVALUE;
104                         else if (!isspace(*ptr))
105                                 ereport(ERROR,
106                                                 (errcode(ERRCODE_SYNTAX_ERROR),
107                                                  errmsg("syntax error"),
108                                          errdetail("Syntax error in position %d near \"%c\"",
109                                                            (int) (ptr - VARDATA(in)), *ptr)));
110                 }
111                 else if (state == CS_WAITVALUE)
112                 {
113                         if (*ptr == '"')
114                         {
115                                 begin = ptr + 1;
116                                 state = CS_INVALUE;
117                         }
118                         else if (!isspace(*ptr))
119                         {
120                                 begin = ptr;
121                                 state = CS_IN2VALUE;
122                         }
123                 }
124                 else if (state == CS_INVALUE)
125                 {
126                         if (*ptr == '"')
127                         {
128                                 mptr->value = nstrdup(begin, ptr - begin);
129                                 mptr++;
130                                 state = CS_WAITDELIM;
131                         }
132                         else if (*ptr == '\\')
133                                 state = CS_INESC;
134                 }
135                 else if (state == CS_IN2VALUE)
136                 {
137                         if (isspace(*ptr) || *ptr == ',')
138                         {
139                                 mptr->value = nstrdup(begin, ptr - begin);
140                                 mptr++;
141                                 state = (*ptr == ',') ? CS_WAITKEY : CS_WAITDELIM;
142                         }
143                         else if (*ptr == '\\')
144                                 state = CS_INESC;
145                 }
146                 else if (state == CS_WAITDELIM)
147                 {
148                         if (*ptr == ',')
149                                 state = CS_WAITKEY;
150                         else if (!isspace(*ptr))
151                                 ereport(ERROR,
152                                                 (errcode(ERRCODE_SYNTAX_ERROR),
153                                                  errmsg("syntax error"),
154                                          errdetail("Syntax error in position %d near \"%c\"",
155                                                            (int) (ptr - VARDATA(in)), *ptr)));
156                 }
157                 else if (state == CS_INESC)
158                         state = CS_INVALUE;
159                 else if (state == CS_IN2ESC)
160                         state = CS_IN2VALUE;
161                 else
162                         ereport(ERROR,
163                                         (errcode(ERRCODE_SYNTAX_ERROR),
164                                          errmsg("bad parser state"),
165                                          errdetail("%d at position %d near \"%c\"",
166                                                            state, (int) (ptr - VARDATA(in)), *ptr)));
167                 ptr++;
168         }
169
170         if (state == CS_IN2VALUE)
171         {
172                 mptr->value = nstrdup(begin, ptr - begin);
173                 mptr++;
174         }
175         else if (!(state == CS_WAITDELIM || state == CS_WAITKEY))
176                 ereport(ERROR,
177                                 (errcode(ERRCODE_SYNTAX_ERROR),
178                                  errmsg("unexpected end of line")));
179 }