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