1*69606e3fSchristos /* vmsify.c -- Module for vms <-> unix file name conversion
2*69606e3fSchristos Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3*69606e3fSchristos 2006 Free Software Foundation, Inc.
4*69606e3fSchristos This file is part of GNU Make.
5*69606e3fSchristos
6*69606e3fSchristos GNU Make is free software; you can redistribute it and/or modify it under the
7*69606e3fSchristos terms of the GNU General Public License as published by the Free Software
8*69606e3fSchristos Foundation; either version 2, or (at your option) any later version.
9*69606e3fSchristos
10*69606e3fSchristos GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11*69606e3fSchristos WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12*69606e3fSchristos A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13*69606e3fSchristos
14*69606e3fSchristos You should have received a copy of the GNU General Public License along with
15*69606e3fSchristos GNU Make; see the file COPYING. If not, write to the Free Software
16*69606e3fSchristos Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */
17*69606e3fSchristos
18*69606e3fSchristos /* Written by Klaus K�mpf (kkaempf@progis.de)
19*69606e3fSchristos of proGIS Software, Aachen, Germany */
20*69606e3fSchristos
21*69606e3fSchristos
22*69606e3fSchristos #include <stdio.h>
23*69606e3fSchristos #include <string.h>
24*69606e3fSchristos #include <ctype.h>
25*69606e3fSchristos
26*69606e3fSchristos #if VMS
27*69606e3fSchristos #include <unixlib.h>
28*69606e3fSchristos #include <stdlib.h>
29*69606e3fSchristos #include <jpidef.h>
30*69606e3fSchristos #include <descrip.h>
31*69606e3fSchristos #include <uaidef.h>
32*69606e3fSchristos #include <ssdef.h>
33*69606e3fSchristos #include <starlet.h>
34*69606e3fSchristos #include <lib$routines.h>
35*69606e3fSchristos /* Initialize a string descriptor (struct dsc$descriptor_s) for an
36*69606e3fSchristos arbitrary string. ADDR is a pointer to the first character
37*69606e3fSchristos of the string, and LEN is the length of the string. */
38*69606e3fSchristos
39*69606e3fSchristos #define INIT_DSC_S(dsc, addr, len) do { \
40*69606e3fSchristos (dsc).dsc$b_dtype = DSC$K_DTYPE_T; \
41*69606e3fSchristos (dsc).dsc$b_class = DSC$K_CLASS_S; \
42*69606e3fSchristos (dsc).dsc$w_length = (len); \
43*69606e3fSchristos (dsc).dsc$a_pointer = (addr); \
44*69606e3fSchristos } while (0)
45*69606e3fSchristos
46*69606e3fSchristos /* Initialize a string descriptor (struct dsc$descriptor_s) for a
47*69606e3fSchristos NUL-terminated string. S is a pointer to the string; the length
48*69606e3fSchristos is determined by calling strlen(). */
49*69606e3fSchristos
50*69606e3fSchristos #define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))
51*69606e3fSchristos #endif
52*69606e3fSchristos
53*69606e3fSchristos /*
54*69606e3fSchristos copy 'from' to 'to' up to but not including 'upto'
55*69606e3fSchristos return 0 if eos on from
56*69606e3fSchristos return 1 if upto found
57*69606e3fSchristos
58*69606e3fSchristos return 'to' at last char + 1
59*69606e3fSchristos return 'from' at match + 1 or eos if no match
60*69606e3fSchristos
61*69606e3fSchristos if as_dir == 1, change all '.' to '_'
62*69606e3fSchristos else change all '.' but the last to '_'
63*69606e3fSchristos */
64*69606e3fSchristos
65*69606e3fSchristos static int
copyto(char ** to,char ** from,char upto,int as_dir)66*69606e3fSchristos copyto (char **to, char **from, char upto, int as_dir)
67*69606e3fSchristos {
68*69606e3fSchristos char *s;
69*69606e3fSchristos
70*69606e3fSchristos s = strrchr (*from, '.');
71*69606e3fSchristos
72*69606e3fSchristos while (**from)
73*69606e3fSchristos {
74*69606e3fSchristos if (**from == upto)
75*69606e3fSchristos {
76*69606e3fSchristos do
77*69606e3fSchristos {
78*69606e3fSchristos (*from)++;
79*69606e3fSchristos }
80*69606e3fSchristos while (**from == upto);
81*69606e3fSchristos return 1;
82*69606e3fSchristos }
83*69606e3fSchristos if (**from == '.')
84*69606e3fSchristos {
85*69606e3fSchristos if ((as_dir == 1)
86*69606e3fSchristos || (*from != s))
87*69606e3fSchristos **to = '_';
88*69606e3fSchristos else
89*69606e3fSchristos **to = '.';
90*69606e3fSchristos }
91*69606e3fSchristos else
92*69606e3fSchristos {
93*69606e3fSchristos #ifdef HAVE_CASE_INSENSITIVE_FS
94*69606e3fSchristos if (isupper ((unsigned char)**from))
95*69606e3fSchristos **to = tolower ((unsigned char)**from);
96*69606e3fSchristos else
97*69606e3fSchristos #endif
98*69606e3fSchristos **to = **from;
99*69606e3fSchristos }
100*69606e3fSchristos (*to)++;
101*69606e3fSchristos (*from)++;
102*69606e3fSchristos }
103*69606e3fSchristos
104*69606e3fSchristos return 0;
105*69606e3fSchristos }
106*69606e3fSchristos
107*69606e3fSchristos
108*69606e3fSchristos /*
109*69606e3fSchristos get translation of logical name
110*69606e3fSchristos
111*69606e3fSchristos */
112*69606e3fSchristos
113*69606e3fSchristos static char *
trnlog(char * name)114*69606e3fSchristos trnlog (char *name)
115*69606e3fSchristos {
116*69606e3fSchristos int stat;
117*69606e3fSchristos static char reslt[1024];
118*69606e3fSchristos $DESCRIPTOR (reslt_dsc, reslt);
119*69606e3fSchristos short resltlen;
120*69606e3fSchristos struct dsc$descriptor_s name_dsc;
121*69606e3fSchristos char *s;
122*69606e3fSchristos
123*69606e3fSchristos INIT_DSC_CSTRING (name_dsc, name);
124*69606e3fSchristos
125*69606e3fSchristos stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
126*69606e3fSchristos
127*69606e3fSchristos if ((stat&1) == 0)
128*69606e3fSchristos {
129*69606e3fSchristos return "";
130*69606e3fSchristos }
131*69606e3fSchristos if (stat == SS$_NOTRAN)
132*69606e3fSchristos {
133*69606e3fSchristos return "";
134*69606e3fSchristos }
135*69606e3fSchristos reslt[resltlen] = '\0';
136*69606e3fSchristos
137*69606e3fSchristos s = (char *)malloc (resltlen+1);
138*69606e3fSchristos if (s == 0)
139*69606e3fSchristos return "";
140*69606e3fSchristos strcpy (s, reslt);
141*69606e3fSchristos return s;
142*69606e3fSchristos }
143*69606e3fSchristos
144*69606e3fSchristos static char *
showall(char * s)145*69606e3fSchristos showall (char *s)
146*69606e3fSchristos {
147*69606e3fSchristos static char t[512];
148*69606e3fSchristos char *pt;
149*69606e3fSchristos
150*69606e3fSchristos pt = t;
151*69606e3fSchristos if (strchr (s, '\\') == 0)
152*69606e3fSchristos return s;
153*69606e3fSchristos while (*s)
154*69606e3fSchristos {
155*69606e3fSchristos if (*s == '\\')
156*69606e3fSchristos {
157*69606e3fSchristos *pt++ = *s;
158*69606e3fSchristos }
159*69606e3fSchristos *pt++ = *s++;
160*69606e3fSchristos }
161*69606e3fSchristos return pt;
162*69606e3fSchristos }
163*69606e3fSchristos
164*69606e3fSchristos
165*69606e3fSchristos enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
166*69606e3fSchristos
167*69606e3fSchristos /*
168*69606e3fSchristos convert unix style name to vms style
169*69606e3fSchristos type = 0 -> name is a full name (directory and filename part)
170*69606e3fSchristos type = 1 -> name is a directory
171*69606e3fSchristos type = 2 -> name is a filename without directory
172*69606e3fSchristos
173*69606e3fSchristos The following conversions are applied
174*69606e3fSchristos (0) (1) (2)
175*69606e3fSchristos input full name dir name file name
176*69606e3fSchristos
177*69606e3fSchristos 1 ./ <cwd> [] <current directory>.dir
178*69606e3fSchristos 2 ../ <home of cwd> <home of cwd> <home of cwd>.dir
179*69606e3fSchristos
180*69606e3fSchristos 3 // <dev of cwd>: <dev of cwd>:[000000] <dev of cwd>:000000.dir
181*69606e3fSchristos 4 //a a: a: a:
182*69606e3fSchristos 5 //a/ a: a: a:000000.dir
183*69606e3fSchristos
184*69606e3fSchristos 9 / [000000] [000000] 000000.dir
185*69606e3fSchristos 10 /a [000000]a [a] [000000]a
186*69606e3fSchristos 11 /a/ [a] [a] [000000]a.dir
187*69606e3fSchristos 12 /a/b [a]b [a.b] [a]b
188*69606e3fSchristos 13 /a/b/ [a.b] [a.b] [a]b.dir
189*69606e3fSchristos 14 /a/b/c [a.b]c [a.b.c] [a.b]c
190*69606e3fSchristos 15 /a/b/c/ [a.b.c] [a.b.c] [a.b]c.dir
191*69606e3fSchristos
192*69606e3fSchristos 16 a a [.a] a
193*69606e3fSchristos 17 a/ [.a] [.a] a.dir
194*69606e3fSchristos 18 a/b [.a]b [.a.b] [.a]b
195*69606e3fSchristos 19 a/b/ [.a.b] [.a.b] [.a]b.dir
196*69606e3fSchristos 20 a/b/c [.a.b]c [.a.b.c] [.a.b]c
197*69606e3fSchristos 21 a/b/c/ [.a.b.c] [.a.b.c] [.a.b]c.dir
198*69606e3fSchristos
199*69606e3fSchristos 22 a.b.c a_b.c [.a_b_c] a_b_c.dir
200*69606e3fSchristos
201*69606e3fSchristos 23 [x][y]z [x.y]z [x.y]z [x.y]z
202*69606e3fSchristos 24 [x][.y]z [x.y]z [x.y]z [x.y]z
203*69606e3fSchristos
204*69606e3fSchristos 25 filenames with '$' are left unchanged if they contain no '/'
205*69606e3fSchristos 25 filenames with ':' are left unchanged
206*69606e3fSchristos 26 filenames with a single pair of '[' ']' are left unchanged
207*69606e3fSchristos
208*69606e3fSchristos the input string is not written to
209*69606e3fSchristos */
210*69606e3fSchristos
211*69606e3fSchristos char *
vmsify(char * name,int type)212*69606e3fSchristos vmsify (char *name, int type)
213*69606e3fSchristos {
214*69606e3fSchristos /* max 255 device
215*69606e3fSchristos max 39 directory
216*69606e3fSchristos max 39 filename
217*69606e3fSchristos max 39 filetype
218*69606e3fSchristos max 5 version
219*69606e3fSchristos */
220*69606e3fSchristos #define MAXPATHLEN 512
221*69606e3fSchristos
222*69606e3fSchristos enum namestate nstate;
223*69606e3fSchristos static char vmsname[MAXPATHLEN+1];
224*69606e3fSchristos char *fptr;
225*69606e3fSchristos char *vptr;
226*69606e3fSchristos char *s,*s1;
227*69606e3fSchristos int as_dir;
228*69606e3fSchristos int count;
229*69606e3fSchristos
230*69606e3fSchristos if (name == 0)
231*69606e3fSchristos return 0;
232*69606e3fSchristos fptr = name;
233*69606e3fSchristos vptr = vmsname;
234*69606e3fSchristos nstate = N_START;
235*69606e3fSchristos
236*69606e3fSchristos /* case 25a */
237*69606e3fSchristos
238*69606e3fSchristos s = strpbrk (name, "$:");
239*69606e3fSchristos if (s != 0)
240*69606e3fSchristos {
241*69606e3fSchristos char *s1;
242*69606e3fSchristos char *s2;
243*69606e3fSchristos
244*69606e3fSchristos if (type == 1)
245*69606e3fSchristos {
246*69606e3fSchristos s1 = strchr (s+1, '[');
247*69606e3fSchristos s2 = strchr (s+1, ']');
248*69606e3fSchristos }
249*69606e3fSchristos
250*69606e3fSchristos if (*s == '$')
251*69606e3fSchristos {
252*69606e3fSchristos if (strchr (name, '/') == 0)
253*69606e3fSchristos {
254*69606e3fSchristos if ((type == 1) && (s1 != 0) && (s2 == 0))
255*69606e3fSchristos {
256*69606e3fSchristos strcpy (vmsname, name);
257*69606e3fSchristos strcat (vmsname, "]");
258*69606e3fSchristos return vmsname;
259*69606e3fSchristos }
260*69606e3fSchristos else
261*69606e3fSchristos return name;
262*69606e3fSchristos }
263*69606e3fSchristos }
264*69606e3fSchristos else
265*69606e3fSchristos {
266*69606e3fSchristos if ((type == 1) && (s1 != 0) && (s2 == 0))
267*69606e3fSchristos {
268*69606e3fSchristos strcpy (vmsname, name);
269*69606e3fSchristos strcat (vmsname, "]");
270*69606e3fSchristos return vmsname;
271*69606e3fSchristos }
272*69606e3fSchristos else
273*69606e3fSchristos return name;
274*69606e3fSchristos }
275*69606e3fSchristos }
276*69606e3fSchristos
277*69606e3fSchristos /* case 26 */
278*69606e3fSchristos
279*69606e3fSchristos s = strchr (name, '[');
280*69606e3fSchristos
281*69606e3fSchristos if (s != 0)
282*69606e3fSchristos {
283*69606e3fSchristos s1 = strchr (s+1, '[');
284*69606e3fSchristos if (s1 == 0)
285*69606e3fSchristos {
286*69606e3fSchristos if ((type == 1)
287*69606e3fSchristos && (strchr (s+1, ']') == 0))
288*69606e3fSchristos {
289*69606e3fSchristos strcpy (vmsname, name);
290*69606e3fSchristos strcat (vmsname, "]");
291*69606e3fSchristos return vmsname;
292*69606e3fSchristos }
293*69606e3fSchristos else
294*69606e3fSchristos return name; /* single [, keep unchanged */
295*69606e3fSchristos }
296*69606e3fSchristos s1--;
297*69606e3fSchristos if (*s1 != ']')
298*69606e3fSchristos {
299*69606e3fSchristos return name; /* not ][, keep unchanged */
300*69606e3fSchristos }
301*69606e3fSchristos
302*69606e3fSchristos /* we have ][ */
303*69606e3fSchristos
304*69606e3fSchristos s = name;
305*69606e3fSchristos
306*69606e3fSchristos /* s -> starting char
307*69606e3fSchristos s1 -> ending ']' */
308*69606e3fSchristos
309*69606e3fSchristos do
310*69606e3fSchristos {
311*69606e3fSchristos strncpy (vptr, s, s1-s); /* copy up to but not including ']' */
312*69606e3fSchristos vptr += s1-s;
313*69606e3fSchristos if (*s1 == 0)
314*69606e3fSchristos break;
315*69606e3fSchristos s = s1 + 1; /* s -> char behind ']' */
316*69606e3fSchristos if (*s != '[') /* was '][' ? */
317*69606e3fSchristos break; /* no, last ] found, exit */
318*69606e3fSchristos s++;
319*69606e3fSchristos if (*s != '.')
320*69606e3fSchristos *vptr++ = '.';
321*69606e3fSchristos s1 = strchr (s, ']');
322*69606e3fSchristos if (s1 == 0) /* no closing ] */
323*69606e3fSchristos s1 = s + strlen (s);
324*69606e3fSchristos }
325*69606e3fSchristos while (1);
326*69606e3fSchristos
327*69606e3fSchristos *vptr++ = ']';
328*69606e3fSchristos
329*69606e3fSchristos fptr = s;
330*69606e3fSchristos
331*69606e3fSchristos }
332*69606e3fSchristos
333*69606e3fSchristos else /* no [ in name */
334*69606e3fSchristos
335*69606e3fSchristos {
336*69606e3fSchristos
337*69606e3fSchristos int state;
338*69606e3fSchristos int rooted = 1; /* flag if logical is rooted, else insert [000000] */
339*69606e3fSchristos
340*69606e3fSchristos state = 0;
341*69606e3fSchristos
342*69606e3fSchristos do
343*69606e3fSchristos {
344*69606e3fSchristos
345*69606e3fSchristos switch (state)
346*69606e3fSchristos {
347*69606e3fSchristos case 0: /* start of loop */
348*69606e3fSchristos if (*fptr == '/')
349*69606e3fSchristos {
350*69606e3fSchristos fptr++;
351*69606e3fSchristos state = 1;
352*69606e3fSchristos }
353*69606e3fSchristos else if (*fptr == '.')
354*69606e3fSchristos {
355*69606e3fSchristos fptr++;
356*69606e3fSchristos state = 10;
357*69606e3fSchristos }
358*69606e3fSchristos else
359*69606e3fSchristos state = 2;
360*69606e3fSchristos break;
361*69606e3fSchristos
362*69606e3fSchristos case 1: /* '/' at start */
363*69606e3fSchristos if (*fptr == '/')
364*69606e3fSchristos {
365*69606e3fSchristos fptr++;
366*69606e3fSchristos state = 3;
367*69606e3fSchristos }
368*69606e3fSchristos else
369*69606e3fSchristos state = 4;
370*69606e3fSchristos break;
371*69606e3fSchristos
372*69606e3fSchristos case 2: /* no '/' at start */
373*69606e3fSchristos s = strchr (fptr, '/');
374*69606e3fSchristos if (s == 0) /* no '/' (16) */
375*69606e3fSchristos {
376*69606e3fSchristos if (type == 1)
377*69606e3fSchristos {
378*69606e3fSchristos strcpy (vptr, "[.");
379*69606e3fSchristos vptr += 2;
380*69606e3fSchristos }
381*69606e3fSchristos copyto (&vptr, &fptr, 0, (type==1));
382*69606e3fSchristos if (type == 1)
383*69606e3fSchristos *vptr++ = ']';
384*69606e3fSchristos state = -1;
385*69606e3fSchristos }
386*69606e3fSchristos else /* found '/' (17..21) */
387*69606e3fSchristos {
388*69606e3fSchristos if ((type == 2)
389*69606e3fSchristos && (*(s+1) == 0)) /* 17(2) */
390*69606e3fSchristos {
391*69606e3fSchristos copyto (&vptr, &fptr, '/', 1);
392*69606e3fSchristos state = 7;
393*69606e3fSchristos }
394*69606e3fSchristos else
395*69606e3fSchristos {
396*69606e3fSchristos strcpy (vptr, "[.");
397*69606e3fSchristos vptr += 2;
398*69606e3fSchristos copyto (&vptr, &fptr, '/', 1);
399*69606e3fSchristos nstate = N_OPEN;
400*69606e3fSchristos state = 9;
401*69606e3fSchristos }
402*69606e3fSchristos }
403*69606e3fSchristos break;
404*69606e3fSchristos
405*69606e3fSchristos case 3: /* '//' at start */
406*69606e3fSchristos while (*fptr == '/') /* collapse all '/' */
407*69606e3fSchristos fptr++;
408*69606e3fSchristos if (*fptr == 0) /* just // */
409*69606e3fSchristos {
410*69606e3fSchristos char cwdbuf[MAXPATHLEN+1];
411*69606e3fSchristos
412*69606e3fSchristos s1 = getcwd(cwdbuf, MAXPATHLEN);
413*69606e3fSchristos if (s1 == 0)
414*69606e3fSchristos {
415*69606e3fSchristos return ""; /* FIXME, err getcwd */
416*69606e3fSchristos }
417*69606e3fSchristos s = strchr (s1, ':');
418*69606e3fSchristos if (s == 0)
419*69606e3fSchristos {
420*69606e3fSchristos return ""; /* FIXME, err no device */
421*69606e3fSchristos }
422*69606e3fSchristos strncpy (vptr, s1, s-s1+1);
423*69606e3fSchristos vptr += s-s1+1;
424*69606e3fSchristos state = -1;
425*69606e3fSchristos break;
426*69606e3fSchristos }
427*69606e3fSchristos
428*69606e3fSchristos s = vptr;
429*69606e3fSchristos
430*69606e3fSchristos if (copyto (&vptr, &fptr, '/', 1) == 0) /* copy device part */
431*69606e3fSchristos {
432*69606e3fSchristos *vptr++ = ':';
433*69606e3fSchristos state = -1;
434*69606e3fSchristos break;
435*69606e3fSchristos }
436*69606e3fSchristos *vptr = ':';
437*69606e3fSchristos nstate = N_DEVICE;
438*69606e3fSchristos if (*fptr == 0) /* just '//a/' */
439*69606e3fSchristos {
440*69606e3fSchristos strcpy (vptr+1, "[000000]");
441*69606e3fSchristos vptr += 9;
442*69606e3fSchristos state = -1;
443*69606e3fSchristos break;
444*69606e3fSchristos }
445*69606e3fSchristos *vptr = 0;
446*69606e3fSchristos /* check logical for [000000] insertion */
447*69606e3fSchristos s1 = trnlog (s);
448*69606e3fSchristos if (*s1 != 0)
449*69606e3fSchristos { /* found translation */
450*69606e3fSchristos char *s2;
451*69606e3fSchristos for (;;) /* loop over all nested logicals */
452*69606e3fSchristos {
453*69606e3fSchristos s2 = s1 + strlen (s1) - 1;
454*69606e3fSchristos if (*s2 == ':') /* translation ends in ':' */
455*69606e3fSchristos {
456*69606e3fSchristos s2 = trnlog (s1);
457*69606e3fSchristos free (s1);
458*69606e3fSchristos if (*s2 == 0)
459*69606e3fSchristos {
460*69606e3fSchristos rooted = 0;
461*69606e3fSchristos break;
462*69606e3fSchristos }
463*69606e3fSchristos s1 = s2;
464*69606e3fSchristos continue; /* next iteration */
465*69606e3fSchristos }
466*69606e3fSchristos if (*s2 == ']') /* translation ends in ']' */
467*69606e3fSchristos {
468*69606e3fSchristos if (*(s2-1) == '.') /* ends in '.]' */
469*69606e3fSchristos {
470*69606e3fSchristos if (strncmp (fptr, "000000", 6) != 0)
471*69606e3fSchristos rooted = 0;
472*69606e3fSchristos }
473*69606e3fSchristos else
474*69606e3fSchristos {
475*69606e3fSchristos strcpy (vmsname, s1);
476*69606e3fSchristos s = strchr (vmsname, ']');
477*69606e3fSchristos *s = '.';
478*69606e3fSchristos nstate = N_DOT;
479*69606e3fSchristos vptr = s;
480*69606e3fSchristos }
481*69606e3fSchristos }
482*69606e3fSchristos break;
483*69606e3fSchristos }
484*69606e3fSchristos free (s1);
485*69606e3fSchristos }
486*69606e3fSchristos else
487*69606e3fSchristos rooted = 0;
488*69606e3fSchristos
489*69606e3fSchristos if (*vptr == 0)
490*69606e3fSchristos {
491*69606e3fSchristos nstate = N_DEVICE;
492*69606e3fSchristos *vptr++ = ':';
493*69606e3fSchristos }
494*69606e3fSchristos else
495*69606e3fSchristos vptr++;
496*69606e3fSchristos
497*69606e3fSchristos if (rooted == 0)
498*69606e3fSchristos {
499*69606e3fSchristos strcpy (vptr, "[000000.");
500*69606e3fSchristos vptr += 8;
501*69606e3fSchristos s1 = vptr-1;
502*69606e3fSchristos nstate = N_DOT;
503*69606e3fSchristos }
504*69606e3fSchristos else
505*69606e3fSchristos s1 = 0;
506*69606e3fSchristos
507*69606e3fSchristos /* s1-> '.' after 000000 or NULL */
508*69606e3fSchristos
509*69606e3fSchristos s = strchr (fptr, '/');
510*69606e3fSchristos if (s == 0)
511*69606e3fSchristos { /* no next '/' */
512*69606e3fSchristos if (*(vptr-1) == '.')
513*69606e3fSchristos *(vptr-1) = ']';
514*69606e3fSchristos else if (rooted == 0)
515*69606e3fSchristos *vptr++ = ']';
516*69606e3fSchristos copyto (&vptr, &fptr, 0, (type == 1));
517*69606e3fSchristos state = -1;
518*69606e3fSchristos break;
519*69606e3fSchristos }
520*69606e3fSchristos else
521*69606e3fSchristos {
522*69606e3fSchristos while (*(s+1) == '/') /* skip multiple '/' */
523*69606e3fSchristos s++;
524*69606e3fSchristos }
525*69606e3fSchristos
526*69606e3fSchristos if ((rooted != 0)
527*69606e3fSchristos && (*(vptr-1) != '.'))
528*69606e3fSchristos {
529*69606e3fSchristos *vptr++ = '[';
530*69606e3fSchristos nstate = N_DOT;
531*69606e3fSchristos }
532*69606e3fSchristos else
533*69606e3fSchristos if ((nstate == N_DOT)
534*69606e3fSchristos && (s1 != 0)
535*69606e3fSchristos && (*(s+1) == 0))
536*69606e3fSchristos {
537*69606e3fSchristos if (type == 2)
538*69606e3fSchristos {
539*69606e3fSchristos *s1 = ']';
540*69606e3fSchristos nstate = N_CLOSED;
541*69606e3fSchristos }
542*69606e3fSchristos }
543*69606e3fSchristos state = 9;
544*69606e3fSchristos break;
545*69606e3fSchristos
546*69606e3fSchristos case 4: /* single '/' at start (9..15) */
547*69606e3fSchristos if (*fptr == 0)
548*69606e3fSchristos state = 5;
549*69606e3fSchristos else
550*69606e3fSchristos state = 6;
551*69606e3fSchristos break;
552*69606e3fSchristos
553*69606e3fSchristos case 5: /* just '/' at start (9) */
554*69606e3fSchristos if (type != 2)
555*69606e3fSchristos {
556*69606e3fSchristos *vptr++ = '[';
557*69606e3fSchristos nstate = N_OPEN;
558*69606e3fSchristos }
559*69606e3fSchristos strcpy (vptr, "000000");
560*69606e3fSchristos vptr += 6;
561*69606e3fSchristos if (type == 2)
562*69606e3fSchristos state = 7;
563*69606e3fSchristos else
564*69606e3fSchristos state = 8;
565*69606e3fSchristos break;
566*69606e3fSchristos
567*69606e3fSchristos case 6: /* chars following '/' at start 10..15 */
568*69606e3fSchristos *vptr++ = '[';
569*69606e3fSchristos nstate = N_OPEN;
570*69606e3fSchristos s = strchr (fptr, '/');
571*69606e3fSchristos if (s == 0) /* 10 */
572*69606e3fSchristos {
573*69606e3fSchristos if (type != 1)
574*69606e3fSchristos {
575*69606e3fSchristos strcpy (vptr, "000000]");
576*69606e3fSchristos vptr += 7;
577*69606e3fSchristos }
578*69606e3fSchristos copyto (&vptr, &fptr, 0, (type == 1));
579*69606e3fSchristos if (type == 1)
580*69606e3fSchristos {
581*69606e3fSchristos *vptr++ = ']';
582*69606e3fSchristos }
583*69606e3fSchristos state = -1;
584*69606e3fSchristos }
585*69606e3fSchristos else /* 11..15 */
586*69606e3fSchristos {
587*69606e3fSchristos if ( (type == 2)
588*69606e3fSchristos && (*(s+1) == 0)) /* 11(2) */
589*69606e3fSchristos {
590*69606e3fSchristos strcpy (vptr, "000000]");
591*69606e3fSchristos nstate = N_CLOSED;
592*69606e3fSchristos vptr += 7;
593*69606e3fSchristos }
594*69606e3fSchristos copyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));
595*69606e3fSchristos state = 9;
596*69606e3fSchristos }
597*69606e3fSchristos break;
598*69606e3fSchristos
599*69606e3fSchristos case 7: /* add '.dir' and exit */
600*69606e3fSchristos if ((nstate == N_OPEN)
601*69606e3fSchristos || (nstate == N_DOT))
602*69606e3fSchristos {
603*69606e3fSchristos s = vptr-1;
604*69606e3fSchristos while (s > vmsname)
605*69606e3fSchristos {
606*69606e3fSchristos if (*s == ']')
607*69606e3fSchristos {
608*69606e3fSchristos break;
609*69606e3fSchristos }
610*69606e3fSchristos if (*s == '.')
611*69606e3fSchristos {
612*69606e3fSchristos *s = ']';
613*69606e3fSchristos break;
614*69606e3fSchristos }
615*69606e3fSchristos s--;
616*69606e3fSchristos }
617*69606e3fSchristos }
618*69606e3fSchristos strcpy (vptr, ".dir");
619*69606e3fSchristos vptr += 4;
620*69606e3fSchristos state = -1;
621*69606e3fSchristos break;
622*69606e3fSchristos
623*69606e3fSchristos case 8: /* add ']' and exit */
624*69606e3fSchristos *vptr++ = ']';
625*69606e3fSchristos state = -1;
626*69606e3fSchristos break;
627*69606e3fSchristos
628*69606e3fSchristos case 9: /* 17..21, fptr -> 1st '/' + 1 */
629*69606e3fSchristos if (*fptr == 0)
630*69606e3fSchristos {
631*69606e3fSchristos if (type == 2)
632*69606e3fSchristos {
633*69606e3fSchristos state = 7;
634*69606e3fSchristos }
635*69606e3fSchristos else
636*69606e3fSchristos state = 8;
637*69606e3fSchristos break;
638*69606e3fSchristos }
639*69606e3fSchristos s = strchr (fptr, '/');
640*69606e3fSchristos if (s == 0)
641*69606e3fSchristos {
642*69606e3fSchristos if (type != 1)
643*69606e3fSchristos {
644*69606e3fSchristos if (nstate == N_OPEN)
645*69606e3fSchristos {
646*69606e3fSchristos *vptr++ = ']';
647*69606e3fSchristos nstate = N_CLOSED;
648*69606e3fSchristos }
649*69606e3fSchristos as_dir = 0;
650*69606e3fSchristos }
651*69606e3fSchristos else
652*69606e3fSchristos {
653*69606e3fSchristos if (nstate == N_OPEN)
654*69606e3fSchristos {
655*69606e3fSchristos *vptr++ = '.';
656*69606e3fSchristos nstate = N_DOT;
657*69606e3fSchristos }
658*69606e3fSchristos as_dir = 1;
659*69606e3fSchristos }
660*69606e3fSchristos }
661*69606e3fSchristos else
662*69606e3fSchristos {
663*69606e3fSchristos while (*(s+1) == '/')
664*69606e3fSchristos s++;
665*69606e3fSchristos if ( (type == 2)
666*69606e3fSchristos && (*(s+1) == 0)) /* 19(2), 21(2)*/
667*69606e3fSchristos {
668*69606e3fSchristos if (nstate != N_CLOSED)
669*69606e3fSchristos {
670*69606e3fSchristos *vptr++ = ']';
671*69606e3fSchristos nstate = N_CLOSED;
672*69606e3fSchristos }
673*69606e3fSchristos as_dir = 1;
674*69606e3fSchristos }
675*69606e3fSchristos else
676*69606e3fSchristos {
677*69606e3fSchristos if (nstate == N_OPEN)
678*69606e3fSchristos {
679*69606e3fSchristos *vptr++ = '.';
680*69606e3fSchristos nstate = N_DOT;
681*69606e3fSchristos }
682*69606e3fSchristos as_dir = 1;
683*69606e3fSchristos }
684*69606e3fSchristos }
685*69606e3fSchristos if ( (*fptr == '.') /* check for '..' or '../' */
686*69606e3fSchristos && (*(fptr+1) == '.')
687*69606e3fSchristos && ((*(fptr+2) == '/')
688*69606e3fSchristos || (*(fptr+2) == 0)) )
689*69606e3fSchristos {
690*69606e3fSchristos fptr += 2;
691*69606e3fSchristos if (*fptr == '/')
692*69606e3fSchristos {
693*69606e3fSchristos do
694*69606e3fSchristos {
695*69606e3fSchristos fptr++;
696*69606e3fSchristos }
697*69606e3fSchristos while (*fptr == '/');
698*69606e3fSchristos }
699*69606e3fSchristos else if (*fptr == 0)
700*69606e3fSchristos type = 1;
701*69606e3fSchristos vptr--; /* vptr -> '.' or ']' */
702*69606e3fSchristos s1 = vptr;
703*69606e3fSchristos for (;;)
704*69606e3fSchristos {
705*69606e3fSchristos s1--;
706*69606e3fSchristos if (*s1 == '.') /* one back */
707*69606e3fSchristos {
708*69606e3fSchristos vptr = s1;
709*69606e3fSchristos nstate = N_OPEN;
710*69606e3fSchristos break;
711*69606e3fSchristos }
712*69606e3fSchristos if (*s1 == '[') /* top level reached */
713*69606e3fSchristos {
714*69606e3fSchristos if (*fptr == 0)
715*69606e3fSchristos {
716*69606e3fSchristos strcpy (s1, "[000000]");
717*69606e3fSchristos vptr = s1 + 8;
718*69606e3fSchristos nstate = N_CLOSED;
719*69606e3fSchristos s = 0;
720*69606e3fSchristos break;
721*69606e3fSchristos }
722*69606e3fSchristos else
723*69606e3fSchristos {
724*69606e3fSchristos vptr = s1+1;
725*69606e3fSchristos nstate = N_OPEN;
726*69606e3fSchristos break;
727*69606e3fSchristos }
728*69606e3fSchristos }
729*69606e3fSchristos }
730*69606e3fSchristos }
731*69606e3fSchristos else
732*69606e3fSchristos {
733*69606e3fSchristos copyto (&vptr, &fptr, '/', as_dir);
734*69606e3fSchristos if (nstate == N_DOT)
735*69606e3fSchristos nstate = N_OPEN;
736*69606e3fSchristos }
737*69606e3fSchristos if (s == 0)
738*69606e3fSchristos { /* 18,20 */
739*69606e3fSchristos if (type == 1)
740*69606e3fSchristos *vptr++ = ']';
741*69606e3fSchristos state = -1;
742*69606e3fSchristos }
743*69606e3fSchristos else
744*69606e3fSchristos {
745*69606e3fSchristos if (*(s+1) == 0)
746*69606e3fSchristos {
747*69606e3fSchristos if (type == 2) /* 19,21 */
748*69606e3fSchristos {
749*69606e3fSchristos state = 7;
750*69606e3fSchristos }
751*69606e3fSchristos else
752*69606e3fSchristos {
753*69606e3fSchristos *vptr++ = ']';
754*69606e3fSchristos state = -1;
755*69606e3fSchristos }
756*69606e3fSchristos }
757*69606e3fSchristos }
758*69606e3fSchristos break;
759*69606e3fSchristos
760*69606e3fSchristos case 10: /* 1,2 first is '.' */
761*69606e3fSchristos if (*fptr == '.')
762*69606e3fSchristos {
763*69606e3fSchristos fptr++;
764*69606e3fSchristos state = 11;
765*69606e3fSchristos }
766*69606e3fSchristos else
767*69606e3fSchristos state = 12;
768*69606e3fSchristos break;
769*69606e3fSchristos
770*69606e3fSchristos case 11: /* 2, '..' at start */
771*69606e3fSchristos count = 1;
772*69606e3fSchristos if (*fptr != 0)
773*69606e3fSchristos {
774*69606e3fSchristos if (*fptr != '/') /* got ..xxx */
775*69606e3fSchristos {
776*69606e3fSchristos return name;
777*69606e3fSchristos }
778*69606e3fSchristos do /* got ../ */
779*69606e3fSchristos {
780*69606e3fSchristos fptr++;
781*69606e3fSchristos while (*fptr == '/') fptr++;
782*69606e3fSchristos if (*fptr != '.')
783*69606e3fSchristos break;
784*69606e3fSchristos if (*(fptr+1) != '.')
785*69606e3fSchristos break;
786*69606e3fSchristos fptr += 2;
787*69606e3fSchristos if ((*fptr == 0)
788*69606e3fSchristos || (*fptr == '/'))
789*69606e3fSchristos count++;
790*69606e3fSchristos }
791*69606e3fSchristos while (*fptr == '/');
792*69606e3fSchristos }
793*69606e3fSchristos { /* got '..' or '../' */
794*69606e3fSchristos char cwdbuf[MAXPATHLEN+1];
795*69606e3fSchristos
796*69606e3fSchristos s1 = getcwd(cwdbuf, MAXPATHLEN);
797*69606e3fSchristos if (s1 == 0)
798*69606e3fSchristos {
799*69606e3fSchristos return ""; /* FIXME, err getcwd */
800*69606e3fSchristos }
801*69606e3fSchristos strcpy (vptr, s1);
802*69606e3fSchristos s = strchr (vptr, ']');
803*69606e3fSchristos if (s != 0)
804*69606e3fSchristos {
805*69606e3fSchristos nstate = N_OPEN;
806*69606e3fSchristos while (s > vptr)
807*69606e3fSchristos {
808*69606e3fSchristos s--;
809*69606e3fSchristos if (*s == '[')
810*69606e3fSchristos {
811*69606e3fSchristos s++;
812*69606e3fSchristos strcpy (s, "000000]");
813*69606e3fSchristos state = -1;
814*69606e3fSchristos break;
815*69606e3fSchristos }
816*69606e3fSchristos else if (*s == '.')
817*69606e3fSchristos {
818*69606e3fSchristos if (--count == 0)
819*69606e3fSchristos {
820*69606e3fSchristos if (*fptr == 0) /* had '..' or '../' */
821*69606e3fSchristos {
822*69606e3fSchristos *s++ = ']';
823*69606e3fSchristos state = -1;
824*69606e3fSchristos }
825*69606e3fSchristos else /* had '../xxx' */
826*69606e3fSchristos {
827*69606e3fSchristos state = 9;
828*69606e3fSchristos }
829*69606e3fSchristos *s = 0;
830*69606e3fSchristos break;
831*69606e3fSchristos }
832*69606e3fSchristos }
833*69606e3fSchristos }
834*69606e3fSchristos }
835*69606e3fSchristos vptr += strlen (vptr);
836*69606e3fSchristos }
837*69606e3fSchristos break;
838*69606e3fSchristos
839*69606e3fSchristos case 12: /* 1, '.' at start */
840*69606e3fSchristos if (*fptr != 0)
841*69606e3fSchristos {
842*69606e3fSchristos if (*fptr != '/')
843*69606e3fSchristos {
844*69606e3fSchristos return name;
845*69606e3fSchristos }
846*69606e3fSchristos while (*fptr == '/')
847*69606e3fSchristos fptr++;
848*69606e3fSchristos }
849*69606e3fSchristos
850*69606e3fSchristos {
851*69606e3fSchristos char cwdbuf[MAXPATHLEN+1];
852*69606e3fSchristos
853*69606e3fSchristos s1 = getcwd(cwdbuf, MAXPATHLEN);
854*69606e3fSchristos if (s1 == 0)
855*69606e3fSchristos {
856*69606e3fSchristos return ""; /*FIXME, err getcwd */
857*69606e3fSchristos }
858*69606e3fSchristos strcpy (vptr, s1);
859*69606e3fSchristos if (*fptr == 0)
860*69606e3fSchristos {
861*69606e3fSchristos state = -1;
862*69606e3fSchristos break;
863*69606e3fSchristos }
864*69606e3fSchristos else
865*69606e3fSchristos {
866*69606e3fSchristos s = strchr (vptr, ']');
867*69606e3fSchristos if (s == 0)
868*69606e3fSchristos {
869*69606e3fSchristos state = -1;
870*69606e3fSchristos break;
871*69606e3fSchristos }
872*69606e3fSchristos *s = 0;
873*69606e3fSchristos nstate = N_OPEN;
874*69606e3fSchristos vptr += strlen (vptr);
875*69606e3fSchristos state = 9;
876*69606e3fSchristos }
877*69606e3fSchristos }
878*69606e3fSchristos break;
879*69606e3fSchristos }
880*69606e3fSchristos
881*69606e3fSchristos }
882*69606e3fSchristos while (state > 0);
883*69606e3fSchristos
884*69606e3fSchristos
885*69606e3fSchristos }
886*69606e3fSchristos
887*69606e3fSchristos
888*69606e3fSchristos /* directory conversion done
889*69606e3fSchristos fptr -> filename part of input string
890*69606e3fSchristos vptr -> free space in vmsname
891*69606e3fSchristos */
892*69606e3fSchristos
893*69606e3fSchristos *vptr++ = 0;
894*69606e3fSchristos
895*69606e3fSchristos return vmsname;
896*69606e3fSchristos }
897*69606e3fSchristos
898*69606e3fSchristos
899*69606e3fSchristos
900*69606e3fSchristos /*
901*69606e3fSchristos convert from vms-style to unix-style
902*69606e3fSchristos
903*69606e3fSchristos dev:[dir1.dir2] //dev/dir1/dir2/
904*69606e3fSchristos */
905*69606e3fSchristos
906*69606e3fSchristos char *
unixify(char * name)907*69606e3fSchristos unixify (char *name)
908*69606e3fSchristos {
909*69606e3fSchristos static char piece[512];
910*69606e3fSchristos char *s, *p;
911*69606e3fSchristos
912*69606e3fSchristos if (strchr (name, '/') != 0) /* already in unix style */
913*69606e3fSchristos return name;
914*69606e3fSchristos
915*69606e3fSchristos p = piece;
916*69606e3fSchristos *p = 0;
917*69606e3fSchristos
918*69606e3fSchristos /* device part */
919*69606e3fSchristos
920*69606e3fSchristos s = strchr (name, ':');
921*69606e3fSchristos
922*69606e3fSchristos if (s != 0)
923*69606e3fSchristos {
924*69606e3fSchristos *s = 0;
925*69606e3fSchristos *p++ = '/';
926*69606e3fSchristos *p++ = '/';
927*69606e3fSchristos strcpy (p, name);
928*69606e3fSchristos p += strlen (p);
929*69606e3fSchristos *s = ':';
930*69606e3fSchristos }
931*69606e3fSchristos
932*69606e3fSchristos /* directory part */
933*69606e3fSchristos
934*69606e3fSchristos *p++ = '/';
935*69606e3fSchristos s = strchr (name, '[');
936*69606e3fSchristos
937*69606e3fSchristos if (s != 0)
938*69606e3fSchristos {
939*69606e3fSchristos s++;
940*69606e3fSchristos switch (*s)
941*69606e3fSchristos {
942*69606e3fSchristos case ']': /* [] */
943*69606e3fSchristos strcat (p, "./");
944*69606e3fSchristos break;
945*69606e3fSchristos case '-': /* [- */
946*69606e3fSchristos strcat (p, "../");
947*69606e3fSchristos break;
948*69606e3fSchristos case '.':
949*69606e3fSchristos strcat (p, "./"); /* [. */
950*69606e3fSchristos break;
951*69606e3fSchristos default:
952*69606e3fSchristos s--;
953*69606e3fSchristos break;
954*69606e3fSchristos }
955*69606e3fSchristos s++;
956*69606e3fSchristos while (*s)
957*69606e3fSchristos {
958*69606e3fSchristos if (*s == '.')
959*69606e3fSchristos *p++ = '/';
960*69606e3fSchristos else
961*69606e3fSchristos *p++ = *s;
962*69606e3fSchristos s++;
963*69606e3fSchristos if (*s == ']')
964*69606e3fSchristos {
965*69606e3fSchristos s++;
966*69606e3fSchristos break;
967*69606e3fSchristos }
968*69606e3fSchristos }
969*69606e3fSchristos if (*s != 0) /* more after ']' ?? */
970*69606e3fSchristos {
971*69606e3fSchristos if (*(p-1) != '/')
972*69606e3fSchristos *p++ = '/';
973*69606e3fSchristos strcpy (p, s); /* copy it anyway */
974*69606e3fSchristos }
975*69606e3fSchristos }
976*69606e3fSchristos
977*69606e3fSchristos else /* no '[' anywhere */
978*69606e3fSchristos
979*69606e3fSchristos {
980*69606e3fSchristos *p++ = 0;
981*69606e3fSchristos }
982*69606e3fSchristos
983*69606e3fSchristos /* force end with '/' */
984*69606e3fSchristos
985*69606e3fSchristos if (*(p-1) != '/')
986*69606e3fSchristos *p++ = '/';
987*69606e3fSchristos *p = 0;
988*69606e3fSchristos
989*69606e3fSchristos return piece;
990*69606e3fSchristos }
991*69606e3fSchristos
992*69606e3fSchristos /* EOF */
993