 /*
  * Khoros: $Id: bld_list.c,v 1.3 1992/03/20 22:36:39 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: bld_list.c,v 1.3 1992/03/20 22:36:39 dkhoros Exp $";
#endif

 /*
  * $Log: bld_list.c,v $
 * Revision 1.3  1992/03/20  22:36:39  dkhoros
 * VirtualPatch5
 *
  */ 


/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>     file name: bld_list.c                             <<<<
   >>>>                                                       <<<<
   >>>>   description: see below                              <<<<
   >>>>                                                       <<<<
   >>>>      routines: write_info                             <<<<
   >>>>                get_dir_info                           <<<<
   >>>>                find_suffix                            <<<<
   >>>>                filesalloc                             <<<<
   >>>>                myalloc                                <<<<
   >>>>                addfile                                <<<<
   >>>>                addsrc                                 <<<<
   >>>>                addfsrc                                <<<<
   >>>>                addgen                                 <<<<
   >>>>                                                       <<<<
   >>>>        author: W. Tait Cyrus -- May 31, 1990          <<<<
   >>>>                                                       <<<<
   >>>> modifications:                                        <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */


/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * 
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */

#include "imkmf.h"

int addsrc(), addysrc(), addlsrc(), addfsrc(), addgen();
int donothing() 
{
}

/*
 * This array contains a list of all known suffix's and whether the
 * suffix is such that it is considered a source.  It also initializes
 * the count of the number of names in each category to zero as well
 * as initializes the pointer to the actual names to NULL.
 */

/*	suffix	category	count	files	function	*/
struct stuff map[] = {
#define DIRSLOC	0
	{"",	DIRS,		0,	NULL,	addgen		},
#define SRCSLOC	1
	{"c",	SRCS,		0,	NULL,	addsrc		},
#define OBJSLOC	2
	{"o",	OBJS,		0,	NULL,	donothing	},
#define SPECIALLOC 3
	{"",	SPECIAL,	0,	NULL,	donothing	},
#define TBALLOC 4
	{"",	SPECIAL,	0,	NULL,	donothing	},
#define FSRCSLOC	5
	{"f",	FSRCS,		0,	NULL,	addfsrc		},
#define FOBJSLOC	6
	{"o",	FOBJS,		0,	NULL,	donothing	},
	{"h",	HEADER,		0,	NULL,	addgen		},
#define LSRCSLOC	8
	{"l",	LSRCS,		0,	NULL,	addlsrc		},
#define YSRCSLOC	9
	{"y",	YSRCS,		0,	NULL,	addysrc		},
	{"csh",	SCRIPT,		0,	NULL,	addgen		},
	{0,	NULL,		0,	NULL,	NULL		}
	};

int find_suffix();

/*
 * This routine writes to the specified output file the specified
 * portition of the directory contents `map'.  If there are no
 * names in the list, then we just write out the category name.
 */

write_info( index, outfile )
   int index;
   FILE *outfile;
   {
   struct files *f;
   f = map[index].files;
   if( f ) fprintf( outfile, "%s =\\\n",map[index].category);
   else fprintf( outfile, "%s =\n",map[index].category);
   while( f ) {
      if( f->next ) fprintf( outfile, "\t%s \\\n",f->name);
      else fprintf( outfile, "\t%s\n",f->name);
      f = f->next;
      }
   }

/*
 * This routine opens the current directory, reads in the names of the
 * files contained in this directory and places the names in the
 * 'appropriate' location in the `map' defined above.
 */

get_dir_info() {
   DIR *dir;
   vdirect *files;
   struct stat filestatus;
   int suffix;

   if( (dir = opendir( "." )) == NULL ) {
      perror( "Can't open cwd \".\"" );
      myexit(1);
      }
   /*
    * Get the name of each file in this directory.
    */
   while( (files = readdir( dir )) != NULL ) {
      /*
       * We don't care about `.', `..', and other files that begin with `.'
       * so we ignore them.
       */
      if( files->d_name[0] != '.' ) {
	 /*
	  * Find out the type (regular, directory, link, etc.) of the file.
	  */
	 if( stat(files->d_name, &filestatus) == -1 ) {
	    fprintf( stderr, "Warning: `%s' is being ignored.\n\t  ",
		files->d_name );
	    perror( NULL );
	    continue;
	    }
	 switch( filestatus.st_mode & S_IFMT ) {
		/*
		 * If a directory, just add directory to appropriate
		 * list in `map'.
		 */
	    case S_IFDIR:
	       (*map[DIRSLOC].function)(DIRSLOC,files);
	       break;
		/*
		 * If a regular file, just add to appropriate list in `map'.
		 */
	    case S_IFREG:
	    case S_IFLNK:
			/*
			 * Find out what the suffix of the name is.  If it
			 * is a known suffix, then the value returned is
			 * the index into `map' where the information about
			 * files with that suffix is kept.
			 */
	       if( (suffix = find_suffix(files->d_name)) != 0 ) {
		  (*map[suffix].function)(suffix,files);
		  }
	       break;
	    default:
	       break;
	    }
	 }
      }
   closedir( dir );
   }

