Age Owner Branch data 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 : :
2756 tgl@sss.pgh.pa.us 50 :CBC 16 : dim = item_count($2, ',');
51 [ + + ]: 16 : if (item_count($4, ',') != dim)
52 : : {
492 53 [ + - ]: 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)));
4548 peter_e@gmx.net 58 :UBC 0 : YYABORT;
59 : : }
2756 tgl@sss.pgh.pa.us 60 [ - + ]:CBC 14 : if (dim > CUBE_MAX_DIM)
61 : : {
492 tgl@sss.pgh.pa.us 62 [ # # ]:UBC 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)));
4548 peter_e@gmx.net 67 : 0 : YYABORT;
68 : : }
69 : :
492 tgl@sss.pgh.pa.us 70 [ - + ]:CBC 14 : if (!write_box(dim, $2, $4, result, escontext))
492 tgl@sss.pgh.pa.us 71 :UBC 0 : YYABORT;
72 : : }
73 : :
74 : : | paren_list COMMA paren_list
75 : : {
76 : : int dim;
77 : :
2756 tgl@sss.pgh.pa.us 78 :CBC 3246 : dim = item_count($1, ',');
79 [ + + ]: 3246 : if (item_count($3, ',') != dim)
80 : : {
492 81 [ + - ]: 2 : errsave(escontext,
82 : : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
83 : : errmsg("invalid input syntax for cube"),
84 : : errdetail("Different point dimensions in (%s) and (%s).",
85 : : $1, $3)));
4548 peter_e@gmx.net 86 :UBC 0 : YYABORT;
87 : : }
2756 tgl@sss.pgh.pa.us 88 [ + + ]:CBC 3244 : if (dim > CUBE_MAX_DIM)
89 : : {
492 90 [ + - ]: 1 : errsave(escontext,
91 : : (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)));
4548 peter_e@gmx.net 95 :UBC 0 : YYABORT;
96 : : }
97 : :
492 tgl@sss.pgh.pa.us 98 [ - + ]:CBC 3243 : if (!write_box(dim, $1, $3, result, escontext))
492 tgl@sss.pgh.pa.us 99 :UBC 0 : YYABORT;
100 : : }
101 : :
102 : : | paren_list
103 : : {
104 : : int dim;
105 : :
2756 tgl@sss.pgh.pa.us 106 :CBC 69 : dim = item_count($1, ',');
107 [ + + ]: 69 : if (dim > CUBE_MAX_DIM)
108 : : {
492 109 [ + - ]: 1 : errsave(escontext,
110 : : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
111 : : errmsg("invalid input syntax for cube"),
112 : : errdetail("A cube cannot have more than %d dimensions.",
113 : : CUBE_MAX_DIM)));
4548 peter_e@gmx.net 114 :UBC 0 : YYABORT;
115 : : }
116 : :
492 tgl@sss.pgh.pa.us 117 [ - + ]:CBC 68 : if (!write_point_as_box(dim, $1, result, escontext))
492 tgl@sss.pgh.pa.us 118 :UBC 0 : YYABORT;
119 : : }
120 : :
121 : : | list
122 : : {
123 : : int dim;
124 : :
2756 tgl@sss.pgh.pa.us 125 :CBC 89 : dim = item_count($1, ',');
126 [ - + ]: 89 : if (dim > CUBE_MAX_DIM)
127 : : {
492 tgl@sss.pgh.pa.us 128 [ # # ]:UBC 0 : errsave(escontext,
129 : : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
130 : : errmsg("invalid input syntax for cube"),
131 : : errdetail("A cube cannot have more than %d dimensions.",
132 : : CUBE_MAX_DIM)));
4548 peter_e@gmx.net 133 : 0 : YYABORT;
134 : : }
135 : :
492 tgl@sss.pgh.pa.us 136 [ + + ]:CBC 89 : if (!write_point_as_box(dim, $1, result, escontext))
137 : 2 : YYABORT;
138 : : }
139 : : ;
140 : :
141 : : paren_list: O_PAREN list C_PAREN
142 : : {
4548 peter_e@gmx.net 143 : 6596 : $$ = $2;
144 : : }
145 : : | O_PAREN C_PAREN
146 : : {
2756 tgl@sss.pgh.pa.us 147 : 4 : $$ = pstrdup("");
148 : : }
149 : : ;
150 : :
151 : : list: CUBEFLOAT
152 : : {
153 : : /* alloc enough space to be sure whole list will fit */
4548 peter_e@gmx.net 154 : 6691 : $$ = palloc(scanbuflen + 1);
155 : 6691 : strcpy($$, $1);
156 : : }
157 : : | list COMMA CUBEFLOAT
158 : : {
159 : 7368 : $$ = $1;
160 : 7368 : strcat($$, ",");
161 : 7368 : strcat($$, $3);
162 : : }
163 : : ;
164 : :
165 : : %%
166 : :
167 : : /* This assumes the string has been normalized by productions above */
168 : : static int
2756 tgl@sss.pgh.pa.us 169 : 6682 : item_count(const char *s, char delim)
170 : : {
171 : 6682 : int nitems = 0;
172 : :
173 [ + + ]: 6682 : if (s[0] != '\0')
174 : : {
175 : 6679 : nitems++;
176 [ + + ]: 14045 : while ((s = strchr(s, delim)) != NULL)
177 : : {
178 : 7366 : nitems++;
179 : 7366 : s++;
180 : : }
181 : : }
182 : 6682 : return nitems;
183 : : }
184 : :
185 : : static bool
492 186 : 3257 : write_box(int dim, char *str1, char *str2,
187 : : NDBOX **result, struct Node *escontext)
188 : : {
189 : : NDBOX *bp;
190 : : char *s;
191 : : char *endptr;
192 : : int i;
3828 heikki.linnakangas@i 193 : 3257 : int size = CUBE_SIZE(dim);
194 : 3257 : bool point = true;
195 : :
4548 peter_e@gmx.net 196 : 3257 : bp = palloc0(size);
197 : 3257 : SET_VARSIZE(bp, size);
3828 heikki.linnakangas@i 198 : 3257 : SET_DIM(bp, dim);
199 : :
4548 peter_e@gmx.net 200 : 3257 : s = str1;
2756 tgl@sss.pgh.pa.us 201 : 3257 : i = 0;
202 [ + + ]: 3257 : if (dim > 0)
203 : : {
492 204 : 3256 : bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
205 [ - + - - : 3256 : if (SOFT_ERROR_OCCURRED(escontext))
- - ]
492 tgl@sss.pgh.pa.us 206 :UBC 0 : return false;
207 : : }
4548 peter_e@gmx.net 208 [ + + ]:CBC 6576 : while ((s = strchr(s, ',')) != NULL)
209 : : {
2756 tgl@sss.pgh.pa.us 210 : 3319 : s++;
492 211 : 3319 : bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
212 [ - + - - : 3319 : if (SOFT_ERROR_OCCURRED(escontext))
- - ]
492 tgl@sss.pgh.pa.us 213 :UBC 0 : return false;
214 : : }
2756 tgl@sss.pgh.pa.us 215 [ - + ]:CBC 3257 : Assert(i == dim);
216 : :
4548 peter_e@gmx.net 217 : 3257 : s = str2;
2756 tgl@sss.pgh.pa.us 218 [ + + ]: 3257 : if (dim > 0)
219 : : {
492 220 : 3256 : bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
221 [ - + - - : 3256 : if (SOFT_ERROR_OCCURRED(escontext))
- - ]
492 tgl@sss.pgh.pa.us 222 :UBC 0 : return false;
223 : : /* code this way to do right thing with NaN */
2756 tgl@sss.pgh.pa.us 224 :CBC 3256 : point &= (bp->x[i] == bp->x[0]);
225 : 3256 : i++;
226 : : }
4548 peter_e@gmx.net 227 [ + + ]: 6576 : while ((s = strchr(s, ',')) != NULL)
228 : : {
2756 tgl@sss.pgh.pa.us 229 : 3319 : s++;
492 230 : 3319 : bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
231 [ - + - - : 3319 : if (SOFT_ERROR_OCCURRED(escontext))
- - ]
492 tgl@sss.pgh.pa.us 232 :UBC 0 : return false;
2756 tgl@sss.pgh.pa.us 233 :CBC 3319 : point &= (bp->x[i] == bp->x[i - dim]);
234 : 3319 : i++;
235 : : }
236 [ - + ]: 3257 : Assert(i == dim * 2);
237 : :
3828 heikki.linnakangas@i 238 [ + + ]: 3257 : if (point)
239 : : {
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
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.
246 : : */
247 : 25 : size = POINT_SIZE(dim);
248 : 25 : SET_VARSIZE(bp, size);
249 : 25 : SET_POINT_BIT(bp);
250 : : }
251 : :
492 tgl@sss.pgh.pa.us 252 : 3257 : *result = bp;
253 : 3257 : return true;
254 : : }
255 : :
256 : : static bool
257 : 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;
264 : : char *endptr;
265 : :
3828 heikki.linnakangas@i 266 : 157 : size = POINT_SIZE(dim);
267 : 157 : bp = palloc0(size);
268 : 157 : SET_VARSIZE(bp, size);
269 : 157 : SET_DIM(bp, dim);
270 : 157 : SET_POINT_BIT(bp);
271 : :
2756 tgl@sss.pgh.pa.us 272 : 157 : s = str;
3828 heikki.linnakangas@i 273 : 157 : i = 0;
2756 tgl@sss.pgh.pa.us 274 [ + + ]: 157 : if (dim > 0)
275 : : {
492 276 : 156 : bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
277 [ + + + - : 155 : if (SOFT_ERROR_OCCURRED(escontext))
+ + ]
278 : 2 : return false;
279 : : }
3828 heikki.linnakangas@i 280 [ + + ]: 276 : while ((s = strchr(s, ',')) != NULL)
281 : : {
2756 tgl@sss.pgh.pa.us 282 : 122 : s++;
492 283 : 122 : bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
284 [ + + + - : 122 : if (SOFT_ERROR_OCCURRED(escontext))
- + ]
492 tgl@sss.pgh.pa.us 285 :UBC 0 : return false;
286 : : }
2756 tgl@sss.pgh.pa.us 287 [ - + ]:CBC 154 : Assert(i == dim);
288 : :
492 289 : 154 : *result = bp;
290 : 154 : return true;
291 : : }
|