btree operator class, too, since in PG 7.4 you can't GROUP without one.
-# $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
segscan.c: segscan.l
ifdef FLEX
- $(FLEX) $(FLEXFLAGS) -Pseg_yy -o'$@' $<
+ $(FLEX) $(FLEXFLAGS) -o'$@' $<
else
@$(missing) flex $< $@
endif
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
+++ /dev/null
-/* 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;
-}
+++ /dev/null
-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);
-- 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
#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;
{
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);
}
return seg_cmp(a, b) > 0;
}
-
bool
seg_ge(SEG * a, SEG * b)
{
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,
-- 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'
NEGATOR = '<>',
RESTRICT = eqsel,
JOIN = eqjoinsel,
- SORT1 = '<',
- SORT2 = '<'
+ MERGES
);
CREATE OPERATOR <> (
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
#include <math.h>
#include "segdata.h"
-#include "buffer.h"
#ifdef __CYGWIN__
#define HUGE HUGE_VAL
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 );
((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",
if ( errno ) {
snprintf(buf, 256, "numeric value %s unrepresentable", value);
- reset_parse_buffer();
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("syntax error"),
}
-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"
#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 (\.\.)(\.)?
%%
-int seg_yylex();
+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);
+}
+
-void seg_flush_scanner_buffer(void) {
- YY_FLUSH_BUFFER;
+/*
+ * Called after parsing is done to clean up after seg_scanner_init()
+ */
+void
+seg_scanner_finish(void)
+{
+ yy_delete_buffer(scanbufhandle);
+ pfree(scanbuf);
}