
#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>

#include <stdio.h>
#include <ctype.h>
#include "jsh.h"

Name_list *file_lst;

Name_list *
init_file_linked_list(home_lock)
register LONG home_lock;
{
register struct	FileInfoBlock		*home_info = NULL;
register struct	name_list	*next;
static char mem_out[] = "out of memory reading directory, sorry";

#ifdef DEBUG
printf("init_file_linked_list(%lx)\n", home_lock);
#endif DEBUG

home_info = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock) );
if (home_info == NULL)
	{
	outta_mem();
	return(NULL);
	}

if ( !Examine(home_lock, home_info) )
	{
	free(home_info );
	return(NULL);
	}

while( ExNext(home_lock,home_info) != 0 )
    {
	next = (struct name_list *)malloc(sizeof(struct name_list) );
	if (next)
	    {
	    next->name = clone_string(home_info->fib_FileName);
		if (next->name == NULL)
		   {
		   free(next);
		   puts(mem_out);
		   break;
		   }
		else
		   {
	       next->next = file_lst;
	       file_lst = next;
		   }
	    }
	else
	    {
		puts(mem_out);
		break;
		}
    }
free(home_info);
return(file_lst);
}



close_file_linked_list()
{
free_name_list(file_lst);
file_lst = NULL;
}


any_wild(pt)
register char *pt;
{
register char c;

if (pt == NULL)
   return(0);
while ( c = *pt++)
   if ( c == '*' )
      return(1);
return(0);
}

expand_wildcards()
{
char *ptin, *ptout;
register char *last_word;
register char c;
register int count, scount;

if (any_wild(buf) )
   {
   init_file_linked_list(cdir);
   last_word = ptin = buf;
   buf = ptout = find_buffer();
   count = MAX_LINE - 4;  /*think 2 instead of 4 really, but... */
   for (;;)
      {
	  if (--count <= 0)
		 {
	     puts("wildcard expansion too long, sorry");
		 close_file_linked_list();
	     return(0);
		 }
	  c = *ptin;
	  switch (c)
	     {
		 case 0:
            *ptout = 0;
		    close_file_linked_list();
			return(1);
		 case ' ':
		 case '\t':
		 case '\r':
		 case '\n':
		    last_word = NULL;
		    *ptout++ = c;
		    break;
		 case '*':
			if (last_word)  /*back up to last word... */
			   {
			   scount = ptin - last_word;
			   ptin = last_word;
			   ptout -= scount;
			   count += scount;
			   }
		    scount = expand_one(&ptin, &ptout, count);
			if (scount < 0)
			   {
		       close_file_linked_list();
			   return(0);
			   }
			count -= scount;
			last_word = NULL;
			break;
		 default:
		    if (last_word == NULL)
			   last_word = ptin;
			*ptout++ = c;
			break;
         }
	  ptin++;
	  }
   }
else
   return(1);
}


expand_one(in, out, count)
char **in, **out;
int count;
{
char lbuf[MAX_LINE];
register Name_list *files;
int ex_count;
register char *lout;
char *lin; /*local out, in */
register int length;
char *name;

ex_count = 0;
first_word( lbuf, *in );
lout = *out;
files = file_lst;
while (files)
   {
   name = files->name;
   if (matches(lbuf, name) )
	  {
	  length = strlen(name) + 1;
	  count -= length;
	  if (count <= 0)
	     {
		 puts("wildcard expansion too long");
		 return(-1);
		 }
	  ex_count += length;
	  *lout++ = ' ';
	  strcpy(lout, name);
	  lout += length-1;
	  }
   files = files->next;
   }
*out = lout;
lin = *in;
lin = skip_to_space(lin);
*in = lin;
return(ex_count);
}

matches(pat, name)
register char *pat;
register char *name;
{
register char a, b;

if (pat == NULL || name == NULL)
   return(0);
for (;;)
   {
   a = *pat++;
   b = *name++;
   if (a == '*')
      {
	  if (pat[0] == 0)
	     return(1);
	  --name;
	  while ( name[0] )
	     {
		 if (matches(pat, name) )
		    return(1);
		 name++;
		 }
	  return(0);
	  }
   else
      {
	  if (a != b)
	     return(0);
	  }
   if ( a == 0)
      return(1);
   }
}

