Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f7563e9

Browse files
author
Michael Meskes
committed
Synced parser.
Made ecpg parser use backend provided keyword list. Changed whenever test so exit value is 0.
1 parent 1ac1bea commit f7563e9

File tree

13 files changed

+274
-629
lines changed

13 files changed

+274
-629
lines changed

src/interfaces/ecpg/ChangeLog

+7
Original file line numberDiff line numberDiff line change
@@ -2351,6 +2351,13 @@ Mon, 12 May 2008 18:19:08 +0200
23512351

23522352
- Check for non-existant connection in prepare statement handling.
23532353
- Do not close files that weren't opened.
2354+
2355+
Tue, 20 May 2008 17:31:01 +0200
2356+
2357+
- Synced parser.
2358+
- Made ecpg parser use backend provided keyword list. One less file to
2359+
sync manually.
2360+
- Changed whenever test so exit value is 0.
23542361
- Set pgtypes library version to 3.1.
23552362
- Set compat library version to 3.1.
23562363
- Set ecpg library version to 6.2.

src/interfaces/ecpg/preproc/Makefile

+8-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
# Copyright (c) 1998-2008, PostgreSQL Global Development Group
66
#
7-
# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.132 2008/03/18 17:46:23 petere Exp $
7+
# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.133 2008/05/20 23:17:32 meskes Exp $
88
#
99
#-------------------------------------------------------------------------
1010

@@ -25,7 +25,7 @@ override CPPFLAGS := -I../include -I$(top_srcdir)/src/interfaces/ecpg/include \
2525
override CFLAGS += $(PTHREAD_CFLAGS)
2626

2727
OBJS= preproc.o type.o ecpg.o output.o parser.o \
28-
keywords.o c_keywords.o ../ecpglib/typename.o descriptor.o variable.o \
28+
keywords.o c_keywords.o ecpg_keywords.o ../ecpglib/typename.o descriptor.o variable.o \
2929
$(WIN32RES)
3030

3131
all: submake-libpgport ecpg
@@ -56,6 +56,11 @@ endif
5656

5757
c_keywords.o keywords.o preproc.o parser.o: preproc.h
5858

59+
# instead of maintaining our own list, take the one from the backend
60+
# we cannot just link it in, but must copy and make some minor changes
61+
keywords.c: % : $(top_srcdir)/src/backend/parser/%
62+
sed -e 's/#include "parser\/parse.h"/#include "preproc.h"/' $< > $@
63+
5964
distprep: $(srcdir)/preproc.c $(srcdir)/preproc.h $(srcdir)/pgc.c
6065

6166
install: all installdirs
@@ -68,7 +73,7 @@ uninstall:
6873
rm -f '$(DESTDIR)$(bindir)/ecpg$(X)'
6974

7075
clean distclean:
71-
rm -f *.o ecpg$(X)
76+
rm -f keywords.c *.o ecpg$(X)
7277
# garbage from partial builds
7378
@rm -f y.tab.c y.tab.h
7479
# garbage from development

src/interfaces/ecpg/preproc/c_keywords.c

+31-29
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* keywords.c
44
* lexical token lookup for reserved words in postgres embedded SQL
55
*
6-
* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/c_keywords.c,v 1.21 2007/08/22 08:20:58 meskes Exp $
6+
* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/c_keywords.c,v 1.22 2008/05/20 23:17:32 meskes Exp $
77
* §
88
*-------------------------------------------------------------------------
99
*/
@@ -21,37 +21,39 @@
2121
* search is used to locate entries.
2222
*/
2323
static const ScanKeyword ScanCKeywords[] = {
24-
/* name value */
25-
{"VARCHAR", VARCHAR},
26-
{"auto", S_AUTO},
27-
{"bool", SQL_BOOL},
28-
{"char", CHAR_P},
29-
{"const", S_CONST},
30-
{"enum", ENUM_P},
31-
{"extern", S_EXTERN},
32-
{"float", FLOAT_P},
33-
{"hour", HOUR_P},
34-
{"int", INT_P},
35-
{"long", SQL_LONG},
36-
{"minute", MINUTE_P},
37-
{"month", MONTH_P},
38-
{"register", S_REGISTER},
39-
{"second", SECOND_P},
40-
{"short", SQL_SHORT},
41-
{"signed", SQL_SIGNED},
42-
{"static", S_STATIC},
43-
{"struct", SQL_STRUCT},
44-
{"to", TO},
45-
{"typedef", S_TYPEDEF},
46-
{"union", UNION},
47-
{"unsigned", SQL_UNSIGNED},
48-
{"varchar", VARCHAR},
49-
{"volatile", S_VOLATILE},
50-
{"year", YEAR_P},
24+
/* name, value, category */
25+
/* category is not needed in ecpg, it is only here so we can share
26+
* the data structure with the backend */
27+
{"VARCHAR", VARCHAR, 0},
28+
{"auto", S_AUTO, 0},
29+
{"bool", SQL_BOOL, 0},
30+
{"char", CHAR_P, 0},
31+
{"const", S_CONST, 0},
32+
{"enum", ENUM_P, 0},
33+
{"extern", S_EXTERN, 0},
34+
{"float", FLOAT_P, 0},
35+
{"hour", HOUR_P, 0},
36+
{"int", INT_P, 0},
37+
{"long", SQL_LONG, 0},
38+
{"minute", MINUTE_P, 0},
39+
{"month", MONTH_P, 0},
40+
{"register", S_REGISTER, 0},
41+
{"second", SECOND_P, 0},
42+
{"short", SQL_SHORT, 0},
43+
{"signed", SQL_SIGNED, 0},
44+
{"static", S_STATIC, 0},
45+
{"struct", SQL_STRUCT, 0},
46+
{"to", TO, 0},
47+
{"typedef", S_TYPEDEF, 0},
48+
{"union", UNION, 0},
49+
{"unsigned", SQL_UNSIGNED, 0},
50+
{"varchar", VARCHAR, 0},
51+
{"volatile", S_VOLATILE, 0},
52+
{"year", YEAR_P, 0},
5153
};
5254

5355
const ScanKeyword *
54-
ScanCKeywordLookup(char *text)
56+
ScanCKeywordLookup(const char *text)
5557
{
5658
return DoLookup(text, &ScanCKeywords[0], endof(ScanCKeywords) - 1);
5759
}

src/interfaces/ecpg/preproc/ecpg_keywords.c

+132-46
Original file line numberDiff line numberDiff line change
@@ -4,62 +4,148 @@
44
* lexical token lookup for reserved words in postgres embedded SQL
55
*
66
* IDENTIFICATION
7-
* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg_keywords.c,v 1.37 2007/11/15 21:14:45 momjian Exp $
7+
* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg_keywords.c,v 1.38 2008/05/20 23:17:32 meskes Exp $
88
*
99
*-------------------------------------------------------------------------
1010
*/
1111

12+
#include "postgres_fe.h"
13+
14+
#include <ctype.h>
15+
16+
#include "extern.h"
17+
#include "preproc.h"
18+
1219
/*
1320
* List of (keyword-name, keyword-token-value) pairs.
1421
*
1522
* !!WARNING!!: This list must be sorted, because binary
1623
* search is used to locate entries.
1724
*/
1825
static const ScanKeyword ScanECPGKeywords[] = {
19-
/* name value */
20-
{"allocate", SQL_ALLOCATE},
21-
{"autocommit", SQL_AUTOCOMMIT},
22-
{"bool", SQL_BOOL},
23-
{"break", SQL_BREAK},
24-
{"call", SQL_CALL},
25-
{"cardinality", SQL_CARDINALITY},
26-
{"connect", SQL_CONNECT},
27-
{"continue", SQL_CONTINUE},
28-
{"count", SQL_COUNT},
29-
{"data", SQL_DATA},
30-
{"datetime_interval_code", SQL_DATETIME_INTERVAL_CODE},
31-
{"datetime_interval_precision", SQL_DATETIME_INTERVAL_PRECISION},
32-
{"describe", SQL_DESCRIBE},
33-
{"descriptor", SQL_DESCRIPTOR},
34-
{"disconnect", SQL_DISCONNECT},
35-
{"found", SQL_FOUND},
36-
{"free", SQL_FREE},
37-
{"go", SQL_GO},
38-
{"goto", SQL_GOTO},
39-
{"identified", SQL_IDENTIFIED},
40-
{"indicator", SQL_INDICATOR},
41-
{"key_member", SQL_KEY_MEMBER},
42-
{"length", SQL_LENGTH},
43-
{"long", SQL_LONG},
44-
{"nullable", SQL_NULLABLE},
45-
{"octet_length", SQL_OCTET_LENGTH},
46-
{"open", SQL_OPEN},
47-
{"output", SQL_OUTPUT},
48-
{"reference", SQL_REFERENCE},
49-
{"returned_length", SQL_RETURNED_LENGTH},
50-
{"returned_octet_length", SQL_RETURNED_OCTET_LENGTH},
51-
{"scale", SQL_SCALE},
52-
{"section", SQL_SECTION},
53-
{"short", SQL_SHORT},
54-
{"signed", SQL_SIGNED},
55-
{"sql", SQL_SQL}, /* strange thing, used for into sql descriptor
26+
/* name, value, category */
27+
/* category is not needed in ecpg, it is only here so we can share
28+
* the data structure with the backend */
29+
{"allocate", SQL_ALLOCATE, 0},
30+
{"autocommit", SQL_AUTOCOMMIT, 0},
31+
{"bool", SQL_BOOL, 0},
32+
{"break", SQL_BREAK, 0},
33+
{"call", SQL_CALL, 0},
34+
{"cardinality", SQL_CARDINALITY, 0},
35+
{"connect", SQL_CONNECT, 0},
36+
{"count", SQL_COUNT, 0},
37+
{"data", SQL_DATA, 0},
38+
{"datetime_interval_code", SQL_DATETIME_INTERVAL_CODE, 0},
39+
{"datetime_interval_precision", SQL_DATETIME_INTERVAL_PRECISION, 0},
40+
{"describe", SQL_DESCRIBE, 0},
41+
{"descriptor", SQL_DESCRIPTOR, 0},
42+
{"disconnect", SQL_DISCONNECT, 0},
43+
{"found", SQL_FOUND, 0},
44+
{"free", SQL_FREE, 0},
45+
{"get", SQL_GET, 0},
46+
{"go", SQL_GO, 0},
47+
{"goto", SQL_GOTO, 0},
48+
{"identified", SQL_IDENTIFIED, 0},
49+
{"indicator", SQL_INDICATOR, 0},
50+
{"key_member", SQL_KEY_MEMBER, 0},
51+
{"length", SQL_LENGTH, 0},
52+
{"long", SQL_LONG, 0},
53+
{"nullable", SQL_NULLABLE, 0},
54+
{"octet_length", SQL_OCTET_LENGTH, 0},
55+
{"open", SQL_OPEN, 0},
56+
{"output", SQL_OUTPUT, 0},
57+
{"reference", SQL_REFERENCE, 0},
58+
{"returned_length", SQL_RETURNED_LENGTH, 0},
59+
{"returned_octet_length", SQL_RETURNED_OCTET_LENGTH, 0},
60+
{"scale", SQL_SCALE, 0},
61+
{"section", SQL_SECTION, 0},
62+
{"short", SQL_SHORT, 0},
63+
{"signed", SQL_SIGNED, 0},
64+
{"sql", SQL_SQL, 0}, /* strange thing, used for into sql descriptor
5665
* MYDESC; */
57-
{"sqlerror", SQL_SQLERROR},
58-
{"sqlprint", SQL_SQLPRINT},
59-
{"sqlwarning", SQL_SQLWARNING},
60-
{"stop", SQL_STOP},
61-
{"struct", SQL_STRUCT},
62-
{"unsigned", SQL_UNSIGNED},
63-
{"var", SQL_VAR},
64-
{"whenever", SQL_WHENEVER},
66+
{"sqlerror", SQL_SQLERROR, 0},
67+
{"sqlprint", SQL_SQLPRINT, 0},
68+
{"sqlwarning", SQL_SQLWARNING, 0},
69+
{"stop", SQL_STOP, 0},
70+
{"struct", SQL_STRUCT, 0},
71+
{"unsigned", SQL_UNSIGNED, 0},
72+
{"var", SQL_VAR, 0},
73+
{"whenever", SQL_WHENEVER, 0},
6574
};
75+
76+
/* This is all taken from src/backend/parser/keyword.c and adjusted for our needs. */
77+
/*
78+
* Do a binary search using plain strcmp() comparison.
79+
*/
80+
const ScanKeyword *
81+
DoLookup(const char *word, const ScanKeyword *low, const ScanKeyword *high)
82+
{
83+
while (low <= high)
84+
{
85+
const ScanKeyword *middle;
86+
int difference;
87+
88+
middle = low + (high - low) / 2;
89+
difference = strcmp(middle->name, word);
90+
if (difference == 0)
91+
return middle;
92+
else if (difference < 0)
93+
low = middle + 1;
94+
else
95+
high = middle - 1;
96+
}
97+
98+
return NULL;
99+
}
100+
101+
/*
102+
* ScanECPGKeywordLookup - see if a given word is a keyword
103+
*
104+
* Returns a pointer to the ScanKeyword table entry, or NULL if no match.
105+
*
106+
* The match is done case-insensitively. Note that we deliberately use a
107+
* dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
108+
* even if we are in a locale where tolower() would produce more or different
109+
* translations. This is to conform to the SQL99 spec, which says that
110+
* keywords are to be matched in this way even though non-keyword identifiers
111+
* receive a different case-normalization mapping.
112+
*/
113+
const ScanKeyword *
114+
ScanECPGKeywordLookup(const char *text)
115+
{
116+
int len,
117+
i;
118+
char word[NAMEDATALEN];
119+
const ScanKeyword *res;
120+
121+
/* First check SQL symbols defined by the backend. */
122+
123+
res = ScanKeywordLookup(text);
124+
if (res)
125+
return res;
126+
127+
len = strlen(text);
128+
/* We assume all keywords are shorter than NAMEDATALEN. */
129+
if (len >= NAMEDATALEN)
130+
return NULL;
131+
132+
/*
133+
* Apply an ASCII-only downcasing. We must not use tolower() since it may
134+
* produce the wrong translation in some locales (eg, Turkish).
135+
*/
136+
for (i = 0; i < len; i++)
137+
{
138+
char ch = text[i];
139+
140+
if (ch >= 'A' && ch <= 'Z')
141+
ch += 'a' - 'A';
142+
word[i] = ch;
143+
}
144+
word[len] = '\0';
145+
146+
/*
147+
* Now do a binary search using plain strcmp() comparison.
148+
*/
149+
150+
return DoLookup(word, &ScanECPGKeywords[0], endof(ScanECPGKeywords) - 1);
151+
}

src/interfaces/ecpg/preproc/extern.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.70 2007/11/15 21:14:45 momjian Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.71 2008/05/20 23:17:32 meskes Exp $ */
22

33
#ifndef _ECPG_PREPROC_EXTERN_H
44
#define _ECPG_PREPROC_EXTERN_H
55

66
#include "type.h"
7+
#include "parser/keywords.h"
78

89
#include <errno.h>
910
#ifndef CHAR_BIT
@@ -74,7 +75,6 @@ extern void base_yyerror(const char *);
7475
extern void *mm_alloc(size_t), *mm_realloc(void *, size_t);
7576
extern char *mm_strdup(const char *);
7677
extern void mmerror(int, enum errortype, char *,...);
77-
extern const ScanKeyword *ScanCKeywordLookup(char *);
7878
extern void output_get_descr_header(char *);
7979
extern void output_get_descr(char *, char *);
8080
extern void output_set_descr_header(char *);
@@ -96,8 +96,9 @@ extern void check_indicator(struct ECPGtype *);
9696
extern void remove_typedefs(int);
9797
extern void remove_variables(int);
9898
extern struct variable *new_variable(const char *, struct ECPGtype *, int);
99-
extern const ScanKeyword *ScanKeywordLookup(char *text);
100-
extern const ScanKeyword *DoLookup(char *, const ScanKeyword *, const ScanKeyword *);
99+
extern const ScanKeyword *ScanCKeywordLookup(const char *);
100+
extern const ScanKeyword *ScanECPGKeywordLookup(const char *text);
101+
extern const ScanKeyword *DoLookup(const char *, const ScanKeyword *, const ScanKeyword *);
101102
extern void scanner_init(const char *);
102103
extern void parser_init(void);
103104
extern void scanner_finish(void);

0 commit comments

Comments
 (0)