~ubuntu-branches/ubuntu/precise/postgresql-9.1/precise-security

« back to all changes in this revision

Viewing changes to src/interfaces/ecpg/preproc/ecpg.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* src/interfaces/ecpg/preproc/ecpg.c */
 
2
 
 
3
/* Main for ecpg, the PostgreSQL embedded SQL precompiler. */
 
4
/* Copyright (c) 1996-2011, PostgreSQL Global Development Group */
 
5
 
 
6
#include "postgres_fe.h"
 
7
 
 
8
#include <unistd.h>
 
9
#include <string.h>
 
10
#include "getopt_long.h"
 
11
 
 
12
#include "extern.h"
 
13
 
 
14
int                     ret_value = 0;
 
15
bool            autocommit = false,
 
16
                        auto_create_c = false,
 
17
                        system_includes = false,
 
18
                        force_indicator = true,
 
19
                        questionmarks = false,
 
20
                        regression_mode = false,
 
21
                        auto_prepare = false;
 
22
 
 
23
char       *output_filename;
 
24
 
 
25
enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL;
 
26
 
 
27
struct _include_path *include_paths = NULL;
 
28
struct cursor *cur = NULL;
 
29
struct typedefs *types = NULL;
 
30
struct _defines *defines = NULL;
 
31
 
 
32
static void
 
33
help(const char *progname)
 
34
{
 
35
        printf(_("%s is the PostgreSQL embedded SQL preprocessor for C programs.\n\n"),
 
36
                   progname);
 
37
        printf(_("Usage:\n"
 
38
                         "  %s [OPTION]... FILE...\n\n"),
 
39
                   progname);
 
40
        printf(_("Options:\n"));
 
41
        printf(_("  -c             automatically generate C code from embedded SQL code;\n"
 
42
                         "                 this affects EXEC SQL TYPE\n"));
 
43
        printf(_("  -C MODE        set compatibility mode; MODE can be one of\n"
 
44
                         "                 \"INFORMIX\", \"INFORMIX_SE\"\n"));
 
45
#ifdef YYDEBUG
 
46
        printf(_("  -d             generate parser debug output\n"));
 
47
#endif
 
48
        printf(_("  -D SYMBOL      define SYMBOL\n"));
 
49
        printf(_("  -h             parse a header file, this option includes option \"-c\"\n"));
 
50
        printf(_("  -i             parse system include files as well\n"));
 
51
        printf(_("  -I DIRECTORY   search DIRECTORY for include files\n"));
 
52
        printf(_("  -o OUTFILE     write result to OUTFILE\n"));
 
53
        printf(_("  -r OPTION      specify run-time behavior; OPTION can be:\n"
 
54
         "                 \"no_indicator\", \"prepare\", \"questionmarks\"\n"));
 
55
        printf(_("  --regression   run in regression testing mode\n"));
 
56
        printf(_("  -t             turn on autocommit of transactions\n"));
 
57
        printf(_("  --help         show this help, then exit\n"));
 
58
        printf(_("  --version      output version information, then exit\n"));
 
59
        printf(_("\nIf no output file is specified, the name is formed by adding .c to the\n"
 
60
                         "input file name, after stripping off .pgc if present.\n"));
 
61
        printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
 
62
}
 
63
 
 
64
static void
 
65
add_include_path(char *path)
 
66
{
 
67
        struct _include_path *ip = include_paths,
 
68
                           *new;
 
69
 
 
70
        new = mm_alloc(sizeof(struct _include_path));
 
71
        new->path = path;
 
72
        new->next = NULL;
 
73
 
 
74
        if (ip == NULL)
 
75
                include_paths = new;
 
76
        else
 
77
        {
 
78
                for (; ip->next != NULL; ip = ip->next);
 
79
                ip->next = new;
 
80
        }
 
81
}
 
82
 
 
83
static void
 
84
add_preprocessor_define(char *define)
 
85
{
 
86
        struct _defines *pd = defines;
 
87
        char       *ptr,
 
88
                           *define_copy = mm_strdup(define);
 
89
 
 
90
        defines = mm_alloc(sizeof(struct _defines));
 
91
 
 
92
        /* look for = sign */
 
93
        ptr = strchr(define_copy, '=');
 
94
        if (ptr != NULL)
 
95
        {
 
96
                char       *tmp;
 
97
 
 
98
                /* symbol has a value */
 
99
                for (tmp = ptr - 1; *tmp == ' '; tmp--);
 
100
                tmp[1] = '\0';
 
101
                defines->old = define_copy;
 
102
                defines->new = ptr + 1;
 
103
        }
 
104
        else
 
105
        {
 
106
                defines->old = define_copy;
 
107
                defines->new = mm_strdup("1");
 
108
        }
 
109
        defines->pertinent = true;
 
110
        defines->used = NULL;
 
111
        defines->next = pd;
 
112
}
 
113
 
 
114
#define ECPG_GETOPT_LONG_HELP                   1
 
115
#define ECPG_GETOPT_LONG_VERSION                2
 
116
#define ECPG_GETOPT_LONG_REGRESSION             3
 
117
int
 
118
main(int argc, char *const argv[])
 
119
{
 
120
        static struct option ecpg_options[] = {
 
121
                {"help", no_argument, NULL, ECPG_GETOPT_LONG_HELP},
 
122
                {"version", no_argument, NULL, ECPG_GETOPT_LONG_VERSION},
 
123
                {"regression", no_argument, NULL, ECPG_GETOPT_LONG_REGRESSION},
 
124
                {NULL, 0, NULL, 0}
 
125
        };
 
126
 
 
127
        int                     fnr,
 
128
                                c,
 
129
                                out_option = 0;
 
130
        bool            verbose = false,
 
131
                                header_mode = false;
 
132
        struct _include_path *ip;
 
133
        const char *progname;
 
134
        char            my_exec_path[MAXPGPATH];
 
135
        char            include_path[MAXPGPATH];
 
136
 
 
137
        set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("ecpg"));
 
138
 
 
139
        progname = get_progname(argv[0]);
 
140
 
 
141
        find_my_exec(argv[0], my_exec_path);
 
142
 
 
143
        output_filename = NULL;
 
144
        while ((c = getopt_long(argc, argv, "vcio:I:tD:dC:r:h?", ecpg_options, NULL)) != -1)
 
