PostgreSQL Source Code git master
ecpg.c File Reference
#include "postgres_fe.h"
#include <unistd.h>
#include "getopt_long.h"
#include "preproc_extern.h"
Include dependency graph for ecpg.c:

Go to the source code of this file.

Macros

#define ECPG_GETOPT_LONG_REGRESSION   1
 

Functions

static void help (const char *progname)
 
static void add_include_path (char *path)
 
static void add_preprocessor_define (char *define)
 
int main (int argc, char *const argv[])
 

Variables

int ret_value = 0
 
bool autocommit = false
 
bool auto_create_c = false
 
bool system_includes = false
 
bool force_indicator = true
 
bool questionmarks = false
 
bool regression_mode = false
 
bool auto_prepare = false
 
static const char * progname
 
char * output_filename
 
enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL
 
struct _include_pathinclude_paths = NULL
 
struct cursorcur = NULL
 
struct typedefstypes = NULL
 
struct _definesdefines = NULL
 
struct declared_listg_declared_list = NULL
 

Macro Definition Documentation

◆ ECPG_GETOPT_LONG_REGRESSION

#define ECPG_GETOPT_LONG_REGRESSION   1

Definition at line 128 of file ecpg.c.

Function Documentation

◆ add_include_path()

static void add_include_path ( char *  path)
static

Definition at line 68 of file ecpg.c.

69{
70 struct _include_path *ip = include_paths,
71 *new;
72
73 new = mm_alloc(sizeof(struct _include_path));
74 new->path = path;
75 new->next = NULL;
76
77 if (ip == NULL)
78 include_paths = new;
79 else
80 {
81 for (; ip->next != NULL; ip = ip->next);
82 ip->next = new;
83 }
84}
struct _include_path * include_paths
Definition: ecpg.c:28
void * mm_alloc(size_t size)
Definition: util.c:85
struct _include_path * next
Definition: type.h:134
char * path
Definition: type.h:133

References include_paths, mm_alloc(), _include_path::next, and _include_path::path.

Referenced by main().

◆ add_preprocessor_define()

static void add_preprocessor_define ( char *  define)
static

Definition at line 90 of file ecpg.c.

91{
92 /* copy the argument to avoid relying on argv storage */
93 char *define_copy = mm_strdup(define);
94 char *ptr;
95 struct _defines *newdef;
96
97 newdef = mm_alloc(sizeof(struct _defines));
98
99 /* look for = sign */
100 ptr = strchr(define_copy, '=');
101 if (ptr != NULL)
102 {
103 /* symbol has a value */
104 char *tmp;
105
106 /* strip any spaces between name and '=' */
107 for (tmp = ptr - 1; tmp >= define_copy && *tmp == ' '; tmp--);
108 tmp[1] = '\0';
109
110 /*
111 * Note we don't bother to separately malloc cmdvalue; it will never
112 * be freed so that's not necessary.
113 */
114 newdef->cmdvalue = ptr + 1;
115 }
116 else
117 {
118 /* define it as "1"; again no need to malloc it */
119 newdef->cmdvalue = "1";
120 }
121 newdef->name = define_copy;
122 newdef->value = mm_strdup(newdef->cmdvalue);
123 newdef->used = NULL;
124 newdef->next = defines;
125 defines = newdef;
126}
struct _defines * defines
Definition: ecpg.c:31
char * mm_strdup(const char *string)
Definition: util.c:97
Definition: type.h:180
struct _defines * next
Definition: type.h:185
char * value
Definition: type.h:182
char * name
Definition: type.h:181
void * used
Definition: type.h:184
const char * cmdvalue
Definition: type.h:183

References _defines::cmdvalue, defines, mm_alloc(), mm_strdup(), _defines::name, _defines::next, _defines::used, and _defines::value.

Referenced by main().

◆ help()

static void help ( const char *  progname)
static

Definition at line 35 of file ecpg.c.

