1 /*------------------------------------------------------------*
2 | init.c |
3 | copyright 1999, Andrew Sumner |
4 | copyright 1991, Michael D. Brennan |
5 | |
6 | This is a source file for the awka package, a translator |
7 | of the AWK programming language to ANSI C. |
8 | |
9 | The file is a modified version of init.c from |
10 | Mawk, an implementation of the AWK processing language, |
11 | distributed by Michael Brennan under the GPL. |
12 | |
13 | This program is free software; you can redistribute it |
14 | and/or modify it under the terms of the GNU General Public |
15 | License as published by the Free Software Foundation; |
16 | either version 2 of the License, or any later version. |
17 | |
18 | This program is distributed in the hope that it will be |
19 | useful, but WITHOUT ANY WARRANTY; without even the implied |
20 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
21 | PURPOSE. See the GNU General Public License for more |
22 | details. |
23 | |
24 | You should have received a copy of the GNU General Public |
25 | License along with this program; if not, write to the |
26 | Free Software Foundation, Inc., 675 Mass Ave, Cambridge, |
27 | MA 02139, USA. |
28 *-----------------------------------------------------------*/
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 /* init.c */
35 #include "awka.h"
36 #include "msg.h"
37 #include "code.h"
38 #include "memory.h"
39 #include "symtype.h"
40 #include "init.h"
41 #include "bi_vars.h"
42 #include "field.h"
43
44 static void PROTO(process_cmdline, (int, char **)) ;
45 static void PROTO(set_ARGV, (int, char **, int)) ;
46 static void PROTO(bad_option, (char *)) ;
47 static void PROTO(no_program, (void)) ;
48
49 extern void PROTO(print_version, (void)) ;
50 extern int PROTO(is_cmdline_assign, (char *)) ;
51
52 extern int awka_main;
53 extern char *awka_main_func;
54
55 char *progname, *uoutfile = NULL ;
56 extern char *int_argv;
57 short interactive_flag = 0 ;
58 char awka_exe = FALSE, awka_comp = FALSE;
59 char awka_tmp = FALSE;
60 int exe_argc = 0;
61 char **exe_argv = NULL;
62 char **incfile = NULL, **incdir = NULL, **libfile = NULL, **libdir = NULL;
63 int incf_allc = 0, incf_used = 0, incd_allc = 0, incd_used = 0, libf_allc = 0, libf_used = 0, libd_allc = 0, libd_used = 0;
64 int dump = 0, warning_msg = 0;
65
66 #ifndef SET_PROGNAME
67 #define SET_PROGNAME() \
68 {char *p = strrchr(argv[0],'/') ;\
69 progname = p ? p+1 : argv[0] ; }
70 #endif
71
72 void
initialize(argc,argv)73 initialize(argc, argv)
74 int argc ; char **argv ;
75 {
76
77 SET_PROGNAME() ;
78
79 bi_vars_init() ; /* load the builtin variables */
80 bi_funct_init() ; /* load the builtin functions */
81 kw_init() ; /* load the keywords */
82 field_init() ;
83
84 process_cmdline(argc, argv) ;
85
86 code_init() ;
87 }
88
89 int dump_code_flag ; /* if on dump internal code */
90 short posix_space_flag ;
91
92 #ifdef DEBUG
93 int dump_RE ; /* if on dump compiled REs */
94 #endif
95
96
97 static void
bad_option(s)98 bad_option(s)
99 char *s ;
100 {
101 errmsg(0, "not an option: %s", s) ; exit(2) ;
102 }
103
104 static void
no_program()105 no_program()
106 {
107 exit(0) ;
108 }
109
110 static void
process_cmdline(argc,argv)111 process_cmdline(argc, argv)
112 int argc ;
113 char **argv ;
114 {
115 int i, j, nextarg ;
116 char *optarg, *p ;
117 PFILE dummy ; /* starts linked list of filenames */
118 PFILE *tail = &dummy ;
119
120 for (i = 1; i < argc && argv[i][0] == '-'; i = nextarg)
121 {
122 if (argv[i][1] == 0) /* - alone */
123 {
124 if (!pfile_name) no_program() ;
125 break ; /* the for loop */
126 }
127 /* safe to look at argv[i][2] */
128
129 j = 1;
130 if (argv[i][j] == '-' && argv[i][0] == '-') j++;
131
132 if (argv[i][j+1] == 0)
133 {
134 if (i == argc - 1 && argv[i][j] != '-' &&
135 argv[i][j] != 'u' && argv[i][j] != 'v' &&
136 argv[i][j] != 'h')
137 {
138 /* there are no more arguments - does this option need one? */
139 if (strchr("IiLlaocfxwt-", argv[i][j]))
140 {
141 errmsg(0, "option %s lacks argument", argv[i]) ;
142 exit(2) ;
143 }
144 bad_option(argv[i]) ;
145 }
146 else if (strchr("-DxtX", argv[i][j]))
147 {
148 nextarg = i + 1;
149 }
150 else
151 {
152 optarg = argv[i + 1] ;
153 nextarg = i + 2 ;
154 }
155 }
156 else if (!strcmp(argv[i], "--"))
157 {
158 if (!awka_exe)
159 {
160 fprintf(stderr,"Need a \"-x\" argument for \"--\" to make any sense.\n");
161 exit(0);
162 }
163 if (pfile_name)
164 scan_init((char *) 0);
165 else
166 {
167 if (i == 0) no_program() ;
168 scan_init(argv[i-1]) ;
169 }
170 goto exe_opts;
171 }
172 else /* argument glued to option mb */
173 {
174 if (argv[i][j-1] == '-')
175 {
176 optarg = &argv[i][j] ;
177 nextarg = i + 1 ;
178 if (argv[i][j] != 'h' && argv[i][j] != 'v' && argv[i][j] != 'u')
179 j++;
180 }
181 else
182 {
183 optarg = &argv[i][j] ;
184 nextarg = i + 1 ;
185 }
186 }
187
188 switch (argv[i][j])
189 {
190 case 'v':
191 print_version() ;
192 break ;
193
194 case 'f':
195 /* first file goes in pfile_name ; any more go
196 on a list */
197 if (!pfile_name) pfile_name = optarg ;
198 else
199 {
200 tail = tail->link = ZMALLOC(PFILE) ;
201 tail->fname = optarg ;
202 }
203 break ;
204
205 case 'c':
206 awka_main = 1;
207 awka_exe = awka_comp = awka_tmp = FALSE;
208 if (argv[i+1][0] == '-')
209 {
210 fprintf(stderr,"Command Line Error: Expecting function-name after -c argument.\n");
211 exit(1);
212 }
213 awka_main_func = argv[i+1];
214 break;
215
216 case 'w': /* warning messages */
217 if (argv[i+1][0] == '-')
218 {
219 fprintf(stderr,"Command Line Error: Expecting message flags 'abcdefg' after -w argument.\n");
220 exit(1);
221 }
222 for (p=argv[i+1]; *p; p++)
223 {
224 switch (*p) {
225 case 'a':
226 warning_msg |= MSG_LIST; break;
227 case 'b':
228 warning_msg |= MSG_SETnREF; break;
229 case 'c':
230 warning_msg |= MSG_REFnSET; break;
231 case 'd':
232 warning_msg |= MSG_GLOBinFUNC; break;
233 case 'e':
234 warning_msg |= MSG_GLOBoinFUNC; break;
235 case 'f':
236 warning_msg |= MSG_VARDECLARE; break;
237 case 'g':
238 warning_msg |= MSG_ASGNasTRUTH; break;
239 }
240 }
241 break;
242
243 case 'i': /* include file */
244 if (!incf_allc)
245 {
246 incf_allc = 8;
247 incfile = (char **) malloc( incf_allc * sizeof(char *) );
248 }
249 else if (incf_used == incf_allc)
250 {
251 incf_allc *= 2;
252 incfile = (char **) realloc( incfile, incf_allc * sizeof(char *) );
253 }
254
255 incfile[incf_used] = (char *) malloc( strlen(argv[++i])+1 );
256 strcpy(incfile[incf_used++], argv[i]);
257 break;
258
259 case 'I': /* include directory */
260 if (!incd_allc)
261 {
262 incd_allc = 8;
263 incdir = (char **) malloc( incd_allc * sizeof(char *) );
264 }
265 else if (incd_used == incd_allc)
266 {
267 incd_allc *= 2;
268 incdir = (char **) realloc( incdir, incd_allc * sizeof(char *) );
269 }
270
271 incdir[incd_used] = (char *) malloc( strlen(argv[++i])+1 );
272 strcpy(incdir[incd_used++], argv[i]);
273 break;
274
275 case 'l': /* library */
276 if (!libf_allc)
277 {
278 libf_allc = 8;
279 libfile = (char **) malloc( libf_allc * sizeof(char *) );
280 }
281 else if (libf_used == libf_allc)
282 {
283 libf_allc *= 2;
284 libfile = (char **) realloc( libfile, libf_allc * sizeof(char *) );
285 }
286
287 libfile[libf_used] = (char *) malloc( strlen(argv[++i])+1 );
288 strcpy(libfile[libf_used++], argv[i]);
289 break;
290
291 case 'L': /* library directory */
292 if (!libd_allc)
293 {
294 libd_allc = 8;
295 libdir = (char **) malloc( libd_allc * sizeof(char *) );
296 }
297 else if (libd_used == libd_allc)
298 {
299 libd_allc *= 2;
300 libdir = (char **) realloc( libdir, libd_allc * sizeof(char *) );
301 }
302
303 libdir[libd_used] = (char *) malloc( strlen(argv[++i])+1 );
304 strcpy(libdir[libd_used++], argv[i]);
305 break;
306
307 case 'X':
308 awka_comp = TRUE;
309 awka_exe = FALSE;
310 awka_main = FALSE;
311 break;
312
313 case 'x':
314 awka_exe = TRUE;
315 awka_comp = FALSE;
316 awka_main = FALSE;
317 break;
318
319 case 't':
320 awka_tmp = TRUE;
321 break;
322
323 case 'D':
324 dump = TRUE;
325 break;
326
327 case 'a':
328 if (++i >= argc)
329 {
330 fprintf(stderr,"Command Line Error: Expecting filename after -a argument.\n");
331 exit(1);
332 }
333 int_argv = (char *) malloc(strlen(argv[i])+1);
334 strcpy(int_argv, argv[i]);
335 break;
336
337 case 'o':
338 if (++i >= argc)
339 {
340 fprintf(stderr,"Command Line Error: Expecting filename after -o argument.\n");
341 exit(1);
342 }
343 uoutfile = (char *) malloc(strlen(argv[i])+1);
344 strcpy(uoutfile, argv[i]);
345 break;
346
347 case 'u':
348 case 'h':
349 fprintf(stderr,"\nusage: awka [-c fn] [-X] [-x -t] [-w flags] [-f filename] program_string [--] [exe-args]\n");
350 fprintf(stderr," awka [-h] [-v]\n\n");
351 fprintf(stderr," -c fn Awka will generate a 'fn' function rather\n");
352 fprintf(stderr," than a main function\n");
353 fprintf(stderr," -x Translates, compiles then executes program\n");
354 fprintf(stderr," -t If -x specified, the temporary C and executable\n");
355 fprintf(stderr," files will be deleted following execution.\n");
356 fprintf(stderr," Without this argument, -x will produce awka_out.c\n");
357 #ifdef __CYGWIN32__
358 fprintf(stderr," and awka_out.exe in the current directory.\n");
359 #else
360 fprintf(stderr," and awka.out in the current directory.\n");
361 #endif
362 fprintf(stderr," -X This will create the C file awka_out.c and compile\n");
363 #ifdef __CYGWIN32__
364 fprintf(stderr," an executable 'awka_out.exe'. Awka will stop after\n");
365 #else
366 fprintf(stderr," an executable 'awka.out'. Awka will stop after\n");
367 #endif
368 fprintf(stderr," the compile is complete.\n");
369 fprintf(stderr," -o fil If -x used, this will create an executable called 'fil'\n");
370 #ifdef __CYGWIN32__
371 fprintf(stderr," instead of the default 'awka_out.exe'\n");
372 #else
373 fprintf(stderr," instead of the default 'awka.out'\n");
374 #endif
375 fprintf(stderr," -f AWK Program file(s)\n");
376 fprintf(stderr," -- If -x specified, all arguments after this point\n");
377 fprintf(stderr," will be passed to the compiled executable.\n");
378 fprintf(stderr," -a str The executable command-line arguments in 'str' will\n");
379 fprintf(stderr," be hard-coded in the translated C output.\n");
380 fprintf(stderr," -w flg Prints various warnings to stderr, useful in debugging\n");
381 fprintf(stderr," large, complex programs. The argument can contain the\n");
382 fprintf(stderr," following characters:-\n");
383 fprintf(stderr," 'a' print a list of all global variables & their usage\n");
384 fprintf(stderr," 'b' warn about variables set but not referenced.\n");
385 fprintf(stderr," 'c' warn about variables referenced but not set.\n");
386 fprintf(stderr," 'd' report global vars used in any function.\n");
387 fprintf(stderr," 'e' report global vars used in just one function.\n");
388 fprintf(stderr," 'f' require global variables to be listed in a VDECL comment\n");
389 fprintf(stderr," 'g' warn about assignments used as truth expressions\n");
390 fprintf(stderr," -v Prints version information\n\n");
391 exit(0);
392
393 default:
394 bad_option(argv[i]) ;
395 }
396 }
397
398 no_more_opts:
399
400 tail->link = (PFILE *) 0 ;
401 pfile_list = dummy.link ;
402
403 if (pfile_name)
404 scan_init((char *) 0) ;
405 else /* program on command line */
406 {
407 if (i == argc) no_program() ;
408 scan_init(argv[i]) ;
409 /* #endif */
410 }
411 i++;
412
413 exe_opts:
414 /* if (i < argc-1 && !strcmp(argv[i+1], "--")) */
415 if (i < argc-1 && !strcmp(argv[i], "--"))
416 {
417 /* i += 2; */
418 i++;
419 exe_argc = argc - i;
420 exe_argv = (char **) malloc(exe_argc * sizeof(char *));
421 for (j=0; i<argc; i++, j++)
422 {
423 exe_argv[j] = (char *) malloc(strlen(argv[i])+1);
424 strcpy(exe_argv[j], argv[i]);
425 }
426 }
427 }
428
429