mirror of
https://github.com/postgres/postgres.git
synced 2025-07-24 14:22:24 +03:00
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
296 lines
6.0 KiB
Plaintext
296 lines
6.0 KiB
Plaintext
%{
|
|
/* contrib/cube/cubeparse.y */
|
|
|
|
/* NdBox = [(lowerleft),(upperright)] */
|
|
/* [(xLL(1)...xLL(N)),(xUR(1)...xUR(n))] */
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "cubedata.h"
|
|
#include "nodes/miscnodes.h"
|
|
#include "utils/float.h"
|
|
#include "varatt.h"
|
|
|
|
/* silence -Wmissing-variable-declarations */
|
|
extern int cube_yychar;
|
|
extern int cube_yynerrs;
|
|
|
|
/* All grammar constructs return strings */
|
|
#define YYSTYPE char *
|
|
|
|
/*
|
|
* 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 int item_count(const char *s, char delim);
|
|
static bool write_box(int dim, char *str1, char *str2,
|
|
NDBOX **result, struct Node *escontext);
|
|
static bool write_point_as_box(int dim, char *str,
|
|
NDBOX **result, struct Node *escontext);
|
|
|
|
%}
|
|
|
|
/* BISON Declarations */
|
|
%parse-param {NDBOX **result}
|
|
%parse-param {Size scanbuflen}
|
|
%parse-param {struct Node *escontext}
|
|
%expect 0
|
|
%name-prefix="cube_yy"
|
|
|
|
%token CUBEFLOAT O_PAREN C_PAREN O_BRACKET C_BRACKET COMMA
|
|
%start box
|
|
|
|
/* Grammar follows */
|
|
%%
|
|
|
|
box: O_BRACKET paren_list COMMA paren_list C_BRACKET
|
|
{
|
|
int dim;
|
|
|
|
dim = item_count($2, ',');
|
|
if (item_count($4, ',') != dim)
|
|
{
|
|
errsave(escontext,
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
errmsg("invalid input syntax for cube"),
|
|
errdetail("Different point dimensions in (%s) and (%s).",
|
|
$2, $4)));
|
|
YYABORT;
|
|
}
|
|
if (dim > CUBE_MAX_DIM)
|
|
{
|
|
errsave(escontext,
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
errmsg("invalid input syntax for cube"),
|
|
errdetail("A cube cannot have more than %d dimensions.",
|
|
CUBE_MAX_DIM)));
|
|
YYABORT;
|
|
}
|
|
|
|
if (!write_box(dim, $2, $4, result, escontext))
|
|
YYABORT;
|
|
}
|
|
|
|
| paren_list COMMA paren_list
|
|
{
|
|
int dim;
|
|
|
|
dim = item_count($1, ',');
|
|
if (item_count($3, ',') != dim)
|
|
{
|
|
errsave(escontext,
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
errmsg("invalid input syntax for cube"),
|
|
errdetail("Different point dimensions in (%s) and (%s).",
|
|
$1, $3)));
|
|
YYABORT;
|
|
}
|
|
if (dim > CUBE_MAX_DIM)
|
|
{
|
|
errsave(escontext,
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
errmsg("invalid input syntax for cube"),
|
|
errdetail("A cube cannot have more than %d dimensions.",
|
|
CUBE_MAX_DIM)));
|
|
YYABORT;
|
|
}
|
|
|
|
if (!write_box(dim, $1, $3, result, escontext))
|
|
YYABORT;
|
|
}
|
|
|
|
| paren_list
|
|
{
|
|
int dim;
|
|
|
|
dim = item_count($1, ',');
|
|
if (dim > CUBE_MAX_DIM)
|
|
{
|
|
errsave(escontext,
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
errmsg("invalid input syntax for cube"),
|
|
errdetail("A cube cannot have more than %d dimensions.",
|
|
CUBE_MAX_DIM)));
|
|
YYABORT;
|
|
}
|
|
|
|
if (!write_point_as_box(dim, $1, result, escontext))
|
|
YYABORT;
|
|
}
|
|
|
|
| list
|
|
{
|
|
int dim;
|
|
|
|
dim = item_count($1, ',');
|
|
if (dim > CUBE_MAX_DIM)
|
|
{
|
|
errsave(escontext,
|
|
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
|
|
errmsg("invalid input syntax for cube"),
|
|
errdetail("A cube cannot have more than %d dimensions.",
|
|
CUBE_MAX_DIM)));
|
|
YYABORT;
|
|
}
|
|
|
|
if (!write_point_as_box(dim, $1, result, escontext))
|
|
YYABORT;
|
|
}
|
|
;
|
|
|
|
paren_list: O_PAREN list C_PAREN
|
|
{
|
|
$$ = $2;
|
|
}
|
|
| O_PAREN C_PAREN
|
|
{
|
|
$$ = pstrdup("");
|
|
}
|
|
;
|
|
|
|
list: CUBEFLOAT
|
|
{
|
|
/* alloc enough space to be sure whole list will fit */
|
|
$$ = palloc(scanbuflen + 1);
|
|
strcpy($$, $1);
|
|
}
|
|
| list COMMA CUBEFLOAT
|
|
{
|
|
$$ = $1;
|
|
strcat($$, ",");
|
|
strcat($$, $3);
|
|
}
|
|
;
|
|
|
|
%%
|
|
|
|
/* This assumes the string has been normalized by productions above */
|
|
static int
|
|
item_count(const char *s, char delim)
|
|
{
|
|
int nitems = 0;
|
|
|
|
if (s[0] != '\0')
|
|
{
|
|
nitems++;
|
|
while ((s = strchr(s, delim)) != NULL)
|
|
{
|
|
nitems++;
|
|
s++;
|
|
}
|
|
}
|
|
return nitems;
|
|
}
|
|
|
|
static bool
|
|
write_box(int dim, char *str1, char *str2,
|
|
NDBOX **result, struct Node *escontext)
|
|
{
|
|
NDBOX *bp;
|
|
char *s;
|
|
char *endptr;
|
|
int i;
|
|
int size = CUBE_SIZE(dim);
|
|
bool point = true;
|
|
|
|
bp = palloc0(size);
|
|
SET_VARSIZE(bp, size);
|
|
SET_DIM(bp, dim);
|
|
|
|
s = str1;
|
|
i = 0;
|
|
if (dim > 0)
|
|
{
|
|
bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
|
|
if (SOFT_ERROR_OCCURRED(escontext))
|
|
return false;
|
|
}
|
|
while ((s = strchr(s, ',')) != NULL)
|
|
{
|
|
s++;
|
|
bp->x[i++] = float8in_internal(s, &endptr, "cube", str1, escontext);
|
|
if (SOFT_ERROR_OCCURRED(escontext))
|
|
return false;
|
|
}
|
|
Assert(i == dim);
|
|
|
|
s = str2;
|
|
if (dim > 0)
|
|
{
|
|
bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
|
|
if (SOFT_ERROR_OCCURRED(escontext))
|
|
return false;
|
|
/* code this way to do right thing with NaN */
|
|
point &= (bp->x[i] == bp->x[0]);
|
|
i++;
|
|
}
|
|
while ((s = strchr(s, ',')) != NULL)
|
|
{
|
|
s++;
|
|
bp->x[i] = float8in_internal(s, &endptr, "cube", str2, escontext);
|
|
if (SOFT_ERROR_OCCURRED(escontext))
|
|
return false;
|
|
point &= (bp->x[i] == bp->x[i - dim]);
|
|
i++;
|
|
}
|
|
Assert(i == dim * 2);
|
|
|
|
if (point)
|
|
{
|
|
/*
|
|
* The value turned out to be a point, ie. all the upper-right
|
|
* coordinates were equal to the lower-left coordinates. Resize the
|
|
* cube we constructed. Note: we don't bother to repalloc() it
|
|
* smaller, as it's unlikely that the tiny amount of memory freed
|
|
* that way would be useful, and the output is always short-lived.
|
|
*/
|
|
size = POINT_SIZE(dim);
|
|
SET_VARSIZE(bp, size);
|
|
SET_POINT_BIT(bp);
|
|
}
|
|
|
|
*result = bp;
|
|
return true;
|
|
}
|
|
|
|
static bool
|
|
write_point_as_box(int dim, char *str,
|
|
NDBOX **result, struct Node *escontext)
|
|
{
|
|
NDBOX *bp;
|
|
int i,
|
|
size;
|
|
char *s;
|
|
char *endptr;
|
|
|
|
size = POINT_SIZE(dim);
|
|
bp = palloc0(size);
|
|
SET_VARSIZE(bp, size);
|
|
SET_DIM(bp, dim);
|
|
SET_POINT_BIT(bp);
|
|
|
|
s = str;
|
|
i = 0;
|
|
if (dim > 0)
|
|
{
|
|
bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
|
|
if (SOFT_ERROR_OCCURRED(escontext))
|
|
return false;
|
|
}
|
|
while ((s = strchr(s, ',')) != NULL)
|
|
{
|
|
s++;
|
|
bp->x[i++] = float8in_internal(s, &endptr, "cube", str, escontext);
|
|
if (SOFT_ERROR_OCCURRED(escontext))
|
|
return false;
|
|
}
|
|
Assert(i == dim);
|
|
|
|
*result = bp;
|
|
return true;
|
|
}
|