perl 4.0.00: (no release announcement available)
[p5sagit/p5-mst-13.2.git] / os2 / suffix.c
CommitLineData
e929a76b 1/*
2 * Suffix appending for in-place editing under MS-DOS and OS/2.
3 *
4 * Here are the rules:
5 *
6 * Style 0: Append the suffix exactly as standard perl would do it.
7 * If the filesystem groks it, use it. (HPFS will always
8 * grok it. FAT will rarely accept it.)
9 *
10 * Style 1: The suffix begins with a '.'. The extension is replaced.
11 * If the name matches the original name, use the fallback method.
12 *
13 * Style 2: The suffix is a single character, not a '.'. Try to add the
14 * suffix to the following places, using the first one that works.
15 * [1] Append to extension.
16 * [2] Append to filename,
17 * [3] Replace end of extension,
18 * [4] Replace end of filename.
19 * If the name matches the original name, use the fallback method.
20 *
21 * Style 3: Any other case: Ignore the suffix completely and use the
22 * fallback method.
23 *
24 * Fallback method: Change the extension to ".$$$". If that matches the
25 * original name, then change the extension to ".~~~".
26 *
27 * If filename is more than 1000 characters long, we die a horrible
28 * death. Sorry.
29 *
30 * The filename restriction is a cheat so that we can use buf[] to store
31 * assorted temporary goo.
32 *
33 * Examples, assuming style 0 failed.
34 *
35 * suffix = ".bak" (style 1)
36 * foo.bar => foo.bak
37 * foo.bak => foo.$$$ (fallback)
38 * foo.$$$ => foo.~~~ (fallback)
39 * makefile => makefile.bak
40 *
41 * suffix = "~" (style 2)
42 * foo.c => foo.c~
43 * foo.c~ => foo.c~~
44 * foo.c~~ => foo~.c~~
45 * foo~.c~~ => foo~~.c~~
46 * foo~~~~~.c~~ => foo~~~~~.$$$ (fallback)
47 *
48 * foo.pas => foo~.pas
49 * makefile => makefile.~
50 * longname.fil => longname.fi~
51 * longname.fi~ => longnam~.fi~
52 * longnam~.fi~ => longnam~.$$$
53 *
54 */
55
56#include "EXTERN.h"
57#include "perl.h"
58#ifdef OS2
59#define INCL_DOSFILEMGR
60#define INCL_DOSERRORS
61#include <os2.h>
62#endif /* OS2 */
63
64static char suffix1[] = ".$$$";
65static char suffix2[] = ".~~~";
66
67#define ext (&buf[1000])
68
69add_suffix(str,suffix)
70register STR *str;
71register char *suffix;
72{
73 int baselen;
74 int extlen;
75 char *s, *t, *p;
76 STRLEN slen;
77
78 if (!(str->str_pok)) (void)str_2ptr(str);
79 if (str->str_cur > 1000)
80 fatal("Cannot do inplace edit on long filename (%d characters)", str->str_cur);
81
82#ifdef OS2
83 /* Style 0 */
84 slen = str->str_cur;
85 str_cat(str, suffix);
86 if (valid_filename(str->str_ptr)) return;
87
88 /* Fooey, style 0 failed. Fix str before continuing. */
89 str->str_ptr[str->str_cur = slen] = '\0';
90#endif /* OS2 */
91
92 slen = strlen(suffix);
93 t = buf; baselen = 0; s = str->str_ptr;
94 while ( (*t = *s) && *s != '.') {
95 baselen++;
96 if (*s == '\\' || *s == '/') baselen = 0;
97 s++; t++;
98 }
99 p = t;
100
101 t = ext; extlen = 0;
102 while (*t++ = *s++) extlen++;
103 if (extlen == 0) { ext[0] = '.'; ext[1] = 0; extlen++; }
104
105 if (*suffix == '.') { /* Style 1 */
106 if (strEQ(ext, suffix)) goto fallback;
107 strcpy(p, suffix);
108 } else if (suffix[1] == '\0') { /* Style 2 */
109 if (extlen < 4) {
110 ext[extlen] = *suffix;
111 ext[++extlen] = '\0';
112 } else if (baselen < 8) {
113 *p++ = *suffix;
114 } else if (ext[3] != *suffix) {
115 ext[3] = *suffix;
116 } else if (buf[7] != *suffix) {
117 buf[7] = *suffix;
118 } else goto fallback;
119 strcpy(p, ext);
120 } else { /* Style 3: Panic */
121fallback:
122 (void)bcopy(strEQ(ext, suffix1) ? suffix2 : suffix1, p, 4+1);
123 }
124 str_set(str, buf);
125}
126
127#ifdef OS2
128int
129valid_filename(s)
130char *s;
131{
132 HFILE hf;
133 USHORT usAction;
134
135 switch(DosOpen(s, &hf, &usAction, 0L, 0, FILE_OPEN,
136 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0L)) {
fe14fcc3 137 case ERROR_INVALID_NAME:
138 case ERROR_FILENAME_EXCED_RANGE:
139 return 0;
e929a76b 140 case NO_ERROR:
141 DosClose(hf);
142 /*FALLTHROUGH*/
143 default:
144 return 1;
e929a76b 145 }
146}
147#endif /* OS2 */