- 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.
-/* $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
#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[];
-/* $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"
return TRUE;
} /* EncodeDateOnly() */
-static void
+void
TrimTrailingZeros(char *str)
{
int len = strlen(str);
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
* 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;
-/* $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 <time.h>
#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.
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.
#
# 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 $
#
#-------------------------------------------------------------------------
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)
@$(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) $< .
* 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 $
* ยง
*-------------------------------------------------------------------------
*/
* !!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},
{"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);
}
* 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 <ctype.h>
-
-#include "extern.h"
-#include "preproc.h"
-
/*
* List of (keyword-name, keyword-token-value) pairs.
* !!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},
{"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;
-}
-/* $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
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 *);
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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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.
* !!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},
{"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
*
* 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. */
/*
* 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);
}
+
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
return(CVARIABLE);
}
<SQL>{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)
return(CPP_LINE);
}
<C>{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)
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
-/* $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 */
%{
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"
%type <str> var_declaration type_declaration single_vt_declaration
%type <str> ECPGSetAutocommit on_off variable_declarations ECPGDescribe
%type <str> ECPGAllocateDescr ECPGDeallocateDescr symbol opt_output
-%type <str> ECPGGetDescriptorHeader ECPGColLabel single_var_declaration
+%type <str> ECPGGetDescriptorHeader ECPGColLabel
%type <str> reserved_keyword unreserved_keyword ecpg_interval opt_ecpg_using
%type <str> col_name_keyword precision opt_scale ECPGExecuteImmediateStmt
%type <str> ECPGTypeName using_list ECPGColLabelCommon UsingConst
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; };
}
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("");
};
}
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("*/"));
-/* $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"
*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;