hyc@umix.cc.umich.edu (Howard Chu) (04/14/88)
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];