]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/preproc/ecpg.c
- Synced parser and keyword file.
[postgresql] / src / interfaces / ecpg / preproc / ecpg.c
1 /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.60 2003/02/14 13:17:13 meskes Exp $ */
2
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 PostgresSQL */
6
7 #include "postgres_fe.h"
8
9 #include <unistd.h>
10 #ifdef HAVE_GETOPT_H
11 #include <getopt.h>
12 #endif
13
14 extern int      optind;
15 extern char *optarg;
16
17 #include "extern.h"
18
19 int                     ret_value = 0,
20                         autocommit = false,
21                         auto_create_c = false;
22
23 enum COMPAT_MODE        compat = ECPG_COMPAT_PGSQL;
24
25 struct _include_path *include_paths = NULL;
26 struct cursor *cur = NULL;
27 struct typedefs *types = NULL;
28 struct _defines *defines = NULL;
29
30 static void
31 help(const char *progname)
32 {
33         printf("%s is the PostgreSQL embedded SQL preprocessor for C programs.\n\n",
34                    progname);
35         printf("Usage:\n"
36                    "  %s [OPTION]... FILE...\n\n",
37                    progname);
38         printf("Options:\n");
39         printf("  -c             automatically generate C code from embedded SQL code;\n"
40                    "                 currently this works for EXEC SQL TYPE\n");
41 #ifdef YYDEBUG
42         printf("  -d             generate parser debug output\n");
43 #endif
44         printf("  -C <mode>      set compatibility mode\n"
45                    "                 mode may be INFORMIX only at the moment\n");
46         printf("  -D SYMBOL      define SYMBOL\n");
47         printf("  -I DIRECTORY   search DIRECTORY for include files\n");
48         printf("  -o OUTFILE     write result to OUTFILE\n");
49         printf("  -t             turn on autocommit of transactions\n");
50         printf("  --help         show this help, then exit\n");
51         printf("  --version      output version information, then exit\n");
52         printf("\nIf no output file is specified, the name is formed by adding .c to the\n"
53                    "input file name, after stripping off .pgc if present.\n");
54         printf("\nReport bugs to <pgsql-bugs@postgresql.org>.\n");
55 }
56
57 static void
58 add_include_path(char *path)
59 {
60         struct _include_path *ip = include_paths;
61
62         include_paths = mm_alloc(sizeof(struct _include_path));
63         include_paths->path = path;
64         include_paths->next = ip;
65
66 }
67
68 static void
69 add_preprocessor_define(char *define)
70 {
71         struct _defines *pd = defines;
72
73         defines = mm_alloc(sizeof(struct _defines));
74         defines->old = strdup(define);
75         defines->new = strdup("");
76         defines->pertinent = true;
77         defines->next = pd;
78 }
79
80 int
81 main(int argc, char *const argv[])
82 {
83         int                     fnr,
84                                 c,
85                                 verbose = false,
86                                 out_option = 0;
87         struct _include_path *ip;
88         char       *progname;
89
90         if (!strrchr(argv[0], '/'))
91                 progname = argv[0];
92         else
93                 progname = strrchr(argv[0], '/') + 1;
94
95         if (argc > 1)
96         {
97                 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
98                 {
99                         help(progname);
100                         exit(0);
101                 }
102                 else if (strcmp(argv[1], "--version") == 0)
103                 {
104                         printf("ecpg (PostgreSQL %s) %d.%d.%d\n", PG_VERSION,
105                                    MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
106                         exit(0);
107                 }
108         }
109
110         add_include_path("/usr/include");
111         add_include_path(INCLUDE_PATH);
112         add_include_path("/usr/local/include");
113         add_include_path(".");
114
115         while ((c = getopt(argc, argv, "vco:I:tD:dC:")) != -1)
116         {
117                 switch (c)
118                 {
119                         case 'o':
120                                 yyout = fopen(optarg, PG_BINARY_W);
121                                 if (yyout == NULL)
122                                         perror(optarg);
123                                 else
124                                         out_option = 1;
125                                 break;
126                         case 'I':
127                                 add_include_path(optarg);
128                                 break;
129                         case 't':
130                                 autocommit = true;
131                                 break;
132                         case 'v':
133                                 verbose = true;
134                                 break;
135                         case 'c':
136                                 auto_create_c = true;
137                                 break;
138                         case 'C':
139                                 if (strcmp(optarg, "INFORMIX") == 0)
140                                         compat = ECPG_COMPAT_INFORMIX;
141                                 else
142                                 {
143                                         fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
144                                         return ILLEGAL_OPTION;
145                                 }                               
146                                 break;
147                         case 'D':
148                                 add_preprocessor_define(optarg);
149                                 break;
150                         case 'd':
151 #ifdef YYDEBUG
152                                 yydebug = 1;
153 #else
154                                 fprintf(stderr, "%s: parser debug support (-d) not available\n",
155                                                 progname);
156 #endif
157                                 break;
158                         default:
159                                 fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
160                                 return ILLEGAL_OPTION;
161                 }
162         }
163
164         if (verbose)
165         {
166                 fprintf(stderr, "%s, the PostgreSQL embedded C preprocessor, version %d.%d.%d\n",
167                                 progname, MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
168                 fprintf(stderr, "exec sql include ... search starts here:\n");
169                 for (ip = include_paths; ip != NULL; ip = ip->next)
170                         fprintf(stderr, " %s\n", ip->path);
171                 fprintf(stderr, "end of search list\n");
172                 return 0;
173         }
174
175         if (optind >= argc)                     /* no files specified */
176         {
177                 fprintf(stderr, "%s: no input files specified\n", progname);
178                 fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
179                 return (ILLEGAL_OPTION);
180         }
181         else
182         {
183                 /* after the options there must not be anything but filenames */
184                 for (fnr = optind; fnr < argc; fnr++)
185                 {
186                         char       *output_filename = NULL,
187                                            *ptr2ext;
188
189                         input_filename = mm_alloc(strlen(argv[fnr]) + 5);
190
191                         strcpy(input_filename, argv[fnr]);
192
193                         /* take care of relative paths */
194                         ptr2ext = strrchr(input_filename, '/');
195                         ptr2ext = (ptr2ext ? strrchr(ptr2ext, '.') : strrchr(input_filename, '.'));
196
197                         /* no extension? */
198                         if (ptr2ext == NULL)
199                         {
200                                 ptr2ext = input_filename + strlen(input_filename);
201
202                                 /* no extension => add .pgc */
203                                 ptr2ext[0] = '.';
204                                 ptr2ext[1] = 'p';
205                                 ptr2ext[2] = 'g';
206                                 ptr2ext[3] = 'c';
207                                 ptr2ext[4] = '\0';
208                         }
209
210                         if (out_option == 0)    /* calculate the output name */
211                         {
212                                 output_filename = strdup(input_filename);
213
214                                 ptr2ext = strrchr(output_filename, '.');
215                                 /* make extension = .c */
216                                 ptr2ext[1] = 'c';
217                                 ptr2ext[2] = '\0';
218
219                                 yyout = fopen(output_filename, PG_BINARY_W);
220                                 if (yyout == NULL)
221                                 {
222                                         perror(output_filename);
223                                         free(output_filename);
224                                         free(input_filename);
225                                         continue;
226                                 }
227                         }
228
229                         yyin = fopen(input_filename, PG_BINARY_R);
230                         if (yyin == NULL)
231                                 perror(argv[fnr]);
232                         else
233                         {
234                                 struct cursor *ptr;
235                                 struct _defines *defptr;
236                                 struct typedefs *typeptr;
237
238                                 /* remove old cursor definitions if any are still there */
239                                 for (ptr = cur; ptr != NULL;)
240                                 {
241                                         struct cursor *this = ptr;
242                                         struct arguments *l1,
243                                                            *l2;
244
245                                         free(ptr->command);
246                                         free(ptr->connection);
247                                         free(ptr->name);
248                                         for (l1 = ptr->argsinsert; l1; l1 = l2)
249                                         {
250                                                 l2 = l1->next;
251                                                 free(l1);
252                                         }
253                                         for (l1 = ptr->argsresult; l1; l1 = l2)
254                                         {
255                                                 l2 = l1->next;
256                                                 free(l1);
257                                         }
258                                         ptr = ptr->next;
259                                         free(this);
260                                 }
261                                 cur = NULL;
262
263                                 /* remove non-pertinent old defines as well */
264                                 while (defines && !defines->pertinent)
265                                 {
266                                         defptr = defines;
267                                         defines = defines->next;
268
269                                         free(defptr->new);
270                                         free(defptr->old);
271                                         free(defptr);
272                                 }
273
274                                 for (defptr = defines; defptr != NULL; defptr = defptr->next)
275                                 {
276                                         struct _defines *this = defptr->next;
277
278                                         if (this && !this->pertinent)
279                                         {
280                                                 defptr->next = this->next;
281
282                                                 free(this->new);
283                                                 free(this->old);
284                                                 free(this);
285                                         }
286                                 }
287
288                                 /* and old typedefs */
289                                 for (typeptr = types; typeptr != NULL;)
290                                 {
291                                         struct typedefs *this = typeptr;
292
293                                         free(typeptr->name);
294                                         ECPGfree_struct_member(typeptr->struct_member_list);
295                                         free(typeptr->type);
296                                         typeptr = typeptr->next;
297                                         free(this);
298                                 }
299                                 types = NULL;
300
301                                 /* initialize whenever structures */
302                                 memset(&when_error, 0, sizeof(struct when));
303                                 memset(&when_nf, 0, sizeof(struct when));
304                                 memset(&when_warn, 0, sizeof(struct when));
305
306                                 /* and structure member lists */
307                                 memset(struct_member_list, 0, sizeof(struct_member_list));
308
309                                 /* finally the actual connection */
310                                 connection = NULL;
311
312                                 /* initialize lex */
313                                 lex_init();
314
315                                 /* we need several includes */
316                                 fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n/* These four include files are added by the preprocessor */\n#include <ecpgtype.h>\n#include <ecpglib.h>\n#include <ecpgerrno.h>\n#include <sqlca.h>\n#line 1 \"%s\"\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL, input_filename);
317
318                                 /* add some compatibility headers */
319                                 if (compat == ECPG_COMPAT_INFORMIX)
320                                         fprintf(yyout, "/* Needed for informix compatibility */\n#include <ecpg_informix.h>\n");
321
322                                 /* and parse the source */
323                                 yyparse();
324
325                                 if (yyin != NULL)
326                                         fclose(yyin);
327                                 if (out_option == 0)
328                                         fclose(yyout);
329                         }
330
331                         if (output_filename)
332                                 free(output_filename);
333
334                         free(input_filename);
335                 }
336         }
337         return ret_value;
338 }