postgres/contrib/seg/segparse.y
Peter Eisentraut ab61c40bfa Add extern declarations for Bison global variables
This adds extern declarations for some global variables produced by
Bison that are not already declared in its generated header file.
This is a workaround to be able to add -Wmissing-variable-declarations
to the global set of warning options in the near future.

Another longer-term solution would be to convert these grammars to
"pure" parsers in Bison, to avoid global variables altogether.  Note
that the core grammar is already pure, so this patch did not need to
touch it.

Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://www.postgresql.org/message-id/flat/e0a62134-83da-4ba4-8cdb-ceb0111c95ce@eisentraut.org
2024-07-25 09:26:08 +02:00

188 lines
3.6 KiB
Plaintext

%{
/* 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"
/* silence -Wmissing-variable-declarations */
extern int seg_yychar;
extern int seg_yynerrs;
/*
* 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);
}