VirtualBox

source: kBuild/trunk/src/kmk/vmsify.c@ 2091

Last change on this file since 2091 was 1993, checked in by bird, 16 years ago

Merged in current GNU Make code (CVS from 2008-10-28). Ref #55.

  • Property svn:eol-style set to native
File size: 17.9 KB
Line 
1/* vmsify.c -- Module for vms <-> unix file name conversion
2Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
32007 Free Software Foundation, Inc.
4This file is part of GNU Make.
5
6GNU Make is free software; you can redistribute it and/or modify it under the
7terms of the GNU General Public License as published by the Free Software
8Foundation; either version 3 of the License, or (at your option) any later
9version.
10
11GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License along with
16this program. If not, see <http://www.gnu.org/licenses/>. */
17
18/* Written by Klaus Kämpf (kkaempf@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
65static int
66copyto (char **to, const char **from, char upto, int as_dir)
67{
68 const 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
113static char *
114trnlog (const 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 = malloc (resltlen+1);
138 if (s == 0)
139 return "";
140 strcpy (s, reslt);
141 return s;
142}
143
144static char *
145showall (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
165enum 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
1771 ./ <cwd> [] <current directory>.dir
1782 ../ <home of cwd> <home of cwd> <home of cwd>.dir
179
1803 // <dev of cwd>: <dev of cwd>:[000000] <dev of cwd>:000000.dir
1814 //a a: a: a:
1825 //a/ a: a: a:000000.dir
183
1849 / [000000] [000000] 000000.dir
18510 /a [000000]a [a] [000000]a
18611 /a/ [a] [a] [000000]a.dir
18712 /a/b [a]b [a.b] [a]b
18813 /a/b/ [a.b] [a.b] [a]b.dir
18914 /a/b/c [a.b]c [a.b.c] [a.b]c
19015 /a/b/c/ [a.b.c] [a.b.c] [a.b]c.dir
191
19216 a a [.a] a
19317 a/ [.a] [.a] a.dir
19418 a/b [.a]b [.a.b] [.a]b
19519 a/b/ [.a.b] [.a.b] [.a]b.dir
19620 a/b/c [.a.b]c [.a.b.c] [.a.b]c
19721 a/b/c/ [.a.b.c] [.a.b.c] [.a.b]c.dir
198
19922 a.b.c a_b.c [.a_b_c] a_b_c.dir
200
20123 [x][y]z [x.y]z [x.y]z [x.y]z
20224 [x][.y]z [x.y]z [x.y]z [x.y]z
203
20425 filenames with '$' are left unchanged if they contain no '/'
20525 filenames with ':' are left unchanged
20626 filenames with a single pair of '[' ']' are left unchanged
207
208 The input string is not written to. The result is also const because
209 it's a static buffer; we don't want to change it.
210*/
211
212const char *
213vmsify (const char *name, int type)
214{
215/* max 255 device
216 max 39 directory
217 max 39 filename
218 max 39 filetype
219 max 5 version
220*/
221#define MAXPATHLEN 512
222
223 enum namestate nstate;
224 static char vmsname[MAXPATHLEN+1];
225 const char *fptr;
226 const char *t;
227 char *vptr;
228 int as_dir;
229 int count;
230
231 if (name == 0)
232 return 0;
233 fptr = name;
234 vptr = vmsname;
235 nstate = N_START;
236
237 /* case 25a */
238 t = strpbrk (name, "$:");
239
240 if (t != 0)
241 {
242 const char *s1;
243 const char *s2;
244
245 if (type == 1)
246 {
247 s1 = strchr (t+1, '[');
248 s2 = strchr (t+1, ']');
249 }
250
251 if (*t == '$')
252 {
253 if (strchr (name, '/') == 0)
254 {
255 strcpy (vmsname, name);
256 if ((type == 1) && (s1 != 0) && (s2 == 0))
257 strcat (vmsname, "]");
258 return vmsname;
259 }
260 }
261 else
262 {
263 strcpy (vmsname, name);
264 if ((type == 1) && (s1 != 0) && (s2 == 0))
265 strcat (vmsname, "]");
266 return vmsname;
267 }
268 }
269
270 /* case 26 */
271 t = strchr (name, '[');
272
273 if (t != 0)
274 {
275 const char *s;
276 const char *s1 = strchr (t+1, '[');
277 if (s1 == 0)
278 {
279 strcpy (vmsname, name);
280 if ((type == 1) && (strchr (t+1, ']') == 0))
281 strcat (vmsname, "]");
282 return vmsname;
283 }
284 s1--;
285 if (*s1 != ']')
286 {
287 strcpy (vmsname, name);
288 return vmsname; /* not ][, keep unchanged */
289 }
290
291 /* we have ][ */
292
293 s = name;
294
295 /* s -> starting char
296 s1 -> ending ']' */
297 do
298 {
299 strncpy (vptr, s, s1-s); /* copy up to but not including ']' */
300 vptr += s1-s;
301 if (*s1 == 0)
302 break;
303 s = s1 + 1; /* s -> char behind ']' */
304 if (*s != '[') /* was '][' ? */
305 break; /* no, last ] found, exit */
306 s++;
307 if (*s != '.')
308 *vptr++ = '.';
309 s1 = strchr (s, ']');
310 if (s1 == 0) /* no closing ] */
311 s1 = s + strlen (s);
312 }
313 while (1);
314
315 *vptr++ = ']';
316
317 fptr = s;
318
319 }
320 else /* no [ in name */
321 {
322 int state = 0;
323 int rooted = 1; /* flag if logical is rooted, else insert [000000] */
324
325 do
326 {
327 switch (state)
328 {
329 case 0: /* start of loop */
330 if (*fptr == '/')
331 {
332 fptr++;
333 state = 1;
334 }
335 else if (*fptr == '.')
336 {
337 fptr++;
338 state = 10;
339 }
340 else
341 state = 2;
342 break;
343
344 case 1: /* '/' at start */
345 if (*fptr == '/')
346 {
347 fptr++;
348 state = 3;
349 }
350 else
351 state = 4;
352 break;
353
354 case 2: /* no '/' at start */
355 {
356 const char *s = strchr (fptr, '/');
357 if (s == 0) /* no '/' (16) */
358 {
359 if (type == 1)
360 {
361 strcpy (vptr, "[.");
362 vptr += 2;
363 }
364 copyto (&vptr, &fptr, 0, (type==1));
365 if (type == 1)
366 *vptr++ = ']';
367 state = -1;
368 }
369 else /* found '/' (17..21) */
370 {
371 if ((type == 2)
372 && (*(s+1) == 0)) /* 17(2) */
373 {
374 copyto (&vptr, &fptr, '/', 1);
375 state = 7;
376 }
377 else
378 {
379 strcpy (vptr, "[.");
380 vptr += 2;
381 copyto (&vptr, &fptr, '/', 1);
382 nstate = N_OPEN;
383 state = 9;
384 }
385 }
386 break;
387 }
388
389 case 3: /* '//' at start */
390 {
391 const char *s;
392 const char *s1;
393 char *vp;
394 while (*fptr == '/') /* collapse all '/' */
395 fptr++;
396 if (*fptr == 0) /* just // */
397 {
398 char cwdbuf[MAXPATHLEN+1];
399
400 s1 = getcwd(cwdbuf, MAXPATHLEN);
401 if (s1 == 0)
402 {
403 vmsname[0] = '\0';
404 return vmsname; /* FIXME, err getcwd */
405 }
406 s = strchr (s1, ':');
407 if (s == 0)
408 {
409 vmsname[0] = '\0';
410 return vmsname; /* FIXME, err no device */
411 }
412 strncpy (vptr, s1, s-s1+1);
413 vptr += s-s1+1;
414 state = -1;
415 break;
416 }
417
418 s = vptr;
419
420 if (copyto (&vptr, &fptr, '/', 1) == 0) /* copy device part */
421 {
422 *vptr++ = ':';
423 state = -1;
424 break;
425 }
426 *vptr = ':';
427 nstate = N_DEVICE;
428 if (*fptr == 0) /* just '//a/' */
429 {
430 strcpy (vptr+1, "[000000]");
431 vptr += 9;
432 state = -1;
433 break;
434 }
435 *vptr = 0;
436 /* check logical for [000000] insertion */
437 vp = trnlog (s);
438 if (*vp != '\0')
439 { /* found translation */
440 for (;;) /* loop over all nested logicals */
441 {
442 char *vp2 = vp + strlen (vp) - 1;
443 if (*vp2 == ':') /* translation ends in ':' */
444 {
445 vp2 = trnlog (vp);
446 free (vp);
447 if (*vp2 == 0)
448 {
449 rooted = 0;
450 break;
451 }
452 vp = vp2;
453 continue; /* next iteration */
454 }
455 if (*vp2 == ']') /* translation ends in ']' */
456 {
457 if (*(vp2-1) == '.') /* ends in '.]' */
458 {
459 if (strncmp (fptr, "000000", 6) != 0)
460 rooted = 0;
461 }
462 else
463 {
464 strcpy (vmsname, s1);
465 vp = strchr (vmsname, ']');
466 *vp = '.';
467 nstate = N_DOT;
468 vptr = vp;
469 }
470 }
471 break;
472 }
473 free (vp);
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 nstate = N_DOT;
489 strcpy (vptr, "[000000.");
490 vptr += 8;
491 vp = vptr-1;
492 }
493 else
494 vp = 0;
495
496 /* vp-> '.' 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 && (vp != 0)
524 && (*(s+1) == 0))
525 {
526 if (type == 2)
527 {
528 *vp = ']';
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 {
558 const char *s;
559 *vptr++ = '[';
560 nstate = N_OPEN;
561 s = strchr (fptr, '/');
562 if (s == 0) /* 10 */
563 {
564 if (type != 1)
565 {
566 strcpy (vptr, "000000]");
567 vptr += 7;
568 }
569 copyto (&vptr, &fptr, 0, (type == 1));
570 if (type == 1)
571 {
572 *vptr++ = ']';
573 }
574 state = -1;
575 }
576 else /* 11..15 */
577 {
578 if ( (type == 2)
579 && (*(s+1) == 0)) /* 11(2) */
580 {
581 strcpy (vptr, "000000]");
582 nstate = N_CLOSED;
583 vptr += 7;
584 }
585 copyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));
586 state = 9;
587 }
588 break;
589 }
590
591 case 7: /* add '.dir' and exit */
592 if ((nstate == N_OPEN)
593 || (nstate == N_DOT))
594 {
595 char *vp = vptr-1;
596 while (vp > vmsname)
597 {
598 if (*vp == ']')
599 {
600 break;
601 }
602 if (*vp == '.')
603 {
604 *vp = ']';
605 break;
606 }
607 vp--;
608 }
609 }
610 strcpy (vptr, ".dir");
611 vptr += 4;
612 state = -1;
613 break;
614
615 case 8: /* add ']' and exit */
616 *vptr++ = ']';
617 state = -1;
618 break;
619
620 case 9: /* 17..21, fptr -> 1st '/' + 1 */
621 {
622 const char *s;
623 if (*fptr == 0)
624 {
625 if (type == 2)
626 {
627 state = 7;
628 }
629 else
630 state = 8;
631 break;
632 }
633 s = strchr (fptr, '/');
634 if (s == 0)
635 {
636 if (type != 1)
637 {
638 if (nstate == N_OPEN)
639 {
640 *vptr++ = ']';
641 nstate = N_CLOSED;
642 }
643 as_dir = 0;
644 }
645 else
646 {
647 if (nstate == N_OPEN)
648 {
649 *vptr++ = '.';
650 nstate = N_DOT;
651 }
652 as_dir = 1;
653 }
654 }
655 else
656 {
657 while (*(s+1) == '/')
658 s++;
659 if ( (type == 2)
660 && (*(s+1) == 0)) /* 19(2), 21(2)*/
661 {
662 if (nstate != N_CLOSED)
663 {
664 *vptr++ = ']';
665 nstate = N_CLOSED;
666 }
667 as_dir = 1;
668 }
669 else
670 {
671 if (nstate == N_OPEN)
672 {
673 *vptr++ = '.';
674 nstate = N_DOT;
675 }
676 as_dir = 1;
677 }
678 }
679 if ( (*fptr == '.') /* check for '..' or '../' */
680 && (*(fptr+1) == '.')
681 && ((*(fptr+2) == '/')
682 || (*(fptr+2) == 0)) )
683 {
684 char *vp;
685 fptr += 2;
686 if (*fptr == '/')
687 {
688 do
689 {
690 fptr++;
691 }
692 while (*fptr == '/');
693 }
694 else if (*fptr == 0)
695 type = 1;
696 vptr--; /* vptr -> '.' or ']' */
697 vp = vptr;
698 for (;;)
699 {
700 vp--;
701 if (*vp == '.') /* one back */
702 {
703 vptr = vp;
704 nstate = N_OPEN;
705 break;
706 }
707 if (*vp == '[') /* top level reached */
708 {
709 if (*fptr == 0)
710 {
711 strcpy (vp, "[000000]");
712 vptr = vp + 8;
713 nstate = N_CLOSED;
714 s = 0;
715 break;
716 }
717 else
718 {
719 vptr = vp+1;
720 nstate = N_OPEN;
721 break;
722 }
723 }
724 }
725 }
726 else
727 {
728 copyto (&vptr, &fptr, '/', as_dir);
729 if (nstate == N_DOT)
730 nstate = N_OPEN;
731 }
732 if (s == 0)
733 { /* 18,20 */
734 if (type == 1)
735 *vptr++ = ']';
736 state = -1;
737 }
738 else
739 {
740 if (*(s+1) == 0)
741 {
742 if (type == 2) /* 19,21 */
743 {
744 state = 7;
745 }
746 else
747 {
748 *vptr++ = ']';
749 state = -1;
750 }
751 }
752 }
753 break;
754 }
755
756 case 10: /* 1,2 first is '.' */
757 if (*fptr == '.')
758 {
759 fptr++;
760 state = 11;
761 }
762 else
763 state = 12;
764 break;
765
766 case 11: /* 2, '..' at start */
767 count = 1;
768 if (*fptr != 0)
769 {
770 if (*fptr != '/') /* got ..xxx */
771 {
772 strcpy (vmsname, name);
773 return vmsname;
774 }
775 do /* got ../ */
776 {
777 fptr++;
778 while (*fptr == '/') fptr++;
779 if (*fptr != '.')
780 break;
781 if (*(fptr+1) != '.')
782 break;
783 fptr += 2;
784 if ((*fptr == 0)
785 || (*fptr == '/'))
786 count++;
787 }
788 while (*fptr == '/');
789 }
790 { /* got '..' or '../' */
791 char *vp;
792 char cwdbuf[MAXPATHLEN+1];
793
794 vp = getcwd(cwdbuf, MAXPATHLEN);
795 if (vp == 0)
796 {
797 vmsname[0] = '\0';
798 return vmsname; /* FIXME, err getcwd */
799 }
800 strcpy (vptr, vp);
801 vp = strchr (vptr, ']');
802 if (vp != 0)
803 {
804 nstate = N_OPEN;
805 while (vp > vptr)
806 {
807 vp--;
808 if (*vp == '[')
809 {
810 vp++;
811 strcpy (vp, "000000]");
812 state = -1;
813 break;
814 }
815 else if (*vp == '.')
816 {
817 if (--count == 0)
818 {
819 if (*fptr == 0) /* had '..' or '../' */
820 {
821 *vp++ = ']';
822 state = -1;
823 }
824 else /* had '../xxx' */
825 {
826 state = 9;
827 }
828 *vp = '\0';
829 break;
830 }
831 }
832 }
833 }
834 vptr += strlen (vptr);
835 }
836 break;
837
838 case 12: /* 1, '.' at start */
839 if (*fptr != 0)
840 {
841 if (*fptr != '/')
842 {
843 strcpy (vmsname, name);
844 return vmsname;
845 }
846 while (*fptr == '/')
847 fptr++;
848 }
849
850 {
851 char *vp;
852 char cwdbuf[MAXPATHLEN+1];
853
854 vp = getcwd(cwdbuf, MAXPATHLEN);
855 if (vp == 0)
856 {
857 vmsname[0] = '\0';
858 return vmsname; /*FIXME, err getcwd */
859 }
860 strcpy (vptr, vp);
861 }
862 if (*fptr == 0)
863 {
864 state = -1;
865 break;
866 }
867 else
868 {
869 char *vp = strchr (vptr, ']');
870 if (vp == 0)
871 {
872 state = -1;
873 break;
874 }
875 *vp = '\0';
876 nstate = N_OPEN;
877 vptr += strlen (vptr);
878 state = 9;
879 }
880 break;
881 }
882
883 }
884 while (state > 0);
885
886
887 }
888
889
890 /* directory conversion done
891 fptr -> filename part of input string
892 vptr -> free space in vmsname
893 */
894
895 *vptr++ = 0;
896
897 return vmsname;
898}
899
900
901
902/*
903 convert from vms-style to unix-style
904
905 dev:[dir1.dir2] //dev/dir1/dir2/
906*/
907
908const char *
909unixify (const char *name)
910{
911 static char piece[512];
912 const char *s;
913 char *p;
914
915 if (strchr (name, '/') != 0) /* already in unix style */
916 {
917 strcpy (piece, name);
918 return piece;
919 }
920
921 p = piece;
922 *p = 0;
923
924 /* device part */
925
926 s = strchr (name, ':');
927
928 if (s != 0)
929 {
930 int l = s - name;
931 *p++ = '/';
932 *p++ = '/';
933 strncpy (p, name, l);
934 p += l;
935 }
936
937 /* directory part */
938
939 *p++ = '/';
940 s = strchr (name, '[');
941
942 if (s != 0)
943 {
944 s++;
945 switch (*s)
946 {
947 case ']': /* [] */
948 strcat (p, "./");
949 break;
950 case '-': /* [- */
951 strcat (p, "../");
952 break;
953 case '.':
954 strcat (p, "./"); /* [. */
955 break;
956 default:
957 s--;
958 break;
959 }
960 s++;
961 while (*s)
962 {
963 if (*s == '.')
964 *p++ = '/';
965 else
966 *p++ = *s;
967 s++;
968 if (*s == ']')
969 {
970 s++;
971 break;
972 }
973 }
974 if (*s != 0) /* more after ']' ?? */
975 {
976 if (*(p-1) != '/')
977 *p++ = '/';
978 strcpy (p, s); /* copy it anyway */
979 }
980 }
981
982 else /* no '[' anywhere */
983
984 {
985 *p++ = 0;
986 }
987
988 /* force end with '/' */
989
990 if (*(p-1) != '/')
991 *p++ = '/';
992 *p = 0;
993
994 return piece;
995}
996
997/* EOF */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette