diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 1f3bf095e44462a5782535e91d36f5ee5f0be8a4..1dbed255367fb33fb0c134238dc6fc3d3b17111a 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -2225,5 +2225,9 @@ Tue, 14 Aug 2007 11:46:51 +0200 - Use '$n' for positional variables, '?' is still possible via ecpg option. - Cleaned up the sources a little bit. + +Wed, 22 Aug 2007 08:41:33 +0200 + + - More cleaning up and removed some duplicates. - Set ecpg library version to 6.0. - Set ecpg version to 4.4. diff --git a/src/interfaces/ecpg/pgtypeslib/dt.h b/src/interfaces/ecpg/pgtypeslib/dt.h index 83f8c520c274b31807a828300b1167071e70a52d..c75775ffb5b49391f3c430930d377a14b3df9d8e 100644 --- a/src/interfaces/ecpg/pgtypeslib/dt.h +++ b/src/interfaces/ecpg/pgtypeslib/dt.h @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt.h,v 1.37 2007/08/14 10:01:53 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt.h,v 1.38 2007/08/22 08:20:58 meskes Exp $ */ #ifndef DT_H #define DT_H @@ -310,31 +310,24 @@ do { \ #define TIMESTAMP_IS_NOEND(j) ((j) == DT_NOEND) #define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j)) -int DecodeTimeOnly(char **field, int *ftype, - int nf, int *dtype, - struct tm * tm, fsec_t *fsec, int *tzp); - -int DecodeInterval(char **field, int *ftype, - int nf, int *dtype, - struct tm * tm, fsec_t *fsec); - -int EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str); -int EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str, bool); -int EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str); - -int tm2timestamp(struct tm *, fsec_t, int *, timestamp *); - -int DecodeUnits(int field, char *lowtoken, int *val); - -bool CheckDateTokenTables(void); - -int EncodeDateOnly(struct tm *, int, char *, bool); -void GetEpochTime(struct tm *); -int ParseDateTime(char *, char *, char **, int *, int, int *, char **); -int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, bool); -void j2date(int, int *, int *, int *); -void GetCurrentDateTime(struct tm *); -int date2j(int, int, int); +int DecodeTimeOnly(char **, int *, int, int *, struct tm *, fsec_t *, int *); +int DecodeInterval(char **, int *, int, int *, struct tm *, fsec_t *); +int DecodeTime(char *, int, int *, struct tm *, fsec_t *); +int EncodeTimeOnly(struct tm *, fsec_t, int *, int, char *); +int EncodeDateTime(struct tm *, fsec_t, int *, char **, int, char *, bool); +int EncodeInterval(struct tm *, fsec_t, int, char *); +int tm2timestamp(struct tm *, fsec_t, int *, timestamp *); +int DecodeUnits(int field, char *lowtoken, int *val); +bool CheckDateTokenTables(void); +int EncodeDateOnly(struct tm *, int, char *, bool); +void GetEpochTime(struct tm *); +int ParseDateTime(char *, char *, char **, int *, int, int *, char **); +int DecodeDateTime(char **, int *, int, int *, struct tm *, fsec_t *, bool); +void j2date(int, int *, int *, int *); +void GetCurrentDateTime(struct tm *); +int date2j(int, int, int); +void TrimTrailingZeros(char *); +void dt2time(double, int *, int *, int *, fsec_t *); extern char *pgtypes_date_weekdays_short[]; extern char *pgtypes_date_months[]; diff --git a/src/interfaces/ecpg/pgtypeslib/dt_common.c b/src/interfaces/ecpg/pgtypeslib/dt_common.c index 53dc325a465bbb44623d6e7737d9501cfe840304..299186ec02a23431e78527d682c5fe792c289432 100644 --- a/src/interfaces/ecpg/pgtypeslib/dt_common.c +++ b/src/interfaces/ecpg/pgtypeslib/dt_common.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.41 2007/08/14 10:01:53 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.42 2007/08/22 08:20:58 meskes Exp $ */ #include "postgres_fe.h" @@ -743,7 +743,7 @@ EncodeDateOnly(struct tm * tm, int style, char *str, bool EuroDates) return TRUE; } /* EncodeDateOnly() */ -static void +void TrimTrailingZeros(char *str) { int len = strlen(str); @@ -1090,7 +1090,7 @@ GetCurrentDateTime(struct tm * tm) abstime2tm(time(NULL), &tz, tm, NULL); } -static void +void dt2time(double jd, int *hour, int *min, int *sec, fsec_t *fsec) { #ifdef HAVE_INT64_TIMESTAMP @@ -1469,7 +1469,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm, bool EuroDates) * Only check the lower limit on hours, since this same code * can be used to represent time spans. */ -static int +int DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec) { char *cp; diff --git a/src/interfaces/ecpg/pgtypeslib/interval.c b/src/interfaces/ecpg/pgtypeslib/interval.c index 534acdcc5fd77379325acffb05f2c64f312ca289..a8f1899fdb3c08bd6280a790dcb3814ac6ee6a1e 100644 --- a/src/interfaces/ecpg/pgtypeslib/interval.c +++ b/src/interfaces/ecpg/pgtypeslib/interval.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/interval.c,v 1.36 2006/10/04 00:30:11 momjian Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/interval.c,v 1.37 2007/08/22 08:20:58 meskes Exp $ */ #include "postgres_fe.h" #include @@ -13,90 +13,6 @@ #include "pgtypes_error.h" #include "pgtypes_interval.h" -/* TrimTrailingZeros() - * ... resulting from printing numbers with full precision. - */ -static void -TrimTrailingZeros(char *str) -{ - int len = strlen(str); - - /* chop off trailing zeros... but leave at least 2 fractional digits */ - while (*(str + len - 1) == '0' && *(str + len - 3) != '.') - { - len--; - *(str + len) = '\0'; - } -} - -/* DecodeTime() - * Decode time string which includes delimiters. - * Only check the lower limit on hours, since this same code - * can be used to represent time spans. - */ -static int -DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec) -{ - char *cp; - - *tmask = DTK_TIME_M; - - tm->tm_hour = strtol(str, &cp, 10); - if (*cp != ':') - return -1; - str = cp + 1; - tm->tm_min = strtol(str, &cp, 10); - if (*cp == '\0') - { - tm->tm_sec = 0; - *fsec = 0; - } - else if (*cp != ':') - return -1; - else - { - str = cp + 1; - tm->tm_sec = strtol(str, &cp, 10); - if (*cp == '\0') - *fsec = 0; - else if (*cp == '.') - { -#ifdef HAVE_INT64_TIMESTAMP - char fstr[MAXDATELEN + 1]; - - /* - * OK, we have at most six digits to work with. Let's construct a - * string and then do the conversion to an integer. - */ - strncpy(fstr, (cp + 1), 7); - strcpy(fstr + strlen(fstr), "000000"); - *(fstr + 6) = '\0'; - *fsec = strtol(fstr, &cp, 10); -#else - str = cp; - *fsec = strtod(str, &cp); -#endif - if (*cp != '\0') - return -1; - } - else - return -1; - } - - /* do a sanity check */ -#ifdef HAVE_INT64_TIMESTAMP - if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 || - tm->tm_sec < 0 || tm->tm_sec > 59 || *fsec >= USECS_PER_SEC) - return -1; -#else - if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 || - tm->tm_sec < 0 || tm->tm_sec > 59 || *fsec >= 1) - return -1; -#endif - - return 0; -} /* DecodeTime() */ - /* DecodeInterval() * Interpret previously parsed fields for general time interval. * Return 0 if decoded and -1 if problems. diff --git a/src/interfaces/ecpg/pgtypeslib/timestamp.c b/src/interfaces/ecpg/pgtypeslib/timestamp.c index 4ec94672bb9402941ed77b38d5d7179d272b03eb..03aa5f07d08795abdec6c95c44efecc384390afa 100644 --- a/src/interfaces/ecpg/pgtypeslib/timestamp.c +++ b/src/interfaces/ecpg/pgtypeslib/timestamp.c @@ -97,36 +97,6 @@ SetEpochTimestamp(void) return dt; } /* SetEpochTimestamp() */ -static void -dt2time(timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec) -{ -#ifdef HAVE_INT64_TIMESTAMP - int64 time; -#else - double time; -#endif - - time = jd; - -#ifdef HAVE_INT64_TIMESTAMP - *hour = time / USECS_PER_HOUR; - time -= (*hour) * USECS_PER_HOUR; - *min = time / USECS_PER_MINUTE; - time -= (*min) * USECS_PER_MINUTE; - *sec = time / USECS_PER_SEC; - *fsec = time - *sec * USECS_PER_SEC; - *sec = time / USECS_PER_SEC; - *fsec = time - *sec * USECS_PER_SEC; -#else - *hour = time / SECS_PER_HOUR; - time -= (*hour) * SECS_PER_HOUR; - *min = time / SECS_PER_MINUTE; - time -= (*min) * SECS_PER_MINUTE; - *sec = time; - *fsec = time - *sec; -#endif -} /* dt2time() */ - /* timestamp2tm() * Convert timestamp data type to POSIX time structure. * Note that year is _not_ 1900-based, but is an explicit full value. diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index 6d8826608798eed09923b908a93def199228bd27..16f26fafdeb7719559452d8940dae6abb15883a7 100644 --- a/src/interfaces/ecpg/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -4,7 +4,7 @@ # # Copyright (c) 1998-2007, PostgreSQL Global Development Group # -# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.127 2007/08/14 10:01:53 meskes Exp $ +# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.128 2007/08/22 08:20:58 meskes Exp $ # #------------------------------------------------------------------------- @@ -27,7 +27,7 @@ override CFLAGS += -Wno-error endif override CFLAGS += $(PTHREAD_CFLAGS) -OBJS= preproc.o type.o ecpg.o ecpg_keywords.o output.o parser.o \ +OBJS= preproc.o type.o ecpg.o output.o parser.o \ keywords.o c_keywords.o ../ecpglib/typename.o descriptor.o variable.o \ $(WIN32RES) @@ -57,7 +57,7 @@ else @$(missing) flex $< $@ endif -c_keywords.o ecpg_keywords.o keywords.o preproc.o parser.o: preproc.h +c_keywords.o keywords.o preproc.o parser.o: preproc.h parser.c: $(top_srcdir)/src/backend/parser/parser.c rm -f $@ && $(LN_S) $< . diff --git a/src/interfaces/ecpg/preproc/c_keywords.c b/src/interfaces/ecpg/preproc/c_keywords.c index e58831008d8b8ae7528af6ffb4739f7f7a312f5e..bd76ac15e64690223482c1158e236edc20612bc9 100644 --- a/src/interfaces/ecpg/preproc/c_keywords.c +++ b/src/interfaces/ecpg/preproc/c_keywords.c @@ -3,7 +3,7 @@ * keywords.c * lexical token lookup for reserved words in postgres embedded SQL * - * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/c_keywords.c,v 1.20 2007/05/10 09:53:16 meskes Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/c_keywords.c,v 1.21 2007/08/22 08:20:58 meskes Exp $ * ยง *------------------------------------------------------------------------- */ @@ -20,7 +20,7 @@ * !!WARNING!!: This list must be sorted, because binary * search is used to locate entries. */ -static ScanKeyword ScanKeywords[] = { +static const ScanKeyword ScanCKeywords[] = { /* name value */ {"VARCHAR", VARCHAR}, {"auto", S_AUTO}, @@ -50,25 +50,8 @@ static ScanKeyword ScanKeywords[] = { {"year", YEAR_P}, }; -ScanKeyword * +const ScanKeyword * ScanCKeywordLookup(char *text) { - ScanKeyword *low = &ScanKeywords[0]; - ScanKeyword *high = endof(ScanKeywords) - 1; - ScanKeyword *middle; - int difference; - - while (low <= high) - { - middle = low + (high - low) / 2; - difference = strcmp(middle->name, text); - if (difference == 0) - return middle; - else if (difference < 0) - low = middle + 1; - else - high = middle - 1; - } - - return NULL; + return DoLookup(text, &ScanCKeywords[0], endof(ScanCKeywords) - 1); } diff --git a/src/interfaces/ecpg/preproc/ecpg_keywords.c b/src/interfaces/ecpg/preproc/ecpg_keywords.c index 3244880151b138124a874e98e685babc25d078e5..6155bc1f7359b7e1129df29903c47ba23580e5a5 100644 --- a/src/interfaces/ecpg/preproc/ecpg_keywords.c +++ b/src/interfaces/ecpg/preproc/ecpg_keywords.c @@ -4,17 +4,10 @@ * lexical token lookup for reserved words in postgres embedded SQL * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg_keywords.c,v 1.35 2007/06/12 07:55:56 meskes Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg_keywords.c,v 1.36 2007/08/22 08:20:58 meskes Exp $ * *------------------------------------------------------------------------- */ -#include "postgres_fe.h" - -#include - -#include "extern.h" -#include "preproc.h" - /* * List of (keyword-name, keyword-token-value) pairs. @@ -22,7 +15,7 @@ * !!WARNING!!: This list must be sorted, because binary * search is used to locate entries. */ -static ScanKeyword ScanKeywords[] = { +static const ScanKeyword ScanECPGKeywords[] = { /* name value */ {"allocate", SQL_ALLOCATE}, {"autocommit", SQL_AUTOCOMMIT}, @@ -71,69 +64,3 @@ static ScanKeyword ScanKeywords[] = { {"whenever", SQL_WHENEVER}, }; -/* - * ScanECPGKeywordLookup - 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. - */ -ScanKeyword * -ScanECPGKeywordLookup(char *text) -{ - int len, - i; - char word[NAMEDATALEN]; - ScanKeyword *low; - 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), and we - * don't trust isupper() very much either. In an ASCII-based encoding the - * tests against A and Z are sufficient, but we also check isupper() so - * that we will work correctly under EBCDIC. The actual case conversion - * step should work for either ASCII or EBCDIC. - */ - for (i = 0; i < len; i++) - { - char ch = text[i]; - - if (ch >= 'A' && ch <= 'Z' && isupper((unsigned char) ch)) - ch += 'a' - 'A'; - word[i] = ch; - } - word[len] = '\0'; - - /* - * Now do a binary search using plain strcmp() comparison. - */ - low = &ScanKeywords[0]; - high = endof(ScanKeywords) - 1; - while (low <= high) - { - 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/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index 8b5b864611063d1db4aafa25b0e223db01396f72..ecd646100eb951fd202ca2c033c28c68ff9e2e24 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.68 2007/08/14 10:54:57 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/extern.h,v 1.69 2007/08/22 08:20:58 meskes Exp $ */ #ifndef _ECPG_PREPROC_EXTERN_H #define _ECPG_PREPROC_EXTERN_H @@ -74,8 +74,7 @@ extern void base_yyerror(const char *); extern void *mm_alloc(size_t), *mm_realloc(void *, size_t); extern char *mm_strdup(const char *); extern void mmerror(int, enum errortype, char *,...); -extern ScanKeyword *ScanECPGKeywordLookup(char *); -extern ScanKeyword *ScanCKeywordLookup(char *); +extern const ScanKeyword *ScanCKeywordLookup(char *); extern void output_get_descr_header(char *); extern void output_get_descr(char *, char *); extern void output_set_descr_header(char *); @@ -97,7 +96,8 @@ extern void check_indicator(struct ECPGtype *); extern void remove_typedefs(int); extern void remove_variables(int); extern struct variable *new_variable(const char *, struct ECPGtype *, int); -extern ScanKeyword *ScanKeywordLookup(char *text); +extern const ScanKeyword *ScanKeywordLookup(char *text); +extern const ScanKeyword *DoLookup(char *, const ScanKeyword *,const ScanKeyword *); extern void scanner_init(const char *); extern void parser_init(void); extern void scanner_finish(void); diff --git a/src/interfaces/ecpg/preproc/keywords.c b/src/interfaces/ecpg/preproc/keywords.c index f2f3094e06c090922ee284ba52aa218684e7b1d3..5c87e5cd13b21167ef80cf94b281c213f2f2433d 100644 --- a/src/interfaces/ecpg/preproc/keywords.c +++ b/src/interfaces/ecpg/preproc/keywords.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.80 2007/06/12 07:55:56 meskes Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.81 2007/08/22 08:20:58 meskes Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,8 @@ #include "extern.h" #include "preproc.h" +/* compile both keyword lists in one file because they are always scanned together */ +#include "ecpg_keywords.c" /* * List of (keyword-name, keyword-token-value) pairs. @@ -26,7 +28,7 @@ * !!WARNING!!: This list must be sorted, because binary * search is used to locate entries. */ -static ScanKeyword ScanKeywords[] = { +static const ScanKeyword ScanPGSQLKeywords[] = { /* name, value */ {"abort", ABORT_P}, {"absolute", ABSOLUTE_P}, @@ -395,6 +397,31 @@ static ScanKeyword ScanKeywords[] = { {"zone", ZONE}, }; + +/* + * Now do a binary search using plain strcmp() comparison. + */ +const ScanKeyword * +DoLookup(char *word, const ScanKeyword *low, const ScanKeyword *high) +{ + 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; +} + /* * ScanKeywordLookup - see if a given word is a keyword * @@ -407,14 +434,13 @@ static ScanKeyword ScanKeywords[] = { * keywords are to be matched in this way even though non-keyword identifiers * receive a different case-normalization mapping. */ -ScanKeyword * +const ScanKeyword * ScanKeywordLookup(char *text) { int len, i; char word[NAMEDATALEN]; - ScanKeyword *low; - ScanKeyword *high; + const ScanKeyword *res; len = strlen(text); /* We assume all keywords are shorter than NAMEDATALEN. */ @@ -438,22 +464,10 @@ ScanKeywordLookup(char *text) /* * Now do a binary search using plain strcmp() comparison. */ - low = &ScanKeywords[0]; - high = endof(ScanKeywords) - 1; - while (low <= high) - { - 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; - } + res = DoLookup(word, &ScanPGSQLKeywords[0], endof(ScanPGSQLKeywords) - 1); + if (res) + return res; - return NULL; + return DoLookup(word, &ScanECPGKeywords[0], endof(ScanECPGKeywords) - 1); } + diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 23f22071225d6403e8605dcfc65ee0a934ce8c80..c9ba3431ce68d41eda386e677fda5000bf1fb0b7 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.153 2007/08/14 10:01:53 meskes Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.154 2007/08/22 08:20:58 meskes Exp $ * *------------------------------------------------------------------------- */ @@ -49,6 +49,7 @@ static void addlitchar (unsigned char); static void parse_include (void); static void check_escape_warning(void); static bool ecpg_isspace(char ch); +static bool isdefine(void); char *token_start; int state_before; @@ -681,41 +682,15 @@ cppline {space}*#(.*\\{space})*.*{newline} return(CVARIABLE); } {identifier} { - ScanKeyword *keyword; - struct _defines *ptr; + const ScanKeyword *keyword; - /* How about a DEFINE? */ - for (ptr = defines; ptr; ptr = ptr->next) - { - if (strcmp(yytext, ptr->old) == 0 && ptr->used == NULL) - { - struct _yy_buffer *yb; - - yb = mm_alloc(sizeof(struct _yy_buffer)); - - yb->buffer = YY_CURRENT_BUFFER; - yb->lineno = yylineno; - yb->filename = mm_strdup(input_filename); - yb->next = yy_buffer; - - ptr->used = yy_buffer = yb; - - yy_scan_string(ptr->new); - break; - } - } - if (ptr == NULL) + if (!isdefine()) { - /* Is it an SQL keyword? */ + /* Is it an SQL/ECPG keyword? */ keyword = ScanKeywordLookup(yytext); if (keyword != NULL) return keyword->value; - /* Is it an ECPG keyword? */ - keyword = ScanECPGKeywordLookup( yytext); - if (keyword != NULL) - return keyword->value; - /* Is it a C keyword? */ keyword = ScanCKeywordLookup(yytext); if (keyword != NULL) @@ -775,39 +750,9 @@ cppline {space}*#(.*\\{space})*.*{newline} return(CPP_LINE); } {identifier} { - ScanKeyword *keyword; - struct _defines *ptr; - - if (INFORMIX_MODE) - { - /* Informix uses SQL defines only in SQL space */ - ptr = NULL; - } - else - { - /* is it a define? */ - for (ptr = defines; ptr; ptr = ptr->next) - { - if (strcmp(yytext, ptr->old) == 0 && ptr->used == NULL) - { - struct _yy_buffer *yb; - - yb = mm_alloc(sizeof(struct _yy_buffer)); - - yb->buffer = YY_CURRENT_BUFFER; - yb->lineno = yylineno; - yb->filename = mm_strdup(input_filename); - yb->next = yy_buffer; + const ScanKeyword *keyword; - ptr->used = yy_buffer = yb; - - yy_scan_string(ptr->new); - break; - } - } - } - - if (ptr == NULL) + if (INFORMIX_MODE || !isdefine()) { keyword = ScanCKeywordLookup(yytext); if (keyword != NULL) @@ -1359,6 +1304,33 @@ ecpg_isspace(char ch) return false; } +static bool isdefine(void) +{ + struct _defines *ptr; + + /* is it a define? */ + for (ptr = defines; ptr; ptr = ptr->next) + { + if (strcmp(yytext, ptr->old) == 0 && ptr->used == NULL) + { + struct _yy_buffer *yb; + + yb = mm_alloc(sizeof(struct _yy_buffer)); + + yb->buffer = YY_CURRENT_BUFFER; + yb->lineno = yylineno; + yb->filename = mm_strdup(input_filename); + yb->next = yy_buffer; + + ptr->used = yy_buffer = yb; + + yy_scan_string(ptr->new); + return true; + } + } + + return false; +} /* * Called before any actual parsing is done diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 6d665392f5e4815c12177a51b18eebd00df9a764..ffbb7f7844dcd296ffd4e32027ad85048ad4906d 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.349 2007/08/14 10:01:53 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.350 2007/08/22 08:20:58 meskes Exp $ */ /* Copyright comment */ %{ @@ -319,6 +319,51 @@ add_additional_variables(char *name, bool insert) return ptr; } + +static void +add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enum, char *type_dimension, char *type_index, int initializer, int array) +{ + /* add entry to list */ + struct typedefs *ptr, *this; + + if ((type_enum == ECPGt_struct || + type_enum == ECPGt_union) && + initializer == 1) + mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in typedef command"); + else + { + for (ptr = types; ptr != NULL; ptr = ptr->next) + { + if (strcmp(name, ptr->name) == 0) + /* re-definition is a bug */ + mmerror(PARSE_ERROR, ET_ERROR, "Type %s already defined", name); + } + adjust_array(type_enum, &dimension, &length, type_dimension, type_index, array, true); + + this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); + + /* initial definition */ + this->next = types; + this->name = name; + this->brace_level = braces_open; + this->type = (struct this_type *) mm_alloc(sizeof(struct this_type)); + this->type->type_enum = type_enum; + this->type->type_str = mm_strdup(name); + this->type->type_dimension = dimension; /* dimension of array */ + this->type->type_index = length; /* length of string */ + this->type->type_sizeof = ECPGstruct_sizeof; + this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ? + ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL; + + if (type_enum != ECPGt_varchar && + type_enum != ECPGt_char && + type_enum != ECPGt_unsigned_char && + atoi(this->type->type_index) >= 0) + mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types"); + + types = this; + } +} %} %name-prefix="base_yy" @@ -597,7 +642,7 @@ add_additional_variables(char *name, bool insert) %type var_declaration type_declaration single_vt_declaration %type ECPGSetAutocommit on_off variable_declarations ECPGDescribe %type ECPGAllocateDescr ECPGDeallocateDescr symbol opt_output -%type ECPGGetDescriptorHeader ECPGColLabel single_var_declaration +%type ECPGGetDescriptorHeader ECPGColLabel %type reserved_keyword unreserved_keyword ecpg_interval opt_ecpg_using %type col_name_keyword precision opt_scale ECPGExecuteImmediateStmt %type ECPGTypeName using_list ECPGColLabelCommon UsingConst @@ -5124,40 +5169,7 @@ ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring ECPGVarDeclaration: single_vt_declaration; single_vt_declaration: type_declaration { $$ = $1; } - | single_var_declaration { $$ = $1; } - ; - -single_var_declaration: storage_declaration - var_type - { - actual_type[struct_level].type_enum = $2.type_enum; - actual_type[struct_level].type_dimension = $2.type_dimension; - actual_type[struct_level].type_index = $2.type_index; - actual_type[struct_level].type_sizeof = $2.type_sizeof; - - actual_startline[struct_level] = hashline_number(); - } - variable_list ';' - { - $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n")); - } - | var_type - { - actual_type[struct_level].type_enum = $1.type_enum; - actual_type[struct_level].type_dimension = $1.type_dimension; - actual_type[struct_level].type_index = $1.type_index; - actual_type[struct_level].type_sizeof = $1.type_sizeof; - - actual_startline[struct_level] = hashline_number(); - } - variable_list ';' - { - $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, make_str(";\n")); - } - | struct_union_type_with_symbol ';' - { - $$ = cat2_str($1, make_str(";")); - } + | var_declaration { $$ = $1; } ; precision: NumConst { $$ = $1; }; @@ -5214,50 +5226,9 @@ type_declaration: S_TYPEDEF } var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';' { - /* add entry to list */ - struct typedefs *ptr, *this; - char * dimension = $6.index1; - char * length = $6.index2; - - if (($3.type_enum == ECPGt_struct || - $3.type_enum == ECPGt_union) && - initializer == 1) - mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in typedef command"); - else - { - for (ptr = types; ptr != NULL; ptr = ptr->next) - { - if (strcmp($5, ptr->name) == 0) - /* re-definition is a bug */ - mmerror(PARSE_ERROR, ET_ERROR, "Type %s already defined", $5); - } - adjust_array($3.type_enum, &dimension, &length, $3.type_dimension, $3.type_index, *$4?1:0, true); - - this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); + add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0); - /* initial definition */ - this->next = types; - this->name = $5; - this->brace_level = braces_open; - this->type = (struct this_type *) mm_alloc(sizeof(struct this_type)); - this->type->type_enum = $3.type_enum; - this->type->type_str = mm_strdup($5); - this->type->type_dimension = dimension; /* dimension of array */ - this->type->type_index = length; /* length of string */ - this->type->type_sizeof = ECPGstruct_sizeof; - this->struct_member_list = ($3.type_enum == ECPGt_struct || $3.type_enum == ECPGt_union) ? - ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL; - - if ($3.type_enum != ECPGt_varchar && - $3.type_enum != ECPGt_char && - $3.type_enum != ECPGt_unsigned_char && - atoi(this->type->type_index) >= 0) - mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types"); - - types = this; - } - - fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4?"*":"", $5, $6.str); + fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str); output_line_number(); $$ = make_str(""); }; @@ -6046,49 +6017,7 @@ ECPGTypedef: TYPE_P } ECPGColLabelCommon IS var_type opt_array_bounds opt_reference { - /* add entry to list */ - struct typedefs *ptr, *this; - char *dimension = $6.index1; - char *length = $6.index2; - - if (($5.type_enum == ECPGt_struct || - $5.type_enum == ECPGt_union) && - initializer == 1) - mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL TYPE command"); - else - { - for (ptr = types; ptr != NULL; ptr = ptr->next) - { - if (strcmp($3, ptr->name) == 0) - /* re-definition is a bug */ - mmerror(PARSE_ERROR, ET_ERROR, "Type %s already defined", $3); - } - - adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false); - - this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); - - /* initial definition */ - this->next = types; - this->name = $3; - this->brace_level = braces_open; - this->type = (struct this_type *) mm_alloc(sizeof(struct this_type)); - this->type->type_enum = $5.type_enum; - this->type->type_str = mm_strdup($3); - this->type->type_dimension = dimension; /* dimension of array */ - this->type->type_index = length; /* length of string */ - this->type->type_sizeof = ECPGstruct_sizeof; - this->struct_member_list = ($5.type_enum == ECPGt_struct || $5.type_enum == ECPGt_union) ? - ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL; - - if ($5.type_enum != ECPGt_varchar && - $5.type_enum != ECPGt_char && - $5.type_enum != ECPGt_unsigned_char && - atoi(this->type->type_index) >= 0) - mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types"); - - types = this; - } + add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0); if (auto_create_c == false) $$ = cat_str(7, make_str("/* exec sql type"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/")); diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index 464c54ed648ea7f07beab32034b2e1e0eb981f72..18708217e039aa7b9c83e05d7369a3be0a6aeffc 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.c,v 1.73 2007/08/14 10:01:53 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.c,v 1.74 2007/08/22 08:20:58 meskes Exp $ */ #include "postgres_fe.h" @@ -80,7 +80,7 @@ ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_mem *ne = (struct ECPGstruct_member *) mm_alloc(sizeof(struct ECPGstruct_member)); - ne->name = strdup(name); + ne->name = mm_strdup(name); ne->type = type; ne->next = NULL;