Age Owner Branch data TLA Line data Source code
1 : : %{
2 : : /* contrib/seg/segparse.y */
3 : :
4 : : #include "postgres.h"
5 : :
6 : : #include <float.h>
7 : : #include <math.h>
8 : :
9 : : #include "fmgr.h"
10 : : #include "nodes/miscnodes.h"
11 : : #include "utils/builtins.h"
12 : : #include "utils/float.h"
13 : :
14 : : #include "segdata.h"
15 : :
16 : : /*
17 : : * Bison doesn't allocate anything that needs to live across parser calls,
18 : : * so we can easily have it use palloc instead of malloc. This prevents
19 : : * memory leaks if we error out during parsing.
20 : : */
21 : : #define YYMALLOC palloc
22 : : #define YYFREE pfree
23 : :
24 : : static bool seg_atof(char *value, float *result, struct Node *escontext);
25 : :
26 : : static int sig_digits(const char *value);
27 : :
28 : : static char strbuf[25] = {
29 : : '0', '0', '0', '0', '0',
30 : : '0', '0', '0', '0', '0',
31 : : '0', '0', '0', '0', '0',
32 : : '0', '0', '0', '0', '0',
33 : : '0', '0', '0', '0', '\0'
34 : : };
35 : :
36 : : %}
37 : :
38 : : /* BISON Declarations */
39 : : %parse-param {SEG *result}
40 : : %parse-param {struct Node *escontext}
41 : : %expect 0
42 : : %name-prefix="seg_yy"
43 : :
44 : : %union
45 : : {
46 : : struct BND
47 : : {
48 : : float val;
49 : : char ext;
50 : : char sigd;
51 : : } bnd;
52 : : char *text;
53 : : }
54 : : %token <text> SEGFLOAT
55 : : %token <text> RANGE
56 : : %token <text> PLUMIN
57 : : %token <text> EXTENSION
58 : : %type <bnd> boundary
59 : : %type <bnd> deviation
60 : : %start range
61 : :
62 : : /* Grammar follows */
63 : : %%
64 : :
65 : :
66 : : range: boundary PLUMIN deviation
67 : : {
3912 tgl@sss.pgh.pa.us 68 :CBC 7 : result->lower = $1.val - $3.val;
69 : 7 : result->upper = $1.val + $3.val;
70 : 7 : sprintf(strbuf, "%g", result->lower);
480 71 [ + + ]: 7 : result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
3912 72 : 7 : sprintf(strbuf, "%g", result->upper);
480 73 [ + + ]: 7 : result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
3912 74 : 7 : result->l_ext = '\0';
75 : 7 : result->u_ext = '\0';
76 : : }
77 : :
78 : : | boundary RANGE boundary
79 : : {
80 : 2351 : result->lower = $1.val;
81 : 2351 : result->upper = $3.val;
82 [ - + ]: 2351 : if ( result->lower > result->upper ) {
478 andrew@dunslane.net 83 [ # # ]:UBC 0 : errsave(escontext,
84 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
85 : : errmsg("swapped boundaries: %g is greater than %g",
86 : : result->lower, result->upper)));
87 : :
4548 peter_e@gmx.net 88 : 0 : YYERROR;
89 : : }
3912 tgl@sss.pgh.pa.us 90 :CBC 2351 : result->l_sigd = $1.sigd;
91 : 2351 : result->u_sigd = $3.sigd;
92 : 2351 : result->l_ext = ( $1.ext ? $1.ext : '\0' );
93 : 2351 : result->u_ext = ( $3.ext ? $3.ext : '\0' );
94 : : }
95 : :
96 : : | boundary RANGE
97 : : {
98 : 46 : result->lower = $1.val;
99 : 46 : result->upper = HUGE_VAL;
100 : 46 : result->l_sigd = $1.sigd;
101 : 46 : result->u_sigd = 0;
102 : 46 : result->l_ext = ( $1.ext ? $1.ext : '\0' );
103 : 46 : result->u_ext = '-';
104 : : }
105 : :
106 : : | RANGE boundary
107 : : {
108 : 49 : result->lower = -HUGE_VAL;
109 : 49 : result->upper = $2.val;
110 : 49 : result->l_sigd = 0;
111 : 49 : result->u_sigd = $2.sigd;
112 : 49 : result->l_ext = '-';
113 : 49 : result->u_ext = ( $2.ext ? $2.ext : '\0' );
114 : : }
115 : :
116 : : | boundary
117 : : {
118 : 360 : result->lower = result->upper = $1.val;
119 : 360 : result->l_sigd = result->u_sigd = $1.sigd;
120 : 360 : result->l_ext = result->u_ext = ( $1.ext ? $1.ext : '\0' );
121 : : }
122 : : ;
123 : :
124 : : boundary: SEGFLOAT
125 : : {
126 : : /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
127 : : float val;
128 : :
478 andrew@dunslane.net 129 [ + + ]: 3950 : if (!seg_atof($1, &val, escontext))
130 : 2 : YYABORT;
131 : :
4548 peter_e@gmx.net 132 : 3947 : $$.ext = '\0';
480 tgl@sss.pgh.pa.us 133 : 3947 : $$.sigd = sig_digits($1);
4548 peter_e@gmx.net 134 : 3947 : $$.val = val;
135 : : }
136 : : | EXTENSION SEGFLOAT
137 : : {
138 : : /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
139 : : float val;
140 : :
478 andrew@dunslane.net 141 [ - + ]: 1217 : if (!seg_atof($2, &val, escontext))
478 andrew@dunslane.net 142 :UBC 0 : YYABORT;
143 : :
4548 peter_e@gmx.net 144 :CBC 1217 : $$.ext = $1[0];
480 tgl@sss.pgh.pa.us 145 : 1217 : $$.sigd = sig_digits($2);
4548 peter_e@gmx.net 146 : 1217 : $$.val = val;
147 : : }
148 : : ;
149 : :
150 : : deviation: SEGFLOAT
151 : : {
152 : : /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
153 : : float val;
154 : :
478 andrew@dunslane.net 155 [ - + ]: 7 : if (!seg_atof($1, &val, escontext))
478 andrew@dunslane.net 156 :UBC 0 : YYABORT;
157 : :
4548 peter_e@gmx.net 158 :CBC 7 : $$.ext = '\0';
480 tgl@sss.pgh.pa.us 159 : 7 : $$.sigd = sig_digits($1);
4548 peter_e@gmx.net 160 : 7 : $$.val = val;
161 : : }
162 : : ;
163 : :
164 : : %%
165 : :
166 : :
167 : : static bool
478 andrew@dunslane.net 168 : 5174 : seg_atof(char *value, float *result, struct Node *escontext)
169 : : {
170 : 5174 : *result = float4in_internal(value, NULL, "seg", value, escontext);
171 [ + + + - : 5173 : if (SOFT_ERROR_OCCURRED(escontext))
+ + ]
172 : 2 : return false;
173 : 5171 : return true;
174 : : }
175 : :
176 : : static int
480 tgl@sss.pgh.pa.us 177 : 5187 : sig_digits(const char *value)
178 : : {
179 : 5187 : int n = significant_digits(value);
180 : :
181 : : /* Clamp, to ensure value will fit in sigd fields */
182 : 5187 : return Min(n, FLT_DIG);
183 : : }
|