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