00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "awk.h"
00027 #include "getopt.h"
00028 #ifdef TANDEM
00029 #include "ptchlvl.h"
00030 #else
00031 #include "patchlev.h"
00032 #endif
00033
00034 #ifndef O_BINARY
00035 #include <fcntl.h>
00036 #endif
00037
00038 #ifdef HAVE_MCHECK_H
00039 #include <mcheck.h>
00040 #endif
00041
00042 #define DEFAULT_PROFILE "awkprof.out"
00043 #define DEFAULT_VARFILE "awkvars.out"
00044
00045 static const char *varfile = DEFAULT_VARFILE;
00046
00047 static void usage P((int exitval, FILE *fp)) ATTRIBUTE_NORETURN;
00048 static void copyleft P((void)) ATTRIBUTE_NORETURN;
00049 static void cmdline_fs P((char *str));
00050 static void init_args P((int argc0, int argc, char *argv0, char **argv));
00051 static void init_vars P((void));
00052 static void add_src P((struct src **data, long *num, long *alloc, enum srctype stype, char *val));
00053 static RETSIGTYPE catchsig P((int sig)) ATTRIBUTE_NORETURN;
00054 static void nostalgia P((void)) ATTRIBUTE_NORETURN;
00055 static void version P((void)) ATTRIBUTE_NORETURN;
00056 static void init_fds P((void));
00057 static void init_groupset P((void));
00058
00059
00060 NODE *ARGC_node, *ARGIND_node, *ARGV_node, *BINMODE_node, *CONVFMT_node;
00061 NODE *ENVIRON_node, *ERRNO_node, *FIELDWIDTHS_node, *FILENAME_node, *FNR_node;
00062 NODE *FS_node, *IGNORECASE_node, *NF_node, *NR_node, *OFMT_node, *OFS_node;
00063 NODE *ORS_node, *PROCINFO_node, *RLENGTH_node, *RSTART_node, *RS_node;
00064 NODE *RT_node, *SUBSEP_node, *LINT_node, *TEXTDOMAIN_node;
00065
00066 long NF;
00067 long NR;
00068 long FNR;
00069 int BINMODE;
00070 int IGNORECASE;
00071 char *OFS;
00072 char *ORS;
00073 char *OFMT;
00074 char *TEXTDOMAIN;
00075 int MRL;
00076
00077
00078
00079
00080
00081
00082
00083 char *CONVFMT = "%.6g";
00084
00085
00086 int errcount = 0;
00087
00088 NODE *Nnull_string;
00089
00090
00091 const char *myname;
00092
00093
00094 NODE *begin_block = NULL;
00095
00096
00097 NODE *end_block = NULL;
00098
00099 int exiting = FALSE;
00100 int exit_val = 0;
00101
00102 #if defined(YYDEBUG) || defined(GAWKDEBUG)
00103 extern int yydebug;
00104 #endif
00105
00106 struct src *srcfiles = NULL;
00107 long numfiles = -1;
00108 static long allocfiles;
00109
00110 #define srcfiles_add(stype, val) \
00111 add_src(&srcfiles, &numfiles, &allocfiles, stype, val)
00112
00113 static struct src *preassigns = NULL;
00114 static long numassigns = -1;
00115 static long allocassigns;
00116
00117 #define preassigns_add(stype, val) \
00118 add_src(&preassigns, &numassigns, &allocassigns, stype, val)
00119
00120 #undef do_lint
00121 #undef do_lint_old
00122
00123 int do_traditional = FALSE;
00124 int do_posix = FALSE;
00125 int do_lint = FALSE;
00126 int do_lint_old = FALSE;
00127 int do_intl = FALSE;
00128 int do_non_decimal_data = FALSE;
00129 int do_nostalgia = FALSE;
00130 int do_intervals = FALSE;
00131 int do_profiling = FALSE;
00132 int do_dump_vars = FALSE;
00133 int do_tidy_mem = FALSE;
00134
00135 int in_begin_rule = FALSE;
00136 int in_end_rule = FALSE;
00137 int whiny_users = FALSE;
00138 #ifdef MBS_SUPPORT
00139 int gawk_mb_cur_max = 1;
00140 #endif
00141
00142 int output_is_tty = FALSE;
00143
00144 extern const char *version_string;
00145
00146 #if defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0
00147 GETGROUPS_T *groupset;
00148 int ngroups;
00149 #endif
00150
00151
00152 NODE *expression_value;
00153
00154 #if _MSC_VER == 510
00155 void (*lintfunc) P((va_list va_alist, ...)) = warning;
00156 #else
00157 #if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__
00158 void (*lintfunc) P((const char *mesg, ...)) = warning;
00159 #else
00160 void (*lintfunc) () = warning;
00161 #endif
00162 #endif
00163
00164 static const struct option optab[] = {
00165 { "compat", no_argument, & do_traditional, 1 },
00166 { "traditional", no_argument, & do_traditional, 1 },
00167 { "lint", optional_argument, NULL, 'l' },
00168 { "lint-old", no_argument, & do_lint_old, 1 },
00169 { "posix", no_argument, & do_posix, 1 },
00170 { "nostalgia", no_argument, & do_nostalgia, 1 },
00171 { "gen-po", no_argument, & do_intl, 1 },
00172 { "non-decimal-data", no_argument, & do_non_decimal_data, 1 },
00173 { "profile", optional_argument, NULL, 'p' },
00174 { "copyleft", no_argument, NULL, 'C' },
00175 { "copyright", no_argument, NULL, 'C' },
00176 { "field-separator", required_argument, NULL, 'F' },
00177 { "file", required_argument, NULL, 'f' },
00178 { "re-interval", no_argument, & do_intervals, 1 },
00179 { "source", required_argument, NULL, 's' },
00180 { "dump-variables", optional_argument, NULL, 'd' },
00181 { "assign", required_argument, NULL, 'v' },
00182 { "version", no_argument, NULL, 'V' },
00183 { "usage", no_argument, NULL, 'u' },
00184 { "help", no_argument, NULL, 'u' },
00185 #ifdef GAWKDEBUG
00186 { "parsedebug", no_argument, NULL, 'D' },
00187 #endif
00188 { NULL, 0, NULL, '\0' }
00189 };
00190
00191 #ifdef NO_LINT
00192 #define do_lint 0
00193 #define do_lint_old 0
00194 #endif
00195
00196
00197
00198 int
00199 main(int argc, char **argv)
00200 {
00201 int c;
00202 char *scan;
00203
00204 const char *optlist = "+F:f:v:W;m:D";
00205 int stopped_early = FALSE;
00206 int old_optind;
00207 extern int optind;
00208 extern int opterr;
00209 extern char *optarg;
00210 int i;
00211
00212
00213 if (getenv("TIDYMEM") != NULL)
00214 do_tidy_mem = TRUE;
00215
00216 if (getenv("WHINY_USERS") != NULL)
00217 whiny_users = TRUE;
00218
00219 #ifdef HAVE_MCHECK_H
00220 if (do_tidy_mem)
00221 mtrace();
00222 #endif
00223
00224 #if defined(LC_CTYPE)
00225 setlocale(LC_CTYPE, "");
00226 #endif
00227 #if defined(LC_COLLATE)
00228 setlocale(LC_COLLATE, "");
00229 #endif
00230 #if HAVE_LC_MESSAGES && defined(LC_MESSAGES)
00231 setlocale(LC_MESSAGES, "");
00232 #endif
00233 #if defined(LC_NUMERIC)
00234
00235
00236
00237
00238
00239
00240 setlocale(LC_NUMERIC, "C");
00241 #endif
00242 #if defined(LC_TIME)
00243 setlocale(LC_TIME, "");
00244 #endif
00245
00246 #ifdef MBS_SUPPORT
00247
00248
00249
00250
00251
00252 gawk_mb_cur_max = MB_CUR_MAX;
00253 #endif
00254
00255 bindtextdomain(PACKAGE, LOCALEDIR);
00256 textdomain(PACKAGE);
00257
00258 (void) signal(SIGFPE, catchsig);
00259 (void) signal(SIGSEGV, catchsig);
00260 #ifdef SIGBUS
00261 (void) signal(SIGBUS, catchsig);
00262 #endif
00263
00264 myname = gawk_name(argv[0]);
00265 argv[0] = (char *) myname;
00266 os_arg_fixup(&argc, &argv);
00267
00268
00269 if (strncmp(version_string, "@(#)", 4) == 0)
00270 version_string += 4;
00271
00272 if (argc < 2)
00273 usage(1, stderr);
00274
00275
00276 init_fds();
00277
00278
00279 array_init();
00280
00281
00282 opterr = FALSE;
00283
00284
00285 for (optopt = 0, old_optind = 1;
00286 (c = getopt_long(argc, argv, optlist, optab, NULL)) != EOF;
00287 optopt = 0, old_optind = optind) {
00288 if (do_posix)
00289 opterr = TRUE;
00290
00291 switch (c) {
00292 case 'F':
00293 preassigns_add(PRE_ASSIGN_FS, optarg);
00294 break;
00295
00296 case 'f':
00297
00298
00299
00300
00301
00302
00303
00304
00305 scan = optarg;
00306 if (argv[optind-1] != optarg)
00307 while (ISSPACE(*scan))
00308 scan++;
00309 srcfiles_add(SOURCEFILE,
00310 (*scan == '\0' ? argv[optind++] : optarg));
00311 break;
00312
00313 case 'v':
00314 preassigns_add(PRE_ASSIGN, optarg);
00315 break;
00316
00317 case 'm':
00318
00319
00320
00321
00322
00323 if (do_lint)
00324 lintwarn(_("`-m[fr]' option irrelevant in gawk"));
00325 if (optarg[0] != 'r' && optarg[0] != 'f')
00326 warning(_("-m option usage: `-m[fr] nnn'"));
00327
00328
00329
00330
00331 if (optarg[0] == 'r') {
00332 if (ISDIGIT(optarg[1]))
00333 MRL = atoi(optarg+1);
00334 else {
00335 MRL = atoi(argv[optind]);
00336 optind++;
00337 }
00338 } else if (optarg[1] == '\0')
00339 optind++;
00340 break;
00341
00342 case 'W':
00343 fprintf(stderr, _("%s: option `-W %s' unrecognized, ignored\n"),
00344 argv[0], optarg);
00345 break;
00346
00347
00348 case 'C':
00349 copyleft();
00350 break;
00351
00352 case 'd':
00353 do_dump_vars = TRUE;
00354 if (optarg != NULL && optarg[0] != '\0')
00355 varfile = optarg;
00356 break;
00357
00358 case 'l':
00359 #ifndef NO_LINT
00360 do_lint = LINT_ALL;
00361 if (optarg != NULL) {
00362 if (strcmp(optarg, "fatal") == 0)
00363 lintfunc = r_fatal;
00364 else if (strcmp(optarg, "invalid") == 0)
00365 do_lint = LINT_INVALID;
00366 }
00367 #endif
00368 break;
00369
00370 case 'p':
00371 do_profiling = TRUE;
00372 if (optarg != NULL)
00373 set_prof_file(optarg);
00374 else
00375 set_prof_file(DEFAULT_PROFILE);
00376 break;
00377
00378 case 's':
00379 if (optarg[0] == '\0')
00380 warning(_("empty argument to `--source' ignored"));
00381 else
00382 srcfiles_add(CMDLINE, optarg);
00383 break;
00384
00385 case 'u':
00386 usage(0, stdout);
00387 break;
00388
00389 case 'V':
00390 version();
00391 break;
00392
00393 case 0:
00394
00395
00396
00397
00398
00399 break;
00400
00401 case 'D':
00402 #ifdef GAWKDEBUG
00403 yydebug = 2;
00404 break;
00405 #endif
00406
00407
00408 case '?':
00409 default:
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 if (! do_posix
00422 && (optopt == '\0' || strchr(optlist, optopt) == NULL)) {
00423
00424
00425
00426
00427
00428 optind = old_optind;
00429 stopped_early = TRUE;
00430 goto out;
00431 } else if (optopt != '\0')
00432
00433 fprintf(stderr,
00434 _("%s: option requires an argument -- %c\n"),
00435 myname, optopt);
00436
00437
00438 break;
00439 }
00440 }
00441 out:
00442
00443 if (do_nostalgia)
00444 nostalgia();
00445
00446
00447 if (! do_posix && getenv("POSIXLY_CORRECT") != NULL) {
00448 do_posix = TRUE;
00449 if (do_lint)
00450 lintwarn(
00451 _("environment variable `POSIXLY_CORRECT' set: turning on `--posix'"));
00452 }
00453
00454 if (do_posix) {
00455 if (do_traditional)
00456 warning(_("`--posix' overrides `--traditional'"));
00457 else
00458 do_traditional = TRUE;
00459
00460
00461
00462
00463 }
00464
00465 if (do_traditional && do_non_decimal_data) {
00466 do_non_decimal_data = FALSE;
00467 warning(_("`--posix'/`--traditional' overrides `--non-decimal-data'"));
00468 }
00469
00470 if (do_lint && os_is_setuid())
00471 warning(_("running %s setuid root may be a security problem"), myname);
00472
00473
00474
00475
00476
00477 if (! do_profiling)
00478 init_profiling(& do_profiling, DEFAULT_PROFILE);
00479
00480
00481 init_groupset();
00482
00483
00484 Nnull_string = make_string("", 0);
00485 Nnull_string->numbr = 0.0;
00486 Nnull_string->type = Node_val;
00487 Nnull_string->flags = (PERM|STRCUR|STRING|NUMCUR|NUMBER);
00488
00489
00490
00491
00492
00493
00494 resetup();
00495
00496
00497 init_vars();
00498
00499
00500 init_fields();
00501
00502
00503 for (i = 0; i <= numassigns; i++)
00504 if (preassigns[i].stype == PRE_ASSIGN)
00505 (void) arg_assign(preassigns[i].val, TRUE);
00506 else
00507 cmdline_fs(preassigns[i].val);
00508 free(preassigns);
00509
00510 if ((BINMODE & 1) != 0)
00511 if (os_setbinmode(fileno(stdin), O_BINARY) == -1)
00512 fatal(_("can't set binary mode on stdin (%s)"), strerror(errno));
00513 if ((BINMODE & 2) != 0) {
00514 if (os_setbinmode(fileno(stdout), O_BINARY) == -1)
00515 fatal(_("can't set binary mode on stdout (%s)"), strerror(errno));
00516 if (os_setbinmode(fileno(stderr), O_BINARY) == -1)
00517 fatal(_("can't set binary mode on stderr (%s)"), strerror(errno));
00518 }
00519
00520 #ifdef GAWKDEBUG
00521 setbuf(stdout, (char *) NULL);
00522 #endif
00523 if (isatty(fileno(stdout)))
00524 output_is_tty = TRUE;
00525
00526 if (numfiles == -1) {
00527 if (optind > argc - 1 || stopped_early)
00528 usage(1, stderr);
00529 srcfiles_add(CMDLINE, argv[optind]);
00530 optind++;
00531 }
00532
00533 init_args(optind, argc, (char *) myname, argv);
00534 (void) tokexpand();
00535
00536
00537 if (yyparse() != 0 || errcount != 0)
00538 exit(1);
00539
00540 free(srcfiles);
00541
00542 if (do_intl)
00543 exit(0);
00544
00545 if (do_lint && begin_block == NULL && expression_value == NULL
00546 && end_block == NULL)
00547 lintwarn(_("no program text at all!"));
00548
00549 if (do_lint)
00550 shadow_funcs();
00551
00552 init_profiling_signals();
00553
00554 #if defined(LC_NUMERIC)
00555
00556 setlocale(LC_NUMERIC, "");
00557 #endif
00558
00559
00560 if (begin_block != NULL) {
00561 in_begin_rule = TRUE;
00562 (void) interpret(begin_block);
00563 }
00564 in_begin_rule = FALSE;
00565 if (! exiting && (expression_value != NULL || end_block != NULL))
00566 do_input();
00567 if (end_block != NULL) {
00568 in_end_rule = TRUE;
00569 (void) interpret(end_block);
00570 }
00571 in_end_rule = FALSE;
00572 if (close_io() != 0 && exit_val == 0)
00573 exit_val = 1;
00574
00575 if (do_profiling) {
00576 dump_prog(begin_block, expression_value, end_block);
00577 dump_funcs();
00578 }
00579
00580 if (do_dump_vars)
00581 dump_vars(varfile);
00582
00583 if (do_tidy_mem)
00584 release_all_vars();
00585
00586 exit(exit_val);
00587 return exit_val;
00588 }
00589
00590
00591
00592 static void
00593 add_src(struct src **data, long *num, long *alloc, enum srctype stype, char *val)
00594 {
00595 #define INIT_SRC 4
00596
00597 ++*num;
00598
00599 if (*data == NULL) {
00600 emalloc(*data, struct src *, INIT_SRC * sizeof(struct src), "add_src");
00601 *alloc = INIT_SRC;
00602 } else if (*num >= *alloc) {
00603 (*alloc) *= 2;
00604 erealloc(*data, struct src *, (*alloc) * sizeof(struct src), "add_src");
00605 }
00606
00607 (*data)[*num].stype = stype;
00608 (*data)[*num].val = val;
00609
00610 #undef INIT_SRC
00611 }
00612
00613
00614
00615 static void
00616 usage(int exitval, FILE *fp)
00617 {
00618
00619
00620 fprintf(fp, _("Usage: %s [POSIX or GNU style options] -f progfile [--] file ...\n"),
00621 myname);
00622 fprintf(fp, _("Usage: %s [POSIX or GNU style options] [--] %cprogram%c file ...\n"),
00623 myname, quote, quote);
00624
00625
00626
00627 fputs(_("POSIX options:\t\tGNU long options:\n"), fp);
00628 fputs(_("\t-f progfile\t\t--file=progfile\n"), fp);
00629 fputs(_("\t-F fs\t\t\t--field-separator=fs\n"), fp);
00630 fputs(_("\t-v var=val\t\t--assign=var=val\n"), fp);
00631 fputs(_("\t-m[fr] val\n"), fp);
00632 fputs(_("\t-W compat\t\t--compat\n"), fp);
00633 fputs(_("\t-W copyleft\t\t--copyleft\n"), fp);
00634 fputs(_("\t-W copyright\t\t--copyright\n"), fp);
00635 fputs(_("\t-W dump-variables[=file]\t--dump-variables[=file]\n"), fp);
00636 fputs(_("\t-W gen-po\t\t--gen-po\n"), fp);
00637 fputs(_("\t-W help\t\t\t--help\n"), fp);
00638 fputs(_("\t-W lint[=fatal]\t\t--lint[=fatal]\n"), fp);
00639 fputs(_("\t-W lint-old\t\t--lint-old\n"), fp);
00640 fputs(_("\t-W non-decimal-data\t--non-decimal-data\n"), fp);
00641 #ifdef NOSTALGIA
00642 fputs(_("\t-W nostalgia\t\t--nostalgia\n"), fp);
00643 #endif
00644 #ifdef GAWKDEBUG
00645 fputs(_("\t-W parsedebug\t\t--parsedebug\n"), fp);
00646 #endif
00647 fputs(_("\t-W profile[=file]\t--profile[=file]\n"), fp);
00648 fputs(_("\t-W posix\t\t--posix\n"), fp);
00649 fputs(_("\t-W re-interval\t\t--re-interval\n"), fp);
00650 fputs(_("\t-W source=program-text\t--source=program-text\n"), fp);
00651 fputs(_("\t-W traditional\t\t--traditional\n"), fp);
00652 fputs(_("\t-W usage\t\t--usage\n"), fp);
00653 fputs(_("\t-W version\t\t--version\n"), fp);
00654
00655
00656
00657 fputs(_("\nTo report bugs, see node `Bugs' in `gawk.info', which is\n\
00658 section `Reporting Problems and Bugs' in the printed version.\n\n"), fp);
00659
00660
00661 fputs(_("gawk is a pattern scanning and processing language.\n\
00662 By default it reads standard input and writes standard output.\n\n"), fp);
00663
00664
00665 fputs(_("Examples:\n\tgawk '{ sum += $1 }; END { print sum }' file\n\
00666 \tgawk -F: '{ print $1 }' /etc/passwd\n"), fp);
00667
00668 fflush(fp);
00669
00670 if (ferror(fp))
00671 exit(1);
00672
00673 exit(exitval);
00674 }
00675
00676
00677
00678 static void
00679 copyleft()
00680 {
00681 static const char blurb_part1[] =
00682 N_("Copyright (C) 1989, 1991-%d Free Software Foundation.\n\
00683 \n\
00684 This program is free software; you can redistribute it and/or modify\n\
00685 it under the terms of the GNU General Public License as published by\n\
00686 the Free Software Foundation; either version 2 of the License, or\n\
00687 (at your option) any later version.\n\
00688 \n");
00689 static const char blurb_part2[] =
00690 N_("This program is distributed in the hope that it will be useful,\n\
00691 but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
00692 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
00693 GNU General Public License for more details.\n\
00694 \n");
00695 static const char blurb_part3[] =
00696 N_("You should have received a copy of the GNU General Public License\n\
00697 along with this program; if not, write to the Free Software\n\
00698 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n");
00699
00700
00701 printf(_(blurb_part1), 2003);
00702 fputs(_(blurb_part2), stdout);
00703 fputs(_(blurb_part3), stdout);
00704 fflush(stdout);
00705
00706 if (ferror(stdout))
00707 exit(1);
00708
00709 exit(0);
00710 }
00711
00712
00713
00714 static void
00715 cmdline_fs(char *str)
00716 {
00717 register NODE **tmp;
00718
00719 tmp = get_lhs(FS_node, (Func_ptr *) 0, FALSE);
00720 unref(*tmp);
00721
00722
00723
00724
00725
00726
00727
00728 if (str[0] == 't' && str[1] == '\0') {
00729 if (do_lint)
00730 lintwarn(_("-Ft does not set FS to tab in POSIX awk"));
00731 if (do_traditional && ! do_posix)
00732 str[0] = '\t';
00733 }
00734 *tmp = make_str_node(str, strlen(str), SCAN);
00735 set_FS();
00736 }
00737
00738
00739
00740 static void
00741 init_args(int argc0, int argc, char *argv0, char **argv)
00742 {
00743 int i, j;
00744 NODE **aptr;
00745
00746 ARGV_node = install("ARGV", node((NODE *) NULL, Node_var_array, (NODE *) NULL));
00747 aptr = assoc_lookup(ARGV_node, tmp_number(0.0), FALSE);
00748 *aptr = make_string(argv0, strlen(argv0));
00749 (*aptr)->flags |= MAYBE_NUM;
00750 for (i = argc0, j = 1; i < argc; i++) {
00751 aptr = assoc_lookup(ARGV_node, tmp_number((AWKNUM) j), FALSE);
00752 *aptr = make_string(argv[i], strlen(argv[i]));
00753 (*aptr)->flags |= MAYBE_NUM;
00754 j++;
00755 }
00756 ARGC_node = install("ARGC",
00757 node(make_number((AWKNUM) j), Node_var, (NODE *) NULL));
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767 struct varinit {
00768 NODE **spec;
00769 const char *name;
00770 NODETYPE type;
00771 const char *strval;
00772 AWKNUM numval;
00773 Func_ptr assign;
00774 };
00775 static const struct varinit varinit[] = {
00776 {&CONVFMT_node, "CONVFMT", Node_CONVFMT, "%.6g", 0, set_CONVFMT },
00777 {&NF_node, "NF", Node_NF, NULL, -1, NULL },
00778 {&FIELDWIDTHS_node, "FIELDWIDTHS", Node_FIELDWIDTHS, "", 0, NULL },
00779 {&NR_node, "NR", Node_NR, NULL, 0, set_NR },
00780 {&FNR_node, "FNR", Node_FNR, NULL, 0, set_FNR },
00781 {&FS_node, "FS", Node_FS, " ", 0, NULL },
00782 {&RS_node, "RS", Node_RS, "\n", 0, set_RS },
00783 {&IGNORECASE_node, "IGNORECASE", Node_IGNORECASE, NULL, 0, NULL },
00784 {&FILENAME_node, "FILENAME", Node_var, "", 0, NULL },
00785 {&OFS_node, "OFS", Node_OFS, " ", 0, set_OFS },
00786 {&ORS_node, "ORS", Node_ORS, "\n", 0, set_ORS },
00787 {&OFMT_node, "OFMT", Node_OFMT, "%.6g", 0, set_OFMT },
00788 {&RLENGTH_node, "RLENGTH", Node_var, NULL, 0, NULL },
00789 {&RSTART_node, "RSTART", Node_var, NULL, 0, NULL },
00790 {&SUBSEP_node, "SUBSEP", Node_var, "\034", 0, NULL },
00791 {&ARGIND_node, "ARGIND", Node_var, NULL, 0, NULL },
00792 {&ERRNO_node, "ERRNO", Node_var, NULL, 0, NULL },
00793 {&RT_node, "RT", Node_var, "", 0, NULL },
00794 {&BINMODE_node, "BINMODE", Node_BINMODE, NULL, 0, NULL },
00795 {&LINT_node, "LINT", Node_LINT, NULL, 0, NULL },
00796 {&TEXTDOMAIN_node, "TEXTDOMAIN", Node_TEXTDOMAIN, "messages", 0, set_TEXTDOMAIN },
00797 {0, NULL, Node_illegal, NULL, 0, NULL },
00798 };
00799
00800
00801
00802 static void
00803 init_vars()
00804 {
00805 register const struct varinit *vp;
00806
00807 for (vp = varinit; vp->name; vp++) {
00808 *(vp->spec) = install((char *) vp->name,
00809 node(vp->strval == NULL ? make_number(vp->numval)
00810 : make_string((char *) vp->strval,
00811 strlen(vp->strval)),
00812 vp->type, (NODE *) NULL));
00813 if (vp->assign)
00814 (*(vp->assign))();
00815 }
00816 }
00817
00818
00819
00820 NODE *
00821 load_environ()
00822 {
00823 #if ! defined(TANDEM)
00824 #if ! (defined(MSDOS) && !defined(DJGPP)) && ! defined(OS2) && ! (defined(VMS) && defined(__DECC))
00825 extern char **environ;
00826 #endif
00827 register char *var, *val;
00828 NODE **aptr;
00829 register int i;
00830 #endif
00831
00832 ENVIRON_node = install("ENVIRON",
00833 node((NODE *) NULL, Node_var_array, (NODE *) NULL));
00834 #if ! defined(TANDEM)
00835 for (i = 0; environ[i] != NULL; i++) {
00836 static char nullstr[] = "";
00837
00838 var = environ[i];
00839 val = strchr(var, '=');
00840 if (val != NULL)
00841 *val++ = '\0';
00842 else
00843 val = nullstr;
00844 aptr = assoc_lookup(ENVIRON_node, tmp_string(var, strlen(var)),
00845 FALSE);
00846 *aptr = make_string(val, strlen(val));
00847 (*aptr)->flags |= MAYBE_NUM;
00848
00849
00850 if (val != nullstr)
00851 *--val = '=';
00852 }
00853
00854
00855
00856
00857 if (getenv("AWKPATH") == NULL) {
00858 aptr = assoc_lookup(ENVIRON_node, tmp_string("AWKPATH", 7), FALSE);
00859 *aptr = make_string(defpath, strlen(defpath));
00860 }
00861 #endif
00862 return ENVIRON_node;
00863 }
00864
00865
00866
00867 NODE *
00868 load_procinfo()
00869 {
00870 int i;
00871 NODE **aptr;
00872 char name[100];
00873 AWKNUM value;
00874
00875 PROCINFO_node = install("PROCINFO",
00876 node((NODE *) NULL, Node_var_array, (NODE *) NULL));
00877
00878 #ifdef GETPGRP_VOID
00879 #define getpgrp_arg()
00880 #else
00881 #define getpgrp_arg() getpid()
00882 #endif
00883
00884 value = getpgrp(getpgrp_arg());
00885 aptr = assoc_lookup(PROCINFO_node, tmp_string("pgrpid", 6), FALSE);
00886 *aptr = make_number(value);
00887
00888
00889
00890
00891
00892
00893
00894 value = getpid();
00895 aptr = assoc_lookup(PROCINFO_node, tmp_string("pid", 3), FALSE);
00896 *aptr = make_number(value);
00897
00898 value = getppid();
00899 aptr = assoc_lookup(PROCINFO_node, tmp_string("ppid", 4), FALSE);
00900 *aptr = make_number(value);
00901
00902 value = getuid();
00903 aptr = assoc_lookup(PROCINFO_node, tmp_string("uid", 3), FALSE);
00904 *aptr = make_number(value);
00905
00906 value = geteuid();
00907 aptr = assoc_lookup(PROCINFO_node, tmp_string("euid", 4), FALSE);
00908 *aptr = make_number(value);
00909
00910 value = getgid();
00911 aptr = assoc_lookup(PROCINFO_node, tmp_string("gid", 3), FALSE);
00912 *aptr = make_number(value);
00913
00914 value = getegid();
00915 aptr = assoc_lookup(PROCINFO_node, tmp_string("egid", 4), FALSE);
00916 *aptr = make_number(value);
00917
00918 aptr = assoc_lookup(PROCINFO_node, tmp_string("FS", 2), FALSE);
00919 *aptr = (using_fieldwidths() ? make_string("FIELDWIDTHS", 11) :
00920 make_string("FS", 2) );
00921
00922 #if defined (HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0
00923 for (i = 0; i < ngroups; i++) {
00924 sprintf(name, "group%d", i + 1);
00925 value = groupset[i];
00926 aptr = assoc_lookup(PROCINFO_node, tmp_string(name, strlen(name)), FALSE);
00927 *aptr = make_number(value);
00928 }
00929 if (groupset) {
00930 free(groupset);
00931 groupset = NULL;
00932 }
00933 #endif
00934 return PROCINFO_node;
00935 }
00936
00937
00938
00939 int
00940 arg_assign(char *arg, int initing)
00941 {
00942 char *cp, *cp2;
00943 int badvar;
00944 Func_ptr after_assign = NULL;
00945 NODE *var;
00946 NODE *it;
00947 NODE **lhs;
00948
00949 cp = strchr(arg, '=');
00950
00951 if (cp == NULL) {
00952 if (! initing)
00953 return FALSE;
00954
00955 fprintf(stderr,
00956 _("%s: `%s' argument to `-v' not in `var=value' form\n\n"),
00957 myname, arg);
00958 usage(1, stderr);
00959 }
00960
00961 *cp++ = '\0';
00962
00963
00964 badvar = FALSE;
00965 if (! ISALPHA(arg[0]) && arg[0] != '_')
00966 badvar = TRUE;
00967 else
00968 for (cp2 = arg+1; *cp2; cp2++)
00969 if (! ISALNUM(*cp2) && *cp2 != '_') {
00970 badvar = TRUE;
00971 break;
00972 }
00973
00974 if (badvar) {
00975 if (initing)
00976 fatal(_("`%s' is not a legal variable name"), arg);
00977
00978 if (do_lint)
00979 lintwarn(_("`%s' is not a variable name, looking for file `%s=%s'"),
00980 arg, arg, cp);
00981 } else {
00982
00983
00984
00985
00986 it = make_str_node(cp, strlen(cp), SCAN);
00987 it->flags |= MAYBE_NUM;
00988 #ifdef LC_NUMERIC
00989 setlocale(LC_NUMERIC, "C");
00990 (void) force_number(it);
00991 setlocale(LC_NUMERIC, "");
00992 #endif
00993 var = variable(arg, FALSE, Node_var);
00994 lhs = get_lhs(var, &after_assign, FALSE);
00995 unref(*lhs);
00996 *lhs = it;
00997 if (after_assign != NULL)
00998 (*after_assign)();
00999 }
01000
01001 *--cp = '=';
01002
01003 return ! badvar;
01004 }
01005
01006
01007
01008 static RETSIGTYPE
01009 catchsig(int sig)
01010 {
01011 if (sig == SIGFPE) {
01012 fatal(_("floating point exception"));
01013 } else if (sig == SIGSEGV
01014 #ifdef SIGBUS
01015 || sig == SIGBUS
01016 #endif
01017 ) {
01018 set_loc(__FILE__, __LINE__);
01019 msg(_("fatal error: internal error"));
01020
01021 abort();
01022 } else
01023 cant_happen();
01024
01025 }
01026
01027
01028
01029 static void
01030 nostalgia()
01031 {
01032
01033
01034
01035
01036 fprintf(stderr, "awk: bailing out near line 1\n");
01037 fflush(stderr);
01038 abort();
01039 }
01040
01041
01042
01043 static void
01044 version()
01045 {
01046 printf("%s.%s\n", version_string, PATCHLEVEL);
01047
01048
01049
01050
01051 copyleft();
01052 exit(0);
01053 }
01054
01055
01056
01057 static void
01058 init_fds()
01059 {
01060 struct stat sbuf;
01061 int fd;
01062 int newfd;
01063
01064
01065 for (fd = 0; fd <= 2; fd++) {
01066 if (fstat(fd, &sbuf) < 0) {
01067 #if MAKE_A_HEROIC_EFFORT
01068 if (do_lint)
01069 lintwarn(_("no pre-opened fd %d"), fd);
01070 #endif
01071 newfd = devopen("/dev/null", "r+");
01072 #ifdef MAKE_A_HEROIC_EFFORT
01073 if (do_lint && newfd < 0)
01074 lintwarn(_("could not pre-open /dev/null for fd %d"), fd);
01075 #endif
01076 }
01077 }
01078 }
01079
01080
01081
01082 static void
01083 init_groupset()
01084 {
01085 #if defined(HAVE_GETGROUPS) && defined(NGROUPS_MAX) && NGROUPS_MAX > 0
01086 #ifdef GETGROUPS_NOT_STANDARD
01087
01088 ngroups = NGROUPS_MAX;
01089 #else
01090
01091
01092
01093
01094 ngroups = getgroups(0, NULL);
01095 #endif
01096 if (ngroups == -1)
01097 fatal(_("could not find groups: %s"), strerror(errno));
01098 else if (ngroups == 0)
01099 return;
01100
01101