1 /* vms-code.c -- additional VMS-specific support code for flex
2 */
3
4 #include "flexdef.h"
5
6 static const char *original_arg0;
7 static const char default_arg0[] = "flex.exe";
8
9 #define IN_FD 0
10 #define OUT_FD 1
11 #define ERR_FD 2
12
13 static char *fix_arg0 PROTO((const char *));
14
15 /* Command line arguments fixup -- simplify argv[0], and handle `>'
16 output redirection request; called first thing from main(). */
17
argv_fixup(iargc,iargv)18 void argv_fixup( iargc, iargv )
19 int *iargc;
20 char ***iargv;
21 {
22 const char *mode[3], *rfm[3], *name[3];
23 char *p;
24 int i, oargc, punct, which, append, alt_rfm;
25
26 /*
27 * Get original argv[0] supplied by run-time library startup code,
28 * then replace it with a stripped down one.
29 */
30 original_arg0 = (*iargv)[0];
31 (*iargv)[0] = fix_arg0(original_arg0);
32
33 /*
34 * Check command line arguments for redirection request(s).
35 * For simplicity, if multiple attempts are made, the last one wins.
36 */
37 name[0] = name[1] = name[2] = 0;
38 oargc = 1; /* number of args caller will see; count includes argv[0] */
39 for (i = 1; i < *iargc; i++) {
40 p = (*iargv)[i];
41 switch (*p) {
42 case '<':
43 /* might be "<dir>file"; then again, perhaps "<<dir>file" */
44 punct = (strchr(p, '>') != 0);
45 if (p[1] == '<') {
46 if (!punct || p[2] == '<')
47 flexerror("<<'sentinel' input not supported.");
48 punct = 0;
49 }
50 if (punct) /* the '<' seems to be directory punctuation */
51 goto arg; /*GOTO*/
52 mode[IN_FD] = "r";
53 rfm[IN_FD] = 0;
54 name[IN_FD] = ++p;
55 if (!*p && (i + 1) < *iargc)
56 name[IN_FD] = (*iargv)[++i];
57 break;
58 case '>':
59 append = (p[1] == '>');
60 if (append) ++p;
61 alt_rfm = (p[1] == '$');
62 if (alt_rfm) ++p;
63 which = (p[1] == '&' ? ERR_FD : OUT_FD);
64 if (which == ERR_FD) ++p;
65 mode[which] = append ? "a" : "w";
66 rfm[which] = alt_rfm ? "rfm=var" : "rfm=stmlf";
67 name[which] = ++p;
68 if (!*p && (i + 1) < *iargc)
69 name[which] = (*iargv)[++i];
70 break;
71 case '|':
72 flexerror("pipe output not supported.");
73 /*NOTREACHED*/
74 break;
75 default:
76 arg: /* ordinary option or argument */
77 (*iargv)[oargc++] = p;
78 break;
79 }
80 }
81 /* perform any requested redirection; don't bother with SYS$xxx logicals */
82 if (name[IN_FD])
83 if (!freopen(name[IN_FD], mode[IN_FD], stdin))
84 lerrsf("failed to redirect `stdin' from \"%s\"", name[IN_FD]);
85 if (name[OUT_FD])
86 if (!freopen(name[OUT_FD], mode[OUT_FD], stdout,
87 rfm[OUT_FD], "rat=cr", "mbc=32", "shr=nil"))
88 lerrsf("failed to redirect `stdout' to \"%s\"", name[OUT_FD]);
89 if (name[ERR_FD]) /* likely won't see message if this fails; oh well... */
90 if (!freopen(name[ERR_FD], mode[ERR_FD], stderr,
91 rfm[ERR_FD], "rat=cr"))
92 lerrsf("failed to redirect `stderr' to \"%s\"", name[ERR_FD]);
93 /* remove any excess arguments (used up from redirection) */
94 while (*iargc > oargc)
95 (*iargv)[--*iargc] = 0;
96 /* all done */
97 return;
98 }
99
100 /* Pick out the basename of a full filename, and return a pointer
101 to a modifiable copy of it. */
102
fix_arg0(arg0)103 static char *fix_arg0( arg0 )
104 const char *arg0;
105 {
106 char *p, *new_arg0;
107
108 if (arg0) {
109 /* strip off the path */
110 if ((p = strrchr(arg0, ':')) != 0) /* device punctuation */
111 arg0 = p + 1;
112 if ((p = strrchr(arg0, ']')) != 0) /* directory punctuation */
113 arg0 = p + 1;
114 if ((p = strrchr(arg0, '>')) != 0) /* alternate dir punct */
115 arg0 = p + 1;
116 }
117 if (!arg0 || !*arg0)
118 arg0 = default_arg0;
119 /* should now have "something.exe;#"; make a modifiable copy */
120 new_arg0 = copy_string(arg0);
121
122 /* strip off ".exe" and/or ";#" (version number),
123 unless it ended up as the whole name */
124 if ((p = strchr(new_arg0, '.')) != 0 && (p > new_arg0)
125 && (p[1] == 'e' || p[1] == 'E')
126 && (p[2] == 'x' || p[2] == 'X')
127 && (p[3] == 'e' || p[3] == 'E')
128 && (p[4] == ';' || p[4] == '.' || p[4] == '\0'))
129 *p = '\0';
130 else if ((p = strchr(new_arg0, ';')) != 0 && (p > new_arg0))
131 *p = '\0';
132
133 return new_arg0;
134 }
135
136
137 #include <ssdef.h>
138 #include <stsdef.h>
139
140 #ifdef exit
141 #undef exit
142 extern void exit PROTO((int)); /* <stdlib.h> ended up prototyping vms_exit */
143 #endif
144
145 /* Convert zero to VMS success and non-zero to VMS failure. The latter
146 does not bother trying to distinguish between various failure reasons. */
147
vms_exit(status)148 void vms_exit( status )
149 int status;
150 {
151 exit( status == 0 ? SS$_NORMAL : (SS$_ABORT | STS$M_INHIB_MSG) );
152 }
153