From 043be9ad9647a0e407f22b7718d632c113953dc8 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 14 Sep 2003 02:18:49 +0000 Subject: [PATCH] Make contrib/seg work with flex 2.5.31. Fix it up to have a real btree operator class, too, since in PG 7.4 you can't GROUP without one. --- contrib/seg/Makefile | 6 +-- contrib/seg/README.seg | 6 --- contrib/seg/buffer.c | 84 ----------------------------------- contrib/seg/buffer.h | 8 ---- contrib/seg/expected/seg.out | 38 +++++++--------- contrib/seg/seg.c | 18 ++++---- contrib/seg/seg.sql.in | 25 ++++++++--- contrib/seg/segparse.y | 36 +-------------- contrib/seg/segscan.l | 86 ++++++++++++++++++++++++++++-------- 9 files changed, 116 insertions(+), 191 deletions(-) delete mode 100644 contrib/seg/buffer.c delete mode 100644 contrib/seg/buffer.h diff --git a/contrib/seg/Makefile b/contrib/seg/Makefile index 2fe7ffb06d8..514a1c4b793 100644 --- a/contrib/seg/Makefile +++ b/contrib/seg/Makefile @@ -1,11 +1,11 @@ -# $Header: /cvsroot/pgsql/contrib/seg/Makefile,v 1.9 2003/05/14 03:27:22 tgl Exp $ +# $Header: /cvsroot/pgsql/contrib/seg/Makefile,v 1.10 2003/09/14 02:18:49 tgl Exp $ subdir = contrib/seg top_builddir = ../.. include $(top_builddir)/src/Makefile.global MODULE_big = seg -OBJS = seg.o segparse.o buffer.o +OBJS = seg.o segparse.o DATA_built = seg.sql DOCS = README.seg REGRESS = seg @@ -27,7 +27,7 @@ endif segscan.c: segscan.l ifdef FLEX - $(FLEX) $(FLEXFLAGS) -Pseg_yy -o'$@' $< + $(FLEX) $(FLEXFLAGS) -o'$@' $< else @$(missing) flex $< $@ endif diff --git a/contrib/seg/README.seg b/contrib/seg/README.seg index 5c80ebcd5c4..99ae8648cda 100644 --- a/contrib/seg/README.seg +++ b/contrib/seg/README.seg @@ -56,12 +56,6 @@ Makefile building instructions for the shared library README.seg the file you are now reading -buffer.c global variables and buffer access utilities - shared between the parser (segparse.y) and the - scanner (segscan.l) - -buffer.h function prototypes for buffer.c - seg.c the implementation of this data type in c seg.sql.in SQL code needed to register this type with postgres diff --git a/contrib/seg/buffer.c b/contrib/seg/buffer.c deleted file mode 100644 index b38e4fcaf24..00000000000 --- a/contrib/seg/buffer.c +++ /dev/null @@ -1,84 +0,0 @@ -/* This module defines the parse buffer and routines for setting/reading it */ - -#include "postgres.h" - -static char *PARSE_BUFFER; -static char *PARSE_BUFFER_PTR; -static unsigned int PARSE_BUFFER_SIZE; -static unsigned int SCANNER_POS; - -void set_parse_buffer(char *s); -void reset_parse_buffer(void); -int read_parse_buffer(void); -char *parse_buffer(void); -char *parse_buffer_ptr(void); -unsigned int parse_buffer_curr_char(void); -unsigned int parse_buffer_size(void); -unsigned int parse_buffer_pos(void); - -extern void seg_flush_scanner_buffer(void); /* defined in segscan.l */ - -void -set_parse_buffer(char *s) -{ - PARSE_BUFFER = s; - PARSE_BUFFER_SIZE = strlen(s); - if (PARSE_BUFFER_SIZE == 0) - ereport(ERROR, - (errcode(ERRCODE_ZERO_LENGTH_CHARACTER_STRING), - errmsg("can't parse an empty string"))); - PARSE_BUFFER_PTR = PARSE_BUFFER; - SCANNER_POS = 0; -} - -void -reset_parse_buffer(void) -{ - PARSE_BUFFER_PTR = PARSE_BUFFER; - SCANNER_POS = 0; - seg_flush_scanner_buffer(); -} - -int -read_parse_buffer(void) -{ - int c; - - /* - * c = *PARSE_BUFFER_PTR++; SCANNER_POS++; - */ - c = PARSE_BUFFER[SCANNER_POS]; - if (SCANNER_POS < PARSE_BUFFER_SIZE) - SCANNER_POS++; - return c; -} - -char * -parse_buffer(void) -{ - return PARSE_BUFFER; -} - -unsigned int -parse_buffer_curr_char(void) -{ - return PARSE_BUFFER[SCANNER_POS]; -} - -char * -parse_buffer_ptr(void) -{ - return PARSE_BUFFER_PTR; -} - -unsigned int -parse_buffer_pos(void) -{ - return SCANNER_POS; -} - -unsigned int -parse_buffer_size(void) -{ - return PARSE_BUFFER_SIZE; -} diff --git a/contrib/seg/buffer.h b/contrib/seg/buffer.h deleted file mode 100644 index eef9124dac5..00000000000 --- a/contrib/seg/buffer.h +++ /dev/null @@ -1,8 +0,0 @@ -extern void set_parse_buffer(char *s); -extern void reset_parse_buffer(void); -extern int read_parse_buffer(void); -extern char *parse_buffer(void); -extern char *parse_buffer_ptr(void); -extern unsigned int parse_buffer_curr_char(void); -extern unsigned int parse_buffer_pos(void); -extern unsigned int parse_buffer_size(void); diff --git a/contrib/seg/expected/seg.out b/contrib/seg/expected/seg.out index 341d174e0d6..cfa8171e681 100644 --- a/contrib/seg/expected/seg.out +++ b/contrib/seg/expected/seg.out @@ -394,35 +394,29 @@ SELECT '100(+-)1'::seg AS seg; -- invalid input SELECT ''::seg AS seg; -ERROR: can't parse an empty string +ERROR: bad seg representation +DETAIL: syntax error at end of input SELECT 'ABC'::seg AS seg; -ERROR: syntax error -DETAIL: syntax error at or near position 1, character ('A', \101), input: 'ABC' - +ERROR: bad seg representation +DETAIL: syntax error at or near "A" SELECT '1ABC'::seg AS seg; -ERROR: syntax error -DETAIL: syntax error at or near position 2, character ('A', \101), input: '1ABC' - +ERROR: bad seg representation +DETAIL: syntax error at or near "A" SELECT '1.'::seg AS seg; -ERROR: syntax error -DETAIL: syntax error at or near position 2, character ('.', \056), input: '1.' - +ERROR: bad seg representation +DETAIL: syntax error at or near "." SELECT '1.....'::seg AS seg; -ERROR: syntax error -DETAIL: syntax error at or near position 6, character ('.', \056), input: '1.....' - +ERROR: bad seg representation +DETAIL: syntax error at or near ".." SELECT '.1'::seg AS seg; -ERROR: syntax error -DETAIL: syntax error at or near position 2, character ('1', \061), input: '.1' - +ERROR: bad seg representation +DETAIL: syntax error at or near "." SELECT '1..2.'::seg AS seg; -ERROR: syntax error -DETAIL: syntax error at or near position 5, character ('.', \056), input: '1..2.' - +ERROR: bad seg representation +DETAIL: syntax error at or near "." SELECT '1 e7'::seg AS seg; -ERROR: syntax error -DETAIL: syntax error at or near position 3, character ('e', \145), input: '1 e7' - +ERROR: bad seg representation +DETAIL: syntax error at or near "e" SELECT '1e700'::seg AS seg; ERROR: syntax error DETAIL: numeric value 1e700 unrepresentable diff --git a/contrib/seg/seg.c b/contrib/seg/seg.c index 443fe3f5a26..c26f9d27cd7 100644 --- a/contrib/seg/seg.c +++ b/contrib/seg/seg.c @@ -23,8 +23,10 @@ #define GIST_QUERY_DEBUG */ -extern void set_parse_buffer(char *str); extern int seg_yyparse(); +extern void seg_yyerror(const char *message); +extern void seg_scanner_init(const char *str); +extern void seg_scanner_finish(void); /* extern int seg_yydebug; @@ -99,16 +101,13 @@ seg_in(char *str) { SEG *result = palloc(sizeof(SEG)); - set_parse_buffer(str); + seg_scanner_init(str); - /* - * seg_yydebug = 1; - */ if (seg_yyparse(result) != 0) - { - pfree(result); - return NULL; - } + seg_yyerror("bogus input"); + + seg_scanner_finish(); + return (result); } @@ -880,7 +879,6 @@ seg_gt(SEG * a, SEG * b) return seg_cmp(a, b) > 0; } - bool seg_ge(SEG * a, SEG * b) { diff --git a/contrib/seg/seg.sql.in b/contrib/seg/seg.sql.in index a1e7e0cf488..2bfd96593dc 100644 --- a/contrib/seg/seg.sql.in +++ b/contrib/seg/seg.sql.in @@ -7,12 +7,12 @@ SET search_path = public; CREATE FUNCTION seg_in(cstring) RETURNS seg AS 'MODULE_PATHNAME' -LANGUAGE 'C'; +LANGUAGE 'C' IMMUTABLE STRICT; CREATE FUNCTION seg_out(seg) RETURNS cstring AS 'MODULE_PATHNAME' -LANGUAGE 'C'; +LANGUAGE 'C' IMMUTABLE STRICT; CREATE TYPE seg ( INTERNALLENGTH = 12, @@ -138,6 +138,13 @@ COMMENT ON FUNCTION seg_different(seg, seg) IS -- support routines for indexing +CREATE OR REPLACE FUNCTION seg_cmp(seg, seg) +RETURNS int4 +AS 'MODULE_PATHNAME' +LANGUAGE 'C' STRICT; + +COMMENT ON FUNCTION seg_cmp(seg, seg) IS 'btree comparison function'; + CREATE FUNCTION seg_union(seg, seg) RETURNS seg AS 'MODULE_PATHNAME' @@ -263,8 +270,7 @@ CREATE OPERATOR = ( NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, - SORT1 = '<', - SORT2 = '<' + MERGES ); CREATE OPERATOR <> ( @@ -333,7 +339,16 @@ AS 'MODULE_PATHNAME' LANGUAGE 'C'; --- Create the operator class for indexing +-- Create the operator classes for indexing + +CREATE OPERATOR CLASS seg_ops + DEFAULT FOR TYPE seg USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 seg_cmp(seg, seg); CREATE OPERATOR CLASS gist_seg_ops DEFAULT FOR TYPE seg USING gist diff --git a/contrib/seg/segparse.y b/contrib/seg/segparse.y index 9c69efede63..d8de4120811 100644 --- a/contrib/seg/segparse.y +++ b/contrib/seg/segparse.y @@ -6,7 +6,6 @@ #include #include "segdata.h" -#include "buffer.h" #ifdef __CYGWIN__ #define HUGE HUGE_VAL @@ -19,7 +18,7 @@ extern int yylex(); /* defined as seg_yylex in segscan.c */ extern int significant_digits( char *str ); /* defined in seg.c */ - int seg_yyerror( char *msg ); + void seg_yyerror(const char *message); int seg_yyparse( void *result ); float seg_atof( char *value ); @@ -72,7 +71,6 @@ range: ((SEG *)result)->lower = $1.val; ((SEG *)result)->upper = $3.val; if ( ((SEG *)result)->lower > ((SEG *)result)->upper ) { - reset_parse_buffer(); ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("swapped boundaries: %g is greater than %g", @@ -145,7 +143,6 @@ float seg_atof ( char *value ) { if ( errno ) { snprintf(buf, 256, "numeric value %s unrepresentable", value); - reset_parse_buffer(); ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error"), @@ -156,35 +153,4 @@ float seg_atof ( char *value ) { } -int seg_yyerror ( char *msg ) { - char *buf = (char *) palloc(256); - int position; - - yyclearin; - - if ( !strcmp(msg, "parse error, expecting `$'") ) { - msg = "expecting end of input"; - } - - position = parse_buffer_pos() > parse_buffer_size() ? parse_buffer_pos() - 1 : parse_buffer_pos(); - - snprintf( - buf, - 256, - "%s at or near position %d, character ('%c', \\%03o), input: '%s'\n", - msg, - position, - parse_buffer()[position - 1], - parse_buffer()[position - 1], - parse_buffer() - ); - - reset_parse_buffer(); - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("syntax error"), - errdetail("%s", buf))); - return 0; -} - #include "segscan.c" diff --git a/contrib/seg/segscan.l b/contrib/seg/segscan.l index 190174d7427..21eb5fa0207 100644 --- a/contrib/seg/segscan.l +++ b/contrib/seg/segscan.l @@ -5,32 +5,29 @@ #include "postgres.h" -#include "buffer.h" +/* No reason to constrain amount of data slurped */ +#define YY_READ_BUF_SIZE 16777216 /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */ #define fprintf(file, fmt, msg) ereport(ERROR, (errmsg_internal("%s", msg))) +/* Handles to the buffer that the lexer uses internally */ +static YY_BUFFER_STATE scanbufhandle; +static char *scanbuf; +static int scanbuflen; -/* flex screws a couple symbols when used with the -P option; fix those */ -#define YY_DECL int seg_yylex YY_PROTO(( void )); \ -int seg_yylex YY_PROTO(( void )) -#define yylval seg_yylval +/* flex 2.5.4 doesn't bother with a decl for this */ +int seg_yylex(void); -/* redefined YY_INPUT reads byte-wise from the memory area defined in buffer.c */ -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ -{ \ - int c = read_parse_buffer(); \ - result = (c == '\0') ? YY_NULL : (buf[0] = c, 1); \ -} - -void seg_flush_scanner_buffer(void); +void seg_scanner_init(const char *str); +void seg_scanner_finish(void); %} %option 8bit %option never-interactive %option nounput %option noyywrap +%option prefix="seg_yy" range (\.\.)(\.)? @@ -52,8 +49,61 @@ float ({integer}|{real})([eE]{integer})? %% -int seg_yylex(); - -void seg_flush_scanner_buffer(void) { - YY_FLUSH_BUFFER; +void +yyerror(const char *message) +{ + if (*yytext == YY_END_OF_BUFFER_CHAR) + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("bad seg representation"), + /* translator: %s is typically "syntax error" */ + errdetail("%s at end of input", message))); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("bad seg representation"), + /* translator: first %s is typically "syntax error" */ + errdetail("%s at or near \"%s\"", message, yytext))); + } +} + + +/* + * Called before any actual parsing is done + */ +void +seg_scanner_init(const char *str) +{ + Size slen = strlen(str); + + /* + * Might be left over after ereport() + */ + if (YY_CURRENT_BUFFER) + yy_delete_buffer(YY_CURRENT_BUFFER); + + /* + * Make a scan buffer with special termination needed by flex. + */ + scanbuflen = slen; + scanbuf = palloc(slen + 2); + memcpy(scanbuf, str, slen); + scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; + scanbufhandle = yy_scan_buffer(scanbuf, slen + 2); + + BEGIN(INITIAL); +} + + +/* + * Called after parsing is done to clean up after seg_scanner_init() + */ +void +seg_scanner_finish(void) +{ + yy_delete_buffer(scanbufhandle); + pfree(scanbuf); }