diff options
Diffstat (limited to 'vms')
-rw-r--r-- | vms/ChangeLog | 28 | ||||
-rw-r--r-- | vms/gawk.cld | 57 | ||||
-rw-r--r-- | vms/vms.h | 1 | ||||
-rw-r--r-- | vms/vms_cli.c | 32 | ||||
-rw-r--r-- | vms/vms_gawk.c | 158 |
5 files changed, 204 insertions, 72 deletions
diff --git a/vms/ChangeLog b/vms/ChangeLog index 2dff4560..3a3b74a1 100644 --- a/vms/ChangeLog +++ b/vms/ChangeLog @@ -1,3 +1,31 @@ +Sat Feb 26 18:35:01 2011 Pat Rankin <rankin@pactechdata.com> + + * vms_gawk.c, gawk.cld: Add support for new command qualifiers: + /extra_commands="text" -e "awk program text" + /profile[=file] --profile [awkprof.out] + /dump_variables[=file] --dump_variables [awkvars.out] + /optimize, /traditional, /re_interval, /sandbox, /non_decimal_data + New but not documented since not useful for present VMS port: + /characters_as_bytes, /use_lc_numeric, /gen_pot + Revamp several existing qualifiers: + /strict was --compat, now synonym for /traditional + /lint=(warn,fatal,invalid,old) + /lint=warn --lint (same as /lint without any value) + /lint=fatal --lint fatal + /lint=old --lint-old + /lint=(warn,fatal) --lint fatal (warn ignored) + /lint=(warn,old) --lint --lint-old + /lint=(fatal,old) --lint fatal --lint-old + /usage, /version, /copyright try harder to make awk program and + data file be optional since these just give messages and then quit. + (vms_usage): Substitute "GAWK", "DGAWK", or "PGAWK" as appropriate + for command name when issuing the VMS-specific usage message. + * vms.h (CLI$_NEGATED): Define macro (from <cilmsgdef.h>). + + * vms_cli.c: Add copyright notice. Remove unused P() macro. + (dcl$present, dcl$get_value, dcl$parse_command): Use lowercase + rather than upper for these system routine names. + Fri Feb 18 19:24:30 2011 Pat Rankin <rankin@pactechdata.com> * vmstest.com (beginfile1, dumpvars): New tests. diff --git a/vms/gawk.cld b/vms/gawk.cld index 7ff50dae..fce15cdf 100644 --- a/vms/gawk.cld +++ b/vms/gawk.cld @@ -1,6 +1,16 @@ ! Gawk.Cld -- command defintion for GAWK ! Pat Rankin, Nov'89 ! [ revised for 2.12, May'91 ] +! [ revised for 4.0.0, Feb'11 ] +! +! This command definition is compiled into an object module which is +! linked into all three programs, GAWK, DGAWK, and PGAWK, and it is +! not able to use syntax-switching qualifers to invoke the different +! images gawk.exe, dgawk.exe, and pgawk.exe. To use dgawk or pgawk +! when this command definition is installed as a native command, use +! $ define gawk location:dgawk.exe +! or $ define gawk location:pgawk.exe +! module Gawk_Cmd define verb GAWK synonym AWK @@ -8,18 +18,35 @@ define verb GAWK parameter p1, value(required,list), label=gawk_p1, prompt="data file(s)" qualifier input, value(required,list,type=$infile), label=progfile qualifier commands, value(required), label=program + qualifier extra_commands, value(required), label=moreprog qualifier field_separator, value(required), label=field_sep - qualifier reg_expr, value(type=reg_expr_keywords) !(OBSOLETE) qualifier variables, value(required,list) + qualifier usage qualifier copyright qualifier version - qualifier lint + qualifier lint, value(list,type=lint_keywords) qualifier posix - qualifier usage - qualifier strict, negatable - qualifier debug, negatable + qualifier strict, negatable !synonym for /traditional + qualifier traditional, negatable + qualifier re_interval, negatable !only used with /traditional + qualifier sandbox + qualifier debug, negatable !obsolete; debug via separate DGAWK program qualifier output, value(type=$outfile,default="SYS$OUTPUT") + qualifier optimize, negatable !actually on always; negation is ignored + qualifier profile, value(type=$outfile,default="awkprof.out") + qualifier dump_variables, value(type=$outfile,default="awkvars.out") + qualifier non_decimal_data + qualifier characters_as_bytes + qualifier use_lc_numeric + qualifier get_pot + qualifier reg_expr, value(type=reg_expr_keywords) !(OBSOLETE) disallow progfile and program !or not progfile and not program + !disallow lint.warn and (lint.fatal or lint.invalid) +define type lint_keywords + keyword warn, default + keyword fatal !lint warnings terminate execution + keyword invalid !warn about invalid constructs but not extensions + keyword old !warn about constructs not available in original awk define type reg_expr_keywords keyword awk keyword egrep, default !synonym for 'posix' @@ -30,17 +57,23 @@ define type reg_expr_keywords ! /input = program source file ('-f progfile') ! /commands = program source text ('program') !note: either input or commands, but not both; if neither, usage message given +! /extra_commands = additional program source text; may be combined with /input ! /field_separator = character(s) delimiting record fields; default is "[ \t]" -! /reg_expr = type of regular expressions: awk or posix (posix == egrep) -!note: by default, use awk style; /reg_expr (w/o value), use egrep style +! /reg_expr = obsolete ! /variables = list of 'var=value' items for assignment prior to BEGIN ! /posix = force POSIX compatability mode operation -! /strict = force compatability mode operation (UN*X SYS V, Release 4) +! /sandbox = disable I/O redirection and use of system() to execute commands +! /strict = synonym for /traditional +! /traditional = force compatability mode operation (UN*X SYS V, Release 4) +! /re_interval = for /traditional, regular expressions allow interval ranges ! /output = destination for print,printf (default is sys$output: ie, 'stdout') ! /lint = scan the awk program for possible problems and warn about them -! /debug = debugging mode -!note: compilation options determine whether debug mode is valid +! /optimize = parse-time evaluation of constant [sub-]expressions only +! /debug = debugging mode; no-op unless program built using `#define DEBUG' +! /dump_var = at program termination, write out final values for all variables +! /profile = collect all parts of the parsed awk program into awkprof.out +!note: use separate pgawk program to collect run-time execution profiling ! /usage = display 'usage' reminder [describing this VMS command syntax] -! /version = show program version -! /copyright = show abbreviated edition of FSF's copyright notice +! /version = show program version and quit; also shows copyright notice +! /copyright = show abbreviated edition of FSF's copyright notice and quit ! @@ -29,6 +29,7 @@ #define CLI$_SYNTAX 0x000310FC /* error signalled by CLI$DCL_PARSE */ #define CLI$_INSFPRM 0x00038048 /* insufficient parameters */ #define CLI$_VALREQ 0x00038150 /* missing required value */ +#define CLI$_NEGATED 0x000381F8 /* explicitly negated */ #define CLI$_CONFLICT 0x00038258 /* conflicting qualifiers */ #define CLI$_NOOPTPRS 0x00038840 /* no option present */ #endif diff --git a/vms/vms_cli.c b/vms/vms_cli.c index 1638290b..ac793c1a 100644 --- a/vms/vms_cli.c +++ b/vms/vms_cli.c @@ -1,19 +1,37 @@ +/* vms_cli.c -- interface to CLI$xxx routines for fetching command line components + + Copyright (C) 1991-1993, 2003, 2011 the Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + + /* * vms_cli.c - command line interface routines. * Pat Rankin, Nov'89 * Routines called from vms_gawk.c for DCL parsing. */ -#define P(foo) () #include "config.h" /* in case we want to suppress 'const' &c */ #include "vms.h" #ifndef _STRING_H #include <string.h> #endif -extern U_Long CLI$PRESENT(const Dsc *); -extern U_Long CLI$GET_VALUE(const Dsc *, Dsc *, short *); -extern U_Long CLI$DCL_PARSE(const Dsc *, const void *, ...); +extern U_Long cli$present(const Dsc *); +extern U_Long cli$get_value(const Dsc *, Dsc *, short *); +extern U_Long cli$dcl_parse(const Dsc *, const void *, ...); extern U_Long sys$cli(void *, ...); extern U_Long sys$filescan(const Dsc *, void *, long *); extern void *lib$establish(U_Long (*handler)(void *, void *)); @@ -28,7 +46,7 @@ Cli_Present( const char *item ) (void)lib$establish(lib$sig_to_ret); item_dsc.len = strlen(item_dsc.adr = (char *)item); - return CLI$PRESENT(&item_dsc); + return cli$present(&item_dsc); } /* Cli_Get_Value() - call CLI$GET_VALUE to retreive the value of a */ @@ -43,7 +61,7 @@ Cli_Get_Value( const char *item, char *result, int size ) item_dsc.len = strlen(item_dsc.adr = (char *)item); res_dsc.len = size, res_dsc.adr = result; - sts = CLI$GET_VALUE(&item_dsc, &res_dsc, &len); + sts = cli$get_value(&item_dsc, &res_dsc, &len); result[len] = '\0'; return sts; } @@ -84,7 +102,7 @@ Cli_Parse_Command( const void *cmd_tables, const char *cmd_verb ) cmd.rdesc.len = sizeof longbuf - ltmp; strncpy(&longbuf[ltmp], cmd.rdesc.adr, cmd.rdesc.len); cmd.rdesc.len += ltmp, cmd.rdesc.adr = longbuf; - sts = CLI$DCL_PARSE( &cmd.rdesc, cmd_tables); + sts = cli$dcl_parse(&cmd.rdesc, cmd_tables); } return sts; diff --git a/vms/vms_gawk.c b/vms/vms_gawk.c index de19c732..1fb956e0 100644 --- a/vms/vms_gawk.c +++ b/vms/vms_gawk.c @@ -1,6 +1,6 @@ /* vms_gawk.c -- parse GAWK command line using DCL syntax - Copyright (C) 1991-1993, 1996, 2003, 2005 the Free Software Foundation, Inc. + Copyright (C) 1991-1993, 1996, 2003, 2005, 2011 the Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,11 +22,12 @@ * rather than as a foreign command string. * Pat Rankin, Nov'89 * [ revised for 2.12, May'91 ] + * [ revised for 4.0.0, Feb'11 ] */ #include "awk.h" #include "vms.h" -#define COMMAND_NAME "GAWK" /* verb name & for 'usage' message(s) */ + #define USAGE_PROG_RQRD 1 #define USAGE_FILE_RQRD 2 #define USAGE_BAD_COMBO 3 @@ -50,6 +51,8 @@ extern void *gawk_cmd; extern void _exit(int); static int vms_usage(int); +static const char *CmdName; /* "GAWK", "DGAWK", or "PGAWK" */ + #define ARG_SIZ 250 union arg_w_prefix { /* structure used to simplify prepending of "-" */ char value[2+ARG_SIZ+1]; @@ -74,7 +77,12 @@ vms_gawk() union arg_w_prefix buf; char misc_args[10], *misc_argp; int argc, W_cnt; - int native_dcl = 1; /* assume true until we know otherwise */ + int native_dcl = 1, /* assume true until we know otherwise */ + short_circ; /* some options make P1, /commands, /input superfluous */ + + CmdName = (which_gawk == exe_profiling) ? "PGAWK" + : (which_gawk == exe_debugging) ? "DGAWK" + : "GAWK"; /* check "GAWK_P1"--it's required; its presence will tip us off */ sts = Cli_Present("GAWK_P1"); @@ -84,14 +92,17 @@ vms_gawk() command, so we'll now attempt to generate a command from the foreign command string and parse that. */ - sts = Cli_Parse_Command(GAWK_CMD, COMMAND_NAME); + sts = Cli_Parse_Command(GAWK_CMD, "GAWK"); /* (*not* CmdName) */ if (vmswork(sts)) sts = Cli_Present("GAWK_P1"); } + short_circ = Present("USAGE") || Present("VERSION") || Present("COPYRIGHT"); if (vmswork(sts)) /* command parsed successfully */ - v_add_arg(argc = 0, COMMAND_NAME); /* save "GAWK" as argv[0] */ + v_add_arg(argc = 0, CmdName); /* save "GAWK|DGAWK|PGAWK" as argv[0] */ else if (CondVal(sts) == CondVal(CLI$_INSFPRM)) - return native_dcl ? vms_usage(USAGE_FILE_RQRD) : 0; /* insufficient parameters */ + /* vms_usage() will handle /usage, /version, and /copyright */ + return short_circ ? vms_usage(0) + : native_dcl ? vms_usage(USAGE_FILE_RQRD) : 0; /* insufficient parameters */ else if (CondVal(sts) == CondVal(CLI$_CONFLICT)) return vms_usage(USAGE_BAD_COMBO); /* conflicting qualifiers (/input+/command) */ #if 0 /* 3.1.2: removed since this can't distinguish RUN vs fork+exec */ @@ -101,8 +112,8 @@ vms_gawk() else return 0; /* forced to rely on original parsing */ - if (Present("USAGE")) /* give usage message and quit */ - return vms_usage(0); + if (short_circ) /* give usage message & quit or have main() */ + return vms_usage(0); /* give --version or --copyleft mesg & quit */ else if (! (Present("PROGRAM") || Present("PROGFILE")) ) return native_dcl ? vms_usage(USAGE_PROG_RQRD) : 0; /* missing required option */ @@ -127,29 +138,53 @@ vms_gawk() #else /* gawk 2.12 and later */ W_cnt = 0, buf.arg.buf[0] = '\0'; strncpy(buf.arg.prefix, "-W", 2); - chk_option("LINT","lint"); - chk_option("POSIX","posix"); - chk_option("STRICT","compat"); - chk_option("COPYRIGHT","copyright"); - chk_option("VERSION","version"); + chk_option("OPTIMIZE", "optimize"); + if (Present("LINT")) { + if (!Present("LINT.FATAL") && !Present("LINT.INVALID")) + chk_option("LINT.WARN", "lint"); + chk_option("LINT.FATAL", "lint=fatal"); + chk_option("LINT.INVALID", "lint=invalid"); + chk_option("LINT.OLD", "lint-old"); /* distinct option */ + } + chk_option("POSIX", "posix"); + if (CondVal(Cli_Present("TRADITIONAL")) != CondVal(CLI$_NEGATED)) + chk_option("STRICT", "traditional"); /* /strict is synonym for /traditional */ + if (CondVal(Cli_Present("STRICT")) != CondVal(CLI$_NEGATED)) + chk_option("TRADITIONAL", "traditional"); + chk_option("RE_INTERVAL", "re-interval"); /* only used with /traditional */ + chk_option("SANDBOX", "sandbox"); + /* potentially a problem due to leading "NO" */ + chk_option("NON_DECIMAL_DATA", "non-decimal-data"); + /* note: locale and translation stuff is not supported by vms gawk */ + chk_option("CHARACTERS_AS_BYTES", "characters-as-bytes"); + chk_option("USE_LC_NUMERIC", "use-lc-numeric"); + chk_option("GEN_POT", "gen-pot"); +# if 0 + /* /copyright and /version don't reach here anymore (short_circ above) */ + chk_option("COPYRIGHT", "copyright"); /* --copyleft */ + chk_option("VERSION", "version"); +# endif if (W_cnt > 0) /* got something */ v_add_arg(++argc, strdup(buf.value)); #endif /*0*/ -#ifdef DEBUG - if (Present("DEBUG")) { -#if 0 - int both = Present("DEBUG.ALL"); - if (both || Present("DEBUG.EXECUTION")) - *misc_argp++ = 'd'; - if (both || Present("DEBUG.PARSE")) -#endif - *misc_argp++ = 'D'; - } +#ifdef DEBUG /* most debugging functionality moved to separate DGAWK program */ + if (Present("DEBUG")) + *misc_argp++ = 'Y'; /* --parsedebug */ #endif *misc_argp = '\0'; /* terminate misc_args[] */ if (misc_argp > &misc_args[1]) /* got something */ v_add_arg(++argc, misc_args); /* store it/them */ + if (Present("PROFILE")) { /* /profile[=file] */ + strncpy(buf.arg.prefix, "-p", 2); + if (Get_Value("PROFILE", buf.arg.buf, sizeof buf.arg.buf)) + v_add_arg(++argc, strdup(buf.value)); + } + if (Present("DUMP_VARIABLES")) { /* /dump_variables[=file] */ + strncpy(buf.arg.prefix, "-d", 2); + if (Get_Value("DUMP_VARIABLES", buf.arg.buf, sizeof buf.arg.buf)) + v_add_arg(++argc, strdup(buf.value)); + } if (Present("FIELD_SEP")) { /* field separator */ strncpy(buf.arg.prefix, "-F", 2); if (Get_Value("FIELD_SEP", buf.arg.buf, sizeof buf.arg.buf)) @@ -160,12 +195,19 @@ vms_gawk() while (Get_Value("VARIABLES", buf.arg.buf, sizeof buf.arg.buf)) v_add_arg(++argc, strdup(buf.value)); } + /* the relative order of -e and -f args matters; unfortunately, + we're losing that here... */ + if (Present("MOREPROG")) { /* /extra_input=text -> -e text */ + strncpy(buf.arg.prefix, "-e", 2); + if (Get_Value("MOREPROG", buf.arg.buf, sizeof buf.arg.buf)) + v_add_arg(++argc, strdup(buf.value)); + } if (Present("PROGFILE")) { /* program files, /input=file -> -f file */ strncpy(buf.arg.prefix, "-f", 2); while (Get_Value("PROGFILE", buf.arg.buf, sizeof buf.arg.buf)) v_add_arg(++argc, strdup(buf.value)); v_add_arg(++argc, "--"); - } else if (Present("PROGRAM")) { /* program text, /program -> 'text' */ + } else if (Present("PROGRAM")) { /* program text, /commands -> 'text' */ v_add_arg(++argc, "--"); if (Get_Value("PROGRAM", buf.value, sizeof buf.value)) v_add_arg(++argc, strdup(buf.value)); @@ -190,16 +232,21 @@ vms_usage( int complaint ) { static const char *usage_txt = "\n\ -usage: %s /COMMANDS=\"awk program text\" data_file[,data_file,...] \n\ - or %s /INPUT=awk_file data_file[,\"Var=value\",data_file,...] \n\ - or %s /INPUT=(awk_file1,awk_file2,...) data_file[,...] \n\ +usage: %s /COMMANDS=\"awk program text\" data_file[,data_file,...] \n\ + or %s /INPUT=awk_file data_file[,\"Var=value\",data_file,...] \n\ + or %s /INPUT=(awk_file1,awk_file2,...) data_file[,...] \n\ + or %s /INPUT=awk_file /EXTRA_COMMANDS=\"program text\" data_file \n\ ", *options_txt = "\n\ -options: /FIELD_SEPARATOR=\"FS_value\" \n\ - - /VARIABLES=(\"Var1=value1\",\"Var2=value2\",...) \n\ - - /LINT /POSIX /[NO]STRICT /VERSION /COPYRIGHT /USAGE \n\ - - /OUTPUT=out_file \n\ -", +options: /FIELD_SEPARATOR=\"FS_value\" \n\ + and /VARIABLES=(\"Var1=value1\",\"Var2=value2\",...) \n\ + and /OPTIMIZE /PROFILE[=file] /DUMP_VARIABLES[=file] \n\ + and /POSIX /[NO]TRADITIONAL /[NO]STRICT /RE_INTERVAL \n\ + and /SANDBOX /NON_DECIMAL_DATA \n\ + and /LINT[=WARN] or /LINT=OLD or /LINT=FATAL \n\ + and /VERSION /COPYRIGHT /USAGE \n\ + and /OUTPUT=out_file \n\ +", /* omitted: /LINT=INVALID /CHARACTERS_AS_BYTES /USE_LC_NUMERIC /GEN_POT */ *no_prog = "missing required element: /COMMANDS or /INPUT", *no_file = "missing required element: data_file \n\ (use \"SYS$INPUT:\" to read data lines from the terminal)", @@ -208,44 +255,49 @@ options: /FIELD_SEPARATOR=\"FS_value\" \n\ *run_used = "\"RUN\" was used; required command components missing"; int status, argc; + /* presence of /usage, /version, or /copyright for feedback+quit + supersedes absence of required program or data file */ + if (Present("USAGE")) { + complaint = 0; /* clean exit */ + } else if (Present("VERSION") || Present("COPYRIGHT")) { + /* construct a truncated Unix-style command line to control main() */ + v_add_arg(argc=0, CmdName); /* save "GAWK",&c as argv[0] */ +#if 0 + v_add_arg(++argc, Present("VERSION") ? "-V" : "-C"); +#else + v_add_arg(++argc, "-W"); + v_add_arg(++argc, Present("VERSION") ? "version" : "copyright"); +#endif + /* kludge to suppress 'usage' message from main() */ + v_add_arg(++argc, "--"); /* no more arguments */ + v_add_arg(++argc, "{}"); /* dummy program text */ + v_add_arg(++argc, "NL:"); /* dummy input file */ + return ++argc; /* count argv[0] too */ + } + fflush(stdout); switch (complaint) { case USAGE_PROG_RQRD: - fprintf(stderr, "\n%%%s-W-%s, %s \n", COMMAND_NAME, "PROG_RQRD", no_prog); + fprintf(stderr, "\n%%%s-W-%s, %s \n", CmdName, "PROG_RQRD", no_prog); status = CLI$_VALREQ | STS$M_INHIB_MSG; break; case USAGE_FILE_RQRD: - if (Present("USAGE")) { - status = 1; /* clean exit */ - } else if (Present("COPYRIGHT") || Present("VERSION")) { - v_add_arg(argc=0, COMMAND_NAME); /* save "GAWK" as argv[0] */ -#if 0 - v_add_arg(++argc, Present("COPYRIGHT") ? "-C" : "-V"); -#else - v_add_arg(++argc, "-W"); - v_add_arg(++argc, Present("COPYRIGHT") ? "copyright" : "version"); -#endif - v_add_arg(++argc, "{}"); /* kludge to suppress 'usage' */ - v_add_arg(++argc, "NL:"); /* dummy input for kludge */ - return ++argc; /* count argv[0] too */ - } else { - fprintf(stderr, "\n%%%s-W-%s, %s \n", COMMAND_NAME, "FILE_RQRD", no_file); - status = CLI$_INSFPRM | STS$M_INHIB_MSG; - } + fprintf(stderr, "\n%%%s-W-%s, %s \n", CmdName, "FILE_RQRD", no_file); + status = CLI$_INSFPRM | STS$M_INHIB_MSG; break; case USAGE_BAD_COMBO: - fprintf(stderr, "\n%%%s-W-%s, %s \n", COMMAND_NAME, "BAD_COMBO", bad_combo); + fprintf(stderr, "\n%%%s-W-%s, %s \n", CmdName, "BAD_COMBO", bad_combo); status = CLI$_CONFLICT | STS$M_INHIB_MSG; break; case USAGE_RUN_CMD: - fprintf(stderr, "\n%%%s-W-%s, %s \n", COMMAND_NAME, "RUN_CMD", run_used); + fprintf(stderr, "\n%%%s-W-%s, %s \n", CmdName, "RUN_CMD", run_used); status = CLI$_NOOPTPRS | STS$M_INHIB_MSG; break; default: status = 1; break; } - fprintf(stderr, usage_txt, COMMAND_NAME, COMMAND_NAME, COMMAND_NAME); + fprintf(stderr, usage_txt, CmdName, CmdName, CmdName, CmdName); fprintf(stderr, options_txt); fflush(stderr); |