1 | /* vms_gawk.c -- parse GAWK command line using DCL syntax
|
---|
2 |
|
---|
3 | Copyright (C) 1991-1993, 1996, 2003, 2005 the Free Software Foundation, Inc.
|
---|
4 |
|
---|
5 | This program is free software; you can redistribute it and/or modify
|
---|
6 | it under the terms of the GNU General Public License as published by
|
---|
7 | the Free Software Foundation; either version 2, or (at your option)
|
---|
8 | any later version.
|
---|
9 |
|
---|
10 | This program is distributed in the hope that it will be useful,
|
---|
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
13 | GNU General Public License for more details.
|
---|
14 |
|
---|
15 | You should have received a copy of the GNU General Public License
|
---|
16 | along with this program; if not, write to the Free Software Foundation,
|
---|
17 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
---|
18 |
|
---|
19 |
|
---|
20 | /*
|
---|
21 | * vms_gawk.c - routines to parse the command line as a native DCL command
|
---|
22 | * rather than as a foreign command string.
|
---|
23 | * Pat Rankin, Nov'89
|
---|
24 | * [ revised for 2.12, May'91 ]
|
---|
25 | */
|
---|
26 |
|
---|
27 | #include "awk.h"
|
---|
28 | #include "vms.h"
|
---|
29 | #define COMMAND_NAME "GAWK" /* verb name & for 'usage' message(s) */
|
---|
30 | #define USAGE_PROG_RQRD 1
|
---|
31 | #define USAGE_FILE_RQRD 2
|
---|
32 | #define USAGE_BAD_COMBO 3
|
---|
33 | #define USAGE_RUN_CMD 4
|
---|
34 | #define STS$M_INHIB_MSG 0x10000000
|
---|
35 |
|
---|
36 | #define Present(arg) vmswork(Cli_Present(arg))
|
---|
37 | #define Get_Value(arg,buf,siz) vmswork(Cli_Get_Value(arg,buf,siz))
|
---|
38 |
|
---|
39 | #ifndef __ia64__
|
---|
40 | extern void gawk_cmd(); /* created with $ SET COMMAND/OBJECT */
|
---|
41 | #define GAWK_CMD ((const void *)gawk_cmd)
|
---|
42 | #else /* linker on Itanium is much pickier about such things */
|
---|
43 | #pragma extern_model save
|
---|
44 | #pragma extern_model strict_refdef
|
---|
45 | /* (could use globalvalue rather than _refdef if we omit GAWK_CMD's `&') */
|
---|
46 | extern void *gawk_cmd;
|
---|
47 | #pragma extern_model restore
|
---|
48 | #define GAWK_CMD ((const void *)&gawk_cmd)
|
---|
49 | #endif
|
---|
50 | extern void _exit(int);
|
---|
51 | static int vms_usage(int);
|
---|
52 |
|
---|
53 | #define ARG_SIZ 250
|
---|
54 | union arg_w_prefix { /* structure used to simplify prepending of "-" */
|
---|
55 | char value[2+ARG_SIZ+1];
|
---|
56 | struct {
|
---|
57 | char prefix[2]; /* for "-?" */
|
---|
58 | char buf[ARG_SIZ];
|
---|
59 | char suffix[1]; /* room for '\0' */
|
---|
60 | } arg;
|
---|
61 | };
|
---|
62 |
|
---|
63 | #define chk_option(qualifier,optname) \
|
---|
64 | if (Present(qualifier)) \
|
---|
65 | strcat(strcat(buf.arg.buf, W_cnt++ ? "," : ""), optname)
|
---|
66 |
|
---|
67 |
|
---|
68 | /* vms_gawk() - parse GAWK command line using DCL and convert it into the */
|
---|
69 | /* appropriate "-arg" values for compatability with GNU code */
|
---|
70 | int
|
---|
71 | vms_gawk()
|
---|
72 | {
|
---|
73 | U_Long sts;
|
---|
74 | union arg_w_prefix buf;
|
---|
75 | char misc_args[10], *misc_argp;
|
---|
76 | int argc, W_cnt;
|
---|
77 | int native_dcl = 1; /* assume true until we know otherwise */
|
---|
78 |
|
---|
79 | /* check "GAWK_P1"--it's required; its presence will tip us off */
|
---|
80 | sts = Cli_Present("GAWK_P1");
|
---|
81 | if (CondVal(sts) == CondVal(CLI$_SYNTAX)) {
|
---|
82 | native_dcl = 0; /* not invoked via a native command verb */
|
---|
83 | /* syntax error indicates that we weren't invoked as a native DCL
|
---|
84 | command, so we'll now attempt to generate a command from the
|
---|
85 | foreign command string and parse that.
|
---|
86 | */
|
---|
87 | sts = Cli_Parse_Command(GAWK_CMD, COMMAND_NAME);
|
---|
88 | if (vmswork(sts))
|
---|
89 | sts = Cli_Present("GAWK_P1");
|
---|
90 | }
|
---|
91 | if (vmswork(sts)) /* command parsed successfully */
|
---|
92 | v_add_arg(argc = 0, COMMAND_NAME); /* save "GAWK" as argv[0] */
|
---|
93 | else if (CondVal(sts) == CondVal(CLI$_INSFPRM))
|
---|
94 | return native_dcl ? vms_usage(USAGE_FILE_RQRD) : 0; /* insufficient parameters */
|
---|
95 | else if (CondVal(sts) == CondVal(CLI$_CONFLICT))
|
---|
96 | return vms_usage(USAGE_BAD_COMBO); /* conflicting qualifiers (/input+/command) */
|
---|
97 | #if 0 /* 3.1.2: removed since this can't distinguish RUN vs fork+exec */
|
---|
98 | else if (CondVal(sts) == CondVal(CLI$_RUNUSED))
|
---|
99 | return vms_usage(USAGE_RUN_CMD); /* RUN GAWK won't work (no command line) */
|
---|
100 | #endif
|
---|
101 | else
|
---|
102 | return 0; /* forced to rely on original parsing */
|
---|
103 |
|
---|
104 | if (Present("USAGE")) /* give usage message and quit */
|
---|
105 | return vms_usage(0);
|
---|
106 | else if (! (Present("PROGRAM") || Present("PROGFILE")) )
|
---|
107 | return native_dcl ? vms_usage(USAGE_PROG_RQRD) : 0; /* missing required option */
|
---|
108 |
|
---|
109 | misc_argp = misc_args;
|
---|
110 | *misc_argp++ = '-'; /* now points at &misc_args[1] */
|
---|
111 | #if 0 /* as of 2.12, -a and -e are obsolete */
|
---|
112 | if (Present("REG_EXPR")) {
|
---|
113 | if (Present("REG_EXPR.AWK")) /* /reg_exp=awk -> -a */
|
---|
114 | *misc_argp++ = 'a';
|
---|
115 | else if (Present("REG_EXPR.EGREP") /* /reg_exp=egrep -> -e */
|
---|
116 | || Present("REG_EXPR.POSIX")) /* /reg_exp=posix -> -e */
|
---|
117 | *misc_argp++ = 'e';
|
---|
118 | }
|
---|
119 | #endif /* 0 */
|
---|
120 | #if 0 /* gawk 2.11.1 */
|
---|
121 | if (Present("STRICT")) /* /strict -> -c */
|
---|
122 | *misc_argp++ = 'c';
|
---|
123 | if (Present("COPYRIGHT")) /* /copyright -> -C */
|
---|
124 | *misc_argp++ = 'C';
|
---|
125 | if (Present("VERSION")) /* /version -> -V */
|
---|
126 | *misc_argp++ = 'V';
|
---|
127 | #else /* gawk 2.12 and later */
|
---|
128 | W_cnt = 0, buf.arg.buf[0] = '\0';
|
---|
129 | strncpy(buf.arg.prefix, "-W", 2);
|
---|
130 | chk_option("LINT","lint");
|
---|
131 | chk_option("POSIX","posix");
|
---|
132 | chk_option("STRICT","compat");
|
---|
133 | chk_option("COPYRIGHT","copyright");
|
---|
134 | chk_option("VERSION","version");
|
---|
135 | if (W_cnt > 0) /* got something */
|
---|
136 | v_add_arg(++argc, strdup(buf.value));
|
---|
137 | #endif /*0*/
|
---|
138 | #ifdef DEBUG
|
---|
139 | if (Present("DEBUG")) {
|
---|
140 | #if 0
|
---|
141 | int both = Present("DEBUG.ALL");
|
---|
142 | if (both || Present("DEBUG.EXECUTION"))
|
---|
143 | *misc_argp++ = 'd';
|
---|
144 | if (both || Present("DEBUG.PARSE"))
|
---|
145 | #endif
|
---|
146 | *misc_argp++ = 'D';
|
---|
147 | }
|
---|
148 | #endif
|
---|
149 | *misc_argp = '\0'; /* terminate misc_args[] */
|
---|
150 | if (misc_argp > &misc_args[1]) /* got something */
|
---|
151 | v_add_arg(++argc, misc_args); /* store it/them */
|
---|
152 |
|
---|
153 | if (Present("FIELD_SEP")) { /* field separator */
|
---|
154 | strncpy(buf.arg.prefix, "-F", 2);
|
---|
155 | if (Get_Value("FIELD_SEP", buf.arg.buf, sizeof buf.arg.buf))
|
---|
156 | v_add_arg(++argc, strdup(buf.value));
|
---|
157 | }
|
---|
158 | if (Present("VARIABLES")) { /* variables to init prior to BEGIN */
|
---|
159 | strncpy(buf.arg.prefix, "-v", 2);
|
---|
160 | while (Get_Value("VARIABLES", buf.arg.buf, sizeof buf.arg.buf))
|
---|
161 | v_add_arg(++argc, strdup(buf.value));
|
---|
162 | }
|
---|
163 | if (Present("PROGFILE")) { /* program files, /input=file -> -f file */
|
---|
164 | strncpy(buf.arg.prefix, "-f", 2);
|
---|
165 | while (Get_Value("PROGFILE", buf.arg.buf, sizeof buf.arg.buf))
|
---|
166 | v_add_arg(++argc, strdup(buf.value));
|
---|
167 | v_add_arg(++argc, "--");
|
---|
168 | } else if (Present("PROGRAM")) { /* program text, /program -> 'text' */
|
---|
169 | v_add_arg(++argc, "--");
|
---|
170 | if (Get_Value("PROGRAM", buf.value, sizeof buf.value))
|
---|
171 | v_add_arg(++argc, strdup(buf.value));
|
---|
172 | }
|
---|
173 |
|
---|
174 | /* we know that "GAWK_P1" is present [data files and/or 'var=value'] */
|
---|
175 | while (Get_Value("GAWK_P1", buf.value, sizeof buf.value))
|
---|
176 | v_add_arg(++argc, strdup(buf.value));
|
---|
177 |
|
---|
178 | if (Present("OUTPUT")) { /* let other parser treat this as 'stdout' */
|
---|
179 | strncpy(buf.arg.prefix, ">$", 2);
|
---|
180 | if (Get_Value("OUTPUT", buf.arg.buf, sizeof buf.arg.buf))
|
---|
181 | v_add_arg(++argc, strdup(buf.value));
|
---|
182 | }
|
---|
183 |
|
---|
184 | return ++argc; /*(increment to account for arg[0])*/
|
---|
185 | }
|
---|
186 |
|
---|
187 | /* vms_usage() - display one or more messages and then terminate */
|
---|
188 | static int /* note: usually doesn't return */
|
---|
189 | vms_usage( int complaint )
|
---|
190 | {
|
---|
191 | static const char
|
---|
192 | *usage_txt = "\n\
|
---|
193 | usage: %s /COMMANDS=\"awk program text\" data_file[,data_file,...] \n\
|
---|
194 | or %s /INPUT=awk_file data_file[,\"Var=value\",data_file,...] \n\
|
---|
195 | or %s /INPUT=(awk_file1,awk_file2,...) data_file[,...] \n\
|
---|
196 | ",
|
---|
197 | *options_txt = "\n\
|
---|
198 | options: /FIELD_SEPARATOR=\"FS_value\" \n\
|
---|
199 | - /VARIABLES=(\"Var1=value1\",\"Var2=value2\",...) \n\
|
---|
200 | - /LINT /POSIX /[NO]STRICT /VERSION /COPYRIGHT /USAGE \n\
|
---|
201 | - /OUTPUT=out_file \n\
|
---|
202 | ",
|
---|
203 | *no_prog = "missing required element: /COMMANDS or /INPUT",
|
---|
204 | *no_file = "missing required element: data_file \n\
|
---|
205 | (use \"SYS$INPUT:\" to read data lines from the terminal)",
|
---|
206 | *bad_combo = "invalid combination of qualifiers \n\
|
---|
207 | (/INPUT=awk_file and /COMMANDS=\"awk program\" are mutually exclusive)",
|
---|
208 | *run_used = "\"RUN\" was used; required command components missing";
|
---|
209 | int status, argc;
|
---|
210 |
|
---|
211 | fflush(stdout);
|
---|
212 | switch (complaint) {
|
---|
213 | case USAGE_PROG_RQRD:
|
---|
214 | fprintf(stderr, "\n%%%s-W-%s, %s \n", COMMAND_NAME, "PROG_RQRD", no_prog);
|
---|
215 | status = CLI$_VALREQ | STS$M_INHIB_MSG;
|
---|
216 | break;
|
---|
217 | case USAGE_FILE_RQRD:
|
---|
218 | if (Present("USAGE")) {
|
---|
219 | status = 1; /* clean exit */
|
---|
220 | } else if (Present("COPYRIGHT") || Present("VERSION")) {
|
---|
221 | v_add_arg(argc=0, COMMAND_NAME); /* save "GAWK" as argv[0] */
|
---|
222 | #if 0
|
---|
223 | v_add_arg(++argc, Present("COPYRIGHT") ? "-C" : "-V");
|
---|
224 | #else
|
---|
225 | v_add_arg(++argc, "-W");
|
---|
226 | v_add_arg(++argc, Present("COPYRIGHT") ? "copyright" : "version");
|
---|
227 | #endif
|
---|
228 | v_add_arg(++argc, "{}"); /* kludge to suppress 'usage' */
|
---|
229 | v_add_arg(++argc, "NL:"); /* dummy input for kludge */
|
---|
230 | return ++argc; /* count argv[0] too */
|
---|
231 | } else {
|
---|
232 | fprintf(stderr, "\n%%%s-W-%s, %s \n", COMMAND_NAME, "FILE_RQRD", no_file);
|
---|
233 | status = CLI$_INSFPRM | STS$M_INHIB_MSG;
|
---|
234 | }
|
---|
235 | break;
|
---|
236 | case USAGE_BAD_COMBO:
|
---|
237 | fprintf(stderr, "\n%%%s-W-%s, %s \n", COMMAND_NAME, "BAD_COMBO", bad_combo);
|
---|
238 | status = CLI$_CONFLICT | STS$M_INHIB_MSG;
|
---|
239 | break;
|
---|
240 | case USAGE_RUN_CMD:
|
---|
241 | fprintf(stderr, "\n%%%s-W-%s, %s \n", COMMAND_NAME, "RUN_CMD", run_used);
|
---|
242 | status = CLI$_NOOPTPRS | STS$M_INHIB_MSG;
|
---|
243 | break;
|
---|
244 | default:
|
---|
245 | status = 1;
|
---|
246 | break;
|
---|
247 | }
|
---|
248 | fprintf(stderr, usage_txt, COMMAND_NAME, COMMAND_NAME, COMMAND_NAME);
|
---|
249 | fprintf(stderr, options_txt);
|
---|
250 | fflush(stderr);
|
---|
251 |
|
---|
252 | errno = EVMSERR;
|
---|
253 | vaxc$errno = status;
|
---|
254 | _exit(status);
|
---|
255 | /* NOTREACHED */
|
---|
256 | return 0;
|
---|
257 | }
|
---|