/* fileargs.c 
 */

#include <stdio.h>
#include "fileargs.h"

extern char *program_name;

static file_list file_list_create_node (char *str)
{
  file_list flist_node_ptr = xmalloc (sizeof (file_list_node));
  flist_node_ptr -> next = 0;
  flist_node_ptr -> str = str;
  return flist_node_ptr;
}

/* take a command line argument which can either be a filename
   or an @ reference and returns a file list in which any @ reference
   has been expanded. */

file_list
get_file_list_from_arg (char *arg)
{
  if (arg [0] != '@')
	{
    /* its just an ordinary file name */
	return file_list_create_node (arg);
	}
  {
	/* its an @ reference */
    file_list flist = 0, flist_end = 0;
	FILE * fp;
    static char buffer [2048];

    /* open the file we get by omitting the leading @ */
	if ((fp = fopen (&arg[1], "r")) == 0)
	  {
        fprintf (stderr, 
              "%s : Couldn't expand @ reference - file (%s) doesn't exist.\n",               program_name, &arg [1]); 
        xexit (1);
      }

	/* read a line at a time */
	while (fgets (buffer, sizeof (buffer) -1, fp))
	  {
		char *p , *fname;
		/* remove trailing whitespace */

        /* start from the terminating null */
        p = buffer + strlen (buffer);

        /* step backwards until we hit the beginning or something
           that isn't a null or whitespace */
        for (; p != buffer && (*p == '\0' ||  isspace (*p)); --p);

        /* p now points to what ought to be the last character in
           the string. Terminate it. */
		*++p = '\0';

        /* put the filename somewhere permanent */
		fname = xmalloc (strlen (buffer) + 1);
		strcpy (fname, buffer);
        
        /* add it to the list. Keep track of the start and end
           of the list */

		if (flist_end)
		  {
            /* this isn't the first node */
            flist_end -> next = file_list_create_node (fname);
	     	flist_end = flist_end -> next;
		  }
        else
          {
            /* this is the first node */
            flist = flist_end = file_list_create_node (fname);
          }
	  }
	fclose (fp);
    return flist;
  } 
}

/* takes an array of names and returns an array in which
   @ references have been expanded. */

char **expand_file_list (char **files)
{
  /* the beginning and end of the list we're going to build */
  file_list flist = 0, flist_end = 0;
  
  int i;
  if (!files) return 0;
  /* step through the array, expanding @ references as we find them */
  for (i = 0; files[i]; ++i)
	{ 
      if (flist_end)
		{
          /* this isn't the first node */
          flist_end -> next = get_file_list_from_arg (files[i]);
		}
      else
        {
          /* this is the first node */
          flist = flist_end = get_file_list_from_arg(files[i]);
        }
      /* flist_end now points to just before the first node in the
         newly added list */

      /* find end of new list */
      while (flist_end -> next) flist_end = flist_end -> next;
	}
  {
    /* count the number of files in the list we've built */
    int nfiles = 0;
    file_list node;
    for  (node = flist; node; node = node -> next)
      ++nfiles;

    /* allocate space for an array large enough to contain these files */
    files = xmalloc (sizeof (char *) * (nfiles + 1));

    /* copy the files from the list to the array */
    for (i  = 0, node = flist; i != nfiles; node = node -> next, ++i)
         files [i]  = node -> str;

    files[i] = 0;
  }
  return files;
}
