VirtualBox

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

Last change on this file since 2657 was 2591, checked in by bird, 13 years ago

kmk: Merged in changes from GNU make 3.82. Previous GNU make base version was gnumake-2008-10-28-CVS.

  • Property svn:eol-style set to native
File size: 18.2 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, 2008, 2009, 2010 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 ([email protected])
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 /*
124 * the string isn't changed, but there is no string descriptor with
125 * "const char *dsc$a_pointer"
126 */
127 INIT_DSC_CSTRING (name_dsc, (char *)name);
128
129 stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
130
131 if ((stat&1) == 0)
132 {
133 return "";
134 }
135 if (stat == SS$_NOTRAN)
136 {
137 return "";
138 }
139 reslt[resltlen] = '\0';
140
141 s = malloc (resltlen+1);
142 if (s == 0)
143 return "";
144 strcpy (s, reslt);
145 return s;
146}
147
148static char *
149showall (char *s)
150{
151 static char t[512];
152 char *pt;
153
154 pt = t;
155 if (strchr (s, '\\') == 0)
156 return s;
157 while (*s)
158 {
159 if (*s == '\\')
160 {
161 *pt++ = *s;
162 }
163 *pt++ = *s++;
164 }
165 return pt;
166}
167
168
169enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
170
171/*
172 convert unix style name to vms style
173 type = 0 -> name is a full name (directory and filename part)
174 type = 1 -> name is a directory
175 type = 2 -> name is a filename without directory
176
177 The following conversions are applied
178 (0) (1) (2)
179 input full name dir name file name
180
1811 ./ <cwd> [] <current directory>.dir
1822 ../ <home of cwd> <home of cwd> <home of cwd>.dir
183
1843 // <dev of cwd>: <dev of cwd>:[000000] <dev of cwd>:000000.dir
1854 //a a: a: a:
1865 //a/ a: a: a:000000.dir
187
1889 / [000000] [000000] 000000.dir
18910 /a [000000]a [a] [000000]a
19011 /a/ [a] [a] [000000]a.dir
19112 /a/b [a]b [a.b] [a]b
19213 /a/b/ [a.b] [a.b] [a]b.dir
19314 /a/b/c [a.b]c [a.b.c] [a.b]c
19415 /a/b/c/ [a.b.c] [a.b.c] [a.b]c.dir
195
19616 a a [.a] a
19717 a/ [.a] [.a] a.dir
19818 a/b [.a]b [.a.b] [.a]b
19919 a/b/ [.a.b] [.a.b] [.a]b.dir
20020 a/b/c [.a.b]c [.a.b.c] [.a.b]c
20121 a/b/c/ [.a.b.c] [.a.b.c] [.a.b]c.dir
202
20322 a.b.c a_b.c [.a_b_c] a_b_c.dir
204
20523 [x][y]z [x.y]z [x.y]z [x.y]z
20624 [x][.y]z [x.y]z [x.y]z [x.y]z
207
20825 filenames with '$' are left unchanged if they contain no '/'
20925 filenames with ':' are left unchanged
21026 filenames with a single pair of '[' ']' are left unchanged
211
212 The input string is not written to. The result is also const because
213 it's a static buffer; we don't want to change it.
214*/
215
216const char *
217vmsify (const char *name, int type)
218{
219/* max 255 device
220 max 39 directory
221 max 39 filename
222 max 39 filetype
223 max 5 version
224*/
225#define MAXPATHLEN 512
226
227 enum namestate nstate;
228 static char vmsname[MAXPATHLEN+1];
229 const char *fptr;
230 const char *t;
231 char *vptr;
232 int as_dir;
233 int count;
234 const char *s;
235 const char *s1;
236 const char *s2;
237
238 if (name == 0)
239 return 0;
240 fptr = name;
241 vptr = vmsname;
242 nstate = N_START;
243
244 /* case 25a */
245 t = strpbrk (name, "$:");
246
247 if (t != 0)
248 {
249// const char *s1;
250// const char *s2;
251
252 if (type == 1)
253 {
254 s1 = strchr (t+1, '[');
255 s2 = strchr (t+1, ']');
256 }
257
258 if (*t == '$')
259 {
260 if (strchr (name, '/') == 0)
261 {
262 strcpy (vmsname, name);
263 if ((type == 1) && (s1 != 0) && (s2 == 0))
264 strcat (vmsname, "]");
265 return vmsname;
266 }
267 }
268 else
269 {
270 strcpy (vmsname, name);
271 if ((type == 1) && (s1 != 0) && (s2 == 0))
272 strcat (vmsname, "]");
273 return vmsname;
274 }
275 }
276
277 /* case 26 */
278 t = strchr (name, '[');
279
280 if (t != 0)
281 {
282// const char *s;
283// const char *s1 = strchr (t+1, '[');
284 s1 = strchr (t+1, '[');
285 if (s1 == 0)
286 {
287 strcpy (vmsname, name);
288 if ((type == 1) && (strchr (t+1, ']') == 0))
289 strcat (vmsname, "]");
290 return vmsname;
291 }
292 s1--;
293 if (*s1 != ']')
294 {
295 strcpy (vmsname, name);
296 return vmsname; /* not ][, keep unchanged */
297 }
298
299 /* we have ][ */
300
301 s = name;
302
303 /* s -> starting char
304 s1 -> ending ']' */
305 do
306 {
307 strncpy (vptr, s, s1-s); /* copy up to but not including ']' */
308 vptr += s1-s;
309 if (*s1 == 0)
310 break;
311 s = s1 + 1; /* s -> char behind ']' */
312 if (*s != '[') /* was '][' ? */
313 break; /* no, last ] found, exit */
314 s++;
315 if (*s != '.')
316 *vptr++ = '.';
317 s1 = strchr (s, ']');
318 if (s1 == 0) /* no closing ] */
319 s1 = s + strlen (s);
320 }
321 while (1);
322
323 *vptr++ = ']';
324
325 fptr = s;
326
327 }
328 else /* no [ in name */
329 {
330 int state = 0;
331 int rooted = 1; /* flag if logical is rooted, else insert [000000] */
332
333 do
334 {
335 switch (state)
336 {
337 case 0: /* start of loop */
338 if (*fptr == '/')
339 {
340 fptr++;
341 state = 1;
342 }
343 else if (*fptr == '.')
344 {
345 fptr++;
346 state = 10;
347 }
348 else
349 state = 2;
350 break;
351
352 case 1: /* '/' at start */
353 if (*fptr == '/')
354 {
355 fptr++;
356 state = 3;
357 }
358 else
359 state = 4;
360 break;
361
362 case 2: /* no '/' at start */
363 {
364 const char *s = strchr (fptr, '/');
365 if (s == 0) /* no '/' (16) */
366 {
367 if (type == 1)
368 {
369 strcpy (vptr, "[.");
370 vptr += 2;
371 }
372 copyto (&vptr, &fptr, 0, (type==1));
373 if (type == 1)
374 *vptr++ = ']';
375 state = -1;
376 }
377 else /* found '/' (17..21) */
378 {
379 if ((type == 2)
380 && (*(s+1) == 0)) /* 17(2) */
381 {
382 copyto (&vptr, &fptr, '/', 1);
383 state = 7;
384 }
385 else
386 {
387 strcpy (vptr, "[.");
388 vptr += 2;
389 copyto (&vptr, &fptr, '/', 1);
390 nstate = N_OPEN;
391 state = 9;
392 }
393 }
394 break;
395 }
396
397 case 3: /* '//' at start */
398 {
399// const char *s;
400// const char *s1;
401 char *vp;
402 while (*fptr == '/') /* collapse all '/' */
403 fptr++;
404 if (*fptr == 0) /* just // */
405 {
406 char cwdbuf[MAXPATHLEN+1];
407
408 s1 = getcwd(cwdbuf, MAXPATHLEN);
409 if (s1 == 0)
410 {
411 vmsname[0] = '\0';
412 return vmsname; /* FIXME, err getcwd */
413 }
414 s = strchr (s1, ':');
415 if (s == 0)
416 {
417 vmsname[0] = '\0';
418 return vmsname; /* FIXME, err no device */
419 }
420 strncpy (vptr, s1, s-s1+1);
421 vptr += s-s1+1;
422 state = -1;
423 break;
424 }
425
426 s = vptr;
427
428 if (copyto (&vptr, &fptr, '/', 1) == 0) /* copy device part */
429 {
430 *vptr++ = ':';
431 state = -1;
432 break;
433 }
434 *vptr = ':';
435 nstate = N_DEVICE;
436 if (*fptr == 0) /* just '//a/' */
437 {
438 strcpy (vptr+1, "[000000]");
439 vptr += 9;
440 state = -1;
441 break;
442 }
443 *vptr = 0;
444 /* check logical for [000000] insertion */
445 vp = trnlog (s);
446 if (*vp != '\0')
447 { /* found translation */
448 for (;;) /* loop over all nested logicals */
449 {
450 char *vp2 = vp + strlen (vp) - 1;
451 if (*vp2 == ':') /* translation ends in ':' */
452 {
453 vp2 = trnlog (vp);
454 free (vp);
455 if (*vp2 == 0)
456 {
457 rooted = 0;
458 break;
459 }
460 vp = vp2;
461 continue; /* next iteration */
462 }
463 if (*vp2 == ']') /* translation ends in ']' */
464 {
465 if (*(vp2-1) == '.') /* ends in '.]' */
466 {
467 if (strncmp (fptr, "000000", 6) != 0)
468 rooted = 0;
469 }
470 else
471 {
472 strcpy (vmsname, s1);
473 vp = strchr (vmsname, ']');
474 *vp = '.';
475 nstate = N_DOT;
476 vptr = vp;
477 }
478 }
479 break;
480 }
481 free (vp);
482 }
483 else
484 rooted = 0;
485
486 if (*vptr == 0)
487 {
488 nstate = N_DEVICE;
489 *vptr++ = ':';
490 }
491 else
492 vptr++;
493
494 if (rooted == 0)
495 {
496 nstate = N_DOT;
497 strcpy (vptr, "[000000.");
498 vptr += 8;
499 vp = vptr-1;
500 }
501 else
502 vp = 0;
503
504 /* vp-> '.' after 000000 or NULL */
505
506 s = strchr (fptr, '/');
507 if (s == 0)
508 { /* no next '/' */
509 if (*(vptr-1) == '.')
510 *(vptr-1) = ']';
511 else if (rooted == 0)
512 *vptr++ = ']';
513 copyto (&vptr, &fptr, 0, (type == 1));
514 state = -1;
515 break;
516 }
517 else
518 {
519 while (*(s+1) == '/') /* skip multiple '/' */
520 s++;
521 }
522
523 if ((rooted != 0)
524 && (*(vptr-1) != '.'))
525 {
526 *vptr++ = '[';
527 nstate = N_DOT;
528 }
529 else
530 if ((nstate == N_DOT)
531 && (vp != 0)
532 && (*(s+1) == 0))
533 {
534 if (type == 2)
535 {
536 *vp = ']';
537 nstate = N_CLOSED;
538 }
539 }
540 state = 9;
541 break;
542 }
543 case 4: /* single '/' at start (9..15) */
544 if (*fptr == 0)
545 state = 5;
546 else
547 state = 6;
548 break;
549
550 case 5: /* just '/' at start (9) */
551 if (type != 2)
552 {
553 *vptr++ = '[';
554 nstate = N_OPEN;
555 }
556 strcpy (vptr, "000000");
557 vptr += 6;
558 if (type == 2)
559 state = 7;
560 else
561 state = 8;
562 break;
563
564 case 6: /* chars following '/' at start 10..15 */
565 {
566 const char *s;
567 *vptr++ = '[';
568 nstate = N_OPEN;
569 s = strchr (fptr, '/');
570 if (s == 0) /* 10 */
571 {
572 if (type != 1)
573 {
574 strcpy (vptr, "000000]");
575 vptr += 7;
576 }
577 copyto (&vptr, &fptr, 0, (type == 1));
578 if (type == 1)
579 {
580 *vptr++ = ']';
581 }
582 state = -1;
583 }
584 else /* 11..15 */
585 {
586 if ( (type == 2)
587 && (*(s+1) == 0)) /* 11(2) */
588 {
589 strcpy (vptr, "000000]");
590 nstate = N_CLOSED;
591 vptr += 7;
592 }
593 copyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));
594 state = 9;
595 }
596 break;
597 }
598
599 case 7: /* add '.dir' and exit */
600 if ((nstate == N_OPEN)
601 || (nstate == N_DOT))
602 {
603 char *vp = vptr-1;
604 while (vp > vmsname)
605 {
606 if (*vp == ']')
607 {
608 break;
609 }
610 if (*vp == '.')
611 {
612 *vp = ']';
613 break;
614 }
615 vp--;
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 {
630 const char *s;
631 if (*fptr == 0)
632 {
633 if (type == 2)
634 {
635 state = 7;
636 }
637 else
638 state = 8;
639 break;
640 }
641 s = strchr (fptr, '/');
642 if (s == 0)
643 {
644 if (type != 1)
645 {
646 if (nstate == N_OPEN)
647 {
648 *vptr++ = ']';
649 nstate = N_CLOSED;
650 }
651 as_dir = 0;
652 }
653 else
654 {
655 if (nstate == N_OPEN)
656 {
657 *vptr++ = '.';
658 nstate = N_DOT;
659 }
660 as_dir = 1;
661 }
662 }
663 else
664 {
665 while (*(s+1) == '/')
666 s++;
667 if ( (type == 2)
668 && (*(s+1) == 0)) /* 19(2), 21(2)*/
669 {
670 if (nstate != N_CLOSED)
671 {
672 *vptr++ = ']';
673 nstate = N_CLOSED;
674 }
675 as_dir = 1;
676 }
677 else
678 {
679 if (nstate == N_OPEN)
680 {
681 *vptr++ = '.';
682 nstate = N_DOT;
683 }
684 as_dir = 1;
685 }
686 }
687 if ( (*fptr == '.') /* check for '..' or '../' */
688 && (*(fptr+1) == '.')
689 && ((*(fptr+2) == '/')
690 || (*(fptr+2) == 0)) )
691 {
692 char *vp;
693 fptr += 2;
694 if (*fptr == '/')
695 {
696 do
697 {
698 fptr++;
699 }
700 while (*fptr == '/');
701 }
702 else if (*fptr == 0)
703 type = 1;
704 vptr--; /* vptr -> '.' or ']' */
705 vp = vptr;
706 for (;;)
707 {
708 vp--;
709 if (*vp == '.') /* one back */
710 {
711 vptr = vp;
712 nstate = N_OPEN;
713 break;
714 }
715 if (*vp == '[') /* top level reached */
716 {
717 if (*fptr == 0)
718 {
719 strcpy (vp, "[000000]");
720 vptr = vp + 8;
721 nstate = N_CLOSED;
722 s = 0;
723 break;
724 }
725 else
726 {
727 vptr = vp+1;
728 nstate = N_OPEN;
729 break;
730 }
731 }
732 }
733 }
734 else
735 {
736 copyto (&vptr, &fptr, '/', as_dir);
737 if (nstate == N_DOT)
738 nstate = N_OPEN;
739 }
740 if (s == 0)
741 { /* 18,20 */
742 if (type == 1)
743 *vptr++ = ']';
744 state = -1;
745 }
746 else
747 {
748 if (*(s+1) == 0)
749 {
750 if (type == 2) /* 19,21 */
751 {
752 state = 7;
753 }
754 else
755 {
756 *vptr++ = ']';
757 state = -1;
758 }
759 }
760 }
761 break;
762 }
763
764 case 10: /* 1,2 first is '.' */
765 if (*fptr == '.')
766 {
767 fptr++;
768 state = 11;
769 }
770 else
771 state = 12;
772 break;
773
774 case 11: /* 2, '..' at start */
775 count = 1;
776 if (*fptr != 0)
777 {
778 if (*fptr != '/') /* got ..xxx */
779 {
780 strcpy (vmsname, name);
781 return vmsname;
782 }
783 do /* got ../ */
784 {
785 fptr++;
786 while (*fptr == '/') fptr++;
787 if (*fptr != '.')
788 break;
789 if (*(fptr+1) != '.')
790 break;
791 fptr += 2;
792 if ((*fptr == 0)
793 || (*fptr == '/'))
794 count++;
795 }
796 while (*fptr == '/');
797 }
798 { /* got '..' or '../' */
799 char *vp;
800 char cwdbuf[MAXPATHLEN+1];
801
802 vp = getcwd(cwdbuf, MAXPATHLEN);
803 if (vp == 0)
804 {
805 vmsname[0] = '\0';
806 return vmsname; /* FIXME, err getcwd */
807 }
808 strcpy (vptr, vp);
809 vp = strchr (vptr, ']');
810 if (vp != 0)
811 {
812 nstate = N_OPEN;
813 while (vp > vptr)
814 {
815 vp--;
816 if (*vp == '[')
817 {
818 vp++;
819 strcpy (vp, "000000]");
820 state = -1;
821 break;
822 }
823 else if (*vp == '.')
824 {
825 if (--count == 0)
826 {
827 if (*fptr == 0) /* had '..' or '../' */
828 {
829 *vp++ = ']';
830 state = -1;
831 }
832 else /* had '../xxx' */
833 {
834 state = 9;
835 }
836 *vp = '\0';
837 break;
838 }
839 }
840 }
841 }
842 vptr += strlen (vptr);
843 }
844 break;
845
846 case 12: /* 1, '.' at start */
847 if (*fptr != 0)
848 {
849 if (*fptr != '/')
850 {
851 strcpy (vmsname, name);
852 return vmsname;
853 }
854 while (*fptr == '/')
855 fptr++;
856 }
857
858 {
859 char *vp;
860 char cwdbuf[MAXPATHLEN+1];
861
862 vp = getcwd(cwdbuf, MAXPATHLEN);
863 if (vp == 0)
864 {
865 vmsname[0] = '\0';
866 return vmsname; /*FIXME, err getcwd */
867 }
868 strcpy (vptr, vp);
869 }
870 if (*fptr == 0)
871 {
872 state = -1;
873 break;
874 }
875 else
876 {
877 char *vp = strchr (vptr, ']');
878 if (vp == 0)
879 {
880 state = -1;
881 break;
882 }
883 *vp = '\0';
884 nstate = N_OPEN;
885 vptr += strlen (vptr);
886 state = 9;
887 }
888 break;
889 }
890
891 }
892 while (state > 0);
893
894
895 }
896
897
898 /* directory conversion done
899 fptr -> filename part of input string
900 vptr -> free space in vmsname
901 */
902
903 *vptr++ = 0;
904
905 return vmsname;
906}
907
908
909
910/*
911 convert from vms-style to unix-style
912
913 dev:[dir1.dir2] //dev/dir1/dir2/
914*/
915
916const char *
917unixify (const char *name)
918{
919 static char piece[512];
920 const char *s;
921 char *p;
922
923 if (strchr (name, '/') != 0) /* already in unix style */
924 {
925 strcpy (piece, name);
926 return piece;
927 }
928
929 p = piece;
930 *p = 0;
931
932 /* device part */
933
934 s = strchr (name, ':');
935
936 if (s != 0)
937 {
938 int l = s - name;
939 *p++ = '/';
940 *p++ = '/';
941 strncpy (p, name, l);
942 p += l;
943 }
944
945 /* directory part */
946
947 *p++ = '/';
948 s = strchr (name, '[');
949
950 if (s != 0)
951 {
952 s++;
953 switch (*s)
954 {
955 case ']': /* [] */
956 strcat (p, "./");
957 break;
958 case '-': /* [- */
959 strcat (p, "../");
960 break;
961 case '.':
962 strcat (p, "./"); /* [. */
963 break;
964 default:
965 s--;
966 break;
967 }
968 s++;
969 while (*s)
970 {
971 if (*s == '.')
972 *p++ = '/';
973 else
974 *p++ = *s;
975 s++;
976 if (*s == ']')
977 {
978 s++;
979 break;
980 }
981 }
982 if (*s != 0) /* more after ']' ?? */
983 {
984 if (*(p-1) != '/')
985 *p++ = '/';
986 strcpy (p, s); /* copy it anyway */
987 }
988 }
989
990 else /* no '[' anywhere */
991
992 {
993 *p++ = 0;
994 }
995
996 /* force end with '/' */
997
998 if (*(p-1) != '/')
999 *p++ = '/';
1000 *p = 0;
1001
1002 return piece;
1003}
1004
1005/* 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