VirtualBox

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

Last change on this file since 3387 was 3140, checked in by bird, 6 years ago

kmk: Merged in changes from GNU make 4.2.1 (2e55f5e4abdc0e38c1d64be703b446695e70b3b6 / https://git.savannah.gnu.org/git/make.git).

  • 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-2016 Free Software Foundation, Inc.
3This file is part of GNU Make.
4
5GNU Make is free software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the Free Software
7Foundation; either version 3 of the License, or (at your option) any later
8version.
9
10GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program. If not, see <http://www.gnu.org/licenses/>. */
16
17/* Written by Klaus Kämpf (kkaempf@progis.de)
18 of proGIS Software, Aachen, Germany */
19
20
21#include <stdio.h>
22#include <string.h>
23#include <ctype.h>
24
25#include "makeint.h"
26
27#if VMS
28#include <unixlib.h>
29#include <stdlib.h>
30#include <jpidef.h>
31#include <descrip.h>
32#include <uaidef.h>
33#include <ssdef.h>
34#include <starlet.h>
35#include <lib$routines.h>
36/* Initialize a string descriptor (struct dsc$descriptor_s) for an
37 arbitrary string. ADDR is a pointer to the first character
38 of the string, and LEN is the length of the string. */
39
40#define INIT_DSC_S(dsc, addr, len) do { \
41 (dsc).dsc$b_dtype = DSC$K_DTYPE_T; \
42 (dsc).dsc$b_class = DSC$K_CLASS_S; \
43 (dsc).dsc$w_length = (len); \
44 (dsc).dsc$a_pointer = (addr); \
45} while (0)
46
47/* Initialize a string descriptor (struct dsc$descriptor_s) for a
48 NUL-terminated string. S is a pointer to the string; the length
49 is determined by calling strlen(). */
50
51#define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))
52#endif
53
54/*
55 copy 'from' to 'to' up to but not including 'upto'
56 return 0 if eos on from
57 return 1 if upto found
58
59 return 'to' at last char + 1
60 return 'from' at match + 1 or eos if no match
61
62 if as_dir == 1, change all '.' to '_'
63 else change all '.' but the last to '_'
64*/
65
66static int
67copyto (char **to, const char **from, char upto, int as_dir)
68{
69 const char *s;
70
71 s = strrchr (*from, '.');
72
73 while (**from)
74 {
75 if (**from == upto)
76 {
77 do
78 {
79 (*from)++;
80 }
81 while (**from == upto);
82 return 1;
83 }
84 if (**from == '.')
85 {
86 if ((as_dir == 1)
87 || (*from != s))
88 **to = '_';
89 else
90 **to = '.';
91 }
92 else
93 {
94#ifdef HAVE_CASE_INSENSITIVE_FS
95 if (isupper ((unsigned char)**from))
96 **to = tolower ((unsigned char)**from);
97 else
98#endif
99 **to = **from;
100 }
101 (*to)++;
102 (*from)++;
103 }
104
105 return 0;
106}
107
108
109/*
110 get translation of logical name
111
112*/
113
114static char *
115trnlog (const char *name)
116{
117 int stat;
118 static char reslt[1024];
119 $DESCRIPTOR (reslt_dsc, reslt);
120 short resltlen;
121 struct dsc$descriptor_s name_dsc;
122 char *s;
123
124 /*
125 * the string isn't changed, but there is no string descriptor with
126 * "const char *dsc$a_pointer"
127 */
128 INIT_DSC_CSTRING (name_dsc, (char *)name);
129
130 stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
131
132 if ((stat&1) == 0)
133 {
134 return "";
135 }
136 if (stat == SS$_NOTRAN)
137 {
138 return "";
139 }
140 reslt[resltlen] = '\0';
141
142 s = xmalloc (resltlen+1);
143 strcpy (s, reslt);
144 return s;
145}
146
147static char *
148showall (char *s)
149{
150 static char t[512];
151 char *pt;
152
153 pt = t;
154 if (strchr (s, '\\') == 0)
155 return s;
156 while (*s)
157 {
158 if (*s == '\\')
159 {
160 *pt++ = *s;
161 }
162 *pt++ = *s++;
163 }
164 return pt;
165}
166
167
168enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
169
170/*
171 convert unix style name to vms style
172 type = 0 -> name is a full name (directory and filename part)
173 type = 1 -> name is a directory
174 type = 2 -> name is a filename without directory
175
176 The following conversions are applied
177 (0) (1) (2)
178 input full name dir name file name
179
1801 ./ <cwd> [] <current directory>.dir
1812 ../ <home of cwd> <home of cwd> <home of cwd>.dir
182
1833 // <dev of cwd>: <dev of cwd>:[000000] <dev of cwd>:000000.dir
1844 //a a: a: a:
1855 //a/ a: a: a:000000.dir
186
1879 / [000000] [000000] 000000.dir
18810 /a [000000]a [a] [000000]a
18911 /a/ [a] [a] [000000]a.dir
19012 /a/b [a]b [a.b] [a]b
19113 /a/b/ [a.b] [a.b] [a]b.dir
19214 /a/b/c [a.b]c [a.b.c] [a.b]c
19315 /a/b/c/ [a.b.c] [a.b.c] [a.b]c.dir
194
19516 a a [.a] a
19617 a/ [.a] [.a] a.dir
19718 a/b [.a]b [.a.b] [.a]b
19819 a/b/ [.a.b] [.a.b] [.a]b.dir
19920 a/b/c [.a.b]c [.a.b.c] [.a.b]c
20021 a/b/c/ [.a.b.c] [.a.b.c] [.a.b]c.dir
201
20222 a.b.c a_b.c [.a_b_c] a_b_c.dir
203
20423 [x][y]z [x.y]z [x.y]z [x.y]z
20524 [x][.y]z [x.y]z [x.y]z [x.y]z
206
20725 filenames with '$' are left unchanged if they contain no '/'
20825 filenames with ':' are left unchanged
20926 filenames with a single pair of '[' ']' are left unchanged
210
211 The input string is not written to. The result is also const because
212 it's a static buffer; we don't want to change it.
213*/
214
215const char *
216vmsify (const char *name, int type)
217{
218/* max 255 device
219 max 39 directory
220 max 39 filename
221 max 39 filetype
222 max 5 version
223*/
224/* todo: VMSMAXPATHLEN is defined for ODS2 names: it needs to be adjusted. */
225#define VMSMAXPATHLEN 512
226
227 enum namestate nstate;
228 static char vmsname[VMSMAXPATHLEN+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[VMSMAXPATHLEN+1];
407
408 s1 = getcwd(cwdbuf, VMSMAXPATHLEN);
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[VMSMAXPATHLEN+1];
801
802 vp = getcwd(cwdbuf, VMSMAXPATHLEN);
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[VMSMAXPATHLEN+1];
861
862 vp = getcwd(cwdbuf, VMSMAXPATHLEN);
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.

© 2023 Oracle
ContactPrivacy policyTerms of Use