145
        {
 
146
                switch (c)
 
147
                {
 
148
                        case ECPG_GETOPT_LONG_VERSION:
 
149
                                printf("ecpg (PostgreSQL %s) %d.%d.%d\n", PG_VERSION,
 
150
                                           MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
 
151
                                exit(0);
 
152
                        case ECPG_GETOPT_LONG_HELP:
 
153
                                help(progname);
 
154
                                exit(0);
 
155
 
 
156
                                /*
 
157
                                 * -? is an alternative spelling of --help. However it is also
 
158
                                 * returned by getopt_long for unknown options. We can
 
159
                                 * distinguish both cases by means of the optopt variable
 
160
                                 * which is set to 0 if it was really -? and not an unknown
 
161
                                 * option character.
 
162
                                 */
 
163
                        case '?':
 
164
                                if (optopt == 0)
 
165
                                {
 
166
                                        help(progname);
 
167
                                        exit(0);
 
168
                                }
 
169
                                break;
 
170
                        case ECPG_GETOPT_LONG_REGRESSION:
 
171
                                regression_mode = true;
 
172
                                break;
 
173
                        case 'o':
 
174
                                output_filename = optarg;
 
175
                                if (strcmp(output_filename, "-") == 0)
 
176
                                        yyout = stdout;
 
177
                                else
 
178
                                        yyout = fopen(output_filename, PG_BINARY_W);
 
179
 
 
180
                                if (yyout == NULL)
 
181
                                {
 
182
                                        fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
 
183
                                                        progname, output_filename, strerror(errno));
 
184
                                        output_filename = NULL;
 
185
                                }
 
186
                                else
 
187
                                        out_option = 1;
 
188
                                break;
 
189
                        case 'I':
 
190
                                add_include_path(optarg);
 
191
                                break;
 
192
                        case 't':
 
193
                                autocommit = true;
 
194
                                break;
 
195
                        case 'v':
 
196
                                verbose = true;
 
197
                                break;
 
198
                        case 'h':
 
199
                                header_mode = true;
 
200
                                /* this must include "-c" to make sense */
 
201
                                /* so do not place a "break;" here */
 
202
                        case 'c':
 
203
                                auto_create_c = true;
 
204
                                break;
 
205
                        case 'i':
 
206
                                system_includes = true;
 
207
                                break;
 
208
                        case 'C':
 
209
                                if (strncmp(optarg, "INFORMIX", strlen("INFORMIX")) == 0)
 
210
                                {
 
211
                                        char            pkginclude_path[MAXPGPATH];
 
212
                                        char            informix_path[MAXPGPATH];
 
213
 
 
214
                                        compat = (strcmp(optarg, "INFORMIX") == 0) ? ECPG_COMPAT_INFORMIX : ECPG_COMPAT_INFORMIX_SE;
 
215
                                        get_pkginclude_path(my_exec_path, pkginclude_path);
 
216
                                        snprintf(informix_path, MAXPGPATH, "%s/informix/esql", pkginclude_path);
 
217
                                        add_include_path(informix_path);
 
218
                                }
 
219
                                else
 
220
                                {
 
221
                                        fprintf(stderr, _("Try \"%s --help\" for more information.\n"), argv[0]);
 
222
                                        return ILLEGAL_OPTION;
 
223
                                }
 
224
                                break;
 
225
                        case 'r':
 
226
                                if (strcmp(optarg, "no_indicator") == 0)
 
227
                                        force_indicator = false;
 
228
                                else if (strcmp(optarg, "prepare") == 0)
 
229
                                        auto_prepare = true;
 
230
                                else if (strcmp(optarg, "questionmarks") == 0)
 
231
                                        questionmarks = true;
 
232
                                else
 
233
                                {
 
234
                                        fprintf(stderr, _("Try \"%s --help\" for more information.\n"), argv[0]);
 
235
                                        return ILLEGAL_OPTION;
 
236
                                }
 
237
                                break;
 
238
                        case 'D':
 
239
                                add_preprocessor_define(optarg);
 
240
                                break;
 
241
                        case 'd':
 
242
#ifdef YYDEBUG
 
243
                                yydebug = 1;
 
244
#else
 
245
                                fprintf(stderr, _("%s: parser debug support (-d) not available\n"),
 
246
                                                progname);
 
247
#endif
 
248
                                break;
 
249
                        default:
 
250
                                fprintf(stderr, _("Try \"%s --help\" for more information.\n"), argv[0]);
 
251
                                return ILLEGAL_OPTION;
 
252
                }
 
253
        }
 
254
 
 
255
        add_include_path(".");
 
256
        add_include_path("/usr/local/include");
 
257
        get_include_path(my_exec_path, include_path);
 
258
        add_include_path(include_path);
 
259
        add_include_path("/usr/include");
 
260
 
 
261
        if (verbose)
 
