#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <dir.h>
#include <ctype.h>

#define TRUE 1
#define FALSE 0

#pragma startup expand_wildcards 10
#define MAXFILES 10000

extern int _argc ;
extern char ** _argv_arr ;
static char oldcwd[256];
static int oldDrive = 0;
static struct ffblk fileBlock;
static char **filelist=0;
static int filenum=0,filecount=0;

static int SetDir(char *dir)
{
  if (dir == 0)
    chdir(oldcwd);
  else
    chdir(dir);
  return(TRUE);
}
static int SetDrive(int drive)
{
  if (drive == -1)
    setdisk(oldDrive);
  else
    setdisk(drive);
  return(TRUE);
}
static void ParseDir(char *spec, int *drive, char **dir, char **file)
{
   char *spec2;
   *drive = -1;
   *dir = 0;
   *file = 0;

   while (*spec == ' ') spec++;

   spec2 = spec;
   while (*spec2)
     *(spec2++) = toupper(*spec2);

   if (*spec) {
     if (*(spec+1) == ':') {
       *drive = *spec - 'A' ;
       *dir = spec + 2 ;
     }
     else
       *dir = spec;
   }

   if ((spec2 = strrchr(*dir,'\\')) != 0) {
     *spec2 = 0;
     *file = spec2+1;
   }
   else {
     *dir = 0;
     *file = spec;
   }
}
static char *FirstFile(char *spec)
{
  if (findfirst(spec, &fileBlock, _A_NORMAL ))
    return(0);
  return(fileBlock.ff_name) ;
}
static char *NextFile(void)
{
  if (findnext( &fileBlock))
    return(0);
  return(fileBlock.ff_name);
}
static int rfsort(const void *elem1, const void *elem2)
{
	return(strcmp(*(char **)elem1, *(char **)elem2));
}
static char *litlate(char *t)
{
	char *q;
	if (!t)
		return 0;
	q = malloc(strlen(t)+1);
	if (!q) {
		fprintf(stdout,"out of memory");
		exit(1) ;
	}
	strcpy(q,t);
	return q;
}
static void ClearFiles(void)
{
	free(filelist);
	filelist = 0;
	filecount = 0 ;
}
static char *ReadFiles(char *spec)
{
	if (!filelist) {
		filelist = malloc(sizeof(char *)*MAXFILES);
		if (!filelist) {
			fprintf(stderr,"out of memory");
			exit(1) ;
		}
	}
	if ((filelist[0] = litlate(FirstFile(spec))) == 0) {
		return 0;
	}
	while((filelist[++filecount] = litlate(NextFile())) != 0)
		if (filecount >= MAXFILES-1) {
			fprintf(stderr,"Too many files... qualify file names to limit to %d at a time",MAXFILES);
			break ;
		}
	return (char *)1;
}
static int qualify(char *name)
{
  int i ;
	for(i=0; i < strlen(name); i++)
		if (!isalnum(*name) && *name != '\\' && *name != ':' && *name != '*' && *name != '?')
			return FALSE ;
	return TRUE ;
}
void expand_wildcards( void) 
{
  int i;
  oldDrive= getdisk();
  getcwd(oldcwd,256);
	filenum = 0;
	filecount = 0;
  for (i=1; i< _argc; i++) {
    char buffer[256];
    char *dir;
    char *file;
    char *fileName;
    int drive;
		if (qualify(_argv_arr[i])) {
    	strcpy(buffer,_argv_arr[i]);
    	ParseDir(buffer,&drive, &dir, &file);
    	if (!SetDrive(drive) ) {
				fprintf(stderr,"Can't change to drive %c:", drive + 'A');
				continue;
    	}
    	getcwd(oldcwd,256);
    	if (!SetDir(dir)) {
				fprintf(stderr,"Can't change to directory %s", dir);
				continue;
    	}
    	if ((fileName = ReadFiles(file)) == 0) {
       	continue;
    	}    	
			SetDir(oldcwd) ;
			if (filecount) {
				_argv_arr = realloc(_argv_arr,(_argc + filecount) * sizeof(char *)) ;
				asm int 3 ;
				memmove(_argv_arr+i+filecount,_argv_arr+i+1,(_argc - i)* sizeof(char *)) ;
				memcpy(_argv_arr+i,filelist,filecount *sizeof(char *)) ;
				_argc += filecount-1 ;
				i += filecount-1 ;
				ClearFiles() ;
			}
		}
	}
}