Home | History | Annotate | Download | only in VMS
      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