handle-unreserved-typedef-names-1.patch
text/x-diff
Filename: handle-unreserved-typedef-names-1.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/interfaces/ecpg/preproc/ecpg.trailer | 117 | 53 |
| src/interfaces/ecpg/preproc/ecpg.type | 0 | 1 |
| src/interfaces/ecpg/preproc/pgc.l | 13 | 4 |
| src/interfaces/ecpg/preproc/preproc_extern.h | 1 | 1 |
| src/interfaces/ecpg/preproc/variable.c | 9 | 4 |
diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer
index b95fc44314..fba35f6be6 100644
--- a/src/interfaces/ecpg/preproc/ecpg.trailer
+++ b/src/interfaces/ecpg/preproc/ecpg.trailer
@@ -564,8 +564,29 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- | ECPGColLabelCommon '(' precision opt_scale ')'
+ | NUMERIC '(' precision opt_scale ')'
{
+ $$.type_enum = ECPGt_numeric;
+ $$.type_str = mm_strdup("numeric");
+ $$.type_dimension = mm_strdup("-1");
+ $$.type_index = mm_strdup("-1");
+ $$.type_sizeof = NULL;
+ }
+ | DECIMAL_P '(' precision opt_scale ')'
+ {
+ $$.type_enum = ECPGt_decimal;
+ $$.type_str = mm_strdup("decimal");
+ $$.type_dimension = mm_strdup("-1");
+ $$.type_index = mm_strdup("-1");
+ $$.type_sizeof = NULL;
+ }
+ | IDENT '(' precision opt_scale ')'
+ {
+ /*
+ * In C parsing mode, NUMERIC and DECIMAL are not keywords, so
+ * they will show up here as a plain identifier, and we need
+ * this duplicate code to recognize them.
+ */
if (strcmp($1, "numeric") == 0)
{
$$.type_enum = ECPGt_numeric;
@@ -587,15 +608,98 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- | ECPGColLabelCommon ecpg_interval
+ | VARCHAR
{
- if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
- mmerror (PARSE_ERROR, ET_ERROR, "interval specification not allowed here");
+ $$.type_enum = ECPGt_varchar;
+ $$.type_str = EMPTY; /*mm_strdup("varchar");*/
+ $$.type_dimension = mm_strdup("-1");
+ $$.type_index = mm_strdup("-1");
+ $$.type_sizeof = NULL;
+ }
+ | FLOAT_P
+ {
+ /* Note: DOUBLE is handled in simple_type */
+ $$.type_enum = ECPGt_float;
+ $$.type_str = mm_strdup("float");
+ $$.type_dimension = mm_strdup("-1");
+ $$.type_index = mm_strdup("-1");
+ $$.type_sizeof = NULL;
+ }
+ | NUMERIC
+ {
+ $$.type_enum = ECPGt_numeric;
+ $$.type_str = mm_strdup("numeric");
+ $$.type_dimension = mm_strdup("-1");
+ $$.type_index = mm_strdup("-1");
+ $$.type_sizeof = NULL;
+ }
+ | DECIMAL_P
+ {
+ $$.type_enum = ECPGt_decimal;
+ $$.type_str = mm_strdup("decimal");
+ $$.type_dimension = mm_strdup("-1");
+ $$.type_index = mm_strdup("-1");
+ $$.type_sizeof = NULL;
+ }
+ | TIMESTAMP
+ {
+ $$.type_enum = ECPGt_timestamp;
+ $$.type_str = mm_strdup("timestamp");
+ $$.type_dimension = mm_strdup("-1");
+ $$.type_index = mm_strdup("-1");
+ $$.type_sizeof = NULL;
+ }
+ | INTERVAL ecpg_interval
+ {
+ $$.type_enum = ECPGt_interval;
+ $$.type_str = mm_strdup("interval");
+ $$.type_dimension = mm_strdup("-1");
+ $$.type_index = mm_strdup("-1");
+ $$.type_sizeof = NULL;
+ }
+ | STRING
+ {
+ if (INFORMIX_MODE)
+ {
+ /* In Informix mode, "string" is automatically a typedef */
+ $$.type_enum = ECPGt_string;
+ $$.type_str = mm_strdup("char");
+ $$.type_dimension = mm_strdup("-1");
+ $$.type_index = mm_strdup("-1");
+ $$.type_sizeof = NULL;
+ }
+ else
+ {
+ /* Otherwise, legal only if user typedef'ed it */
+ struct typedefs *this = get_typedef("string", false);
+
+ $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name);
+ $$.type_enum = this->type->type_enum;
+ $$.type_dimension = this->type->type_dimension;
+ $$.type_index = this->type->type_index;
+ if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
+ $$.type_sizeof = this->type->type_sizeof;
+ else
+ $$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")"));
+ struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+ }
+ }
+ | IDENT ecpg_interval
+ {
/*
- * Check for type names that the SQL grammar treats as
- * unreserved keywords
+ * In C parsing mode, the above SQL type names are not keywords,
+ * so they will show up here as a plain identifier, and we need
+ * this duplicate code to recognize them.
+ *
+ * Note that we also handle the type names bytea, date, and
+ * datetime here, but not above because those are not currently
+ * SQL keywords. If they ever become so, they must gain duplicate
+ * productions above.
*/
+ if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
+ mmerror (PARSE_ERROR, ET_ERROR, "interval specification not allowed here");
+
if (strcmp($1, "varchar") == 0)
{
$$.type_enum = ECPGt_varchar;
@@ -686,45 +790,8 @@ var_type: simple_type
}
else
{
- /* this is for typedef'ed types */
- struct typedefs *this = get_typedef($1);
-
- $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name);
- $$.type_enum = this->type->type_enum;
- $$.type_dimension = this->type->type_dimension;
- $$.type_index = this->type->type_index;
- if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
- $$.type_sizeof = this->type->type_sizeof;
- else
- $$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")"));
-
- struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
- }
- }
- | STRING
- {
- /*
- * It's quite horrid that ECPGColLabelCommon excludes
- * unreserved_keyword, meaning that unreserved keywords can't be
- * used as type names in var_type. However, this is hard to avoid
- * since what follows ecpgstart can be either a random SQL
- * statement or an ECPGVarDeclaration (beginning with var_type).
- * Pending a bright idea about how to fix that, we must
- * special-case STRING (and any other unreserved keywords that are
- * likely to be needed here).
- */
- if (INFORMIX_MODE)
- {
- $$.type_enum = ECPGt_string;
- $$.type_str = mm_strdup("char");
- $$.type_dimension = mm_strdup("-1");
- $$.type_index = mm_strdup("-1");
- $$.type_sizeof = NULL;
- }
- else
- {
- /* this is for typedef'ed types */
- struct typedefs *this = get_typedef("string");
+ /* Otherwise, it must be a user-defined typedef name */
+ struct typedefs *this = get_typedef($1, false);
$$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name);
$$.type_enum = this->type->type_enum;
@@ -751,7 +818,7 @@ var_type: simple_type
{
/* No */
- this = get_typedef(name);
+ this = get_typedef(name, false);
$$.type_str = mm_strdup(this->name);
$$.type_enum = this->type->type_enum;
$$.type_dimension = this->type->type_dimension;
@@ -1657,17 +1724,14 @@ ColLabel: ECPGColLabel { $$ = $1; }
| ECPGunreserved_interval { $$ = $1; }
;
-ECPGColLabel: ECPGColLabelCommon { $$ = $1; }
+ECPGColLabel: ecpg_ident { $$ = $1; }
| unreserved_keyword { $$ = $1; }
- | reserved_keyword { $$ = $1; }
- | ECPGKeywords_rest { $$ = $1; }
- | CONNECTION { $$ = mm_strdup("connection"); }
- ;
-
-ECPGColLabelCommon: ecpg_ident { $$ = $1; }
| col_name_keyword { $$ = $1; }
| type_func_name_keyword { $$ = $1; }
+ | reserved_keyword { $$ = $1; }
| ECPGKeywords_vanames { $$ = $1; }
+ | ECPGKeywords_rest { $$ = $1; }
+ | CONNECTION { $$ = mm_strdup("connection"); }
;
ECPGCKeywords: S_AUTO { $$ = mm_strdup("auto"); }
diff --git a/src/interfaces/ecpg/preproc/ecpg.type b/src/interfaces/ecpg/preproc/ecpg.type
index d1cde691c0..4fe80a5a4b 100644
--- a/src/interfaces/ecpg/preproc/ecpg.type
+++ b/src/interfaces/ecpg/preproc/ecpg.type
@@ -3,7 +3,6 @@
%type <str> ECPGCKeywords
%type <str> ECPGColId
%type <str> ECPGColLabel
-%type <str> ECPGColLabelCommon
%type <str> ECPGConnect
%type <str> ECPGCursorStmt
%type <str> ECPGDeallocateDescr
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index 996718cb8a..c344f8f30f 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -983,10 +983,19 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
{
int kwvalue;
- /* Is it an SQL/ECPG keyword? */
- kwvalue = ScanECPGKeywordLookup(yytext);
- if (kwvalue >= 0)
- return kwvalue;
+ /*
+ * User-defined typedefs override SQL keywords, but
+ * not C keywords. Currently, a typedef name is just
+ * reported as IDENT, but someday we might need to
+ * return a distinct token type.
+ */
+ if (get_typedef(yytext, true) == NULL)
+ {
+ /* Is it an SQL/ECPG keyword? */
+ kwvalue = ScanECPGKeywordLookup(yytext);
+ if (kwvalue >= 0)
+ return kwvalue;
+ }
/* Is it a C keyword? */
kwvalue = ScanCKeywordLookup(yytext);
diff --git a/src/interfaces/ecpg/preproc/preproc_extern.h b/src/interfaces/ecpg/preproc/preproc_extern.h
index 992797b8bb..6be59b7193 100644
--- a/src/interfaces/ecpg/preproc/preproc_extern.h
+++ b/src/interfaces/ecpg/preproc/preproc_extern.h
@@ -93,7 +93,7 @@ extern void add_variable_to_head(struct arguments **, struct variable *, struct
extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
extern void remove_variable_from_list(struct arguments **list, struct variable *var);
extern void dump_variables(struct arguments *, int);
-extern struct typedefs *get_typedef(char *);
+extern struct typedefs *get_typedef(const char *name, bool noerror);
extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool);
extern void reset_variables(void);
extern void check_indicator(struct ECPGtype *);
diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c
index 887d479e73..2a2b953118 100644
--- a/src/interfaces/ecpg/preproc/variable.c
+++ b/src/interfaces/ecpg/preproc/variable.c
@@ -497,15 +497,20 @@ check_indicator(struct ECPGtype *var)
}
struct typedefs *
-get_typedef(char *name)
+get_typedef(const char *name, bool noerror)
{
struct typedefs *this;
- for (this = types; this && strcmp(this->name, name) != 0; this = this->next);
- if (!this)
+ for (this = types; this != NULL; this = this->next)
+ {
+ if (strcmp(this->name, name) == 0)
+ return this;
+ }
+
+ if (!noerror)
mmfatal(PARSE_ERROR, "unrecognized data type name \"%s\"", name);
- return this;
+ return NULL;
}
void