/*
 * This routine walks through the specified `name' looking for the
 * suffix of the name.  If none exists, then this routine returns
 * 0 else it sees if the suffix is one which is "known" (in map).
 * The index into `name' of the suffix is returned if it is a known
 * suffix.
 */

int
find_suffix( name )
   char *name;
   {
   char *c;
   int index;

   if( (c = strrchr( name, '.' )) == NULL ) return( 0 );
   index = 1;
   while( map[index].suffix ) {
      if( strcmp( c+1, map[index].suffix ) == 0 ) {
	 *c = 0;
	 return( index );
	 }
      index++;
      }
   return( 0 );
   }

/*
 * This routine allocates memory for a file structure.
 */

struct files *
filesalloc()  {
   struct files *tmp;

   tmp = (struct files *)myalloc(sizeof(struct files));
   return( tmp );
   }

/*
 * This routine allocates memory for general use in the program.  This
 * routine does all of the error checking.
 */

char *
myalloc( size )
   int size;
   {
   char *tmp;
   if( (tmp = malloc( size + 1 )) == NULL ) {
      fprintf( stderr, "Error, can't alloc mmemory\n" );
      myexit( 1 );
      }
   bzero( tmp, size );
   return( tmp );
   }

/*
 * This routine inserts the given "name" in the specified linked list ("s")
 * in alphabetical order.
 */

addfile( name, s, suffix )
   char *name;
   struct files **s;
   char *suffix;
   {
   struct files *tmp, *prev;
   char tmpname[MAXNAMLEN];
   int comp;

	/*
	 * Check to see if this is the first name in linked list.
	 */
   if( !*s ) {
      *s = filesalloc();
      (*s)->name = myalloc( strlen( name ) + strlen( suffix ) + 1 );
      if( *suffix ) sprintf( (*s)->name, "%s.%s", name, suffix );
      else sprintf( (*s)->name, "%s", name );
      }
	/*
	 * We have to walk through the linked list looking for the
	 * correct place to insert name to keep list in alphabetical
	 * order.
	 */
   else {
      tmp = *s;
      prev = NULL;
      if( *suffix ) sprintf( tmpname, "%s.%s", name, suffix );
      else sprintf( tmpname, "%s", name );
      while( tmp ) {
	 comp = strcmp( tmpname, tmp->name );
	 if( comp == 0 ) return;	/* Name already here */
	 if( comp < 0 ) {
		/*
		 * Name needs to be inserted BEFORE 'tmp', but we need
		 * to check to see if this means we insert at the TOP
		 * of the linked list.
		 */
	    if( prev == NULL ) {
	       *s = filesalloc();
	       (*s)->next = tmp;
	       tmp = *s;
	       }
	    else {
	       prev->next = filesalloc();
	       (prev->next)->next = tmp;
	       tmp = prev->next;
	       }
	    break;
	    }
	 prev = tmp;
	 tmp = tmp->next;
	 }
	/*
	 * We have gone throught the entire list and did not find a
	 * place to put 'name'.  This means we put it at the end of
	 * the linked list.
	 */
      if( !tmp ) {
	 prev->next = filesalloc();
	 tmp = prev->next;
	 }
	/*
	 * Now we just fill in the information for the newly
	 * created node.
	 */
      tmp->name = myalloc( strlen( name ) + strlen( suffix ) + 1 );
      if( *suffix ) sprintf( tmp->name, "%s.%s", name, suffix );
      else sprintf( tmp->name, "%s", name );
      }
   }

int
addsrc( suffix, file )
   int suffix;
   vdirect *file;
   {
   map[ SRCSLOC ].count++;
   map[ OBJSLOC ].count++;
   addfile( file->d_name, &(map[SRCSLOC].files), map[suffix].suffix);
   addfile( file->d_name, &(map[OBJSLOC].files), map[OBJSLOC].suffix);
   }

int
addfsrc( suffix, file )
   int suffix;
   vdirect *file;
   {
   map[ FSRCSLOC ].count++;
   map[ FOBJSLOC ].count++;
   addfile( file->d_name, &(map[FSRCSLOC].files), map[suffix].suffix);
   addfile( file->d_name, &(map[FOBJSLOC].files), map[FOBJSLOC].suffix);
   }

int
addysrc( suffix, file )
   int suffix;
   vdirect *file;
   {
   map[ OBJSLOC ].count++;
   map[ YSRCSLOC ].count++;
   addfile( file->d_name, &(map[OBJSLOC].files), map[OBJSLOC].suffix);
   addfile( file->d_name, &(map[YSRCSLOC].files), map[YSRCSLOC].suffix);
   }

int
addlsrc( suffix, file )
   int suffix;
   vdirect *file;
   {
   map[ OBJSLOC ].count++;
   map[ YSRCSLOC ].count++;
   addfile( file->d_name, &(map[OBJSLOC].files), map[OBJSLOC].suffix);
   addfile( file->d_name, &(map[LSRCSLOC].files), map[LSRCSLOC].suffix);
   }

int
addgen( suffix, file )
   int suffix;
   vdirect *file;
   {
   map[ suffix ].count++;
   addfile( file->d_name, &(map[suffix].files), map[suffix].suffix);
   }
