mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-12 18:34:36 +08:00
Added an option to force ecpg to also parse files includes via '#include' and some more Informix stuff.
This commit is contained in:
parent
cffded96ea
commit
9e9d8d54e3
@ -1391,6 +1391,11 @@ Tue Apr 8 14:03:32 CEST 2003
|
|||||||
- Added rstrdate function.
|
- Added rstrdate function.
|
||||||
- Made Informix mode honor environment variable to set dbname to
|
- Made Informix mode honor environment variable to set dbname to
|
||||||
connect 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 version to 2.12.0.
|
||||||
- Set ecpg library to 3.4.2.
|
- Set ecpg library to 3.4.2.
|
||||||
- Set pgtypes library to 1.0.0
|
- Set pgtypes library to 1.0.0
|
||||||
|
@ -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. */
|
/* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
|
||||||
/* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
|
/* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
|
||||||
@ -19,7 +19,8 @@ extern char *optarg;
|
|||||||
|
|
||||||
int ret_value = 0,
|
int ret_value = 0,
|
||||||
autocommit = false,
|
autocommit = false,
|
||||||
auto_create_c = false;
|
auto_create_c = false,
|
||||||
|
system_includes = false;
|
||||||
|
|
||||||
enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL;
|
enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL;
|
||||||
|
|
||||||
@ -43,11 +44,13 @@ help(const char *progname)
|
|||||||
printf(" -d generate parser debug output\n");
|
printf(" -d generate parser debug output\n");
|
||||||
#endif
|
#endif
|
||||||
printf(" -C <mode> set compatibility mode\n"
|
printf(" -C <mode> 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(" -D SYMBOL define SYMBOL\n");
|
||||||
printf(" -I DIRECTORY search DIRECTORY for include files\n");
|
printf(" -I DIRECTORY search DIRECTORY for include files\n");
|
||||||
printf(" -o OUTFILE write result to OUTFILE\n");
|
printf(" -o OUTFILE write result to OUTFILE\n");
|
||||||
printf(" -t turn on autocommit of transactions\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(" --help show this help, then exit\n");
|
||||||
printf(" --version output version information, 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"
|
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("/usr/local/include");
|
||||||
add_include_path(".");
|
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)
|
switch (c)
|
||||||
{
|
{
|
||||||
@ -150,10 +153,14 @@ main(int argc, char *const argv[])
|
|||||||
case 'c':
|
case 'c':
|
||||||
auto_create_c = true;
|
auto_create_c = true;
|
||||||
break;
|
break;
|
||||||
|
case 'i':
|
||||||
|
system_includes = true;
|
||||||
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
if (strcmp(optarg, "INFORMIX") == 0)
|
if (strcmp(optarg, "INFORMIX") == 0)
|
||||||
{
|
{
|
||||||
compat = ECPG_COMPAT_INFORMIX;
|
compat = ECPG_COMPAT_INFORMIX;
|
||||||
|
system_includes = true;
|
||||||
add_preprocessor_define("dec_t=Numeric");
|
add_preprocessor_define("dec_t=Numeric");
|
||||||
add_preprocessor_define("intrvl_t=Interval");
|
add_preprocessor_define("intrvl_t=Interval");
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
extern int braces_open,
|
extern int braces_open,
|
||||||
autocommit,
|
autocommit,
|
||||||
auto_create_c,
|
auto_create_c,
|
||||||
|
system_includes,
|
||||||
ret_value,
|
ret_value,
|
||||||
struct_level;
|
struct_level;
|
||||||
extern char *descriptor_index;
|
extern char *descriptor_index;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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"
|
#include "extern.h"
|
||||||
|
|
||||||
|
|
||||||
extern YYSTYPE yylval;
|
extern YYSTYPE yylval;
|
||||||
|
|
||||||
static int xcdepth = 0; /* depth of nesting in slash-star comments */
|
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 addlit(char *ytext, int yleng);
|
||||||
static void addlitchar (unsigned char);
|
static void addlitchar (unsigned char);
|
||||||
static void string_unput (char *);
|
static void string_unput (char *);
|
||||||
|
static void parse_include (void);
|
||||||
|
|
||||||
char *token_start;
|
char *token_start;
|
||||||
int state_before;
|
int state_before;
|
||||||
@ -265,12 +265,17 @@ else [eE][lL][sS][eE]
|
|||||||
elif [eE][lL][iI][fF]
|
elif [eE][lL][iI][fF]
|
||||||
endif [eE][nN][dD][iI][fF]
|
endif [eE][nN][dD][iI][fF]
|
||||||
|
|
||||||
|
struct [sS][tT][rR][uU][cC][tT]
|
||||||
|
|
||||||
exec_sql {exec}{space}*{sql}{space}*
|
exec_sql {exec}{space}*{sql}{space}*
|
||||||
ipdigit ({digit}|{digit}{digit}|{digit}{digit}{digit})
|
ipdigit ({digit}|{digit}{digit}|{digit}{digit}{digit})
|
||||||
ip {ipdigit}\.{ipdigit}\.{ipdigit}\.{ipdigit}
|
ip {ipdigit}\.{ipdigit}\.{ipdigit}\.{ipdigit}
|
||||||
|
|
||||||
|
/* we might want to parse all cpp include files */
|
||||||
|
cppinclude {space}*#{include}{space}*
|
||||||
|
|
||||||
/* Take care of cpp continuation lines */
|
/* Take care of cpp continuation lines */
|
||||||
cppline {space}*#(.*\\{space})*.*
|
cppline {space}*#(.*\\{space})+.*
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Quoted strings must allow some special characters such as single-quote
|
* Quoted strings must allow some special characters such as single-quote
|
||||||
@ -429,6 +434,20 @@ cppline {space}*#(.*\\{space})*.*
|
|||||||
else
|
else
|
||||||
return yytext[0];
|
return yytext[0];
|
||||||
}
|
}
|
||||||
|
<C>{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;
|
||||||
|
}
|
||||||
|
}
|
||||||
<SQL>{self} { /*
|
<SQL>{self} { /*
|
||||||
* We may find a ';' inside a structure
|
* We may find a ';' inside a structure
|
||||||
* definition in a TYPE or VAR statement.
|
* definition in a TYPE or VAR statement.
|
||||||
@ -550,22 +569,6 @@ cppline {space}*#(.*\\{space})*.*
|
|||||||
ScanKeyword *keyword;
|
ScanKeyword *keyword;
|
||||||
struct _defines *ptr;
|
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? */
|
/* How about a DEFINE? */
|
||||||
for (ptr = defines; ptr; ptr = ptr->next)
|
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.
|
* None of the above. Return it as an identifier.
|
||||||
*
|
*
|
||||||
@ -627,42 +645,53 @@ cppline {space}*#(.*\\{space})*.*
|
|||||||
}
|
}
|
||||||
return ICONST;
|
return ICONST;
|
||||||
}
|
}
|
||||||
|
<C>{cppinclude} {
|
||||||
|
if (system_includes)
|
||||||
|
{
|
||||||
|
BEGIN(incl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yylval.str = mm_strdup(yytext);
|
||||||
|
return(CPP_LINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
<C>{cppline} {
|
<C>{cppline} {
|
||||||
yylval.str = mm_strdup(yytext);
|
yylval.str = mm_strdup(yytext);
|
||||||
return(CPP_LINE);
|
return(CPP_LINE);
|
||||||
}
|
}
|
||||||
<C>{identifier} {
|
<C>{identifier} {
|
||||||
ScanKeyword *keyword;
|
ScanKeyword *keyword;
|
||||||
|
struct _defines *ptr;
|
||||||
|
|
||||||
keyword = ScanCKeywordLookup(yytext);
|
/* is it a define? */
|
||||||
if (keyword != NULL) {
|
for (ptr = defines; ptr; ptr = ptr->next)
|
||||||
return keyword->value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
struct _defines *ptr;
|
if (strcmp(yytext, ptr->old) == 0)
|
||||||
|
|
||||||
for (ptr = defines; ptr; ptr = ptr->next)
|
|
||||||
{
|
{
|
||||||
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->buffer = YY_CURRENT_BUFFER;
|
||||||
yb->lineno = yylineno;
|
yb->lineno = yylineno;
|
||||||
yb->filename = mm_strdup(input_filename);
|
yb->filename = mm_strdup(input_filename);
|
||||||
yb->next = yy_buffer;
|
yb->next = yy_buffer;
|
||||||
|
|
||||||
yy_buffer = yb;
|
yy_buffer = yb;
|
||||||
|
|
||||||
yy_scan_string(ptr->new);
|
yy_scan_string(ptr->new);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ptr == NULL)
|
}
|
||||||
{
|
|
||||||
|
if (ptr == NULL)
|
||||||
|
{
|
||||||
|
keyword = ScanCKeywordLookup(yytext);
|
||||||
|
if (keyword != NULL)
|
||||||
|
return keyword->value;
|
||||||
|
|
||||||
|
else {
|
||||||
yylval.str = mm_strdup(yytext);
|
yylval.str = mm_strdup(yytext);
|
||||||
return IDENT;
|
return IDENT;
|
||||||
}
|
}
|
||||||
@ -940,7 +969,11 @@ cppline {space}*#(.*\\{space})*.*
|
|||||||
}
|
}
|
||||||
<def>[^;] { addlit(yytext, yyleng); }
|
<def>[^;] { addlit(yytext, yyleng); }
|
||||||
|
|
||||||
<incl>[^;]+";" {
|
<incl>\<[^\>]+\>{space}*";"? { parse_include(); }
|
||||||
|
<incl>{dquote}{xdinside}{dquote}{space}*";"? { parse_include(); }
|
||||||
|
<incl>[^;\<\>\"]+";" {
|
||||||
|
parse_include();
|
||||||
|
#if 0
|
||||||
/* got the include file name */
|
/* got the include file name */
|
||||||
struct _yy_buffer *yb;
|
struct _yy_buffer *yb;
|
||||||
struct _include_path *ip;
|
struct _include_path *ip;
|
||||||
@ -1026,6 +1059,7 @@ cppline {space}*#(.*\\{space})*.*
|
|||||||
output_line_number();
|
output_line_number();
|
||||||
|
|
||||||
BEGIN C;
|
BEGIN C;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
<<EOF>> {
|
<<EOF>> {
|
||||||
@ -1128,3 +1162,96 @@ string_unput (char *string)
|
|||||||
unput(string[i]);
|
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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user