home *** CD-ROM | disk | FTP | other *** search
- Path: wupost!uunet!munnari.oz.au!murtoa.cs.mu.oz.au!csv.viccol.edu.au!timcc
- From: timcc@csv.viccol.edu.au (Tim Cook)
- Newsgroups: alt.sources
- Subject: dl v1.6, part 2 of 3
- Message-ID: <1991Aug21.173913.6832@csv.viccol.edu.au>
- Date: 21 Aug 91 22:39:13 GMT
- Organization: Computer Services, Victoria College, Melbourne
- Lines: 903
-
- #!/bin/sh
- # This is part 02 of a multipart archive
- # ============= dl.c ==============
- if test -f 'dl.c' -a X"$1" != X"-c"; then
- echo 'x - skipping dl.c (File already exists)'
- else
- echo 'x - extracting dl.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'dl.c' &&
- /* dl.c - Descriptive ls
- X *
- X * Copyright (c) 1991 Tim Cook.
- X * Non-profit distribution allowed. See README for details.
- X */
- X
- static char rcsid[] = "$Header: dl.c 1.6 91/08/21 $" ;
- X
- #include "config.h"
- #include <stdio.h>
- #include <sys/param.h>
- #include <sys/stat.h>
- #include <sys/file.h>
- #include <list.h>
- X
- #ifdef SYSV
- #include <time.h>
- #else
- #include <sys/time.h>
- #endif
- X
- #ifndef MAXPATHLEN
- #define MAXPATHLEN 1024
- #endif
- X
- extern time_t time () ;
- extern UID_T getuid () ;
- extern int getgroups () ;
- X
- extern char *getdesc () ;
- extern VOID enddesc () ;
- extern char *pathname () ;
- X
- #define strgencpy(new, old) \
- X (new = strcpy ((char *) allocate (strlen (old) + 1), old))
- X
- static struct file_info {
- X ino_t inode ;
- X u_short mode ;
- X short nlink ;
- X off_t size ;
- X time_t mtime ;
- X char name[4] ; /* This can actually contain a string of any
- X length, I'm just giving the compiler the
- X opportunity to align. */
- X } ;
- X
- /*
- X * How much space needed for a struct file_info that contains string "s"
- X */
- #define file_info_size(s) \
- X (sizeof (struct file_info) - 3 + strlen (s))
- X
- /* options */
- static int show_date = FALSE ;
- static int sort_by_date = FALSE ;
- static int even_inaccessible = FALSE ;
- static int filename_columns = 14 ;
- static int recursive = FALSE ;
- X
- /* other globals */
- #define FROM_ARGV 0
- #define FROM_DIR 1
- X
- static time_t six_months_ago ;
- static struct file_info not_there ; /* Symbolic value */
- static int name_and_size_columns ;
- static int space = FALSE ; /* If TRUE, we need to print a blank
- X line before anything else */
- static int printed_anything = FALSE ;
- static UID_T uid ;
- static int no_groups ;
- static UID_T groups[NGROUPS] ;
- X
- static VOID_PTR get_element_from_argv () ;
- static VOID build_and_sort_list () ;
- static struct file_info *get_file_info () ;
- static VOID list_file () ;
- static VOID list_directory () ;
- X
- X
- int main (argc, argv)
- X int argc ;
- X char **argv ;
- {
- X extern char *optarg ;
- X extern int optind, opterr ;
- X
- X int option ;
- X struct list file_list, dir_list ;
- X struct file_info *file_info ;
- X char *dir_name ;
- X int multiple_args ;
- X
- X opterr = 0 ;
- X while ((option = getopt (argc, argv, "deitf:R")) != EOF) {
- X switch ((char) option) {
- X case 'd' :
- X show_date = TRUE ; break ;
- X case 'e' :
- X case 'i' :
- X even_inaccessible = TRUE ; break ;
- X case 't' :
- X sort_by_date = TRUE ; break ;
- X case 'f' :
- X filename_columns = atoi (optarg) ; break ;
- X case 'R' :
- X recursive = TRUE ; break ;
- X case '?' :
- X break ; } }
- X
- X multiple_args = (argc - optind) > 1 ;
- X
- X name_and_size_columns = filename_columns + 8 ;
- X
- X if (show_date)
- X six_months_ago = time ((time_t *) 0) - (182 * 24 * 60 * 60) ;
- X
- X if (! even_inaccessible) {
- X uid = (UID_T) getuid () ;
- X no_groups = getgroups (NGROUPS, groups) ; }
- X
- X if (optind == argc) {
- X list_directory ("", FALSE) ;
- X enddesc () ;
- X exit (0) ; }
- X
- X list_init (&file_list) ;
- X build_and_sort_list (&file_list, NULL_CP, FROM_ARGV, (char *) argv,
- X (char *) &optind) ;
- X
- X list_init (&dir_list) ;
- X while ((file_info = get_file_info (&file_list, NULL_CP))
- X != (struct file_info *) NULL) {
- X if (file_info != ¬_there) {
- X if (file_info->mode & S_IFDIR)
- X /* Collect these for later */
- X list_push (&dir_list, (VOID_PTR) file_info->name,
- X strlen (file_info->name) + 1) ;
- X else {
- X list_file (file_info, NULL_CP) ; } } }
- X list_free (&file_list) ;
- X
- X /* Now, the directories we collected above */
- X while ((dir_name = (char *) list_shift (&dir_list)))
- X list_directory (dir_name, multiple_args) ;
- X list_free (&dir_list) ;
- X
- X enddesc () ;
- X exit (0) ;
- X }
- X
- X
- static
- VOID_PTR get_element_from_argv (param_1, param_2)
- X char *param_1, *param_2 ;
- {
- X int *argc ;
- X char **argv ;
- X
- X argv = (char **) param_1 ;
- X argc = (int *) param_2 ;
- X return (VOID_PTR) argv[(*argc)++] ;
- X }
- X
- X
- static
- VOID_PTR get_element_from_dir (param_1, param_2)
- X char *param_1 ; /* directory pointer (DIR *) */
- X char *param_2 ; /* name of directory */
- {
- X DIRENT *dir_entry ;
- X
- X for (dir_entry = readdir ((DIR *) param_1) ;
- X dir_entry != (DIRENT *) NULL && dir_entry->d_name[0] == '.' ;
- X dir_entry = readdir ((DIR *) param_1)) ;
- X if (dir_entry == (DIRENT *) NULL)
- X return (VOID_PTR) NULL ;
- X return (VOID_PTR) dir_entry->d_name ;
- X }
- X
- X
- static
- int file_info_date_cmp (info_1, info_2)
- X struct file_info **info_1, **info_2 ;
- {
- X return (int) ((*info_2)->mtime - (*info_1)->mtime) ;
- X }
- X
- X
- static
- int compare_str (str_1, str_2)
- X char **str_1, **str_2 ;
- {
- X return strcmp (*str_1, *str_2) ;
- X }
- X
- X
- static
- VOID build_and_sort_list (file_list, directory, where_from, param_1, param_2)
- X struct list *file_list ;
- X char *directory ;
- X int where_from ;
- X char *param_1, *param_2 ;
- {
- X VOID_PTR (*get_element) () ;
- X struct stat file_status ;
- X char *name ;
- X
- X if (where_from == FROM_ARGV)
- X get_element = get_element_from_argv ;
- X else
- X get_element = get_element_from_dir ;
- X
- X if (sort_by_date) {
- X struct file_info *file_info ;
- X
- X file_info = (struct file_info *)
- X allocate (sizeof (struct file_info) + MAXPATHLEN) ;
- X
- X while ((name = (char *) get_element (param_1, param_2)) != NULL_CP) {
- X if (stat (pathname (directory, name), &file_status) == -1)
- X perror (name) ;
- X else {
- X file_info->inode = file_status.st_ino ;
- X file_info->mode = file_status.st_mode ;
- X file_info->nlink = file_status.st_nlink ;
- X file_info->size = file_status.st_size ;
- X file_info->mtime = file_status.st_mtime ;
- X strcpy (file_info->name, name) ;
- X list_push (file_list, (VOID_PTR) file_info,
- X file_info_size (name)) ;
- X } }
- X
- X free ((VOID_PTR) file_info) ;
- X
- X list_sort (file_list, file_info_date_cmp) ; }
- X
- X else { /* Sort by name */
- X while ((name = (char *) get_element (param_1, param_2)) != NULL_CP) {
- X list_push (file_list, (VOID_PTR) name,
- X ((where_from == FROM_ARGV) ? 0 : (strlen (name) + 1))) ; }
- X list_sort (file_list, compare_str) ; }
- X }
- X
- X
- static
- struct file_info *get_file_info (file_list, directory)
- X struct list *file_list ;
- X char *directory ;
- {
- X static struct stat status ; /* Tongue twister */
- X char *name ;
- X int listable ;
- X int n ;
- X
- X if (sort_by_date)
- X return (struct file_info *) list_shift (file_list) ;
- X else {
- X name = (char *) list_shift (file_list) ;
- X if (name == (char *) NULL)
- X return (struct file_info *) NULL ;
- X else
- X if (stat (pathname (directory, name), &status) == -1) {
- X perror (name) ;
- X return ¬_there ; }
- X else {
- X if (! even_inaccessible) {
- X if (uid == (UID_T) status.st_uid)
- X listable = status.st_mode & 0500 ;
- X else {
- X for (n = 0 ; n < no_groups ; n++) {
- X if (groups[n] == (GID_T) status.st_gid) {
- X listable = status.st_mode & 050 ;
- X n = no_groups + 1 ; } }
- X if (n == no_groups)
- X listable = status.st_mode & 05 ; } }
- X else
- X listable = TRUE ;
- X if (! listable)
- X return ¬_there ;
- X else {
- X static struct file_info *file_info ;
- X
- X if (! file_info)
- X file_info = (struct file_info *)
- X allocate (sizeof (struct file_info) + MAXPATHLEN) ;
- X file_info->inode = status.st_ino ;
- X file_info->mode = status.st_mode ;
- X file_info->nlink = status.st_nlink ;
- X file_info->size = status.st_size ;
- X file_info->mtime = status.st_mtime ;
- X strcpy (file_info->name, name) ;
- X return file_info ; } } }
- X }
- X
- X
- static
- VOID list_directory (directory_name, show_directory)
- X char *directory_name ;
- X int show_directory ;
- {
- X DIR *dirp ;
- X struct list file_list, dir_list ;
- X struct file_info *file_info ;
- X
- X space = FALSE ;
- X if (show_directory) {
- X if (printed_anything) {
- X printc ('\n') ; }
- X printf ("%s:\n", directory_name) ;
- X printed_anything = TRUE ; }
- X
- X if ((dirp = opendir (*directory_name == EOS ? "." : directory_name))
- X == (DIR *) NULL) {
- X perror (directory_name) ; }
- X else {
- X list_init (&file_list) ;
- X build_and_sort_list (&file_list, directory_name, FROM_DIR,
- X (char *) dirp, directory_name) ;
- X list_init (&dir_list) ;
- X while ((file_info = get_file_info (&file_list, directory_name))
- X != (struct file_info *) NULL) {
- X if (file_info != ¬_there) {
- X if (recursive && file_info->mode & S_IFDIR)
- X /* Save this for later */
- X list_push (&dir_list, (VOID_PTR) file_info->name,
- X strlen (file_info->name) + 1) ;
- X list_file (file_info, directory_name) ; } }
- X list_free (&file_list) ;
- X closedir (dirp) ;
- X
- X if (recursive) {
- X char *saved_dir ;
- X char *path, *sub_dir ;
- X
- X /* Now, the directories we saved earlier */
- X while ((saved_dir = (char *) list_shift (&dir_list))) {
- X path = pathname (directory_name, saved_dir) ;
- X list_directory (strgencpy (sub_dir, path), TRUE) ;
- X free ((VOID_PTR) sub_dir) ; }
- X list_free (&dir_list) ; } }
- X
- X space = TRUE ;
- X }
- X
- X
- X
- X
- static
- VOID list_file (file_info, directory)
- X struct file_info *file_info ;
- X char *directory ;
- {
- X static char month[][12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"} ;
- X char out_name[MAXPATHLEN+2] ; /* What to print */
- X char *desc ;
- X static char size[12] ;
- X static char date[16] ;
- X int name_len, size_len, gap ;
- X struct tm *tm_time ;
- X
- X desc = getdesc (directory, file_info->name, file_info->inode) ;
- X
- X /* Now we only need what we will show */
- X strcpy (out_name, file_info->name) ;
- X
- X name_len = strlen (out_name) ;
- X /* If it is a directory, make it obvious */
- X if (file_info->mode & S_IFDIR) {
- X strcat (out_name, "/") ;
- X name_len++ ;
- X size[1] = EOS ;
- X size_len = 1 ;
- X if (file_info->nlink > 2) { /* Denotes a directory that contains */
- X size[0] = '=' ; } /* one or more sub-directories */
- X else {
- X size[0] = '-' ; } }
- X else {
- X sprintf (size, "%d", file_info->size) ;
- X size_len = strlen (size) ; }
- X if (name_len + size_len < name_and_size_columns)
- X gap = name_and_size_columns - name_len ;
- X else {
- X print (out_name) ;
- X out_name[0] = '\n' ; out_name[1] = EOS ;
- X gap = name_and_size_columns ; }
- X if (show_date) {
- X tm_time = localtime (&file_info->mtime) ;
- X if (six_months_ago > file_info->mtime) {
- X /* The bloody thing is more than 6 months old! */
- #ifdef US_DATE_FORMAT
- X sprintf (date, " %s %2d %d ", month[tm_time->tm_mon],
- X tm_time->tm_mday, tm_time->tm_year + 1900) ;
- #else
- X sprintf (date, " %2d %s %d ", tm_time->tm_mday,
- X month[tm_time->tm_mon], tm_time->tm_year + 1900) ;
- #endif
- X }
- X else {
- #ifdef US_DATE_FORMAT
- X sprintf (date, " %s %2d %02d:%02d ", month[tm_time->tm_mon],
- X tm_time->tm_mday, tm_time->tm_hour, tm_time->tm_min) ;
- #else
- X sprintf (date, " %2d %s %02d:%02d ", tm_time->tm_mday,
- X month[tm_time->tm_mon], tm_time->tm_hour, tm_time->tm_min) ;
- #endif
- X } }
- X else {
- X date[0] = ' ' ;
- X date[1] = EOS ; }
- X
- X if (space) {
- X printc ('\n') ;
- X space = FALSE ; }
- X printf ("%s %*s%s %s\n", out_name, gap, size, date,
- #ifdef PASS_NULL_TO_PRINTF
- X desc
- #else
- X (desc == NULL_CP) ? "" : desc
- #endif
- X ) ;
- X printed_anything = TRUE ;
- X }
- SHAR_EOF
- chmod 0640 dl.c ||
- echo 'restore of dl.c failed'
- fi
- # ============= describe.c ==============
- if test -f 'describe.c' -a X"$1" != X"-c"; then
- echo 'x - skipping describe.c (File already exists)'
- else
- echo 'x - extracting describe.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'describe.c' &&
- /* describe.c - Set or list a descriptive comment for a file
- X *
- X * Copyright (c) 1991 Tim Cook.
- X * Non-profit distribution allowed. See README for details.
- X */
- X
- static char rcsid[] = "$Header: describe.c 1.6 91/08/21 $" ;
- X
- #include "config.h"
- #include <stdio.h>
- #include <sys/param.h>
- #include <sys/file.h>
- #include <sys/stat.h>
- X
- #ifdef SYSV
- #include <fcntl.h> /* for O_CREAT, etc. */
- #endif
- X
- #ifndef MAXPATHLEN
- #define MAXPATHLEN 1024
- #endif
- X
- extern char *getdesc () ;
- extern int setdesc () ;
- extern VOID enddesc () ;
- X
- static char *program_name ;
- X
- static VOID usage () ;
- static VOID set_from_file () ;
- static VOID list_descriptions () ;
- X
- X
- int main (argc, argv)
- X int argc ;
- X char **argv ;
- {
- X extern char *optarg ;
- X extern int optind, opterr ;
- X int delete_desc = FALSE ;
- X struct stat status ;
- X int option ;
- X char *directory ;
- X
- X program_name = argv[0] ;
- X while ((option = getopt (argc, argv, "dlsf:")) != EOF) {
- X switch (option) {
- X case 's':
- X case 'f': /* Set descriptions from file */
- X if (delete_desc)
- X usage () ;
- X if (optind >= argc)
- X directory = "." ;
- X else
- X directory = argv[optind] ;
- X set_from_file (optarg, directory) ;
- X enddesc () ;
- X exit (0) ;
- X break ;
- X case 'l': /* List directory */
- X if (delete_desc)
- X usage () ;
- X if (optind >= argc)
- X directory = "." ;
- X else
- X directory = argv[optind] ;
- X list_descriptions (directory) ;
- X enddesc () ;
- X exit (0) ;
- X break ;
- X case 'd': /* Delete description(s) */
- X delete_desc = TRUE ;
- X break ;
- X default:
- X usage () ; } }
- X
- X if (delete_desc) {
- X char directory[MAXPATHLEN+1] ;
- X char file_name[MAXPATHLEN+1] ;
- X
- X if (optind >= argc)
- X usage () ;
- X for ( ; optind < argc ; optind++) {
- X split_pathname (argv[optind], directory, file_name) ;
- X if (stat (argv[optind], &status) == -1) {
- X perror2 (program_name, argv[optind]) ; }
- X if (! setdesc (directory, file_name, status.st_ino, NULL_CP))
- X perror2 (program_name, argv[optind]) ; } }
- X
- X else {
- X
- X /* Set description of specified file */
- X
- X char directory[MAXPATHLEN+1] ;
- X char file_name[MAXPATHLEN+1] ;
- X
- X if (argc != 3)
- X usage () ;
- X
- X split_pathname (argv[1], directory, file_name) ;
- X if (stat (argv[1], &status) == -1) {
- X perror2 (program_name, argv[1]) ;
- X exit (1) ; }
- X if (! setdesc (directory, file_name, status.st_ino, argv[2]))
- X perror2 (program_name, argv[1]) ;
- X }
- X
- X enddesc () ;
- X }
- X
- X
- static
- VOID usage ()
- {
- X fprintf (stderr, "\
- usage: %s <file> <description>\n\
- X or: %s -s <descriptions-file> [<directory>]\n\
- X or: %s -d <file> ...\n\
- X or: %s -l [<directory>]\n",
- X program_name, program_name, program_name, program_name) ;
- X exit (2) ;
- X }
- X
- X
- static
- VOID set_from_file (file, directory)
- X char *file ;
- X char *directory ;
- {
- X FILE *descriptions ;
- X char file_name[MAXPATHLEN+1] ;
- X char buffer[1024] ;
- X char description[256] ;
- X struct stat status ;
- X int n ;
- X
- X if (strcmp (file, "-") == 0)
- X descriptions = stdin ;
- X else {
- X if ((descriptions = fopen (file, "r")) == (FILE *) NULL) {
- X perror2 (program_name, file) ;
- X exit (1) ; } }
- X if (chdir (directory) == -1) {
- X perror2 (program_name, directory) ;
- X exit (1) ; }
- X while (! feof (descriptions)) {
- X if (fgets (buffer, sizeof (buffer), descriptions) != NULL_CP) {
- X n = sscanf (buffer, "\"%[^\"]\" %[^\n]\n", file_name, description) ;
- X if (n < 2)
- X n = sscanf (buffer, "%s %[^\n]\n", file_name, description) ;
- X if (n == 2 && file_name[0] != '#') {
- X if (stat (file_name, &status) == -1) {
- X perror2 (program_name, file_name) ; }
- X else {
- X if (! setdesc (directory, file_name, status.st_ino,
- X description))
- X perror2 (program_name, file_name) ; } } }
- X }
- X fclose (descriptions) ;
- X }
- X
- X
- static
- VOID list_descriptions (directory)
- X char *directory ;
- {
- X char file_name[MAXPATHLEN+1] ;
- X int file_name_length ;
- X int gap ;
- X DIR *dir ;
- X DIRENT *dir_entry ;
- X char *desc ;
- #ifdef SYSV
- X int namlen ;
- #endif
- X
- X /*
- X * Loop through all the files in this directory, seeing if we can
- X * find a description for each one.
- X */
- X
- X if ((dir = opendir (*directory == EOS ? "." : directory)) == (DIR *) NULL) {
- X perror ("opendir") ;
- X exit (1) ; }
- X while ((dir_entry = readdir (dir)) != (DIRENT *) NULL) {
- X
- X if ((desc = getdesc (directory, dir_entry->d_name, dir_entry->d_ino))
- X != NULL_CP) {
- X
- X /* Print it out! */
- #ifdef SYSV
- X file_name_length = strlen (dir_entry->d_name) ;
- #else
- X file_name_length = dir_entry->d_namlen ;
- #endif
- X strncpy (file_name, dir_entry->d_name, file_name_length) ;
- X file_name[file_name_length] = EOS ;
- X
- X if (strpbrk (file_name, " \t") != NULL_CP) {
- X printc ('"') ;
- X print (file_name) ;
- X printc ('"') ;
- X gap = 18 - file_name_length ; }
- X else {
- X print (file_name) ;
- X gap = 20 - file_name_length ; }
- X printc (' ') ; /* We need at least one space */
- X while (gap-- > 0)
- X printc (' ') ;
- X print (desc) ;
- X printc ('\n') ; } }
- X
- X }
- SHAR_EOF
- chmod 0640 describe.c ||
- echo 'restore of describe.c failed'
- fi
- # ============= list.c ==============
- if test -f 'list.c' -a X"$1" != X"-c"; then
- echo 'x - skipping list.c (File already exists)'
- else
- echo 'x - extracting list.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'list.c' &&
- /* list.c - List manipulation routines
- X *
- X * SYNOPSIS
- X * #include <list.h>
- X *
- X * void list_init (struct list *list) ;
- X *
- X * Initializes the list. Does not free any storage that
- X * may have been allocated to the list.
- X *
- X * void list_free (struct list *list) ;
- X *
- X * Deallocates and initializes the list.
- X *
- X * void list_push (struct list *list, void *element, size_t length) ;
- X *
- X * Adds the element to the end of the list. If length is
- X * non-zero, a copy is made of the data pointed to by element,
- X * and the address of the copy is added to the list instead.
- X *
- X * void *list_pop (struct list *list) ;
- X *
- X * Returns the last element in the list and removes it.
- X *
- X * void *list_shift (struct list *list) ;
- X *
- X * Returns the first element in the list and removes it
- X *
- X * void *list_element (struct list *list, int element_no) ;
- X *
- X * Returns the specified element (elements are numbered
- X * starting from 0), or NULL if the list does not contain
- X * any elements. Has no effect on the contents of the
- X * list.
- X *
- X * int list_elements (struct list *list) ;
- X *
- X * Returns the number of elements in the list.
- X *
- X * int list_empty (struct list *list) ;
- X *
- X * Returns non-zero if the list contains any elements,
- X * zero otherwise.
- X *
- X * void list_sort (struct list *list, int (*compare) ()) ;
- X *
- X * Sorts the list using compare() (like qsort(3))
- X *
- X * NOTE: list_init(), list_element(), list_elements() and list_empty()
- X * are implemented as macros.
- X *
- X * Copyright (c) 1991 Tim Cook.
- X * Non-profit distribution allowed. See README for details.
- X */
- X
- static char rcsid[] = "$Header: list.c 1.5 91/08/21 $" ;
- X
- #define _LIST_C_
- X
- #define VOID_PTR char *
- #define VOID_PTR_PTR char **
- X
- #include "config.h"
- #include <list.h>
- X
- #ifndef NULL
- #define NULL 0
- #endif
- X
- extern VOID_PTR allocate () ;
- extern VOID_PTR re_allocate () ;
- X
- #ifndef INITIAL_LIST_ENTRIES
- #define INITIAL_LIST_ENTRIES 512
- #endif
- #ifndef DATA_BLOCK_SIZE
- #define DATA_BLOCK_SIZE 16384
- #endif
- X
- /*
- X * This must be defined to an unsigned integer data type to which
- X * pointer types can be freely cast.
- X */
- X
- #define PTR_CARD unsigned long
- X
- X
- VOID list_free (list)
- X struct list *list ;
- {
- X if (! list_empty (list) && list->s_start != (VOID_PTR_PTR) NULL) {
- X free ((VOID_PTR) list->s_start) ;
- X if (list->data) {
- X int i ;
- X
- X for (i = 2 ; list->data[i] ; i++)
- X free (list->data[i]) ;
- X free ((VOID_PTR) list->data) ; }
- X list_init (list) ; } /* May as well */
- X }
- X
- X
- VOID list_push (list, element, length)
- X struct list *list ;
- X VOID_PTR element ;
- X size_t length ;
- {
- X if (length) {
- X size_t data_block_size ;
- X int new_block = 0 ;
- X
- #ifdef ALIGN
- X /* Make sure subsequent data is stored aligned */
- #if ALIGN == 2
- X if (length & 1)
- X length++ ;
- #else
- X /*
- X * ALIGN must be a power of 2 (reasonable to expect), but at
- X * least we don't need to do a divide.
- X */
- X if (length & (ALIGN - 1))
- X length += ALIGN - (length & (ALIGN - 1)) ;
- #endif
- #endif
- X
- X if (length > DATA_BLOCK_SIZE)
- X data_block_size = length ;
- X else
- X data_block_size = DATA_BLOCK_SIZE ;
- X
- X /*
- X * Allocate storage for data pointed to by list element
- X */
- X if (! list->data) {
- X /* No blocks allocated at all, set it up */
- X list->data = (VOID_PTR_PTR) allocate (sizeof (VOID_PTR_PTR) * 4) ;
- X new_block = 2 ; }
- X else {
- X /* We have some storage, but do we have enough? */
- X if ((PTR_CARD) list->data[0] + length > (PTR_CARD) list->data[1]) {
- X /* Nope, allocate new block */
- X
- X for (new_block = 2 ; list->data[new_block] ; new_block++) ;
- X list->data = (VOID_PTR_PTR) re_allocate (list->data,
- X sizeof (VOID_PTR_PTR) * new_block + 2) ; } }
- X
- X if (new_block) {
- X /*
- X * The contents of the array pointed to by list->data is as
- X * follows:
- X *
- X * The first element points to the first free byte of storage.
- X * The second to the first inaccessible byte.
- X * Subsequent elements contain a NULL-terminated list of all
- X * blocks.
- X */
- X list->data[new_block] = allocate (data_block_size) ;
- X list->data[new_block+1] = (VOID_PTR) NULL ;
- X list->data[0] = list->data[new_block] ;
- X list->data[1] = (VOID_PTR)
- X ((PTR_CARD) list->data[new_block] + data_block_size) ; }
- X
- X /* Copy data pointed to by list element */
- X memcpy (list->data[0], element, length) ;
- X /* Now, make sure we add the right pointer to the list */
- X element = list->data[0] ;
- X /* Adjust free pointer */
- X list->data[0] = (VOID_PTR) ((PTR_CARD) list->data[0] + length) ;
- X }
- X
- X /* Now, add the "pointer" itself */
- X if (list_empty (list)) {
- X list->s_start = (VOID_PTR_PTR) allocate (
- X sizeof (VOID_PTR) * INITIAL_LIST_ENTRIES) ;
- X list->s_end = list->s_start + INITIAL_LIST_ENTRIES ;
- X list->start = list->s_start ;
- X list->end = list->start ; }
- X else {
- X if (list->end >= list->s_end) {
- X /* We need to re-allocate */
- X register PTR_CARD x, y, z ;
- X
- X x = (PTR_CARD) list->s_end - (PTR_CARD) list->s_start ;
- X y = (PTR_CARD) list->start - (PTR_CARD) list->s_start ;
- X z = (PTR_CARD) list->end - (PTR_CARD) list->s_start ;
- X x = x << 1 ; /* Double allocation size */
- X list->s_start = (VOID_PTR_PTR) re_allocate (list->s_start, x) ;
- X list->s_end = (VOID_PTR_PTR) ((PTR_CARD) list->s_start + x) ;
- X list->start = (VOID_PTR_PTR) ((PTR_CARD) list->s_start + y) ;
- X list->end = (VOID_PTR_PTR) ((PTR_CARD) list->s_start + z) ; } }
- X
- X *list->end = element ;
- X list->end++ ;
- X }
- X
- X
- VOID_PTR list_shift (list)
- X struct list *list ;
- {
- X if (list_empty (list))
- X return (VOID_PTR) NULL ;
- X else
- X if (list->start >= list->end)
- X return (VOID_PTR) NULL ;
- X else
- X return *list->start++ ;
- X }
- X
- X
- VOID_PTR list_pop (list) /* WORK */
- X struct list *list ;
- {
- X if (list_empty (list))
- X return (VOID_PTR) NULL ;
- X else
- X if (list->end < list->start) /* WORK */
- X return (VOID_PTR) NULL ;
- X else
- X return *list->end-- ;
- X }
- X
- X
- VOID list_sort (list, compare)
- X struct list *list ;
- X int (*compare) () ;
- {
- X if (! list_empty (list))
- X qsort (list->start, (int) list_elements (list),
- X sizeof (VOID_PTR), compare) ;
- X }
- SHAR_EOF
- chmod 0640 list.c ||
- echo 'restore of list.c failed'
- fi
- echo End of part 2, continue with part 3
- exit 0
-