Age Owner TLA Line data Source code
1 : %{
2 : /* contrib/cube/cubeparse.y */
3 :
4 : /* NdBox = [(lowerleft),(upperright)] */
5 : /* [(xLL(1)...xLL(N)),(xUR(1)...xUR(n))] */
6 :
7 : #include "postgres.h"
8 :
9 : #include "cubedata.h"
10 : #include "nodes/miscnodes.h"
11 : #include "utils/float.h"
12 : #include "varatt.h"
13 :
14 : /* All grammar constructs return strings */
15 : #define YYSTYPE char *
16 :
17 : /*
18 : * Bison doesn't allocate anything that needs to live across parser calls,
19 : * so we can easily have it use palloc instead of malloc. This prevents
20 : * memory leaks if we error out during parsing.
21 : */
22 : #define YYMALLOC palloc
23 : #define YYFREE pfree
24 :
25 : static int item_count(const char *s, char delim);
26 : static bool write_box(int dim, char *str1, char *str2,
27 : NDBOX **result, struct Node *escontext);
28 : static bool write_point_as_box(int dim, char *str,
29 : NDBOX **result, struct Node *escontext);
30 :
31 : %}
32 :
33 : /* BISON Declarations */
34 : %parse-param {NDBOX **result}
35 : %parse-param {Size scanbuflen}
36 : %parse-param {struct Node *escontext}
37 : %expect 0
38 : %name-prefix="cube_yy"
39 :
40 : %token CUBEFLOAT O_PAREN C_PAREN O_BRACKET C_BRACKET COMMA
41 : %start box
42 :
43 : /* Grammar follows */
44 : %%
45 :
46 : box: O_BRACKET paren_list COMMA paren_list C_BRACKET
47 : {
48 : int dim;
49 :
2385 tgl 50 CBC 16 : dim = item_count($2, ',');
51 16 : if (item_count($4, ',') != dim)
52 : {
121 tgl 53 GNC 2 : errsave(escontext,
54 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
55 : errmsg("invalid input syntax for cube"),
56 : errdetail("Different point dimensions in (%s) and (%s).",
57 : $2, $4)));
4177 peter_e 58 UBC 0 : YYABORT;
59 : }
2385 tgl 60 CBC 14 : if (dim > CUBE_MAX_DIM)
61 : {
121 tgl 62 UNC 0 : errsave(escontext,
63 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
64 : errmsg("invalid input syntax for cube"),
65 : errdetail("A cube cannot have more than %d dimensions.",
66 : CUBE_MAX_DIM)));
4177 peter_e 67 UBC 0 : YYABORT;
68 : }
69 :
121 tgl 70 GNC 14 : if (!write_box(dim, $2, $4, result, escontext))
121 tgl 71 UNC 0 : YYABORT;
4177 peter_e 72 EUB : }
73 :
74 : | paren_list COMMA paren_list
75 : {
76 : int dim;
77 :
2385 tgl 78 GIC 3246 : dim = item_count($1, ',');
2385 tgl 79 CBC 3246 : if (item_count($3, ',') != dim)
2385 tgl 80 ECB : {
121 tgl 81 GNC 2 : errsave(escontext,
2385 tgl 82 ECB : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
83 : errmsg("invalid input syntax for cube"),
84 : errdetail("Different point dimensions in (%s) and (%s).",
85 : $1, $3)));
4177 peter_e 86 UIC 0 : YYABORT;
4177 peter_e 87 EUB : }
2385 tgl 88 GIC 3244 : if (dim > CUBE_MAX_DIM)
2385 tgl 89 ECB : {
121 tgl 90 GNC 1 : errsave(escontext,
2385 tgl 91 ECB : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
92 : errmsg("invalid input syntax for cube"),
93 : errdetail("A cube cannot have more than %d dimensions.",
94 : CUBE_MAX_DIM)));
4177 peter_e 95 UIC 0 : YYABORT;
4177 peter_e 96 EUB : }
97 :
121 tgl 98 GNC 3243 : if (!write_box(dim, $1, $3, result, escontext))
121 tgl 99 UNC 0 : YYABORT;
4177 peter_e 100 ECB : }
4177 peter_e 101 EUB :
102 : | paren_list
103 : {
104 : int dim;
105 :
2385 tgl 106 GIC 69 : dim = item_count($1, ',');
107 69 : if (dim > CUBE_MAX_DIM)
2385 tgl 108 ECB : {
121 tgl 109 GNC 1 : errsave(escontext,
110 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2385 tgl 111 ECB : errmsg("invalid input syntax for cube"),
112 : errdetail("A cube cannot have more than %d dimensions.",
113 : CUBE_MAX_DIM)));
4177 peter_e 114 UIC 0 : YYABORT;
115 : }
4177 peter_e 116 EUB :
121 tgl 117 GNC 68 : if (!write_point_as_box(dim, $1, result, escontext))
121 tgl 118 UNC 0 : YYABORT;
119 : }
4177 peter_e 120 ECB :
4177 peter_e 121 EUB : | list
122 : {
123 : int dim;
124 :
2385 tgl 125 GIC 89 : dim = item_count($1, ',');
126 89 : if (dim > CUBE_MAX_DIM)
127 : {
121 tgl 128 UNC 0 : errsave(escontext,
2385 tgl 129 ECB : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
130 : errmsg("invalid input syntax for cube"),
4177 peter_e 131 EUB : errdetail("A cube cannot have more than %d dimensions.",
132 : CUBE_MAX_DIM)));
4177 peter_e 133 UIC 0 : YYABORT;
134 : }
135 :
121 tgl 136 GNC 89 : if (!write_point_as_box(dim, $1, result, escontext))
137 2 : YYABORT;
138 : }
139 : ;
4177 peter_e 140 ECB :
141 : paren_list: O_PAREN list C_PAREN
142 : {
4177 peter_e 143 GIC 6596 : $$ = $2;
144 : }
145 : | O_PAREN C_PAREN
146 : {
2385 tgl 147 CBC 4 : $$ = pstrdup("");
148 : }
149 : ;
150 :
4177 peter_e 151 ECB : list: CUBEFLOAT
152 : {
153 : /* alloc enough space to be sure whole list will fit */
4177 peter_e 154 GIC 6691 : $$ = palloc(scanbuflen + 1);
155 6691 : strcpy($$, $1);
156 : }
157 : | list COMMA CUBEFLOAT
4177 peter_e 158 ECB : {
4177 peter_e 159 CBC 7368 : $$ = $1;
4177 peter_e 160 GIC 7368 : strcat($$, ",");
161 7368 : strcat($$, $3);
162 : }
4177 peter_e 163 ECB : ;
8154 tgl 164 :
165 : %%
166 :
167 : /* This assumes the string has been normalized by productions above */
168 : static int
2385 tgl 169 GIC 6682 : item_count(const char *s, char delim)
170 : {
171 6682 : int nitems = 0;
172 :
2385 tgl 173 CBC 6682 : if (s[0] != '\0')
174 : {
175 6679 : nitems++;
2385 tgl 176 GIC 14045 : while ((s = strchr(s, delim)) != NULL)
2385 tgl 177 ECB : {
2385 tgl 178 GIC 7366 : nitems++;
2385 tgl 179 CBC 7366 : s++;
2385 tgl 180 ECB : }
181 : }
2385 tgl 182 CBC 6682 : return nitems;
8154 tgl 183 ECB : }
184 :
185 : static bool
121 tgl 186 GNC 3257 : write_box(int dim, char *str1, char *str2,
187 : NDBOX **result, struct Node *escontext)
188 : {
189 : NDBOX *bp;
190 : char *s;
2385 tgl 191 ECB : char *endptr;
192 : int i;
3457 heikki.linnakangas 193 GIC 3257 : int size = CUBE_SIZE(dim);
194 3257 : bool point = true;
195 :
4177 peter_e 196 3257 : bp = palloc0(size);
197 3257 : SET_VARSIZE(bp, size);
3457 heikki.linnakangas 198 CBC 3257 : SET_DIM(bp, dim);
4177 peter_e 199 ECB :
4177 peter_e 200 GIC 3257 : s = str1;
2385 tgl 201 CBC 3257 : i = 0;
202 3257 : if (dim > 0)
203 : {
121 tgl 204 GNC 3256 : bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
205 3256 : if (SOFT_ERROR_OCCURRED(escontext))
121 tgl 206 UNC 0 : return false;
207 : }
4177 peter_e 208 GIC 6576 : while ((s = strchr(s, ',')) != NULL)
4177 peter_e 209 ECB : {
2385 tgl 210 CBC 3319 : s++;
121 tgl 211 GNC 3319 : bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
212 3319 : if (SOFT_ERROR_OCCURRED(escontext))
121 tgl 213 UNC 0 : return false;
214 : }
2385 tgl 215 CBC 3257 : Assert(i == dim);
4177 peter_e 216 ECB :
4177 peter_e 217 GBC 3257 : s = str2;
2385 tgl 218 GIC 3257 : if (dim > 0)
2385 tgl 219 ECB : {
121 tgl 220 GNC 3256 : bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
221 3256 : if (SOFT_ERROR_OCCURRED(escontext))
121 tgl 222 UNC 0 : return false;
2385 tgl 223 ECB : /* code this way to do right thing with NaN */
2385 tgl 224 CBC 3256 : point &= (bp->x[i] == bp->x[0]);
225 3256 : i++;
2385 tgl 226 EUB : }
4177 peter_e 227 GIC 6576 : while ((s = strchr(s, ',')) != NULL)
4177 peter_e 228 ECB : {
2385 tgl 229 GIC 3319 : s++;
121 tgl 230 GNC 3319 : bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
231 3319 : if (SOFT_ERROR_OCCURRED(escontext))
121 tgl 232 UNC 0 : return false;
2385 tgl 233 CBC 3319 : point &= (bp->x[i] == bp->x[i - dim]);
2385 tgl 234 GIC 3319 : i++;
3457 heikki.linnakangas 235 ECB : }
2385 tgl 236 CBC 3257 : Assert(i == dim * 2);
3457 heikki.linnakangas 237 EUB :
3457 heikki.linnakangas 238 GIC 3257 : if (point)
3457 heikki.linnakangas 239 ECB : {
240 : /*
241 : * The value turned out to be a point, ie. all the upper-right
242 : * coordinates were equal to the lower-left coordinates. Resize the
243 : * cube we constructed. Note: we don't bother to repalloc() it
2385 tgl 244 : * smaller, as it's unlikely that the tiny amount of memory freed
245 : * that way would be useful, and the output is always short-lived.
3457 heikki.linnakangas 246 : */
3457 heikki.linnakangas 247 GBC 25 : size = POINT_SIZE(dim);
3457 heikki.linnakangas 248 CBC 25 : SET_VARSIZE(bp, size);
249 25 : SET_POINT_BIT(bp);
250 : }
4177 peter_e 251 ECB :
121 tgl 252 GNC 3257 : *result = bp;
253 3257 : return true;
8154 tgl 254 ECB : }
255 :
256 : static bool
121 tgl 257 GNC 157 : write_point_as_box(int dim, char *str,
258 : NDBOX **result, struct Node *escontext)
259 : {
260 : NDBOX *bp;
261 : int i,
262 : size;
263 : char *s;
2385 tgl 264 ECB : char *endptr;
3457 heikki.linnakangas 265 :
3457 heikki.linnakangas 266 CBC 157 : size = POINT_SIZE(dim);
3457 heikki.linnakangas 267 GIC 157 : bp = palloc0(size);
268 157 : SET_VARSIZE(bp, size);
3457 heikki.linnakangas 269 CBC 157 : SET_DIM(bp, dim);
270 157 : SET_POINT_BIT(bp);
271 :
2385 tgl 272 GIC 157 : s = str;
3457 heikki.linnakangas 273 157 : i = 0;
2385 tgl 274 CBC 157 : if (dim > 0)
275 : {
121 tgl 276 GNC 156 : bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
277 155 : if (SOFT_ERROR_OCCURRED(escontext))
278 2 : return false;
279 : }
3457 heikki.linnakangas 280 GIC 276 : while ((s = strchr(s, ',')) != NULL)
281 : {
2385 tgl 282 122 : s++;
121 tgl 283 GNC 122 : bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
284 122 : if (SOFT_ERROR_OCCURRED(escontext))
121 tgl 285 UNC 0 : return false;
286 : }
2385 tgl 287 GIC 154 : Assert(i == dim);
288 :
121 tgl 289 GNC 154 : *result = bp;
290 154 : return true;
8154 tgl 291 ECB : }
|