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 19typedef struct ENT 20{ 21 struct ENT *next; 22 char *dos_name; 23 char *full_name; 24 char *path; 25 int tagged; 26} ENT; 27 28ENT *eroot = 0; 29 30int first_inv = 1; 31int first_msg = 1; 32 33/****************************************************************\ 34 * Utility routines * 35\****************************************************************/ 36 37void 38invalid_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 51ENT * 52alloc_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 64void 65fill_ent (ent, path) 66ENT *ent; 67char *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 178int 179compare_ent_dosname (e1, e2) 180ENT **e1; 181ENT **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 191int 192compare_ent_fullname (e1, e2) 193ENT **e1; 194ENT **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 204char * 205mpath (ent) 206ENT *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 220void 221add_ent (ent) 222ENT *ent; 223{ 224 ent->next = eroot; 225 eroot = ent; 226} 227 228void 229handle_input (line) 230char *line; 231{ 232 ENT *ent = alloc_ent (); 233 fill_ent (ent, line); 234 add_ent (ent); 235} 236 237void 238display_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 331main (argc, argv) 332int argc; 333char **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 361