diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 13:44:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 13:44:03 +0000 |
commit | 293913568e6a7a86fd1479e1cff8e2ecb58d6568 (patch) | |
tree | fc3b469a3ec5ab71b36ea97cc7aaddb838423a0c /contrib/seg/segparse.y | |
parent | Initial commit. (diff) | |
download | postgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.tar.xz postgresql-16-293913568e6a7a86fd1479e1cff8e2ecb58d6568.zip |
Adding upstream version 16.2.upstream/16.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'contrib/seg/segparse.y')
-rw-r--r-- | contrib/seg/segparse.y | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/contrib/seg/segparse.y b/contrib/seg/segparse.y new file mode 100644 index 0000000..bf759db --- /dev/null +++ b/contrib/seg/segparse.y @@ -0,0 +1,183 @@ +%{ +/* contrib/seg/segparse.y */ + +#include "postgres.h" + +#include <float.h> +#include <math.h> + +#include "fmgr.h" +#include "nodes/miscnodes.h" +#include "utils/builtins.h" +#include "utils/float.h" + +#include "segdata.h" + +/* + * Bison doesn't allocate anything that needs to live across parser calls, + * so we can easily have it use palloc instead of malloc. This prevents + * memory leaks if we error out during parsing. + */ +#define YYMALLOC palloc +#define YYFREE pfree + +static bool seg_atof(char *value, float *result, struct Node *escontext); + +static int sig_digits(const char *value); + +static char strbuf[25] = { + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '0', + '0', '0', '0', '0', '\0' +}; + +%} + +/* BISON Declarations */ +%parse-param {SEG *result} +%parse-param {struct Node *escontext} +%expect 0 +%name-prefix="seg_yy" + +%union +{ + struct BND + { + float val; + char ext; + char sigd; + } bnd; + char *text; +} +%token <text> SEGFLOAT +%token <text> RANGE +%token <text> PLUMIN +%token <text> EXTENSION +%type <bnd> boundary +%type <bnd> deviation +%start range + +/* Grammar follows */ +%% + + +range: boundary PLUMIN deviation + { + result->lower = $1.val - $3.val; + result->upper = $1.val + $3.val; + sprintf(strbuf, "%g", result->lower); + result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd)); + sprintf(strbuf, "%g", result->upper); + result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd)); + result->l_ext = '\0'; + result->u_ext = '\0'; + } + + | boundary RANGE boundary + { + result->lower = $1.val; + result->upper = $3.val; + if ( result->lower > result->upper ) { + errsave(escontext, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("swapped boundaries: %g is greater than %g", + result->lower, result->upper))); + + YYERROR; + } + result->l_sigd = $1.sigd; + result->u_sigd = $3.sigd; + result->l_ext = ( $1.ext ? $1.ext : '\0' ); + result->u_ext = ( $3.ext ? $3.ext : '\0' ); + } + + | boundary RANGE + { + result->lower = $1.val; + result->upper = HUGE_VAL; + result->l_sigd = $1.sigd; + result->u_sigd = 0; + result->l_ext = ( $1.ext ? $1.ext : '\0' ); + result->u_ext = '-'; + } + + | RANGE boundary + { + result->lower = -HUGE_VAL; + result->upper = $2.val; + result->l_sigd = 0; + result->u_sigd = $2.sigd; + result->l_ext = '-'; + result->u_ext = ( $2.ext ? $2.ext : '\0' ); + } + + | boundary + { + result->lower = result->upper = $1.val; + result->l_sigd = result->u_sigd = $1.sigd; + result->l_ext = result->u_ext = ( $1.ext ? $1.ext : '\0' ); + } + ; + +boundary: SEGFLOAT + { + /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ + float val; + + if (!seg_atof($1, &val, escontext)) + YYABORT; + + $$.ext = '\0'; + $$.sigd = sig_digits($1); + $$.val = val; + } + | EXTENSION SEGFLOAT + { + /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ + float val; + + if (!seg_atof($2, &val, escontext)) + YYABORT; + + $$.ext = $1[0]; + $$.sigd = sig_digits($2); + $$.val = val; + } + ; + +deviation: SEGFLOAT + { + /* temp variable avoids a gcc 3.3.x bug on Sparc64 */ + float val; + + if (!seg_atof($1, &val, escontext)) + YYABORT; + + $$.ext = '\0'; + $$.sigd = sig_digits($1); + $$.val = val; + } + ; + +%% + + +static bool +seg_atof(char *value, float *result, struct Node *escontext) +{ + *result = float4in_internal(value, NULL, "seg", value, escontext); + if (SOFT_ERROR_OCCURRED(escontext)) + return false; + return true; +} + +static int +sig_digits(const char *value) +{ + int n = significant_digits(value); + + /* Clamp, to ensure value will fit in sigd fields */ + return Min(n, FLT_DIG); +} |