2007-11-15 21:14:46 +00:00
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.102 2007/11/15 21:14:45 momjian Exp $ */
2001-08-24 22:37:36 +00:00
1998-02-05 15:46:43 +00:00
/* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
2000-01-27 19:01:35 +00:00
/* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
2003-03-10 22:28:22 +00:00
/* Placed under the same license as PostgreSQL */
1998-02-05 15:46:43 +00:00
2001-02-10 02:31:31 +00:00
# include "postgres_fe.h"
1999-07-19 01:18:05 +00:00
# include <unistd.h>
2003-03-18 10:46:39 +00:00
# include <string.h>
2007-01-11 15:47:34 +00:00
# include "getopt_long.h"
2001-08-24 22:37:36 +00:00
1998-02-11 15:30:00 +00:00
# include "extern.h"
1998-02-06 13:32:34 +00:00
2001-08-24 22:37:36 +00:00
int ret_value = 0 ,
2002-03-21 18:28:07 +00:00
autocommit = false ,
2003-05-01 17:16:57 +00:00
auto_create_c = false ,
2003-06-25 10:44:21 +00:00
system_includes = false ,
2004-01-28 20:43:03 +00:00
force_indicator = true ,
2007-08-14 10:01:54 +00:00
questionmarks = false ,
2007-01-11 15:47:34 +00:00
header_mode = false ,
2007-08-14 10:01:54 +00:00
regression_mode = false ,
auto_prepare = false ;
2003-02-13 13:11:52 +00:00
2007-11-15 21:14:46 +00:00
char * output_filename ;
2007-06-11 11:52:08 +00:00
2003-08-04 00:43:34 +00:00
enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL ;
2003-02-13 13:11:52 +00:00
1999-12-26 21:31:35 +00:00
struct _include_path * include_paths = NULL ;
1998-08-11 18:33:37 +00:00
struct cursor * cur = NULL ;
1999-02-20 07:01:08 +00:00
struct typedefs * types = NULL ;
1999-12-26 21:31:35 +00:00
struct _defines * defines = NULL ;
1998-02-06 13:32:34 +00:00
static void
2001-08-24 22:37:36 +00:00
help ( const char * progname )
1998-02-06 13:32:34 +00:00
{
2001-08-24 22:37:36 +00:00
printf ( " %s is the PostgreSQL embedded SQL preprocessor for C programs. \n \n " ,
progname ) ;
2001-08-28 02:47:18 +00:00
printf ( " Usage: \n "
2002-10-18 22:05:36 +00:00
" %s [OPTION]... FILE... \n \n " ,
2001-08-28 02:47:18 +00:00
progname ) ;
2001-08-24 22:37:36 +00:00
printf ( " Options: \n " ) ;
2002-10-18 22:05:36 +00:00
printf ( " -c automatically generate C code from embedded SQL code; \n "
" currently this works for EXEC SQL TYPE \n " ) ;
2003-11-02 12:55:24 +00:00
printf ( " -C MODE set compatibility mode; \n "
Wording cleanup for error messages. Also change can't -> cannot.
Standard English uses "may", "can", and "might" in different ways:
may - permission, "You may borrow my rake."
can - ability, "I can lift that log."
might - possibility, "It might rain today."
Unfortunately, in conversational English, their use is often mixed, as
in, "You may use this variable to do X", when in fact, "can" is a better
choice. Similarly, "It may crash" is better stated, "It might crash".
2007-02-01 19:10:30 +00:00
" MODE can be one of \" INFORMIX \" , \" INFORMIX_SE \" \n " ) ;
2000-11-07 08:46:27 +00:00
# ifdef YYDEBUG
2002-10-18 22:05:36 +00:00
printf ( " -d generate parser debug output \n " ) ;
2000-11-07 08:46:27 +00:00
# endif
2002-10-18 22:05:36 +00:00
printf ( " -D SYMBOL define SYMBOL \n " ) ;
2004-01-28 09:52:14 +00:00
printf ( " -h parse a header file, this option includes option \" -c \" \n " ) ;
2003-11-02 12:55:24 +00:00
printf ( " -i parse system include files as well \n " ) ;
2002-10-18 22:05:36 +00:00
printf ( " -I DIRECTORY search DIRECTORY for include files \n " ) ;
printf ( " -o OUTFILE write result to OUTFILE \n " ) ;
2003-11-02 12:55:24 +00:00
printf ( " -r OPTION specify runtime behaviour; \n "
2007-08-14 10:01:54 +00:00
" OPTION can be: \n "
" \" no_indicator \" \n "
" \" prepare \" \n "
" \" questionmarks \" \n " ) ;
2002-10-18 22:05:36 +00:00
printf ( " -t turn on autocommit of transactions \n " ) ;
printf ( " --help show this help, then exit \n " ) ;
2007-01-11 15:47:34 +00:00
printf ( " --regression run in regression testing mode \n " ) ;
2002-10-18 22:05:36 +00:00
printf ( " --version output version information, then exit \n " ) ;
printf ( " \n If no output file is specified, the name is formed by adding .c to the \n "
" input file name, after stripping off .pgc if present. \n " ) ;
2001-08-24 22:37:36 +00:00
printf ( " \n Report bugs to <pgsql-bugs@postgresql.org>. \n " ) ;
1998-03-20 03:08:11 +00:00
}
static void
1998-09-01 04:40:42 +00:00
add_include_path ( char * path )
1998-03-20 03:08:11 +00:00
{
2003-08-04 00:43:34 +00:00
struct _include_path * ip = include_paths ,
* new ;
1998-09-01 04:40:42 +00:00
2003-05-13 11:29:14 +00:00
new = mm_alloc ( sizeof ( struct _include_path ) ) ;
new - > path = path ;
new - > next = NULL ;
2002-09-04 20:31:48 +00:00
2003-05-13 11:29:14 +00:00
if ( ip = = NULL )
include_paths = new ;
else
{
2003-08-04 00:43:34 +00:00
for ( ; ip - > next ! = NULL ; ip = ip - > next ) ;
2003-05-13 11:29:14 +00:00
ip - > next = new ;
}
1998-02-06 13:32:34 +00:00
}
2000-01-18 13:03:49 +00:00
static void
add_preprocessor_define ( char * define )
{
struct _defines * pd = defines ;
2003-08-04 00:43:34 +00:00
char * ptr ,
* define_copy = mm_strdup ( define ) ;
2000-01-18 13:03:49 +00:00
defines = mm_alloc ( sizeof ( struct _defines ) ) ;
2003-08-04 00:43:34 +00:00
2003-03-18 10:46:39 +00:00
/* look for = sign */
ptr = strchr ( define_copy , ' = ' ) ;
if ( ptr ! = NULL )
{
2003-08-04 00:43:34 +00:00
char * tmp ;
2004-07-20 18:06:41 +00:00
/* symbol has a value */
2003-08-04 00:43:34 +00:00
for ( tmp = ptr - 1 ; * tmp = = ' ' ; tmp - - ) ;
2003-03-18 10:46:39 +00:00
tmp [ 1 ] = ' \0 ' ;
defines - > old = define_copy ;
2003-08-04 00:43:34 +00:00
defines - > new = ptr + 1 ;
2003-03-18 10:46:39 +00:00
}
else
{
defines - > old = define_copy ;
2004-07-20 18:06:41 +00:00
defines - > new = mm_strdup ( " 1 " ) ;
2003-03-18 10:46:39 +00:00
}
2000-01-18 13:03:49 +00:00
defines - > pertinent = true ;
2004-07-20 18:06:41 +00:00
defines - > used = NULL ;
2000-01-18 13:03:49 +00:00
defines - > next = pd ;
}
2007-01-11 15:47:34 +00:00
# define ECPG_GETOPT_LONG_HELP 1
# define ECPG_GETOPT_LONG_VERSION 2
# define ECPG_GETOPT_LONG_REGRESSION 3
1998-02-06 13:32:34 +00:00
int
main ( int argc , char * const argv [ ] )
1998-02-05 15:46:43 +00:00
{
2007-01-11 15:47:34 +00:00
static struct option ecpg_options [ ] = {
{ " help " , no_argument , NULL , ECPG_GETOPT_LONG_HELP } ,
{ " version " , no_argument , NULL , ECPG_GETOPT_LONG_VERSION } ,
{ " regression " , no_argument , NULL , ECPG_GETOPT_LONG_REGRESSION } ,
2007-11-15 21:14:46 +00:00
{ NULL , 0 , NULL , 0 }
2007-01-11 15:47:34 +00:00
} ;
1998-09-01 04:40:42 +00:00
int fnr ,
c ,
1999-12-23 12:33:19 +00:00
verbose = false ,
1998-09-01 04:40:42 +00:00
out_option = 0 ;
struct _include_path * ip ;
2004-05-12 13:38:49 +00:00
const char * progname ;
2004-08-29 05:07:03 +00:00
char my_exec_path [ MAXPGPATH ] ;
char include_path [ MAXPGPATH ] ;
2003-04-04 20:42:13 +00:00
progname = get_progname ( argv [ 0 ] ) ;
2001-08-24 22:37:36 +00:00
2004-05-17 14:35:34 +00:00
find_my_exec ( argv [ 0 ] , my_exec_path ) ;
2007-06-11 11:52:08 +00:00
output_filename = NULL ;
2007-01-11 15:47:34 +00:00
while ( ( c = getopt_long ( argc , argv , " vcio:I:tD:dC:r:h? " , ecpg_options , NULL ) ) ! = - 1 )
1998-02-06 13:32:34 +00:00
{
switch ( c )
{
2007-01-11 15:47:34 +00:00
case ECPG_GETOPT_LONG_VERSION :
printf ( " ecpg (PostgreSQL %s) %d.%d.%d \n " , PG_VERSION ,
MAJOR_VERSION , MINOR_VERSION , PATCHLEVEL ) ;
exit ( 0 ) ;
case ECPG_GETOPT_LONG_HELP :
help ( progname ) ;
exit ( 0 ) ;
2007-11-15 21:14:46 +00:00
/*
* - ? is an alternative spelling of - - help . However it is also
* returned by getopt_long for unknown options . We can
* distinguish both cases by means of the optopt variable
* which is set to 0 if it was really - ? and not an unknown
* option character .
*/
2007-01-11 15:47:34 +00:00
case ' ? ' :
if ( optopt = = 0 )
{
help ( progname ) ;
exit ( 0 ) ;
}
break ;
case ECPG_GETOPT_LONG_REGRESSION :
regression_mode = true ;
break ;
1998-02-06 13:32:34 +00:00
case ' o ' :
2007-06-11 11:52:08 +00:00
output_filename = optarg ;
if ( strcmp ( output_filename , " - " ) = = 0 )
2003-05-27 14:36:00 +00:00
yyout = stdout ;
else
2007-06-11 11:52:08 +00:00
yyout = fopen ( output_filename , PG_BINARY_W ) ;
2003-08-04 00:43:34 +00:00
2007-11-15 21:14:46 +00:00
if ( yyout = = NULL )
2007-06-11 11:52:08 +00:00
{
2004-11-09 15:57:57 +00:00
fprintf ( stderr , " %s: could not open file \" %s \" : %s \n " ,
2007-06-11 11:52:08 +00:00
progname , output_filename , strerror ( errno ) ) ;
output_filename = NULL ;
}
1998-02-06 13:32:34 +00:00
else
out_option = 1 ;
break ;
1998-03-20 03:08:11 +00:00
case ' I ' :
add_include_path ( optarg ) ;
1998-09-01 04:40:42 +00:00
break ;
case ' t ' :
2002-03-21 09:42:52 +00:00
autocommit = true ;
1998-09-01 04:40:42 +00:00
break ;
1998-02-11 15:30:00 +00:00
case ' v ' :
1999-12-23 12:33:19 +00:00
verbose = true ;
The first fix is to allow an input file with a relative path and without
a ".pgc " extension. The second patch fixes a coredump when there is
more than one input file (in that case, cur and types were not set to
NULL before processing the second f ile)
The patch below modifies the accepted grammar of ecpg to accept
FETCH [direction] [amount] cursor name
i.e. the IN|FROM clause becomes optional (as in Oracle and Informix).
This removes the incompatibility mentioned in section "Porting From
Other RDBMS Packages" p169, PostgreSQL Programmer's Guide. The grammar
is modified in such a way as to avoid shift/reduce conflicts. It does
not accept the statement "EXEC SQL FETCH;" anymore, as the old grammar
did (this seems to be a bug of the old grammar anyway).
This patch cleans up the handling of space characters in the scanner;
some patte rns require \n to be in {space}, some do not. A second fix is
the handling of cpp continuati on lines; the old pattern did not match
these. The parser is patched to fix an off-by-one error in the #line
directives. The pa rser is also enhanced to report the correct location
of errors in declarations in the "E XEC SQL DECLARE SECTION". Finally,
some right recursions in the parser were replaced by left-recursions.
This patch adds preprocessor directives to ecpg; in particular
EXEC SQL IFDEF, EXEC SQL IFNDEF, EXEC SQL ELSE, EXEC SQL ELIF and EXEC SQL ENDIF
"EXEC SQL IFDEF" is used with defines made with "EXEC SQL DEFINE" and
defines, specified on the command line with -D. Defines, specified on
the command line are persistent across multiple input files. Defines can
be nested up to a maximum level of 128 (see patch). There is a fair
amount of error checking to make sure directives are matched properly. I
need preprocessor directives for porting code, that is written for an
Informix database, to a PostgreSQL database, while maintaining
compatibility with the original code. I decided not to extend the
already large ecpg grammar. Everything is done in the scanner by adding
some states, e.g. to skip all input except newlines and directives. The
preprocessor commands are compatible with Informix. Oracle uses a cpp
replacement.
Rene Hogendoorn
1999-12-21 17:42:16 +00:00
break ;
2004-01-28 09:52:14 +00:00
case ' h ' :
header_mode = true ;
/* this must include "-c" to make sense */
/* so do not place a break; here */
2002-03-21 09:42:52 +00:00
case ' c ' :
auto_create_c = true ;
break ;
2003-05-01 17:16:57 +00:00
case ' i ' :
system_includes = true ;
break ;
2003-02-13 13:11:52 +00:00
case ' C ' :
2003-06-26 11:37:05 +00:00
if ( strncmp ( optarg , " INFORMIX " , strlen ( " INFORMIX " ) ) = = 0 )
2003-03-18 10:46:39 +00:00
{
2004-08-29 05:07:03 +00:00
char pkginclude_path [ MAXPGPATH ] ;
char informix_path [ MAXPGPATH ] ;
2003-06-26 11:37:05 +00:00
compat = ( strcmp ( optarg , " INFORMIX " ) = = 0 ) ? ECPG_COMPAT_INFORMIX : ECPG_COMPAT_INFORMIX_SE ;
2004-05-17 14:35:34 +00:00
get_pkginclude_path ( my_exec_path , pkginclude_path ) ;
snprintf ( informix_path , MAXPGPATH , " %s/informix/esql " , pkginclude_path ) ;
add_include_path ( informix_path ) ;
2003-03-18 10:46:39 +00:00
}
2003-02-13 13:11:52 +00:00
else
{
fprintf ( stderr , " Try '%s --help' for more information. \n " , argv [ 0 ] ) ;
return ILLEGAL_OPTION ;
2003-08-04 00:43:34 +00:00
}
2003-02-13 13:11:52 +00:00
break ;
2003-06-25 10:44:21 +00:00
case ' r ' :
if ( strcmp ( optarg , " no_indicator " ) = = 0 )
force_indicator = false ;
2007-08-14 10:01:54 +00:00
else if ( strcmp ( optarg , " prepare " ) = = 0 )
auto_prepare = true ;
else if ( strcmp ( optarg , " questionmarks " ) = = 0 )
questionmarks = true ;
2003-06-25 10:44:21 +00:00
else
{
fprintf ( stderr , " Try '%s --help' for more information. \n " , argv [ 0 ] ) ;
return ILLEGAL_OPTION ;
}
break ;
2000-01-18 13:03:49 +00:00
case ' D ' :
2000-04-12 17:17:23 +00:00
add_preprocessor_define ( optarg ) ;
break ;
2000-11-07 08:46:27 +00:00
case ' d ' :
2001-08-24 22:37:36 +00:00
# ifdef YYDEBUG
2001-03-22 04:01:46 +00:00
yydebug = 1 ;
2001-08-24 22:37:36 +00:00
# else
fprintf ( stderr , " %s: parser debug support (-d) not available \n " ,
progname ) ;
2000-11-07 08:46:27 +00:00
# endif
2001-08-24 22:37:36 +00:00
break ;
1998-02-06 13:32:34 +00:00
default :
2001-08-24 22:37:36 +00:00
fprintf ( stderr , " Try '%s --help' for more information. \n " , argv [ 0 ] ) ;
1998-09-01 03:29:17 +00:00
return ILLEGAL_OPTION ;
1998-02-06 13:32:34 +00:00
}
}
2003-05-13 11:29:14 +00:00
add_include_path ( " . " ) ;
add_include_path ( " /usr/local/include " ) ;
2004-05-17 14:35:34 +00:00
get_include_path ( my_exec_path , include_path ) ;
add_include_path ( include_path ) ;
2003-05-13 11:29:14 +00:00
add_include_path ( " /usr/include " ) ;
1999-12-23 12:33:19 +00:00
if ( verbose )
{
2001-08-24 22:37:36 +00:00
fprintf ( stderr , " %s, the PostgreSQL embedded C preprocessor, version %d.%d.%d \n " ,
progname , MAJOR_VERSION , MINOR_VERSION , PATCHLEVEL ) ;
1999-12-23 12:33:19 +00:00
fprintf ( stderr , " exec sql include ... search starts here: \n " ) ;
for ( ip = include_paths ; ip ! = NULL ; ip = ip - > next )
fprintf ( stderr , " %s \n " , ip - > path ) ;
2001-08-24 22:37:36 +00:00
fprintf ( stderr , " end of search list \n " ) ;
return 0 ;
1999-12-23 12:33:19 +00:00
}
2000-04-12 17:17:23 +00:00
1998-02-26 04:46:47 +00:00
if ( optind > = argc ) /* no files specified */
1998-03-20 03:08:11 +00:00
{
2001-08-24 22:37:36 +00:00
fprintf ( stderr , " %s: no input files specified \n " , progname ) ;
fprintf ( stderr , " Try '%s --help' for more information. \n " , argv [ 0 ] ) ;
1998-09-01 04:40:42 +00:00
return ( ILLEGAL_OPTION ) ;
1998-03-20 03:08:11 +00:00
}
1998-02-11 15:30:00 +00:00
else
1998-02-06 13:32:34 +00:00
{
1998-02-11 15:30:00 +00:00
/* after the options there must not be anything but filenames */
for ( fnr = optind ; fnr < argc ; fnr + + )
1998-02-06 13:32:34 +00:00
{
2007-11-15 21:14:46 +00:00
char * ptr2ext ;
1998-02-06 13:32:34 +00:00
2003-05-27 14:36:00 +00:00
/* If argv[fnr] is "-" we have to read from stdin */
if ( strcmp ( argv [ fnr ] , " - " ) = = 0 )
{
2003-08-04 00:43:34 +00:00
input_filename = mm_alloc ( strlen ( " stdin " ) + 1 ) ;
2003-05-27 14:36:00 +00:00
strcpy ( input_filename , " stdin " ) ;
yyin = stdin ;
}
else
{
input_filename = mm_alloc ( strlen ( argv [ fnr ] ) + 5 ) ;
strcpy ( input_filename , argv [ fnr ] ) ;
1998-02-06 13:32:34 +00:00
2003-05-27 14:36:00 +00:00
/* take care of relative paths */
2004-06-10 22:26:24 +00:00
ptr2ext = last_dir_separator ( input_filename ) ;
2003-05-27 14:36:00 +00:00
ptr2ext = ( ptr2ext ? strrchr ( ptr2ext , ' . ' ) : strrchr ( input_filename , ' . ' ) ) ;
2000-04-12 17:17:23 +00:00
2003-05-27 14:36:00 +00:00
/* no extension? */
if ( ptr2ext = = NULL )
{
ptr2ext = input_filename + strlen ( input_filename ) ;
2004-01-28 09:52:14 +00:00
/* no extension => add .pgc or .pgh */
2003-05-27 14:36:00 +00:00
ptr2ext [ 0 ] = ' . ' ;
ptr2ext [ 1 ] = ' p ' ;
ptr2ext [ 2 ] = ' g ' ;
2004-08-29 05:07:03 +00:00
ptr2ext [ 3 ] = ( header_mode = = true ) ? ' h ' : ' c ' ;
2003-05-27 14:36:00 +00:00
ptr2ext [ 4 ] = ' \0 ' ;
}
2003-08-04 00:43:34 +00:00
2003-05-27 14:36:00 +00:00
yyin = fopen ( input_filename , PG_BINARY_R ) ;
1998-02-11 15:30:00 +00:00
}
1998-02-06 13:32:34 +00:00
2001-10-28 06:26:15 +00:00
if ( out_option = = 0 ) /* calculate the output name */
1998-02-10 16:44:17 +00:00
{
2003-05-27 14:36:00 +00:00
if ( strcmp ( input_filename , " stdin " ) = = 0 )
yyout = stdout ;
else
{
output_filename = strdup ( input_filename ) ;
1998-09-01 04:40:42 +00:00
2003-05-27 14:36:00 +00:00
ptr2ext = strrchr ( output_filename , ' . ' ) ;
2004-01-28 09:52:14 +00:00
/* make extension = .c resp. .h */
2004-08-29 05:07:03 +00:00
ptr2ext [ 1 ] = ( header_mode = = true ) ? ' h ' : ' c ' ;
2003-05-27 14:36:00 +00:00
ptr2ext [ 2 ] = ' \0 ' ;
1998-09-01 04:40:42 +00:00
2003-05-27 14:36:00 +00:00
yyout = fopen ( output_filename , PG_BINARY_W ) ;
if ( yyout = = NULL )
{
2004-11-09 15:57:57 +00:00
fprintf ( stderr , " %s: could not open file \" %s \" : %s \n " ,
progname , output_filename , strerror ( errno ) ) ;
2003-05-27 14:36:00 +00:00
free ( output_filename ) ;
free ( input_filename ) ;
continue ;
}
1998-02-11 15:30:00 +00:00
}
1998-02-06 13:32:34 +00:00
}
1998-02-11 15:30:00 +00:00
if ( yyin = = NULL )
2004-11-09 15:57:57 +00:00
fprintf ( stderr , " %s: could not open file \" %s \" : %s \n " ,
progname , argv [ fnr ] , strerror ( errno ) ) ;
1998-02-11 15:30:00 +00:00
else
{
1998-04-21 13:23:24 +00:00
struct cursor * ptr ;
1998-08-25 12:17:27 +00:00
struct _defines * defptr ;
1999-02-20 07:01:08 +00:00
struct typedefs * typeptr ;
1999-05-25 16:15:34 +00:00
1998-08-11 18:33:37 +00:00
/* remove old cursor definitions if any are still there */
1998-08-25 12:17:27 +00:00
for ( ptr = cur ; ptr ! = NULL ; )
1998-08-11 18:33:37 +00:00
{
1998-08-25 12:17:27 +00:00
struct cursor * this = ptr ;
2000-04-12 17:17:23 +00:00
struct arguments * l1 ,
* l2 ;
1998-09-01 04:40:42 +00:00
1998-08-11 18:33:37 +00:00
free ( ptr - > command ) ;
1999-02-23 12:57:03 +00:00
free ( ptr - > connection ) ;
1998-08-11 18:33:37 +00:00
free ( ptr - > name ) ;
1999-02-20 07:01:08 +00:00
for ( l1 = ptr - > argsinsert ; l1 ; l1 = l2 )
1998-08-11 18:33:37 +00:00
{
l2 = l1 - > next ;
free ( l1 ) ;
}
1999-02-20 07:01:08 +00:00
for ( l1 = ptr - > argsresult ; l1 ; l1 = l2 )
1998-08-11 18:33:37 +00:00
{
l2 = l1 - > next ;
free ( l1 ) ;
}
1998-08-25 12:17:27 +00:00
ptr = ptr - > next ;
free ( this ) ;
1998-08-11 18:33:37 +00:00
}
2000-01-18 13:03:49 +00:00
cur = NULL ;
1998-09-01 04:40:42 +00:00
2000-01-18 13:03:49 +00:00
/* remove non-pertinent old defines as well */
2000-04-12 17:17:23 +00:00
while ( defines & & ! defines - > pertinent )
{
defptr = defines ;
defines = defines - > next ;
2000-01-18 13:03:49 +00:00
2000-04-12 17:17:23 +00:00
free ( defptr - > new ) ;
free ( defptr - > old ) ;
free ( defptr ) ;
2000-01-18 13:03:49 +00:00
}
2000-04-12 17:17:23 +00:00
for ( defptr = defines ; defptr ! = NULL ; defptr = defptr - > next )
1998-08-25 12:17:27 +00:00
{
2000-04-12 17:17:23 +00:00
struct _defines * this = defptr - > next ;
1998-09-01 04:40:42 +00:00
2000-04-12 17:17:23 +00:00
if ( this & & ! this - > pertinent )
{
defptr - > next = this - > next ;
free ( this - > new ) ;
free ( this - > old ) ;
free ( this ) ;
}
1998-08-25 12:17:27 +00:00
}
1999-05-25 16:15:34 +00:00
1999-02-20 07:01:08 +00:00
/* and old typedefs */
for ( typeptr = types ; typeptr ! = NULL ; )
{
struct typedefs * this = typeptr ;
1998-09-01 04:40:42 +00:00
1999-02-20 07:01:08 +00:00
free ( typeptr - > name ) ;
ECPGfree_struct_member ( typeptr - > struct_member_list ) ;
2000-01-18 13:03:49 +00:00
free ( typeptr - > type ) ;
1999-02-20 07:01:08 +00:00
typeptr = typeptr - > next ;
free ( this ) ;
}
2000-01-18 13:03:49 +00:00
types = NULL ;
2000-04-12 17:17:23 +00:00
2000-01-18 13:03:49 +00:00
/* initialize whenever structures */
memset ( & when_error , 0 , sizeof ( struct when ) ) ;
memset ( & when_nf , 0 , sizeof ( struct when ) ) ;
memset ( & when_warn , 0 , sizeof ( struct when ) ) ;
2000-04-12 17:17:23 +00:00
2000-01-18 13:03:49 +00:00
/* and structure member lists */
memset ( struct_member_list , 0 , sizeof ( struct_member_list ) ) ;
2000-04-12 17:17:23 +00:00
2003-06-13 10:50:58 +00:00
/* and our variable counter for Informix compatibility */
ecpg_informix_var = 0 ;
2000-02-17 19:48:58 +00:00
/* finally the actual connection */
connection = NULL ;
2003-08-04 00:43:34 +00:00
1998-02-11 15:30:00 +00:00
/* initialize lex */
lex_init ( ) ;
1998-09-01 04:40:42 +00:00
2002-01-10 10:42:54 +00:00
/* we need several includes */
2004-01-28 09:52:14 +00:00
/* but not if we are in header mode */
2007-11-15 21:14:46 +00:00
if ( regression_mode )
2007-01-11 15:47:34 +00:00
fprintf ( yyout , " /* Processed by ecpg (regression mode) */ \n " ) ;
else
fprintf ( yyout , " /* Processed by ecpg (%d.%d.%d) */ \n " , MAJOR_VERSION , MINOR_VERSION , PATCHLEVEL ) ;
2004-08-29 05:07:03 +00:00
2004-01-28 09:52:14 +00:00
if ( header_mode = = false )
{
fprintf ( yyout , " /* These include files are added by the preprocessor */ \n #include <ecpgtype.h> \n #include <ecpglib.h> \n #include <ecpgerrno.h> \n #include <sqlca.h> \n " ) ;
1998-02-06 13:32:34 +00:00
2004-01-28 09:52:14 +00:00
/* add some compatibility headers */
if ( INFORMIX_MODE )
fprintf ( yyout , " /* Needed for informix compatibility */ \n #include <ecpg_informix.h> \n " ) ;
2003-08-04 00:43:34 +00:00
2004-01-28 09:52:14 +00:00
fprintf ( yyout , " /* End of automatic include section */ \n " ) ;
}
2003-02-14 13:17:13 +00:00
2007-11-15 21:14:46 +00:00
if ( regression_mode )
2007-01-12 10:00:14 +00:00
fprintf ( yyout , " #define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y)) \n " ) ;
2006-02-08 09:10:05 +00:00
output_line_number ( ) ;
2004-08-29 05:07:03 +00:00
1998-02-11 15:30:00 +00:00
/* and parse the source */
2007-03-17 19:25:24 +00:00
base_yyparse ( ) ;
1998-02-06 13:32:34 +00:00
2004-01-28 09:52:14 +00:00
/* check if all cursors were indeed opened */
for ( ptr = cur ; ptr ! = NULL ; )
{
2004-08-29 05:07:03 +00:00
char errortext [ 128 ] ;
2004-01-28 09:52:14 +00:00
if ( ! ( ptr - > opened ) )
{
2004-08-29 05:07:03 +00:00
/*
2005-10-15 02:49:52 +00:00
* Does not really make sense to declare a cursor but
* not open it
2004-08-29 05:07:03 +00:00
*/
2005-08-29 01:32:00 +00:00
snprintf ( errortext , sizeof ( errortext ) , " cursor \" %s \" has been declared but not opened \n " , ptr - > name ) ;
2004-01-28 09:52:14 +00:00
mmerror ( PARSE_ERROR , ET_WARNING , errortext ) ;
}
ptr = ptr - > next ;
}
2004-08-29 05:07:03 +00:00
2003-05-27 14:36:00 +00:00
if ( yyin ! = NULL & & yyin ! = stdin )
1998-03-20 03:08:11 +00:00
fclose ( yyin ) ;
2003-05-27 14:36:00 +00:00
if ( out_option = = 0 & & yyout ! = stdout )
1998-02-11 15:30:00 +00:00
fclose ( yyout ) ;
}
1998-04-21 13:23:24 +00:00
2007-06-11 11:52:08 +00:00
if ( output_filename & & out_option = = 0 )
1998-04-21 13:23:24 +00:00
free ( output_filename ) ;
1998-09-01 04:40:42 +00:00
1998-03-20 03:08:11 +00:00
free ( input_filename ) ;
1998-02-11 15:30:00 +00:00
}
1998-02-06 13:32:34 +00:00
}
1999-12-08 09:52:29 +00:00
return ret_value ;
1998-02-05 15:46:43 +00:00
}