[comp.sources.misc] v07i094: brik: a general-purpose CRC-32 program

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (07/22/89)

Posting-number: Volume 7, Issue 94
Submitted-by: dhesi@bsu-cs.bsu.edu (Rahul Dhesi)
Archive-name: brik2/part01

Brik 2.0 is a general-purpose program that calculates both text and
binary cyclic redundancy codes (CRCs).  Text-mode CRCs calculated by
brik are portable across systems for files that are in the usual text
format on each system.  Binary-mode CRCs are portable for files that
are moved from system to system without any change.  Brik can also be
used to verify and update a Checksum header of this type:

Checksum: 2656043176 (verify with "brik -cv")

Brik 2.0 is believed to compile and run under MS-DOS (Turbo C 2.0, MASM
or TASM assemblers);  System V Release 2;  4.3BSD;  and VAX/VMS.
Assembly code for the 8086 processor is included with makes the program
quite fast under MS-DOS.

There are three shar archives.  Extract each separately.

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	brik.c
#	turboc.c
#	brik.h
# This archive created: Mon Jul 17 01:23:02 1989
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'brik.c'" '(29846 characters)'
if test -f 'brik.c'
then
	echo shar: "will not over-write existing file 'brik.c'"
else
sed 's/^X//' << \SHAR_EOF > 'brik.c'
X/* ::[[ @(#) brik.c 1.55 89/07/12 03:31:06 ]]:: */
X#ifndef LINT
X static char sccsid[]="::[[ @(#) brik.c 1.55 89/07/12 03:31:06 ]]::";
X#endif
X
X#define DATESTAMP "1989/07/11"
X#define VERSION   "2.0"
X
X/*
X(c) Copyright 1989 Rahul Dhesi, All rights reserved.  Permission is
Xgranted to use, copy, and distribute this file under the terms of the
XGNU General Public License version 1.0.
X*/
X
X/*
XChecksum: 2990338384      (check or update this with "brik")
X*/
X
Xstatic char copyright[] =
X"\
XCopyright 1989 Rahul Dhesi, All rights reserved.  Use and distribution is\n\
Xpermitted under the terms of the GNU General Public License version 1.0.\n\
X";
X
X/*
XThe following code assumes the ASCII character set and 8-bit bytes.
X*/
X
X#ifndef OK_STDIO
X# include <stdio.h>
X# define OK_STDIO
X#endif
X
X#include "brik.h"          /* configuration options */
X#include "assert.h"
X
Xtypedef unsigned long tcrc; /* type of crc value -- same as in addbfcrc.c */
X
X#ifdef GENTAB
Xvoid mkcrctab PARMS ((void));
X#endif /* GENTAB */
X
X#ifdef STDINCLUDE
X# include <stdlib.h>
X# include <string.h>
X#else
X FILE *fopen PARMS ((char *filename, char *mode));
X char *nextfile PARMS ((int, char *, int));
X char *strcat PARMS ((char *, char *));
X char *strchr PARMS ((char *, char));
X char *strcpy PARMS ((char *, char *));
X char *strncat PARMS ((char *, char *, int));
X int strcmp PARMS ((char *, char *));
X int strlen PARMS ((char *));
X void exit PARMS ((int status));
X#endif /* STDINCLUDE */
X
X/* twilight zone functions -- may or may not be standard */
Xint main PARMS ((int, char **));
Xint getopt PARMS ((int, char **, char *));
X
X/* our own functions */
XFILE *efopen PARMS ((char *filename, char *mode, int errlevel));
Xchar suffix PARMS ((void));
Xchar *nextfile PARMS ((int, char *, int));
Xvoid dofname PARMS ((char *));
Xvoid dofptr PARMS ((FILE *, char *));
Xint lowerit PARMS ((int));
Xvoid printhdr PARMS ((void));
Xvoid readnames PARMS ((FILE *));
Xvoid updatefile PARMS ((FILE *, long, tcrc, char *));
Xint whole_check PARMS ((FILE *, char *));
Xtcrc findcrc PARMS ((FILE *, char *, int *));
Xtcrc xatol PARMS ((char *));
Xvoid addbfcrc PARMS ((char *, int));
Xvoid brktst PARMS ((void));
Xvoid hdrcrc PARMS ((FILE *, char *));
Xvoid longhelp PARMS ((void));
Xvoid shorthelp PARMS ((void));
Xvoid showerr PARMS ((char *, int));
X
X/* the following constants can be changed if you know what you are doing */
X#define ERRLIMIT  127      /* exit(n) returns n not exceeding this */
X#define LINESIZE  8192     /* handle lines of up to this length */
X#define ERRBUFSIZ 1024     /* buffer size for perror() message */
X#define BACKSIZE  1024     /* how much to seek back looking for header */
X#define BINTABSIZ 256      /* size of binary char test table */
X#ifdef CTRLZ_CHECK
X# define Z_THRESHOLD 10    /* see how CTRLZ_CHECK is used later */
X#endif /* CTRLZ_CHECK */
X
X/* the following constants should not be changed */
X#define MYNL      10       /* newline for CRC calculation */
X#define PATTERN   "Checksum:"    /* look for this header */
X#define CHARSINCRC 10      /* characters in CRC */
X#define CMTCH     '#'      /* begins comment in CRC list */
X
X/* error levels */
X#define LVL_WARN  0
X#define LVL_ERR   1
X#define LVL_FATAL 2
X
X#ifdef  USEINDEX
X# define strchr   index
X#endif  /* USEINDEX */
X
X#ifdef NOTRAIL_B              /* avoid trailing "b" in mode string */
X# define BRIK_RD  "r"
X# define BRIK_RW  "r+"
X# define BRIK_RDB "r"
X#else
X# define BRIK_RD  "r"
X# define BRIK_RW  "r+"
X# define BRIK_RDB "rb"
X#endif   /* NOTRAIL_B */
X
X#define  whitespace(x)     (strchr(" \t\n",(x)) != NULL)
X/* format strings for printing CRCs and filenames etc. */
Xstatic char ok[] =      "ok ";
Xstatic char bad[] =     "BAD";
Xstatic char blank[] =   "   ";
Xstatic char fmtstr[] = "%10lu%c %s %s\n";
Xstatic char hdrfmt[] = "Checksum: %10lu  %s\n";
X
Xstatic char version[] = VERSION;
Xchar bintab[BINTABSIZ];    /* binary char test table */
Xint patlen;                /* length of PATTERN */
Xint errcount = 0;          /* count of errors */
Xint gen1 = 0;              /* generate CRCs for all files */
Xint gen2 = 0;              /* generate CRCs for files with headers */
Xint silent = 0;            /* be silent, just set error status */
Xint quiet = 0;             /* talks less, but not completely silent */
Xint verbose = 0;           /* be verbose, print message for good files too */
Xint updfile = 0;           /* update file by inserting CRC */
Xint check1 = 0;            /* whether to check header crcs */
Xint check2 = 0;            /* whether to check whole file crcs */
Xint fromfile = 0;          /* read filenames from a file */
Xint binary = 0;            /* manipulate binary file */
Xint trailing = 0;          /* include trailing empty lines */
Xint prthdr = 0;            /* print Checksum: XXXXXXXXXX header */
Xint autocheck = 0;         /* brik must decide if text or binary */
Xint is_stdin = 0;          /* current file is stdin */
Xint doubtful = 0;          /* text but doubtful */
X
X#ifdef DEBUG
Xint debugging = 0;
X#endif
X
X/* opens file, prints error message if can't open */
XFILE *efopen (fname, mode, level)
Xchar *fname;               /* filename to open */
Xchar *mode;                /* mode, e.g. "r" or "r+" */
Xint level;                 /* error level */
X{
X   FILE *fptr;
X   fptr = fopen (fname, mode);
X   if (fptr == NULL)
X      showerr (fname, level);
X   return (fptr);
X}
X
X/* LOWERIT is a function or macro that returns lowercase of a character */
X#ifndef LOWERIT
X# ifdef AVOID_MACROS
X#  define LOWERIT    lowerit
X# else
X#  define LOWERIT(c)        ((c)>='A' && (c)<='Z' ? ('a'-'A')+(c) : (c))
X# endif
X#endif
X
X/* Function needed by SEEKFIX code even if a macro is available */
Xint lowerit (c) int c;  /* returns lowercase of an ASCII character */
X{
X  if (c >= 'A' && c <= 'Z') return (('a'-'A') + c);
X  else return (c);
X}
X
X/* STRNICMP is a case-insensitive strncmp */
X#ifndef STRNICMP
Xint STRNICMP (s1, s2, n)
Xregister char *s1, *s2;
Xint n;
X{
X   assert (n >= 0);
X   assert (LOWERIT('X') == 'x');
X   assert (LOWERIT('*') == '*');
X
X   for ( ; LOWERIT(*s1) == LOWERIT(*s2);  s1++, s2++) {
X      if (--n == 0 || *s1 == '\0')
X         return(0);
X   }
X   return(LOWERIT(*s1) - LOWERIT(*s2));
X}
X#endif /* STRNICMP */
X
X#ifdef AVOID_MACROS
X# define BRINCMP     STRNICMP
X#else
X# define BRINCMP(s1,s2,n) (LOWERIT(*(s1))!=LOWERIT(*(s2))||STRNICMP(s1,s2,n))
X#endif
X
X
X#define xdigit(x)    ((x) >= '0' && (x) <= '9')
X
X/*
Xxatol is given a string that (supposedly) begins with a string
Xof digits.  It returns a corresponding positive numeric value.
X*/
Xtcrc xatol (str)
Xchar *str;
X{
X   tcrc retval;
X   retval = 0L;
X   while (xdigit(*str)) {
X      retval = retval * 10L + (*str-'0');
X      str++;
X   }
X   return (retval);
X}
X
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X{
X   int i;
X   int c;                        /* next option letter */
X   int count = 0;                /* count of required options seen */
X   char *infname;                /* name of file to read filenames from */
X   FILE *infptr;                 /* open file ptr for infname */
X
X   extern int optind;            /* from getopt: next arg to process */
X   extern int opterr;            /* used by getopt */
X
X   opterr = 1;                   /* so getopt will print err msg */
X   argv[0] = "brik";             /* for getopt to use */
X
X   patlen = strlen (PATTERN);
X
X#ifdef DEBUG
X   while ((c = getopt (argc, argv, "cCgGasqvWHfbThd")) != EOF)
X#else
X   while ((c = getopt (argc, argv, "cCgGasqvWHfbTh")) != EOF)
X#endif
X   {
X      switch (c) {
X         case 'a':   autocheck++; binary = 0; trailing = 0; break;
X         case 'c':   check1++; count++; break;
X         case 'C':   check2++; count++; break;
X         case 'g':   gen1++; count++; break;
X         case 'G':   gen2++; count++; break;
X         case 's':   silent++; verbose = 0; break;
X         case 'q':   quiet++; verbose = 0; break;
X         case 'v':   verbose++; silent = 0; break;
X         case 'W':   updfile++; break;
X         case 'f':   fromfile++; break;
X         case 'b':   binary++; autocheck = 0; trailing = 0; break;
X         case 'T':   trailing++; binary = 0; autocheck = 0; break;
X         case 'H':   prthdr++; break;
X#ifdef DEBUG
X         case 'd':   debugging++; break;
X#endif
X         case 'h':   longhelp();
X         case '?':   shorthelp();
X      }
X   }
X
X   if (count != 1)
X      shorthelp();
X
X   if (binary && (check1 || gen1)) {
X      fprintf (stderr, "brik: fatal: Can't read or update CRC header in binary mode\n");
X      exit (1);
X   }
X
X   if ((updfile || prthdr) && !gen1) {
X      fprintf (stderr, "brik: fatal: Use of -W and -H requires -g\n");
X      exit (1);
X   }
X
X#if 0
X   if (gen1 || gen2 && !updfile)
X      silent = 0;
X#endif
X
X   if (gen1)
X      autocheck = 0;
X
X#ifdef GENTAB
X   /* generate CRC table */
X   mkcrctab();
X#endif /* GENTAB */
X
X   /* initialize binary char test table */
X   for (i = 0;  i < BINTABSIZ;  i++) {
X      if ( (i < 7) || (i > 13 && i < 26) || (i > 126)) /*ASCII binary chars*/
X         bintab[i] = 1;
X      else
X         bintab[i] = 0;
X   }
X
X   i = optind;
X
X   if (fromfile) {                  /* read filenames from file */
X      if (i >= argc) {              /* need filenames after -f */
X         fprintf (stderr, "brik: fatal: Filename(s) needed after -f\n");
X         exit (1);
X      }
X      for (; i < argc;  i++) {
X         infname = argv[i];
X         if (strcmp(infname, "-") == 0) { /* "-" means stdin */
X            readnames (stdin);
X         } else {
X#ifdef WILDCARD
X            extern char *nextfile();
X            nextfile (0, infname, 0);     /* initialize fileset 0 */
X            while ((infname = nextfile(1, (char *) NULL, 0)) != NULL) {
X               infptr = efopen (infname, BRIK_RD, LVL_ERR);
X               readnames (infptr);
X               fclose (infptr);
X            }
X#else
X            infptr = efopen (infname, BRIK_RD, LVL_ERR);
X            readnames (infptr);
X            fclose (infptr);
X#endif /* WILDCARD */
X         }
X      }
X   } else {                         /* read filenames from command line */
X      if (i >= argc) {
X#ifndef BIN_STDIN_OK
X         if (binary && !check2) {
X            fprintf (stderr, "brik: fatal: Can't handle stdin in binary mode\n");
X            exit (1);
X         }
X#endif
X         is_stdin = 1;
X         dofptr (stdin, "stdin");      /* if no files, read stdin */
X      } else {
X         for (;  i < argc;  i ++) {
X#ifdef WILDCARD
X            extern char *nextfile();
X            char *one_name;               /* a matching filename */
X            nextfile (0, argv[i], 0);     /* initialize fileset 0 */
X            while ((one_name = nextfile(1, (char *) NULL, 0)) != NULL)
X               dofname (one_name);
X#else
X            dofname (argv[i]);
X#endif /* WILDCARD */
X         }
X      }
X   }
Xerrexit:
X   if (errcount > ERRLIMIT)
X      errcount = ERRLIMIT;       /* don't overflow status code */
X   exit (errcount);
X   return (errcount);            /* to keep turbo c and lint happy */
X}
X
X/*
X**   Reads names from supplied file pointer and handles them.  Just
X**   returns if supplied NULL file pointer.  Will also expand wildcards
X**   in names read from this file.
X*/
Xvoid readnames (infptr)
XFILE *infptr;
X{
X   char buf[LINESIZE];
X   if (infptr == NULL)
X      return;
X   while (fgets (buf, LINESIZE, infptr) != NULL) {
X#ifdef WILDCARD
X      char *fname;                  /* matching filename */
X      extern char *nextfile();
X#endif /* WILDCARD */
X      buf[strlen(buf)-1] = '\0'; /* zap trailing newline */
X#ifdef WILDCARD
X      nextfile (0, buf, 1);     /* initialize fileset 1 */
X      while ((fname = nextfile(1, (char *) NULL, 1)) != NULL) {
X         dofname (fname);
X      }
X#else
X      dofname (buf);
X#endif /* WILDCARD */
X   }
X}
X
X/* do one filename */
Xvoid dofname (this_arg)
Xchar *this_arg;
X{
X   FILE *this_file;
X   char *mode;                         /* "r", "rb", "rw", etc. for fopen */
X#ifdef BRKTST
X   extern void brktst();
X   brktst();
X#endif
X
X   if (autocheck)
X      binary = 0;             /* always begin by assuming text */
X
X   if (strcmp(this_arg,"-") == 0) {
X#ifndef BIN_STDIN_OK
X      if (binary && !check2) {
X         fprintf (stderr, "brik: fatal: Can't handle stdin in binary mode\n");
X         exit (1);
X      }
X#endif
X
X      is_stdin = 1;
X      this_file = stdin;
X      this_arg = "stdin";
X   } else {
X      if (updfile) {
X         assert (!binary);
X         this_file = efopen (this_arg, BRIK_RW, LVL_ERR);
X      } else {
X         if (binary && !check2) /* check2 reads filenames, not data */
X            mode = BRIK_RDB;
X         else
X            mode = BRIK_RD;
X         this_file = efopen (this_arg, mode, LVL_ERR);
X      }
X   }
X   if (this_file == NULL)
X      errcount++;
X   else {
X#ifdef NOCASE
X      char *p;
X      for (p = this_arg;  *p != '\0';  p++)
X         *p = LOWERIT(*p);
X#endif
X      dofptr (this_file, this_arg);
X      if (this_file != NULL)
X         fclose (this_file);
X   }
X}
X
X/* returns appropriate suffix character for CRC, based on global flags */
Xchar suffix()
X{
X   return (doubtful ? '*' : (binary ? 'b' : (trailing ? 'T' : ' ')));
X}
X
X
X/*
X**   Do one file pointer.  Decides if CRC header will be read or written,
X**   or whether just the whole file will be read.
X*/
Xvoid dofptr (fptr, fname)
XFILE *fptr;
Xchar *fname;
X{
X   int retval;                      /* return value from findcrc */
X   if (check2)
X      whole_check (fptr, fname);    /* do whole file check from list */
X   else if (gen1 || check1)         /* header-based CRC check or update */
X      hdrcrc (fptr, fname);
X   else {                           /* whole-file CRC calculation */
X      extern tcrc crccode;
X      assert (gen2);
X      printhdr();
X      (void) findcrc (fptr, fname, &retval);
X      if (!silent) {
X         if (!binary && retval == 1)
X            doubtful = 1;                 /* tell suffix() it's '*' */
X         printf (fmtstr, crccode, suffix(), blank, fname);
X      }
X   }
X   is_stdin = 0;                    /* set, but not reset, by our caller */
X   doubtful = 0;                    /* sphagetti code, need to fix later */
X}
X
X/* Does whole file check from a list of files and CRCs */
Xwhole_check (fptr, listname)
XFILE *fptr;                   /* open file ptr of CRC list file */
Xchar *listname;               /* name of CRC list file */
X{
X   tcrc fcrc;        /* recorded crc */
X   char *fname;               /* name of file whose CRC being checked */
X   char buf [LINESIZE];       /* line buffer */
X   char *p;                   /* temp ptr */
X   FILE *orgfile;             /* file pointer for original file to check */
X   int lino = 0;              /* line no. in list file for error msg */
X   char *mode;                /* mode string for fopen */
X
X   while (fgets (buf, LINESIZE, fptr) != NULL) {
X      lino++;
X      p = buf;
X      if (*p == CMTCH)              /* skip comment lines */
X         continue;
X      while (*p != '\0' && whitespace(*p))      /* skip whitespace */
X         p++;
X      if (*p == '\0')
X         continue;                              /* skip empty lines */
X      if (!xdigit(*p))
X         goto badline;
X      fcrc = xatol (p); /* recorded CRC */
X
X      while (xdigit(*p))
X         p++;                                   /* skip past numeric chars */
X
X      doubtful = binary = trailing = 0;
X      if (*p == 'b')                            /* 'b' means binary */
X         binary = 1;
X
X      if (*p == 'T')                            /* 'T' means trailing mode */
X         trailing = 1;
X
X      if (*p == '*')
X         doubtful = 1;                          /* text but doubtful */
X
X      while (*p != '\0' && !whitespace(*p)) /* to whitespace */
X         p++;
X      while (whitespace(*p))   /* skip whitespace */
X         p++;
X
X      if (*p == '\n' || *p == '\0') {     /* if at end of line */
X         goto badline;
X      }
X      fname = p;
X      while (*p != '\0' && !whitespace(*p))  /* skip to whitespace */
X         p++;
X      *p = '\0';                    /* null-terminate filename */
X
X      if (binary)
X         mode = BRIK_RDB;
X      else
X         mode = BRIK_RD;
X
X      orgfile = efopen (fname, mode, LVL_ERR);
X      if (orgfile == NULL) {
X         errcount++;
X      } else {
X         int retval;
X         tcrc foundcrc;
X         assert (!(binary && trailing));
X         foundcrc = findcrc (orgfile, fname, &retval);
X         if (foundcrc == fcrc) {
X            if (verbose)
X               printf (fmtstr, foundcrc, suffix(), ok, fname);
X         } else {
X            if (!silent)
X               printf (fmtstr, foundcrc, suffix(), bad, fname);
X            errcount ++;
X         }
X         if (orgfile != NULL)
X            fclose (orgfile);
X      }
X   }
X   return;
Xbadline:
X   fprintf (stderr,
X      "brik: error: Abandoning %s due to badly formatted line %d\n",
X      listname, lino);
X   return;
X}
X
X
X/*
XInitializing the CRC to all one bits avoids failure of detection
Xshould entire data stream get cyclically bit-shifted by one position.
XThe calculation of the probability of this happening is left as
Xan exercise for the reader.
X*/
X#define INITCRC   0xFFFFFFFFL;
X
X/*
X**   hdrcrc processes one file given an open file pointer
X**   and the filename.  The filename is used for messages etc.
X**   It does all manipulation of header-related CRCs, i.e.,
X**   checking generating header CRC.  It deals only with text files.
X*/
Xvoid hdrcrc (fptr, fname)
XFILE *fptr;
Xchar *fname;
X{
X   char buf[LINESIZE];
X   int lino = 0;
X   char *ptr;
X   tcrc fcrc;   /* crc recorded in file */
X   extern tcrc crccode;
X   int retval;                      /* return value from findcrc */
X   long hdrpos;                     /* where we found crc header in file */
X
X   crccode = INITCRC;
X
X   assert (!binary);
X
X#ifndef NIXSEEK
X   hdrpos = ftell (fptr);
X#endif
X   while (fgets (buf, LINESIZE, fptr) != NULL) {
X#ifdef BRKTST
X      extern void brktst();
X      brktst();
X#endif
X      lino++;
X      if (BRINCMP (buf, PATTERN, patlen) == 0) {      /* found header */
X#ifdef NIXSEEK
X         hdrpos = ftell (fptr);        /* seek posn of line with header */
X#endif
X         ptr = buf + patlen;           /* point to beyond header */
X         while (*ptr != '\0' && whitespace(*ptr))
X            ptr++;                     /* skip white space */
X         fcrc = xatol (ptr);           /* get stored crc */
X         while (xdigit(*ptr))
X            ptr++;                     /* skip past digits */
X         if (check1) {
X            if (*ptr == 'T')           /* if 'T' suffix then */
X               trailing = 1;          /* ..include trailing empty lines */
X            else
X               trailing = 0;
X         }
X
X         /* find CRC for rest of file */
X         (void) findcrc (fptr, fname, &retval);
X
X         if (gen1) {                   /* generating CRC */
X            if (updfile) {             /* if updating file posn */
X               updatefile (fptr, hdrpos, crccode, fname); /* then do it */
X               if (prthdr && !silent)  /* printing header */
X                  printf (hdrfmt, crccode, fname);
X            } else {
X               if (prthdr && !silent)  /* printing header */
X                  printf (hdrfmt, crccode, fname);
X               else if (!silent)
X                  printf (fmtstr, crccode, suffix(), blank, fname);
X            }
X         } else {                      /* checking CRC */
X            if (fcrc == crccode) {
X               if (verbose)
X                  printf (fmtstr, crccode, suffix(), ok, fname);
X            } else {
X               if (!silent)
X                  printf (fmtstr, crccode, suffix(), bad, fname);
X               errcount ++;
X            }
X         }
X         return;
X      } /* end if (BRINCMP (...) ) */
X#ifndef NIXSEEK
X      hdrpos = ftell (fptr);
X#endif
X   } /* end of while (fgets(...)) */
X
X   /* reach here if header not found -- this is an error */
X   if (!silent)
X      printf ("%10s      %s\n", "????", fname);
X   errcount++;
X   return;
X}
X
X/* update file with CRC -- must be seekable */
Xvoid updatefile (fptr, hdrpos, crccode, fname)
XFILE *fptr;
Xlong hdrpos;
Xtcrc crccode;
Xchar *fname;
X{
X   char buf[LINESIZE];
X   int buflen;             /* will hold count of chars in buf */
X   int chars_to_print;     /* chars needed to fill in CRC */
X
X   /*
X   1 for blank, CHARSINCRC for actual CRC, and possibly
X   1 more for 'T' suffix if including trailing empty lines too
X   */
X   chars_to_print = 1 + CHARSINCRC + (trailing ? 1 : 0);
X
X#ifndef NIXSEEK
X   /* hdrpos is already seek position of header */
X   if (fseek (fptr, hdrpos, 0) != 0) { /* seek back */
X      fprintf(stderr,
X         "brik: error: No CRC written, seek failed on %s\n",fname);
X      return;
X   }
X
XSEEKFIX
X
X   fgets (buf, LINESIZE, fptr);
X   if (BRINCMP (buf, PATTERN, patlen) == 0)
X      goto foundit;
X   fprintf(stderr,
X      "brik: error: No CRC written, header lost in %s\n",fname);
X   return;
X#else
X   /* Following code does fseeks in a non-ANSI-conformant way */
X   /* hdrpos is seek position *after* header was read.  Need to get back */
X   if (hdrpos >= BACKSIZE)
X      hdrpos -= BACKSIZE;
X   else
X      hdrpos = 0L;
X   if (fseek (fptr, hdrpos, 0) != 0) {       /* seek back first */
X      fprintf(stderr,"brik: error: No CRC written, seek failed on %s\n",fname);
X      return;
X   }
X   /* now seek forward until we see CRC header again */
X   hdrpos = ftell (fptr);
X   while (fgets (buf, LINESIZE, fptr) != NULL) {
X      if (BRINCMP (buf, PATTERN, patlen) == 0)
X         goto foundit;
X      hdrpos = ftell (fptr);
X   }
X   fprintf(stderr,"brik: error: No CRC written, header lost in %s\n",fname);
X   return;
X#endif /* NIXSEEK */
X
Xfoundit:    /* hdrpos points to line with header */
X   if (fseek (fptr, hdrpos, 0) != 0) { /* seek failed */
X      fprintf(stderr,"brik: error: No CRC written, seek failed on %s\n",fname);
X      return;
X   }
XSEEKFIX
X   /* we are seeked back to the line with the CRC header */
X
X#ifdef CHECKSEEK  /* triple-check seeks */
X   {
X      char tmpbf1[LINESIZE];
X      char tmpbf2[LINESIZE];
X      fseek (fptr, hdrpos, 0);
X      assert (ftell (fptr) == hdrpos);
XSEEKFIX
X      fgets (tmpbf1, LINESIZE, fptr);
X      fseek (fptr, 0L, 0); fseek (fptr, 0L, 2);    /* exercise seeks */
X      fseek (fptr, hdrpos, 0);
X      assert (ftell (fptr) == hdrpos);
XSEEKFIX
X      fgets (tmpbf2, LINESIZE, fptr);
X      if (strcmp(tmpbf1,tmpbf2) != 0 || BRINCMP(tmpbf1,PATTERN,patlen) != 0) {
X         fprintf (stderr,
X            "brik: error: Bad seek on %s, abandoning this file\n", fname);
X         return;
X      }
X      fseek (fptr, hdrpos, 0);
XSEEKFIX
X   }
X#endif /* CHECKSEEK */
X
X#ifdef DEBUG
X   if (debugging) {  /* zap newline, print buffer, restore newline */
X      int nlpos; char savech;
X      nlpos = strlen(buf) - 1;  savech = buf[nlpos];  buf[nlpos] = '\0';
X      fprintf (stderr, "read header  [%s]\n", buf);
X      buf[nlpos] = savech;
X   }
X#endif
X
X   buflen = strlen (buf);
X#ifdef DEBUG
X   if (debugging)  /* need chars_to_print plus one trailing space or newline */
X      fprintf(stderr,"need %d chars, have %d\n",chars_to_print+1,buflen-patlen);
X#endif
X   if (buflen - patlen > chars_to_print) {      /* if enough space */
X      char sprbuf[1+CHARSINCRC+1+1+6];  /* blank+CRC+suffix+null+fudge */
X      char *ptr;
X      int i;
X      ptr = &buf[patlen];                 /* point to beyond header */
X      sprintf (sprbuf, " %10lu%c", crccode, 'T');
X      for (i = 0;  i < chars_to_print;  i++) /* trailing 'T' possibly ignored */
X         ptr[i] = sprbuf[i];
X      if (ptr[i] != '\n')
X         ptr[i] = ' ';           /* terminate with newline or blank */
X      fseek (fptr, 0L, 1);       /* after read, must seek before write */
X      if (fwrite (buf, 1, buflen, fptr) != buflen) {
X         fprintf(stderr,
X            "brik: error: Write failed while writing CRC to %s\n",fname);
X      } else if (verbose)
X         printf (fmtstr, crccode, suffix(), blank, fname);
X         /* printf ("%10lu      %s\n", crccode, fname); */
X#ifdef DEBUG
X      buf[strlen(buf)-1] = '\0'; /* zap trailing newline */
X      if (debugging)
X         fprintf (stderr, "wrote header [%s]\n", buf);
X#endif
X   } else {
X      fprintf(stderr,"brik: error: Not enough space for CRC in %s\n",fname);
X      return;
X   }
X}
X
Xvoid longhelp()
X{
Xprintf ("%s\n", copyright);
X
Xprintf (
X"Usage:  brik -cCgGsqvWHfbT [ file ] ...  (must have one of -cCgG) \n\n");
X
Xprintf ("Brik %s (%s) generates and verifies CRC-32 checksums.  It can\n",
X      version, DATESTAMP);
X
Xprintf ("\
Xalso read or update a \"Checksum: xxxxxxxxxx\" header at the beginning\n\
Xof a line in which xxxxxxxxxx represents the CRC of all lines in the file\n\
X*after* this header.  A filename of \"-\" (or none) means standard input.\n\n\
X");
X
Xprintf ("\
X   -g     look for Checksum: header, generate CRC for rest of file\n\
X   -c     get CRC from header, verify CRC of rest of file\n\
X   -G     generate CRC for entire file (add -b for binary files)\n\
X   -C     verify all file CRCs from output of -G (-f is not needed)\n\
X   -b     use binary mode -- read file byte by byte, not line by line\n\
X   -a     automatically decide whether each file is text or binary\n\
X");
X
X#ifdef WILDCARD
Xprintf ("   -f     read filenames (wildcards ok) from specified files\n");
X#else
Xprintf ("   -f     read filenames from specified files\n");
X#endif
X
Xprintf ("\
X   -v     be verbose, report all results (else only errors are reported)\n\
X   -s     be silent, say nothing, just return status code\n\
X   -q     be quiet, don't print header for -G\n\
X   -W     after generating CRC with -g, write it to original header\n\
X   -H     after generating CRC with -g, print header to stdout\n\
X   -T     include trailing empty lines, normally ignored (text mode only)\n\
X");
Xexit (0);
X}
X
X/*
X**   Generates CRC of an open file, from current file position to end
X**   Except in -T mode, will ignore all trailing empty lines in text
X**   files.  Algorithm for this is:
X**      1.   After each nonempty line, save crccode so far.
X**      2.   At end of file, if last line was empty, use saved crccode rather
X**           than current one.
X**   In whole-file mode, if was text mode but binary file, and if auto
X**   check is on, will re-open file in binary mode and do it again
X**   (except if stdin was being read)
X**   Returns 1 in retval if it detected that a text file contained binary
X*    characters.
X*/
X
Xtcrc findcrc (fptr, fname, retval)
XFILE *fptr;
Xchar *fname;
Xint *retval;
X{
X   int count;
X   char buf[LINESIZE];
X   extern tcrc crccode;
X   int warned = 0;
X   tcrc savedcrc; /* save crccode for trailing empty lines */
X   int buflen;
X   *retval = 0;         /* will become 1 later if needed */
X
Xagain:      /* restart here if retrying in binary mode */
X
X   savedcrc = crccode = INITCRC;
X
X   if (binary) {                                   /* binary */
X      while ((count = fread (buf, 1, LINESIZE, fptr)) > 0) {
X#ifdef BRKTST
X         extern void brktst(); brktst();
X#endif
X         addbfcrc (buf, count);
X      }
X   } else {                                           /* text */
X#ifdef CTRLZ_CHECK
X      int lines = 0;                /* will count lines */
X#endif /* CTRLZ_CHECK */
X      buflen = 1;                   /* assume empty lines so far */
X      while (fgets (buf, LINESIZE, fptr) != NULL) {
X         register char *p;
X         char *limit;
X#ifdef BRKTST
X         extern void brktst(); brktst();
X#endif
X
X#ifdef CTRLZ_CHECK
X         lines++;    /* count lines */
X#endif /* CTRLZ_CHECK */
X
X         buflen = strlen (buf);
X         limit = buf + buflen;
X         for (p = buf;  p != limit;  p++) {
X            if (!warned && BINCHAR(*p)) {
X               *retval = 1;
X               if (autocheck && !is_stdin)/* restart, now known to be binary */
X                  goto restart;
X               else {               /* don't restart, just warn */
X                  warned = 1;
X               }
X            }
X            if (*p == '\n')
X               *p = MYNL;
X         }
X         addbfcrc (buf, buflen);
X         if (buflen != 1)
X            savedcrc = crccode;
X      }
X#ifdef CTRLZ_CHECK
X      if (gen2) {
X         int z_bin_check PARMS ((FILE *fptr, char *fname));
X         if (!warned && lines < Z_THRESHOLD && z_bin_check (fptr, fname)) {
X            *retval = 1;
X            if (autocheck && !is_stdin)
X               goto restart;
X         }
X      }
X#endif
X      if (!trailing && buflen == 1)
X         crccode = savedcrc;
X   }
X   if (ferror (fptr))
X      fprintf (stderr, "brik: warning: error occurred while reading %s\n", fname);
X   return (crccode);
X
X/*
Xreach here if we were trying to get a text crc but the file was binary, we
Xare in autocheck mode, and we are not reading stdin.  Now we re-initialize
Xvariables, reopen the file in binary mode, and begin again.
X*/
Xrestart:
X   binary = 1;
X   fclose (fptr);  fptr = efopen (fname, BRIK_RDB, LVL_ERR);
X   if (fptr == NULL) {
X      errcount++;
X      return (crccode);
X   } else
X      goto again;
X}
X
Xvoid printhdr ()
X{
X   static int firsttime = 1;
X   if (firsttime && !quiet && !silent) {
X      printf ("%c Whole file CRCs generated by Brik v%s.  Use \"brik -C\" to verify them.\n\n",
X         CMTCH, version);
X        printf ("%c CRC-32        filename\n", CMTCH);
X        printf ("%c ------        --------\n\n", CMTCH);
X      firsttime = 0;
X   }
X}
X
X/*
X**   Prints error message via perror().  The message is printed in the
X**   format "brik: %s: %s" where the first %s is the level text ("warning",
X**   "error", or "fatal") and the second %s is the string supplied by
X**   perror().
X**
X*/
X
Xvoid showerr (errmsg, level)
Xchar *errmsg;
Xint level;
X{
X#define ERRSTRMAX  40         /* don't copy more than this many chars */
X   static char leveltext[][7] =   {"warning", "error", "fatal"};
X   char errbuf[ERRBUFSIZ];       /* buffer for error message */
X   strcpy (errbuf, "brik: ");
X   assert (level >= LVL_WARN && level <= LVL_FATAL);
X   strncat (errbuf, leveltext[level], ERRSTRMAX);
X   strcat (errbuf, ": ");
X   strncat (errbuf, errmsg, ERRSTRMAX);
X   perror (errbuf);
X}
X
Xvoid shorthelp()
X{
X   fprintf (stderr, "%s\n\n%s", "Usage to get help:  brik -h", copyright);
X   exit (1);
X}
SHAR_EOF
fi
echo shar: "extracting 'turboc.c'" '(9089 characters)'
if test -f 'turboc.c'
then
	echo shar: "will not over-write existing file 'turboc.c'"
