From 9e9d8d54e32e3ce9fa839b9b23192bc698eca5d0 Mon Sep 17 00:00:00 2001 From: Michael Meskes Date: Thu, 1 May 2003 17:16:57 +0000 Subject: [PATCH] Added an option to force ecpg to also parse files includes via '#include' and some more Informix stuff. --- src/interfaces/ecpg/ChangeLog | 5 + src/interfaces/ecpg/preproc/ecpg.c | 15 +- src/interfaces/ecpg/preproc/extern.h | 1 + src/interfaces/ecpg/preproc/pgc.l | 211 +++++++++++++++++++++------ 4 files changed, 186 insertions(+), 46 deletions(-) diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 4c5e84b694..eb0398939f 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -1391,6 +1391,11 @@ Tue Apr 8 14:03:32 CEST 2003 - Added rstrdate function. - Made Informix mode honor environment variable to set dbname to connect to. + +Thu May 1 14:54:41 CEST 2003 + + - Enable more Informix shortcuts. + - Added option '-i' to parse files included via cpp diretive as well. - Set ecpg version to 2.12.0. - Set ecpg library to 3.4.2. - Set pgtypes library to 1.0.0 diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index f1c39edba6..2634eeee9c 100644 --- a/src/interfaces/ecpg/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -1,4 +1,4 @@ -/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.66 2003/04/08 12:34:25 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.67 2003/05/01 17:16:57 meskes Exp $ */ /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */ /* (C) Michael Meskes Feb 5th, 1998 */ @@ -19,7 +19,8 @@ extern char *optarg; int ret_value = 0, autocommit = false, - auto_create_c = false; + auto_create_c = false, + system_includes = false; enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL; @@ -43,11 +44,13 @@ help(const char *progname) printf(" -d generate parser debug output\n"); #endif printf(" -C set compatibility mode\n" - " mode may be INFORMIX only at the moment\n"); + " mode may be INFORMIX only at the moment\n" + " INFORMIX mode implies '-i'\n"); printf(" -D SYMBOL define SYMBOL\n"); printf(" -I DIRECTORY search DIRECTORY for include files\n"); printf(" -o OUTFILE write result to OUTFILE\n"); printf(" -t turn on autocommit of transactions\n"); + printf(" -i parse system include files as well\n"); printf(" --help show this help, then exit\n"); printf(" --version output version information, then exit\n"); printf("\nIf no output file is specified, the name is formed by adding .c to the\n" @@ -127,7 +130,7 @@ main(int argc, char *const argv[]) add_include_path("/usr/local/include"); add_include_path("."); - while ((c = getopt(argc, argv, "vco:I:tD:dC:")) != -1) + while ((c = getopt(argc, argv, "vcio:I:tD:dC:")) != -1) { switch (c) { @@ -150,10 +153,14 @@ main(int argc, char *const argv[]) case 'c': auto_create_c = true; break; + case 'i': + system_includes = true; + break; case 'C': if (strcmp(optarg, "INFORMIX") == 0) { compat = ECPG_COMPAT_INFORMIX; + system_includes = true; add_preprocessor_define("dec_t=Numeric"); add_preprocessor_define("intrvl_t=Interval"); } diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index 3a30225f0c..73a00067e8 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -15,6 +15,7 @@ extern int braces_open, autocommit, auto_create_c, + system_includes, ret_value, struct_level; extern char *descriptor_index; diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 7e4b5fadd2..ab25f481ca 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.106 2003/02/17 14:06:39 meskes Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.107 2003/05/01 17:16:57 meskes Exp $ * *------------------------------------------------------------------------- */ @@ -25,7 +25,6 @@ #include "extern.h" - extern YYSTYPE yylval; static int xcdepth = 0; /* depth of nesting in slash-star comments */ @@ -44,6 +43,7 @@ static int literalalloc; /* current allocated buffer size */ static void addlit(char *ytext, int yleng); static void addlitchar (unsigned char); static void string_unput (char *); +static void parse_include (void); char *token_start; int state_before; @@ -265,12 +265,17 @@ else [eE][lL][sS][eE] elif [eE][lL][iI][fF] endif [eE][nN][dD][iI][fF] +struct [sS][tT][rR][uU][cC][tT] + exec_sql {exec}{space}*{sql}{space}* ipdigit ({digit}|{digit}{digit}|{digit}{digit}{digit}) ip {ipdigit}\.{ipdigit}\.{ipdigit}\.{ipdigit} +/* we might want to parse all cpp include files */ +cppinclude {space}*#{include}{space}* + /* Take care of cpp continuation lines */ -cppline {space}*#(.*\\{space})*.* +cppline {space}*#(.*\\{space})+.* /* * Quoted strings must allow some special characters such as single-quote @@ -429,6 +434,20 @@ cppline {space}*#(.*\\{space})*.* else return yytext[0]; } +{informix_special}{struct} { + /* are we simulating Informix? */ + if (compat == ECPG_COMPAT_INFORMIX) + { + string_unput("typedef struct "); + BEGIN SQL; + return SQL_START; + } + else + { + string_unput("struct "); + return S_ANYTHING; + } +} {self} { /* * We may find a ';' inside a structure * definition in a TYPE or VAR statement. @@ -550,22 +569,6 @@ cppline {space}*#(.*\\{space})*.* ScanKeyword *keyword; struct _defines *ptr; - /* Is it an SQL 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 keyword->value; - - /* How about a DEFINE? */ for (ptr = defines; ptr; ptr = ptr->next) { @@ -587,6 +590,21 @@ cppline {space}*#(.*\\{space})*.* } } + /* Is it an SQL 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 keyword->value; + /* * None of the above. Return it as an identifier. * @@ -627,42 +645,53 @@ cppline {space}*#(.*\\{space})*.* } return ICONST; } +{cppinclude} { + if (system_includes) + { + BEGIN(incl); + } + else + { + yylval.str = mm_strdup(yytext); + return(CPP_LINE); + } + } {cppline} { yylval.str = mm_strdup(yytext); return(CPP_LINE); } {identifier} { ScanKeyword *keyword; + struct _defines *ptr; - keyword = ScanCKeywordLookup(yytext); - if (keyword != NULL) { - return keyword->value; - } - else + /* is it a define? */ + for (ptr = defines; ptr; ptr = ptr->next) { - struct _defines *ptr; - - for (ptr = defines; ptr; ptr = ptr->next) + if (strcmp(yytext, ptr->old) == 0) { - if (strcmp(yytext, ptr->old) == 0) - { - struct _yy_buffer *yb; + struct _yy_buffer *yb; - yb = mm_alloc(sizeof(struct _yy_buffer)); + 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; + yb->buffer = YY_CURRENT_BUFFER; + yb->lineno = yylineno; + yb->filename = mm_strdup(input_filename); + yb->next = yy_buffer; - yy_buffer = yb; + yy_buffer = yb; - yy_scan_string(ptr->new); - break; - } + yy_scan_string(ptr->new); + break; } - if (ptr == NULL) - { + } + + if (ptr == NULL) + { + keyword = ScanCKeywordLookup(yytext); + if (keyword != NULL) + return keyword->value; + + else { yylval.str = mm_strdup(yytext); return IDENT; } @@ -940,7 +969,11 @@ cppline {space}*#(.*\\{space})*.* } [^;] { addlit(yytext, yyleng); } -[^;]+";" { +\<[^\>]+\>{space}*";"? { parse_include(); } +{dquote}{xdinside}{dquote}{space}*";"? { parse_include(); } +[^;\<\>\"]+";" { + parse_include(); +#if 0 /* got the include file name */ struct _yy_buffer *yb; struct _include_path *ip; @@ -1026,6 +1059,7 @@ cppline {space}*#(.*\\{space})*.* output_line_number(); BEGIN C; +#endif } <> { @@ -1128,3 +1162,96 @@ string_unput (char *string) unput(string[i]); } +static void +parse_include(void) +{ + /* got the include file name */ + struct _yy_buffer *yb; + struct _include_path *ip; + char inc_file[MAXPGPATH]; + unsigned int i; + + yb = mm_alloc(sizeof(struct _yy_buffer)); + + yb->buffer = YY_CURRENT_BUFFER; + yb->lineno = yylineno; + yb->filename = input_filename; + yb->next = yy_buffer; + + yy_buffer = yb; + + /* + * skip the ";" if there is one and trailing whitespace. Note that + * yytext contains at least one non-space character plus the ";" + */ + for ( i = strlen(yytext)-2; + i > 0 && isspace((unsigned char) yytext[i]); + i-- ) + {} + + if (yytext[i] == ';') + i--; + + yytext[i+1] = '\0'; + + yyin = NULL; + + /* If file name is enclosed in '"' remove these and look only in '.' */ + /* Informix does look into all include paths though, except filename starts with '/' */ + if ((yytext[0] == '"' && yytext[i] == '"') && (compat != ECPG_COMPAT_INFORMIX || yytext[1] == '/')) + { + yytext[i] = '\0'; + memmove(yytext, yytext+1, strlen(yytext)); + + strncpy(inc_file, yytext, sizeof(inc_file)); + yyin = fopen(inc_file, "r"); + if (!yyin) + { + if (strcmp(inc_file + strlen(inc_file) - 2, ".h")) + { + strcat(inc_file, ".h"); + yyin = fopen(inc_file, "r"); + } + } + + } + else + { + if ((yytext[0] == '"' && yytext[i] == '"') || (yytext[0] == '<' && yytext[i] == '>')) + { + yytext[i] = '\0'; + memmove(yytext, yytext+1, strlen(yytext)); + } + + for (ip = include_paths; yyin == NULL && ip != NULL; ip = ip->next) + { + if (strlen(ip->path) + strlen(yytext) + 3 > MAXPGPATH) + { + fprintf(stderr, "Error: Path %s/%s is too long in line %d, skipping.\n", ip->path, yytext, yylineno); + continue; + } + snprintf (inc_file, sizeof(inc_file), "%s/%s", ip->path, yytext); + yyin = fopen(inc_file, "r"); + if (!yyin) + { + if (strcmp(inc_file + strlen(inc_file) - 2, ".h")) + { + strcat(inc_file, ".h"); + yyin = fopen( inc_file, "r" ); + } + } + } + } + if (!yyin) + { + snprintf(errortext, sizeof(errortext), "Cannot open include file %s in line %d\n", yytext, yylineno); + mmerror(NO_INCLUDE_FILE, ET_FATAL, errortext); + } + + input_filename = mm_strdup(inc_file); + yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE )); + yylineno = 1; + output_line_number(); + + BEGIN C; +}