blob: ad553df7e8c3d62b6ed075f63b67ab777537b263 [file] [log] [blame]
/*
** DosFCheck - check file names for DOS consistency
**
** Distribute freely, it only encourages DOS compatibility!
** - DJ Delorie
*/
/* This file is not part of GCC. */
#include <stdio.h>
#ifdef __MSDOS__
#include <alloc.h>
#else
#include <malloc.h>
#endif
#include <ctype.h>
#include <string.h>
typedef struct ENT
{
struct ENT *next;
char *dos_name;
char *full_name;
char *path;
int tagged;
} ENT;
ENT *eroot = 0;
int first_inv = 1;
int first_msg = 1;
/****************************************************************\
* Utility routines *
\****************************************************************/
void
invalid_msg ()
{
if (first_inv)
{
if (first_msg)
first_msg = 0;
else
putchar ('\n');
printf ("The following files are not valid DOS file names:\n");
first_inv = 0;
}
}
ENT *
alloc_ent ()
{
ENT *rv = (ENT *)malloc (sizeof (ENT));
if (rv == 0)
{
fprintf (stderr, "Unable to allocate memory for an ENT\n");
exit (1);
}
memset (rv, 0, sizeof (ENT));
return rv;
}
void
fill_ent (ent, path)
ENT *ent;
char *path;
{
char *first = path;
char *null = path+strlen (path);
char *last_slash = strrchr (path, '/');
char *cp, *dp;
int dots_seen, chars_seen;
if (last_slash+1 == null)
{
* --null = '\0';
last_slash = strrchr (path, '/');
}
if (!last_slash)
{
last_slash = first-1;
}
if (null-last_slash < 13)
ent->dos_name = (char *)malloc (null-last_slash);
else
ent->dos_name = (char *)malloc (13);
ent->full_name = (char *)malloc (null-last_slash);
ent->path = (char *)malloc (last_slash-first+1);
strcpy (ent->full_name, last_slash+1);
if (last_slash > first)
{
strncpy (ent->path, first, last_slash-first);
ent->path[last_slash-first] = '\0';
}
else
*ent->path = '\0';
cp = last_slash+1;
dp = ent->dos_name;
dots_seen = 0;
chars_seen = 0;
while (1)
{
if (! *cp)
break;
switch (*cp)
{
case '.':
if (cp == last_slash+1 && strcmp (last_slash+1, "."))
{
invalid_msg ();
printf ("%s - file name cannot start with dot\n", path);
*dp = 0;
break;
}
if (dots_seen == 1)
{
invalid_msg ();
printf ("%s - too many dots\n", path);
*dp = '\0';
break;
}
*dp++ = '.';
chars_seen = 0;
dots_seen++;
break;
case '"':
case '*':
case '+':
case ',':
case ';':
case '<':
case '=':
case '>':
case '?':
case '[':
case '\\':
case ']':
case '|':
invalid_msg ();
printf ("%s - invalid character `%c'\n", path, *cp);
*dp++ = '?';
chars_seen++;
break;
default:
if (dots_seen)
{
if (chars_seen >= 3)
break;
}
else
if (chars_seen >= 8)
break;
if ((*cp <= ' ') || (*cp >= 0x7f))
{
invalid_msg ();
printf ("%s - invalid character `%c'\n", path, *cp);
*dp++ = '?';
chars_seen++;
break;
}
if (islower (*cp))
*dp++ = toupper (*cp);
else
*dp++ = *cp;
chars_seen++;
break;
}
cp++;
}
*dp++ = '\0';
}
int
compare_ent_dosname (e1, e2)
ENT **e1;
ENT **e2;
{
int r = strcmp ((*e1)->dos_name, (*e2)->dos_name);
if (r == 0)
r = strcmp ((*e1)->path, (*e2)->path);
if (r == 0)
r = strcmp ((*e1)->full_name, (*e2)->full_name);
return r;
}
int
compare_ent_fullname (e1, e2)
ENT **e1;
ENT **e2;
{
int r = strncmp ((*e1)->full_name, (*e2)->full_name, 14);
if (r == 0)
r = strcmp ((*e1)->path, (*e2)->path);
if (r == 0)
r = strcmp ((*e1)->full_name, (*e2)->full_name);
return r;
}
char *
mpath (ent)
ENT *ent;
{
static char buf[500];
if (ent->path && ent->path[0])
sprintf (buf, "%s/%s", ent->path, ent->full_name);
else
return ent->full_name;
return buf;
}
/****************************************************************\
* List handling routines *
\****************************************************************/
void
add_ent (ent)
ENT *ent;
{
ent->next = eroot;
eroot = ent;
}
void
handle_input (line)
char *line;
{
ENT *ent = alloc_ent ();
fill_ent (ent, line);
add_ent (ent);
}
void
display_problems ()
{
ENT **elist, *ent;
int ecount, i, first, first_err;
for (ecount=0, ent=eroot; ent; ent=ent->next, ecount++);
elist = (ENT **)malloc (sizeof (ENT *) * ecount);
for (ecount=0, ent=eroot; ent; ent=ent->next, ecount++)
elist[ecount] = ent;
qsort (elist, ecount, sizeof (ENT *), compare_ent_dosname);
first = 1;
first_err = 1;
for (i=0; i<ecount-1; i++)
{
if ((strcmp (elist[i]->dos_name, elist[i+1]->dos_name) == 0)
&& (strcmp (elist[i]->path, elist[i+1]->path) == 0))
{
if (first_err)
{
if (first_msg)
first_msg = 0;
else
putchar ('\n');
printf ("The following resolve to the same DOS file names:\n");
first_err = 0;
}
if (first)
{
printf ("%14s : %s\n", elist[i]->dos_name, mpath (elist[i]));
first = 0;
}
printf ("\t\t %s\n", mpath (elist[i+1]));
}
else
first = 1;
}
qsort (elist, ecount, sizeof (ENT *), compare_ent_fullname);
first = 1;
first_err = 1;
for (i=0; i<ecount-1; i++)
{
if ((strncmp (elist[i]->full_name, elist[i+1]->full_name, 14) == 0)
&& (strcmp (elist[i]->path, elist[i+1]->path) == 0))
{
if (first_err)
{
if (first_msg)
first_msg = 0;
else
putchar ('\n');
printf ("The following resolve to the same SysV file names:\n");
first_err = 0;
}
if (first)
{
printf ("%.14s : %s\n", elist[i]->full_name, mpath (elist[i]));
first = 0;
elist[i]->tagged = 1;
}
printf ("\t\t %s\n", mpath (elist[i+1]));
elist[i+1]->tagged = 1;
}
else
first = 1;
}
first_err = 1;
for (i=0; i<ecount; i++)
{
if ((strlen (elist[i]->full_name) > 14) && !elist[i]->tagged)
{
if (first_err)
{
if (first_msg)
first_msg = 0;
else
putchar ('\n');
printf ("The following file names are too long for SysV:\n");
first_err = 0;
}
printf ("%.14s : %s\n", elist[i]->full_name, mpath (elist[i]));
}
}
}
/****************************************************************\
* Main entry point *
\****************************************************************/
main (argc, argv)
int argc;
char **argv;
{
FILE *input = stdin;
if (argc > 1)
{
input = fopen (argv[1], "r");
if (!input)
{
perror (argv[1]);
exit (1);
}
}
while (1)
{
char line[500];
char *lp;
fgets (line, 500, input);
if (feof (input))
break;
lp = line+strlen (line);
while ((lp != line) && (*lp <= ' '))
lp--;
lp[1] = 0;
handle_input (line);
}
display_problems ();
}