[418] | 1 | /* --redexp.vms--
|
---|
| 2 | This 'C' module may be included prior to the ``main'' programs on VMS in
|
---|
| 3 | order to allow 'C' arguments to contain redirection symbols (<,>,>>) and
|
---|
| 4 | VMS wild cards (*,%, ...], [-). By including this module, two programs
|
---|
| 5 | redirect() and expand() are run prior to turning control over to
|
---|
| 6 | your main() entry point.
|
---|
| 7 |
|
---|
| 8 | redirect-- Gregg Townsend circa 1983,
|
---|
| 9 | expand-- John Campbell circa 1987
|
---|
| 10 |
|
---|
| 11 | This code is public domain, others may use it freely. Credit, however, to
|
---|
| 12 | Gregg Townsend (who wrote ``redirect()'') and John Campbell (who followed
|
---|
| 13 | with ``expand()'') would be appreciated. If someone writes the next
|
---|
| 14 | logical successor ``pipe()'', please email a copy to
|
---|
| 15 | ...!arizona!naucse!jdc (John Campbell) (Gregg works on unix :-).
|
---|
| 16 |
|
---|
| 17 | HISTORY
|
---|
| 18 |
|
---|
| 19 | */
|
---|
| 20 |
|
---|
| 21 | #include <rms.h> /* No easy way to tell if this has already been included. */
|
---|
| 22 | #ifndef ERANGE
|
---|
| 23 | #include <stdlib.h> /* Include only if missing. */
|
---|
| 24 | #endif
|
---|
| 25 | #ifndef __FILE
|
---|
| 26 | #include <stdio.h> /* Include only if missing. */
|
---|
| 27 | #endif
|
---|
| 28 | #include <ctype.h> /* Added for conversion to lower case */
|
---|
| 29 | #ifndef __STRING_LOADED
|
---|
| 30 | #include <string.h>
|
---|
| 31 | #endif /* !__STRING_LOADED */
|
---|
| 32 |
|
---|
| 33 | /* Expansion of wild cards is done using RMS. */
|
---|
| 34 | struct NAMBLK { struct NAM nam; /* VMS nam block structure */
|
---|
| 35 | char es[NAM$C_MAXRSS], /* Extended string */
|
---|
| 36 | rs[NAM$C_MAXRSS]; /* Resultant string */
|
---|
| 37 | };
|
---|
| 38 |
|
---|
| 39 | #define ErrorExit 1
|
---|
| 40 |
|
---|
| 41 | /* Allow the user to override _N_FARGS or _E_FLAG if they wish. */
|
---|
| 42 | #ifndef _N_FARGS
|
---|
| 43 | #define _N_FARGS 0 /* no automatic redirection please */
|
---|
| 44 | #endif
|
---|
| 45 | #ifndef _E_FLAG
|
---|
| 46 | #define _E_FLAG 4 /* only include dev and dir if different from default */
|
---|
| 47 | #endif
|
---|
| 48 | /*
|
---|
| 49 | Since the following will possibly be included in a single module, try
|
---|
| 50 | hard to avoid name conflicts. (Just being static doesn't cut it if
|
---|
| 51 | compiled in the same module.)
|
---|
| 52 | */
|
---|
| 53 | #define redirect _r_edirect
|
---|
| 54 | #define filearg _f_ilearg
|
---|
| 55 | #define expand _e_xpand
|
---|
| 56 | #define wild_found _w_ild_found
|
---|
| 57 | #define wild_expand _w_ild_expand
|
---|
| 58 |
|
---|
| 59 | /* forward protypes */
|
---|
| 60 | static void redirect(int *argc, char *argv[], int nfargs);
|
---|
| 61 | char **expand (int *argc, const char *argv[], const int flag);
|
---|
| 62 |
|
---|
| 63 | main(int argc, char *argv[], char *envp[])
|
---|
| 64 | {
|
---|
| 65 | redirect (&argc, argv, _N_FARGS);
|
---|
| 66 | argv = expand (&argc, argv, _E_FLAG);
|
---|
| 67 |
|
---|
| 68 | /* Make the user's main entry point this routine's entry point. */
|
---|
| 69 | #define main _user_main
|
---|
| 70 | _user_main (argc, argv, envp);
|
---|
| 71 | }
|
---|
| 72 |
|
---|
| 73 | /* ------------------------ REDIRECT code ------------------------ */
|
---|
| 74 |
|
---|
| 75 | /*
|
---|
| 76 | * redirect(&argc,argv,nfargs) - redirect standard I/O
|
---|
| 77 | * int *argc number of command arguments (from call to main)
|
---|
| 78 | * char *argv[] command argument list (from call to main)
|
---|
| 79 | * int nfargs number of filename arguments to process
|
---|
| 80 | *
|
---|
| 81 | * argc and argv will be adjusted by redirect.
|
---|
| 82 | *
|
---|
| 83 | * redirect processes a program's command argument list and handles redirection
|
---|
| 84 | * of stdin, and stdout. Any arguments which redirect I/O are removed from the
|
---|
| 85 | * argument list, and argc is adjusted accordingly. redirect would typically be
|
---|
| 86 | * called as the first statement in the main program.
|
---|
| 87 | *
|
---|
| 88 | * Files are redirected based on syntax or position of command arguments.
|
---|
| 89 | * Arguments of the following forms always redirect a file:
|
---|
| 90 | *
|
---|
| 91 | * <file redirects standard input to read the given file
|
---|
| 92 | * >file redirects standard output to write to the given file
|
---|
| 93 | * >>file redirects standard output to append to the given file
|
---|
| 94 | *
|
---|
| 95 | * It is often useful to allow alternate input and output files as the
|
---|
| 96 | * first two command arguments without requiring the <file and >file
|
---|
| 97 | * syntax. If the nfargs argument to redirect is 2 or more then the
|
---|
| 98 | * first two command arguments, if supplied, will be interpreted in this
|
---|
| 99 | * manner: the first argument replaces stdin and the second stdout.
|
---|
| 100 | * A filename of "-" may be specified to occupy a position without
|
---|
| 101 | * performing any redirection.
|
---|
| 102 | *
|
---|
| 103 | * If nfargs is 1, only the first argument will be considered and will
|
---|
| 104 | * replace standard input if given. Any arguments processed by setting
|
---|
| 105 | * nfargs > 0 will be removed from the argument list, and again argc will
|
---|
| 106 | * be adjusted. Positional redirection follows syntax-specified
|
---|
| 107 | * redirection and therefore overrides it.
|
---|
| 108 | *
|
---|
| 109 | */
|
---|
| 110 |
|
---|
| 111 | /* forward prototype for local routine */
|
---|
| 112 | static void filearg(int *argc, char *argv[], int n, int i, FILE *fp, char mode[]);
|
---|
| 113 |
|
---|
| 114 | static void redirect(int *argc, char *argv[], int nfargs)
|
---|
| 115 | {
|
---|
| 116 | int i;
|
---|
| 117 |
|
---|
| 118 | i = 1;
|
---|
| 119 | while (i < *argc) { /* for every command argument... */
|
---|
| 120 | switch (argv[i][0]) { /* check first character */
|
---|
| 121 | case '<': /* <file redirects stdin */
|
---|
| 122 | filearg(argc,argv,i,1,stdin,"r");
|
---|
| 123 | break;
|
---|
| 124 | case '>': /* >file or >>file redirects stdout */
|
---|
| 125 | if (argv[i][1] == '>')
|
---|
| 126 | filearg(argc,argv,i,2,stdout,"a");
|
---|
| 127 | else
|
---|
| 128 | filearg(argc,argv,i,1,stdout,"w");
|
---|
| 129 | break;
|
---|
| 130 | default: /* not recognized, go on to next arg */
|
---|
| 131 | i++;
|
---|
| 132 | }
|
---|
| 133 | }
|
---|
| 134 | if (nfargs >= 1 && *argc > 1) /* if positional redirection & 1 arg */
|
---|
| 135 | filearg(argc,argv,1,0,stdin,"r"); /* then redirect stdin */
|
---|
| 136 | if (nfargs >= 2 && *argc > 1) /* likewise for 2nd arg if wanted */
|
---|
| 137 | filearg(argc,argv,1,0,stdout,"w");/* redirect stdout */
|
---|
| 138 | }
|
---|
| 139 |
|
---|
| 140 | /* local routine for redirect() */
|
---|
| 141 | /* filearg(&argc,argv,n,i,fp,mode) - redirect and remove file argument
|
---|
| 142 | * int *argc number of command arguments (from call to main)
|
---|
| 143 | * char *argv[] command argument list (from call to main)
|
---|
| 144 | * int n argv entry to use as file name and then delete
|
---|
| 145 | * int i first character of file name to use (skip '<' etc.)
|
---|
| 146 | * FILE *fp file pointer for file to reopen (typically stdin etc.)
|
---|
| 147 | * char mode[] file access mode (see freopen spec)
|
---|
| 148 | */
|
---|
| 149 |
|
---|
| 150 | static void filearg(int *argc, char *argv[], int n, int i, FILE *fp, char mode[])
|
---|
| 151 | {
|
---|
| 152 | if (strcmp(argv[n]+i,"-")) /* alter file if arg not "-" */
|
---|
| 153 | fp = freopen(argv[n]+i,mode,fp,"mbf=8","mbc=16");
|
---|
| 154 | if (fp == NULL) { /* abort on error */
|
---|
| 155 | fprintf(stderr,"%%can't open %s",argv[n]+i);
|
---|
| 156 | exit(ErrorExit);
|
---|
| 157 | }
|
---|
| 158 | for ( ; n < *argc; n++) /* move down following arguments */
|
---|
| 159 | argv[n] = argv[n+1];
|
---|
| 160 | *argc = *argc - 1; /* decrement argument count */
|
---|
| 161 | }
|
---|
| 162 |
|
---|
| 163 | /* ------------------------ EXPAND code ------------------------ */
|
---|
| 164 | /*-
|
---|
| 165 | ``expand()'' is a routine to expand wild-cards to file specifications.
|
---|
| 166 | This routine is often used in conjunction with ``redirect()'' to provide
|
---|
| 167 | both wild card expansion and standard file redirection prior to doing
|
---|
| 168 | any real work in a 'C' program.
|
---|
| 169 |
|
---|
| 170 | Normal usage is to include the following line prior to using argc or
|
---|
| 171 | argv in main():
|
---|
| 172 |
|
---|
| 173 | argv = expand (&argc, argv, 0);
|
---|
| 174 |
|
---|
| 175 | ``argc'' will be adjusted by ``expand()'', the return value from expand
|
---|
| 176 | will replace ``argv''.
|
---|
| 177 |
|
---|
| 178 | ``expand()'' processes a program's command argument list and expands any
|
---|
| 179 | wild cards into zero or more argv entries. Only arguments that posses VMS
|
---|
| 180 | wild-cards are expanded. Wild cards searched for are ``*'', ``%'',
|
---|
| 181 | ``...]'', and ``[-''. If the wild-card is found inside a single or double
|
---|
| 182 | quote ("*" or '%') then they are not counted as wild-cards. Be aware that
|
---|
| 183 | the expansion of a VMS wild card will match all VMS files, including
|
---|
| 184 | directory files (".DIR;1").
|
---|
| 185 |
|
---|
| 186 | NOTE: The use of quotes in VMS requires thinking about how the CLI expands
|
---|
| 187 | things before handing the argument line over to your program. Do not
|
---|
| 188 | expect "*" to avoid expansion, use """*""" instead. Likewise, expression
|
---|
| 189 | substitution precludes the use of (') to quote wild cards:
|
---|
| 190 | $ A := HELLO
|
---|
| 191 | $ ECHO 'a' ! 'C' program that calls ``expand()''
|
---|
| 192 | hello
|
---|
| 193 | The easiest way to escape a wild-card may be "'*'". The point is that
|
---|
| 194 | ``expand()'' will only recognize quotes passed into main().
|
---|
| 195 | Note: I have added '\' as an escape character -hdd.
|
---|
| 196 |
|
---|
| 197 | ``expand()'' references the VMS runtime routines, you will need to
|
---|
| 198 | link with the 'C' RTL whenever expand is used.
|
---|
| 199 |
|
---|
| 200 | Parameters:
|
---|
| 201 |
|
---|
| 202 | argc: Pointer to the number of command arguments (from main),
|
---|
| 203 | the contents of this parameter are modified.
|
---|
| 204 |
|
---|
| 205 | argv: Pointer to the initial command argument list (from main),
|
---|
| 206 | the contents are copied into a new array which is returned
|
---|
| 207 | from this routine.
|
---|
| 208 |
|
---|
| 209 | flag: Flag indicating how to expand wild-cards:
|
---|
| 210 | 0 - Complete file name expansion
|
---|
| 211 | 1 - only file name (no directory or version).
|
---|
| 212 | 2 - directory info and file name (no version).
|
---|
| 213 | 3 - file name and version info (no directory).
|
---|
| 214 | 4 - omit fields that are the same as RMS default.
|
---|
| 215 | -*/
|
---|
| 216 |
|
---|
| 217 | /* Local prototypes. */
|
---|
| 218 | int wild_found (char *string);
|
---|
| 219 | char **wild_expand (const char *string, char **argv, int *argc,
|
---|
| 220 | int extra, int flag);
|
---|
| 221 | /*
|
---|
| 222 | General note: removing the prototyping and const keywords should
|
---|
| 223 | allow this code to compile with VMS 'C' compilers prior to version
|
---|
| 224 | 2.3-024.
|
---|
| 225 | */
|
---|
| 226 |
|
---|
| 227 | char **expand (int *argc, const char *argv[], const int flag)
|
---|
| 228 | {
|
---|
| 229 | int i, nargc;
|
---|
| 230 | char **nargv;
|
---|
| 231 | char *s1;
|
---|
| 232 |
|
---|
| 233 | /* Get an initial amount of memory for the master nargv array. */
|
---|
| 234 | if ((nargv = (char **)malloc ((*argc+1) * sizeof (char *))) == NULL) {
|
---|
| 235 | fprintf (stderr, "Not enough memory to expand argument list\n");
|
---|
| 236 | exit (ErrorExit);
|
---|
| 237 | }
|
---|
| 238 | /* Copy the command name (0th argument), but only the name of the exe */
|
---|
| 239 | nargv[0] = strchr(argv[0],']');
|
---|
| 240 | if (nargv[0] != NULL) {
|
---|
| 241 | nargv[0]++;
|
---|
| 242 | if ((s1=strrchr(nargv[0],'.')) != NULL) *s1 = '\0';
|
---|
| 243 | } else {
|
---|
| 244 | nargv[0] = argv[0]; /* if nothing suitable take original */
|
---|
| 245 | }
|
---|
| 246 |
|
---|
| 247 | /* Copy all other arguments, expanding those that have wild characters. */
|
---|
| 248 | for (nargc = i = 1; i < *argc; i++) {
|
---|
| 249 | if (wild_found(argv[i]))
|
---|
| 250 | nargv = wild_expand(argv[i], nargv, &nargc, *argc-i, flag);
|
---|
| 251 | else
|
---|
| 252 | nargv[nargc++] = argv[i];
|
---|
| 253 | }
|
---|
| 254 | *argc = nargc;
|
---|
| 255 | nargv[nargc] = NULL; /* realloc always 0 fills, but... */
|
---|
| 256 |
|
---|
| 257 | return nargv;
|
---|
| 258 | }
|
---|
| 259 |
|
---|
| 260 | static int wild_found (char *string)
|
---|
| 261 | /*
|
---|
| 262 | Routine to search the given string for a VMS wild-card pattern.
|
---|
| 263 | Returns 1 if "*", "%", "[-", or "...]" is found. (This may not
|
---|
| 264 | be all VMS wild-cards but it is enough for now--anyone that wants
|
---|
| 265 | to recognize others can change this code.)
|
---|
| 266 |
|
---|
| 267 | Parameter:
|
---|
| 268 |
|
---|
| 269 | string: '\0' terminated character array.
|
---|
| 270 | */
|
---|
| 271 | {
|
---|
| 272 | int state = 0;
|
---|
| 273 |
|
---|
| 274 | /* State of 0 is "rest" state. State 1 on our way to [-, states 2-4
|
---|
| 275 | on our way to ...], negative states indicate the two quotes (' -10,
|
---|
| 276 | " -1).
|
---|
| 277 | */
|
---|
| 278 | for ( ;*string; string++) {
|
---|
| 279 | switch (*string) {
|
---|
| 280 | case '*':
|
---|
| 281 | case '%':
|
---|
| 282 | if (state >= 0)
|
---|
| 283 | return 1; /* Unquoted % or * found. */
|
---|
| 284 | break;
|
---|
| 285 | case '[':
|
---|
| 286 | if (state >= 0)
|
---|
| 287 | state = 1;
|
---|
| 288 | break;
|
---|
| 289 | case ']':
|
---|
| 290 | if (state == 4)
|
---|
| 291 | return 1; /* Unquoted ...] found. */
|
---|
| 292 | else if (state >= 0)
|
---|
| 293 | state = 0;
|
---|
| 294 | break;
|
---|
| 295 | case '-':
|
---|
| 296 | if (state == 1)
|
---|
| 297 | return 1; /* Unquoted [- found. */
|
---|
| 298 | else if (state >= 0)
|
---|
| 299 | state = 0;
|
---|
| 300 | break;
|
---|
| 301 | case '.':
|
---|
| 302 | if (state == 1 || state == 0)
|
---|
| 303 | state = 2; /* First '.' */
|
---|
| 304 | else if (state > 1 && state < 5)
|
---|
| 305 | state++; /* ... == states 2, 3, 4 */
|
---|
| 306 | else if (state >= 0)
|
---|
| 307 | state = 0;
|
---|
| 308 | break;
|
---|
| 309 | case '\'':
|
---|
| 310 | if (state <= -10)
|
---|
| 311 | state += 10; /* One ', possibly one " also */
|
---|
| 312 | else if (state < 0)
|
---|
| 313 | state -= 10; /* 0 ', possibly one " */
|
---|
| 314 | else
|
---|
| 315 | state = -10; /* No ' or " prior to this ' */
|
---|
| 316 | break;
|
---|
| 317 | case '"':
|
---|
| 318 | if (state == -11)
|
---|
| 319 | state = -10; /* Both " and ' prior to this. */
|
---|
| 320 | else if (state == -10)
|
---|
| 321 | state = -11; /* A ' prior to this. */
|
---|
| 322 | else if (state == -1)
|
---|
| 323 | state = 0; /* A " prior to this. */
|
---|
| 324 | else
|
---|
| 325 | state = -1; /* No ' or " prior to this " */
|
---|
| 326 | break;
|
---|
| 327 | case '\\':
|
---|
| 328 | string = strcpy(string, string+1);
|
---|
| 329 | state = 0;
|
---|
| 330 | break;
|
---|
| 331 | }
|
---|
| 332 | }
|
---|
| 333 | return 0;
|
---|
| 334 | }
|
---|
| 335 |
|
---|
| 336 |
|
---|
| 337 | static char **wild_expand(const char *wild, char **argv,
|
---|
| 338 | int *argc, int extra, int flag)
|
---|
| 339 | /*
|
---|
| 340 | Routine to expand wild into new arguments appended to the end
|
---|
| 341 | of argv[*argc]. This routine must realloc in order to make room
|
---|
| 342 | for the individual arguments and malloc for enough space for each
|
---|
| 343 | of the arguments. The return value is a new **argv.
|
---|
| 344 |
|
---|
| 345 | Parameters:
|
---|
| 346 |
|
---|
| 347 | wild: '\0' terminated string that needs to be expanded.
|
---|
| 348 |
|
---|
| 349 | argv: initial starting address of the argv array.
|
---|
| 350 |
|
---|
| 351 | argc: pointer to an integer that tells the current end of the
|
---|
| 352 | argument list.
|
---|
| 353 |
|
---|
| 354 | extra: The number of extra pointers that the returned argv
|
---|
| 355 | must have available for future assignments.
|
---|
| 356 |
|
---|
| 357 | flag: Flag indicating how to expand wild-card:
|
---|
| 358 | 0 - Complete file name expansion
|
---|
| 359 | 1 - only file name (no directory or version).
|
---|
| 360 | 2 - directory info and file name (no version)
|
---|
| 361 | 3 - file name and version info (no directory).
|
---|
| 362 | 4 - omit fields that are the same as RMS default.
|
---|
| 363 | */
|
---|
| 364 | {
|
---|
| 365 | int more_to_go = 1, err, length, status, len_wild, i, ddev_l, ddir_l;
|
---|
| 366 | char *namptr;
|
---|
| 367 | struct FAB fab_blk;
|
---|
| 368 | struct NAMBLK nam_blk;
|
---|
| 369 | char path[256];
|
---|
| 370 | char *ddevice = &path[0]; /* default device and directory */
|
---|
| 371 | char *ddirectory, *ppath;
|
---|
| 372 |
|
---|
| 373 | char *env = getenv("PATH");
|
---|
| 374 | ppath = &path[0];
|
---|
| 375 | while (*env) {
|
---|
| 376 | char *p = env++;
|
---|
| 377 | if ((*ppath++ = _toupper(*p)) == ':') {
|
---|
| 378 | ddev_l = ppath - &path[0];
|
---|
| 379 | *ppath++ = 0;
|
---|
| 380 | ddirectory = ppath;
|
---|
| 381 | }
|
---|
| 382 | }
|
---|
| 383 | *ppath++ = 0;
|
---|
| 384 | ddir_l = ppath - ddirectory - 1;
|
---|
| 385 | len_wild = strlen(wild);
|
---|
| 386 |
|
---|
| 387 | /* Initialize all the fab and nam fields needed for parse and search */
|
---|
| 388 |
|
---|
| 389 | fab_blk = cc$rms_fab; /* Initialize FAB structure */
|
---|
| 390 |
|
---|
| 391 | nam_blk.nam = cc$rms_nam; /* Initialize NAM structure */
|
---|
| 392 | fab_blk.fab$l_dna = ".*"; /* Default file specif. */
|
---|
| 393 | fab_blk.fab$b_dns = 2; /* Length of default spec. */
|
---|
| 394 | fab_blk.fab$l_nam = &nam_blk.nam; /* Set address of NAM in FAB*/
|
---|
| 395 | nam_blk.nam.nam$b_ess = NAM$C_MAXRSS; /* Set extended string size*/
|
---|
| 396 | nam_blk.nam.nam$l_esa = nam_blk.es; /* and address */
|
---|
| 397 | nam_blk.nam.nam$b_rss = NAM$C_MAXRSS; /* Set resultant string size*/
|
---|
| 398 | nam_blk.nam.nam$l_rsa = nam_blk.rs; /* and address */
|
---|
| 399 | nam_blk.nam.nam$l_rlf = NULL; /* No related file address */
|
---|
| 400 |
|
---|
| 401 | fab_blk.fab$l_fna = wild; /* Address of file name string */
|
---|
| 402 | fab_blk.fab$b_fns = len_wild; /* Length of file name string */
|
---|
| 403 |
|
---|
| 404 | /* Prepare to enter the search loop, parse fab. */
|
---|
| 405 | err = SYS$PARSE (&fab_blk);
|
---|
| 406 |
|
---|
| 407 | /* Catch the directory not found error and return no files found. */
|
---|
| 408 | if (err != RMS$_NORMAL)
|
---|
| 409 | exit(err);
|
---|
| 410 |
|
---|
| 411 | while (more_to_go) {
|
---|
| 412 | err = SYS$SEARCH (&fab_blk);
|
---|
| 413 | if (err == RMS$_NMF || err == RMS$_FNF)
|
---|
| 414 | more_to_go = 0; /* Done, no more files found */
|
---|
| 415 | else if (err != RMS$_NORMAL)
|
---|
| 416 | exit (err);
|
---|
| 417 | else {
|
---|
| 418 | /* Count that we now have this many arguments. */
|
---|
| 419 | (*argc)++;
|
---|
| 420 |
|
---|
| 421 | /* Make sure there is room for a new pointer. */
|
---|
| 422 | if ((argv = realloc (argv, (*argc + extra)*sizeof(char *))) == NULL) {
|
---|
| 423 | fprintf (stderr, "Not enough memory to expand argument list\n");
|
---|
| 424 | exit(ErrorExit);
|
---|
| 425 | }
|
---|
| 426 |
|
---|
| 427 | /* Move the right name into the list. */
|
---|
| 428 | switch (flag) {
|
---|
| 429 | case 0: /* Complete file name */
|
---|
| 430 | length = nam_blk.nam.nam$b_rsl;
|
---|
| 431 | namptr = nam_blk.rs;
|
---|
| 432 | break;
|
---|
| 433 | case 1: /* File name only (no directory or version). */
|
---|
| 434 | length = nam_blk.nam.nam$b_name + nam_blk.nam.nam$b_type;
|
---|
| 435 | namptr = nam_blk.nam.nam$l_name;
|
---|
| 436 | break;
|
---|
| 437 | case 2: /* directory and file name (no version) */
|
---|
| 438 | length = nam_blk.nam.nam$b_rsl - nam_blk.nam.nam$b_ver;
|
---|
| 439 | namptr = nam_blk.rs;
|
---|
| 440 | break;
|
---|
| 441 | case 3: /* File name and version (no directory). */
|
---|
| 442 | length = nam_blk.nam.nam$b_name +
|
---|
| 443 | nam_blk.nam.nam$b_type +
|
---|
| 444 | nam_blk.nam.nam$b_ver;
|
---|
| 445 | namptr = nam_blk.nam.nam$l_name;
|
---|
| 446 | break;
|
---|
| 447 | case 4: /* Remove redundant fields, no version */
|
---|
| 448 | length = nam_blk.nam.nam$b_rsl - nam_blk.nam.nam$b_ver;
|
---|
| 449 | namptr = nam_blk.rs;
|
---|
| 450 | if ((nam_blk.nam.nam$b_dev==ddev_l) &&
|
---|
| 451 | !strncmp(namptr, ddevice, nam_blk.nam.nam$b_dev)) {
|
---|
| 452 | length -= nam_blk.nam.nam$b_dev;
|
---|
| 453 | namptr += nam_blk.nam.nam$b_dev;
|
---|
| 454 | if ((nam_blk.nam.nam$b_dir==ddir_l) &&
|
---|
| 455 | !strncmp(namptr, ddirectory, nam_blk.nam.nam$b_dir)) {
|
---|
| 456 | length -= nam_blk.nam.nam$b_dir;
|
---|
| 457 | namptr += nam_blk.nam.nam$b_dir;
|
---|
| 458 | }
|
---|
| 459 | }
|
---|
| 460 | break;
|
---|
| 461 | default:
|
---|
| 462 | fprintf (stderr, "illegal flag used in VMS expand call\n");
|
---|
| 463 | exit (ErrorExit);
|
---|
| 464 | } /* end of switch */
|
---|
| 465 | /* Copy the requested string into the argument array. */
|
---|
| 466 | if ((argv[*argc-1] = malloc (length+1)) == NULL) {
|
---|
| 467 | fprintf (stderr, "Not enough memory to expand argument list\n");
|
---|
| 468 | exit (ErrorExit);
|
---|
| 469 | }
|
---|
| 470 | /* Copy the string, translate to lower case */
|
---|
| 471 | /* strncpy (argv[*argc-1], namptr, length); */
|
---|
| 472 | for (i=0; i<length; i++) {
|
---|
| 473 | argv[*argc-1][i] = _tolower(*namptr);
|
---|
| 474 | namptr++;
|
---|
| 475 | }
|
---|
| 476 | /* End of modification */
|
---|
| 477 | argv[*argc-1][length] = '\0';
|
---|
| 478 | }
|
---|
| 479 | } /* end while (more_to_go) */
|
---|
| 480 | return (argv);
|
---|
| 481 | }
|
---|
| 482 |
|
---|
| 483 | /* Remove all the defines that might affect the user's code. */
|
---|
| 484 |
|
---|
| 485 | #undef redirect
|
---|
| 486 | #undef filearg
|
---|
| 487 | #undef expand
|
---|
| 488 | #undef wild_found
|
---|
| 489 | #undef wild_expand
|
---|
| 490 |
|
---|
| 491 | #if 0
|
---|
| 492 | /* ------------------------ ECHO sample code ------------------------ */
|
---|
| 493 |
|
---|
| 494 | #include <stdio.h>
|
---|
| 495 | /* here come the 3 lines that make this Unix program into a VMS one: */
|
---|
| 496 | #ifdef VMS
|
---|
| 497 | #include <redexp.vms>
|
---|
| 498 | #endif
|
---|
| 499 |
|
---|
| 500 | /*
|
---|
| 501 | This main program allows you to run experiments with redexp.vms.
|
---|
| 502 | Try $ echo *.*, $ echo -f1 [-...]*.*, $ echo -f[0-3] *.*.
|
---|
| 503 | Questions about using "%", "\", etc. may be answered by testing
|
---|
| 504 | with this version of echo.
|
---|
| 505 |
|
---|
| 506 | To use this, cut from the "#if 0" above up to the last #endif,
|
---|
| 507 | and put the text in echo.c. Assuming you have defined VAXC$INCLUDE
|
---|
| 508 | to also look in the directory where you put redexp.VMS, you should
|
---|
| 509 | be able to compile and link echo. Define a symbol echo as
|
---|
| 510 | echo :== $sys$disk:[]echo
|
---|
| 511 | and you are ready to run.
|
---|
| 512 |
|
---|
| 513 | */
|
---|
| 514 | main(argc, argv)
|
---|
| 515 | int argc;
|
---|
| 516 | char *argv[];
|
---|
| 517 | {
|
---|
| 518 | int i = 0;
|
---|
| 519 |
|
---|
| 520 | while (i < argc) {
|
---|
| 521 | printf("argv[%d]: %s\n", i, argv[i]);
|
---|
| 522 | i++;
|
---|
| 523 | }
|
---|
| 524 | }
|
---|
| 525 | /* ------------------------ ECHO sample code end --------------------- */
|
---|
| 526 | #endif /* if 0 */
|
---|