Commit 45c00246 authored by Tom Lane's avatar Tom Lane

Remove fixed-size literal buffer from ecpg's lexer (same

fix recently applied to backend's lexer).  I see that YY_USES_REJECT
still gets defined for this lexer, which means it's going to have trouble
parsing really long tokens.  Not sure if it's worth doing anything about
that or not; I don't have the interest right now to understand why
ecpg's additions to the syntax cause this problem...
parent abceb20a
...@@ -15,11 +15,19 @@ OBJ=preproc.o pgc.o type.o ecpg.o ecpg_keywords.o \ ...@@ -15,11 +15,19 @@ OBJ=preproc.o pgc.o type.o ecpg.o ecpg_keywords.o \
all:: ecpg all:: ecpg
# Rule that really do something.
ecpg: $(OBJ)
$(CC) -o ecpg $(OBJ) $(LEXLIB) $(LDFLAGS)
preproc.c preproc.h: preproc.y preproc.c preproc.h: preproc.y
$(YACC) $(YFLAGS) $< $(YACC) $(YFLAGS) $<
mv y.tab.c preproc.c mv y.tab.c preproc.c
mv y.tab.h preproc.h mv y.tab.h preproc.h
pgc.c: pgc.l
$(LEX) $<
mv lex.yy.c pgc.c
clean: clean:
rm -f *.o core a.out ecpg$(X) *~ *.output rm -f *.o core a.out ecpg$(X) *~ *.output
# And the garbage that might have been left behind by partial build: # And the garbage that might have been left behind by partial build:
...@@ -33,19 +41,9 @@ install: all ...@@ -33,19 +41,9 @@ install: all
uninstall: uninstall:
rm -f $(BINDIR)/ecpg rm -f $(BINDIR)/ecpg
# Rule that really do something. preproc.o: preproc.h ../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c
ecpg: $(OBJ) type.o: ../include/ecpgtype.h
$(CC) -o ecpg $(OBJ) $(LEXLIB) $(LDFLAGS) pgc.o: ../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c preproc.h
pgc.c: pgc.l
$(LEX) $<
sed -e 's/#define YY_BUF_SIZE .*/#define YY_BUF_SIZE 65536/' \
<lex.yy.c >pgc.c
rm -f lex.yy.c
preproc.o : preproc.h ../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c
type.o : ../include/ecpgtype.h
pgc.o : ../include/ecpgtype.h keywords.c c_keywords.c ecpg_keywords.c preproc.h
keywords.o: ../include/ecpgtype.h preproc.h keywords.o: ../include/ecpgtype.h preproc.h
c_keywords.o: ../include/ecpgtype.h preproc.h c_keywords.o: ../include/ecpgtype.h preproc.h
ecpg_keywords.o: ../include/ecpgtype.h preproc.h ecpg_keywords.o: ../include/ecpgtype.h preproc.h
......
/* This is a modified version of src/backend/parser/scan.l */
%{ %{
/*-------------------------------------------------------------------------
*
* pgc.l
* lexical scanner for ecpg
*
* This is a modified version of src/backend/parser/scan.l
*
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.45 1999/10/22 23:14:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include <ctype.h> #include <ctype.h>
#include <sys/types.h> #include <sys/types.h>
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#include "postgres.h" #include "postgres.h"
#ifndef PATH_MAX #ifndef PATH_MAX
#include <sys/param.h> #include <sys/param.h>
#define PATH_MAX MAXPATHLEN #define PATH_MAX MAXPATHLEN
#endif #endif
#include "miscadmin.h" #include "miscadmin.h"
#include "nodes/pg_list.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "nodes/pg_list.h"
#include "parser/gramparse.h" #include "parser/gramparse.h"
#include "parser/scansup.h" #include "parser/scansup.h"
#include "extern.h" #include "extern.h"
#include "preproc.h" #include "preproc.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#ifdef YY_READ_BUF_SIZE
#undef YY_READ_BUF_SIZE
#endif
#define YY_READ_BUF_SIZE MAX_PARSE_BUFFER
/* some versions of lex define this as a macro */ /* some versions of lex define this as a macro */
#if defined(yywrap) #if defined(yywrap)
#undef yywrap #undef yywrap
#endif /* yywrap */ #endif /* yywrap */
extern YYSTYPE yylval; extern YYSTYPE yylval;
int llen;
char literal[MAX_PARSE_BUFFER]; /*
* literalbuf is used to accumulate literal values when multiple rules
* are needed to parse a single literal. Call startlit to reset buffer
* to empty, addlit to add text. Note that the buffer is permanently
* malloc'd to the largest size needed so far in the current run.
*/
static char *literalbuf = NULL; /* expandable buffer */
static int literallen; /* actual current length */
static int literalalloc; /* current allocated buffer size */
#define startlit() (literalbuf[0] = '\0', literallen = 0)
static void addlit(char *ytext, int yleng);
int before_comment; int before_comment;
struct _yy_buffer { YY_BUFFER_STATE buffer; struct _yy_buffer { YY_BUFFER_STATE buffer;
...@@ -142,16 +165,14 @@ self [,()\[\].;$\:\+\-\*\/\%\^\<\>\=\|] ...@@ -142,16 +165,14 @@ self [,()\[\].;$\:\+\-\*\/\%\^\<\>\=\|]
op_and_self [\~\!\@\#\^\&\|\`\?\$\:\+\-\*\/\%\<\>\=] op_and_self [\~\!\@\#\^\&\|\`\?\$\:\+\-\*\/\%\<\>\=]
operator {op_and_self}+ operator {op_and_self}+
/* we do not allow unary minus in numbers. /* we no longer allow unary minus in numbers.
* instead we pass it verbatim to parser. there it gets * instead we pass it separately to parser. there it gets
* coerced via doNegate() -- Leon aug 20 1999 * coerced via doNegate() -- Leon aug 20 1999
*/ */
integer {digit}+ integer {digit}+
decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*)) decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*))
real ((({digit}*\.{digit}+)|({digit}+\.{digit}*)|({digit}+))([Ee][-+]?{digit}+)) real ((({digit}*\.{digit}+)|({digit}+\.{digit}*)|({digit}+))([Ee][-+]?{digit}+))
/*
real (((({digit}*\.{digit}+)|({digit}+\.{digit}*))([Ee][-+]?{digit}+)?)|({digit}+[Ee][-+]?{digit}+))
*/
param \${integer} param \${integer}
...@@ -200,25 +221,21 @@ cppline {space}*#.*(\\{space}*\n)*\n* ...@@ -200,25 +221,21 @@ cppline {space}*#.*(\\{space}*\n)*\n*
<SQL>{xbstart} { <SQL>{xbstart} {
BEGIN(xb); BEGIN(xb);
llen = 0; startlit();
*literal = '\0';
} }
<xb>{xbstop} { <xb>{xbstop} {
char* endptr; char* endptr;
BEGIN(SQL); BEGIN(SQL);
errno = 0; errno = 0;
yylval.ival = strtol((char *)literal,&endptr,2); yylval.ival = strtol(literalbuf, &endptr, 2);
if (*endptr != '\0' || errno == ERANGE) if (*endptr != '\0' || errno == ERANGE)
yyerror("ERROR: Bad binary integer input!"); yyerror("ERROR: Bad binary integer input!");
return ICONST; return ICONST;
} }
<xh>{xhinside} | <xh>{xhinside} |
<xb>{xbinside} { <xb>{xbinside} {
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1)) addlit(yytext, yyleng);
yyerror("ERROR: quoted string parse buffer exceeded");
memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng;
} }
<xh>{xhcat} | <xh>{xhcat} |
<xb>{xbcat} { <xb>{xbcat} {
...@@ -226,15 +243,14 @@ cppline {space}*#.*(\\{space}*\n)*\n* ...@@ -226,15 +243,14 @@ cppline {space}*#.*(\\{space}*\n)*\n*
<SQL>{xhstart} { <SQL>{xhstart} {
BEGIN(xh); BEGIN(xh);
llen = 0; startlit();
*literal = '\0';
} }
<xh>{xhstop} { <xh>{xhstop} {
char* endptr; char* endptr;
BEGIN(SQL); BEGIN(SQL);
errno = 0; errno = 0;
yylval.ival = strtol((char *)literal,&endptr,16); yylval.ival = strtol(literalbuf, &endptr, 16);
if (*endptr != '\0' || errno == ERANGE) if (*endptr != '\0' || errno == ERANGE)
yyerror("ERROR: Bad hexadecimal integer input"); yyerror("ERROR: Bad hexadecimal integer input");
return ICONST; return ICONST;
...@@ -242,21 +258,17 @@ cppline {space}*#.*(\\{space}*\n)*\n* ...@@ -242,21 +258,17 @@ cppline {space}*#.*(\\{space}*\n)*\n*
<SQL>{xqstart} { <SQL>{xqstart} {
BEGIN(xq); BEGIN(xq);
llen = 0; startlit();
*literal = '\0';
} }
<xq>{xqstop} { <xq>{xqstop} {
BEGIN(SQL); BEGIN(SQL);
yylval.str = mm_strdup(literal); yylval.str = mm_strdup(literalbuf);
return SCONST; return SCONST;
} }
<xq>{xqdouble} | <xq>{xqdouble} |
<xq>{xqinside} | <xq>{xqinside} |
<xq>{xqliteral} { <xq>{xqliteral} {
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1)) addlit(yytext, yyleng);
yyerror("ERROR: quoted string parse buffer exceeded");
memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng;
} }
<xq>{xqcat} { <xq>{xqcat} {
} }
...@@ -264,35 +276,27 @@ cppline {space}*#.*(\\{space}*\n)*\n* ...@@ -264,35 +276,27 @@ cppline {space}*#.*(\\{space}*\n)*\n*
<SQL>{xdstart} { <SQL>{xdstart} {
BEGIN(xd); BEGIN(xd);
llen = 0; startlit();
*literal = '\0';
} }
<xd>{xdstop} { <xd>{xdstop} {
BEGIN(SQL); BEGIN(SQL);
yylval.str = mm_strdup(literal); yylval.str = mm_strdup(literalbuf);
return CSTRING; return CSTRING;
} }
<xd>{xdinside} { <xd>{xdinside} {
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1)) addlit(yytext, yyleng);
yyerror("ERROR: quoted string parse buffer exceeded");
memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng;
} }
{xdstart} { {xdstart} {
BEGIN(xdc); BEGIN(xdc);
llen = 0; startlit();
*literal = '\0';
} }
<xdc>{xdstop} { <xdc>{xdstop} {
BEGIN(C); BEGIN(C);
yylval.str = mm_strdup(literal); yylval.str = mm_strdup(literalbuf);
return CSTRING; return CSTRING;
} }
<xdc>{xdcinside} { <xdc>{xdcinside} {
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1)) addlit(yytext, yyleng);
yyerror("ERROR: quoted string parse buffer exceeded");
memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng;
} }
<SQL>{typecast} { return TYPECAST; } <SQL>{typecast} { return TYPECAST; }
<SQL>{self} { /* <SQL>{self} { /*
...@@ -486,8 +490,7 @@ cppline {space}*#.*(\\{space}*\n)*\n* ...@@ -486,8 +490,7 @@ cppline {space}*#.*(\\{space}*\n)*\n*
<def_ident>{identifier} { <def_ident>{identifier} {
old = mm_strdup(yytext); old = mm_strdup(yytext);
BEGIN(def); BEGIN(def);
llen = 0; startlit();
*literal = '\0';
} }
<def>{space} /* eat the whitespace */ <def>{space} /* eat the whitespace */
<def>";" { <def>";" {
...@@ -498,8 +501,8 @@ cppline {space}*#.*(\\{space}*\n)*\n* ...@@ -498,8 +501,8 @@ cppline {space}*#.*(\\{space}*\n)*\n*
if (strcmp(old, ptr->old) == 0) if (strcmp(old, ptr->old) == 0)
{ {
free(ptr->new); free(ptr->new);
/* ptr->new = mm_strdup(scanstr(literal));*/ /* ptr->new = mm_strdup(scanstr(literalbuf));*/
ptr->new = mm_strdup(literal); ptr->new = mm_strdup(literalbuf);
} }
} }
if (ptr == NULL) if (ptr == NULL)
...@@ -508,8 +511,8 @@ cppline {space}*#.*(\\{space}*\n)*\n* ...@@ -508,8 +511,8 @@ cppline {space}*#.*(\\{space}*\n)*\n*
/* initial definition */ /* initial definition */
this->old = old; this->old = old;
/* this->new = mm_strdup(scanstr(literal));*/ /* this->new = mm_strdup(scanstr(literalbuf));*/
this->new = mm_strdup(literal); this->new = mm_strdup(literalbuf);
this->next = defines; this->next = defines;
defines = this; defines = this;
} }
...@@ -517,10 +520,7 @@ cppline {space}*#.*(\\{space}*\n)*\n* ...@@ -517,10 +520,7 @@ cppline {space}*#.*(\\{space}*\n)*\n*
BEGIN(C); BEGIN(C);
} }
<def>[^";"] { <def>[^";"] {
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1)) addlit(yytext, yyleng);
yyerror("ERROR: define statement parse buffer exceeded");
memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng;
} }
<C>{exec}{space}{sql}{space}{include} { BEGIN(incl); } <C>{exec}{space}{sql}{space}{include} { BEGIN(incl); }
<incl>{space} /* eat the whitespace */ <incl>{space} /* eat the whitespace */
...@@ -602,9 +602,34 @@ void ...@@ -602,9 +602,34 @@ void
lex_init(void) lex_init(void)
{ {
braces_open = 0; braces_open = 0;
/* initialize literal buffer to a reasonable but expansible size */
if (literalbuf == NULL)
{
literalalloc = 128;
literalbuf = (char *) malloc(literalalloc);
}
startlit();
BEGIN C; BEGIN C;
} }
static void
addlit(char *ytext, int yleng)
{
/* enlarge buffer if needed */
if ((literallen+yleng) >= literalalloc)
{
do {
literalalloc *= 2;
} while ((literallen+yleng) >= literalalloc);
literalbuf = (char *) realloc(literalbuf, literalalloc);
}
/* append data --- note we assume ytext is null-terminated */
memcpy(literalbuf+literallen, ytext, yleng+1);
literallen += yleng;
}
int yywrap(void) int yywrap(void)
{ {
return 1; return 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment