From 2c6af4f44228d76d3351fe26f68b00b55cdd239a Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 23 Mar 2016 20:22:08 -0400 Subject: Move keywords.c/kwlookup.c into src/common/. Now that we have src/common/ for code shared between frontend and backend, we can get rid of (most of) the klugy ways that the keyword table and keyword lookup code were formerly shared between different uses. This is a first step towards a more general plan of getting rid of special-purpose kluges for sharing code in src/bin/. I chose to merge kwlookup.c back into keywords.c, as it once was, and always has been so far as keywords.h is concerned. We could have kept them separate, but there is noplace that uses ScanKeywordLookup without also wanting access to the backend's keyword list, so there seems little point. ecpg is still a bit weird, but at least now the trickiness is documented. I think that the MSVC build script should require no adjustments beyond what's done here ... but we'll soon find out. --- src/backend/parser/Makefile | 4 +- src/backend/parser/README | 6 +- src/backend/parser/keywords.c | 27 -------- src/backend/parser/kwlookup.c | 89 ------------------------- src/backend/utils/adt/misc.c | 2 +- src/backend/utils/adt/ruleutils.c | 2 +- src/bin/pg_dump/.gitignore | 2 - src/bin/pg_dump/Makefile | 19 ++---- src/bin/pg_dump/dumputils.c | 10 +-- src/bin/pg_dump/keywords.c | 30 --------- src/bin/psql/.gitignore | 2 - src/bin/psql/Makefile | 9 +-- src/bin/scripts/.gitignore | 2 - src/bin/scripts/Makefile | 23 +++---- src/common/Makefile | 14 +++- src/common/keywords.c | 114 +++++++++++++++++++++++++++++++++ src/include/common/keywords.h | 39 +++++++++++ src/include/parser/gramparse.h | 4 +- src/include/parser/keywords.h | 38 ----------- src/include/parser/scanner.h | 2 +- src/interfaces/ecpg/preproc/.gitignore | 1 - src/interfaces/ecpg/preproc/Makefile | 7 +- src/interfaces/ecpg/preproc/extern.h | 3 +- src/interfaces/ecpg/preproc/keywords.c | 16 ++++- src/tools/msvc/Mkvcbuild.pm | 21 ++---- 25 files changed, 220 insertions(+), 266 deletions(-) delete mode 100644 src/backend/parser/keywords.c delete mode 100644 src/backend/parser/kwlookup.c delete mode 100644 src/bin/pg_dump/keywords.c create mode 100644 src/common/keywords.c create mode 100644 src/include/common/keywords.h delete mode 100644 src/include/parser/keywords.h diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile index 9cc8946fa1..fdd8485cec 100644 --- a/src/backend/parser/Makefile +++ b/src/backend/parser/Makefile @@ -12,7 +12,7 @@ include $(top_builddir)/src/Makefile.global override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS) -OBJS= analyze.o gram.o scan.o keywords.o kwlookup.o parser.o \ +OBJS= analyze.o gram.o scan.o parser.o \ parse_agg.o parse_clause.o parse_coerce.o parse_collate.o parse_cte.o \ parse_expr.o parse_func.o parse_node.o parse_oper.o parse_param.o \ parse_relation.o parse_target.o parse_type.o parse_utilcmd.o scansup.o @@ -44,7 +44,7 @@ scan.c: FLEX_NO_BACKUP=yes # Force these dependencies to be known even without dependency info built: -gram.o scan.o keywords.o parser.o: gram.h +gram.o scan.o parser.o: gram.h # gram.c, gram.h, and scan.c are in the distribution tarball, so they diff --git a/src/backend/parser/README b/src/backend/parser/README index 08625e427d..6d8f19b5ca 100644 --- a/src/backend/parser/README +++ b/src/backend/parser/README @@ -10,8 +10,6 @@ to the optimizer and then executor. parser.c things start here scan.l break query into tokens scansup.c handle escapes in input strings -kwlookup.c turn keywords into specific tokens -keywords.c table of standard keywords (passed to kwlookup.c) gram.y parse the tokens and produce a "raw" parse tree analyze.c top level of parse analysis for optimizable queries parse_agg.c handle aggregates, like SUM(col1), AVG(col2), ... @@ -28,3 +26,7 @@ parse_relation.c support routines for tables and column handling parse_target.c handle the result list of the query parse_type.c support routines for data type handling parse_utilcmd.c parse analysis for utility commands (done at execution time) + +See also src/common/keywords.c, which contains the table of standard +keywords and the keyword lookup function. We separated that out because +various frontend code wants to use it too. diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c deleted file mode 100644 index 7a4f128690..0000000000 --- a/src/backend/parser/keywords.c +++ /dev/null @@ -1,27 +0,0 @@ -/*------------------------------------------------------------------------- - * - * keywords.c - * lexical token lookup for key words in PostgreSQL - * - * - * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/backend/parser/keywords.c - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "parser/gramparse.h" - -#define PG_KEYWORD(a,b,c) {a,b,c}, - - -const ScanKeyword ScanKeywords[] = { -#include "parser/kwlist.h" -}; - -const int NumScanKeywords = lengthof(ScanKeywords); diff --git a/src/backend/parser/kwlookup.c b/src/backend/parser/kwlookup.c deleted file mode 100644 index 4406fef37f..0000000000 --- a/src/backend/parser/kwlookup.c +++ /dev/null @@ -1,89 +0,0 @@ -/*------------------------------------------------------------------------- - * - * kwlookup.c - * lexical token lookup for key words in PostgreSQL - * - * NB - this file is also used by ECPG and several frontend programs in - * src/bin/ including pg_dump and psql - * - * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/backend/parser/kwlookup.c - * - *------------------------------------------------------------------------- - */ - -/* use c.h so this can be built as either frontend or backend */ -#include "c.h" - -#include - -#include "parser/keywords.h" - -/* - * ScanKeywordLookup - see if a given word is a keyword - * - * Returns a pointer to the ScanKeyword table entry, or NULL if no match. - * - * The match is done case-insensitively. Note that we deliberately use a - * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z', - * even if we are in a locale where tolower() would produce more or different - * translations. This is to conform to the SQL99 spec, which says that - * keywords are to be matched in this way even though non-keyword identifiers - * receive a different case-normalization mapping. - */ -const ScanKeyword * -ScanKeywordLookup(const char *text, - const ScanKeyword *keywords, - int num_keywords) -{ - int len, - i; - char word[NAMEDATALEN]; - const ScanKeyword *low; - const ScanKeyword *high; - - len = strlen(text); - /* We assume all keywords are shorter than NAMEDATALEN. */ - if (len >= NAMEDATALEN) - return NULL; - - /* - * Apply an ASCII-only downcasing. We must not use tolower() since it may - * produce the wrong translation in some locales (eg, Turkish). - */ - for (i = 0; i < len; i++) - { - char ch = text[i]; - - if (ch >= 'A' && ch <= 'Z') - ch += 'a' - 'A'; - word[i] = ch; - } - word[len] = '\0'; - - /* - * Now do a binary search using plain strcmp() comparison. - */ - low = keywords; - high = keywords + (num_keywords - 1); - while (low <= high) - { - const ScanKeyword *middle; - int difference; - - middle = low + (high - low) / 2; - difference = strcmp(middle->name, word); - if (difference == 0) - return middle; - else if (difference < 0) - low = middle + 1; - else - high = middle - 1; - } - - return NULL; -} diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index 4dcc5a63be..faa8ef3c91 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -25,10 +25,10 @@ #include "catalog/pg_tablespace.h" #include "catalog/pg_type.h" #include "commands/dbcommands.h" +#include "common/keywords.h" #include "funcapi.h" #include "miscadmin.h" #include "parser/scansup.h" -#include "parser/keywords.h" #include "postmaster/syslogger.h" #include "rewrite/rewriteHandler.h" #include "storage/fd.h" diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 490a0906e8..2b47e95a68 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -38,6 +38,7 @@ #include "catalog/pg_type.h" #include "commands/defrem.h" #include "commands/tablespace.h" +#include "common/keywords.h" #include "executor/spi.h" #include "funcapi.h" #include "mb/pg_wchar.h" @@ -45,7 +46,6 @@ #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/tlist.h" -#include "parser/keywords.h" #include "parser/parse_node.h" #include "parser/parse_agg.h" #include "parser/parse_func.h" diff --git a/src/bin/pg_dump/.gitignore b/src/bin/pg_dump/.gitignore index c2c8677bd8..ae4cf3ce42 100644 --- a/src/bin/pg_dump/.gitignore +++ b/src/bin/pg_dump/.gitignore @@ -1,5 +1,3 @@ -/kwlookup.c - /pg_dump /pg_dumpall /pg_restore diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile index 4162c8e564..ddf940210a 100644 --- a/src/bin/pg_dump/Makefile +++ b/src/bin/pg_dump/Makefile @@ -22,21 +22,16 @@ OBJS= pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \ pg_backup_null.o pg_backup_tar.o pg_backup_directory.o \ pg_backup_utils.o parallel.o compress_io.o dumputils.o $(WIN32RES) -KEYWRDOBJS = keywords.o kwlookup.o - -kwlookup.c: % : $(top_srcdir)/src/backend/parser/% - rm -f $@ && $(LN_S) $< . - all: pg_dump pg_restore pg_dumpall -pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport - $(CC) $(CFLAGS) pg_dump.o common.o pg_dump_sort.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) +pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) | submake-libpq submake-libpgport + $(CC) $(CFLAGS) pg_dump.o common.o pg_dump_sort.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) -pg_restore: pg_restore.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport - $(CC) $(CFLAGS) pg_restore.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) +pg_restore: pg_restore.o $(OBJS) | submake-libpq submake-libpgport + $(CC) $(CFLAGS) pg_restore.o $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) -pg_dumpall: pg_dumpall.o dumputils.o $(KEYWRDOBJS) | submake-libpq submake-libpgport - $(CC) $(CFLAGS) pg_dumpall.o dumputils.o $(KEYWRDOBJS) $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) +pg_dumpall: pg_dumpall.o dumputils.o | submake-libpq submake-libpgport + $(CC) $(CFLAGS) pg_dumpall.o dumputils.o $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) install: all installdirs $(INSTALL_PROGRAM) pg_dump$(X) '$(DESTDIR)$(bindir)'/pg_dump$(X) @@ -50,4 +45,4 @@ uninstall: rm -f $(addprefix '$(DESTDIR)$(bindir)'/, pg_dump$(X) pg_restore$(X) pg_dumpall$(X)) clean distclean maintainer-clean: - rm -f pg_dump$(X) pg_restore$(X) pg_dumpall$(X) $(OBJS) pg_dump.o common.o pg_dump_sort.o pg_restore.o pg_dumpall.o kwlookup.c $(KEYWRDOBJS) + rm -f pg_dump$(X) pg_restore$(X) pg_dumpall$(X) $(OBJS) pg_dump.o common.o pg_dump_sort.o pg_restore.o pg_dumpall.o diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 24ba5c8755..a685d28d60 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -18,13 +18,9 @@ #include "dumputils.h" -#include "parser/keywords.h" +#include "common/keywords.h" -/* Globals from keywords.c */ -extern const ScanKeyword FEScanKeywords[]; -extern const int NumFEScanKeywords; - #define supports_grant_options(version) ((version) >= 70400) static bool parseAclItem(const char *item, const char *type, @@ -116,8 +112,8 @@ fmtId(const char *rawid) * that's fine, since we already know we have all-lower-case. */ const ScanKeyword *keyword = ScanKeywordLookup(rawid, - FEScanKeywords, - NumFEScanKeywords); + ScanKeywords, + NumScanKeywords); if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD) need_quotes = true; diff --git a/src/bin/pg_dump/keywords.c b/src/bin/pg_dump/keywords.c deleted file mode 100644 index 6f3a2d7eda..0000000000 --- a/src/bin/pg_dump/keywords.c +++ /dev/null @@ -1,30 +0,0 @@ -/*------------------------------------------------------------------------- - * - * keywords.c - * lexical token lookup for key words in PostgreSQL - * - * - * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/bin/pg_dump/keywords.c - * - *------------------------------------------------------------------------- - */ -#include "postgres_fe.h" - -#include "parser/keywords.h" - -/* - * We don't need the token number, so leave it out to avoid requiring other - * backend headers. - */ -#define PG_KEYWORD(a,b,c) {a,0,c}, - -const ScanKeyword FEScanKeywords[] = { -#include "parser/kwlist.h" -}; - -const int NumFEScanKeywords = lengthof(FEScanKeywords); diff --git a/src/bin/psql/.gitignore b/src/bin/psql/.gitignore index dc88807f52..ce881f45ad 100644 --- a/src/bin/psql/.gitignore +++ b/src/bin/psql/.gitignore @@ -3,7 +3,5 @@ /sql_help.h /sql_help.c /dumputils.c -/keywords.c -/kwlookup.c /psql diff --git a/src/bin/psql/Makefile b/src/bin/psql/Makefile index 5f4038e2cb..75a9b395b4 100644 --- a/src/bin/psql/Makefile +++ b/src/bin/psql/Makefile @@ -22,7 +22,7 @@ override CPPFLAGS := -I. -I$(srcdir) -I$(libpq_srcdir) -I$(top_srcdir)/src/bin/p OBJS= command.o common.o help.o input.o stringutils.o mainloop.o copy.o \ startup.o prompt.o variables.o large_obj.o print.o describe.o \ - tab-complete.o mbprint.o dumputils.o keywords.o kwlookup.o \ + tab-complete.o mbprint.o dumputils.o \ sql_help.o psqlscan.o psqlscanslash.o \ $(WIN32RES) @@ -34,10 +34,7 @@ psql: $(OBJS) | submake-libpq submake-libpgport help.o: sql_help.h -dumputils.c keywords.c: % : $(top_srcdir)/src/bin/pg_dump/% - rm -f $@ && $(LN_S) $< . - -kwlookup.c: % : $(top_srcdir)/src/backend/parser/% +dumputils.c: % : $(top_srcdir)/src/bin/pg_dump/% rm -f $@ && $(LN_S) $< . sql_help.c: sql_help.h ; @@ -70,7 +67,7 @@ uninstall: rm -f '$(DESTDIR)$(bindir)/psql$(X)' '$(DESTDIR)$(datadir)/psqlrc.sample' clean distclean: - rm -f psql$(X) $(OBJS) dumputils.c keywords.c kwlookup.c lex.backup + rm -f psql$(X) $(OBJS) dumputils.c lex.backup # files removed here are supposed to be in the distribution tarball, # so do not clean them in the clean/distclean rules diff --git a/src/bin/scripts/.gitignore b/src/bin/scripts/.gitignore index 1056b2870c..e12d27a2f1 100644 --- a/src/bin/scripts/.gitignore +++ b/src/bin/scripts/.gitignore @@ -10,8 +10,6 @@ /pg_isready /dumputils.c -/keywords.c -/kwlookup.c /mbprint.c /print.c diff --git a/src/bin/scripts/Makefile b/src/bin/scripts/Makefile index c4e04c9aa8..ad34d42d68 100644 --- a/src/bin/scripts/Makefile +++ b/src/bin/scripts/Makefile @@ -25,26 +25,23 @@ all: $(PROGRAMS) %: %.o $(WIN32RES) $(CC) $(CFLAGS) $^ $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X) -createdb: createdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq submake-libpgport +createdb: createdb.o common.o dumputils.o | submake-libpq submake-libpgport createlang: createlang.o common.o print.o mbprint.o | submake-libpq submake-libpgport -createuser: createuser.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq submake-libpgport -dropdb: dropdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq submake-libpgport +createuser: createuser.o common.o dumputils.o | submake-libpq submake-libpgport +dropdb: dropdb.o common.o dumputils.o | submake-libpq submake-libpgport droplang: droplang.o common.o print.o mbprint.o | submake-libpq submake-libpgport -dropuser: dropuser.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq submake-libpgport -clusterdb: clusterdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq submake-libpgport -vacuumdb: vacuumdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq submake-libpgport -reindexdb: reindexdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq submake-libpgport +dropuser: dropuser.o common.o dumputils.o | submake-libpq submake-libpgport +clusterdb: clusterdb.o common.o dumputils.o | submake-libpq submake-libpgport +vacuumdb: vacuumdb.o common.o dumputils.o | submake-libpq submake-libpgport +reindexdb: reindexdb.o common.o dumputils.o | submake-libpq submake-libpgport pg_isready: pg_isready.o common.o | submake-libpq submake-libpgport -dumputils.c keywords.c: % : $(top_srcdir)/src/bin/pg_dump/% +dumputils.c: % : $(top_srcdir)/src/bin/pg_dump/% rm -f $@ && $(LN_S) $< . print.c mbprint.c : % : $(top_srcdir)/src/bin/psql/% rm -f $@ && $(LN_S) $< . -kwlookup.c: % : $(top_srcdir)/src/backend/parser/% - rm -f $@ && $(LN_S) $< . - install: all installdirs $(INSTALL_PROGRAM) createdb$(X) '$(DESTDIR)$(bindir)'/createdb$(X) $(INSTALL_PROGRAM) dropdb$(X) '$(DESTDIR)$(bindir)'/dropdb$(X) @@ -65,8 +62,8 @@ uninstall: clean distclean maintainer-clean: rm -f $(addsuffix $(X), $(PROGRAMS)) $(addsuffix .o, $(PROGRAMS)) - rm -f common.o dumputils.o kwlookup.o keywords.o print.o mbprint.o $(WIN32RES) - rm -f dumputils.c print.c mbprint.c kwlookup.c keywords.c + rm -f common.o dumputils.o print.o mbprint.o $(WIN32RES) + rm -f dumputils.c print.c mbprint.c rm -rf tmp_check check: diff --git a/src/common/Makefile b/src/common/Makefile index f7a4a4d099..72b73697a8 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -36,8 +36,9 @@ override CPPFLAGS += -DVAL_LDFLAGS_EX="\"$(LDFLAGS_EX)\"" override CPPFLAGS += -DVAL_LDFLAGS_SL="\"$(LDFLAGS_SL)\"" override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\"" -OBJS_COMMON = config_info.o controldata_utils.o exec.o pg_lzcompress.o \ - pgfnames.o psprintf.o relpath.o rmtree.o string.o username.o wait_error.o +OBJS_COMMON = config_info.o controldata_utils.o exec.o keywords.o \ + pg_lzcompress.o pgfnames.o psprintf.o relpath.o rmtree.o \ + string.o username.o wait_error.o OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o restricted_token.o @@ -83,5 +84,14 @@ $(OBJS_SRV): | submake-errcodes submake-errcodes: $(MAKE) -C ../backend submake-errcodes +# Dependencies of keywords.o need to be managed explicitly to make sure +# that you don't get broken parsing code, even in a non-enable-depend build. +# Note that gram.h isn't required for the frontend version of keywords.o. +$(top_builddir)/src/include/parser/gram.h: $(top_srcdir)/src/backend/parser/gram.y + $(MAKE) -C $(top_builddir)/src/backend $(top_builddir)/src/include/parser/gram.h + +keywords.o: $(top_srcdir)/src/include/parser/kwlist.h +keywords_srv.o: $(top_builddir)/src/include/parser/gram.h $(top_srcdir)/src/include/parser/kwlist.h + clean distclean maintainer-clean: rm -f libpgcommon.a libpgcommon_srv.a $(OBJS_FRONTEND) $(OBJS_SRV) diff --git a/src/common/keywords.c b/src/common/keywords.c new file mode 100644 index 0000000000..485dd02e89 --- /dev/null +++ b/src/common/keywords.c @@ -0,0 +1,114 @@ +/*------------------------------------------------------------------------- + * + * keywords.c + * lexical token lookup for key words in PostgreSQL + * + * + * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/common/keywords.c + * + *------------------------------------------------------------------------- + */ +#ifndef FRONTEND +#include "postgres.h" +#else +#include "postgres_fe.h" +#endif + +#ifndef FRONTEND + +#include "parser/gramparse.h" + +#define PG_KEYWORD(a,b,c) {a,b,c}, + +#else + +#include "common/keywords.h" + +/* + * We don't need the token number for frontend uses, so leave it out to avoid + * requiring backend headers that won't compile cleanly here. + */ +#define PG_KEYWORD(a,b,c) {a,0,c}, + +#endif /* FRONTEND */ + + +const ScanKeyword ScanKeywords[] = { +#include "parser/kwlist.h" +}; + +const int NumScanKeywords = lengthof(ScanKeywords); + + +/* + * ScanKeywordLookup - see if a given word is a keyword + * + * The table to be searched is passed explicitly, so that this can be used + * to search keyword lists other than the standard list appearing above. + * + * Returns a pointer to the ScanKeyword table entry, or NULL if no match. + * + * The match is done case-insensitively. Note that we deliberately use a + * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z', + * even if we are in a locale where tolower() would produce more or different + * translations. This is to conform to the SQL99 spec, which says that + * keywords are to be matched in this way even though non-keyword identifiers + * receive a different case-normalization mapping. + */ +const ScanKeyword * +ScanKeywordLookup(const char *text, + const ScanKeyword *keywords, + int num_keywords) +{ + int len, + i; + char word[NAMEDATALEN]; + const ScanKeyword *low; + const ScanKeyword *high; + + len = strlen(text); + /* We assume all keywords are shorter than NAMEDATALEN. */ + if (len >= NAMEDATALEN) + return NULL; + + /* + * Apply an ASCII-only downcasing. We must not use tolower() since it may + * produce the wrong translation in some locales (eg, Turkish). + */ + for (i = 0; i < len; i++) + { + char ch = text[i]; + + if (ch >= 'A' && ch <= 'Z') + ch += 'a' - 'A'; + word[i] = ch; + } + word[len] = '\0'; + + /* + * Now do a binary search using plain strcmp() comparison. + */ + low = keywords; + high = keywords + (num_keywords - 1); + while (low <= high) + { + const ScanKeyword *middle; + int difference; + + middle = low + (high - low) / 2; + difference = strcmp(middle->name, word); + if (difference == 0) + return middle; + else if (difference < 0) + low = middle + 1; + else + high = middle - 1; + } + + return NULL; +} diff --git a/src/include/common/keywords.h b/src/include/common/keywords.h new file mode 100644 index 0000000000..577100d1b9 --- /dev/null +++ b/src/include/common/keywords.h @@ -0,0 +1,39 @@ +/*------------------------------------------------------------------------- + * + * keywords.h + * lexical token lookup for key words in PostgreSQL + * + * + * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/common/keywords.h + * + *------------------------------------------------------------------------- + */ +#ifndef KEYWORDS_H +#define KEYWORDS_H + +/* Keyword categories --- should match lists in gram.y */ +#define UNRESERVED_KEYWORD 0 +#define COL_NAME_KEYWORD 1 +#define TYPE_FUNC_NAME_KEYWORD 2 +#define RESERVED_KEYWORD 3 + + +typedef struct ScanKeyword +{ + const char *name; /* in lower case */ + int16 value; /* grammar's token code */ + int16 category; /* see codes above */ +} ScanKeyword; + +extern PGDLLIMPORT const ScanKeyword ScanKeywords[]; +extern PGDLLIMPORT const int NumScanKeywords; + + +extern const ScanKeyword *ScanKeywordLookup(const char *text, + const ScanKeyword *keywords, + int num_keywords); + +#endif /* KEYWORDS_H */ diff --git a/src/include/parser/gramparse.h b/src/include/parser/gramparse.h index c3ec1992c6..6d8e4937ee 100644 --- a/src/include/parser/gramparse.h +++ b/src/include/parser/gramparse.h @@ -4,8 +4,8 @@ * Shared definitions for the "raw" parser (flex and bison phases only) * * NOTE: this file is only meant to be included in the core parsing files, - * ie, parser.c, gram.y, scan.l, and keywords.c. Definitions that are needed - * outside the core parser should be in parser.h. + * ie, parser.c, gram.y, scan.l, and src/common/keywords.c. + * Definitions that are needed outside the core parser should be in parser.h. * * * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group diff --git a/src/include/parser/keywords.h b/src/include/parser/keywords.h deleted file mode 100644 index 4ac861646d..0000000000 --- a/src/include/parser/keywords.h +++ /dev/null @@ -1,38 +0,0 @@ -/*------------------------------------------------------------------------- - * - * keywords.h - * lexical token lookup for key words in PostgreSQL - * - * - * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * src/include/parser/keywords.h - * - *------------------------------------------------------------------------- - */ -#ifndef KEYWORDS_H -#define KEYWORDS_H - -/* Keyword categories --- should match lists in gram.y */ -#define UNRESERVED_KEYWORD 0 -#define COL_NAME_KEYWORD 1 -#define TYPE_FUNC_NAME_KEYWORD 2 -#define RESERVED_KEYWORD 3 - - -typedef struct ScanKeyword -{ - const char *name; /* in lower case */ - int16 value; /* grammar's token code */ - int16 category; /* see codes above */ -} ScanKeyword; - -extern PGDLLIMPORT const ScanKeyword ScanKeywords[]; -extern PGDLLIMPORT const int NumScanKeywords; - -extern const ScanKeyword *ScanKeywordLookup(const char *text, - const ScanKeyword *keywords, - int num_keywords); - -#endif /* KEYWORDS_H */ diff --git a/src/include/parser/scanner.h b/src/include/parser/scanner.h index 0060501937..b885e67a83 100644 --- a/src/include/parser/scanner.h +++ b/src/include/parser/scanner.h @@ -19,7 +19,7 @@ #ifndef SCANNER_H #define SCANNER_H -#include "parser/keywords.h" +#include "common/keywords.h" /* * The scanner returns extra data about scanned tokens in this union type. diff --git a/src/interfaces/ecpg/preproc/.gitignore b/src/interfaces/ecpg/preproc/.gitignore index 6fca9aff59..aacfb844bd 100644 --- a/src/interfaces/ecpg/preproc/.gitignore +++ b/src/interfaces/ecpg/preproc/.gitignore @@ -4,4 +4,3 @@ /pgc.c /ecpg -/kwlookup.c diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index ee3b13a4af..30db5a049a 100644 --- a/src/interfaces/ecpg/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -27,7 +27,7 @@ override CPPFLAGS := -I../include -I$(top_srcdir)/src/interfaces/ecpg/include \ override CFLAGS += $(PTHREAD_CFLAGS) -DECPG_COMPILE OBJS= preproc.o pgc.o type.o ecpg.o output.o parser.o \ - keywords.o c_keywords.o ecpg_keywords.o kwlookup.o ../ecpglib/typename.o descriptor.o variable.o \ + keywords.o c_keywords.o ecpg_keywords.o ../ecpglib/typename.o descriptor.o variable.o \ $(WIN32RES) # Suppress parallel build to avoid a bug in GNU make 3.82 @@ -53,9 +53,6 @@ preproc.y: ../../../backend/parser/gram.y parse.pl ecpg.addons ecpg.header ecpg. ecpg_keywords.o c_keywords.o keywords.o preproc.o pgc.o parser.o: preproc.h -kwlookup.c: % : $(top_srcdir)/src/backend/parser/% - rm -f $@ && $(LN_S) $< . - distprep: preproc.y preproc.c preproc.h pgc.c install: all installdirs @@ -68,7 +65,7 @@ uninstall: rm -f '$(DESTDIR)$(bindir)/ecpg$(X)' clean distclean: - rm -f kwlookup.c *.o ecpg$(X) + rm -f *.o ecpg$(X) # garbage from development @rm -f core a.out diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index ea8fd8ed98..f6841726e4 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -4,7 +4,8 @@ #define _ECPG_PREPROC_EXTERN_H #include "type.h" -#include "parser/keywords.h" + +#include "common/keywords.h" #include #ifndef CHAR_BIT diff --git a/src/interfaces/ecpg/preproc/keywords.c b/src/interfaces/ecpg/preproc/keywords.c index 2f17f0c5c0..cffdaed67b 100644 --- a/src/interfaces/ecpg/preproc/keywords.c +++ b/src/interfaces/ecpg/preproc/keywords.c @@ -15,13 +15,23 @@ */ #include "postgres_fe.h" -#include "parser/keywords.h" -#include "type.h" +/* + * This is much trickier than it looks. We are #include'ing kwlist.h + * but the "value" numbers that go into the table are from preproc.h + * not the backend's gram.h. Therefore this table will recognize all + * keywords known to the backend, but will supply the token numbers used + * by ecpg's grammar, which is what we need. The ecpg grammar must + * define all the same token names the backend does, else we'll get + * undefined-symbol failures in this compile. + */ + +#include "common/keywords.h" + #include "extern.h" #include "preproc.h" -#define PG_KEYWORD(a,b,c) {a,b,c}, +#define PG_KEYWORD(a,b,c) {a,b,c}, const ScanKeyword SQLScanKeywords[] = { #include "parser/kwlist.h" diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 012b327d9d..8716642847 100644 --- a/src/tools/msvc/Mkvcbuild.pm +++ b/src/tools/msvc/Mkvcbuild.pm @@ -108,8 +108,9 @@ sub mkvcbuild } our @pgcommonallfiles = qw( - config_info.c controldata_utils.c exec.c pg_lzcompress.c pgfnames.c - psprintf.c relpath.c rmtree.c string.c username.c wait_error.c); + config_info.c controldata_utils.c exec.c keywords.c + pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c + string.c username.c wait_error.c); our @pgcommonfrontendfiles = ( @pgcommonallfiles, qw(fe_memutils.c @@ -343,8 +344,6 @@ sub mkvcbuild $pgdump->AddFile('src/bin/pg_dump/pg_dump.c'); $pgdump->AddFile('src/bin/pg_dump/common.c'); $pgdump->AddFile('src/bin/pg_dump/pg_dump_sort.c'); - $pgdump->AddFile('src/bin/pg_dump/keywords.c'); - $pgdump->AddFile('src/backend/parser/kwlookup.c'); $pgdump->AddLibrary('ws2_32.lib'); my $pgdumpall = AddSimpleFrontend('pg_dump', 1); @@ -360,16 +359,12 @@ sub mkvcbuild $pgdumpall->AddIncludeDir('src/backend'); $pgdumpall->AddFile('src/bin/pg_dump/pg_dumpall.c'); $pgdumpall->AddFile('src/bin/pg_dump/dumputils.c'); - $pgdumpall->AddFile('src/bin/pg_dump/keywords.c'); - $pgdumpall->AddFile('src/backend/parser/kwlookup.c'); $pgdumpall->AddLibrary('ws2_32.lib'); my $pgrestore = AddSimpleFrontend('pg_dump', 1); $pgrestore->{name} = 'pg_restore'; $pgrestore->AddIncludeDir('src/backend'); $pgrestore->AddFile('src/bin/pg_dump/pg_restore.c'); - $pgrestore->AddFile('src/bin/pg_dump/keywords.c'); - $pgrestore->AddFile('src/backend/parser/kwlookup.c'); $pgrestore->AddLibrary('ws2_32.lib'); my $zic = $solution->AddProject('zic', 'exe', 'utils'); @@ -618,15 +613,7 @@ sub mkvcbuild foreach my $f (@files) { $f =~ s/\.o$/\.c/; - if ($f eq 'keywords.c') - { - $proj->AddFile('src/bin/pg_dump/keywords.c'); - } - elsif ($f eq 'kwlookup.c') - { - $proj->AddFile('src/backend/parser/kwlookup.c'); - } - elsif ($f eq 'dumputils.c') + if ($f eq 'dumputils.c') { $proj->AddFile('src/bin/pg_dump/dumputils.c'); } -- cgit v1.2.1