3 /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
4 /* (C) Michael Meskes <meskes@postgresql.org> Feb 5th, 1998 */
5 /* Placed under the same license as PostgreSQL */
7 #include "postgres_fe.h"
11 #include "getopt_long.h"
17 auto_create_c
= false,
18 system_includes
= false,
19 force_indicator
= true,
20 questionmarks
= false,
21 regression_mode
= false,
24 char *output_filename
;
26 enum COMPAT_MODE compat
= ECPG_COMPAT_PGSQL
;
28 struct _include_path
*include_paths
= NULL
;
29 struct cursor
*cur
= NULL
;
30 struct typedefs
*types
= NULL
;
31 struct _defines
*defines
= NULL
;
34 help(const char *progname
)
36 printf(_("%s is the PostgreSQL embedded SQL preprocessor for C programs.\n\n"),
39 " %s [OPTION]... FILE...\n\n"),
41 printf(_("Options:\n"));
42 printf(_(" -c automatically generate C code from embedded SQL code;\n"
43 " this affects EXEC SQL TYPE\n"));
44 printf(_(" -C MODE set compatibility mode; MODE can be one of\n"
45 " \"INFORMIX\", \"INFORMIX_SE\"\n"));
47 printf(_(" -d generate parser debug output\n"));
49 printf(_(" -D SYMBOL define SYMBOL\n"));
50 printf(_(" -h parse a header file, this option includes option \"-c\"\n"));
51 printf(_(" -i parse system include files as well\n"));
52 printf(_(" -I DIRECTORY search DIRECTORY for include files\n"));
53 printf(_(" -o OUTFILE write result to OUTFILE\n"));
54 printf(_(" -r OPTION specify run-time behavior; OPTION can be:\n"
55 " \"no_indicator\", \"prepare\", \"questionmarks\"\n"));
56 printf(_(" --regression run in regression testing mode\n"));
57 printf(_(" -t turn on autocommit of transactions\n"));
58 printf(_(" --help show this help, then exit\n"));
59 printf(_(" --version output version information, then exit\n"));
60 printf(_("\nIf no output file is specified, the name is formed by adding .c to the\n"
61 "input file name, after stripping off .pgc if present.\n"));
62 printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
66 add_include_path(char *path
)
68 struct _include_path
*ip
= include_paths
,
71 new = mm_alloc(sizeof(struct _include_path
));
79 for (; ip
->next
!= NULL
; ip
= ip
->next
);
85 add_preprocessor_define(char *define
)
87 struct _defines
*pd
= defines
;
89 *define_copy
= mm_strdup(define
);
91 defines
= mm_alloc(sizeof(struct _defines
));
94 ptr
= strchr(define_copy
, '=');
99 /* symbol has a value */
100 for (tmp
= ptr
- 1; *tmp
== ' '; tmp
--);
102 defines
->old
= define_copy
;
103 defines
->new = ptr
+ 1;
107 defines
->old
= define_copy
;
108 defines
->new = mm_strdup("1");
110 defines
->pertinent
= true;
111 defines
->used
= NULL
;
115 #define ECPG_GETOPT_LONG_HELP 1
116 #define ECPG_GETOPT_LONG_VERSION 2
117 #define ECPG_GETOPT_LONG_REGRESSION 3
119 main(int argc
, char *const argv
[])
121 static struct option ecpg_options
[] = {
122 {"help", no_argument
, NULL
, ECPG_GETOPT_LONG_HELP
},
123 {"version", no_argument
, NULL
, ECPG_GETOPT_LONG_VERSION
},
124 {"regression", no_argument
, NULL
, ECPG_GETOPT_LONG_REGRESSION
},
133 struct _include_path
*ip
;
134 const char *progname
;
135 char my_exec_path
[MAXPGPATH
];
136 char include_path
[MAXPGPATH
];
138 set_pglocale_pgservice(argv
[0], PG_TEXTDOMAIN("ecpg"));
140 progname
= get_progname(argv
[0]);
142 find_my_exec(argv
[0], my_exec_path
);
144 output_filename
= NULL
;
145 while ((c
= getopt_long(argc
, argv
, "vcio:I:tD:dC:r:h?", ecpg_options
, NULL
)) != -1)
149 case ECPG_GETOPT_LONG_VERSION
:
150 printf("ecpg (PostgreSQL %s) %d.%d.%d\n", PG_VERSION
,
151 MAJOR_VERSION
, MINOR_VERSION
, PATCHLEVEL
);
153 case ECPG_GETOPT_LONG_HELP
:
158 * -? is an alternative spelling of --help. However it is also
159 * returned by getopt_long for unknown options. We can
160 * distinguish both cases by means of the optopt variable
161 * which is set to 0 if it was really -? and not an unknown
171 case ECPG_GETOPT_LONG_REGRESSION
:
172 regression_mode
= true;
175 output_filename
= optarg
;
176 if (strcmp(output_filename
, "-") == 0)
179 yyout
= fopen(output_filename
, PG_BINARY_W
);
183 fprintf(stderr
, _("%s: could not open file \"%s\": %s\n"),
184 progname
, output_filename
, strerror(errno
));
185 output_filename
= NULL
;
191 add_include_path(optarg
);
201 /* this must include "-c" to make sense */
202 /* so do not place a "break;" here */
204 auto_create_c
= true;
207 system_includes
= true;
210 if (strncmp(optarg
, "INFORMIX", strlen("INFORMIX")) == 0)
212 char pkginclude_path
[MAXPGPATH
];
213 char informix_path
[MAXPGPATH
];
215 compat
= (strcmp(optarg
, "INFORMIX") == 0) ? ECPG_COMPAT_INFORMIX
: ECPG_COMPAT_INFORMIX_SE
;
216 get_pkginclude_path(my_exec_path
, pkginclude_path
);
217 snprintf(informix_path
, MAXPGPATH
, "%s/informix/esql", pkginclude_path
);
218 add_include_path(informix_path
);
222 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), argv
[0]);
223 return ILLEGAL_OPTION
;
227 if (strcmp(optarg
, "no_indicator") == 0)
228 force_indicator
= false;
229 else if (strcmp(optarg
, "prepare") == 0)
231 else if (strcmp(optarg
, "questionmarks") == 0)
232 questionmarks
= true;
235 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), argv
[0]);
236 return ILLEGAL_OPTION
;
240 add_preprocessor_define(optarg
);
246 fprintf(stderr
, _("%s: parser debug support (-d) not available\n"),
251 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), argv
[0]);
252 return ILLEGAL_OPTION
;
256 add_include_path(".");
257 add_include_path("/usr/local/include");
258 get_include_path(my_exec_path
, include_path
);
259 add_include_path(include_path
);
260 add_include_path("/usr/include");
264 fprintf(stderr
, _("%s, the PostgreSQL embedded C preprocessor, version %d.%d.%d\n"),
265 progname
, MAJOR_VERSION
, MINOR_VERSION
, PATCHLEVEL
);
266 fprintf(stderr
, _("EXEC SQL INCLUDE ... search starts here:\n"));
267 for (ip
= include_paths
; ip
!= NULL
; ip
= ip
->next
)
268 fprintf(stderr
, " %s\n", ip
->path
);
269 fprintf(stderr
, _("end of search list\n"));
273 if (optind
>= argc
) /* no files specified */
275 fprintf(stderr
, _("%s: no input files specified\n"), progname
);
276 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), argv
[0]);
277 return (ILLEGAL_OPTION
);
281 /* after the options there must not be anything but filenames */
282 for (fnr
= optind
; fnr
< argc
; fnr
++)
286 /* If argv[fnr] is "-" we have to read from stdin */
287 if (strcmp(argv
[fnr
], "-") == 0)
289 input_filename
= mm_alloc(strlen("stdin") + 1);
290 strcpy(input_filename
, "stdin");
295 input_filename
= mm_alloc(strlen(argv
[fnr
]) + 5);
296 strcpy(input_filename
, argv
[fnr
]);
298 /* take care of relative paths */
299 ptr2ext
= last_dir_separator(input_filename
);
300 ptr2ext
= (ptr2ext
? strrchr(ptr2ext
, '.') : strrchr(input_filename
, '.'));
305 ptr2ext
= input_filename
+ strlen(input_filename
);
307 /* no extension => add .pgc or .pgh */
311 ptr2ext
[3] = (header_mode
== true) ? 'h' : 'c';
315 yyin
= fopen(input_filename
, PG_BINARY_R
);
318 if (out_option
== 0) /* calculate the output name */
320 if (strcmp(input_filename
, "stdin") == 0)
324 output_filename
= strdup(input_filename
);
326 ptr2ext
= strrchr(output_filename
, '.');
327 /* make extension = .c resp. .h */
328 ptr2ext
[1] = (header_mode
== true) ? 'h' : 'c';
331 yyout
= fopen(output_filename
, PG_BINARY_W
);
334 fprintf(stderr
, _("%s: could not open file \"%s\": %s\n"),
335 progname
, output_filename
, strerror(errno
));
336 free(output_filename
);
337 free(input_filename
);
344 fprintf(stderr
, _("%s: could not open file \"%s\": %s\n"),
345 progname
, argv
[fnr
], strerror(errno
));
349 struct _defines
*defptr
;
350 struct typedefs
*typeptr
;
352 /* remove old cursor definitions if any are still there */
353 for (ptr
= cur
; ptr
!= NULL
;)
355 struct cursor
*this = ptr
;
356 struct arguments
*l1
,
360 free(ptr
->connection
);
362 for (l1
= ptr
->argsinsert
; l1
; l1
= l2
)
367 for (l1
= ptr
->argsresult
; l1
; l1
= l2
)
377 /* remove non-pertinent old defines as well */
378 while (defines
&& !defines
->pertinent
)
381 defines
= defines
->next
;
388 for (defptr
= defines
; defptr
!= NULL
; defptr
= defptr
->next
)
390 struct _defines
*this = defptr
->next
;
392 if (this && !this->pertinent
)
394 defptr
->next
= this->next
;
402 /* and old typedefs */
403 for (typeptr
= types
; typeptr
!= NULL
;)
405 struct typedefs
*this = typeptr
;
408 ECPGfree_struct_member(typeptr
->struct_member_list
);
410 typeptr
= typeptr
->next
;
415 /* initialize whenever structures */
416 memset(&when_error
, 0, sizeof(struct when
));
417 memset(&when_nf
, 0, sizeof(struct when
));
418 memset(&when_warn
, 0, sizeof(struct when
));
420 /* and structure member lists */
421 memset(struct_member_list
, 0, sizeof(struct_member_list
));
423 /* and our variable counter for Informix compatibility */
424 ecpg_informix_var
= 0;
426 /* finally the actual connection */
432 /* we need several includes */
433 /* but not if we are in header mode */
435 fprintf(yyout
, "/* Processed by ecpg (regression mode) */\n");
437 fprintf(yyout
, "/* Processed by ecpg (%d.%d.%d) */\n", MAJOR_VERSION
, MINOR_VERSION
, PATCHLEVEL
);
439 if (header_mode
== false)
441 fprintf(yyout
, "/* These include files are added by the preprocessor */\n#include <ecpglib.h>\n#include <ecpgerrno.h>\n#include <sqlca.h>\n");
443 /* add some compatibility headers */
445 fprintf(yyout
, "/* Needed for informix compatibility */\n#include <ecpg_informix.h>\n");
447 fprintf(yyout
, "/* End of automatic include section */\n");
451 fprintf(yyout
, "#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))\n");
453 output_line_number();
455 /* and parse the source */
459 * Check whether all cursors were indeed opened. It
460 * does not really make sense to declare a cursor but
463 for (ptr
= cur
; ptr
!= NULL
; ptr
= ptr
->next
)
465 mmerror(PARSE_ERROR
, ET_WARNING
, "cursor \"%s\" has been declared but not opened", ptr
->name
);
467 if (yyin
!= NULL
&& yyin
!= stdin
)
469 if (out_option
== 0 && yyout
!= stdout
)
473 if (output_filename
&& out_option
== 0)
474 free(output_filename
);
476 free(input_filename
);