36{
37 printf(_("%s is the PostgreSQL embedded SQL preprocessor for C programs.\n\n"),
38 progname);
39 printf(_("Usage:\n"
40 " %s [OPTION]... FILE...\n\n"),
41 progname);
42 printf(_("Options:\n"));
43 printf(_(" -c automatically generate C code from embedded SQL code;\n"
44 " this affects EXEC SQL TYPE\n"));
45 printf(_(" -C MODE set compatibility mode; MODE can be one of\n"
46 " \"INFORMIX\", \"INFORMIX_SE\", \"ORACLE\"\n"));
47#ifdef YYDEBUG
48 printf(_(" -d generate parser debug output\n"));
49#endif
50 printf(_(" -D SYMBOL define SYMBOL\n"));
51 printf(_(" -h parse a header file, this option includes option \"-c\"\n"));
52 printf(_(" -i parse system include files as well\n"));
53 printf(_(" -I DIRECTORY search DIRECTORY for include files\n"));
54 printf(_(" -o OUTFILE write result to OUTFILE\n"));
55 printf(_(" -r OPTION specify run-time behavior; OPTION can be:\n"
56 " \"no_indicator\", \"prepare\", \"questionmarks\"\n"));
57 printf(_(" --regression run in regression testing mode\n"));
58 printf(_(" -t turn on autocommit of transactions\n"));
59 printf(_(" -V, --version output version information, then exit\n"));
60 printf(_(" -?, --help show this help, then exit\n"));
61 printf(_("\nIf no output file is specified, the name is formed by adding .c to the\n"
62 "input file name, after stripping off .pgc if present.\n"));
63 printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
64 printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
65}
static const char * progname
Definition: ecpg.c:23
#define _(x)
Definition: elog.c:90
#define printf(...)
Definition: port.h:244

References _, printf, and progname.

Referenced by main().

◆ main()

int main ( int  argc,
char *const  argv[] 
)

Definition at line 130 of file ecpg.c.

131{
132 static struct option ecpg_options[] = {
133 {"regression", no_argument, NULL, ECPG_GETOPT_LONG_REGRESSION},
134 {NULL, 0, NULL, 0}
135 };
136
137 int fnr,
138 c,
139 out_option = 0;
140 bool verbose = false,
141 header_mode = false;
142 struct _include_path *ip;
144 char include_path[MAXPGPATH];
145
146 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("ecpg"));
147
148 progname = get_progname(argv[0]);
149
150 if (find_my_exec(argv[0], my_exec_path) < 0)
151 {
152 fprintf(stderr, _("%s: could not locate my own executable path\n"), argv[0]);
153 return ILLEGAL_OPTION;
154 }
155
156 if (argc > 1)
157 {
158 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
159 {
160 help(progname);
161 exit(0);
162 }
163 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
164 {
165 printf("ecpg (PostgreSQL) %s\n", PG_VERSION);
166 exit(0);
167 }
168 }
169
170 output_filename = NULL;
171 while ((c = getopt_long(argc, argv, "cC:dD:hiI:o:r:tv", ecpg_options, NULL)) != -1)
172 {
173 switch (c)
174 {
175 case 'c':
176 auto_create_c = true;
177 break;
178 case 'C':
179 if (pg_strcasecmp(optarg, "INFORMIX") == 0 || pg_strcasecmp(optarg, "INFORMIX_SE") == 0)
180 {
181 char pkginclude_path[MAXPGPATH];
182 char informix_path[MAXPGPATH];
183
185 get_pkginclude_path(my_exec_path, pkginclude_path);
186 snprintf(informix_path, MAXPGPATH, "%s/informix/esql", pkginclude_path);
187 add_include_path(informix_path);
188 }
189 else if (pg_strcasecmp(optarg, "ORACLE") == 0)
190 {
192 }
193 else
194 {
195 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), argv[0]);
196 return ILLEGAL_OPTION;
197 }
198 break;
199 case 'd':
200#ifdef YYDEBUG
201 base_yydebug = 1;
202#else
203 fprintf(stderr, _("%s: parser debug support (-d) not available\n"),
204 progname);
205#endif
206 break;
207 case 'D':
209 break;
210 case 'h':
211 header_mode = true;
212 /* this must include "-c" to make sense: */
213 auto_create_c = true;
214 break;
215 case 'i':
216 system_includes = true;
217 break;
218 case 'I':
220 break;
221 case 'o':
223 if (strcmp(output_filename, "-") == 0)
225 else
227
228 if (base_yyout == NULL)
229 {
230 fprintf(stderr, _("%s: could not open file \"%s\": %m\n"),
232 output_filename = NULL;
233 }
234 else
235 out_option = 1;
236 break;
237 case 'r':
238 if (pg_strcasecmp(optarg, "no_indicator") == 0)
239 force_indicator = false;
240 else if (pg_strcasecmp(optarg, "prepare") == 0)
241 auto_prepare = true;
242 else if (pg_strcasecmp(optarg, "questionmarks") == 0)
243 questionmarks = true;
244 else
245 {
246 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), argv[0]);
247 return ILLEGAL_OPTION;
248 }
249 break;
250 case 't':
251 autocommit = true;
252 break;
253 case 'v':
254 verbose = true;
255 break;
257 regression_mode = true;
258 break;
259 default:
260 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), argv[0]);
261 return ILLEGAL_OPTION;
262 }
263 }
264
265 add_include_path(".");
266 add_include_path("/usr/local/include");
267 get_include_path(my_exec_path, include_path);
268 add_include_path(include_path);
269 add_include_path("/usr/include");
270
271 if (verbose)
272 {
273 fprintf(stderr,
274 _("%s, the PostgreSQL embedded C preprocessor, version %s\n"),
275 progname, PG_VERSION);
276 fprintf(stderr, _("EXEC SQL INCLUDE ... search starts here:\n"));
277 for (ip = include_paths; ip != NULL; ip = ip->next)
278 fprintf(stderr, " %s\n", ip->path);
279 fprintf(stderr, _("end of search list\n"));
280 return 0;
281 }
282
283 if (optind >= argc) /* no files specified */
284 {
285 fprintf(stderr, _("%s: no input files specified\n"), progname);
286 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), argv[0]);
287 return ILLEGAL_OPTION;
288 }
289 else
290 {
291 /* after the options there must not be anything but filenames */
292 for (fnr = optind; fnr < argc; fnr++)
293 {
294 char *ptr2ext;
295
296 /* If argv[fnr] is "-" we have to read from stdin */
297 if (strcmp(argv[fnr], "-") == 0)
298 {
299 input_filename = mm_alloc(strlen("stdin") + 1);
300 strcpy(input_filename, "stdin");
301 base_yyin = stdin;
302 }
303 else
304 {
305 input_filename = mm_alloc(strlen(argv[fnr]) + 5);
306 strcpy(input_filename, argv[fnr]);
307
308 /* take care of relative paths */
310 ptr2ext = (ptr2ext ? strrchr(ptr2ext, '.') : strrchr(input_filename, '.'));
311
312 /* no extension? */
313 if (ptr2ext == NULL)
314 {
315 ptr2ext = input_filename + strlen(input_filename);
316
317 /* no extension => add .pgc or .pgh */
318 ptr2ext[0] = '.';
319 ptr2ext[1] = 'p';
320 ptr2ext[2] = 'g';
321 ptr2ext[3] = (header_mode == true) ? 'h' : 'c';
322 ptr2ext[4] = '\0';
323 }
324
326 }
327
328 if (out_option == 0) /* calculate the output name */
329 {
330 if (strcmp(input_filename, "stdin") == 0)
332 else
333 {
336
337 ptr2ext = strrchr(output_filename, '.');
338 /* make extension = .c resp. .h */
339 ptr2ext[1] = (header_mode == true) ? 'h' : 'c';
340 ptr2ext[2] = '\0';
341
343 if (base_yyout == NULL)
344 {
345 fprintf(stderr, _("%s: could not open file \"%s\": %m\n"),
348 output_filename = NULL;
350 continue;
351 }
352 }
353 }
354
355 if (base_yyin == NULL)
356 fprintf(stderr, _("%s: could not open file \"%s\": %m\n"),
357 progname, argv[fnr]);
358 else
359 {
360 struct cursor *ptr;
361 struct _defines *defptr;
362 struct _defines *prevdefptr;
363 struct _defines *nextdefptr;
364 struct typedefs *typeptr;
365 struct declared_list *list;
366
367 /* remove old cursor definitions if any are still there */
368 for (ptr = cur; ptr != NULL;)
369 {
370 struct cursor *this = ptr;
371 struct arguments *l1,
372 *l2;
373
374 free(ptr->command);
375 free(ptr->connection);
376 free(ptr->name);
377 for (l1 = ptr->argsinsert; l1; l1 = l2)
378 {
379 l2 = l1->next;
380 free(l1);
381 }
382 for (l1 = ptr->argsresult; l1; l1 = l2)
383 {
384 l2 = l1->next;
385 free(l1);
386 }
387 ptr = ptr->next;
388 free(this);
389 }
390 cur = NULL;
391
392 /* remove old declared statements if any are still there */
393 for (list = g_declared_list; list != NULL;)
394 {
395 struct declared_list *this = list;
396
397 list = list->next;
398 free(this);
399 }
400
401 /* restore defines to their command-line state */
402 prevdefptr = NULL;
403 for (defptr = defines; defptr != NULL; defptr = nextdefptr)
404 {
405 nextdefptr = defptr->next;
406 if (defptr->cmdvalue != NULL)
407 {
408 /* keep it, resetting the value */
409 free(defptr->value);
410 defptr->value = mm_strdup(defptr->cmdvalue);
411 prevdefptr = defptr;
412 }
413 else
414 {
415 /* remove it */
416 if (prevdefptr != NULL)
417 prevdefptr->next = nextdefptr;
418 else
419 defines = nextdefptr;
420 free(defptr->name);
421 free(defptr->value);
422 free(defptr);
423 }
424 }
425
426 /* and old typedefs */
427 for (typeptr = types; typeptr != NULL;)
428 {
429 struct typedefs *this = typeptr;
430
431 free(typeptr->name);
433 free(typeptr->type);
434 typeptr = typeptr->next;
435 free(this);
436 }
437 types = NULL;
438
439 /* initialize whenever structures */
440 memset(&when_error, 0, sizeof(struct when));
441 memset(&when_nf, 0, sizeof(struct when));
442 memset(&when_warn, 0, sizeof(struct when));
443
444 /* and structure member lists */
445 memset(struct_member_list, 0, sizeof(struct_member_list));
446
447 /*
448 * and our variable counter for out of scope cursors'
449 * variables
450 */
452
453 /* finally the actual connection */
454 connection = NULL;
455
456 /* initialize lex */
457 lex_init();
458
459 /* we need several includes */
460 /* but not if we are in header mode */
461 if (regression_mode)
462 fprintf(base_yyout, "/* Processed by ecpg (regression mode) */\n");
463 else
464 fprintf(base_yyout, "/* Processed by ecpg (%s) */\n", PG_VERSION);
465
466 if (header_mode == false)
467 {
468 fprintf(base_yyout, "/* These include files are added by the preprocessor */\n#include <ecpglib.h>\n#include <ecpgerrno.h>\n#include <sqlca.h>\n");
469
470 /* add some compatibility headers */
471 if (INFORMIX_MODE)
472 fprintf(base_yyout, "/* Needed for informix compatibility */\n#include <ecpg_informix.h>\n");
473
474 fprintf(base_yyout, "/* End of automatic include section */\n");
475 }
476
477 if (regression_mode)
478 fprintf(base_yyout, "#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))\n");
479
481
482 /* and parse the source */
483 base_yyparse();
484
485 /*
486 * Check whether all cursors were indeed opened. It does not
487 * really make sense to declare a cursor but not open it.
488 */
489 for (ptr = cur; ptr != NULL; ptr = ptr->next)
490 if (!(ptr->opened))
491 mmerror(PARSE_ERROR, ET_WARNING, "cursor \"%s\" has been declared but not opened", ptr->name);
492
493 if (base_yyin != NULL && base_yyin != stdin)
494 fclose(base_yyin);
495 if (out_option == 0 && base_yyout != stdout)
496 fclose(base_yyout);
497
498 /*
499 * If there was an error, delete the output file.
500 */
501 if (ret_value != 0)
502 {
503 if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0)
504 fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
505 }
506 }
507
508 if (output_filename && out_option == 0)
509 {
511 output_filename = NULL;
512 }
513
515 }
516 }
517 return ret_value;
518}
#define PG_BINARY_R
Definition: c.h:1229
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1168
#define PG_BINARY_W
Definition: c.h:1230
int find_my_exec(const char *argv0, char *retpath)
Definition: exec.c:160
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:429
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
bool auto_prepare
Definition: ecpg.c:21
char * output_filename
Definition: ecpg.c:24
bool regression_mode
Definition: ecpg.c:20
static void help(const char *progname)
Definition: ecpg.c:35
static void add_include_path(char *path)
Definition: ecpg.c:68
bool system_includes
Definition: ecpg.c:17
bool autocommit
Definition: ecpg.c:15
static void add_preprocessor_define(char *define)
Definition: ecpg.c:90
struct typedefs * types
Definition: ecpg.c:30
enum COMPAT_MODE compat
Definition: ecpg.c:26
int ret_value
Definition: ecpg.c:14
bool auto_create_c
Definition: ecpg.c:16
bool force_indicator
Definition: ecpg.c:18
#define ECPG_GETOPT_LONG_REGRESSION
Definition: ecpg.c:128
struct declared_list * g_declared_list
Definition: ecpg.c:32
bool questionmarks
Definition: ecpg.c:19
struct cursor * cur
Definition: ecpg.c:29
@ ECPG_COMPAT_ORACLE
@ ECPG_COMPAT_INFORMIX
@ ECPG_COMPAT_INFORMIX_SE
#define INFORMIX_MODE(X)
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:60
#define no_argument
Definition: getopt_long.h:24
char my_exec_path[MAXPGPATH]
Definition: globals.c:80
int base_yyparse(core_yyscan_t yyscanner)
#define free(a)
Definition: header.h:65
int verbose
exit(1)
void output_line_number(void)
Definition: output.c:10
struct when when_error when_nf when_warn
Definition: output.c:30
#define MAXPGPATH
PGDLLIMPORT int optind
Definition: getopt.c:51
PGDLLIMPORT char * optarg
Definition: getopt.c:53
void lex_init(void)
Definition: pgc.l:1616
void get_include_path(const char *my_exec_path, char *ret_path)
Definition: path.c:843
char * last_dir_separator(const char *filename)
Definition: path.c:140
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define snprintf
Definition: port.h:238
const char * get_progname(const char *argv0)
Definition: path.c:575
void get_pkginclude_path(const char *my_exec_path, char *ret_path)
Definition: path.c:852
char * c
void mmerror(int error_code, enum errortype type, const char *error,...) pg_attribute_printf(3
int ecpg_internal_var
char * input_filename
#define PARSE_ERROR
struct ECPGstruct_member * struct_member_list[STRUCT_DEPTH]
#define ILLEGAL_OPTION
FILE * base_yyin
FILE * base_yyout
struct arguments * next
Definition: type.h:201
Definition: type.h:138
bool opened
Definition: type.h:143
char * command
Definition: type.h:141
struct arguments * argsinsert
Definition: type.h:144
char * name
Definition: type.h:139
char * connection
Definition: type.h:142
struct cursor * next
Definition: type.h:148
struct arguments * argsresult
Definition: type.h:146
Definition: type.h:159
char * name
Definition: type.h:160
struct ECPGstruct_member * struct_member_list
Definition: type.h:162
struct typedefs * next
Definition: type.h:164
struct this_type * type
Definition: type.h:161
Definition: type.h:89
void ECPGfree_struct_member(struct ECPGstruct_member *rm)
Definition: type.c:618
@ ET_WARNING
Definition: type.h:220

References _, add_include_path(), add_preprocessor_define(), cursor::argsinsert, cursor::argsresult, auto_create_c, auto_prepare, autocommit, base_yyin, base_yyout, base_yyparse(), _defines::cmdvalue, cursor::command, compat, cursor::connection, cur, defines, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE, ECPG_COMPAT_ORACLE, ECPG_GETOPT_LONG_REGRESSION, ecpg_internal_var, ECPGfree_struct_member(), ET_WARNING, exit(), find_my_exec(), force_indicator, fprintf, free, g_declared_list, get_include_path(), get_pkginclude_path(), get_progname(), getopt_long(), help(), ILLEGAL_OPTION, include_paths, INFORMIX_MODE, input_filename, last_dir_separator(), lex_init(), sort-test::list, MAXPGPATH, mm_alloc(), mm_strdup(), mmerror(), my_exec_path, cursor::name, typedefs::name, _defines::name, _include_path::next, cursor::next, typedefs::next, _defines::next, arguments::next, no_argument, cursor::opened, optarg, optind, output_filename, output_line_number(), PARSE_ERROR, _include_path::path, PG_BINARY_R, PG_BINARY_W, pg_strcasecmp(), PG_TEXTDOMAIN, printf, progname, questionmarks, regression_mode, ret_value, set_pglocale_pgservice(), snprintf, generate_unaccent_rules::stdout, struct_member_list, typedefs::struct_member_list, system_includes, typedefs::type, types, _defines::value, verbose, and when_warn.

Variable Documentation

◆ auto_create_c

bool auto_create_c = false

Definition at line 16 of file ecpg.c.

Referenced by main().

◆ auto_prepare

bool auto_prepare = false

Definition at line 21 of file ecpg.c.

Referenced by main(), and output_statement().

◆ autocommit

bool autocommit = false

Definition at line 15 of file ecpg.c.

Referenced by ECPGconnect(), and main().

◆ compat

◆ cur

◆ defines

struct _defines* defines = NULL

Definition at line 31 of file ecpg.c.

Referenced by add_preprocessor_define(), isdefine(), and main().

◆ force_indicator

bool force_indicator = true

◆ g_declared_list

struct declared_list* g_declared_list = NULL

Definition at line 32 of file ecpg.c.

Referenced by main().

◆ include_paths

struct _include_path* include_paths = NULL

Definition at line 28 of file ecpg.c.

Referenced by add_include_path(), main(), and parse_include().

◆ output_filename

char* output_filename

◆ progname

const char* progname
static

Definition at line 23 of file ecpg.c.

Referenced by help(), and main().

◆ questionmarks

bool questionmarks = false

◆ regression_mode

bool regression_mode = false

Definition at line 20 of file ecpg.c.

Referenced by main().

◆ ret_value

int ret_value = 0

Definition at line 14 of file ecpg.c.

Referenced by main(), and vmmerror().

◆ system_includes

bool system_includes = false

Definition at line 17 of file ecpg.c.

Referenced by main().

◆ types