ftp.nice.ch/pub/next/unix/archiver/freeze.2.3.N.bs.tar.gz#/freeze/freeze.c

This is freeze.c in view mode; [Download] [Up]

#include "freeze.h"
#include "lz.h"
#include "huf.h"
#include "patchlevel.h"

/*
 * Freeze - data freezing program
 * Version 1.0:
 * This program is made from GNU compress.c and Yoshizaki/Tagawa's
 * lzhuf.c. (Thanks to all of them.)
 * The algorithm is modified for using in pipe
 * (added ENDOF symbol in Huffman table).
 * Version 1.1:
 * Check for lack of bytes in frozen file when melting.
 * Put the GetBit routine into DecodeChar for reduce function-
 * call overhead when melting.
 * Version 1.2:
 * Added delayed coding a la COMIC.
 * Now freeze works on Intels (*NIX, Microsoft, Turbo),
 * Sun (SunOS).
 * Version 2.0:
 * Buffer size is now 8192 bytes, maximum match length - 256 bytes.
 * Improved hash function (with tuning of hash-table)
 * Version 2.1: Noticeable speedup: Insert_Node and Get_Next_Match
 * are now separated. (Boyer-Moore string matching)
 * Version 2.2: Tunable static Huffman table for position information,
 * this info may be given in the command string now.
 * Version 2.2.3: Bug fixes, 10% freezing speedup.
 * Version 2.3: Minor bug fixes (DOS filenames handling, backward
 * compatibility feature improved, "bits" compression ratio display,
 * preventive check for special files), speedups, more comments added.
 */

static char ident[] = "@(#) freeze.c 2.3.%d %s leo@s514.ipmce.su\n";

int exit_stat = 0;

void Usage() {
#ifdef DEBUG

# ifdef MSDOS
    fprintf(stderr,"Usage: freeze [-cdDfitvVg] [file | +type ...]\n");
# else
    fprintf(stderr,"Usage: freeze [-cdDfvVg] [file | +type ...]\n");
# endif /* MSDOS */

#else

# ifdef MSDOS
    fprintf(stderr,"Usage: freeze [-cdfitvVg] [file | +type ...]\n");
# else
    fprintf(stderr,"Usage: freeze [-cdfvVg] [file | +type ...]\n");
# endif /* MSDOS */

#endif /* DEBUG */
}

void (*meltfunc)();     /* To call something for melting */

short topipe = 0,       /* Write output on stdout, suppress messages */
      precious = 1,     /* Don't unlink output file on interrupt */
      quiet = 1,        /* Don't tell me about freezing */
      do_melt = 0,      /* freeze means "freeze" */
      greedy = 0,       /* GREEDY parsing */
      force = 0;        /* "Force" flag */

char ofname [MAXNAMLEN];
struct stat statbuf;    /* Used by 'main' and 'copystat' routines */

#ifdef MSDOS
   char *last_sep();	/* last slash, backslash, or colon */
   char tail[2];        /* 2nd and 3rd chars of file extension */
# ifdef BIN_DEFAULT
	short image = O_BINARY;
# else
	short image = O_TEXT;
# endif
#else
#  define last_sep(s) rindex((s), '/')	/* Unix always uses slashes */
char deffile[] = "/etc/default/freeze";
#endif

#ifdef DEBUG
short debug = 0;
short verbose = 0;
char * pr_char();
long symbols_out = 0, refers_out = 0;
#endif /* DEBUG */

/* Do not sleep when freeze works :-) */
long indc_count, indc_threshold;

#ifdef INT_SIG
int
#else
void
#endif
(*bgnd_flag)();

void writeerr(), copystat(), version(), tune_table();

