source: trunk/third/gmake/vmsify.c @ 15972

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