/* vms-code.c -- additional VMS-specific support code for flex */ #include "flexdef.h" static const char *original_arg0; static const char default_arg0[] = "flex.exe"; #define IN_FD 0 #define OUT_FD 1 #define ERR_FD 2 static char *fix_arg0 PROTO((const char *)); /* Command line arguments fixup -- simplify argv[0], and handle `>' output redirection request; called first thing from main(). */ void argv_fixup( iargc, iargv ) int *iargc; char ***iargv; { const char *mode[3], *rfm[3], *name[3]; char *p; int i, oargc, punct, which, append, alt_rfm; /* * Get original argv[0] supplied by run-time library startup code, * then replace it with a stripped down one. */ original_arg0 = (*iargv)[0]; (*iargv)[0] = fix_arg0(original_arg0); /* * Check command line arguments for redirection request(s). * For simplicity, if multiple attempts are made, the last one wins. */ name[0] = name[1] = name[2] = 0; oargc = 1; /* number of args caller will see; count includes argv[0] */ for (i = 1; i < *iargc; i++) { p = (*iargv)[i]; switch (*p) { case '<': /* might be "file"; then again, perhaps "<file" */ punct = (strchr(p, '>') != 0); if (p[1] == '<') { if (!punct || p[2] == '<') flexerror("<<'sentinel' input not supported."); punct = 0; } if (punct) /* the '<' seems to be directory punctuation */ goto arg; /*GOTO*/ mode[IN_FD] = "r"; rfm[IN_FD] = 0; name[IN_FD] = ++p; if (!*p && (i + 1) < *iargc) name[IN_FD] = (*iargv)[++i]; break; case '>': append = (p[1] == '>'); if (append) ++p; alt_rfm = (p[1] == '$'); if (alt_rfm) ++p; which = (p[1] == '&' ? ERR_FD : OUT_FD); if (which == ERR_FD) ++p; mode[which] = append ? "a" : "w"; rfm[which] = alt_rfm ? "rfm=var" : "rfm=stmlf"; name[which] = ++p; if (!*p && (i + 1) < *iargc) name[which] = (*iargv)[++i]; break; case '|': flexerror("pipe output not supported."); /*NOTREACHED*/ break; default: arg: /* ordinary option or argument */ (*iargv)[oargc++] = p; break; } } /* perform any requested redirection; don't bother with SYS$xxx logicals */ if (name[IN_FD]) if (!freopen(name[IN_FD], mode[IN_FD], stdin)) lerrsf("failed to redirect `stdin' from \"%s\"", name[IN_FD]); if (name[OUT_FD]) if (!freopen(name[OUT_FD], mode[OUT_FD], stdout, rfm[OUT_FD], "rat=cr", "mbc=32", "shr=nil")) lerrsf("failed to redirect `stdout' to \"%s\"", name[OUT_FD]); if (name[ERR_FD]) /* likely won't see message if this fails; oh well... */ if (!freopen(name[ERR_FD], mode[ERR_FD], stderr, rfm[ERR_FD], "rat=cr")) lerrsf("failed to redirect `stderr' to \"%s\"", name[ERR_FD]); /* remove any excess arguments (used up from redirection) */ while (*iargc > oargc) (*iargv)[--*iargc] = 0; /* all done */ return; } /* Pick out the basename of a full filename, and return a pointer to a modifiable copy of it. */ static char *fix_arg0( arg0 ) const char *arg0; { char *p, *new_arg0; if (arg0) { /* strip off the path */ if ((p = strrchr(arg0, ':')) != 0) /* device punctuation */ arg0 = p + 1; if ((p = strrchr(arg0, ']')) != 0) /* directory punctuation */ arg0 = p + 1; if ((p = strrchr(arg0, '>')) != 0) /* alternate dir punct */ arg0 = p + 1; } if (!arg0 || !*arg0) arg0 = default_arg0; /* should now have "something.exe;#"; make a modifiable copy */ new_arg0 = copy_string(arg0); /* strip off ".exe" and/or ";#" (version number), unless it ended up as the whole name */ if ((p = strchr(new_arg0, '.')) != 0 && (p > new_arg0) && (p[1] == 'e' || p[1] == 'E') && (p[2] == 'x' || p[2] == 'X') && (p[3] == 'e' || p[3] == 'E') && (p[4] == ';' || p[4] == '.' || p[4] == '\0')) *p = '\0'; else if ((p = strchr(new_arg0, ';')) != 0 && (p > new_arg0)) *p = '\0'; return new_arg0; } #include #include #ifdef exit #undef exit extern void exit PROTO((int)); /* ended up prototyping vms_exit */ #endif /* Convert zero to VMS success and non-zero to VMS failure. The latter does not bother trying to distinguish between various failure reasons. */ void vms_exit( status ) int status; { exit( status == 0 ? SS$_NORMAL : (SS$_ABORT | STS$M_INHIB_MSG) ); }