ARC 5.20 w/Squashing, 6/9
Howard Chu
hyc at umix.cc.umich.edu
Thu Apr 14 16:02:33 AEST 1988
XX i += HSIZE;
XX
XX if (htab[i] == fcode) {
XX ent = codetab[i];
XX return;
XX }
XX if (htab[i] > 0)
XX goto probe;
XX
XXnomatch:
XX putcode(ent, t);
XX ent = c;
XX if (free_ent < maxcodemax) {
XX codetab[i] = free_ent++; /* code -> hashtable */
XX htab[i] = fcode;
XX }
XX if (in_count >= checkpoint)
XX cl_block(t); /* check for adaptive reset */
XX}
XX
XXLONG
XXpred_cm(t) /* finish compressing a file */
XX FILE *t; /* where to put it */
XX{
XX putcode(ent, t); /* put out the final code */
XX putcode(-1, t); /* tell output we are done */
XX
XX return bytes_out; /* say how big it got */
XX}
XX
XX/*
XX * Decompress a file. This routine adapts to the codes in the file building
XX * the string table on-the-fly; requiring no table to be stored in the
XX * compressed file. The tables used herein are shared with those of the
XX * compress() routine. See the definitions above.
XX */
XX
XXINT
XXdecomp(f, t) /* decompress a file */
XX FILE *f; /* file to read codes from */
XX FILE *t; /* file to write text to */
XX{
XX unsigned char *stackp;
XX INT finchar;
XX INT code, oldcode, incode;
XX
XX if ((code = getc_unp(f)) != BITS)
XX abort("File packed with %d bits, I can only handle %d", code, BITS);
XX
XX n_bits = INIT_BITS; /* set starting code size */
XX clear_flg = 0;
XX
XX /*
XX * As above, initialize the first 256 entries in the table.
XX */
XX maxcode = MAXCODE(n_bits = INIT_BITS);
XX setmem(prefix, 256 * sizeof(INT), 0); /* reset decode string table */
XX for (code = 255; code >= 0; code--)
XX suffix[code] = (unsigned char) code;
XX
XX free_ent = FIRST;
XX
XX finchar = oldcode = getcode(f);
XX if (oldcode == -1) /* EOF already? */
XX return; /* Get out of here */
XX putc_ncr((char) finchar, t); /* first code must be 8 bits=char */
XX stackp = stack;
XX
XX while ((code = getcode(f)) > -1) {
XX if (code == CLEAR) { /* reset string table */
XX setmem(prefix, 256 * sizeof(INT), 0);
XX clear_flg = 1;
XX free_ent = FIRST - 1;
XX if ((code = getcode(f)) == -1) /* O, untimely death! */
XX break;
XX }
XX incode = code;
XX /*
XX * Special case for KwKwK string.
XX */
XX if (code >= free_ent) {
XX *stackp++ = finchar;
XX code = oldcode;
XX }
XX /*
XX * Generate output characters in reverse order
XX */
XX while (code >= 256) {
XX *stackp++ = suffix[code];
XX code = prefix[code];
XX }
XX *stackp++ = finchar = suffix[code];
XX
XX /*
XX * And put them out in forward order
XX */
XX do
XX putc_ncr(*--stackp, t);
XX while (stackp > stack);
XX
XX /*
XX * Generate the new entry.
XX */
XX if ((code = free_ent) < maxcodemax) {
XX prefix[code] = (unsigned short) oldcode;
XX suffix[code] = finchar;
XX free_ent = code + 1;
XX }
XX /*
XX * Remember previous code.
XX */
XX oldcode = incode;
XX }
XX}
XX
XX
XX/*************************************************************************
XX * Please note how much trouble it can be to maintain upwards *
XX * compatibility. All that follows is for the sole purpose of unpacking *
XX * files which were packed using an older method. *
XX *************************************************************************/
XX
XX
XX/*
XX * The h() pointer points to the routine to use for calculating a hash value.
XX * It is set in the init routines to point to either of oldh() or newh().
XX *
XX * oldh() calculates a hash value by taking the middle twelve bits of the square
XX * of the key.
XX *
XX * newh() works somewhat differently, and was tried because it makes ARC about
XX * 23% faster. This approach was abandoned because dynamic Lempel-Zev
XX * (above) works as well, and packs smaller also. However, inadvertent
XX * release of a developmental copy forces us to leave this in.
XX */
XX
XXstatic unsigned INT(*h) (); /* pointer to hash function */
XX
XXstatic unsigned INT
XXoldh(pred, foll) /* old hash function */
XX unsigned INT pred; /* code for preceeding string */
XX unsigned char foll; /* value of following char */
XX{
XX LONG local; /* local hash value */
XX
XX local = ((pred + foll) | 0x0800) & 0xFFFF; /* create the hash key */
XX local *= local; /* square it */
XX return (local >> 6) & 0x0FFF; /* return the middle 12 bits */
XX}
XX
XXstatic unsigned INT
XXnewh(pred, foll) /* new hash function */
XX unsigned INT pred; /* code for preceeding string */
XX unsigned char foll; /* value of following char */
XX{
XX return (((pred + foll) & 0xFFFF) * 15073) & 0xFFF; /* faster hash */
XX}
XX
XX/*
XX * The eolist() function is used to trace down a list of entries with
XX * duplicate keys until the last duplicate is found.
XX */
XX
XXstatic unsigned INT
XXeolist(index) /* find last duplicate */
XX unsigned INT index;
XX{
XX INT temp;
XX
XX while (temp = string_tab[index].next) /* while more duplicates */
XX index = temp;
XX
XX return index;
XX}
XX
XX/*
XX * The hash() routine is used to find a spot in the hash table for a new
XX * entry. It performs a "hash and linear probe" lookup, using h() to
XX * calculate the starting hash value and eolist() to perform the linear
XX * probe. This routine DOES NOT detect a table full condition. That MUST be
XX * checked for elsewhere.
XX */
XX
XXstatic unsigned INT
XXhash(pred, foll) /* find spot in the string table */
XX unsigned INT pred; /* code for preceeding string */
XX unsigned char foll; /* char following string */
XX{
XX unsigned INT local, tempnext; /* scratch storage */
XX struct entry *ep; /* allows faster table handling */
XX
XX local = (*h) (pred, foll); /* get initial hash value */
XX
XX if (!string_tab[local].used) /* if that spot is free */
XX return local; /* then that's all we need */
XX
XX else { /* else a collision has occured */
XX local = eolist(local); /* move to last duplicate */
XX
XX /*
XX * We must find an empty spot. We start looking 101 places
XX * down the table from the last duplicate.
XX */
XX
XX tempnext = (local + 101) & 0x0FFF;
XX ep = &string_tab[tempnext]; /* initialize pointer */
XX
XX while (ep->used) { /* while empty spot not found */
XX if (++tempnext == TABSIZE) { /* if we are at the end */
XX tempnext = 0; /* wrap to beginning of table */
XX ep = string_tab;
XX } else
XX ++ep; /* point to next element in table */
XX }
XX
XX /*
XX * local still has the pointer to the last duplicate, while
XX * tempnext has the pointer to the spot we found. We use
XX * this to maintain the chain of pointers to duplicates.
XX */
XX
XX string_tab[local].next = tempnext;
XX
XX return tempnext;
XX }
XX}
XX
XX/*
XX * The unhash() function is used to search the hash table for a given key.
XX * Like hash(), it performs a hash and linear probe search. It returns
XX * either the number of the entry (if found) or NOT_FND (if not found).
XX */
XX
XXstatic unsigned INT
XXunhash(pred, foll) /* search string table for a key */
XX unsigned INT pred; /* code of preceeding string */
XX unsigned char foll; /* character following string */
XX{
XX unsigned INT local, offset; /* scratch storage */
XX struct entry *ep; /* this speeds up access */
XX
XX local = (*h) (pred, foll); /* initial hash */
XX
XX while (1) {
XX ep = &string_tab[local]; /* speed up table access */
XX
XX if ((ep->predecessor == pred) && (ep->follower == foll))
XX return local; /* we have a match */
XX
XX if (!ep->next) /* if no more duplicates */
XX return NOT_FND; /* then key is not listed */
XX
XX local = ep->next; /* move on to next duplicate */
XX }
XX}
XX
XX/*
XX * The init_tab() routine is used to initialize our hash table. You realize,
XX * of course, that "initialize" is a complete misnomer.
XX */
XX
XXstatic INT
XXinit_tab()
XX{ /* set ground state in hash table */
XX unsigned INT i; /* table index */
XX
XX setmem((char *) string_tab, sizeof(string_tab), 0);
XX
XX for (i = 0; i < 256; i++) /* list all single byte strings */
XX upd_tab(NO_PRED, i);
XX
XX inbuf = EMPTY; /* nothing is in our buffer */
XX}
XX
XX/*
XX * The upd_tab routine is used to add a new entry to the string table. As
XX * previously stated, no checks are made to ensure that the table has any
XX * room. This must be done elsewhere.
XX */
XX
XXINT
XXupd_tab(pred, foll) /* add an entry to the table */
XX unsigned INT pred; /* code for preceeding string */
XX unsigned INT foll; /* character which follows string */
XX{
XX struct entry *ep; /* pointer to current entry */
XX
XX /* calculate offset just once */
XX
XX ep = &string_tab[hash(pred, foll)];
XX
XX ep->used = TRUE; /* this spot is now in use */
XX ep->next = 0; /* no duplicates after this yet */
XX ep->predecessor = pred; /* note code of preceeding string */
XX ep->follower = foll; /* note char after string */
XX}
XX
XX/*
XX * This algorithm encoded a file into twelve bit strings (three nybbles). The
XX * gocode() routine is used to read these strings a byte (or two) at a time.
XX */
XX
XXstatic INT
XXgocode(fd) /* read in a twelve bit code */
XX FILE *fd; /* file to get code from */
XX{
XX unsigned INT localbuf, returnval;
XX INT temp;
XX
XX if (inbuf == EMPTY) { /* if on a code boundary */
XX if ((temp = getc_unp(fd)) == EOF) /* get start of next
XX * code */
XX return EOF; /* pass back end of file status */
XX localbuf = temp & 0xFF; /* mask down to true byte value */
XX if ((temp = getc_unp(fd)) == EOF)
XX /* get end of code, * start of next */
XX return EOF; /* this should never happen */
XX inbuf = temp & 0xFF; /* mask down to true byte value */
XX
XX returnval = ((localbuf << 4) & 0xFF0) + ((inbuf >> 4) & 0x00F);
XX inbuf &= 0x000F;/* leave partial code pending */
XX } else { /* buffer contains first nybble */
XX if ((temp = getc_unp(fd)) == EOF)
XX return EOF;
XX localbuf = temp & 0xFF;
XX
XX returnval = localbuf + ((inbuf << 8) & 0xF00);
XX inbuf = EMPTY; /* note no hanging nybbles */
XX }
XX return returnval; /* pass back assembled code */
XX}
XX
XXstatic INT
XXpush(c) /* push char onto stack */
XX INT c; /* character to push */
XX{
XX stack[sp] = ((char) c); /* coerce integer into a char */
XX
XX if (++sp >= TABSIZE)
XX abort("Stack overflow\n");
XX}
XX
XXstatic INT
XXpop()
XX{ /* pop character from stack */
XX if (sp > 0)
XX return ((int) stack[--sp]); /* leave ptr at next empty
XX * slot */
XX
XX else
XX return EMPTY;
XX}
XX
XX/***** LEMPEL-ZEV DECOMPRESSION *****/
XX
XXstatic INT code_count; /* needed to detect table full */
XXstatic unsigned INT code; /* where we are so far */
XXstatic INT firstc; /* true only on first character */
XX
XXINT
XXinit_ucr(new) /* get set for uncrunching */
XX INT new; /* true to use new hash function */
XX{
XX if (new) /* set proper hash function */
XX h = newh;
XX else
XX h = oldh;
XX
XX sp = 0; /* clear out the stack */
XX init_tab(); /* set up atomic code definitions */
XX code_count = TABSIZE - 256; /* note space left in table */
XX firstc = 1; /* true only on first code */
XX}
XX
XXINT
XXgetc_ucr(f) /* get next uncrunched byte */
XX FILE *f; /* file containing crunched data */
XX{
XX unsigned INT c; /* a character of input */
XX INT code, newcode;
XX static INT oldcode, finchar;
XX struct entry *ep; /* allows faster table handling */
XX
XX if (firstc) { /* first code is always known */
XX firstc = FALSE; /* but next will not be first */
XX oldcode = gocode(f);
XX return finchar = string_tab[oldcode].follower;
XX }
XX if (!sp) { /* if stack is empty */
XX if ((code = newcode = gocode(f)) == EOF)
XX return EOF;
XX
XX ep = &string_tab[code]; /* initialize pointer */
XX
XX if (!ep->used) {/* if code isn't known */
XX code = oldcode;
XX ep = &string_tab[code]; /* re-initialize pointer */
XX push(finchar);
XX }
XX while (ep->predecessor != NO_PRED) {
XX push(ep->follower); /* decode string backwards */
XX code = ep->predecessor;
XX ep = &string_tab[code];
XX }
XX
XX push(finchar = ep->follower); /* save first character also */
XX
XX /*
XX * The above loop will terminate, one way or another, with
XX * string_tab[code].follower equal to the first character in
XX * the string.
XX */
XX
XX if (code_count) { /* if room left in string table */
XX upd_tab(oldcode, finchar);
XX --code_count;
XX }
XX oldcode = newcode;
XX }
XX return pop(); /* return saved character */
XX}
SHAR_EOF
if test 23276 -ne "`wc -c arclzw.c`"
then
echo shar: error transmitting arclzw.c '(should have been 23276 characters)'
fi
echo shar: extracting arcmatch.c '(3403 characters)'
sed 's/^XX//' << \SHAR_EOF > arcmatch.c
XX/*
XX * $Log: arcmatch.c,v $
XX * Revision 1.2 88/04/11 18:20:43 hyc
XX * fixup pattern matching for BSD...
XX *
XX * Revision 1.1 88/04/11 18:12:56 hyc
XX * Initial revision
XX *
XX * Revision 1.2 87/12/19 04:39:35 hyc
XX * Don't convert names to upper case for BSD...
XX *
XX * Revision 1.1 87/12/19 04:39:06 hyc
XX * Initial revision
XX *
XX * Revision 1.3 87/08/13 17:05:01 hyc
XX * Run thru indent, fixed some signed vs. unsigned problems
XX * with bp <-> buf, and inbuf and localbuf...
XX * Revision 1.2 87/07/21 08:48:16 hyc ***
XX * empty log message ***
XX *
XX */
XX
XX/*
XX * ARC - Archive utility - ARCMATCH
XX *
XX * Version 2.17, created on 12/17/85 at 20:32:18
XX *
XX * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
XX *
XX * By: Thom Henderson
XX *
XX * Description: This file contains service routines needed to maintain an
XX * archive.
XX *
XX * Language: Computer Innovations Optimizing C86
XX */
XX#include <stdio.h>
XX#include "arc.h"
XX
XXINT
XXmatch(n, t) /* test name against template */
XX char *n; /* name to test */
XX char *t; /* template to test against */
XX{
XX#ifdef MTS
XX fortran patbuild(), patmatch(), patfree();
XX static int patlen = (-1);
XX static int patwork = 0;
XX static int patswch = 0;
XX char patccid[4];
XX static char patchar[2] = "?";
XX static char oldtemp[16] = 0;
XX int namlen, RETCODE;
XX
XX if (strcmp(t, oldtemp)) {
XX if (patwork)
XX patfree(&patwork);
XX strcpy(oldtemp, t);
XX patlen = strlen(oldtemp);
XX patbuild(oldtemp, &patlen, &patwork, &patswch, patccid, patchar, _retcode RETCODE);
XX if (RETCODE > 8) {
XX printf("MTS: patbuild returned %d\n", RETCODE);
XX abort("bad wildcard in filename");
XX }
XX }
XX namlen = strlen(n);
XX patmatch(n, &namlen, &patwork, _retcode RETCODE);
XX switch (RETCODE) {
XX case 0:
XX return (1);
XX case 4:
XX return (0);
XX default:
XX abort("wildcard pattern match failed");
XX }
XX}
XX
XX#else
XX#ifndef BSD
XX upper(n);
XX upper(t); /* avoid case problems */
XX
XX /* first match name part */
XX
XX while ((*n && *n != '.') || (*t && *t != '.')) {
XX if (*n != *t && *t != '?') { /* match fail? */
XX if (*t != '*') /* wildcard fail? */
XX return 0; /* then no match */
XX else { /* else jump over wildcard */
XX while (*n && *n != '.')
XX n++;
XX while (*t && *t != '.')
XX t++;
XX break; /* name part matches wildcard */
XX }
XX } else { /* match good for this char */
XX n++; /* advance to next char */
XX t++;
XX }
XX }
XX
XX if (*n && *n == '.')
XX n++; /* skip extension delimiters */
XX if (*t && *t == '.')
XX t++;
XX
XX#endif /* BSD */
XX
XX /* now match name part */
XX
XX while (*n || *t) {
XX if (*n != *t && *t != '?') { /* match fail? */
XX if (*t != '*') /* wildcard fail? */
XX return 0; /* then no match */
XX else
XX return 1; /* else good enough */
XX } else { /* match good for this char */
XX n++; /* advance to next char */
XX t++;
XX }
XX }
XX
XX return 1; /* match worked */
XX}
XX#endif
XX
XXINT
XXrempath(nargs, arg) /* remove paths from filenames */
XX INT nargs; /* number of names */
XX char *arg[]; /* pointers to names */
XX{
XX char *i, *rindex(); /* string index, reverse indexer */
XX INT n; /* index */
XX
XX for (n = 0; n < nargs; n++) { /* for each supplied name */
XX if (!(i = rindex(arg[n], '\\'))) /* search for end of
XX * path */
XX if (!(i = rindex(arg[n], '/')))
XX i = rindex(arg[n], ':');
XX if (i) /* if path was found */
XX arg[n] = i + 1; /* then skip it */
XX }
XX}
SHAR_EOF
if test 3403 -ne "`wc -c arcmatch.c`"
then
echo shar: error transmitting arcmatch.c '(should have been 3403 characters)'
fi
echo shar: extracting arcmisc.c '(11060 characters)'
sed 's/^XX//' << \SHAR_EOF > arcmisc.c
XX#include <stdio.h>
XX#include <ctype.h>
XX#include "arc.h"
XX#ifdef MSDOS
XX#include <dir.h>
XX#endif
XX#ifdef BSD
XX#include <sys/types.h>
XX#include <sys/dir.h>
XX#endif
XX
XX/* Miscellaneous routines to get ARC running on BSD 4.2... */
XX
XX
XXchar *
XXsetmem(dest, size, c)
XX char *dest;
XX unsigned INT size;
XX char c;
XX{
XX unsigned INT i;
XX
XX for (i = 0; i < size; dest[i] = c, i++);
XX return (&dest[0]);
XX}
XX
XX#ifdef MTS
XX#define CUTOFF sepchr[0]
XX#endif
XX#ifdef MSDOS
XX#define CUTOFF '\\'
XX#endif
XX#ifdef BSD
XX#define CUTOFF '/'
XX#endif
XX
XXstatic INT
XX_makefn(source, dest)
XX unsigned char *source;
XX unsigned char *dest;
XX{
XX INT j;
XX
XX setmem(dest, 17, 0); /* clear result field */
XX for (j = 0; *source && *source != '.'; ++source)
XX if (j < 8)
XX dest[j++] = *source;
XX for (j = 9; *source; ++source)
XX if (j < 13)
XX dest[j++] = *source;
XX}
XX/*
XX * make a file name using a template
XX */
XX
XXchar *
XXmakefnam(rawfn, template, result)
XX unsigned char *rawfn; /* the original file name */
XX unsigned char *template; /* the template data */
XX unsigned char *result; /* where to place the result */
XX{
XX unsigned char et[17], er[17], rawbuf[100], *i, *rindex();
XX
XX *rawbuf = 0;
XX strcpy(rawbuf, rawfn);
XX#ifdef MTS
XX i = rawbuf;
XX if (rawbuf[0] == tmpchr[0]) {
XX i++;
XX strcpy(rawfn, i);
XX } else
XX#endif
XX if ((i = rindex(rawbuf, CUTOFF))) {
XX i++;
XX strcpy(rawfn, i);
XX }
XX#ifdef MSDOS
XX else if ((i = rindex(rawbuf, ':'))) {
XX i++;
XX strcpy(rawfn, i);
XX }
XX#endif
XX if (i)
XX *i = 0;
XX else
XX *rawbuf = 0;
XX
XX _makefn(template, et);
XX _makefn(rawfn, er);
XX *result = 0; /* assure no data */
XX strcat(result, rawbuf);
XX strcat(result, er[0] ? er : et);
XX strcat(result, er[9] ? er + 9 : et + 9);
XX return ((char *) &result[0]);
XX}
XX
XX#if MSDOS
XX
XXINT
XXalphasort(dirptr1, dirptr2)
XX struct direct **dirptr1, **dirptr2;
XX{
XX return (strcmp((*dirptr1)->d_name, (*dirptr2)->d_name));
XX}
XX
XX#endif
XX
XXINT
XXupper(string)
XX char *string;
XX{
XX char *p;
XX
XX for (p = string; *p != NULL; p++)
XX if (islower(*p))
XX *p = toupper(*p);
XX}
XXINT
XXabort(s, arg1, arg2, arg3)
XX char *s;
XX{
XX fprintf(stderr, "ARC: ");
XX fprintf(stderr, s, arg1, arg2, arg3);
XX fprintf(stderr, "\n");
XX#ifdef BSD
XX perror("BSD");
XX#endif
XX exit(1);
XX}
XX
XX#ifndef MTS
XX
XXchar *
XXgcdir(dirname)
XX char *dirname;
XX
XX{
XX if (dirname == NULL || strlen(dirname) == 0)
XX dirname = (char *) malloc(1024);
XX
XX getwd(dirname);
XX}
XX
XXchar *pattern; /* global so that fmatch can use them */
XXINT filemode;
XX
XXchar *
XXdir(filename, mode) /* get files, one by one */
XX char *filename; /* template, or NULL */
XX INT mode; /* search mode bits */
XX{
XX static struct direct **namelist;
XX static char **NameList;
XX#ifdef BSD
XX int alphasort();
XX int scandir();
XX#endif /* BSD */
XX int fmatch();
XX static INT Nnum = 0, ii;
XX char *result = NULL;
XX
XX pattern = filename;
XX filemode = mode; /* set up globals for fmatch */
XX if (Nnum == 0) { /* first call */
XX Nnum = scandir(".", &namelist, fmatch, alphasort);
XX NameList = (char **) malloc(Nnum * sizeof(char *));
XX for (ii = 0; ii < Nnum; ii++) {
XX (NameList)[ii] = (char *) malloc(namelist[ii]->d_namlen + 1);
XX strcpy((NameList)[ii], namelist[ii]->d_name);
XX }
XX ii = 0;
XX }
XX if (ii >= Nnum) { /* all out of files */
XX if (Nnum) { /* there were some files found */
XX for (ii = 0; ii < Nnum; ii++)
XX free(namelist[ii]);
XX free(namelist);
XX }
XX Nnum = 0;
XX return (NULL);
XX } else {
XX return ((NameList)[ii++]);
XX }
XX}
XX
XX
XX#define ASTERISK '*' /* The '*' metacharacter */
XX#define QUESTION '?' /* The '?' metacharacter */
XX#define LEFT_BRACKET '[' /* The '[' metacharacter */
XX#define RIGHT_BRACKET ']' /* The ']' metacharacter */
XX
XX#define IS_OCTAL(ch) (ch >= '0' && ch <= '7')
XX
XXtypedef INT BOOLEAN;
XX#define VOID short
XX#define TRUE 1
XX#define FALSE 0
XX#define EOS '\000'
XX
XXstatic BOOLEAN do_list();
XXstatic char nextch();
XXstatic VOID list_parse();
XX
XX
XX
XX/*
XX * FUNCTION
XX *
XX * do_list process a list and following substring
XX *
XX * SYNOPSIS
XX *
XX * static BOOLEAN do_list (string, pattern) register char *string; register char
XX * *pattern;
XX *
XX * DESCRIPTION
XX *
XX * Called when a list is found in the pattern. Returns TRUE if the current
XX * character matches the list and the remaining substring matches the
XX * remaining pattern.
XX *
XX * Returns FALSE if either the current character fails to match the list or the
XX * list matches but the remaining substring and subpattern's don't.
XX *
XX * RESTRICTIONS
XX *
XX * The mechanism used to match characters in an inclusive pair (I.E. [a-d]) may
XX * not be portable to machines in which the native character set is not
XX * ASCII.
XX *
XX * The rules implemented here are:
XX *
XX * (1) The backslash character may be used to quote any special character.
XX * I.E. "\]" and "\-" anywhere in list, or "\!" at start of list.
XX *
XX * (2) The sequence \nnn becomes the character given by nnn (in octal).
XX *
XX * (3) Any non-escaped ']' marks the end of list.
XX *
XX * (4) A list beginning with the special character '!' matches any character
XX * NOT in list. The '!' character is only special if it is the first
XX * character in the list.
XX *
XX */
XX
XX
XX
XX/*
XX * PSEUDO CODE
XX *
XX * Begin do_list Default result is no match Skip over the opening left bracket
XX * If the next pattern character is a '!' then List match gives FALSE Skip
XX * over the '!' character Else List match gives TRUE End if While not at
XX * closing bracket or EOS Get lower and upper bounds If character in bounds
XX * then Result is same as sense flag. Skip over rest of list End if End while
XX * If match found then If not at end of pattern then Call match with rest of
XX * pattern End if End if Return match result End do_list
XX *
XX */
XX
XXstatic BOOLEAN
XXdo_list(string, pattern)
XX register char *string;
XX char *pattern;
XX{
XX register BOOLEAN ismatch;
XX register BOOLEAN if_found;
XX register BOOLEAN if_not_found;
XX auto char lower;
XX auto char upper;
XX
XX pattern++;
XX if (*pattern == '!') {
XX if_found = FALSE;
XX if_not_found = TRUE;
XX pattern++;
XX } else {
XX if_found = TRUE;
XX if_not_found = FALSE;
XX }
XX ismatch = if_not_found;
XX while (*pattern != ']' && *pattern != EOS) {
XX list_parse(&pattern, &lower, &upper);
XX if (*string >= lower && *string <= upper) {
XX ismatch = if_found;
XX while (*pattern != ']' && *pattern != EOS) {
XX pattern++;
XX }
XX }
XX }
XX if (*pattern++ != ']') {
XX fprintf(stderr, "warning - character class error\n");
XX } else {
XX if (ismatch) {
XX ismatch = match(++string, pattern);
XX }
XX }
XX return (ismatch);
XX}
XX
XX
XX
XX/*
XX * FUNCTION
XX *
XX * list_parse parse part of list into lower and upper bounds
XX *
XX * SYNOPSIS
XX *
XX * static VOID list_parse (patp, lowp, highp) char **patp; char *lowp; char
XX * *highp;
XX *
XX * DESCRIPTION
XX *
XX * Given pointer to a pattern pointer (patp), pointer to a place to store lower
XX * bound (lowp), and pointer to a place to store upper bound (highp), parses
XX * part of the list, updating the pattern pointer in the process.
XX *
XX * For list characters which are not part of a range, the lower and upper bounds
XX * are set to that character.
XX *
XX */
XX
XXstatic VOID
XXlist_parse(patp, lowp, highp)
XX char **patp;
XX char *lowp;
XX char *highp;
XX{
XX *lowp = nextch(patp);
XX if (**patp == '-') {
XX (*patp)++;
XX *highp = nextch(patp);
XX } else {
XX *highp = *lowp;
XX }
XX}
XX
XX
XX
XX/*
XX * FUNCTION
XX *
XX * nextch determine next character in a pattern
XX *
XX * SYNOPSIS
XX *
XX * static char nextch (patp) char **patp;
XX *
XX * DESCRIPTION
XX *
XX * Given pointer to a pointer to a pattern, uses the pattern pointer to
XX * determine the next character in the pattern, subject to translation of
XX * backslash-char and backslash-octal sequences.
XX *
XX * The character pointer is updated to point at the next pattern character to be
XX * processed.
XX *
XX */
XX
XXstatic char
XXnextch(patp)
XX char **patp;
XX{
XX register char ch;
XX register char chsum;
XX register INT count;
XX
XX ch = *(*patp)++;
XX if (ch == '\\') {
XX ch = *(*patp)++;
XX if (IS_OCTAL(ch)) {
XX chsum = 0;
XX for (count = 0; count < 3 && IS_OCTAL(ch); count++) {
XX chsum *= 8;
XX chsum += ch - '0';
XX ch = *(*patp)++;
XX }
XX (*patp)--;
XX ch = chsum;
XX }
XX }
XX return (ch);
XX}
XX
XX/*
XX * Filename match - here, * matches everything
XX */
XX
XXint
XXfmatch(direntry)
XX struct direct *direntry;
XX{
XX char *ptr, *string;
XX
XX string = direntry->d_name;
XX
XX if (!strcmp(pattern, "") || !strcmp(pattern, "*.*") || !strcmp(pattern, "*"))
XX return (1);
XX return (match(string, pattern));
XX}
XX#else
XX/* dir code for MTS under Bell Labs C... */
XX
XXchar *
XXdir(filepattern, junk)
XX char *filepattern; /* template or NULL */
XX INT junk; /* unused on MTS */
XX{
XX char *malloc(), *index();
XX#ifdef USECATSCAN
XX fortran catscan(), fileinfo();
XX
XX struct catname {
XX short len;
XX char name[257];
XX } pattern;
XX
XX struct catval {
XX int maxlen;
XX int actlen;
XX char name[257];
More information about the Alt.sources
mailing list