/*****************************************************************
 *
 * Usage: freeze [-cdfivV] [-t type] [file ...]
 * Inputs:
 *
 *      -c:         Write output on stdout, don't remove original.
 *
 *      -d:         If given, melting is done instead.
 *
 *      -g:         Use "greedy" parsing (1.5% worse, 40% faster).
 *                  (Means nothing when melting)
 *
 *      -f:         Forces output file to be generated, even if one already
 *                  exists, and even if no space is saved by freezeing.
 *                  If -f is not used, the user will be prompted if stdin is
 *                  a tty, otherwise, the output file will not be overwritten.
 *
 *      -i:         Image mode (defined only under MS-DOS).  Prevents
 *                  conversion between UNIX text representation (LF line
 *                  termination) in frozen form and MS-DOS text
 *                  representation (CR-LF line termination) in melted
 *                  form.  Useful with non-text files.  Default if
 *                  BIN_DEFAULT specified.
 *
 *      -b:         Binary mode.  Synonym for -i.  MS-DOS only.
 *
 *      -t:         Text mode (defined only under MS-DOS).  Treat file
 *                  as text (CR-LF and ^Z special) in melted form.  Default
 *                  unless BIN_DEFAULT specified.
 *
 *      -v:         Write freezing statistics
 *
 *      -V:         Write version and compilation options.
 *
 *      file ...:   Files to be frozen.  If none specified, stdin
 *		    is used.
 * Outputs:
 *      file.F:     Frozen form of file with same mode, owner, and utimes
 *	or stdout   (if stdin used as input)
 *
 * Assumptions:
 *      When filenames are given, replaces with the frozen version
 *      (.F suffix) only if the file decreases in size.
 * Algorithm:
 *      Modified Lempel-Ziv-SS method (LZSS), adaptive Huffman coding
 *      for literal symbols and length info.
 *      Static Huffman coding for position info. (Is it optimal ?)
 *      Lower bits of position info are put in output
 *      file without any coding because of their random distribution.
 */

/* From compress.c. Replace .Z --> .F etc */

void main( argc, argv )
register int argc; char **argv;
{
    short overwrite = 0;  /* Do not overwrite unless given -f flag */
    char tempname[100];
    char **filelist, **fileptr;
    char *cp, *rindex();

#ifndef MSDOS
    char *malloc();
#endif

#if defined(__TURBOC__) || !defined(INT_SIG)
    extern void onintr();
#else
    extern onintr();
#endif

#ifdef MSDOS
    char *sufp;
#else
#ifdef INT_SIG
    extern oops();
#else
    extern void oops();
#endif
#endif

#ifndef MSDOS
    if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN )
#endif
    {
	signal ( SIGINT, onintr );
#ifdef __TURBOC__
	setcbrk(1);
#endif
#ifndef MSDOS
	signal ( SIGSEGV, oops );
#endif
    }

    filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
    *filelist = NULL;

    if((cp = last_sep(argv[0])) != 0) {
	cp++;
    } else {
	cp = argv[0];
    }

#ifdef MSDOS

