2
* main.c -- Code generator and main program for gawk.
2
* main.c -- Code generator and main program for gawk.
6
* Copyright (C) 1986, 1988, 1989, 1991-2024,
7
* the Free Software Foundation, Inc.
6
* Copyright (C) 1986, 1988, 1989, 1991-2013 the Free Software Foundation, Inc.
9
8
* This file is part of GAWK, the GNU implementation of the
10
9
* AWK Programming Language.
12
11
* GAWK is free software; you can redistribute it and/or modify
13
12
* it under the terms of the GNU General Public License as published by
14
13
* the Free Software Foundation; either version 3 of the License, or
15
14
* (at your option) any later version.
17
16
* GAWK is distributed in the hope that it will be useful,
18
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
19
* GNU General Public License for more details.
22
21
* You should have received a copy of the GNU General Public License
23
22
* along with this program; if not, write to the Free Software
24
23
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27
26
/* FIX THIS BEFORE EVERY RELEASE: */
28
#define UPDATE_YEAR 2024
27
#define UPDATE_YEAR 2013
31
30
#include "getopt.h"
49
48
static void init_vars(void);
50
49
static NODE *load_environ(void);
51
50
static NODE *load_procinfo(void);
52
static void catchsig(int sig);
51
static RETSIGTYPE catchsig(int sig);
52
#ifdef HAVE_LIBSIGSEGV
53
static int catchsegv(void *fault_address, int serious);
54
static void catchstackoverflow(int emergency, stackoverflow_context_t scp);
56
static void nostalgia(void) ATTRIBUTE_NORETURN;
53
57
static void version(void) ATTRIBUTE_NORETURN;
54
58
static void init_fds(void);
55
59
static void init_groupset(void);
56
60
static void save_argv(int, char **);
57
static const char *platform_name();
58
static void check_pma_security(const char *pma_file);
62
extern int debug_prog(INSTRUCTION *pc); /* debug.c */
63
extern int init_debug(); /* debug.c */
60
65
/* These nodes store all the special variables AWK uses */
61
66
NODE *ARGC_node, *ARGIND_node, *ARGV_node, *BINMODE_node, *CONVFMT_node;
62
static NODE *ENVIRON_node;
63
NODE *ERRNO_node, *FIELDWIDTHS_node, *FILENAME_node;
67
NODE *ENVIRON_node, *ERRNO_node, *FIELDWIDTHS_node, *FILENAME_node;
64
68
NODE *FNR_node, *FPAT_node, *FS_node, *IGNORECASE_node, *LINT_node;
65
69
NODE *NF_node, *NR_node, *OFMT_node, *OFS_node, *ORS_node, *PROCINFO_node;
66
70
NODE *RLENGTH_node, *RSTART_node, *RS_node, *RT_node, *SUBSEP_node;
181
176
{ "lint", optional_argument, NULL, 'L' },
182
177
{ "lint-old", no_argument, NULL, 't' },
183
178
{ "load", required_argument, NULL, 'l' },
184
#if defined(LOCALEDEBUG)
185
{ "locale", required_argument, NULL, 'Z' },
187
179
{ "non-decimal-data", no_argument, NULL, 'n' },
188
{ "no-optimize", no_argument, NULL, 's' },
180
{ "nostalgia", no_argument, & do_nostalgia, 1 },
189
181
{ "optimize", no_argument, NULL, 'O' },
190
182
#if defined(YYDEBUG) || defined(GAWKDEBUG)
191
183
{ "parsedebug", no_argument, NULL, 'Y' },
193
{ "persist", optional_argument, NULL, 'T' },
194
185
{ "posix", no_argument, NULL, 'P' },
195
186
{ "pretty-print", optional_argument, NULL, 'o' },
196
187
{ "profile", optional_argument, NULL, 'p' },
197
188
{ "re-interval", no_argument, NULL, 'r' },
198
189
{ "sandbox", no_argument, NULL, 'S' },
199
190
{ "source", required_argument, NULL, 'e' },
200
{ "trace", no_argument, NULL, 'I' },
201
191
{ "traditional", no_argument, NULL, 'c' },
202
192
{ "use-lc-numeric", no_argument, & use_lc_numeric, 1 },
203
193
{ "version", no_argument, & do_version, 'V' },
246
219
#ifdef HAVE_MCHECK_H
247
220
#ifdef HAVE_MTRACE
248
if (! using_persistent_malloc && do_tidy_mem)
250
223
#endif /* HAVE_MTRACE */
251
224
#endif /* HAVE_MCHECK_H */
253
os_arg_fixup(&argc, &argv); /* emulate redirection, expand wildcards */
256
usage(EXIT_FAILURE, stderr);
258
if ((cp = getenv("GAWK_LOCALE_DIR")) != NULL)
261
#if defined(F_GETFL) && defined(O_APPEND)
262
// 1/2018: This is needed on modern BSD systems so that the
263
// inplace tests pass. I think it's a bug in those kernels
264
// but let's just work around it anyway.
265
int flags = fcntl(fileno(stderr), F_GETFL, NULL);
266
if (flags >= 0 && (flags & O_APPEND) == 0) {
268
(void) fcntl(fileno(stderr), F_SETFL, flags);
272
#if defined(LOCALEDEBUG)
273
initial_locale = locale;
277
(void) signal(SIGSEGV, catchsig);
226
#if defined(LC_CTYPE)
227
setlocale(LC_CTYPE, "");
229
#if defined(LC_COLLATE)
230
setlocale(LC_COLLATE, "");
232
#if defined(LC_MESSAGES)
233
setlocale(LC_MESSAGES, "");
235
#if defined(LC_NUMERIC) && defined(HAVE_LOCALE_H)
237
* Force the issue here. According to POSIX 2001, decimal
238
* point is used for parsing source code and for command-line
239
* assignments and the locale value for processing input,
240
* number to string conversion, and printing output.
242
* 10/2005 --- see below also; we now only use the locale's
243
* decimal point if do_posix in effect.
246
* This is a mess. We need to get the locale's numeric info for
247
* the thousands separator for the %'d flag.
249
setlocale(LC_NUMERIC, "");
251
setlocale(LC_NUMERIC, "C");
254
setlocale(LC_TIME, "");
259
* In glibc, MB_CUR_MAX is actually a function. This value is
260
* tested *a lot* in many speed-critical places in gawk. Caching
261
* this value once makes a speed difference.
263
gawk_mb_cur_max = MB_CUR_MAX;
264
/* Without MBS_SUPPORT, gawk_mb_cur_max is 1. */
265
#ifdef LIBC_IS_BORKED
269
env_lc = getenv("LC_ALL");
271
env_lc = getenv("LANG");
272
if (env_lc != NULL && env_lc[1] == '\0' && tolower(env_lc[0]) == 'c')
277
/* init the cache for checking bytes if they're characters */
281
(void) bindtextdomain(PACKAGE, LOCALEDIR);
282
(void) textdomain(PACKAGE);
278
284
(void) signal(SIGFPE, catchsig);
280
286
(void) signal(SIGBUS, catchsig);
284
290
* Ignore SIGPIPE so that writes to pipes that fail don't
285
291
* kill the process but instead return -1 and set errno.
310
329
output_fp = stdout;
331
/* we do error messages ourselves on invalid options */
334
/* copy argv before getopt gets to it; used to restart the debugger */
335
save_argv(argc, argv);
312
337
/* initialize global (main) execution context */
313
338
push_context(new_context());
315
parse_args(argc, argv);
317
#if defined(LOCALEDEBUG)
318
if (locale != initial_locale)
323
* In glibc, MB_CUR_MAX is actually a function. This value is
324
* tested *a lot* in many speed-critical places in gawk. Caching
325
* this value once makes a speed difference.
327
gawk_mb_cur_max = MB_CUR_MAX;
329
/* init the cache for checking bytes if they're characters */
332
/* set up the single byte case table */
333
if (gawk_mb_cur_max == 1)
340
/* option processing. ready, set, go! */
341
for (optopt = 0, old_optind = 1;
342
(c = getopt_long(argc, argv, optlist, optab, NULL)) != EOF;
343
optopt = 0, old_optind = optind) {
349
add_preassign(PRE_ASSIGN_FS, optarg);
353
disallow_var_assigns = true;
357
* Allow multiple -f options.
358
* This makes function libraries real easy.
359
* Most of the magic is in the scanner.
361
* The following is to allow for whitespace at the end
362
* of a #! /bin/gawk line in an executable file
365
if (argv[optind-1] != optarg)
366
while (isspace((unsigned char) *scan))
368
src = (*scan == '\0' ? argv[optind++] : optarg);
369
(void) add_srcfile((src && src[0] == '-' && src[1] == '\0') ?
370
SRC_STDIN : SRC_FILE,
371
src, srcfiles, NULL, NULL);
376
add_preassign(PRE_ASSIGN, optarg);
384
do_flags |= DO_TRADITIONAL;
392
do_flags |= DO_DUMP_VARS;
393
if (optarg != NULL && optarg[0] != '\0')
398
do_flags |= DO_DEBUG;
399
if (optarg != NULL && optarg[0] != '\0')
400
command_file = optarg;
404
if (optarg[0] == '\0')
405
warning(_("empty argument to `-e/--source' ignored"));
407
(void) add_srcfile(SRC_CMDLINE, optarg, srcfiles, NULL, NULL);
415
/* write usage to stdout, per GNU coding stds */
416
usage(EXIT_SUCCESS, stdout);
420
(void) add_srcfile(SRC_INC, optarg, srcfiles, NULL, NULL);
424
(void) add_srcfile(SRC_EXTLIB, optarg, srcfiles, NULL, NULL);
429
do_flags |= DO_LINT_ALL;
430
if (optarg != NULL) {
431
if (strcmp(optarg, "fatal") == 0)
433
else if (strcmp(optarg, "invalid") == 0) {
434
do_flags &= ~DO_LINT_ALL;
435
do_flags |= DO_LINT_INVALID;
441
do_flags |= DO_LINT_OLD;
450
do_flags |= DO_NON_DEC_DATA;
454
use_lc_numeric = true;
462
do_flags |= DO_PROFILE;
465
do_flags |= DO_PRETTY_PRINT;
467
set_prof_file(optarg);
469
set_prof_file(DEFAULT_PROFILE);
479
do_flags |= DO_POSIX;
483
do_flags |= DO_INTERVALS;
487
do_flags |= DO_SANDBOX;
494
case 'W': /* gawk specific options - now in getopt_long */
495
fprintf(stderr, _("%s: option `-W %s' unrecognized, ignored\n"),
501
* getopt_long found an option that sets a variable
502
* instead of returning a letter. Do nothing, just
503
* cycle around for the next one.
508
#if defined(YYDEBUG) || defined(GAWKDEBUG)
514
/* if not debugging, fall through */
518
* If not posix, an unrecognized option stops argument
519
* processing so that it can go into ARGV for the awk
520
* program to see. This makes use of ``#! /bin/gawk -f''
523
* However, it's never simple. If optopt is set,
524
* an option that requires an argument didn't get the
525
* argument. We care because if opterr is 0, then
526
* getopt_long won't print the error message for us.
529
&& (optopt == '\0' || strchr(optlist, optopt) == NULL)) {
531
* can't just do optind--. In case of an
532
* option with >= 2 letters, getopt_long
533
* won't have incremented optind.
536
stopped_early = true;
538
} else if (optopt != '\0') {
539
/* Use POSIX required message format */
541
_("%s: option requires an argument -- %c\n"),
543
usage(EXIT_FAILURE, stderr);
546
let getopt print error message for us */
549
if (c == 'E') /* --exec ends option processing */
336
557
/* check for POSIXLY_CORRECT environment variable */
337
558
if (! do_posix && getenv("POSIXLY_CORRECT") != NULL) {
625
818
fputs(_("\t-g\t\t\t--gen-pot\n"), fp);
626
819
fputs(_("\t-h\t\t\t--help\n"), fp);
627
820
fputs(_("\t-i includefile\t\t--include=includefile\n"), fp);
628
fputs(_("\t-I\t\t\t--trace\n"), fp);
629
fputs(_("\t-k\t\t\t--csv\n"), fp);
630
821
fputs(_("\t-l library\t\t--load=library\n"), fp);
632
* TRANSLATORS: the "fatal", "invalid" and "no-ext" here are literal
633
* values, they should not be translated. Thanks.
635
fputs(_("\t-L[fatal|invalid|no-ext]\t--lint[=fatal|invalid|no-ext]\n"), fp);
822
fputs(_("\t-L [fatal]\t\t--lint[=fatal]\n"), fp);
823
fputs(_("\t-n\t\t\t--non-decimal-data\n"), fp);
636
824
fputs(_("\t-M\t\t\t--bignum\n"), fp);
637
825
fputs(_("\t-N\t\t\t--use-lc-numeric\n"), fp);
638
fputs(_("\t-n\t\t\t--non-decimal-data\n"), fp);
639
826
fputs(_("\t-o[file]\t\t--pretty-print[=file]\n"), fp);
640
827
fputs(_("\t-O\t\t\t--optimize\n"), fp);
641
828
fputs(_("\t-p[file]\t\t--profile[=file]\n"), fp);
642
829
fputs(_("\t-P\t\t\t--posix\n"), fp);
643
830
fputs(_("\t-r\t\t\t--re-interval\n"), fp);
644
fputs(_("\t-s\t\t\t--no-optimize\n"), fp);
645
831
fputs(_("\t-S\t\t\t--sandbox\n"), fp);
646
832
fputs(_("\t-t\t\t\t--lint-old\n"), fp);
647
833
fputs(_("\t-V\t\t\t--version\n"), fp);
649
fputs(_("\t-Y\t\t\t--parsedebug\n"), fp);
835
fputs(_("\t-W nostalgia\t\t--nostalgia\n"), fp);
652
fputs(_("\t-Z locale-name\t\t--locale=locale-name\n"), fp);
838
fputs(_("\t-Y\t\t--parsedebug\n"), fp);
655
841
/* This is one string to make things easier on translators. */
656
/* TRANSLATORS: --help output (end)
842
/* TRANSLATORS: --help output 5 (end)
843
TRANSLATORS: the placeholder indicates the bug-reporting address
844
for this application. Please add _another line_ with the
845
address for translation bugs.
658
fputs(_("\nTo report bugs, use the `gawkbug' program.\n\
659
For full instructions, see the node `Bugs' in `gawk.info'\n\
660
which is section `Reporting Problems and Bugs' in the\n\
661
printed version. This same information may be found at\n\
662
https://www.gnu.org/software/gawk/manual/html_node/Bugs.html.\n\
663
PLEASE do NOT try to report bugs by posting in comp.lang.awk,\n\
664
or by using a web forum such as Stack Overflow.\n\n"), fp);
666
// 5.2.60 is beta release on master, will become 5.3.0.
667
// 5.2.2a is beta release on stable, will become 5.2.3.
668
if (patchlevel >= 60 || isalpha((int) PACKAGE_VERSION[strlen(PACKAGE_VERSION)-1]))
674
fprintf(fp, _("Source code for gawk may be obtained from\n%s/gawk-%s.tar.gz\n\n"),
675
url, PACKAGE_VERSION);
847
fputs(_("\nTo report bugs, see node `Bugs' in `gawk.info', which is\n\
848
section `Reporting Problems and Bugs' in the printed version.\n\n"), fp);
678
851
fputs(_("gawk is a pattern scanning and processing language.\n\
679
852
By default it reads standard input and writes standard output.\n\n"), fp);
682
fprintf(fp, _("Examples:\n\t%s '{ sum += $1 }; END { print sum }' file\n\
683
\t%s -F: '{ print $1 }' /etc/passwd\n"), myname, myname);
855
fputs(_("Examples:\n\tgawk '{ sum += $1 }; END { print sum }' file\n\
856
\tgawk -F: '{ print $1 }' /etc/passwd\n"), fp);
687
860
if (ferror(fp)) {
688
os_maybe_set_errno();
690
861
/* don't warn about stdout/stderr if EPIPE, but do error exit */
695
warning(_("error writing standard output: %s"), strerror(errno));
696
else if (fp == stderr)
697
warning(_("error writing standard error: %s"), strerror(errno));
699
// some other problem than SIGPIPE
862
if (errno != EPIPE) {
864
warning(_("error writing standard output (%s)"), strerror(errno));
865
else if (fp == stderr)
866
warning(_("error writing standard error (%s)"), strerror(errno));
700
868
exit(EXIT_FAILURE);
777
943
init_args(int argc0, int argc, const char *argv0, char **argv)
781
NODE *shadow_node = NULL;
783
949
ARGV_node = install_symbol(estrdup("ARGV", 4), Node_var_array);
784
sub = make_number(0.0);
785
val = make_string(argv0, strlen(argv0));
786
val->flags |= USER_INPUT;
787
assoc_set(ARGV_node, sub, val);
790
shadow_node = make_array();
791
sub = make_string(argv0, strlen(argv0));
792
val = make_number(0.0);
793
assoc_set(shadow_node, sub, val);
950
tmp = make_number(0.0);
951
aptr = assoc_lookup(ARGV_node, tmp);
954
*aptr = make_string(argv0, strlen(argv0));
955
(*aptr)->flags |= MAYBE_NUM;
797
956
for (i = argc0, j = 1; i < argc; i++, j++) {
798
sub = make_number((AWKNUM) j);
799
val = make_string(argv[i], strlen(argv[i]));
800
val->flags |= USER_INPUT;
801
assoc_set(ARGV_node, sub, val);
804
sub = make_string(argv[i], strlen(argv[i]));
805
val = make_number(0.0);
806
assoc_set(shadow_node, sub, val);
957
tmp = make_number((AWKNUM) j);
958
aptr = assoc_lookup(ARGV_node, tmp);
961
*aptr = make_string(argv[i], strlen(argv[i]));
962
(*aptr)->flags |= MAYBE_NUM;
810
965
ARGC_node = install_symbol(estrdup("ARGC", 4), Node_var);
811
966
ARGC_node->var_value = make_number((AWKNUM) j);
814
init_argv_array(ARGV_node, shadow_node);
852
1004
{&FPAT_node, "FPAT", "[^[:space:]]+", 0, NULL, set_FPAT, false, NON_STANDARD },
853
1005
{&IGNORECASE_node, "IGNORECASE", NULL, 0, NULL, set_IGNORECASE, false, NON_STANDARD },
854
1006
{&LINT_node, "LINT", NULL, 0, NULL, set_LINT, false, NON_STANDARD },
855
{&PREC_node, "PREC", NULL, DEFAULT_PREC, NULL, set_PREC, false, NON_STANDARD},
1007
{&PREC_node, "PREC", NULL, DEFAULT_PREC, NULL, set_PREC, false, NON_STANDARD},
856
1008
{&NF_node, "NF", NULL, -1, update_NF, set_NF, false, 0 },
857
1009
{&NR_node, "NR", NULL, 0, update_NR, set_NR, true, 0 },
858
1010
{&OFMT_node, "OFMT", "%.6g", 0, NULL, set_OFMT, true, 0 },
1222
1335
lintwarn(_("`%s' is not a variable name, looking for file `%s=%s'"),
1228
// Assigning a string or typed regex
1230
if (! validate_qualified_name(arg)) {
1235
if (check_special(arg) >= 0)
1236
fatal(_("cannot use gawk builtin `%s' as variable name"), arg);
1240
if (var != NULL && var->type == Node_func)
1241
fatal(_("cannot use function `%s' as variable name"), arg);
1244
cp2 = cp + strlen(cp) - 1; // end char
1245
if (! do_traditional
1246
&& strlen(cp) >= 3 // '@/' doesn't do it.
1247
&& cp[0] == '@' && cp[1] == '/' && *cp2 == '/') {
1249
size_t len = strlen(cp) - 3;
1251
ezalloc(cp2, char *, len + 1, "arg_assign");
1252
memcpy(cp2, cp + 2, len);
1254
it = make_typed_regex(cp2, len);
1255
// fall through to variable setup
1257
// string assignment
1338
if (check_special(arg) >= 0)
1339
fatal(_("cannot use gawk builtin `%s' as variable name"), arg);
1259
// POSIX disallows any newlines inside strings
1260
// The scanner handles that for program files.
1261
// We have to check here for strings passed to -v.
1262
if (do_posix && strchr(cp, '\n') != NULL)
1263
fatal(_("POSIX does not allow physical newlines in string values"));
1343
if (var != NULL && var->type == Node_func)
1344
fatal(_("cannot use function `%s' as variable name"), arg);
1266
1348
* BWK awk expands escapes inside assignments.
1267
1349
* This makes sense, so we do it too.
1268
* In addition, remove \-<newline> as in scanning.
1270
1351
it = make_str_node(cp, strlen(cp), SCAN);
1271
it->flags |= USER_INPUT;
1352
it->flags |= MAYBE_NUM;
1272
1353
#ifdef LC_NUMERIC
1274
1355
* See comment above about locale decimal point.
1277
1358
setlocale(LC_NUMERIC, "C");
1278
#endif /* LC_NUMERIC */
1279
1359
(void) force_number(it);
1282
setlocale(LC_NUMERIC, locale);
1361
setlocale(LC_NUMERIC, "");
1283
1362
#endif /* LC_NUMERIC */
1365
* since we are restoring the original text of ARGV later,
1366
* need to copy the variable name part if we don't want
1367
* name like v=abc instead of just v in var->vname
1370
cp2 = estrdup(arg, cp - arg); /* var name */
1372
var = variable(0, cp2, Node_var);
1373
if (var == NULL) /* error */
1374
final_exit(EXIT_FATAL);
1375
if (var->type == Node_var && var->var_update)
1377
lhs = get_lhs(var, false);
1380
/* check for set_FOO() routine */
1381
if (var->type == Node_var && var->var_assign)
1287
* since we are restoring the original text of ARGV later,
1288
* need to copy the variable name part if we don't want
1289
* name like v=abc instead of just v in var->vname
1292
cp2 = estrdup(arg, cp - arg); /* var name */
1294
var = variable(0, cp2, Node_var);
1295
if (var == NULL) /* error */
1296
final_exit(EXIT_FATAL);
1298
if (var->type == Node_var && var->var_update)
1300
lhs = get_lhs(var, false);
1303
/* check for set_FOO() routine */
1304
if (var->type == Node_var && var->var_assign)
1309
1386
*--cp = '='; /* restore original text of ARGV */
1310
1387
FNR = save_FNR;
1323
1400
|| sig == SIGBUS
1326
if (errcount > 0) // assume a syntax error corrupted our data structures
1329
1403
set_loc(__FILE__, __LINE__);
1330
1404
msg(_("fatal error: internal error"));
1331
1405
/* fatal won't abort() if not compiled for debugging */
1332
// GLIBC 2.27 doesn't necessarily flush on abort. Sigh.
1336
cant_happen("unexpected signal, number %d (%s)", sig, strsignal(sig));
1337
1409
/* NOTREACHED */
1340
#ifdef USE_PERSISTENT_MALLOC
1341
/* get_pma_version --- get a usable version string out of PMA */
1344
get_pma_version(void)
1346
static char buf[200];
1347
const char *open, *close;
1412
#ifdef HAVE_LIBSIGSEGV
1413
/* catchsegv --- for use with libsigsegv */
1416
catchsegv(void *fault_address, int serious)
1418
set_loc(__FILE__, __LINE__);
1419
msg(_("fatal error: internal error: segfault"));
1425
/* catchstackoverflow --- for use with libsigsegv */
1428
catchstackoverflow(int emergency, stackoverflow_context_t scp)
1430
set_loc(__FILE__, __LINE__);
1431
msg(_("fatal error: internal error: stack overflow"));
1436
#endif /* HAVE_LIBSIGSEGV */
1438
/* nostalgia --- print the famous error message and die */
1352
* The default version string looks like this:
1353
* 2022.08Aug.03.1659520468 (Avon 7)
1354
* Yucko. Just pull out the bits between the parens.
1444
* N.B.: This string is not gettextized, on purpose.
1357
open = strchr(pma_version, '(');
1359
return pma_version; // sigh.
1362
close = strchr(open, ')');
1364
return pma_version; // sigh, again.
1366
// copy over the short name
1367
for (out = buf, in = open; in < close;)
1447
fprintf(stderr, "awk: bailing out near line 1\n");
1376
1452
/* version --- print version message */
1553
/* parse_args --- do the getopt_long thing */
1556
parse_args(int argc, char **argv)
1559
* The + on the front tells GNU getopt not to rearrange argv.
1561
const char *optlist = "+F:f:v:W;bcCd::D::e:E:ghi:kIl:L::nNo::Op::MPrSstVYZ:";
1567
/* we do error messages ourselves on invalid options */
1570
/* copy argv before getopt gets to it; used to restart the debugger */
1571
save_argv(argc, argv);
1573
/* option processing. ready, set, go! */
1574
for (optopt = 0, old_optind = 1;
1575
(c = getopt_long(argc, argv, optlist, optab, NULL)) != EOF;
1576
optopt = 0, old_optind = optind) {
1582
add_preassign(PRE_ASSIGN_FS, optarg);
1586
disallow_var_assigns = true;
1590
* Allow multiple -f options.
1591
* This makes function libraries real easy.
1592
* Most of the magic is in the scanner.
1594
* The following is to allow for whitespace at the end
1595
* of a #! /bin/gawk line in an executable file
1598
if (argv[optind-1] != optarg)
1599
while (isspace((unsigned char) *scan))
1601
src = (*scan == '\0' ? argv[optind++] : optarg);
1602
(void) add_srcfile((src && src[0] == '-' && src[1] == '\0') ?
1603
SRC_STDIN : SRC_FILE,
1604
src, srcfiles, NULL, NULL);
1609
add_preassign(PRE_ASSIGN, optarg);
1617
do_flags |= DO_TRADITIONAL;
1625
do_flags |= DO_DUMP_VARS;
1626
if (optarg != NULL && optarg[0] != '\0')
1631
do_flags |= DO_DEBUG;
1632
if (optarg != NULL && optarg[0] != '\0')
1633
command_file = optarg;
1637
if (optarg[0] == '\0')
1638
warning(_("empty argument to `-e/--source' ignored"));
1640
(void) add_srcfile(SRC_CMDLINE, optarg, srcfiles, NULL, NULL);
1644
do_flags |= DO_INTL;
1648
/* write usage to stdout, per GNU coding stds */
1649
usage(EXIT_SUCCESS, stdout);
1653
(void) add_srcfile(SRC_INC, optarg, srcfiles, NULL, NULL);
1660
case 'k': // k is for "comma". it's a stretch, I know
1665
(void) add_srcfile(SRC_EXTLIB, optarg, srcfiles, NULL, NULL);
1670
do_flags |= (DO_LINT_ALL|DO_LINT_EXTENSIONS);
1671
if (optarg != NULL) {
1672
if (strcmp(optarg, "fatal") == 0)
1674
else if (strcmp(optarg, "invalid") == 0) {
1675
do_flags &= ~DO_LINT_ALL;
1676
do_flags |= DO_LINT_INVALID;
1678
else if (strcmp(optarg, "no-ext") == 0) {
1679
do_flags &= ~DO_LINT_EXTENSIONS;
1685
do_flags |= DO_LINT_OLD;
1694
do_flags |= DO_NON_DEC_DATA;
1698
use_lc_numeric = true;
1706
if (do_pretty_print && ! do_profile)
1707
warning(_("`--profile' overrides `--pretty-print'"));
1708
do_flags |= DO_PROFILE;
1711
if (c == 'o' && do_profile)
1712
warning(_("`--profile' overrides `--pretty-print'"));
1713
do_flags |= DO_PRETTY_PRINT;
1715
set_prof_file(optarg);
1717
set_prof_file(DEFAULT_PROFILE);
1722
do_flags |= DO_MPFR;
1724
warning(_("-M ignored: MPFR/GMP support not compiled in"));
1729
do_flags |= DO_POSIX;
1733
// This no longer has any effect. It remains for the
1734
// lint check in main().
1735
do_flags |= DO_INTERVALS;
1739
do_optimize = false;
1743
do_flags |= DO_SANDBOX;
1746
case 'T': // --persist[=file]
1747
#ifdef USE_PERSISTENT_MALLOC
1749
optarg = "/some/file";
1750
fatal(_("Use `GAWK_PERSIST_FILE=%s gawk ...' instead of --persist."), optarg);
1752
warning(_("Persistent memory is not supported."));
1753
#endif /* USE_PERSISTENT_MALLOC */
1760
case 'W': /* gawk specific options - now in getopt_long */
1761
fprintf(stderr, _("%s: option `-W %s' unrecognized, ignored\n"),
1767
* getopt_long found an option that sets a variable
1768
* instead of returning a letter. Do nothing, just
1769
* cycle around for the next one.
1775
#if defined(YYDEBUG) || defined(GAWKDEBUG)
1781
#if defined(LOCALEDEBUG)
1787
/* if not debugging, fall through */
1791
* If not posix, an unrecognized option stops argument
1792
* processing so that it can go into ARGV for the awk
1793
* program to see. This makes use of ``#! /bin/gawk -f''
1796
* However, it's never simple. If optopt is set,
1797
* an option that requires an argument didn't get the
1798
* argument. We care because if opterr is 0, then
1799
* getopt_long won't print the error message for us.
1802
&& (optopt == '\0' || strchr(optlist, optopt) == NULL)) {
1804
* can't just do optind--. In case of an
1805
* option with >= 2 letters, getopt_long
1806
* won't have incremented optind.
1808
optind = old_optind;
1809
stopped_early = true;
1811
} else if (optopt != '\0') {
1812
/* Use POSIX required message format */
1814
_("%s: option requires an argument -- %c\n"),
1816
usage(EXIT_FAILURE, stderr);
1819
let getopt print error message for us */
1822
if (c == 'E') /* --exec ends option processing */
1826
do_optimize = (do_optimize && ! do_pretty_print);
1833
/* set_locale_stuff --- setup the locale stuff */
1836
set_locale_stuff(void)
1838
#if defined(LC_CTYPE)
1839
setlocale(LC_CTYPE, locale);
1841
#if defined(LC_COLLATE)
1842
setlocale(LC_COLLATE, locale);
1844
#if defined(LC_MESSAGES)
1845
setlocale(LC_MESSAGES, locale);
1847
#if defined(LC_NUMERIC) && defined(HAVE_LOCALE_H)
1849
* Force the issue here. According to POSIX 2001, decimal
1850
* point is used for parsing source code and for command-line
1851
* assignments and the locale value for processing input,
1852
* number to string conversion, and printing output.
1854
* 10/2005 --- see below also; we now only use the locale's
1855
* decimal point if do_posix in effect.
1858
* This is a mess. We need to get the locale's numeric info for
1859
* the thousands separator for the %'d flag.
1861
setlocale(LC_NUMERIC, locale);
1863
setlocale(LC_NUMERIC, "C");
1865
#if defined(LC_TIME)
1866
setlocale(LC_TIME, locale);
1869
/* These must be done after calling setlocale */
1870
(void) bindtextdomain(PACKAGE, locale_dir);
1871
(void) textdomain(PACKAGE);
1874
/* platform_name --- return the platform name */
1879
// Cygwin and Mac OS X count as POSIX
1882
#elif defined(__MINGW32__)
1884
#elif defined(USE_EBCDIC)
1891
/* set_current_namespace --- set current_namespace and handle memory management */
1894
set_current_namespace(const char *new_namespace)
1896
if (current_namespace != awk_namespace)
1897
efree((void *) current_namespace);
1899
current_namespace = new_namespace;
1902
/* check_pma_security --- make some minimal security checks */
1905
check_pma_security(const char *pma_file)
1907
#ifdef USE_PERSISTENT_MALLOC
1909
int euid = geteuid();
1911
// don't use 'fatal' routine, it seems to need to allocate memory
1912
// and we haven't initialized PMA yet.
1914
if (pma_file == NULL)
1916
else if (stat(pma_file, & sbuf) < 0) {
1917
fprintf(stderr, _("%s: fatal: cannot stat %s: %s\n"),
1918
myname, pma_file, strerror(errno));
1920
} else if (euid == 0) {
1921
fprintf(stderr, _("%s: fatal: using persistent memory is not allowed when running as root.\n"), myname);
1923
} else if (sbuf.st_uid != euid) {
1924
fprintf(stderr, _("%s: warning: %s is not owned by euid %d.\n"),
1925
myname, pma_file, euid);
1927
#endif /* USE_PERSISTENT_MALLOC */