else
sed 's/^X//' << \SHAR_EOF > 'turboc.c'
X/* nextfile.c */
X/* ::[[ @(#) turboc.c 1.7 89/07/12 03:18:30 ]]:: */
X#ifndef LINT
Xstatic char sccsid[]="::[[ @(#) turboc.c 1.7 89/07/12 03:18:30 ]]::";
X#endif
X
X/*
XThis file is used only for MS-DOS.  It is used with Turbo C 1.0.  It also
Xapparently works with Microsoft C 5.1 (see makefile.msc).
X*/
X
X/*
XChecksum:   60385500      (check or update this with "brik")
X*/
X
X/*
Xnextfile() is a general wildcard expansion function that may be used
Xwith other programs.  Usage instructions are below.  It does not
Xsimply expand wildcards in an entire argument list.  Instead, it is
Xcalled in a loop as described below, and returns one matching
Xfilename each time it is called.
X
XThese functions are for the SMALL MEMORY MODEL ONLY.
X*/
X
X#include "assert.h"
X#include "brik.h"
X
X#define  FMAX  2        /* Number of different filename patterns */
X#define  PATHSIZE 200   /* Size of MS-DOS pathname */
X#define  NULL  0
X
X#ifdef ANSIPROTO
Xchar *strtcpy (char *, char *);
Xint strlen (char *);
Xchar *strcpy (char *, char *);
X#endif
X
X
X/* Structure definitions for MS-DOS software interrupt intdos() */
X
Xstruct WORD_REGISTERS {
X   unsigned int ax, bx, cx, dx, si, di, carry, flags;
X};
X
X/* byte registers */
X
Xstruct BYTE_REGISTERS {
X   unsigned char al, ah, bl, bh, cl, ch, dl, dh;
X};
X
Xunion REGS {
X   struct WORD_REGISTERS x;
X   struct BYTE_REGISTERS h;
X};
X
Xint intdos (union REGS *, union REGS *);
X
X/*
Xformat of disk transfer address after MS-DOS calls FindFirst and
XFindNext
X*/
Xstruct dta_t {
X   char junk[22];
X   int time;
X   int date;
X   long size;
X   char fname[13];
X   char just_in_case[4];   /* in case MS-DOS writes too much */
X};
X
Xvoid setdta (struct dta_t *);
Xvoid fcbpath (struct dta_t *, char *, char *);
X
X/*******************/
X/*
Xnextfile() returns the name of the next source file matching a filespec.
X
XINPUT
X   what: A flag specifying what to do.  If "what" is 0, nextfile()
X      initializes itself.  If "what" is 1, nextfile() returns the next
X      matching filename.
X   filespec:  The filespec, usually containing wildcard characters, that
X      specifies which files are needed.  If "what" is 0, filespec must be
X      the filespec for which matching filenames are needed.  If "what" is 1,
X      nextfile() does not use "filespec" and "filespec" should be NULL to
X      avoid an assertion error during debugging.
X   fileset:  nextfile() can keep track of more than one set of filespecs.
X      The fileset specifies which filespec is being matched and therefore
X      which set of files is being considered.  "fileset" can be in the
X      range 0:FMAX.  Initialization of one fileset does not affect the
X      other filesets.
X
XOUTPUT
X   IF what == 0 THEN
X      return value is NULL
X   ELSE IF what == 1 THEN
X      IF a matching filename is found THEN
X         return value is pointer to matching filename including supplied path
X      ELSE
X         IF at least one file matched previously but no more match THEN
X            return value is NULL
X         ELSE IF supplied filespec never matched any filename THEN
X            IF this is the first call with what == 1 THEN
X               return value is pointer to original filespec
X            ELSE
X               return value is NULL
X            END IF
X         END IF
X      END IF
X   END IF
X
XNOTE
X
X   Initialization done when "what"=0 is not dependent on the correctness
X   of the supplied filespec but simply initializes internal variables
X   and makes a local copy of the supplied filespec.  If the supplied
X   filespec was illegal, the only effect is that the first time that
X   nextfile() is called with "what"=1, it will return the original
X   filespec instead of a matching filename.  That the filespec was
X   illegal will become obvious when the caller attempts to open the
X   returned filename for input/output and the open attempt fails.
X
XUSAGE HINTS
X
Xnextfile() can be used in the following manner:
X
X      char *filespec;                  -- will point to filespec
X      char *this_file;                 -- will point to matching filename
X      filespec = parse_command_line(); -- may contain wildcards
X      FILE *stream;
X
X      nextfile (0, filespec, 0);          -- initialize fileset 0
X      while ((this_file = nextfile(1, (char *) NULL, 0)) != NULL) {
X         stream = fopen (this_file, "whatever");
X         if (stream == NULL)
X            printf ("could not open %s\n", this_file);
X         else
X            perform_operations (stream);
X      }
X*/
X
Xchar *nextfile (what, filespec, fileset)
Xint what;                        /* whether to initialize or match      */
Xregister char *filespec;         /* filespec to match if initializing   */
Xregister int fileset;            /* which set of files                  */
X{
X   static struct dta_t new_dta [FMAX+1];     /* our own private dta        */
X   static int first_time [FMAX+1];
X   static char pathholder [FMAX+1][PATHSIZE]; /* holds a pathname to return */
X   static char saved_fspec [FMAX+1][PATHSIZE];/* our own copy of filespec   */
X   union REGS regs;
X
X   assert(fileset >= 0 && fileset <= FMAX);
X   if (what == 0) {
X      assert(filespec != NULL);
X      strcpy (saved_fspec[fileset], filespec);  /* save the filespec */
X      first_time[fileset] = 1;
X      return ((char *) NULL);
X   }
X
X   setdta (&new_dta[fileset]);   /* set new dta -- our very own */
X   assert(what == 1);
X   assert(filespec == NULL);
X   assert(first_time[fileset] == 0 || first_time[fileset] == 1);
X
X   if (first_time[fileset]) {             /* first time -- initialize etc. */
X      /* find first matching file */
X      regs.h.ah = 0x4e;                   /* FindFirst MS-DOS call    */
X      regs.x.dx = (unsigned int) saved_fspec[fileset]; /* filespec to match */
X      regs.x.cx = 0;                      /* search attributes       */
X      intdos (&regs, &regs);
X   } else {
X      /* find next matching file */
X      regs.h.ah = 0x4f;                   /* FindNext MS-DOS call     */
X      intdos (&regs, &regs);
X   }
X
X   if (regs.x.carry != 0) {            /* if error status                  */
X      if (first_time[fileset]) {       /*   if file never matched then     */
X         first_time[fileset] = 0;
X         return (saved_fspec[fileset]);/*      return original filespec    */
X      } else {                         /*   else                           */
X         first_time[fileset] = 0;      /*                                  */
X         return ((char *) NULL);         /*      return (NULL) for no more   */
X      }
X   } else {                                        /* a file matched */
X      first_time[fileset] = 0;
X      /* add path info  */
X      fcbpath (&new_dta[fileset], saved_fspec[fileset], pathholder[fileset]);
X      return (pathholder[fileset]);                /* matching path  */
X   }
X} /* nextfile */
X
X/*******************/
X/* This function sets the dta to a new dta */
Xvoid setdta (dta)
Xstruct dta_t *dta;
X{
X   union REGS regs;
X   regs.h.ah = 0x1a;                /* SetDTA Call       */
X   regs.x.dx = (unsigned int) dta;  /* new DTA address   */
X   intdos (&regs, &regs);
X}
X
X/*******************/
X/*
Xfcbpath() accepts a pointer to the Disk Transfer Area, a character
Xpointer to a pathname that may contain wildcards, and a character
Xpointer to a buffer.  It copies into the buffer the path prefix from
Xthe pathname and the filename prefix from the DTA so that it forms a
Xcomplete path.
X*/
X
Xvoid fcbpath (dta, old_path, new_path)
Xstruct dta_t *dta;
Xchar *old_path;
Xregister char *new_path;
X{
X   register int i;
X   int length, start_pos;
X
X   strcpy(new_path, old_path);               /* copy the whole thing first */
X   length = strlen(new_path);
X   i = length - 1;                           /* i points to end of path */
X   while (i >= 0 && new_path[i] != '/' && new_path[i] != '\\' && new_path[i] != ':')
X      i--;
X   /* either we found a "/", "\", or ":", or we reached the beginning of
X      the name.  In any case, i points to the last character of the
X      path part. */
X   start_pos = i + 1;
X   for (i = 0; i < 13; i++)
X      new_path[start_pos+i] = dta->fname[i];
X   new_path[start_pos+13] = '\0';
X}
X/* -- END OF nextfile() and related functions -- */
X
Xextern unsigned _stklen = 30000;
X
X#include <conio.h>
Xvoid brktst() { kbhit(); }      /* test for user interrupt */
X
X#ifdef CTRLZ_CHECK
X# define CTRLZ_BUFSIZ   1024
X# include <io.h>
X# include <fcntl.h>
X
X/*
Xz_bin_check is called to see if the specified file is a
Xbinary file.  If so, it will return nonzero.  To avoid an early control Z
Xfalsely indicating EOF, z_bin_check changes the mode of the file
Xto binary.
X*/
Xint z_bin_check (fptr, fname)
XFILE *fptr;
Xchar *fname;
X{
X   char *p;
X   char *limit;
X   char buf[CTRLZ_BUFSIZ];
X   int count;
X
X   setmode (fileno(fptr), O_BINARY);   /* set stream to binary mode */
X   fseek (fptr, 0L, SEEK_SET);         /* rewind */
X
X   while ((count = fread (buf, 1, CTRLZ_BUFSIZ, fptr)) > 0) {
X      limit = buf + count;
X      for (p = buf;  p != limit;  p++) {
X      extern char bintab[];      /* needed for BINCHAR */
X         if (BINCHAR(*p))
X            return (1);          /* indicate binary file */
X      }
X   }
X   return (0);
X}
X#endif /* CTRLZ_CHECK */
SHAR_EOF
fi
echo shar: "extracting 'brik.h'" '(8828 characters)'
if test -f 'brik.h'
then
	echo shar: "will not over-write existing file 'brik.h'"