/* use case-insensitive match: parent may not be command.com */
    if(stricmp(cp, "melt.exe") == 0) {
#else
    if(strcmp(cp, "melt") == 0) {
#endif

	do_melt = 1;
	
#ifdef MSDOS
    } else if(stricmp(cp, "fcat.exe") == 0) {
#else
    } else if(strcmp(cp, "fcat") == 0) {
#endif

	do_melt = 1;
	topipe = 1;

    } else {
	/* Freezing */
#ifndef MSDOS
	defopen(deffile);
#else
	cp = rindex(cp, '.');
	*++cp = 'C';
	*++cp = 'N';
	*++cp = 'F';
	*++cp = '\0';
	defopen(argv[0]);
#endif
    }
#ifdef BSD4_2
    /* 4.2BSD dependent - take it out if not */
    setlinebuf( stderr );
#endif /* BSD4_2 */

    /* Argument Processing
     * All flags are optional.
     * -D => debug
     * -V => print Version; debug verbose
     * -d => do_melt
     * -v => unquiet
     * -g => greedy
     * -f => force overwrite of output file
     * -c => cat all output to stdout
     * if a string is left, must be an input filename.
     */
    for (argc--, argv++; argc > 0; argc--, argv++) {
	if (**argv == '-') {	/* A flag argument */
	    while (*++(*argv)) {	/* Process all flags in this arg */
		switch (**argv) {
#ifdef DEBUG
		    case 'D':
			debug = 1;
			break;
		    case 'V':
			verbose = 1;
#else
		    case 'V':
			version();
#endif /* DEBUG */
			break;
#ifdef MSDOS
		    case 'i':
		    case 'b':
			image = O_BINARY;	/* binary (aka image) mode */
			break;

		    case 't':			/* text mode */
			image = O_TEXT;
			break;
#endif
		    case 'v':
			quiet--;
			break;
		    case 'g':
			greedy = 1;
			break;
		    case 'd':
			do_melt = 1;
			break;
		    case 'f':
		    case 'F':
			overwrite = 1;
			force = 1;
			break;
		    case 'c':
			topipe = 1;
			break;
		    case 'q':
			quiet = 1;
			break;
		    default:
			fprintf(stderr, "Unknown flag: '%c'; ", **argv);
			Usage();
			exit(1);
		}
	    }
	}
	else {		/* Input file name */
	    *fileptr++ = *argv; /* Build input file list */
	    *fileptr = NULL;
	}
    }

# ifdef DEBUG
    if (verbose && !debug)
	version();
#endif

    if (*filelist != NULL) {
	for (fileptr = filelist; *fileptr; fileptr++) {
	    if (**fileptr == '+' && do_melt == 0) {
		tune_table(*fileptr + 1);
	/* If a file type is given, but no file names */
		if (filelist[1] == NULL)
			goto Pipe;
		continue;
	    }
	    exit_stat = 0;
	    if (do_melt != 0) {		       /* MELTING */

#ifdef MSDOS
		/* Check for .F or XF suffix; add one if necessary */
		cp = *fileptr + strlen(*fileptr) - 2;
		if ((*cp != '.' && *cp != 'X' && *cp != 'x') ||
		    (*(++cp) != 'F' && *cp != 'f')) {
		    strcpy(tempname, *fileptr);
		    *tail = '\0';
		    if ((cp=rindex(tempname,'.')) == NULL)
			strcat(tempname, ".F");
		    else if(*(++cp) == '\0')
		    /* pseudo-extension: FOOBAR. */
			strcat(tempname, "F");
		    else {
		    /* cp now points to file extension */
			tail[0] = cp[1];        /* save two chars */
			tail[1] = cp[2];
			*(++cp) = '\0';
			strcat(tempname, "XF");
		    }
		    *fileptr = tempname;
		}
#else
		/* Check for .F suffix */
		if (strcmp(*fileptr + strlen(*fileptr) - 2, ".F") != 0) {
		    /* No .F: tack one on */
		    strcpy(tempname, *fileptr);
		    strcat(tempname, ".F");
		    *fileptr = tempname;
		}
#endif /*MSDOS */

		/* Open input file for melting */

		if (checkstat(*fileptr))
			continue;

#ifdef MSDOS
		if ((freopen(*fileptr, "rb", stdin)) == NULL)
#else
		if ((freopen(*fileptr, "r", stdin)) == NULL)
#endif
		{
			perror(*fileptr); continue;
		}

		/* Check the magic number */
		if (getchar() != MAGIC1)
			goto reject;
		switch (getchar()) {
#ifdef COMPAT
		case MAGIC2_1:
			meltfunc = melt1;
			break;
#endif
		case MAGIC2_2:
			meltfunc = melt2;
			break;
		default: reject:
			fprintf(stderr, "%s: not in frozen format\n",
				*fileptr);
			continue;
		}

		/* Generate output filename */
		strcpy(ofname, *fileptr);
		ofname[strlen(*fileptr) - 2] = '\0';  /* Strip off .F */
#ifdef MSDOS
		strcat(ofname, tail);
#endif
	    } else {

			/* FREEZING */
#ifdef MSDOS
		cp = *fileptr + strlen(*fileptr) - 2;
		if ((*cp == '.' || *cp == 'X' || *cp == 'x') &&
		    (*(++cp) == 'F' || *cp == 'f')) {
		    fprintf(stderr,"%s: already has %s suffix -- no change\n",
			*fileptr,--cp); /* } */
#else
		if (strcmp(*fileptr + strlen(*fileptr) - 2, ".F") == 0) {
		    fprintf(stderr, "%s: already has .F suffix -- no change\n",
			*fileptr);
#endif /* MSDOS */

		    continue;
		}
		/* Open input file for freezing */

		if (checkstat(*fileptr))
			continue;

#ifdef MSDOS
		if ((freopen(*fileptr, image == O_TEXT ? "rt" : "rb", stdin))
		    == NULL)
#else
		if ((freopen(*fileptr, "r", stdin)) == NULL)
#endif
		{
		    perror(*fileptr); continue;
		}

		/* Generate output filename */
		strcpy(ofname, *fileptr);
#ifndef BSD4_2		/* Short filenames */
		if ((cp = last_sep(ofname)) != NULL) cp++;
		else cp = ofname;
# ifdef MSDOS
		if (topipe == 0 && (sufp = rindex(cp, '.')) != NULL &&
		    strlen(sufp) > 2) fprintf(stderr,
		    "%s: part of filename extension will be replaced by XF\n",
		    cp);
# else
		if (topipe == 0 && strlen(cp) > 12) {
		    fprintf(stderr,"%s: filename too long to tack on .F\n",cp);
		    continue;
		}
# endif /* MSDOS */
#endif	/* BSD4_2		Long filenames allowed */
							 
#ifdef MSDOS
		/* There is no difference between FOOBAR and FOOBAR. names */
		if ((cp = rindex(ofname, '.')) == NULL)
			strcat(ofname, ".F");
		else if (cp[1] == '\0')
			/* FOOBAR. case */
			strcat(ofname, "F");
		else {
			cp[2] = '\0';
			strcat(ofname, "XF");
		}
#else
		strcat(ofname, ".F");
#endif /* MSDOS */

	    }
	    precious = 0;
	    /* Check for overwrite of existing file */
	    if (overwrite == 0 && topipe == 0) {
		if (stat(ofname, &statbuf) == 0) {
		    char response[2];
		    response[0] = 'n';
		    fprintf(stderr, "%s already exists;", ofname);
#ifndef MSDOS
		    if (foreground()) {
#endif
			fprintf(stderr,
			    " do you wish to overwrite %s (y or n)? ", ofname);
			fflush(stderr);
			read(2, response, 2);
			while (response[1] != '\n') {
			    if (read(2, response+1, 1) < 0) {	/* Ack! */
				perror("stderr"); break;
			    }
			}
#ifndef MSDOS
		    }
#endif
		    if (response[0] != 'y') {
			fprintf(stderr, "\tnot overwritten\n");
			continue;
		    }
		}
	    }
	    if(topipe == 0) {  /* Open output file */

#ifdef DEBUG
		if (do_melt == 0 || debug == 0) {
#endif
#ifdef MSDOS
		if (freopen(ofname, do_melt && image == O_TEXT ? "wt" : "wb",
		    stdout) == NULL)
#else		 
		if (freopen(ofname, "w", stdout) == NULL)
#endif
		{
		    perror(ofname); continue;
		}
#ifdef DEBUG
		}
#endif
		if(quiet != 1)  {
			fprintf(stderr, "%s:", *fileptr);
			indc_threshold = 2048;
			indc_count = 1024;
		}
	    }
	    else {	/* output is to stdout */
#ifdef MSDOS
			/* freeze output always binary; melt output
			   is binary if image == O_BINARY
			*/
		if (do_melt == 0 || image == O_BINARY)
			setmode(fileno(stdout), O_BINARY);
#endif
	    }
	    /* Actually do the freezing/melting */
	    if (do_melt == 0)
		freeze();
#ifndef DEBUG
	    else
		meltfunc();
#else
	    else if (debug && verbose)
		printcodes(meltfunc == (void(*)()) melt2);
	    else
		meltfunc();
#endif /* DEBUG */

	/* check output status, and close to make sure data is written */
	    if ( ferror(stdout) || (!topipe && fclose(stdout) < 0))
		writeerr();

	    if(topipe == 0)
		copystat(*fileptr);     /* Copy stats */
	 }
    } else {		/* Standard input */
Pipe:
	if (fstat(fileno(stdin), &statbuf)) {
		perror("stdin");
		exit(1);
	}
	file_length = statbuf.st_size;

	indc_threshold = file_length / 100;
	if (indc_threshold < 4096)
		indc_threshold = 4096;
#ifdef DEBUG
	fprintf(stderr, "File length: %ld\n", file_length);
#endif

	topipe = 1;
	if (do_melt == 0) {
#ifdef MSDOS
			/* freeze output always binary */
			/* freeze input controlled by -i -t -b switches */
		setmode(fileno(stdout), O_BINARY);
		setmode(fileno(stdin), image);
#endif
		freeze();
		if(quiet != 1)
			putc('\n', stderr);
	} else {
#ifdef MSDOS
		    /* melt input always binary */
		    /* melt output to stdout binary if so requested */
	    setmode(fileno(stdin), O_BINARY);
	    setmode(fileno(stdout), image);
#endif
	    /* Check the magic number */
		if (getchar() != MAGIC1)
			goto badstdin;
		switch (getchar()) {
#ifdef COMPAT
		case MAGIC2_1:
			meltfunc = melt1;
			break;
#endif
		case MAGIC2_2:
			meltfunc = melt2;
			break;
		default: badstdin:
			fprintf(stderr, "stdin: not in frozen format\n");
			exit(1);
		}

#ifndef DEBUG
	    meltfunc();
#else
	    if (debug && verbose)
		printcodes(meltfunc == (void(*)()) melt2);
	    else
		meltfunc();
#endif /* DEBUG */
	}
    }
    exit(exit_stat);
    /*NOTREACHED*/
}

long in_count = 1;      /* length of input */
long bytes_out;         /* length of frozen output */
long file_length = 0;   /* initial length of file */

/* Calculates and prints the compression ratio w/o floating point OPs */

void prratio(stream, was, is)
FILE *stream;
long was, is;
{
	register long q;        /* This works everywhere */

	if (!is) is++;

	if(was > 214748L) {     /* 2147483647/10000 */
		q = was / (is / 10000L);
	} else {
		q = 10000L * was / is; /* Long calculations, though */
	}
	if (q < 0) {
		putc('-', stream);
		q = -q;
	}
	fprintf(stream, "%d.%02d%%", (int)(q / 100), (int)(q % 100));
#ifdef GATHER_STAT
	fprintf(stream, "(%ld / %ld)", was, is);
#endif
}

/* Calculates and prints bits/byte compression ratio as above */

void prbits(stream, was, is)
FILE *stream;
long was, is;
{
	register long q;

	if (!was) was++;

	if(is > 2684354L) {     /*  2147483647/800 */
		q = is / (was / 800L);
	} else {
		q = 800L * is / was;             
	}
	fprintf(stream, " (%d.%02d bits)", (int)(q / 100), (int)(q % 100));
}

/* From compress.c */

char *
rindex(s, c)		/* For those who don't have it in libc.a */
register char *s, c;
{
	char *p;
	for (p = NULL; *s; s++)
	    if (*s == c)
		p = s;
	return(p);
}

/* There was an error when reading or writing files */

void writeerr()
{
    if (!topipe) {
	perror ( ofname );
	unlink ( ofname );
    }
    exit ( 1 );
}

void copystat(ifname)
char *ifname;
{
#ifdef __TURBOC__
struct ftime utimbuf;
#endif
    int mode;
#ifndef __TURBOC__
    time_t timep[2];
#endif

#ifdef MSDOS
    if (_osmajor < 3) freopen("CON","at",stdout); else	  /* MS-DOS 2.xx bug */
#endif

    fclose(stdout);

    if (exit_stat == 2 && (!force)) { /* No freezing: remove file.F */

	if(quiet != 1)
		fprintf(stderr, "-- file unchanged\n");

    } else {		    /* ***** Successful Freezing ***** */

	if (stat (ifname, &statbuf)) {  /* file disappeared ?! */
		perror(ifname);
		exit_stat = 1;
		return;
	}

	exit_stat = 0;
	mode = statbuf.st_mode & 07777;
	if (chmod(ofname, mode))		/* Copy modes */
	    perror(ofname);

#ifndef MSDOS
	/* Copy ownership */
	chown(ofname, (int) statbuf.st_uid, (int) statbuf.st_gid);
#endif

#ifdef __TURBOC__
        getftime(fileno(stdin),&utimbuf);
        freopen(ofname,"rb",stdout);
        setftime(fileno(stdout),&utimbuf);
        fclose(stdout);
#else
	timep[0] = statbuf.st_atime;
	timep[1] = statbuf.st_mtime;
	utime(ofname, timep);	/* Update last accessed and modified times */
#endif
	precious = 1;
	if (unlink(ifname))	/* Remove input file */
	    perror(ifname);
	if(quiet != 1)
		fprintf(stderr, " -- replaced with %s\n", ofname);
	return;		/* Successful return */
    }

    /* Unsuccessful return -- one of the tests failed */
    if (unlink(ofname))
	perror(ofname);
}

/* Checks status of a file, returns 0 if the file may be frozen,
	or 1 otherwise; assigns this value to exit_stat
*/
int checkstat(ifname)
char *ifname;
{
	if (stat (ifname, &statbuf)) {
		perror(ifname);
		return exit_stat = 1;
	}

	/* Do NOT try to freeze /dev/null or /dev/tty ... */

#ifndef MSDOS
	if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
		fprintf(stderr, "%s: ", ifname);
		fprintf(stderr, " not a regular file -- unchanged\n");
		return exit_stat = 1;

	} else if (statbuf.st_nlink > 1) {
		fprintf(stderr, "%s: ", ifname);
		fprintf(stderr, " has %d other links -- unchanged\n",
		statbuf.st_nlink - 1);
		return exit_stat = 1;
	}
#endif /* MSDOS */

	file_length = statbuf.st_size;

	indc_threshold = file_length / 100;
	if (indc_threshold < 4096)
		indc_threshold = 4096;

	return exit_stat = 0;
}

