Apply GUC name from central table in more places of guc.c
[pgsql.git] / contrib / cube / cubeparse.y
blob52622875cbb883f61fe81d2c198253aa7a2d36dd
1 %{
2 /* contrib/cube/cubeparse.y */
4 /* NdBox = [(lowerleft),(upperright)] */
5 /* [(xLL(1)...xLL(N)),(xUR(1)...xUR(n))] */
7 #include "postgres.h"
9 #include "cubedata.h"
10 #include "nodes/miscnodes.h"
11 #include "utils/float.h"
12 #include "varatt.h"
14 /* All grammar constructs return strings */
15 #define YYSTYPE char *
17 #include "cubeparse.h"
19 /* silence -Wmissing-variable-declarations */
20 extern int cube_yychar;
21 extern int cube_yynerrs;
24 * Bison doesn't allocate anything that needs to live across parser calls,
25 * so we can easily have it use palloc instead of malloc. This prevents
26 * memory leaks if we error out during parsing.
28 #define YYMALLOC palloc
29 #define YYFREE pfree
31 static int item_count(const char *s, char delim);
32 static bool write_box(int dim, char *str1, char *str2,
33 NDBOX **result, struct Node *escontext);
34 static bool write_point_as_box(int dim, char *str,
35 NDBOX **result, struct Node *escontext);
39 /* BISON Declarations */
40 %parse-param {NDBOX **result}
41 %parse-param {Size scanbuflen}
42 %parse-param {struct Node *escontext}
43 %expect 0
44 %name-prefix="cube_yy"
46 %token CUBEFLOAT O_PAREN C_PAREN O_BRACKET C_BRACKET COMMA
47 %start box
49 /* Grammar follows */
52 box: O_BRACKET paren_list COMMA paren_list C_BRACKET
54 int dim;
56 dim = item_count($2, ',');
57 if (item_count($4, ',') != dim)
59 errsave(escontext,
60 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
61 errmsg("invalid input syntax for cube"),
62 errdetail("Different point dimensions in (%s) and (%s).",
63 $2, $4)));
64 YYABORT;
66 if (dim > CUBE_MAX_DIM)
68 errsave(escontext,
69 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
70 errmsg("invalid input syntax for cube"),
71 errdetail("A cube cannot have more than %d dimensions.",
72 CUBE_MAX_DIM)));
73 YYABORT;
76 if (!write_box(dim, $2, $4, result, escontext))
77 YYABORT;
80 | paren_list COMMA paren_list
82 int dim;
84 dim = item_count($1, ',');
85 if (item_count($3, ',') != dim)
87 errsave(escontext,
88 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
89 errmsg("invalid input syntax for cube"),
90 errdetail("Different point dimensions in (%s) and (%s).",
91 $1, $3)));
92 YYABORT;
94 if (dim > CUBE_MAX_DIM)
96 errsave(escontext,
97 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
98 errmsg("invalid input syntax for cube"),
99 errdetail("A cube cannot have more than %d dimensions.",
100 CUBE_MAX_DIM)));
101 YYABORT;
104 if (!write_box(dim, $1, $3, result, escontext))
105 YYABORT;
108 | paren_list
110 int dim;
112 dim = item_count($1, ',');
113 if (dim > CUBE_MAX_DIM)
115 errsave(escontext,
116 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
117 errmsg("invalid input syntax for cube"),
118 errdetail("A cube cannot have more than %d dimensions.",
119 CUBE_MAX_DIM)));
120 YYABORT;
123 if (!write_point_as_box(dim, $1, result, escontext))
124 YYABORT;
127 | list
129 int dim;
131 dim = item_count($1, ',');
132 if (dim > CUBE_MAX_DIM)
134 errsave(escontext,
135 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
136 errmsg("invalid input syntax for cube"),
137 errdetail("A cube cannot have more than %d dimensions.",
138 CUBE_MAX_DIM)));
139 YYABORT;
142 if (!write_point_as_box(dim, $1, result, escontext))
143 YYABORT;
147 paren_list: O_PAREN list C_PAREN
149 $$ = $2;
151 | O_PAREN C_PAREN
153 $$ = pstrdup("");
157 list: CUBEFLOAT
159 /* alloc enough space to be sure whole list will fit */
160 $$ = palloc(scanbuflen + 1);
161 strcpy($$, $1);
163 | list COMMA CUBEFLOAT
165 $$ = $1;
166 strcat($$, ",");
167 strcat($$, $3);
173 /* This assumes the string has been normalized by productions above */
174 static int
175 item_count(const char *s, char delim)
177 int nitems = 0;
179 if (s[0] != '\0')
181 nitems++;
182 while ((s = strchr(s, delim)) != NULL)
184 nitems++;
185 s++;
188 return nitems;
191 static bool
192 write_box(int dim, char *str1, char *str2,
193 NDBOX **result, struct Node *escontext)
195 NDBOX *bp;
196 char *s;
197 char *endptr;
198 int i;
199 int size = CUBE_SIZE(dim);
200 bool point = true;
202 bp = palloc0(size);
203 SET_VARSIZE(bp, size);
204 SET_DIM(bp, dim);
206 s = str1;
207 i = 0;
208 if (dim > 0)
210 bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
211 if (SOFT_ERROR_OCCURRED(escontext))
212 return false;
214 while ((s = strchr(s, ',')) != NULL)
216 s++;
217 bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
218 if (SOFT_ERROR_OCCURRED(escontext))
219 return false;
221 Assert(i == dim);
223 s = str2;
224 if (dim > 0)
226 bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
227 if (SOFT_ERROR_OCCURRED(escontext))
228 return false;
229 /* code this way to do right thing with NaN */
230 point &= (bp->x[i] == bp->x[0]);
231 i++;
233 while ((s = strchr(s, ',')) != NULL)
235 s++;
236 bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
237 if (SOFT_ERROR_OCCURRED(escontext))
238 return false;
239 point &= (bp->x[i] == bp->x[i - dim]);
240 i++;
242 Assert(i == dim * 2);
244 if (point)
247 * The value turned out to be a point, ie. all the upper-right
248 * coordinates were equal to the lower-left coordinates. Resize the
249 * cube we constructed. Note: we don't bother to repalloc() it
250 * smaller, as it's unlikely that the tiny amount of memory freed
251 * that way would be useful, and the output is always short-lived.
253 size = POINT_SIZE(dim);
254 SET_VARSIZE(bp, size);
255 SET_POINT_BIT(bp);
258 *result = bp;
259 return true;
262 static bool
263 write_point_as_box(int dim, char *str,
264 NDBOX **result, struct Node *escontext)
266 NDBOX *bp;
267 int i,
268 size;
269 char *s;
270 char *endptr;
272 size = POINT_SIZE(dim);
273 bp = palloc0(size);
274 SET_VARSIZE(bp, size);
275 SET_DIM(bp, dim);
276 SET_POINT_BIT(bp);
278 s = str;
279 i = 0;
280 if (dim > 0)
282 bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
283 if (SOFT_ERROR_OCCURRED(escontext))
284 return false;
286 while ((s = strchr(s, ',')) != NULL)
288 s++;
289 bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
290 if (SOFT_ERROR_OCCURRED(escontext))
291 return false;
293 Assert(i == dim);
295 *result = bp;
296 return true;