else
sed 's/^X//' << \SHAR_EOF > 'brik.h'
X/* ::[[ @(#) brik.h 1.31 89/07/12 03:18:00 ]]:: */
X
X/*
XChecksum: 3082630653      (check or update this with "brik")
X*/
X
X/*
XThe contents of this file are hereby released to the public domain.
X
X                                   -- Rahul Dhesi 1989/03/10
X*/
X
X/*
XBrik assumes eight-bit bytes and the ASCII character set.  There may also
Xbe some implicit assumptions that the parity bit in characters in text
Xfiles is always zero.
X
XOptions for compiling brik.c on various systems.
X
XGENTAB      If this symbol is defined, brik will generate a CRC table at
X            runtime rather than using one statically stored in the
X            executable code.  This will make brik start up a tad slower
X            but will make the code smaller, since the CRC table takes
X            up about 256 * sizeof(unsigned long) bytes.  The code is
X            smaller only if your C compiler correctly handles
X            uninitialized static data by allocating space for it only
X            at runtime.  Not all compilers are this smart.  If yours
X            isn't, definining GENTAB can actually increase the size
X            of your code.
XNOTRAIL_B   Define this if a trailing "b" is not permitted in the fopen
X            mode string to open files in binary mode.  To the best of
X            my knowledge, only Ultrix objects to a trailing "b".
XBIN_STDIN_OK  If stdin can be a binary file, this should be defined so
X            that brik will allow binary CRCs to be calculated for stdin.
X            If it is not defined, brik will give an error message if a
X            binary CRC calculation is attempted on stdin.  Should be
X            defined for **IX and similar environments.
XWILDCARD    Define this if wildcards are to be expanded by this program.
X            If WILDCARD is defined, then a function nextfile() must also
X            be available that conforms to the specifications in turboc.c.
XUSEINDEX    Define this symbol to make brik use index() instead of strchr().
X            Probably needed only 4.2BSD and earlier.
XBRKTST      If defined, brik will explicitly test for user interrupts in
X            all long loops, so that the program can easily be interrupted
X            on microcomputers that don't accept user interrupts
X            asynchronously.  If BRKTST is defined, brik will call the
X            function brktst() periodically.  This function should check
X            for a user interrupt and abort the program if it has occurred.
XNIXSEEK     If seeks are UNIX-like, i.e., seeks are possible at any byte
X            offset even in text files, then NIXSEEK may be defined to make
X            the -gW option perform faster.  If NIXSEEK is not defined, all
X            seeks will be to line boundaries using an offset already
X            obtained from ftell().  Even on non-UNIX-like systems, it *may*
X            be possible to define NIXSEEK, since when brik seeks to an
X            arbitrary byte boundary, it always immediately reads
X            sequentially forward to a line boundary.  Seeks are needed only
X            for the -gW option, which causes brik to seek back to where
X            it found the Checksum: header so it can update the stored CRC.
XCHECKSEEK   If seeks are flaky it may help to define CHECKSEEK.  In this
X            case brik will seek, read a line, seek again, read the line
X            again, compare the two, and proceed only if both reads gave the
X            checksum header it was looking for, thus confirming that the
X            seeks are working right.  This is a very conservative strategy
X            to minimize the risk of corrupting a file by overwriting it at
X            the wrong place due to a faulty seek.
XBUG1,       If ftell() just after fgets() does not return the correct seek
XBUG2        offset of the next line, one of these two symbols can be defined
X            (but not both).  Each adds different bug fix code and one of them
X            may work for you.
XANSIPROTO   If defined, ANSI-style function prototypes will be used.
XSTDINCLUDE  If defined, ANSI-standard include files will be included.
X            If not defined, many standard functions will be declared
X            explicitly.
XNDEBUG      If this symbol is defined, assert() macros throughout the
X            brik code will get nulled out, making the executable code
X            slightly smaller.
XDEBUG       If this symbol is defined, an undocumented -d switch will
X            be accepted that will cause information about Checksum:
X            header reads and writes to be printed.
XEXITBUG     Define this symbol if the exit() function has a bug causing
X            anomalous results if the exit code is not exactly 1.
XAVOID_MACROS  Brik uses macros for speed in case-insensitive string
X            comparisons.  If you get "macro too long" or "expression too
X            complex" or similar compilation errors, you can define the
X            symbol AVOID_MACROS.  This will cause slower but more compact
X            code to be used that does not use long macros, possibly
X            allowing compilation.
XLOWERIT     If a fast macro or function call is available that will accept
X            a single parameter of type "int" and return its lowercase
X            value, the symbol LOWERIT may be defined to invoke it.  This
X            macro or function must accept any int value, whether or not
X            it represents an uppercase character.  Since LOWERIT is
X            never called with side-effects, it can safely be a macro.
X            If any include file is needed, include it here.  For example,
X            if a tolower() macro or function is available that requires
X            <ctype.h> to be included, use "#include <ctype.h>" followed
X            by "#define LOWERIT tolower" somewhere in brik.h.
XSTRNICMP    If a case-insensitive implementation of strncmp is available,
X            define STRNICMP to be equivalent to it.  If STRNICMP is not
X            defined, brik uses its own case-insensitive string comparison
X            function.  STRNICMP must accept the same arguments as strncmp.
XBINCHAR     Brik uses a table look-up to test if a character is binary, to
X            warn the user if a text mode CRC is being used on a binary file.
X            The user may optionally define his own BINCHAR(c) macro, which
X            must return nonzero if c should be considered a binary character.
XNOCASE      This symbol should be defined if the filesystem is case-
X            insensitive.  It will cause all filenames printed to be in
X            lowercase.  This will help make a list of files generated by
X            the -G option to be more easily usable on systems with case-
X            sensitive filesystems, as most file transfer mechanisms (e.g.
X            zmodem, kermit, zoo archives) will be compatible with this.
XCTRLZ_CHECK If this symbol is defined, special-case code is compiled in
X            that will more reliably detect when a file is binary, even
X            if control Z occurs early in a file causing the C runtime
X            library to falsely assume end-of-file.
X
X                                     -- Rahul Dhesi
X                                        1989/07/07
X                                        UUCP:      iuvax!bsu-cs!dhesi
X                                        Internet:  dhesi@bsu-cs.bsu.edu
X*/
X
X#ifdef TURBOC
X# define GENTAB
X# define WILDCARD
X# define ANSIPROTO
X# define STDINCLUDE
X# define BRKTST
X# define NOCASE
X# define STRNICMP    strnicmp
X# include <ctype.h>
X# define LOWERIT tolower
X# define CTRLZ_CHECK
X#endif /* TURBOC */
X
X/* Microsoft C 5.1 -- use supplied "makefile.msc" makefile -- not tested */
X#ifdef MSC51
X# define WILDCARD
X# define ANSIPROTO
X# define BRKTST
X/* # define BUG1 or BUG2 if necessary -- not tested */
X# define NOCASE
X# define STRNICMP    strnicmp
X  int strnicmp (char *, char *, unsigned);
X# include <ctype.h>
X# define LOWERIT tolower
X#endif /* MSC51 */
X
X#ifdef SYS_V
X# define NIXSEEK
X# define BIN_STDIN_OK
X#endif /* SYS_V */
X
X#ifdef BSD
X# define NIXSEEK
X# define USEINDEX
X# define BIN_STDIN_OK
X#endif /* BSD */
X
X#ifdef VMS
X# define WILDCARD
X# define CHECKSEEK
X# define BUG2
X# define EXITBUG
X# define NOCASE
X#endif /* VMS */
X
X#ifdef BUG1
X# define SEEKFIX  \
X fgetc(fptr);while(lowerit(fgetc(fptr))!='c')fseek(fptr,-2L,1);fseek(fptr,-1L,1);
X#endif
X
X#ifdef BUG2
X# define SEEKFIX  \
X   fseek(fptr,-2L,1);while(fgetc(fptr)!='\n');
X#endif
X
X#ifndef BUG1
X# ifndef BUG2
X#  define SEEKFIX
X# endif
X#endif
X
X/* another thing to try */
X/* fseek(fptr,-2L,1);while(lowerit(fgetc(fptr))!='C');fseek(fptr,-1L,1); */
X
X#ifdef EXITBUG
X# define exit bugexit
X#endif
X
X#ifndef PARMS
X# ifdef ANSIPROTO
X#  define   PARMS(x)    x
X# else
X#  define   PARMS(x)    ()
X# endif
X#endif
X
X/* macro for testing if chars within range -- table look-up */
X#ifndef BINCHAR
X# define BINCHAR(c)      bintab[(c) & 0xff]
X#endif /* BINCHAR */
SHAR_EOF
fi
exit 0
#	End of shell archive