#ifndef MSDOS
/*
 * This routine returns 1 if we are running in the foreground and stderr
 * is a tty. (as in compress(1))
 */
int foreground()
{
	if(bgnd_flag != SIG_DFL)  /* background? */
		return(0);
	else {                          /* foreground */
		if(isatty(2)) {		/* and stderr is a tty */
			return(1);
		} else {
			return(0);
		}
	}
}
#endif

#if defined(__TURBOC__) || !defined(INT_SIG)
void
#endif

/* Exception handler (SIGINT) */

onintr ( ) {
    if (!precious) {
	fclose(stdout);
	unlink ( ofname );
    }
    exit ( 1 );
}

#if defined(__TURBOC__) || !defined(INT_SIG)
void
#endif

/* Exception handler (SIGSEGV) */

oops ( )        /* file is corrupt or internal error */
{
    fflush(stdout);
    fprintf(stderr, "Segmentation violation occured...\n");
    exit ( 1 );
}

/* Prints version and compilation options */

void version()
{
	fprintf(stderr, ident, PATCHLEVEL, PATCHDATE);
	fprintf(stderr, "LZSS 8192/256 + Huffman coding\nOptions: ");
#ifdef COMPAT
	fprintf(stderr, "compatible with vers. 1.0, ");
#endif
#ifdef DEBUG
	fprintf(stderr, "DEBUG, ");
#endif
#ifdef BSD4_2
	fprintf(stderr, "BSD4_2, ");
#endif
#ifdef  __XENIX__
	fprintf(stderr, "XENIX, ");
#endif
#ifdef  __TURBOC__
	fprintf(stderr, "TURBO, ");
#endif
#ifdef GATHER_STAT
	fprintf(stderr, "GATHER_STAT, ");
#endif
	fprintf(stderr, "HASH: %d bits\n", BITS);
	fprintf(stderr, "Static Huffman table: %d %d %d %d %d %d %d %d\n",
		Table2[1], Table2[2], Table2[3], Table2[4],
		Table2[5], Table2[6], Table2[7], Table2[8]);
#ifdef MSDOS
	fprintf(stderr, "Default melted mode: %s\n",
			image == O_BINARY ? "binary" : "text");
#endif
	exit(0);
}

