From c31a80faf0e19973a8ed854bd379e346d5542b19 Mon Sep 17 00:00:00 2001 From: "Marc G. Fournier" Date: Tue, 26 May 1998 13:43:55 +0000 Subject: [PATCH] From: Michael Meskes +Wed May 20 10:46:48 CEST 1998 + + - Fixed handling of preprocessor directives and variable + initialization. + - Added enum datatype. - Set version to 2.3.2 --- src/interfaces/ecpg/ChangeLog | 6 ++ src/interfaces/ecpg/TODO | 2 - src/interfaces/ecpg/lib/typename.c | 5 +- src/interfaces/ecpg/preproc/c_keywords.c | 1 + src/interfaces/ecpg/preproc/ecpg_keywords.c | 2 +- src/interfaces/ecpg/preproc/pgc.l | 11 ++- src/interfaces/ecpg/preproc/preproc.y | 101 +++++++++++++------- src/interfaces/ecpg/preproc/type.c | 3 +- src/interfaces/ecpg/preproc/type.h | 8 +- 9 files changed, 95 insertions(+), 44 deletions(-) diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 2dd35c7b48c..0211c321cb7 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -232,4 +232,10 @@ Tue May 19 11:49:34 CEST 1998 - Tested (and fixed) 'set connection' - Fixed string notation in C + +Wed May 20 10:46:48 CEST 1998 + + - Fixed handling of preprocessor directives and variable + initialization. + - Added enum datatype. - Set version to 2.3.2 diff --git a/src/interfaces/ecpg/TODO b/src/interfaces/ecpg/TODO index cff7d70aeb2..06a818d1e8d 100644 --- a/src/interfaces/ecpg/TODO +++ b/src/interfaces/ecpg/TODO @@ -1,5 +1,3 @@ -ecpg does not understand enum datatypes. - The complete structure definition has to be listed inside the declare section of the structure variable for ecpg to be able to understand it. diff --git a/src/interfaces/ecpg/lib/typename.c b/src/interfaces/ecpg/lib/typename.c index f4c0b160632..9ef1d282526 100644 --- a/src/interfaces/ecpg/lib/typename.c +++ b/src/interfaces/ecpg/lib/typename.c @@ -8,7 +8,8 @@ ECPGtype_name(enum ECPGttype typ) { switch (typ) { - case ECPGt_char:return "char"; + case ECPGt_char: + return "char"; case ECPGt_unsigned_char: return "unsigned char"; case ECPGt_short: @@ -29,6 +30,8 @@ ECPGtype_name(enum ECPGttype typ) return "double"; case ECPGt_bool: return "bool"; + case ECPGt_varchar: + return "varchar"; default: abort(); } diff --git a/src/interfaces/ecpg/preproc/c_keywords.c b/src/interfaces/ecpg/preproc/c_keywords.c index cf93a241f92..ed5501b6113 100644 --- a/src/interfaces/ecpg/preproc/c_keywords.c +++ b/src/interfaces/ecpg/preproc/c_keywords.c @@ -27,6 +27,7 @@ static ScanKeyword ScanKeywords[] = { {"char", S_CHAR}, {"const", S_CONST}, {"double", S_DOUBLE}, + {"enum", S_ENUM}, {"extern", S_EXTERN}, {"float", S_FLOAT}, {"int", S_INT}, diff --git a/src/interfaces/ecpg/preproc/ecpg_keywords.c b/src/interfaces/ecpg/preproc/ecpg_keywords.c index bc724c54b31..f7aac477d5f 100644 --- a/src/interfaces/ecpg/preproc/ecpg_keywords.c +++ b/src/interfaces/ecpg/preproc/ecpg_keywords.c @@ -10,8 +10,8 @@ #include "postgres.h" #include "type.h" -#include "y.tab.h" #include "extern.h" +#include "y.tab.h" /* * List of (keyword-name, keyword-token-value) pairs. diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 6ac025c0fee..eabc4fd6c6d 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -25,11 +25,10 @@ #include "parser/gramparse.h" #include "parser/scansup.h" #include "type.h" +#include "extern.h" #include "y.tab.h" #include "utils/builtins.h" -#include "extern.h" - /* some versions of lex define this as a macro */ #if defined(yywrap) #undef yywrap @@ -160,6 +159,8 @@ exec [eE][xX][eE][cC] include [iI][nN][cC][lL][uU][dD][eE] sql [sS][qQ][lL] +cppline {space}*#.*(\\{space}*\n)*\n* + /* DO NOT PUT ANY COMMENTS IN THE FOLLOWING SECTION. * AT&T lex does not properly handle C-style comments in this second lex block. * So, put comments here. tgl - 1997-09-08 @@ -281,7 +282,7 @@ sql [sS][qQ][lL] memcpy(literal+llen, yytext, yyleng+1); llen += yyleng; } -{xdstart} { +{xdstart} { BEGIN(xdc); llen = 0; *literal = '\0'; @@ -442,6 +443,10 @@ sql [sS][qQ][lL] {exec}{space}{sql} { BEGIN SQL; return SQL_START; } {ccomment} { /* ignore */ } +{cppline} { + yylval.str = strdup((char*)yytext); + return(CPP_LINE); + } {identifier} { ScanKeyword *keyword; diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 53916b23168..138cd601d1c 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -500,6 +500,7 @@ output_statement(char * stmt, int mode) whenever_action(mode); free(stmt); } + %} %union { @@ -509,6 +510,7 @@ output_statement(char * stmt, int mode) struct when action; struct index index; int tagname; + struct this_type type; enum ECPGttype type_enum; } @@ -520,8 +522,8 @@ output_statement(char * stmt, int mode) %token SQL_STOP SQL_WHENEVER /* C token */ -%token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_EXTERN -%token S_FLOAT S_INT +%token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_ENUM S_EXTERN +%token S_FLOAT S_INT S %token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT %token S_UNSIGNED S_VARCHAR @@ -582,7 +584,7 @@ output_statement(char * stmt, int mode) %token PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL /* Special keywords, not in the query language - see the "lex" file */ -%token IDENT SCONST Op CSTRING CVARIABLE +%token IDENT SCONST Op CSTRING CVARIABLE CPP_LINE %token ICONST PARAM %token FCONST @@ -676,12 +678,15 @@ output_statement(char * stmt, int mode) %type blockend variable_list variable var_anything do_anything %type opt_pointer cvariable ECPGDisconnect dis_name %type stmt symbol opt_symbol ECPGRelease execstring server_name -%type connection_object opt_server opt_port +%type connection_object opt_server opt_port c_thing %type user_name opt_user char_variable ora_user ident %type db_prefix server opt_options opt_connection_name -%type ECPGSetConnection +%type ECPGSetConnection c_line cpp_line s_enum +%type enum_type -%type simple_type type struct_type +%type simple_type + +%type type %type action @@ -694,7 +699,8 @@ statements: /* empty */ statement: ecpgstart stmt SQL_SEMI | ECPGDeclaration - | c_anything { fputs($1, yyout); free($1); } + | c_thing { fprintf(yyout, "%s", $1); free($1); } + | cpp_line { fprintf(yyout, "%s", $1); free($1); } | blockstart { fputs($1, yyout); free($1); } | blockend { fputs($1, yyout); free($1); } @@ -3795,29 +3801,49 @@ variable_declarations: /* empty */ declaration: storage_clause type { actual_storage[struct_level] = $1; - actual_type[struct_level] = $2; - if ($2 != ECPGt_varchar && $2 != ECPGt_struct) - fprintf(yyout, "%s %s", $1, ECPGtype_name($2)); + actual_type[struct_level] = $2.type_enum; + if ($2.type_enum != ECPGt_varchar && $2.type_enum != ECPGt_struct) + fprintf(yyout, "%s %s", $1, $2.type_str); + free($2.type_str); } variable_list ';' { fputc(';', yyout); } -storage_clause : S_EXTERN { $$ = make1_str("extern"); } - | S_STATIC { $$ = make1_str("static"); } - | S_SIGNED { $$ = make1_str("signed"); } - | S_CONST { $$ = make1_str("const"); } - | S_REGISTER { $$ = make1_str("register"); } - | S_AUTO { $$ = make1_str("auto"); } - | /* empty */ { $$ = make1_str("") ; } +storage_clause : S_EXTERN { $$ = "extern"; } + | S_STATIC { $$ = "static"; } + | S_SIGNED { $$ = "signed"; } + | S_CONST { $$ = "const"; } + | S_REGISTER { $$ = "register"; } + | S_AUTO { $$ = "auto"; } + | /* empty */ { $$ = ""; } type: simple_type + { + $$.type_enum = $1; + $$.type_str = strdup(ECPGtype_name($1)); + } | struct_type + { + $$.type_enum = ECPGt_struct; + $$.type_str = make1_str(""); + } + | enum_type + { + $$.type_str = $1; + $$.type_enum = ECPGt_int; + } + +enum_type: s_enum '{' c_line '}' + { + $$ = cat4_str($1, make1_str("{"), $3, make1_str("}")); + } + +s_enum: S_ENUM opt_symbol { $$ = cat2_str(make1_str("enum"), $2); } struct_type: s_struct '{' variable_declarations '}' { ECPGfree_struct_member(struct_member_list[struct_level]); free(actual_storage[struct_level--]); fputs("} ", yyout); - $$ = ECPGt_struct; } s_struct : S_STRUCT opt_symbol @@ -3957,7 +3983,7 @@ variable: opt_pointer symbol opt_array_bounds opt_initializer if (struct_level == 0) new_variable($2, type); else - ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]))->typ; + ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1])); free($1); free($2); @@ -4562,27 +4588,36 @@ civariableonly : cvariable name { add_variable(&argsinsert, find_variable($1), &no_indicator); } -cvariable: CVARIABLE { $$ = make1_str($1); } +cvariable: CVARIABLE { $$ = $1; } indicator: /* empty */ { $$ = NULL; } | cvariable { check_indicator((find_variable($1))->type); $$ = $1; } | SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; } | SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; } -ident: IDENT { $$ = make1_str($1); } +ident: IDENT { $$ = $1; } | CSTRING { $$ = $1; } /* * C stuff */ -symbol: IDENT { $$ = make1_str($1); } +symbol: IDENT { $$ = $1; } -c_anything: IDENT { $$ = make1_str($1); } +cpp_line: CPP_LINE { $$ = $1; } + +c_line: c_anything { $$ = $1; } + | c_line c_anything + { + $$ = make2_str($1, $2); + } + +c_thing: c_anything | ';' { $$ = make1_str(";"); } + +c_anything: IDENT { $$ = $1; } | CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); } | Iconst { $$ = $1; } | FCONST { $$ = make_name(); } - | '*' { $$ = make1_str("*"); } - | ';' { $$ = make1_str(";"); } + | '*' { $$ = make1_str("*"); } | S_AUTO { $$ = make1_str("auto"); } | S_BOOL { $$ = make1_str("bool"); } | S_CHAR { $$ = make1_str("char"); } @@ -4607,19 +4642,17 @@ c_anything: IDENT { $$ = make1_str($1); } | '=' { $$ = make1_str("="); } | ',' { $$ = make1_str(","); } -do_anything: IDENT { $$ = make1_str($1); } +do_anything: IDENT { $$ = $1; } | CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\""));} | Iconst { $$ = $1; } | FCONST { $$ = make_name(); } | ',' { $$ = make1_str(","); } -var_anything: IDENT { $$ = make1_str($1); } - | CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); } - | Iconst { $$ = $1; } - | FCONST { $$ = make_name(); } -/*FIXME: | ',' { $$ = make1_str(","); }*/ - | '{' { $$ = make1_str("{"); } - | '}' { $$ = make1_str("}"); } +var_anything: IDENT { $$ = $1; } + | CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); } + | Iconst { $$ = $1; } + | FCONST { $$ = make_name(); } + | '{' c_line '}' { $$ = make3_str(make1_str("{"), $2, make1_str("}")); } blockstart : '{' { braces_open++; @@ -4635,6 +4668,6 @@ blockend : '}' { void yyerror(char * error) { - fprintf(stderr, "%s in line %d\n", error, yylineno); + fprintf(stderr, "%s in line %d of file %s\n", error, yylineno, input_filename); exit(PARSE_ERROR); } diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index ce0e1b0cd20..dd395c80eb9 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -52,7 +52,7 @@ struct_member_dup(struct ECPGstruct_member * rm) } /* The NAME argument is copied. The type argument is preserved as a pointer. */ -struct ECPGstruct_member * +void ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_member ** start) { struct ECPGstruct_member *ptr, @@ -69,7 +69,6 @@ ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_mem ptr->next = ne; else *start = ne; - return ne; } struct ECPGtype * diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index 5895359c2ea..835f50b359f 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -25,7 +25,7 @@ struct ECPGtype }; /* Everything is malloced. */ -struct ECPGstruct_member *ECPGmake_struct_member(char *, struct ECPGtype *, struct ECPGstruct_member **); +void ECPGmake_struct_member(char *, struct ECPGtype *, struct ECPGstruct_member **); struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, long); struct ECPGtype *ECPGmake_varchar_type(enum ECPGttype, long); struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, long); @@ -81,3 +81,9 @@ struct index int index2; char *str; }; + +struct this_type +{ + enum ECPGttype type_enum; + char *type_str; +};