1 | /* |
---|
2 | ** DosFCheck - check file names for DOS consistency |
---|
3 | ** |
---|
4 | ** Distribute freely, it only encourages DOS compatibility! |
---|
5 | ** - DJ Delorie |
---|
6 | */ |
---|
7 | |
---|
8 | /* This file is not part of GCC. */ |
---|
9 | |
---|
10 | #include <stdio.h> |
---|
11 | #ifdef __MSDOS__ |
---|
12 | #include <alloc.h> |
---|
13 | #else |
---|
14 | #include <malloc.h> |
---|
15 | #endif |
---|
16 | #include <ctype.h> |
---|
17 | #include <string.h> |
---|
18 | |
---|
19 | typedef struct ENT |
---|
20 | { |
---|
21 | struct ENT *next; |
---|
22 | char *dos_name; |
---|
23 | char *full_name; |
---|
24 | char *path; |
---|
25 | int tagged; |
---|
26 | } ENT; |
---|
27 | |
---|
28 | ENT *eroot = 0; |
---|
29 | |
---|
30 | int first_inv = 1; |
---|
31 | int first_msg = 1; |
---|
32 | |
---|
33 | /****************************************************************\ |
---|
34 | * Utility routines * |
---|
35 | \****************************************************************/ |
---|
36 | |
---|
37 | void |
---|
38 | invalid_msg () |
---|
39 | { |
---|
40 | if (first_inv) |
---|
41 | { |
---|
42 | if (first_msg) |
---|
43 | first_msg = 0; |
---|
44 | else |
---|
45 | putchar ('\n'); |
---|
46 | printf ("The following files are not valid DOS file names:\n"); |
---|
47 | first_inv = 0; |
---|
48 | } |
---|
49 | } |
---|
50 | |
---|
51 | ENT * |
---|
52 | alloc_ent () |
---|
53 | { |
---|
54 | ENT *rv = (ENT *)malloc (sizeof (ENT)); |
---|
55 | if (rv == 0) |
---|
56 | { |
---|
57 | fprintf (stderr, "Unable to allocate memory for an ENT\n"); |
---|
58 | exit (1); |
---|
59 | } |
---|
60 | memset (rv, 0, sizeof (ENT)); |
---|
61 | return rv; |
---|
62 | } |
---|
63 | |
---|
64 | void |
---|
65 | fill_ent (ent, path) |
---|
66 | ENT *ent; |
---|
67 | char *path; |
---|
68 | { |
---|
69 | char *first = path; |
---|
70 | char *null = path+strlen (path); |
---|
71 | char *last_slash = strrchr (path, '/'); |
---|
72 | char *cp, *dp; |
---|
73 | int dots_seen, chars_seen; |
---|
74 | |
---|
75 | if (last_slash+1 == null) |
---|
76 | { |
---|
77 | * --null = '\0'; |
---|
78 | last_slash = strrchr (path, '/'); |
---|
79 | } |
---|
80 | |
---|
81 | if (!last_slash) |
---|
82 | { |
---|
83 | last_slash = first-1; |
---|
84 | } |
---|
85 | |
---|
86 | if (null-last_slash < 13) |
---|
87 | ent->dos_name = (char *)malloc (null-last_slash); |
---|
88 | else |
---|
89 | ent->dos_name = (char *)malloc (13); |
---|
90 | ent->full_name = (char *)malloc (null-last_slash); |
---|
91 | ent->path = (char *)malloc (last_slash-first+1); |
---|
92 | |
---|
93 | strcpy (ent->full_name, last_slash+1); |
---|
94 | if (last_slash > first) |
---|
95 | { |
---|
96 | strncpy (ent->path, first, last_slash-first); |
---|
97 | ent->path[last_slash-first] = '\0'; |
---|
98 | } |
---|
99 | else |
---|
100 | *ent->path = '\0'; |
---|
101 | |
---|
102 | cp = last_slash+1; |
---|
103 | dp = ent->dos_name; |
---|
104 | dots_seen = 0; |
---|
105 | chars_seen = 0; |
---|
106 | while (1) |
---|
107 | { |
---|
108 | if (! *cp) |
---|
109 | break; |
---|
110 | switch (*cp) |
---|
111 | { |
---|
112 | case '.': |
---|
113 | if (cp == last_slash+1 && strcmp (last_slash+1, ".")) |
---|
114 | { |
---|
115 | invalid_msg (); |
---|
116 | printf ("%s - file name cannot start with dot\n", path); |
---|
117 | *dp = 0; |
---|
118 | break; |
---|
119 | } |
---|
120 | if (dots_seen == 1) |
---|
121 | { |
---|
122 | invalid_msg (); |
---|
123 | printf ("%s - too many dots\n", path); |
---|
124 | *dp = '\0'; |
---|
125 | break; |
---|
126 | } |
---|
127 | *dp++ = '.'; |
---|
128 | chars_seen = 0; |
---|
129 | dots_seen++; |
---|
130 | break; |
---|
131 | case '"': |
---|
132 | case '*': |
---|
133 | case '+': |
---|
134 | case ',': |
---|
135 | case ';': |
---|
136 | case '<': |
---|
137 | case '=': |
---|
138 | case '>': |
---|
139 | case '?': |
---|
140 | case '[': |
---|
141 | case '\\': |
---|
142 | case ']': |
---|
143 | case '|': |
---|
144 | invalid_msg (); |
---|
145 | printf ("%s - invalid character `%c'\n", path, *cp); |
---|
146 | *dp++ = '?'; |
---|
147 | chars_seen++; |
---|
148 | break; |
---|
149 | default: |
---|
150 | if (dots_seen) |
---|
151 | { |
---|
152 | if (chars_seen >= 3) |
---|
153 | break; |
---|
154 | } |
---|
155 | else |
---|
156 | if (chars_seen >= 8) |
---|
157 | break; |
---|
158 | if ((*cp <= ' ') || (*cp >= 0x7f)) |
---|
159 | { |
---|
160 | invalid_msg (); |
---|
161 | printf ("%s - invalid character `%c'\n", path, *cp); |
---|
162 | *dp++ = '?'; |
---|
163 | chars_seen++; |
---|
164 | break; |
---|
165 | } |
---|
166 | if (islower (*cp)) |
---|
167 | *dp++ = toupper (*cp); |
---|
168 | else |
---|
169 | *dp++ = *cp; |
---|
170 | chars_seen++; |
---|
171 | break; |
---|
172 | } |
---|
173 | cp++; |
---|
174 | } |
---|
175 | *dp++ = '\0'; |
---|
176 | } |
---|
177 | |
---|
178 | int |
---|
179 | compare_ent_dosname (e1, e2) |
---|
180 | ENT **e1; |
---|
181 | ENT **e2; |
---|
182 | { |
---|
183 | int r = strcmp ((*e1)->dos_name, (*e2)->dos_name); |
---|
184 | if (r == 0) |
---|
185 | r = strcmp ((*e1)->path, (*e2)->path); |
---|
186 | if (r == 0) |
---|
187 | r = strcmp ((*e1)->full_name, (*e2)->full_name); |
---|
188 | return r; |
---|
189 | } |
---|
190 | |
---|
191 | int |
---|
192 | compare_ent_fullname (e1, e2) |
---|
193 | ENT **e1; |
---|
194 | ENT **e2; |
---|
195 | { |
---|
196 | int r = strncmp ((*e1)->full_name, (*e2)->full_name, 14); |
---|
197 | if (r == 0) |
---|
198 | r = strcmp ((*e1)->path, (*e2)->path); |
---|
199 | if (r == 0) |
---|
200 | r = strcmp ((*e1)->full_name, (*e2)->full_name); |
---|
201 | return r; |
---|
202 | } |
---|
203 | |
---|
204 | char * |
---|
205 | mpath (ent) |
---|
206 | ENT *ent; |
---|
207 | { |
---|
208 | static char buf[500]; |
---|
209 | if (ent->path && ent->path[0]) |
---|
210 | sprintf (buf, "%s/%s", ent->path, ent->full_name); |
---|
211 | else |
---|
212 | return ent->full_name; |
---|
213 | return buf; |
---|
214 | } |
---|
215 | |
---|
216 | /****************************************************************\ |
---|
217 | * List handling routines * |
---|
218 | \****************************************************************/ |
---|
219 | |
---|
220 | void |
---|
221 | add_ent (ent) |
---|
222 | ENT *ent; |
---|
223 | { |
---|
224 | ent->next = eroot; |
---|
225 | eroot = ent; |
---|
226 | } |
---|
227 | |
---|
228 | void |
---|
229 | handle_input (line) |
---|
230 | char *line; |
---|
231 | { |
---|
232 | ENT *ent = alloc_ent (); |
---|
233 | fill_ent (ent, line); |
---|
234 | add_ent (ent); |
---|
235 | } |
---|
236 | |
---|
237 | void |
---|
238 | display_problems () |
---|
239 | { |
---|
240 | ENT **elist, *ent; |
---|
241 | int ecount, i, first, first_err; |
---|
242 | |
---|
243 | for (ecount=0, ent=eroot; ent; ent=ent->next, ecount++); |
---|
244 | elist = (ENT **)malloc (sizeof (ENT *) * ecount); |
---|
245 | for (ecount=0, ent=eroot; ent; ent=ent->next, ecount++) |
---|
246 | elist[ecount] = ent; |
---|
247 | |
---|
248 | qsort (elist, ecount, sizeof (ENT *), compare_ent_dosname); |
---|
249 | |
---|
250 | first = 1; |
---|
251 | first_err = 1; |
---|
252 | for (i=0; i<ecount-1; i++) |
---|
253 | { |
---|
254 | if ((strcmp (elist[i]->dos_name, elist[i+1]->dos_name) == 0) && |
---|
255 | (strcmp (elist[i]->path, elist[i+1]->path) == 0)) |
---|
256 | { |
---|
257 | if (first_err) |
---|
258 | { |
---|
259 | if (first_msg) |
---|
260 | first_msg = 0; |
---|
261 | else |
---|
262 | putchar ('\n'); |
---|
263 | printf ("The following resolve to the same DOS file names:\n"); |
---|
264 | first_err = 0; |
---|
265 | } |
---|
266 | if (first) |
---|
267 | { |
---|
268 | printf ("%14s : %s\n", elist[i]->dos_name, mpath (elist[i])); |
---|
269 | first = 0; |
---|
270 | } |
---|
271 | printf ("\t\t %s\n", mpath (elist[i+1])); |
---|
272 | } |
---|
273 | else |
---|
274 | first = 1; |
---|
275 | } |
---|
276 | |
---|
277 | qsort (elist, ecount, sizeof (ENT *), compare_ent_fullname); |
---|
278 | |
---|
279 | first = 1; |
---|
280 | first_err = 1; |
---|
281 | for (i=0; i<ecount-1; i++) |
---|
282 | { |
---|
283 | if ((strncmp (elist[i]->full_name, elist[i+1]->full_name, 14) == 0) && |
---|
284 | (strcmp (elist[i]->path, elist[i+1]->path) == 0)) |
---|
285 | { |
---|
286 | if (first_err) |
---|
287 | { |
---|
288 | if (first_msg) |
---|
289 | first_msg = 0; |
---|
290 | else |
---|
291 | putchar ('\n'); |
---|
292 | printf ("The following resolve to the same SysV file names:\n"); |
---|
293 | first_err = 0; |
---|
294 | } |
---|
295 | if (first) |
---|
296 | { |
---|
297 | printf ("%.14s : %s\n", elist[i]->full_name, mpath (elist[i])); |
---|
298 | first = 0; |
---|
299 | elist[i]->tagged = 1; |
---|
300 | } |
---|
301 | printf ("\t\t %s\n", mpath (elist[i+1])); |
---|
302 | elist[i+1]->tagged = 1; |
---|
303 | } |
---|
304 | else |
---|
305 | first = 1; |
---|
306 | } |
---|
307 | |
---|
308 | first_err = 1; |
---|
309 | for (i=0; i<ecount; i++) |
---|
310 | { |
---|
311 | if ((strlen (elist[i]->full_name) > 14) && !elist[i]->tagged) |
---|
312 | { |
---|
313 | if (first_err) |
---|
314 | { |
---|
315 | if (first_msg) |
---|
316 | first_msg = 0; |
---|
317 | else |
---|
318 | putchar ('\n'); |
---|
319 | printf ("The following file names are too long for SysV:\n"); |
---|
320 | first_err = 0; |
---|
321 | } |
---|
322 | printf ("%.14s : %s\n", elist[i]->full_name, mpath (elist[i])); |
---|
323 | } |
---|
324 | } |
---|
325 | } |
---|
326 | |
---|
327 | /****************************************************************\ |
---|
328 | * Main entry point * |
---|
329 | \****************************************************************/ |
---|
330 | |
---|
331 | main (argc, argv) |
---|
332 | int argc; |
---|
333 | char **argv; |
---|
334 | { |
---|
335 | FILE *input = stdin; |
---|
336 | if (argc > 1) |
---|
337 | { |
---|
338 | input = fopen (argv[1], "r"); |
---|
339 | if (!input) |
---|
340 | { |
---|
341 | perror (argv[1]); |
---|
342 | exit (1); |
---|
343 | } |
---|
344 | } |
---|
345 | while (1) |
---|
346 | { |
---|
347 | char line[500]; |
---|
348 | char *lp; |
---|
349 | fgets (line, 500, input); |
---|
350 | if (feof (input)) |
---|
351 | break; |
---|
352 | lp = line+strlen (line); |
---|
353 | while ((lp != line) && (*lp <= ' ')) |
---|
354 | lp--; |
---|
355 | lp[1] = 0; |
---|
356 | handle_input (line); |
---|
357 | } |
---|
358 | display_problems (); |
---|
359 | } |
---|
360 | |
---|