aboutsummaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c212
1 files changed, 114 insertions, 98 deletions
diff --git a/main.c b/main.c
index 3680e3f4..98f8739f 100644
--- a/main.c
+++ b/main.c
@@ -58,6 +58,9 @@ static void init_groupset(void);
static void save_argv(int, char **);
+extern int debug_prog(INSTRUCTION *pc); /* debug.c */
+
+
/* These nodes store all the special variables AWK uses */
NODE *ARGC_node, *ARGIND_node, *ARGV_node, *BINMODE_node, *CONVFMT_node;
NODE *ENVIRON_node, *ERRNO_node, *FIELDWIDTHS_node, *FILENAME_node;
@@ -129,30 +132,18 @@ static int disallow_var_assigns = FALSE; /* true for --exec */
static void add_preassign(enum assign_type type, char *val);
-#undef do_lint
-#undef do_lint_old
-
-int do_traditional = FALSE; /* no gnu extensions, add traditional weirdnesses */
-int do_posix = FALSE; /* turn off gnu and unix extensions */
-int do_lint = FALSE; /* provide warnings about questionable stuff */
-int do_lint_old = FALSE; /* warn about stuff not in V7 awk */
-int do_intl = FALSE; /* dump locale-izable strings to stdout */
-int do_non_decimal_data = FALSE; /* allow octal/hex C style DATA. Use with caution! */
-int do_nostalgia = FALSE; /* provide a blast from the past */
-int do_intervals = FALSE; /* allow {...,...} in regexps, see resetup() */
-int do_profiling = FALSE; /* profile and pretty print the program */
-int do_dump_vars = FALSE; /* dump all global variables at end */
-int do_tidy_mem = FALSE; /* release vars when done */
-int do_optimize = TRUE; /* apply default optimizations */
-int do_binary = FALSE; /* hands off my data! */
-int do_sandbox = FALSE; /* sandbox mode - disable 'system' function & redirections */
+int do_flags = FALSE;
+int do_optimize = TRUE; /* apply default optimizations */
+static int do_nostalgia = FALSE; /* provide a blast from the past */
+static int do_binary = FALSE; /* hands off my data! */
+
int use_lc_numeric = FALSE; /* obey locale for decimal point */
#if MBS_SUPPORT
int gawk_mb_cur_max; /* MB_CUR_MAX value, see comment in main() */
#endif
-FILE *output_fp; /* default output for debugger */
+FILE *output_fp; /* default gawk output, can be redirected in the debugger */
int output_is_tty = FALSE; /* control flushing of output */
/* default format for strftime(), available via PROCINFO */
@@ -167,26 +158,24 @@ int ngroups; /* size of said set */
void (*lintfunc)(const char *mesg, ...) = warning;
-/*
- * Note: reserve -D for future use, to merge dgawk into gawk.
- * Note: reserve -l for future use, for xgawk's -l option.
- */
static const struct option optab[] = {
- { "traditional", no_argument, & do_traditional, 1 },
+ { "traditional", no_argument, NULL, 'c' },
{ "lint", optional_argument, NULL, 'L' },
- { "lint-old", no_argument, & do_lint_old, 1 },
- { "optimize", no_argument, & do_optimize, 'O' },
- { "posix", no_argument, & do_posix, 1 },
- { "command", required_argument, NULL, 'R' },
+ { "lint-old", no_argument, NULL, 't' },
+ { "optimize", no_argument, NULL, 'O' },
+ { "posix", no_argument, NULL, 'P' },
{ "nostalgia", no_argument, & do_nostalgia, 1 },
- { "gen-pot", no_argument, & do_intl, 1 },
- { "non-decimal-data", no_argument, & do_non_decimal_data, 1 },
+ { "gen-pot", no_argument, NULL, 'g' },
+ { "non-decimal-data", no_argument, NULL, 'n' },
+ { "pretty-print", optional_argument, NULL, 'o' },
{ "profile", optional_argument, NULL, 'p' },
+ { "debug", optional_argument, NULL, 'D' },
{ "copyright", no_argument, NULL, 'C' },
{ "field-separator", required_argument, NULL, 'F' },
{ "file", required_argument, NULL, 'f' },
- { "re-interval", no_argument, & do_intervals, 1 },
+ { "re-interval", no_argument, NULL, 'r' },
{ "source", required_argument, NULL, 'e' },
+ { "load", required_argument, NULL, 'l' },
{ "dump-variables", optional_argument, NULL, 'd' },
{ "assign", required_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
@@ -194,17 +183,13 @@ static const struct option optab[] = {
{ "exec", required_argument, NULL, 'E' },
{ "use-lc-numeric", no_argument, & use_lc_numeric, 1 },
{ "characters-as-bytes", no_argument, & do_binary, 'b' },
- { "sandbox", no_argument, & do_sandbox, 1 },
+ { "sandbox", no_argument, NULL, 'S' },
#if defined(YYDEBUG) || defined(GAWKDEBUG)
{ "parsedebug", no_argument, NULL, 'Y' },
#endif
{ NULL, 0, NULL, '\0' }
};
-#ifdef NO_LINT
-#define do_lint 0
-#define do_lint_old 0
-#endif
/* main --- process args, parse program, run it, clean up */
@@ -213,19 +198,21 @@ main(int argc, char **argv)
{
/*
* The + on the front tells GNU getopt not to rearrange argv.
- * Note: reserve -D for future use, to merge dgawk into gawk.
* Note: reserve -l for future use, for xgawk's -l option.
*/
- const char *optlist = "+F:f:v:W;m:bcCd::e:E:gh:L:nNOp::PrR:StVY";
+ const char *optlist = "+F:f:v:W;m:bcCd::D::e:E:gh:l:L:nNo::Op::PrStVY";
int stopped_early = FALSE;
int old_optind;
int i;
int c;
char *scan, *src;
char *extra_stack;
+ int have_srcfile = FALSE;
+ SRCFILE *s;
/* do these checks early */
- do_tidy_mem = (getenv("TIDYMEM") != NULL);
+ if (getenv("TIDYMEM") != NULL)
+ do_flags |= DO_TIDY_MEM;
#ifdef HAVE_MCHECK_H
#ifdef HAVE_MTRACE
@@ -373,7 +360,7 @@ main(int argc, char **argv)
break;
case 'c':
- do_traditional = TRUE;
+ do_flags |= DO_TRADITIONAL;
break;
case 'C':
@@ -381,11 +368,17 @@ main(int argc, char **argv)
break;
case 'd':
- do_dump_vars = TRUE;
+ do_flags |= DO_DUMP_VARS;
if (optarg != NULL && optarg[0] != '\0')
varfile = optarg;
break;
+ case 'D':
+ do_flags |= DO_DEBUG;
+ if (optarg != NULL && optarg[0] != '\0')
+ command_file = optarg;
+ break;
+
case 'e':
if (optarg[0] == '\0')
warning(_("empty argument to `-e/--source' ignored"));
@@ -394,7 +387,7 @@ main(int argc, char **argv)
break;
case 'g':
- do_intl = TRUE;
+ do_flags |= DO_INTL;
break;
case 'h':
@@ -402,19 +395,25 @@ main(int argc, char **argv)
usage(EXIT_SUCCESS, stdout);
break;
-#ifndef NO_LINT
+ case 'l':
+ (void) add_srcfile(SRC_EXTLIB, optarg, srcfiles, NULL, NULL);
+ break;
+
case 'L':
- do_lint = LINT_ALL;
+#ifndef NO_LINT
+ do_flags |= DO_LINT_ALL;
if (optarg != NULL) {
if (strcmp(optarg, "fatal") == 0)
lintfunc = r_fatal;
- else if (strcmp(optarg, "invalid") == 0)
- do_lint = LINT_INVALID;
+ else if (strcmp(optarg, "invalid") == 0) {
+ do_flags &= ~DO_LINT_ALL;
+ do_flags |= DO_LINT_INVALID;
+ }
}
break;
case 't':
- do_lint_old = TRUE;
+ do_flags |= DO_LINT_OLD;
break;
#else
case 'L':
@@ -423,7 +422,7 @@ main(int argc, char **argv)
#endif
case 'n':
- do_non_decimal_data = TRUE;
+ do_flags |= DO_NON_DEC_DATA;
break;
case 'N':
@@ -435,7 +434,10 @@ main(int argc, char **argv)
break;
case 'p':
- do_profiling = TRUE;
+ do_flags |= DO_PROFILE;
+ /* fall through */
+ case 'o':
+ do_flags |= DO_PRETTY_PRINT;
if (optarg != NULL)
set_prof_file(optarg);
else
@@ -443,15 +445,15 @@ main(int argc, char **argv)
break;
case 'P':
- do_posix = TRUE;
+ do_flags |= DO_POSIX;
break;
case 'r':
- do_intervals = TRUE;
+ do_flags |= DO_INTERVALS;
break;
case 'S':
- do_sandbox = TRUE;
+ do_flags |= DO_SANDBOX;
break;
case 'V':
@@ -472,20 +474,13 @@ main(int argc, char **argv)
break;
case 'Y':
- case 'R':
#if defined(YYDEBUG) || defined(GAWKDEBUG)
if (c == 'Y') {
yydebug = 2;
break;
}
#endif
- if (c == 'R' && which_gawk == exe_debugging) {
- if (optarg[0] != '\0')
- command_file = optarg;
- break;
- }
- /* if not debugging or dgawk, fall through */
-
+ /* if not debugging, fall through */
case '?':
default:
/*
@@ -530,7 +525,7 @@ out:
/* check for POSIXLY_CORRECT environment variable */
if (! do_posix && getenv("POSIXLY_CORRECT") != NULL) {
- do_posix = TRUE;
+ do_flags |= DO_POSIX;
if (do_lint)
lintwarn(
_("environment variable `POSIXLY_CORRECT' set: turning on `--posix'"));
@@ -541,7 +536,7 @@ out:
if (do_traditional) /* both on command line */
warning(_("`--posix' overrides `--traditional'"));
else
- do_traditional = TRUE;
+ do_flags |= DO_TRADITIONAL;
/*
* POSIX compliance also implies
* no GNU extensions either.
@@ -549,7 +544,7 @@ out:
}
if (do_traditional && do_non_decimal_data) {
- do_non_decimal_data = FALSE;
+ do_flags &= ~DO_NON_DEC_DATA;
warning(_("`--posix'/`--traditional' overrides `--non-decimal-data'"));
}
@@ -565,21 +560,13 @@ out:
}
#endif
- /*
- * Force profiling if this is pgawk.
- * Don't bother if the command line already set profiling up.
- */
- if (! do_profiling)
- init_profiling(& do_profiling, DEFAULT_PROFILE);
-
/* load group set */
init_groupset();
/* initialize the null string */
Nnull_string = make_string("", 0);
Nnull_string->numbr = 0.0;
- Nnull_string->type = Node_val;
- Nnull_string->flags = (PERM|STRCUR|STRING|NUMCUR|NUMBER);
+ Nnull_string->flags = (MALLOC|STRCUR|STRING|NUMCUR|NUMBER);
/*
* Tell the regex routines how they should work.
@@ -588,7 +575,7 @@ out:
*/
resetup();
- (void) grow_stack();
+ init_interpret();
/* Set up the special variables */
init_vars();
@@ -623,8 +610,17 @@ out:
#endif
if (os_isatty(fileno(stdout)))
output_is_tty = TRUE;
+
+ /* load extension libs */
+ for (s = srcfiles->next; s != srcfiles; s = s->next) {
+ if (s->stype == SRC_EXTLIB)
+ (void) load_ext(s->fullpath, "dlload", NULL);
+ else
+ have_srcfile++;
+ }
+
/* No -f or --source options, use next arg */
- if (srcfiles->next == srcfiles) {
+ if (! have_srcfile) {
if (optind > argc - 1 || stopped_early) /* no args left or no program */
usage(EXIT_FAILURE, stderr);
(void) add_srcfile(SRC_CMDLINE, argv[optind], srcfiles, NULL, NULL);
@@ -644,7 +640,7 @@ out:
setlocale(LC_NUMERIC, "C");
#endif
/* Read in the program */
- if (parse_program(&code_block) != 0)
+ if (parse_program(& code_block) != 0)
exit(EXIT_FAILURE);
if (do_intl)
@@ -656,7 +652,8 @@ out:
if (do_lint && code_block->nexti->opcode == Op_atexit)
lintwarn(_("no program text at all!"));
- init_profiling_signals();
+ if (do_profile)
+ init_profiling_signals();
#if defined(LC_NUMERIC)
/*
@@ -677,10 +674,16 @@ out:
if (use_lc_numeric)
setlocale(LC_NUMERIC, "");
#endif
+
+ init_io();
+ output_fp = stdout;
- interpret(code_block);
+ if (do_debug)
+ debug_prog(code_block);
+ else
+ interpret(code_block);
- if (do_profiling) {
+ if (do_pretty_print) {
dump_prog(code_block);
dump_funcs();
}
@@ -734,7 +737,7 @@ usage(int exitval, FILE *fp)
fprintf(fp, _("Usage: %s [POSIX or GNU style options] -f progfile [--] file ...\n"),
myname);
fprintf(fp, _("Usage: %s [POSIX or GNU style options] [--] %cprogram%c file ...\n"),
- myname, quote, quote);
+ myname, quote, quote);
/* GNU long options info. This is too many options. */
@@ -747,19 +750,20 @@ usage(int exitval, FILE *fp)
fputs(_("\t-c\t\t\t--traditional\n"), fp);
fputs(_("\t-C\t\t\t--copyright\n"), fp);
fputs(_("\t-d[file]\t\t--dump-variables[=file]\n"), fp);
+ fputs(_("\t-D[file]\t\t--debug[=file]\n"), fp);
fputs(_("\t-e 'program-text'\t--source='program-text'\n"), fp);
fputs(_("\t-E file\t\t\t--exec=file\n"), fp);
fputs(_("\t-g\t\t\t--gen-pot\n"), fp);
fputs(_("\t-h\t\t\t--help\n"), fp);
+ fputs(_("\t-l library\t\t--load=library\n"), fp);
fputs(_("\t-L [fatal]\t\t--lint[=fatal]\n"), fp);
fputs(_("\t-n\t\t\t--non-decimal-data\n"), fp);
fputs(_("\t-N\t\t\t--use-lc-numeric\n"), fp);
+ fputs(_("\t-o[file]\t\t--pretty-print[=file]\n"), fp);
fputs(_("\t-O\t\t\t--optimize\n"), fp);
fputs(_("\t-p[file]\t\t--profile[=file]\n"), fp);
fputs(_("\t-P\t\t\t--posix\n"), fp);
fputs(_("\t-r\t\t\t--re-interval\n"), fp);
- if (which_gawk == exe_debugging)
- fputs(_("\t-R file\t\t\t--command=file\n"), fp);
fputs(_("\t-S\t\t\t--sandbox\n"), fp);
fputs(_("\t-t\t\t\t--lint-old\n"), fp);
fputs(_("\t-V\t\t\t--version\n"), fp);
@@ -857,6 +861,7 @@ cmdline_fs(char *str)
if (do_traditional && ! do_posix)
str[0] = '\t';
}
+
*tmp = make_str_node(str, strlen(str), SCAN); /* do process escapes */
set_FS();
}
@@ -870,26 +875,27 @@ init_args(int argc0, int argc, const char *argv0, char **argv)
NODE **aptr;
NODE *tmp;
- ARGV_node = install_symbol(estrdup("ARGV", 4), mk_symbol(Node_var_array, (NODE *) NULL));
+ ARGV_node = install_symbol(estrdup("ARGV", 4), Node_var_array);
tmp = make_number(0.0);
- aptr = assoc_lookup(ARGV_node, tmp, FALSE);
+ aptr = assoc_lookup(ARGV_node, tmp);
unref(tmp);
unref(*aptr);
*aptr = make_string(argv0, strlen(argv0));
(*aptr)->flags |= MAYBE_NUM;
for (i = argc0, j = 1; i < argc; i++, j++) {
tmp = make_number((AWKNUM) j);
- aptr = assoc_lookup(ARGV_node, tmp, FALSE);
+ aptr = assoc_lookup(ARGV_node, tmp);
unref(tmp);
unref(*aptr);
*aptr = make_string(argv[i], strlen(argv[i]));
(*aptr)->flags |= MAYBE_NUM;
}
- ARGC_node = install_symbol(estrdup("ARGC", 4),
- mk_symbol(Node_var, make_number((AWKNUM) j)));
+ ARGC_node = install_symbol(estrdup("ARGC", 4), Node_var);
+ ARGC_node->var_value = make_number((AWKNUM) j);
}
+
/*
* Set all the special variables to their initial values.
* Note that some of the variables that have set_FOO routines should
@@ -952,13 +958,11 @@ init_vars()
for (vp = varinit; vp->name != NULL; vp++) {
if ((vp->flags & NO_INSTALL) != 0)
continue;
- n = mk_symbol(Node_var, vp->strval == NULL
- ? make_number(vp->numval)
- : make_string(vp->strval, strlen(vp->strval)));
+ n = *(vp->spec) = install_symbol(estrdup(vp->name, strlen(vp->name)), Node_var);
+ n->var_value = vp->strval == NULL ? make_number(vp->numval)
+ : make_string(vp->strval, strlen(vp->strval));
n->var_assign = (Func_ptr) vp->assign;
n->var_update = (Func_ptr) vp->update;
-
- *(vp->spec) = install_symbol(estrdup(vp->name, strlen(vp->name)), n);
if (vp->do_assign)
(*(vp->assign))();
}
@@ -982,9 +986,7 @@ load_environ()
int i;
NODE *tmp;
- ENVIRON_node = install_symbol(estrdup("ENVIRON", 7),
- mk_symbol(Node_var_array, (NODE *) NULL));
-
+ ENVIRON_node = install_symbol(estrdup("ENVIRON", 7), Node_var_array);
for (i = 0; environ[i] != NULL; i++) {
static char nullstr[] = "";
@@ -995,7 +997,7 @@ load_environ()
else
val = nullstr;
tmp = make_string(var, strlen(var));
- aptr = assoc_lookup(ENVIRON_node, tmp, FALSE);
+ aptr = assoc_lookup(ENVIRON_node, tmp);
unref(tmp);
unref(*aptr);
*aptr = make_string(val, strlen(val));
@@ -1018,7 +1020,7 @@ load_environ()
val = getenv("AWKPATH");
if (val == NULL)
val = defpath;
- aptr = assoc_lookup(ENVIRON_node, tmp, FALSE);
+ aptr = assoc_lookup(ENVIRON_node, tmp);
unref(*aptr);
*aptr = make_string(val, strlen(val));
}
@@ -1037,8 +1039,7 @@ load_procinfo()
#endif
AWKNUM value;
- PROCINFO_node = install_symbol(estrdup("PROCINFO", 8),
- mk_symbol(Node_var_array, (NODE *) NULL));
+ PROCINFO_node = install_symbol(estrdup("PROCINFO", 8), Node_var_array);
update_PROCINFO_str("version", VERSION);
update_PROCINFO_str("strftime", def_strftime_format);
@@ -1234,7 +1235,7 @@ arg_assign(char *arg, int initing)
cp2 = estrdup(arg, cp - arg); /* var name */
- var = variable(cp2, Node_var);
+ var = variable(0, cp2, Node_var);
if (var == NULL) /* error */
exit(EXIT_FATAL);
if (var->type == Node_var && var->var_update)
@@ -1461,3 +1462,18 @@ update_global_values()
vp->update();
}
}
+
+/* getenv_long --- read a long value (>= 0) from an environment var. */
+
+long
+getenv_long(const char *name)
+{
+ const char *val;
+ long newval;
+ if ((val = getenv(name)) != NULL && isdigit((unsigned char) *val)) {
+ for (newval = 0; *val && isdigit((unsigned char) *val); val++)
+ newval = (newval * 10) + *val - '0';
+ return newval;
+ }
+ return -1;
+}