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 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 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> 139 #include <stsdef.h> 140 141 #ifdef exit 142 #undef exit 143 extern void exit PROTO((int)); /* <stdlib.h> ended up prototyping vms_exit */ 144 #endif 145 146 /* Convert zero to VMS success and non-zero to VMS failure. The latter 147 does not bother trying to distinguish between various failure reasons. */ 148 149 void vms_exit( status ) 150 int status; 151 { 152 exit( status == 0 ? SS$_NORMAL : (SS$_ABORT | STS$M_INHIB_MSG) ); 153 } 154