1 /*------------------------------------------------------------*
2 | init.c |
3 | copyright 1999, Andrew Sumner (andrewsumner@yahoo.com) |
4 | |
5 | This is a source file for the awka package, a translator |
6 | of the AWK programming language to ANSI C. |
7 | |
8 | This library is free software; you can redistribute it |
9 | and/or modify it under the terms of the GNU General |
10 | Public License (GPL). |
11 | |
12 | This library is distributed in the hope that it will be |
13 | useful, but WITHOUT ANY WARRANTY; without even the implied |
14 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
15 | PURPOSE. |
16 *------------------------------------------------------------*/
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #define _INIT_C
23
24 #define _IN_LIBRARY
25 #include "libawka.h"
26
27 extern void _awka_arrayinitargv( char **, int, char *argv[] );
28 extern void _awka_arrayinitenviron( char **, int );
29 extern char _a_char[256], _interactive;
30 extern struct gvar_struct *_gvar;
31 struct awka_fn_struct *_awkafn;
32 extern struct a_VAR **_lvar;
33
34 char **awka_filein = NULL;
35 int awka_filein_no = 0, _awka_fileoffset = 0;
36 char **_argv = NULL, **_int_argv = NULL;
37 int _argc, _int_argc = 0, _orig_argc = 0;
38 extern char _a_space[256];
39 char _env_used = 0;
40 char *patch_str, *date_str;
41
42 struct ivar_idx
43 {
44 char *name;
45 int var;
46 } ivar[] = {
47 "ARGC", a_ARGC,
48 "ARGIND", a_ARGIND,
49 "ARGV", a_ARGV,
50 "CONVFMT", a_CONVFMT,
51 "ENVIRON", a_ENVIRON,
52 "FIELDWIDTHS", a_FIELDWIDTHS,
53 "FILENAME", a_FILENAME,
54 "FNR", a_FNR,
55 "FS", a_FS,
56 "NF", a_NF,
57 "NR", a_NR,
58 "OFMT", a_OFMT,
59 "OFS", a_OFS,
60 "ORS", a_ORS,
61 "PROCINFO", a_PROCINFO,
62 "RLENGTH", a_RLENGTH,
63 "RS", a_RS,
64 "RSTART", a_RSTART,
65 "RT", a_RT,
66 "SAVEWIDTHS", a_SAVEWIDTHS,
67 "SORTTYPE", a_SORTTYPE,
68 "SUBSEP", a_SUBSEP
69 };
70
71 #define IVAR_MAX 20
72
73 int
findivar(char * c)74 findivar(char *c)
75 {
76 int i = IVAR_MAX / 2, hi = IVAR_MAX, lo = 0;
77 int x;
78
79 while (1)
80 {
81 if (!(x = strcmp(ivar[i].name, c)))
82 return i;
83 else if (x > 0)
84 {
85 if (i == lo)
86 return -1;
87 else if (i-1 == lo)
88 {
89 if (!strcmp(ivar[lo].name, c))
90 return lo;
91 return -1;
92 }
93 hi = i;
94 i = lo + ((hi - lo) / 2);
95 }
96 else
97 {
98 if (i == hi)
99 return -1;
100 else if (i+1 == hi)
101 {
102 if (!strcmp(ivar[hi].name, c))
103 return hi;
104 return -1;
105 }
106 lo = i;
107 i = lo + ((hi - lo) / 2);
108 }
109 }
110 }
111
112 void
awka_initgvar(int idx,char * name,a_VAR * var)113 awka_initgvar(int idx, char *name, a_VAR *var)
114 {
115 int i = strlen(name);
116 malloc( &_gvar[idx].name, i+1);
117 strncpy(_gvar[idx].name, name, i-4);
118 _gvar[idx].name[i-4] = 0;
119 _gvar[idx].var = var;
120 }
121
122 void
_awka_initstreams()123 _awka_initstreams()
124 {
125 int i;
126 _a_ioallc = 5;
127 malloc( &_a_iostream, 5 * sizeof(_a_IOSTREAM) );
128
129 for (i=0; i<5; i++)
130 {
131 _a_iostream[i].name = _a_iostream[i].buf = _a_iostream[i].end = _a_iostream[i].current = NULL;
132 _a_iostream[i].io = _a_IO_CLOSED;
133 _a_iostream[i].fp = NULL;
134 _a_iostream[i].alloc = _a_iostream[i].interactive = 0;
135 }
136
137 if (_interactive == TRUE)
138 {
139 setvbuf(stdin, NULL, _IONBF, 0);
140 setvbuf(stdout, NULL, _IONBF, 0);
141 }
142
143 malloc( &_a_iostream[0].name, 12 );
144 strcpy(_a_iostream[0].name, "/dev/stdout");
145 _a_iostream[0].fp = stdout;
146 fflush(_a_iostream[0].fp);
147
148 malloc( &_a_iostream[1].name, 12 );
149 strcpy(_a_iostream[1].name, "/dev/stderr");
150 _a_iostream[1].fp = stderr;
151 fflush(_a_iostream[1].fp);
152
153 _a_iostream[0].buf = _a_iostream[1].buf = NULL;
154 _a_iostream[0].alloc = _a_iostream[1].alloc = 0;
155 _a_iostream[0].current = _a_iostream[0].end = NULL;
156 _a_iostream[1].current = _a_iostream[1].end = NULL;
157 _a_iostream[0].io = _a_iostream[1].io = _a_IO_WRITE;
158 _a_iostream[0].pipe = _a_iostream[1].pipe = FALSE;
159 _a_ioused = 2;
160 }
161
162 static INLINE void
_awka_initchar()163 _awka_initchar()
164 {
165 register int i;
166
167 memset(_a_char, ' ', 256);
168 _a_char['\n'] = '\n';
169 _a_char['\t'] = '\t';
170 for (i=32; i<127; i++)
171 _a_char[i] = (char) i;
172
173 memset(_a_space, 0, 256);
174 _a_space['\n'] = 1;
175 _a_space['\t'] = 1;
176 _a_space['\f'] = 1;
177 _a_space['\r'] = 1;
178 _a_space['\013'] = 1;
179 _a_space[' '] = 1;
180 }
181
182 #ifdef PROCINFO_READY_TO_USE
183 void
_awka_init_procinfo(a_VAR * procinfo)184 _awka_init_procinfo( a_VAR *procinfo )
185 {
186 a_VAR *ret, *tmp = NULL;
187 awka_varinit(tmp);
188
189 /* egid */
190 /* euid */
191
192 /* FS */
193 awka_strcpy(tmp, "FS");
194 ret = awka_arraysearch1( procinfo, tmp, a_ARR_CREATE, 0 );
195 awka_strcpy(ret, "FS");
196 ret->type = a_VARUNK;
197
198 /* gid */
199 /* pgrpid */
200 /* pid */
201 /* ppid */
202 /* uid */
203 }
204 #endif
205
206 void
_awka_init_ivar(int i)207 _awka_init_ivar(int i)
208 {
209 if (a_bivar[i]) return;
210
211 malloc( &a_bivar[i], sizeof(a_VAR) );
212 a_bivar[i]->slen = 0;
213 a_bivar[i]->allc = 0;
214 a_bivar[i]->dval = 0;
215 a_bivar[i]->ptr = NULL;
216 a_bivar[i]->type2 = 0;
217 a_bivar[i]->temp = 0;
218 a_bivar[i]->type = a_VARNUL;
219
220 switch (i) {
221 case a_ARGV:
222 a_bivar[i]->type = a_VARARR;
223 awka_arraycreate(a_bivar[i], a_ARR_TYPE_SPLIT);
224 break;
225
226 case a_CONVFMT:
227 case a_OFMT:
228 a_bivar[i]->type = a_VARSTR;
229 a_bivar[i]->allc = malloc( &a_bivar[i]->ptr, 5 );
230 a_bivar[i]->slen = 4;
231 strcpy(a_bivar[i]->ptr, "%.6g");
232 break;
233
234 case a_ENVIRON:
235 a_bivar[i]->type = a_VARARR;
236 _awka_arrayinitenviron(&(a_bivar[i]->ptr), _env_used);
237 break;
238
239 case a_FILENAME:
240 case a_DOL0:
241 a_bivar[i]->type = a_VARUNK;
242 a_bivar[i]->allc = malloc( &a_bivar[i]->ptr, 1 );
243 a_bivar[i]->ptr[0] = '\0';
244 a_bivar[i]->slen = 0;
245 break;
246
247 case a_FS:
248 case a_OFS:
249 a_bivar[i]->type = a_VARSTR;
250 a_bivar[i]->allc = malloc( &a_bivar[i]->ptr, 5 );
251 a_bivar[i]->ptr[0] = ' ';
252 a_bivar[i]->ptr[1] = '\0';
253 a_bivar[i]->slen = 1;
254 break;
255
256 case a_ARGC:
257 case a_ARGIND:
258 case a_NF:
259 case a_FNR:
260 case a_NR:
261 case a_RLENGTH:
262 case a_RSTART:
263 a_bivar[i]->type = a_VARDBL;
264 break;
265
266 case a_FIELDWIDTHS:
267 case a_SAVEWIDTHS:
268 a_bivar[i]->type = a_VARSTR;
269 a_bivar[i]->allc = malloc( &a_bivar[i]->ptr, 1 );
270 a_bivar[i]->ptr[0] = '\0';
271 break;
272
273 case a_RT:
274 case a_RS:
275 case a_ORS:
276 a_bivar[i]->type = a_VARSTR;
277 a_bivar[i]->allc = malloc( &a_bivar[i]->ptr, 5 );
278 a_bivar[i]->ptr[0] = '\n';
279 a_bivar[i]->ptr[1] = '\0';
280 a_bivar[i]->slen = 1;
281 break;
282
283 case a_SUBSEP:
284 a_bivar[i]->type = a_VARSTR;
285 a_bivar[i]->allc = malloc( &a_bivar[i]->ptr, 5 );
286 a_bivar[i]->ptr[0] = '\034';
287 a_bivar[i]->ptr[1] = '\0';
288 a_bivar[i]->slen = 1;
289 break;
290
291 case a_DOLN:
292 a_bivar[i]->type = a_VARARR;
293 awka_arraycreate(a_bivar[i], a_ARR_TYPE_SPLIT);
294 break;
295
296 case a_PROCINFO:
297 a_bivar[i]->type = a_VARARR;
298 awka_arraycreate(a_bivar[i], a_ARR_TYPE_HSH);
299 /* _awka_init_procinfo( a_bivar[i] ); */
300 }
301 }
302
303 void
_awka_kill_ivar()304 _awka_kill_ivar()
305 {
306 int i;
307
308 for (i=0; i<a_BIVARS; i++)
309 {
310 if (!(a_bivar[i])) continue;
311
312 awka_killvar(a_bivar[i]);
313 free(a_bivar[i]);
314 a_bivar[i] = NULL;
315 }
316
317 if (awka_filein)
318 {
319 for (i=0; i<awka_filein_no; i++)
320 if (awka_filein[i])
321 free(awka_filein[i]);
322 free(awka_filein);
323 }
324 awka_filein = NULL;
325 awka_filein_no = 0;
326
327 if (_orig_argc)
328 {
329 for (i=0; i<_orig_argc; i++)
330 if (_argv[i])
331 free(_argv[i]);
332 free(_argv);
333 }
334 _argv = NULL;
335 _argc = 0;
336 }
337
338 void
_awka_kill_gvar()339 _awka_kill_gvar()
340 {
341 struct gvar_struct *gvar = _gvar;
342
343 if (_gvar)
344 {
345 while (gvar->name)
346 {
347 free(gvar->name);
348 awka_killvar(gvar->var);
349 gvar++;
350 }
351 free(_gvar);
352 _gvar = NULL;
353 }
354 }
355
356 void
_awka_kill_fn()357 _awka_kill_fn()
358 {
359 if (_awkafn)
360 free(_awkafn);
361 _awkafn = NULL;
362 }
363
364 void
awka_init(int argc,char * argv[],char * patch_string,char * date_string)365 awka_init(int argc, char *argv[], char *patch_string, char *date_string)
366 {
367 int i=0, j;
368 extern void _awka_gc_init();
369
370 patch_str = patch_string;
371 date_str = date_string;
372
373 _argc = argc + _int_argc;
374 _orig_argc = argc;
375 malloc( &_argv, argc * sizeof(char *) );
376
377 if (argc)
378 {
379 i++;
380 malloc( &_argv[0], strlen(argv[0])+1 );
381 strcpy(_argv[0], argv[0]);
382 }
383
384 for (j=0; j<_int_argc; j++)
385 {
386 malloc( &_argv[j+i], strlen(_int_argv[j])+1 );
387 strcpy(_argv[j+i], _int_argv[j]);
388 }
389
390 for (; i<argc; i++)
391 {
392 malloc( &_argv[i+j], strlen(argv[i])+1 );
393 strcpy(_argv[i+j], argv[i]);
394 }
395
396 _awka_gc_init();
397
398 for (i=0; i<a_BIVARS; i++) a_bivar[i] = NULL;
399 _awka_init_ivar(a_ARGC);
400 _awka_init_ivar(a_ARGV);
401
402 awka_parsecmdline(1);
403
404 /* set up internal variables */
405 for (i=0; i<a_BIVARS; i++)
406 if (i != a_ARGC && i != a_ARGV)
407 _awka_init_ivar(i);
408
409 /* set up output streams */
410 _awka_initstreams();
411 _awka_initchar();
412
413 #ifndef a_DUMP_ON_ERROR
414 /* handle signals */
415 awka_init_parachute();
416 #endif
417 }
418
419 void
_awka_printhelp()420 _awka_printhelp()
421 {
422 fprintf(stderr,"\nThis executable was generated from an AWK program using Awka.\n\n");
423 fprintf(stderr,"Command-line Options:\n\n");
424 fprintf(stderr," -We All following arguments will be added to the ARGV array.\n");
425 fprintf(stderr," -Wi Interactive mode. Input from stdin will be unbuffered.\n");
426 fprintf(stderr," -v var=value Sets variable 'var' to 'value'. 'var' must be a defined\n");
427 fprintf(stderr," variable else an error message will be printed.\n");
428 fprintf(stderr," -Fvalue Sets FS to value.\n");
429 fprintf(stderr," -showarg shows compiled-in arguments.\n");
430 fprintf(stderr," -awkaversion prints version of awka that generated this executable\n");
431 fprintf(stderr," -help prints this message.\n\n");
432 exit(1);
433 }
434
435 #define _setp \
436 if (_argv[i][2] == '\0') \
437 { \
438 i++; \
439 if (i >= _argc) \
440 awka_error("command line parse: expecting argument after %s.\n",_argv[i-1]); \
441 p = _argv[i]; \
442 } \
443 else \
444 p = _argv[i]+2
445
446 void
awka_parsecmdline(int first)447 awka_parsecmdline(int first)
448 {
449 int i = 1, j, argc, options_done = FALSE;
450 char c, *p, *p1, *p2, tmp[128];
451 a_VAR *var;
452
453 awka_getd(a_bivar[a_ARGC]);
454
455 if (!first)
456 {
457 for (i=1; i<_argc; i++)
458 if (_argv[i])
459 free(_argv[i]);
460
461 argc = _argc;
462 _argc = (int) awka_getd(a_bivar[a_ARGC]);
463
464 if (argc != _argc)
465 realloc( &_argv, _argc * sizeof(char *));
466
467 for (i=0; i<_argc; i++)
468 {
469 var = awka_arraysearch1(a_bivar[a_ARGV], awka_tmp_dbl2var(i), a_ARR_QUERY, 0);
470 if (var->slen != -1)
471 {
472 var = awka_arraysearch1(a_bivar[a_ARGV], awka_tmp_dbl2var(i), a_ARR_CREATE, 0);
473 p1 = awka_gets1(var);
474 malloc( &_argv[i], var->slen+1);
475 strcpy(_argv[i], p1);
476 }
477 else
478 {
479 _argv[i] = NULL;
480 }
481 }
482
483 if (awka_filein_no)
484 {
485 for (i=0; i<awka_filein_no; i++)
486 free(awka_filein[i]);
487 free(awka_filein);
488 awka_filein_no = 0;
489 }
490
491 a_bivar[a_ARGC]->dval = 0;
492 }
493 else
494 {
495 a_bivar[a_ARGC]->dval = 0;
496 awka_strcpy(awka_arraysearch1(a_bivar[a_ARGV], a_bivar[a_ARGC], a_ARR_CREATE, 1), _argv[0]);
497 }
498
499 i = 1;
500 while (i < _argc)
501 {
502 if (!_argv[i]) { i++; continue; }
503 c = _argv[i][0];
504
505 if (options_done == FALSE && c == '-' && _argv[i][1] != '\0')
506 {
507 switch (_argv[i][1])
508 {
509 case 'F':
510 _setp;
511 if (!first) break;
512 if (!a_bivar[a_FS])
513 _awka_init_ivar(a_FS);
514 awka_strcpy(a_bivar[a_FS], p);
515 break;
516
517 case '-':
518 switch (_argv[i][2])
519 {
520 case 'h':
521 case 'u':
522 _awka_printhelp();
523 default:
524 awka_error("command line parse: unknown option %s\n",_argv[i]);
525
526 case 'a':
527 break;
528 }
529 case 'a':
530 fprintf(stderr,"\n\"%s\" was generated by Awka (http://awka.sourceforge.net)\n",_argv[0]);
531 fprintf(stderr," - translator version %s, %s\n",patch_str,date_str);
532 fprintf(stderr," - library version %s, %s\n\n",AWKAVERSION,DATE_STRING);
533 exit(0);
534
535 case 'v':
536 _setp;
537 if (!first) break;
538 strcpy(tmp, p);
539 p1 = p2 = tmp;
540 while (*p2 && *p2 != '=') p2++;
541 if (*p2 == '=')
542 *p2++ = '\0';
543 else
544 awka_error("command line parse: expected 'var=value' after -v.\n");
545 if (p1 == p2-1)
546 awka_error("command line parse: null value for 'var' in 'var=value' after -v.\n");
547
548 j = 0;
549 while (_gvar[j].name)
550 {
551 if (!strcmp(_gvar[j].name, tmp))
552 break;
553 j++;
554 }
555 if (!_gvar[j].name)
556 {
557 if ((j = findivar(tmp)) == -1)
558 awka_error("command line parse: variable '%s' not defined.\n",tmp);
559 if (!a_bivar[ivar[j].var])
560 _awka_init_ivar(ivar[j].var);
561 if (a_bivar[ivar[j].var]->type == a_VARARR)
562 awka_error("command line parse: array variable '%s' used as scalar.\n",tmp);
563 awka_strcpy(a_bivar[ivar[j].var], p2);
564 a_bivar[ivar[j].var]->type = a_VARUNK;
565 break;
566 }
567 else if (_gvar[j].var->type == a_VARARR)
568 awka_error("command line parse: array variable '%s' used as scalar.\n",tmp);
569 awka_strcpy(_gvar[j].var, p2);
570 _gvar[j].var->type = a_VARUNK;
571 break;
572
573 case 'W':
574 _setp;
575 switch (*p)
576 {
577 case 'e':
578 options_done = TRUE;
579 break;
580
581 case 'i':
582 _interactive = TRUE;
583 break;
584
585 default:
586 awka_error("command line parse: unknown option -W%s\n",p);
587 }
588 break;
589
590 case 's':
591 if (_int_argc == 0)
592 fprintf(stderr,"No compiled-in arguments.\n");
593 else
594 {
595 fprintf(stderr,"The following arguments were compiled into this executable:-\n ");
596 for (j=0; j<_int_argc; j++)
597 fprintf(stderr," %s", _int_argv[j]);
598 fprintf(stderr,"\n");
599 }
600 exit(1);
601
602 case 'h':
603 _awka_printhelp();
604
605 default:
606 awka_error("command-line parse error: unknown argument '%s' - type \"-help\" for more info.\n",_argv[i]);
607 }
608 }
609 else if (_argv[i][0] != '\0')
610 {
611 a_bivar[a_ARGC]->dval++;
612 var = awka_arraysearch1(a_bivar[a_ARGV], a_bivar[a_ARGC], a_ARR_CREATE, 0);
613 awka_strcpy(var, _argv[i]);
614 var->type = a_VARUNK;
615 if (!awka_filein_no)
616 malloc( &awka_filein, (_argc + i) * sizeof(char *) );
617
618 malloc( &awka_filein[awka_filein_no], strlen(_argv[i])+1 );
619 strcpy(awka_filein[awka_filein_no++], _argv[i]);
620 if (!_awka_fileoffset) _awka_fileoffset = i;
621 }
622
623 i++;
624 }
625 a_bivar[a_ARGC]->dval++;
626
627 if (!awka_filein_no)
628 {
629 malloc( &awka_filein, sizeof(char *) );
630 malloc( &awka_filein[0], 3 );
631 strcpy(awka_filein[0], "-");
632 awka_filein_no = 1;
633 _awka_fileoffset = -1;
634 }
635 }
636
637