diff options
Diffstat (limited to 'vms/filutils.c')
-rw-r--r-- | vms/filutils.c | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/vms/filutils.c b/vms/filutils.c new file mode 100644 index 0000000..8cae5f7 --- /dev/null +++ b/vms/filutils.c @@ -0,0 +1,321 @@ +/* + * Copyright © 1994 the Free Software Foundation, Inc. + * + * Author: Richard Levitte (levitte@e.kth.se) + * + * This file is a part of GNU VMSLIB, the GNU library for porting GNU + * software to VMS. + * + * GNU VMSLIB is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNU VMSLIB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <string.h> +#include <file.h> +#include <rmsdef.h> +#include <fab.h> +#include <nam.h> +#include <stdlib.h> +#include <lib$routines.h> +#include <descrip.h> +#include "filutils.h" + +/* file_name_as_directory was snarfed from src/fileio.c in GNU Emacs. */ + +char * +file_name_as_directory (out, in) + char *out, *in; +{ + int size = strlen (in) - 1; + int ext_point = 0; + + strcpy (out, in); + + /* Is it already a directory string? */ + if (in[size] == ':' || in[size] == ']' || in[size] == '>') + return out; + /* Is it a VMS directory file name? If so, hack VMS syntax. */ + else + if (! strchr (in, '/')) + { + ext_point = 1; + if (size > 3 && (! strcmp (&in[size - 3], ".DIR") + || ! strcmp (&in[size - 3], ".dir"))) + ext_point = -3; + else + if (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4) + || ! strncmp (&in[size - 5], ".dir", 4)) + && (in[size - 1] == '.' || in[size - 1] == ';') + && in[size] == '1') + ext_point = -5; + } + if (ext_point != 0) + { + register char *p, *dot; + char brack; + + /* dir:[000000]x.dir --> dir:x.dir --> dir:[x] + dir:[000000.x]y.dir --> dir:[x]y.dir --> dir:[x.y] + but dir:[000000.000000]x.dir --> dir:[000000.000000.x] + dir:[000000.000000.x]y.dir --> dir:[000000.000000.x.y] */ + static char tem[256]; + + p = dot = strchr(in,':'); + if (p != 0 && (p[1] == '[' || p[1] == '<')) + { + p += 2; + if (strncmp(p,"000000",6) == 0) + { + p += 6; + if (strncmp(p,".000000",7) != 0 + && (*p == ']' || *p == '>' || *p == '.')) + { + size = dot - in + 1; + strncpy(tem, in, size); + if (*p == '.') + tem[size++] = '['; + strcpy(tem + size, p + 1); + in = tem; + size = strlen(in) - 1; + } + } + } + /* x.dir -> [.x] + dir:x.dir --> dir:[x] + dir:[x]y.dir --> dir:[x.y] */ + p = in + size; + while (p != in && *p != ':' && *p != '>' && *p != ']') p--; + { + char *emergency_dir = 0; + int emergency_point = 0; /* relative to the end of `out' */ + + if (p != in) + { + strncpy (out, in, p - in); + out[p - in] = '\0'; + if (*p == ':') + { + brack = ']'; + strcat (out, ":["); + emergency_dir = "000000"; + emergency_point = 0; + } + else + { + brack = *p; + strcat (out, "."); + emergency_dir = ""; + emergency_point = -1; + } + p++; + } + else + { + brack = ']'; + strcpy (out, "[."); + emergency_dir = ""; + emergency_point = -2; + } + if (strncmp (p, "000000.", 7) == 0 + && (strncmp (p+7, "000000", 6) != 0 + || (p[13] != ']' && p[13] != '>' && p[13] != '.'))) + p += 7; + if (p < (in + size + ext_point)) + { + register copy_len = ((in + size + ext_point) - p); + size = strlen (out) + copy_len; + strncat (out, p, copy_len); + } + else + { + size = strlen (out) + emergency_point; + strcpy (out + size, emergency_dir); + size += strlen (emergency_dir); + } + } + out[size++] = brack; + out[size] = '\0'; + } + return out; +} + +/* + * Convert from directory name to filename. + * On VMS: + * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1 + * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1 + * On UNIX, it's simple: just make sure there is a terminating / + + * Value is nonzero if the string output is different from the input. + */ + +/* directory_file_name was snarfed from src/fileio.c in GNU Emacs. */ + +#include <stdio.h> +directory_file_name (src, dst) + char *src, *dst; +{ + long slen; + long rlen; + char * ptr, * rptr; + char bracket; + struct FAB fab = cc$rms_fab; + struct NAM nam = cc$rms_nam; + char esa[NAM$C_MAXRSS]; + + slen = strlen (src); + + if (! strchr (src, '/') + && (src[slen - 1] == ']' + || src[slen - 1] == ':' + || src[slen - 1] == '>')) + { + /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */ + fab.fab$l_fna = src; + fab.fab$b_fns = slen; + fab.fab$l_nam = &nam; + fab.fab$l_fop = FAB$M_NAM; + + nam.nam$l_esa = esa; + nam.nam$b_ess = sizeof esa; + nam.nam$b_nop |= NAM$M_SYNCHK; + + /* We call SYS$PARSE to handle such things as [--] for us. */ + if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL) + { + slen = nam.nam$b_esl; + if (esa[slen - 1] == ';' && esa[slen - 2] == '.') + slen -= 2; + esa[slen] = '\0'; + src = esa; + } + if (src[slen - 1] != ']' && src[slen - 1] != '>') + { + /* what about when we have logical_name:???? */ + if (src[slen - 1] == ':') + { /* Xlate logical name and see what we get */ + ptr = strcpy (dst, src); /* upper case for getenv */ + while (*ptr) + { + if ('a' <= *ptr && *ptr <= 'z') + *ptr -= 040; + ptr++; + } + dst[slen - 1] = 0; /* remove colon */ + if (!(src = getenv (dst))) + return 0; + /* should we jump to the beginning of this procedure? + Good points: allows us to use logical names that xlate + to Unix names, + Bad points: can be a problem if we just translated to a device + name... + For now, I'll punt and always expect VMS names, and hope for + the best! */ + slen = strlen (src); + if (src[slen - 1] != ']' && src[slen - 1] != '>') + { /* no recursion here! */ + strcpy (dst, src); + return 0; + } + } + else + { /* not a directory spec */ + strcpy (dst, src); + return 0; + } + } + bracket = src[slen - 1]; + + /* If bracket is ']' or '>', bracket - 2 is the corresponding + opening bracket. */ + ptr = strchr (src, bracket - 2); + if (ptr == 0) + { /* no opening bracket */ + strcpy (dst, src); + return 0; + } + if (!(rptr = strrchr (src, '.'))) + rptr = ptr; + slen = rptr - src; + strncpy (dst, src, slen); + dst[slen] = '\0'; +#if 0 + fprintf (stderr, "dst = \"%s\"\nsrc = \"%s\"\nslen = %d\n", + dst, src, slen); +#endif + if (*rptr == '.') + { + dst[slen++] = bracket; + dst[slen] = '\0'; + } + else + { + /* If we have the top-level of a rooted directory (i.e. xx:[000000]), + then translate the device and recurse. */ + if (dst[slen - 1] == ':' + && dst[slen - 2] != ':' /* skip decnet nodes */ + && ((src[slen] == '[' + && strcmp(src + slen + 1, "000000]") == 0) + || src[slen] == '<' + && strcmp(src + slen + 1, "000000>") == 0)) + { + static char equiv_buf[256]; + static struct dsc$descriptor_s equiv + = {sizeof (equiv_buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, equiv_buf}; + static struct dsc$descriptor_s d_name + = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; + short eqlen; + + dst[slen - 1] = '\0'; + d_name.dsc$w_length = strlen (dst); + d_name.dsc$a_pointer = dst; + if (LIB$SYS_TRNLOG (&d_name, &eqlen, &equiv) == 1 + && (equiv_buf[eqlen] = '\0', ptr = equiv_buf) != 0 + && (rlen = strlen (ptr) - 1) > 0 + && (ptr[rlen] == ']' || ptr[rlen] == '>') + && ptr[rlen - 1] == '.') + { + char * buf = (char *) xmalloc (strlen (ptr) + 1); + int tmp = ptr[rlen]; + if (buf == 0) + return 0; /* bad luck */ + strcpy (buf, ptr); + buf[rlen - 1] = tmp; + buf[rlen] = '\0'; + tmp = directory_file_name (buf, dst); + free (buf); + return tmp; + } + else + dst[slen - 1] = ':'; + } + strcat (dst, "[000000]"); + slen += 8; + } + rptr++; + rlen = strlen (rptr) - 1; + strncat (dst, rptr, rlen); + dst[slen + rlen] = '\0'; + strcat (dst, ".DIR.1"); + return 1; + } + + /* Process as Unix format: just remove any final slash. + But leave "/" unchanged; do not change it to "". */ + strcpy (dst, src); + if (slen > 1 && dst[slen - 1] == '/') + { + dst[slen - 1] = 0; + return 1; + } + return 0; +} + +/* end of snarf. */ |