diff options
author | Roland McGrath <roland@redhat.com> | 1996-03-20 14:57:41 +0000 |
---|---|---|
committer | Roland McGrath <roland@redhat.com> | 1996-03-20 14:57:41 +0000 |
commit | 9e443adaf679b071fb3319cfc3259e322dcb6e57 (patch) | |
tree | a84a507d09be97fb0932bb661139921a59db71bd /vmsify.c | |
parent | dfefc77263fe835ae12b3ee27cc3ed9b084311c1 (diff) | |
download | gunmake-9e443adaf679b071fb3319cfc3259e322dcb6e57.tar.gz |
Tue Mar 19 20:21:34 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu>
Merged VMS port from Klaus Kaempf <kkaempf@didymus.rmi.de>.
* make.h (PARAMS): New macro.
* config.h-vms: New file.
* makefile.com: New file.
* makefile.vms: New file.
* readme.vms: New file.
* vmsdir.h: New file.
* vmsfunctions.c: New file.
* vmsify.c: New file.
* file.h: Renamed to filedef.h to avoid conflict with VMS system hdr.
* ar.c: Added prototypes and changes for VMS.
* commands.c: Likewise.
* commands.h: Likewise.
* default.c: Likewise.
* dep.h: Likewise.
* dir.c: Likewise.
* expand.c: Likewise.
* file.c: Likewise.
* function.c: Likewise.
* implicit.c: Likewise.
* job.c: Likewise.
* job.h: Likewise.
* main.c: Likewise.
* make.h: Likewise.
* misc.c: Likewise.
* read.c: Likewise.
* remake.c: Likewise.
* remote-stub.c: Likewise.
* rule.c: Likewise.
* rule.h: Likewise.
* variable.c: Likewise.
* variable.h: Likewise.
* vpath.c: Likewise.
* compatMakefile (srcs): Rename file.h to filedef.h.
Diffstat (limited to 'vmsify.c')
-rw-r--r-- | vmsify.c | 925 |
1 files changed, 925 insertions, 0 deletions
diff --git a/vmsify.c b/vmsify.c new file mode 100644 index 0000000..7d1fa6f --- /dev/null +++ b/vmsify.c @@ -0,0 +1,925 @@ +/* + vmsify.c + + Module for vms <-> unix file name conversion + + Written by Klaus Kämpf (kkaempf@didymus.rmi.de) + +*/ + +#include <string.h> +#include <ctype.h> + +#if VMS +#include <unixlib.h> +#include <stdlib.h> +#include <jpidef.h> +#include <descrip.h> +#include <uaidef.h> +#include <ssdef.h> +#include <starlet.h> +#include <lib$routines.h> +/* Initialize a string descriptor (struct dsc$descriptor_s) for an + arbitrary string. ADDR is a pointer to the first character + of the string, and LEN is the length of the string. */ + +#define INIT_DSC_S(dsc, addr, len) do { \ + (dsc).dsc$b_dtype = DSC$K_DTYPE_T; \ + (dsc).dsc$b_class = DSC$K_CLASS_S; \ + (dsc).dsc$w_length = (len); \ + (dsc).dsc$a_pointer = (addr); \ +} while (0) + +/* Initialize a string descriptor (struct dsc$descriptor_s) for a + NUL-terminated string. S is a pointer to the string; the length + is determined by calling strlen(). */ + +#define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s)) +#endif + +/* + copy 'from' to 'to' up to but not including 'upto' + return 0 if eos on from + return 1 if upto found + + return 'to' at last char + 1 + return 'from' at match + 1 or eos if no match + + if as_dir == 1, change all '.' to '_' + else change all '.' but the last to '_' +*/ + +static int +copyto (char **to, char **from, char upto, int as_dir) +{ + char *s; + + s = strrchr (*from, '.'); + + while (**from) + { + if (**from == upto) + { + do + { + (*from)++; + } + while (**from == upto); + return 1; + } + if (**from == '.') + { + if ((as_dir == 1) + || (*from != s)) + **to = '_'; + else + **to = '.'; + } + else + { + if (islower (**from)) + **to = toupper (**from); + else + **to = **from; + } + (*to)++; + (*from)++; + } + + return 0; +} + + +/* + get translation of logical name + +*/ + +static char * +trnlog (char *name) +{ + int stat; + static char reslt[1024]; + $DESCRIPTOR (reslt_dsc, reslt); + short resltlen; + struct dsc$descriptor_s name_dsc; + char *s; + + INIT_DSC_CSTRING (name_dsc, name); + + stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc); + + if ((stat&1) == 0) + { + return ""; + } + if (stat == SS$_NOTRAN) + { + return ""; + } + reslt[resltlen] = '\0'; + + s = (char *)malloc (resltlen+1); + if (s == 0) + return ""; + strcpy (s, reslt); + return s; +} + +enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE }; + +/* + convert unix style name to vms style + type = 0 -> name is a full name (directory and filename part) + type = 1 -> name is a directory + type = 2 -> name is a filename without directory + + The following conversions are applied + (0) (1) (2) + input full name dir name file name + +1 ./ <cwd> [] <current directory>.dir +2 ../ <home of cwd> <home of cwd> <home of cwd>.dir + +3 // <dev of cwd>: <dev of cwd>:[000000] <dev of cwd>:000000.dir +4 //a a: a: a: +5 //a/ a: a: a:000000.dir + +9 / [000000] [000000] 000000.dir +10 /a [000000]a [a] [000000]a +11 /a/ [a] [a] [000000]a.dir +12 /a/b [a]b [a.b] [a]b +13 /a/b/ [a.b] [a.b] [a]b.dir +14 /a/b/c [a.b]c [a.b.c] [a.b]c +15 /a/b/c/ [a.b.c] [a.b.c] [a.b]c.dir + +16 a a [.a] a +17 a/ [.a] [.a] a.dir +18 a/b [.a]b [.a.b] [.a]b +19 a/b/ [.a.b] [.a.b] [.a]b.dir +20 a/b/c [.a.b]c [.a.b.c] [.a.b]c +21 a/b/c/ [.a.b.c] [.a.b.c] [.a.b]c.dir + +22 a.b.c a_b.c [.a_b_c] a_b_c.dir + +23 [x][y]z [x.y]z [x.y]z [x.y]z +24 [x][.y]z [x.y]z [x.y]z [x.y]z + +25 filenames with '$' are left unchanged if they contain no '/' +25 filenames with ':' are left unchanged +26 filenames with a single pair of '[' ']' are left unchanged + + the input string is not written to +*/ + +char * +vmsify (name, type) + char *name; + int type; +{ +/* max 255 device + max 39 directory + max 39 filename + max 39 filetype + max 5 version +*/ +#define MAXPATHLEN 512 + + enum namestate nstate; + static char vmsname[MAXPATHLEN+1]; + char *fptr; + char *vptr; + char *s,*s1; + int as_dir; + int count; + + if (name == 0) + return 0; + fptr = name; + vptr = vmsname; + nstate = N_START; + + /* case 25a */ + + s = strpbrk (name, "$:"); + if (s != 0) + { + if (*s == '$') + { + if (strchr (name, '/') == 0) + { + return name; + } + } + else + { + return name; + } + } + + /* case 26 */ + + s = strchr (name, '['); + + if (s != 0) + { + s1 = strchr (s+1, '['); + if (s1 == 0) + { + return name; /* single [, keep unchanged */ + } + s1--; + if (*s1 != ']') + { + return name; /* not ][, keep unchanged */ + } + + /* we have ][ */ + + s = name; + + /* s -> starting char + s1 -> ending ']' */ + + do + { + strncpy (vptr, s, s1-s); /* copy up to but not including ']' */ + vptr += s1-s; + if (*s1 == 0) + break; + s = s1 + 1; /* s -> char behind ']' */ + if (*s != '[') /* was '][' ? */ + break; /* no, last ] found, exit */ + s++; + if (*s != '.') + *vptr++ = '.'; + s1 = strchr (s, ']'); + if (s1 == 0) /* no closing ] */ + s1 = s + strlen (s); + } + while (1); + + *vptr++ = ']'; + + fptr = s; + + } + + else /* no [ in name */ + + { + + int state; + int rooted = 1; /* flag if logical is rooted, else insert [000000] */ + + state = 0; + + do + { + + switch (state) + { + case 0: /* start of loop */ + if (*fptr == '/') + { + fptr++; + state = 1; + } + else if (*fptr == '.') + { + fptr++; + state = 10; + } + else + state = 2; + break; + + case 1: /* '/' at start */ + if (*fptr == '/') + { + fptr++; + state = 3; + } + else + state = 4; + break; + + case 2: /* no '/' at start */ + s = strchr (fptr, '/'); + if (s == 0) /* no '/' (16) */ + { + if (type == 1) + { + strcpy (vptr, "[."); + vptr += 2; + } + copyto (&vptr, &fptr, 0, (type==1)); + if (type == 1) + *vptr++ = ']'; + state = -1; + } + else /* found '/' (17..21) */ + { + if ((type == 2) + && (*(s+1) == 0)) /* 17(2) */ + { + copyto (&vptr, &fptr, '/', 1); + state = 7; + } + else + { + strcpy (vptr, "[."); + nstate = N_DOT; + vptr += 2; + copyto (&vptr, &fptr, '/', 1); + state = 9; + } + } + break; + + case 3: /* '//' at start */ + while (*fptr == '/') /* collapse all '/' */ + fptr++; + if (*fptr == 0) /* just // */ + { + char cwdbuf[MAXPATHLEN+1]; + + s1 = getcwd(cwdbuf, MAXPATHLEN); + if (s1 == 0) + { + return ""; /* FIXME, err getcwd */ + } + s = strchr (s1, ':'); + if (s == 0) + { + return ""; /* FIXME, err no device */ + } + strncpy (vptr, s1, s-s1+1); + vptr += s-s1+1; + state = -1; + break; + } + + s = vptr; + + if (copyto (&vptr, &fptr, '/', 1) == 0) /* copy device part */ + { + *vptr++ = ':'; + state = -1; + break; + } + *vptr = ':'; + nstate = N_DEVICE; + if (*fptr == 0) /* just '//a/' */ + { + strcpy (vptr+1, "[000000]"); + vptr += 9; + state = -1; + break; + } + *vptr = 0; + /* check logical for [000000] insertion */ + s1 = trnlog (s); + if (*s1 != 0) + { /* found translation */ + char *s2; + for (;;) /* loop over all nested logicals */ + { + s2 = s1 + strlen (s1) - 1; + if (*s2 == ':') /* translation ends in ':' */ + { + s2 = trnlog (s1); + free (s1); + if (*s2 == 0) + { + rooted = 0; + break; + } + s1 = s2; + continue; /* next iteration */ + } + if (*s2 == ']') /* translation ends in ']' */ + { + if (*(s2-1) == '.') /* ends in '.]' */ + { + if (strncmp (fptr, "000000", 6) != 0) + rooted = 0; + } + else + { + strcpy (vmsname, s1); + s = strchr (vmsname, ']'); + *s = '.'; + nstate = N_DOT; + vptr = s; + } + } + break; + } + free (s1); + } + else + rooted = 0; + + if (*vptr == 0) + { + nstate = N_DEVICE; + *vptr++ = ':'; + } + else + vptr++; + + if (rooted == 0) + { + strcpy (vptr, "[000000."); + vptr += 8; + s1 = vptr-1; + nstate = N_DOT; + } + else + s1 = 0; + + /* s1-> '.' after 000000 or NULL */ + + s = strchr (fptr, '/'); + if (s == 0) + { /* no next '/' */ + if (*(vptr-1) == '.') + *(vptr-1) = ']'; + else if (rooted == 0) + *vptr++ = ']'; + copyto (&vptr, &fptr, 0, (type == 1)); + state = -1; + break; + } + else + { + while (*(s+1) == '/') /* skip multiple '/' */ + s++; + } + + if ((rooted != 0) + && (*(vptr-1) != '.')) + { + *vptr++ = '['; + nstate = N_DOT; + } + else + if ((nstate == N_DOT) + && (s1 != 0) + && (*(s+1) == 0)) + { + if (type == 2) + { + *s1 = ']'; + nstate = N_CLOSED; + } + } + state = 9; + break; + + case 4: /* single '/' at start (9..15) */ + if (*fptr == 0) + state = 5; + else + state = 6; + break; + + case 5: /* just '/' at start (9) */ + if (type != 2) + { + *vptr++ = '['; + nstate = N_OPEN; + } + strcpy (vptr, "000000"); + vptr += 6; + if (type == 2) + state = 7; + else + state = 8; + break; + + case 6: /* chars following '/' at start 10..15 */ + *vptr++ = '['; + nstate = N_OPEN; + s = strchr (fptr, '/'); + if (s == 0) /* 10 */ + { + if (type != 1) + { + strcpy (vptr, "000000]"); + vptr += 7; + } + copyto (&vptr, &fptr, 0, (type == 1)); + if (type == 1) + { + *vptr++ = ']'; + } + state = -1; + } + else /* 11..15 */ + { + if ( (type == 2) + && (*(s+1) == 0)) /* 11(2) */ + { + strcpy (vptr, "000000]"); + nstate = N_CLOSED; + vptr += 7; + } + copyto (&vptr, &fptr, '/', (*(vptr-1) != ']')); + state = 9; + } + break; + + case 7: /* add '.dir' and exit */ + if ((nstate == N_OPEN) + || (nstate == N_DOT)) + { + s = vptr-1; + while (s > vmsname) + { + if (*s == ']') + { + break; + } + if (*s == '.') + { + *s = ']'; + break; + } + s--; + } + } + strcpy (vptr, ".dir"); + vptr += 4; + state = -1; + break; + + case 8: /* add ']' and exit */ + *vptr++ = ']'; + state = -1; + break; + + case 9: /* 17..21, fptr -> 1st '/' + 1 */ + if (*fptr == 0) + { + if (type == 2) + { + state = 7; + } + else + state = 8; + break; + } + s = strchr (fptr, '/'); + if (s == 0) + { + if (type != 1) + { + if (nstate == N_OPEN) + { + *vptr++ = ']'; + nstate = N_CLOSED; + } + as_dir = 0; + } + else + { + if (nstate == N_OPEN) + { + *vptr++ = '.'; + nstate = N_DOT; + } + as_dir = 1; + } + } + else + { + while (*(s+1) == '/') + s++; + if ( (type == 2) + && (*(s+1) == 0)) /* 19(2), 21(2)*/ + { + if (nstate != N_CLOSED) + { + *vptr++ = ']'; + nstate = N_CLOSED; + } + as_dir = 1; + } + else + { + if (nstate == N_OPEN) + { + *vptr++ = '.'; + nstate = N_DOT; + } + as_dir = 1; + } + } + if ( (*fptr == '.') /* check for '..' or '../' */ + && (*(fptr+1) == '.') + && ((*(fptr+2) == '/') + || (*(fptr+2) == 0)) ) + { + fptr += 2; + if (*fptr == '/') + { + do + { + fptr++; + } + while (*fptr == '/'); + } + else if (*fptr == 0) + type = 1; + vptr--; /* vptr -> '.' or ']' */ + s1 = vptr; + for (;;) + { + s1--; + if (*s1 == '.') /* one back */ + { + vptr = s1; + nstate = N_OPEN; + break; + } + if (*s1 == '[') /* top level reached */ + { + if (*fptr == 0) + { + strcpy (s1, "[000000]"); + vptr = s1 + 8; + nstate = N_CLOSED; + s = 0; + break; + } + else + { + vptr = s1+1; + nstate = N_OPEN; + break; + } + } + } + } + else + { + copyto (&vptr, &fptr, '/', as_dir); + if (nstate == N_DOT) + nstate = N_OPEN; + } + if (s == 0) + { /* 18,20 */ + if (type == 1) + *vptr++ = ']'; + state = -1; + } + else + { + if (*(s+1) == 0) + { + if (type == 2) /* 19,21 */ + { + state = 7; + } + else + { + *vptr++ = ']'; + state = -1; + } + } + } + break; + + case 10: /* 1,2 first is '.' */ + if (*fptr == '.') + { + fptr++; + state = 11; + } + else + state = 12; + break; + + case 11: /* 2, '..' at start */ + count = 1; + if (*fptr != 0) + { + if (*fptr != '/') /* got ..xxx */ + { + return name; + } + do /* got ../ */ + { + fptr++; + while (*fptr == '/') fptr++; + if (*fptr != '.') + break; + if (*(fptr+1) != '.') + break; + fptr += 2; + if ((*fptr == 0) + || (*fptr == '/')) + count++; + } + while (*fptr == '/'); + } + { /* got '..' or '../' */ + char cwdbuf[MAXPATHLEN+1]; + + s1 = getcwd(cwdbuf, MAXPATHLEN); + if (s1 == 0) + { + return ""; /* FIXME, err getcwd */ + } + strcpy (vptr, s1); + s = strchr (vptr, ']'); + if (s != 0) + { + while (s > vptr) + { + s--; + if (*s == '[') + { + s++; + strcpy (s, "000000]"); + state = -1; + break; + } + else if (*s == '.') + { + if (--count == 0) + { + if (*fptr == 0) /* had '..' or '../' */ + { + *s++ = ']'; + state = -1; + } + else /* had '../xxx' */ + { + state = 9; + } + *s = 0; + break; + } + } + } + } + vptr += strlen (vptr); + } + break; + + case 12: /* 1, '.' at start */ + if (*fptr != 0) + { + if (*fptr != '/') + { + return name; + } + fptr++; + } + + { + char cwdbuf[MAXPATHLEN+1]; + + s1 = getcwd(cwdbuf, MAXPATHLEN); + if (s1 == 0) + { + return ""; /*FIXME, err getcwd */ + } + strcpy (vptr, s1); + if (*fptr == 0) + { + state = -1; + break; + } + else + { + s = strchr (vptr, ']'); + if (s == 0) + { + state = -1; + break; + } + *s = 0; + nstate = N_OPEN; + vptr += strlen (vptr); + state = 9; + } + } + break; + } + + } + while (state > 0); + + + } + + + /* directory conversion done + fptr -> filename part of input string + vptr -> free space in vmsname + */ + + *vptr++ = 0; + + return vmsname; +} + + + +/* + convert from vms-style to unix-style + + dev:[dir1.dir2] //dev/dir1/dir2/ +*/ + +char * +unixify (char *name) +{ + static char piece[512]; + char *s, *p; + + if (strchr (name, '/') != 0) /* already in unix style */ + return name; + + p = piece; + *p = 0; + + /* device part */ + + s = strchr (name, ':'); + + if (s != 0) + { + *s = 0; + *p++ = '/'; + *p++ = '/'; + strcpy (p, name); + p += strlen (p); + *s = ':'; + } + + /* directory part */ + + *p++ = '/'; + s = strchr (name, '['); + + if (s != 0) + { + s++; + switch (*s) + { + case ']': /* [] */ + strcat (p, "./"); + break; + case '-': /* [- */ + strcat (p, "../"); + break; + case '.': + strcat (p, "./"); /* [. */ + break; + default: + s--; + break; + } + s++; + while (*s) + { + if (*s == '.') + *p++ = '/'; + else + *p++ = *s; + s++; + if (*s == ']') + { + s++; + break; + } + } + if (*s != 0) /* more after ']' ?? */ + { + if (*(p-1) != '/') + *p++ = '/'; + strcpy (p, s); /* copy it anyway */ + } + } + + else /* no '[' anywhere */ + + { + *p++ = 0; + } + + /* force end with '/' */ + + if (*(p-1) != '/') + *p++ = '/'; + *p = 0; + + return piece; +} + +/* EOF */ |