VirtualBox

source: kBuild/vendor/gnumake/2005-05-16/vmsify.c

Last change on this file was 54, checked in by (none), 21 years ago

This commit was manufactured by cvs2svn to create branch 'GNU'.

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