262
        {
 
263
                fprintf(stderr, _("%s, the PostgreSQL embedded C preprocessor, version %d.%d.%d\n"),
 
264
                                progname, MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
 
265
                fprintf(stderr, _("EXEC SQL INCLUDE ... search starts here:\n"));
 
266
                for (ip = include_paths; ip != NULL; ip = ip->next)
 
267
                        fprintf(stderr, " %s\n", ip->path);
 
268
                fprintf(stderr, _("end of search list\n"));
 
269
                return 0;
 
270
        }
 
271
 
 
272
        if (optind >= argc)                     /* no files specified */
 
273
        {
 
274
                fprintf(stderr, _("%s: no input files specified\n"), progname);
 
275
                fprintf(stderr, _("Try \"%s --help\" for more information.\n"), argv[0]);
 
276
                return (ILLEGAL_OPTION);
 
277
        }
 
278
        else
 
279
        {
 
280
                /* after the options there must not be anything but filenames */
 
281
                for (fnr = optind; fnr < argc; fnr++)
 
282
                {
 
283
                        char       *ptr2ext;
 
284
 
 
285
                        /* If argv[fnr] is "-" we have to read from stdin */
 
286
                        if (strcmp(argv[fnr], "-") == 0)
 
287
                        {
 
288
                                input_filename = mm_alloc(strlen("stdin") + 1);
 
289
                                strcpy(input_filename, "stdin");
 
290
                                yyin = stdin;
 
291
                        }
 
292
                        else
 
293
                        {
 
294
                                input_filename = mm_alloc(strlen(argv[fnr]) + 5);
 
295
                                strcpy(input_filename, argv[fnr]);
 
296
 
 
297
                                /* take care of relative paths */
 
298
                                ptr2ext = last_dir_separator(input_filename);
 
299
                                ptr2ext = (ptr2ext ? strrchr(ptr2ext, '.') : strrchr(input_filename, '.'));
 
300
 
 
301
                                /* no extension? */
 
302
                                if (ptr2ext == NULL)
 
303
                                {
 
304
                                        ptr2ext = input_filename + strlen(input_filename);
 
305
 
 
306
                                        /* no extension => add .pgc or .pgh */
 
307
                                        ptr2ext[0] = '.';
 
308
                                        ptr2ext[1] = 'p';
 
309
                                        ptr2ext[2] = 'g';
 
310
                                        ptr2ext[3] = (header_mode == true) ? 'h' : 'c';
 
311
                                        ptr2ext[4] = '\0';
 
312
                                }
 
313
 
 
314
                                yyin = fopen(input_filename, PG_BINARY_R);
 
315
                        }
 
316
 
 
317
                        if (out_option == 0)    /* calculate the output name */
 
318
                        {
 
319
                                if (strcmp(input_filename, "stdin") == 0)
 
320
                                        yyout = stdout;
 
321
                                else
 
322
                                {
 
323
                                        output_filename = strdup(input_filename);
 
324
 
 
325
                                        ptr2ext = strrchr(output_filename, '.');
 
326
                                        /* make extension = .c resp. .h */
 
327
                                        ptr2ext[1] = (header_mode == true) ? 'h' : 'c';
 
328
                                        ptr2ext[2] = '\0';
 
329
 
 
330
                                        yyout = fopen(output_filename, PG_BINARY_W);
 
331
                                        if (yyout == NULL)
 
332
                                        {
 
333
                                                fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
 
334
                                                                progname, output_filename, strerror(errno));
 
335
                                                free(output_filename);
 
336
                                                free(input_filename);
 
337
                                                continue;
 
338
                                        }
 
339
                                }
 
340
                        }
 
341
 
 
342
                        if (yyin == NULL)
 
343
                                fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
 
344
                                                progname, argv[fnr], strerror(errno));
 
345
                        else
 
346
                        {
 
347
                                struct cursor *ptr;
 
348
                                struct _defines *defptr;
 
349
                                struct typedefs *typeptr;
 
350
 
 
351
                                /* remove old cursor definitions if any are still there */
 
352
                                for (ptr = cur; ptr != NULL;)
 
353
                                {
 
354
                                        struct cursor *this = ptr;
 
355
                                        struct arguments *l1,
 
356
                                                           *l2;
 
357
 
 
358
                                        free(ptr->command);
 
359
                                        free(ptr->connection);
 
360
                                        free(ptr->name);
 
361
                                        for (l1 = ptr->argsinsert; l1; l1 = l2)
 
362
                                        {
 
363
                                                l2 = l1->next;
 
364
                                                free(l1);
 
365
                                        }
 
366
                                        for (l1 = ptr->argsresult; l1; l1 = l2)
 
367
                                        {
 
368
                                                l2 = l1->next;
 
369
                                                free(l1);
 
370
                                        }
 
371
                                        ptr = ptr->next;
 
372
                                        free(this);
 
373
                                }
 
374
                                cur = NULL;
 
375
 
 
376
                                /* remove non-pertinent old defines as well */
 
377
                                while (defines && !defines->pertinent)
 
378
                                {
 
379
                                        defptr = defines;
 
380
                                        defines = defines->next;
 
381
 
 
382
                                        free(defptr->new);
 
383
                                        free(defptr->old);
 
384
                                        free(defptr);
 
385
                                }
 
386
 
 
387
                                for (defptr = defines; defptr != NULL; defptr = defptr->next)
 
388
                                {
 
389
                                        struct _defines *this = defptr->next;
 
390
 
 
391
                                        if (this && !this->pertinent)
 
392
                                        {
 
393
                                                defptr->next = this->next;
 
394
 
 
395
                                                free(this->new);
 
396
                                                free(this->old);
 
397
                                                free(this);
 
398
                                        }
 
399
                                }
 
400
 
 
401
                                /* and old typedefs */
 
402
                                for (typeptr = types; typeptr != NULL;)
 
403
                                {
 
404
                                        struct typedefs *this = typeptr;
 
405
 
 
406
                                        free(typeptr->name);
 
407
                                        ECPGfree_struct_member(typeptr->struct_member_list);
 
408
                                        free(typeptr->type);
 
409
                                        typeptr = typeptr->next;
 
410
                                        free(this);
 
411
                                }
 
412
                                types = NULL;
 
413
 
 
414
                                /* initialize whenever structures */
 
415
                                memset(&when_error, 0, sizeof(struct when));
 
416
                                memset(&when_nf, 0, sizeof(struct when));
 
417
                                memset(&when_warn, 0, sizeof(struct when));
 
418
 
 
419
                                /* and structure member lists */
 
420
                                memset(struct_member_list, 0, sizeof(struct_member_list));
 
421
 
 
422
                                /*
 
423
                                 * and our variable counter for out of scope cursors'
 
424
                                 * variables
 
425
                                 */
 
426
                                ecpg_internal_var = 0;
 
427
 
 
428
                                /* finally the actual connection */
 
429
                                connection = NULL;
 
430
 
 
431
                                /* initialize lex */
 
432
                                lex_init();
 
433
 
 
434
                                /* we need several includes */
 
435
                                /* but not if we are in header mode */
 
436
                                if (regression_mode)
 
437
                                        fprintf(yyout, "/* Processed by ecpg (regression mode) */\n");
 
438
                                else
 
439
                                        fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
 
440
 
 
441
                                if (header_mode == false)
 
442
                                {
 
443
                                        fprintf(yyout, "/* These include files are added by the preprocessor */\n#include <ecpglib.h>\n#include <ecpgerrno.h>\n#include <sqlca.h>\n");
 
444
 
 
445
                                        /* add some compatibility headers */
 
446
                                        if (INFORMIX_MODE)
 
447
                                                fprintf(yyout, "/* Needed for informix compatibility */\n#include <ecpg_informix.h>\n");
 
448
 
 
449
                                        fprintf(yyout, "/* End of automatic include section */\n");
 
450
                                }
 
451
 
 
452
                                if (regression_mode)
 
453
                                        fprintf(yyout, "#define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))\n");
 
454
 
 
455
                                output_line_number();
 
456
 
 
457
                                /* and parse the source */
 
458
                                base_yyparse();
 
459
 
 
460
                                /*
 
461
                                 * Check whether all cursors were indeed opened.  It does not
 
462
                                 * really make sense to declare a cursor but not open it.
 
463
                                 */
 
464
                                for (ptr = cur; ptr != NULL; ptr = ptr->next)
 
465
                                        if (!(ptr->opened))
 
466
                                                mmerror(PARSE_ERROR, ET_WARNING, "cursor \"%s\" has been declared but not opened", ptr->name);
 
467
 
 
468
                                if (yyin != NULL && yyin != stdin)
 
469
                                        fclose(yyin);
 
470
                                if (out_option == 0 && yyout != stdout)
 
471
                                        fclose(yyout);
 
472
 
 
473
                                /*
 
474
                                 * If there was an error, delete the output file.
 
475
                                 */
 
476
                                if (ret_value != 0)
 
477
                                {
 
478
                                        if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0)
 
479
                                                fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
 
480
                                }
 
481
                        }
 
482
 
 
483
                        if (output_filename && out_option == 0)
 
484
                                free(output_filename);
 
485
 
 
486
                        free(input_filename);
 
487
                }
 
488
        }
 
489
        return ret_value;
 
490
}