#
# Makefile for parser
#
-# $Header: /cvsroot/pgsql/src/backend/parser/Makefile,v 1.36 2002/03/08 07:12:11 tgl Exp $
+# $Header: /cvsroot/pgsql/src/backend/parser/Makefile,v 1.37 2002/04/20 21:56:14 petere Exp $
#
#-------------------------------------------------------------------------
parse_expr.o parse_func.o parse_node.o parse_oper.o parse_relation.o \
parse_type.o parse_coerce.o parse_target.o scan.o scansup.o
+FLEXFLAGS = -CF
+
all: SUBSYS.o
$(srcdir)/scan.c: scan.l
ifdef FLEX
- $(FLEX) $(FLEXFLAGS) -Pbase_yy -o'$@' $<
+ $(FLEX) $(FLEXFLAGS) -o'$@' $<
else
@$(missing) flex $< $@
endif
rm -f SUBSYS.o $(OBJS)
# And the garbage that might have been left behind by partial build:
@rm -f y.tab.c y.tab.h lex.yy.c
-
-
-# This is unusual: We actually have to build some of the parts before
-# we know what the header file dependencies are.
-dep depend: gram.c scan.c
- $(CC) -MM $(CFLAGS) *.c >depend
-
-ifeq (depend,$(wildcard depend))
-include depend
-endif
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.39 2002/03/30 01:02:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.40 2002/04/20 21:56:14 petere Exp $
*
*-------------------------------------------------------------------------
*/
void
parseTypeString(const char *str, Oid *type_id, int32 *typmod)
{
- char *buf;
+ StringInfoData buf;
List *raw_parsetree_list;
SelectStmt *stmt;
ResTarget *restarget;
A_Const *aconst;
TypeName *typename;
- buf = (char *) palloc(strlen(str) + 16);
- sprintf(buf, "SELECT (NULL::%s)", str);
+ initStringInfo(&buf);
+ appendStringInfo(&buf, "SELECT (NULL::%s)", str);
- raw_parsetree_list = parser(buf, NULL, 0);
+ raw_parsetree_list = parser(&buf, NULL, 0);
/*
* Make sure we got back exactly what we expected and no more;
*type_id = typenameTypeId(typename);
*typmod = typename->typmod;
- pfree(buf);
+ pfree(buf.data);
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.51 2001/11/05 17:46:26 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.52 2002/04/20 21:56:14 petere Exp $
*
*-------------------------------------------------------------------------
*/
#include "parser/parse_expr.h"
-#if defined(FLEX_SCANNER)
-extern void DeleteBuffer(void);
-#endif /* FLEX_SCANNER */
-
-char *parseString; /* the char* which holds the string to be
- * parsed */
List *parsetree; /* result of parsing is left here */
static int lookahead_token; /* one-token lookahead */
* Returns a list of raw (un-analyzed) parse trees.
*/
List *
-parser(char *str, Oid *typev, int nargs)
+parser(StringInfo str, Oid *typev, int nargs)
{
int yyresult;
- parseString = str;
parsetree = NIL; /* in case parser forgets to set it */
have_lookahead = false;
- scanner_init();
+ scanner_init(str);
parser_init(typev, nargs);
parse_expr_init();
yyresult = yyparse();
-#if defined(FLEX_SCANNER)
- DeleteBuffer();
-#endif /* FLEX_SCANNER */
-
+ scanner_finish();
clearerr(stdin);
if (yyresult) /* error */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.91 2002/03/06 06:09:56 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.92 2002/04/20 21:56:14 petere Exp $
*
*-------------------------------------------------------------------------
*/
#include <ctype.h>
#include <unistd.h>
-#ifndef __linux__
-#include <math.h>
-#endif
#include <errno.h>
#include "miscadmin.h"
#include "parser/gramparse.h"
#include "parser/keywords.h"
#include "parser/parse.h"
-#include "parser/scansup.h"
#include "utils/builtins.h"
#ifdef MULTIBYTE
#include "mb/pg_wchar.h"
#endif
-extern char *parseString;
-static char *parseCh;
-
-/* some versions of lex define this as a macro */
-#if defined(yywrap)
-#undef yywrap
-#endif /* yywrap */
-
-/* set up my input handler --- need one flavor for flex, one for lex */
-#if defined(FLEX_SCANNER)
-
-#define YY_NEVER_INTERACTIVE 1
-#define YY_NO_UNPUT
-static int myinput(char* buf, int max);
-#undef YY_INPUT
-#define YY_INPUT(buf,result,max) {result = myinput(buf,max);}
-
-/* No reason to constrain amount of data slurped per myinput() call. */
+/* 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) elog(FATAL, "%s", (msg))
-#else /* !FLEX_SCANNER */
-
-#undef input
-int input();
-#undef unput
-void unput(char);
-
-#endif /* FLEX_SCANNER */
-
extern YYSTYPE yylval;
static int xcdepth = 0; /* depth of nesting in slash-star comments */
#define startlit() (literalbuf[0] = '\0', literallen = 0)
static void addlit(char *ytext, int yleng);
+static void addlitchar(unsigned char ychar);
+static char *litbufdup(void);
+
+/* Handles to the buffer that the lexer uses internally */
+static YY_BUFFER_STATE scanbufhandle;
+static char *scanbuf;
+
+unsigned char unescape_single_char(unsigned char c);
%}
+
+%option 8bit
+%option never-interactive
+%option nounput
+%option noyywrap
+%option prefix="base_yy"
+
/*
* OK, here is a short description of lex/flex rules behavior.
* The longest pattern which matches an input string is always chosen.
/* Extended quote
* xqdouble implements SQL92 embedded quote
* xqcat allows strings to cross input lines
- * Note: reduction of '' and \ sequences to output text is done in scanstr(),
- * not by rules here. But we do get rid of xqcat sequences here.
*/
quote '
xqstart {quote}
xqstop {quote}
xqdouble {quote}{quote}
xqinside [^\\']+
-xqliteral [\\](.|\n)
+xqescape [\\][^0-7]
+xqoctesc [\\][0-7]{1,3}
xqcat {quote}{whitespace_with_newline}{quote}
-/* Delimited quote
+/* Double quote
* Allows embedded spaces and other special characters into identifiers.
*/
dquote \"
other .
-/* DO NOT PUT ANY COMMENTS IN THE FOLLOWING SECTION.
- * AT&T lex does not properly handle C-style comments in this second lex block.
- * So, put comments here. thomas - 1997-09-08
- *
+/*
* Quoted strings must allow some special characters such as single-quote
* and newline.
* Embedded single-quotes are implemented both in the SQL92-standard
{xbitstart} {
BEGIN(xbit);
startlit();
- addlit("b", 1);
+ addlitchar('b');
}
<xbit>{xbitstop} {
BEGIN(INITIAL);
if (literalbuf[strspn(literalbuf + 1, "01") + 1] != '\0')
elog(ERROR, "invalid bit string input: '%s'",
literalbuf);
- yylval.str = pstrdup(literalbuf);
+ yylval.str = litbufdup();
return BITCONST;
}
<xh>{xhinside} |
}
<xq>{xqstop} {
BEGIN(INITIAL);
- yylval.str = scanstr(literalbuf);
+ yylval.str = litbufdup();
return SCONST;
}
-<xq>{xqdouble} |
-<xq>{xqinside} |
-<xq>{xqliteral} {
+<xq>{xqdouble} {
+ addlitchar('\'');
+ }
+<xq>{xqinside} {
addlit(yytext, yyleng);
}
+<xq>{xqescape} {
+ addlitchar(unescape_single_char(yytext[1]));
+ }
+<xq>{xqoctesc} {
+ unsigned char c = strtoul(yytext+1, NULL, 8);
+ addlitchar(c);
+ }
<xq>{xqcat} {
/* ignore */
}
literalbuf[NAMEDATALEN-1] = '\0';
#endif
}
- yylval.str = pstrdup(literalbuf);
+ yylval.str = litbufdup();
return IDENT;
}
<xd>{xddouble} {
- addlit(yytext, yyleng-1);
+ addlitchar('"');
}
<xd>{xdinside} {
addlit(yytext, yyleng);
elog(ERROR, "parser: %s at or near \"%s\"", message, yytext);
}
-int
-yywrap(void)
-{
- return(1);
-}
/*
- scanner_init:
- called by postgres before any actual parsing is done
-*/
+ * Called before any actual parsing is done
+ */
void
-scanner_init(void)
+scanner_init(StringInfo str)
{
- /* it's important to set this to NULL
- because input()/myinput() checks the non-nullness of parseCh
- to know when to pass the string to lex/flex */
- parseCh = NULL;
+ /*
+ * Might be left over after elog()
+ */
+ if (YY_CURRENT_BUFFER)
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+
+ scanbuf = palloc(str->len + 2);
+ memcpy(scanbuf, str->data, str->len);
+ scanbuf[str->len] = scanbuf[str->len + 1] = YY_END_OF_BUFFER_CHAR;
+ scanbufhandle = yy_scan_buffer(scanbuf, str->len + 2);
/* initialize literal buffer to a reasonable but expansible size */
literalalloc = 128;
literalbuf = (char *) palloc(literalalloc);
startlit();
-#if defined(FLEX_SCANNER)
- if (YY_CURRENT_BUFFER)
- yy_flush_buffer(YY_CURRENT_BUFFER);
-#endif /* FLEX_SCANNER */
- BEGIN INITIAL;
+ BEGIN(INITIAL);
}
+
+/*
+ * Called after parsing is done to clean up after scanner_init()
+ */
+void
+scanner_finish(void)
+{
+ yy_delete_buffer(scanbufhandle);
+ pfree(scanbuf);
+}
+
+
static void
addlit(char *ytext, int yleng)
{
literalbuf[literallen] = '\0';
}
-#if !defined(FLEX_SCANNER)
-/* get lex input from a string instead of from stdin */
-int
-input()
+static void
+addlitchar(unsigned char ychar)
{
- if (parseCh == NULL)
- parseCh = parseString;
- if (*parseCh == '\0')
- return(0);
- else
- return(*parseCh++);
+ /* enlarge buffer if needed */
+ if ((literallen+1) >= literalalloc)
+ {
+ literalalloc *= 2;
+ literalbuf = (char *) repalloc(literalbuf, literalalloc);
+ }
+ /* append new data, add trailing null */
+ literalbuf[literallen] = ychar;
+ literallen += 1;
+ literalbuf[literallen] = '\0';
}
-/* undo lex input from a string instead of from stdin */
-void
-unput(char c)
+
+/*
+ * One might be tempted to write pstrdup(literalbuf) instead of this,
+ * but for long literals this is much faster because the length is
+ * already known.
+ */
+static char *
+litbufdup(void)
{
- if (parseCh == NULL)
- elog(FATAL, "Unput() failed.\n");
- else if (c != 0)
- *--parseCh = c;
-}
+ char *new;
-#endif /* !defined(FLEX_SCANNER) */
+ new = palloc(literallen + 1);
+ memcpy(new, literalbuf, literallen+1);
+ return new;
+}
-#ifdef FLEX_SCANNER
-/* input routine for flex to read input from a string instead of a file */
-static int
-myinput(char* buf, int max)
+unsigned char
+unescape_single_char(unsigned char c)
{
- int len;
-
- if (parseCh == NULL)
- parseCh = parseString;
- len = strlen(parseCh); /* remaining data available */
- /* Note: this code used to think that flex wants a null-terminated
- * string. It does NOT, and returning 1 less character than it asks
- * for will cause failure under the right boundary conditions. So
- * shut up and fill the buffer to the limit, you hear?
- */
- if (len > max)
- len = max;
- if (len > 0)
- memcpy(buf, parseCh, len);
- parseCh += len;
- return len;
+ switch (c)
+ {
+ case 'b':
+ return '\b';
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ default:
+ return c;
+ }
}
-
-#endif /* FLEX_SCANNER */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.261 2002/04/18 20:01:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.262 2002/04/20 21:56:15 petere Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
static int InteractiveBackend(StringInfo inBuf);
static int SocketBackend(StringInfo inBuf);
static int ReadCommand(StringInfo inBuf);
-static List *pg_parse_query(char *query_string, Oid *typev, int nargs);
+static List *pg_parse_query(StringInfo query_string, Oid *typev, int nargs);
static List *pg_analyze_and_rewrite(Node *parsetree);
static void start_xact_command(void);
static void finish_xact_command(void);
List *raw_parsetree_list;
List *querytree_list;
List *list_item;
+ StringInfoData stri;
+
+ initStringInfo(&stri);
+ appendStringInfo(&stri, "%s", query_string);
/*
* (1) parse the request string into a list of raw parse trees.
*/
- raw_parsetree_list = pg_parse_query(query_string, typev, nargs);
+ raw_parsetree_list = pg_parse_query(&stri, typev, nargs);
/*
* (2) Do parse analysis and rule rewrite.
* commands are not processed any further than the raw parse stage.
*/
static List *
-pg_parse_query(char *query_string, Oid *typev, int nargs)
+pg_parse_query(StringInfo query_string, Oid *typev, int nargs)
{
List *raw_parsetree_list;
if (Debug_print_query)
- elog(LOG, "query: %s", query_string);
+ elog(LOG, "query: %s", query_string->data);
if (Show_parser_stats)
ResetUsage();
*/
void
-pg_exec_query_string(char *query_string, /* string to execute */
+pg_exec_query_string(StringInfo query_string, /* string to execute */
CommandDest dest, /* where results should go */
MemoryContext parse_context) /* context for
* parsetrees */
List *parsetree_list,
*parsetree_item;
- debug_query_string = query_string; /* used by pgmonitor */
+ debug_query_string = query_string->data; /* used by pgmonitor */
/*
* Start up a transaction command. All queries generated by the
* process utility functions (create, destroy, etc..)
*/
if (Debug_print_query)
- elog(LOG, "ProcessUtility: %s", query_string);
+ elog(LOG, "ProcessUtility: %s", query_string->data);
else elog(DEBUG2, "ProcessUtility");
if (querytree->originalQuery)
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
- puts("$Revision: 1.261 $ $Date: 2002/04/18 20:01:09 $\n");
+ puts("$Revision: 1.262 $ $Date: 2002/04/20 21:56:15 $\n");
}
/*
pgstat_report_activity(parser_input->data);
- pg_exec_query_string(parser_input->data,
+ pg_exec_query_string(parser_input,
whereToSendOutput,
QueryContext);
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: gramparse.h,v 1.20 2002/04/09 20:35:55 tgl Exp $
+ * $Id: gramparse.h,v 1.21 2002/04/20 21:56:15 petere Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef GRAMPARSE_H
#define GRAMPARSE_H
+#include "lib/stringinfo.h"
+
/* from parser.c */
extern int yylex(void);
/* from scan.l */
-extern void scanner_init(void);
+extern void scanner_init(StringInfo str);
+extern void scanner_finish(void);
extern int base_yylex(void);
extern void yyerror(const char *message);
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parser.h,v 1.11 2001/11/05 17:46:35 momjian Exp $
+ * $Id: parser.h,v 1.12 2002/04/20 21:56:15 petere Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSER_H
#define PARSER_H
+#include "lib/stringinfo.h"
#include "parser/parse_node.h"
-extern List *parser(char *str, Oid *typev, int nargs);
+extern List *parser(StringInfo str, Oid *typev, int nargs);
#endif /* PARSER_H */
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: tcopprot.h,v 1.47 2001/11/10 23:51:14 tgl Exp $
+ * $Id: tcopprot.h,v 1.48 2002/04/20 21:56:15 petere Exp $
*
* OLD COMMENTS
* This file was created so that other c files could get the two
#include <setjmp.h>
#include "executor/execdesc.h"
+#include "lib/stringinfo.h"
#include "tcop/dest.h"
extern List *pg_parse_and_rewrite(char *query_string,
Oid *typev, int nargs);
extern Plan *pg_plan_query(Query *querytree);
-extern void pg_exec_query_string(char *query_string,
+extern void pg_exec_query_string(StringInfo query_string,
CommandDest dest,
MemoryContext parse_context);
#endif /* BOOTSTRAP_INCLUDE */