/* Deals with static Huffman table parameters.
	Input: command line option w/o leading `+'.
	Output: fills the array `Table2' if OK, exit(1) otherwise.
*/

void tune_table(type) char *type;
{
	extern char * defread();
	register char *s = defread(type), *t;
	static int v[8];
	int i, is_list = 0;
	if(!s) {
	/* try to consider 'type' as a list of values: n1,n2, ... */
		if(rindex(type, ','))
			is_list = 1;
		else {
			fprintf(stderr, "\"%s\" - no such file type\n", type);
			exit(1);
		}
		if(sscanf(type, "%d,%d,%d,%d,%d,%d,%d,%d",
			v, v+1, v+2, v+3, v+4, v+5, v+6, v+7) != 8) {
			fprintf(stderr,
				"%s - a list of 8 numbers expected\n", type);
			exit(1);
		}
	}
	if(!is_list && (!(t = rindex(s, '=')) ||
		sscanf(++t, "%d %d %d %d %d %d %d %d",
		v, v+1, v+2, v+3, v+4, v+5, v+6, v+7) != 8)) {
		fprintf(stderr,
			"\"%s\" - invalid entry\n", type);
		exit(1);
	}
	for(i = 0; i < 8; i++)
		Table2[i+1] = v[i];
	if(quiet < 0) {
		if(!is_list) {
			t = s;
		/* make full word */
			while(*s != '=' && *s != ' ' && *s != '\t') s++;
			*s = '\0';
		} else
			t = "";
		fprintf(stderr, "Using \"%s%s\" type\n", type, t);
	}
}

#ifdef MSDOS

/* MSDOS typically has ':' and '\\' separators, but some command
  processors (and the int 21h function handler) support '/' too.
  Find the last of these.
*/

char * last_sep(s)
register char *s;
{
	char *p;
	for (p = NULL; *s; s++)
	    if (*s == '/' || *s == '\\' || *s == ':')
		p = s;
	return(p);
}

#endif	/* MSDOS */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.