[comp.sources.misc] v07i068: flip 1.0: a newline conversion program

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

Posting-number: Volume 7, Issue 68
Submitted-by: dhesi@bsu-cs.bsu.edu (Rahul Dhesi)
Archive-name: flip

This program converts text file between MS-DOS and **IX format.  It
works under System V, 4.3BSD, Ultrix, and MS-DOS/Turbo C.  It detects
binary files in a nearly foolproof way and leaves them alone unless you
override this.  It will also leave files alone that are already in the
right format.  User interrupts are handled gracefully and no garbage or
corrupted files left behind.  An MS-DOS binary will eventually appear
in comp.binaries.ibm.pc.

Rahul Dhesi <dhesi@bsu-cs.bsu.edu>
UUCP:    ...!{iuvax,pur-ee}!bsu-cs!dhesi

#! /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:
#	Checksums
#	FILES
#	flip.1
#	flip.c
#	flip.h
#	flip.man
#	flip.prj
#	getopt.c
#	install.doc
#	makefile.nix
#	makefile.tcc
#	turboc.c
#	turboc.cfg
# This archive created: Tue Jul  4 17:58:12 1989
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'Checksums'" '(429 characters)'
if test -f 'Checksums'
then
	echo shar: "will not over-write existing file 'Checksums'"
else
sed 's/^X//' << \SHAR_EOF > 'Checksums'
X# Whole file CRCs generated by Brik v1.0.  Use "brik -C" to verify them.
X
X# CRC-32        filename
X# ------        --------
X
X2395754544      FILES
X1324253258      flip.1
X2015490080      flip.c
X 116242883      flip.h
X3654056916      flip.man
X3390294771      flip.prj
X2215166699      getopt.c
X3196976162      install.doc
X3441461244      makefile.nix
X2236661872      makefile.tcc
X3460687634      turboc.c
X1182134946      turboc.cfg
SHAR_EOF
fi
echo shar: "extracting 'FILES'" '(682 characters)'
if test -f 'FILES'
then
	echo shar: "will not over-write existing file 'FILES'"
else
sed 's/^X//' << \SHAR_EOF > 'FILES'
X  chars   name              description
X
X   3710   flip.1            (**ix) manual for formatting with "nroff -man"
X   1731   makefile.nix      (**ix) make file 
X
X   4455   flip.man          (generic) formatted manual
X   1522   install.doc       (generic) installation instructions
X
X  13273   flip.c            (generic) flip C source
X   7556   flip.h            (generic) flip C source
X   2801   getopt.c          (generic) getopt function C source
X
X    605   makefile.tcc      (ms-dos/turbo c) make file
X     56   flip.prj          (ms-dos/turbo c) project file
X    140   turboc.cfg        (ms-dos/turbo c) configuration file
X  10224   turboc.c          (ms-dos/turbo c) C source
SHAR_EOF
fi
echo shar: "extracting 'flip.1'" '(3710 characters)'
if test -f 'flip.1'
then
	echo shar: "will not over-write existing file 'flip.1'"
else
sed 's/^X//' << \SHAR_EOF > 'flip.1'
X.\" ::[[ @(#) flip.1 1.3 89/07/04 16:30:40 ::]]
X.\"
X.TH FLIP 1 "Jul 4, 1989"
X.AT 3
X.SH NAME
Xflip \- do newline conversions between **IX and MS\-DOS
X.SH SYNOPSIS
X.B flip \-h
X.sp  0
X.B flip 
X\-umvtsbz
X.B file ...
X.SH DESCRIPTION
X.PP
X.I Flip
Xis a file interchange program that converts text file formats
Xbetween **IX and MS\-DOS.  It converts lines ending with carriage\-return
X(CR) and linefeed (LF) to lines ending with just linefeed, or vice versa.
X.PP
X.I Flip
Xhas the following features.
X.TP
Xo
XIf a file contains isolated CR characters for underlining or
Xoverprinting,
X.I flip
Xdoes not change them.
X.TP
Xo
XWhen asked to convert a file to the same format that it
Xalready has,
X.I flip
Xcauses no change to the file.  Thus to
Xconvert all files to **IX format you can type
X.IP "" 10
X.I flip
X.B \-u
X*.*  (under MS\-DOS)
X.sp 0
X.I flip
X.B \-u
X*    (under **IX)
X.IP "" 5
Xand all files will end up right, regardless of whether they
Xwere in MS-DOS or in **IX format to begin with.  This also
Xworks in the opposite direction.
X.TP
Xo
X.I Flip
Xpreserves file timestamps.  You can override this.
X.TP
Xo
X.I Flip
Xis written in C and will compile and run under
XMS-DOS/Turbo C, 4.3BSD, and System V.
X.TP
Xo
X.I Flip
Xaccepts wildcards and multiple filenames on the
Xcommand line.
X.TP
Xo
XIf a user interrupt aborts
X.IR Flip ,
Xit does not leave behind
Xany garbage files or cause corruption of the files being
Xconverted.
X.TP
Xo
X.I Flip
Xwill normally refuse to convert binary files.  You can
Xoverride this.
X.TP
Xo
XWhen converting from MS-DOS to **IX format,
X.I flip
Xremoves any
Xtrailing control Z (the last character in the file), but
Xleaves embedded control Z characters unchanged.  This minimizes
Xthe possibility of accidentally converting a binary file that
Xcontains a control Z near the beginning.  You can override this
Xand ask
X.I flip
Xto recognize the first control Z found as end-of-file.
X.TP
Xo
X.I Flip
Xcan be asked to strip the high (parity) bit as it converts
Xa file.
X.PP
X.I Flip
Xis normally invoked as:
X.IP "" 5
X.I flip
X.B \-umhvtb
Xfile ...
X.IP "" 0
XOne of
X.BR \-u ,
X.BR \-m ,
Xor
X.B \-h
Xis required.  Switches may be given separately or
Xcombined together after a dash.  For example, the three command lines given
Xbelow are equivalent:
X.IP "" 5
X.I flip
X.B \-uvt
X*.c
X.sp 0
X.I flip
X.B "-u -v -t"
X*.c
X.sp 0
X.I flip
X.B "-u -vt"
X*.c
X.PP
XThe meanings of the switches are as follows.
X.TP
X\-u
Xconvert to **IX format (CR LF => LF, lone CR or LF unchanged,
Xtrailing control Z removed, embedded control Z unchanged)
X.TP
X\-m
Xconvert to MS-DOS format (lone LF => CR LF, lone CR unchanged)
X.TP
X\-h
Xgive a help message
X.TP
X\-v
Xbe verbose, print filenames as they are processed
X.TP
X\-t
Xtouch files (don't preserve timestamps)
X.TP
X\-s
Xstrip high bit
X.TP
X\-b
Xconvert binary files too (else binary files are left unchanged)
X.TP
X\-z
Xtruncate file at first control Z encountered
X.PP
XOn systems that allow a program to know its own name,
X.I flip
Xmay be renamed (or
Xlinked) to a file called
X.I toix
X(or
X.I toix.exe
Xunder MS-DOS) for conversion
Xto **IX format, or to a file called
X.I toms
X(or
X.I toms.exe
Xunder MS-DOS) for
Xconversion to MS-DOS format.  When invoked with the name
X.I toix
Xor
X.IR toms,
X.I flip
Xwill act as if it were invoked with the
X.B \-u
Xor
X.B \-m
Xoption respectively.
X.SH COPYRIGHT
XBoth this documentation and
X.I flip
Xare Copyright 1989 Rahul Dhesi, all
Xrights reserved.  Permission is granted to copy, use, and distribute for any
Xcommercial or noncommercial purpose in accordance with the requirements of
Xversion 1.0 of the
X.I GNU General Public license.
X.PP
XNote:  This software has not been endorsed by the Free Software Foundation,
Xthe creator of the GNU license, and I am not affiliated with that
Xorganization.
X.SH AUTHOR
XRahul Dhesi
SHAR_EOF
fi
echo shar: "extracting 'flip.c'" '(13273 characters)'
if test -f 'flip.c'
then
	echo shar: "will not over-write existing file 'flip.c'"
else
sed 's/^X//' << \SHAR_EOF > 'flip.c'
X/* ::[[ @(#) flip.c 1.18 89/07/04 16:07:16 ]]:: */
X#ifndef LINT
Xstatic char sccsid[]="::[[ @(#) flip.c 1.18 89/07/04 16:07:16 ]]::";
X#endif
X
X/*
XCopyright 1989 Rahul Dhesi, All rights reserved.
X
XChecksum: 1217582374 (check or update with "brik")
X*/
X
X/*
XDoes newline conversions between **IX and MS-DOS conventions.  Uses a state
Xmachine, so repeated conversions on the same file will do no harm.
XAssumes the US ASCII character set in some places (search for 'ASCII').
X*/
X
X/* change contents of flip.h as needed */
X#include "flip.h"
X
Xenum choices   { MSTOIX, IXTOMS, NEITHER };           /* conversion choices */
Xenum state     { NONE, SAWCR, SAWLF, SAWCRLF, SAWCTRLZ };
X
Xvoid usage PARMS ((void));
Xvoid give_help PARMS ((void));
Xvoid flip_exit PARMS ((int));
Xint getopt PARMS ((int argc, char **argv, char *options));
Xvoid doarg PARMS ((char *, enum choices));
Xint dofile PARMS ((char *, enum choices));
Xchar *nextfile PARMS ((int, char *, int));
Xint ixtoms PARMS ((FILE *, FILE *));
Xint mstoix PARMS ((FILE *, FILE *));
Xvoid error PARMS ((char *, char *));
Xvoid setup_sigs PARMS ((void));
Xvoid cleanup PARMS ((int));
Xchar *mktemp PARMS ((char *));
X
X#ifdef STDINCLUDE
X# include <stdlib.h>
X# include <string.h>
X#else
Xvoid exit PARMS ((int));
Xchar *strcpy PARMS ((char *, char *));
X#endif
X
X#ifdef NDEBUG
X# define assert(c)
X#else
X# ifdef STDINCLUDE
X#  include <assert.h>
X# else
X#  define assert(c)  if(!(c)) \
X                  fprintf(stderr,"assert error %s:%d\n",__FILE__,__LINE__)
X# endif /* STDINCLUDE */
X#endif /* NDEBUG */
X
X#ifdef USE_TABLE
Xchar *bintab;
X#endif
X
X#ifdef USE_SIG
Xint got_sig;               /* will indicate if signal received */
X#endif
X
Xchar *myname = NULL;
X
Xint exitstat = 0;          /* exit status */
Xint verbose = 0;           /* set by -v option */
Xint touch = 0;             /* set by -t option */
Xint strip = 0;             /* set by -s option */
Xint bintoo = 0;            /* set by -b option */
Xint ztrunc = 0;            /* set by -z option */
X
Xmain (argc, argv)
Xint argc;
Xchar **argv;
X
X{
X   int option;
X   extern int optind;
X   int i;
X   enum choices which = NEITHER;
X#ifdef USE_TABLE
X#define TABSIZ    256
X   char table[TABSIZ];
X#endif
X
X#ifdef PICKNAME
X   register char *p; /* temp pointer for finding our name */
X   register char *arg0 = *argv;
X#endif /* PICKNAME */
X
X   SPEC_INIT            /* optional initialization */
X
X#ifdef USE_SIG
X   setup_sigs();
X#endif
X
X#ifdef PICKNAME
X# define STRCMP(a,op,b)    (strcmp(a,b) op 0)
X   p = arg0 + strlen(arg0);
X
X   if (p != arg0) {     /* if program name is defined */
X      while (p != arg0 && *p != '/' && *p != '\\')
X         p--;
X      assert ((p - arg0) <= strlen (arg0));
X      if (p != arg0)
X         p++;
X
X      /* p now points to trailing name component, or nothing */
X      myname = p;
X      while (*p != '\0' && *p != '.') {   /* ASCII convert to lowercase */
X         if (*p >= 'A' && *p <= 'Z') {
X            *p = (*p - 'A' + 'a');
X         }
X         p++;
X      }
X      if (p != myname && *p == '.')
X         *p = '\0';     /* remove trailing .exe or .com under MS-DOS etc. */
X
X      if (STRCMP(myname,==,"toix"))
X         which = MSTOIX;
X      else if (STRCMP(myname,==,"toms"))
X         which = IXTOMS;
X   } else
X   myname = "flip";
X#else
X   myname = "flip";
X#endif /* PICKNAME */
X
Xargv[0] = myname;                /* for use by getopt */
X
X#ifdef USE_TABLE
X/* table to find out which characters are binary */
X   for (i = 0;  i < TABSIZ;  i++) {
X      if ( (i < 7) || (i > 13 && i < 26) || (i > 126)) /*ASCII binary chars*/
X         table[i] = 1;
X      else
X         table[i] = 0;
X   }
X   bintab = table;
X#endif /* USE_TABLE */
X
X   if (argc < 2) {
X      usage();
X      flip_exit (1);
X   }
X
X   while ((option = getopt (argc, argv, "umhvtsbz")) != EOF) {
X      switch (option) {
X       case 'u': which = MSTOIX;  break;
X       case 'm': which = IXTOMS; break;
X       case 'h': give_help(); flip_exit (0);
X       case 'v': verbose = 1;  break;
X       case 't': touch = 1;  break;
X       case 's': strip = 1;  break;
X       case 'b': bintoo = 1;  break;
X       case 'z': ztrunc = 1;  break;
X       default:  usage(); flip_exit (1);
X      }
X   }
X
X   switch (which) {
X    case MSTOIX:
X      /* printf ("converting to **ix format\n"); */
X      break;
X    case IXTOMS:
X      /* printf ("converting to msdos format\n"); */
X      break;
X    default:
X      fprintf (stderr, "%s: error: -u or -m is required\n", myname);
X      flip_exit (1);
X      break;
X   }
X
X   if (argc <= optind) {
X      fprintf (stderr, "%s: error: filenames are needed\n", myname);
X      flip_exit (1);
X   }
X
X   for (i = optind;  i < argc;  i++)
X      doarg (argv[i], which);
X
X   return (exitstat);
X}
X
X
X/*
XDoes conversion for one argument, calling dofile with wildcards
Xexpanded.  Updates exitstat in case of error.
X*/
X
Xvoid doarg (arg, which)
Xchar *arg;
Xenum choices which;
X{
X#ifdef WILDCARD
X   char *this_file;
X
X   nextfile (0, arg, 0);
X   while ((this_file = nextfile(1, (char *) NULL, 0)) != NULL) {
X      exitstat |= dofile (this_file, which);
X   }
X#else
X   exitstat |= dofile (arg, which);
X#endif /* WILDCARD */
X}
X
X#ifdef USE_SIG
X# include <signal.h>
X#endif
X
XFILE *outfile;       /* make it visible to both dofile and cleanup */
X
X/*
XHere we have filename and an option.  We call a different routine
Xfor each type of conversion.  This way more types of conversions
Xcan be easily added in the future.
X*/
X
Xint dofile (fname, which)
Xchar *fname;
Xenum choices which;
X{
X   FILE *infile;
X   char tfname[PATHSIZE];
X   SGFTIME timestamp;  /* save file timestamp here, restore later */
X   int errstat = 0;
X   char *p;             /* temp file ptr */
X
X#ifdef USE_SIG
X   if (got_sig)
X      flip_exit (INT_EXIT);
X#endif
X
X   /* if writable, open for reading */
X   if ((infile = fopen (fname, R_PL_B)) != NULL) {
X      fclose (infile);
X      infile = fopen (fname, RB);
X   }
X
X   if (infile == NULL) {
X      error (fname, ": can't open");
X      return (1);
X   }
X
X   /*
X   to make temp file in same dir as original, we make p point to the filename
X   component of fname, put '\0' there, and strcat the temp name to it
X   */
X   strcpy (tfname, fname);
X   p = tfname + strlen(tfname);
X
X   while (p != tfname && *p != '/' && *p != '\\')
X      p--;
X   if (p != tfname)
X      p++;
X   *p = '\0';
X
X#define  TEMPLATE    "XXXXXX"
X   {
X      char template[7];
X      strcpy (template, TEMPLATE);
X      strcat (tfname, mktemp (template));
X   }
X
X   outfile = fopen (tfname, WB);
X
X   if (outfile == NULL) {
X      fclose (infile);
X      error (fname, ": skipped, could not open temporary file");
X      return (1);
X   }
X
X   if (!touch)
X      GETFT (infile, fname, timestamp);      /* save current timestamp */
X
X   assert (which == IXTOMS || which == MSTOIX);
X
X#ifdef BIGBUF
X   setvbuf (infile,  (char *) NULL, _IOFBF, BIGBUF);
X   setvbuf (outfile, (char *) NULL, _IOFBF, BIGBUF);
X#endif /* BIGBUF */
X
X   switch (which) {
X    case IXTOMS:
X      errstat = ixtoms (infile, outfile);
X      break;
X    case MSTOIX:
X      errstat = mstoix (infile, outfile);
X      break;
X   }
X
X   fclose (infile);
X
X   switch (errstat) {
X    case ERRBINF:
X      fclose (outfile);
X      DELFILE (tfname);
X      fprintf (stderr, "%s: binary file, not converted\n", fname);
X      return (1);
X      /* break; */  /* unreachable code */
X#ifdef USE_SIG
X    case ERRSIG:
X      fclose (outfile);
X      DELFILE (tfname);
X      flip_exit (INT_EXIT);
X      break;
X#endif
X    default:
X      ;
X   }
X
X   assert (errstat == 0);
X
X   if (!ferror(outfile) && fflush(outfile) != EOF && fclose(outfile) != EOF) {
X      int moved;
X      DELFILE (fname);
X      moved = MVFILE (tfname, fname);
X      if (moved == 0) {
X         FILE *fptr;
X         if (!touch && (fptr = fopen (fname, RB)) != NULL) {
X            SETFT (fptr, fname, timestamp);
X            fclose (fptr);
X         }
X         if (verbose) {
X            printf ("%s\n", fname);
X            fflush (stdout);
X         }
X         return (0);
X      } else {
X         error (fname, ": not converted, could not rename temp file");
X         DELFILE (tfname);
X         return (1);
X      }
X   } else {
X      fclose (outfile); /* outfile was not closed, so close it here */
X      return (1);
X   }
X}
X
X/* convert from ms-dos to **ix format */
Xint mstoix (infile, outfile)
XFILE *infile;           /* input file   */
XFILE *outfile;          /* output file  */
X{
X   int c;
X   enum state state = NONE;
X
X   /* lone LF => unchanged, lone CR => unchanged,
X      CR LF => LF, ^Z at end means EOF; ^Z elsewhere => unchanged */
X
X   while (1) {       /* break out on EOF only */
X      while ((c = getc (infile)) != EOF) {
X#ifdef USE_SIG
X         if (got_sig)
X            return (ERRSIG);
X#endif
X         if (!bintoo && BINCHAR(c))
X            return (ERRBINF);
X         if (strip)
X            STRIP(c);
X         switch (c) {
X          case LF:
X            CHECK_BREAK
X            putc (c, outfile); if (state == SAWCR) state = NONE; break;
X          case CR:
X            state = SAWCR; break;
X          case CTRLZ:
X            if (state == SAWCR) putc (CR, outfile);
X            state = SAWCTRLZ; goto saweof;
X          default:
X            if (state == SAWCR) { state = NONE; putc (CR, outfile); }
X            putc (c, outfile);
X            break;
X         }
X      }
X saweof:
X      /* exit outer loop only on EOF or ^Z as last char */
X      if (
X          ztrunc && state == SAWCTRLZ
X          || (c = getc (infile)) == EOF
X         )
X         break;
X      else
X         ungetc (c, infile);
X      if (state == SAWCTRLZ)
X         putc (CTRLZ, outfile);
X   }
X   return (0);
X}
X
X/* convert from **ix to ms-dos format */
Xint ixtoms (infile, outfile)
XFILE *infile;           /* input file   */
XFILE *outfile;          /* output file  */
X{
X   int c;
X   enum state state = NONE;
X
X   /* LF => CR LF, but leave CR LF alone */
X   while ((c = getc (infile)) != EOF) {
X#ifdef USE_SIG
X      if (got_sig)
X         return (ERRSIG);
X#endif
X      if (!bintoo && BINCHAR(c))
X         return (ERRBINF);
X      if (strip)
X         STRIP(c);
X      switch (c) {
X       case LF:
X         CHECK_BREAK
X         if (state == SAWCR)
X            state = NONE;
X         else
X            putc (CR, outfile);
X         putc (LF, outfile);
X         break;
X       case CR:
X         state = SAWCR; putc (c, outfile); break;
X       case CTRLZ:
X         if (ztrunc)
X            return (0);
X         /* FALL THROUGH */
X       default:
X         state = NONE; putc (c, outfile); break;
X      }
X   }
X   return (0);
X}
X
X/* set up signal handler for selected signals */
X#ifdef USE_SIG
Xvoid setup_sigs ()
X{
X# ifdef SIGPIPE
X   if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
X      signal (SIGPIPE, cleanup);
X# endif
X# ifdef SIGHUP
X   if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
X      signal (SIGHUP, cleanup);
X# endif
X# ifdef SIGQUIT
X   if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
X      signal (SIGQUIT, cleanup);
X# endif
X# ifdef SIGINT
X   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
X      signal (SIGINT, cleanup);
X# endif
X# ifdef SIGTERM
X   if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
X      signal (SIGTERM, cleanup);
X# endif
X}
X
X/* set flag on signal */
Xvoid cleanup(sig)
Xint sig;
X{
X   signal (sig, SIG_IGN);     /* needed for flaky System V Release 2 */
X   got_sig = 1;
X   signal (sig, cleanup);     /* ditto */
X}
X#endif /* USE_SIG */
X
X#define  ERRSIZE     200
X
X/* prints error message via perror */
Xvoid error (msg1, msg2)
Xchar *msg1, *msg2;
X{
X   char buf[ERRSIZE];
X   strcpy (buf, myname);
X   strcat (buf, ": ");
X   strcat (buf, msg1);
X   strcat (buf, msg2);
X   perror (buf);
X   fflush (stderr);
X}
X
X/* gives brief usage message */
Xvoid usage()
X{
X   fprintf (stderr,
X"usage:  %s [-u | -m] [other options] file ...  (or \"%s -h\" for more help)\n",
X myname, myname);
X}
X
X/* gives help screen */
X
Xvoid give_help()
X{
Xprintf ("\
XFile interchange program flip version 1.00.  Copyright 1989 Rahul Dhesi,\n\
XAll rights reserved.  Both noncommercial and commercial copying, use, and\n\
Xcreation of derivative works are permitted in accordance with the\n\
Xrequirements of the GNU license.  This program does newline conversions.\n");
X
Xprintf ("\n\
X   Usage:     flip -umhvtsbz file ...\n\
X\n\
XOne of -u, -m, or -h is required;  others are optional.  See user manual.\n");
X
Xprintf ("\n\
X   -u     convert to **IX format (CR LF => LF, lone CR or LF unchanged,\n\
X          trailing control Z removed, embedded control Z unchanged)\n\
X   -m     convert to MS-DOS format (lone LF => CR LF, lone CR unchanged)\n\
X   -h     give this help message\n\
X   -v     be verbose, print filenames as they are processed\n\
X   -t     touch files (don't preserve timestamps)\n\
X   -s     strip high bit\n\
X   -b     convert binary files too (else binary files are left unchanged)\n\
X   -z     truncate file at first control Z encountered\n\
X");
X#ifdef PICKNAME
Xprintf ("\n\
XMay be invoked as \"toix\" (same as \"flip -u\") or \"toms\" (same as \"flip -m\").\n\
X");
X#endif
Xreturn;
X}
X
X/* normal exits go through here -- atexit would be nice but not portable */
Xvoid flip_exit(stat)
Xint stat;
X{
X   SPEC_EXIT
X   exit (stat);
X}
X
X/*
Xspecial code for **IX -- not in use because can't properly handle
XSIGINT while /bin/mv is executing
X*/
X
X#ifdef NIX
X# ifndef MVFILE
Xint MVFILE (src, dest)
Xchar *dest;
Xchar *src;
X{
X   char cmd[2 * PATHSIZE];
X   sprintf (cmd, "/bin/mv %s %s", src, dest);
X   return (system(cmd));
X}
X# endif /* MVFILE */
X#endif /* NIX */
SHAR_EOF
fi
echo shar: "extracting 'flip.h'" '(7556 characters)'
if test -f 'flip.h'
then
	echo shar: "will not over-write existing file 'flip.h'"
else
sed 's/^X//' << \SHAR_EOF > 'flip.h'
X/* ::[[ @(#) flip.h 1.16 89/07/04 17:00:46 ]]:: */
X
X/*
XCopyright 1989 Rahul Dhesi, All rights reserved.
X
XChecksum: 2652839101 (check or update with "brik")
X
XANSI-compatibility strategy:
X
X1.   If ANSIPROTO is defined, function prototypes are used, ANSI-style.
X     If it is not defined, regular function declarations (without a
X     parameter list) are used.  This is achieved with the use of
X     the PARMS macro.
X2.   If STDINCLUDE is defined, ANSI-conformant header files are
X     included.  Otherwise functions that would be declared in such
X     header files are declared individually.
X*/
X
X#ifndef OK_NL
X
X/* Define ANSIPROTO and/or STDINCLUDE here if needed */
X#ifdef TURBOC
X# define    ANSIPROTO
X# define    STDINCLUDE
X#endif /* TURBOC */
X
X
X
X#include <stdio.h>
X
X#ifndef PARMS
X# ifdef ANSIPROTO
X#  define   PARMS(x)    x
X# else
X#  define   PARMS(x)    ()
X# endif
X#endif
X
X/************************************************************/
X/*** change following definitions as needed for your system */
X/************************************************************/
X/*
XBIGBUF      If defined, setvbuf() will be used to set input and
X            output buffers to BIGBUF characters
XBINCHAR     This must be a macro accepting a single character
X            argument and returning nonzero if and only if that
X            character is a binary character.  By default, BINCHAR
X            is defined to look up a table, and the table is compiled
X            in by defining USE_TABLE.
XCHECK_BREAK If your operating system requires programs to check
X            for user interrupts at intervals, define CHECK_BREAK to
X            be a function or macro that checks for a user interrupt.
X            Flip will call this at intervals.  If not needed,
X            define CHECK_BREAK to be null.
XDELFILE     Must be a function or macro that will accept one filenames
X            and delete that file, returning zero on success, nonzero
X            on failure.
XGETFT       Must be a macro with usage GETFT(file,name,var) that will
X            take an open file, a filename, and a variable name, and
X            put in that variable the timestamp of the file.
XINT_EXIT    If USE_SIG is defined, INT_EXIT must be defined to
X            be the exit code returned by flip when its execution
X            is aborted by a user interrupt.
XMVFILE      Must be a function or macro that will take two filenames
X            and rename the first file to the second file, returning
X            zero on success, nonzero on failure.
XNIX         If this symbol is defined, some things common to most
X            implementations of **IX get defined and need not be
X            individually defined.
XPATHSIZE    size of buffer(s) to use to hold pathname(s)
XPICKNAME    Do "#define PICKNAME" if you want the program to know its
X            name and respond to it.  If PICKNAME is not defined, the
X            program will assume that it is called "flip".
XSETFT       Must be a function or macro with usage SETFT(file,name,var)
X            that will take an open file, a filename, and a variable
X            name, and set the timestamp of the file from the variable.
XSIG_T       If USE_SIG is defined, then SIG_T must be defined
X            (or typedef'd) to be the data type returned by
X            (*signal).  Usually int or void.
XSPEC_EXIT   Like SPEC_INIT, but is called just before flip exits.
XSPEC_INIT   This is invoked to initialize flip.  Should be defined to
X            be either a function call (with trailing semicolon) or
X            null string.
XSGFTIME     This must be a typedef for a data type suitable to store
X            file times.
XUSE_TABLE   If this is defined, flip code will use a table look-up
X            to decide which characters should be considered binary.
X            See also BINCHAR.
XULTRIX_BUG  At least one version of Ultrix chokes on a trailing "b"
X            in the mode string for fopen().  If ULTRIX_BUG is defined
X            no trailing "b" will be used.
XUSE_SIG     If this is defined, then signal() will be used so flip
X            may trap user interrupts and delete temporary files.
X            If USE_SIG is defined, then SIG_T and INT_EXIT must also
X            be defined (below).
XWILDCARD    If this is defined, the function nextfile() will be called
X            to expand wildcards.  If WILDCARD is not defined, no
X            wildcard expansion will be done and nextfile() is not
X            needed.  For a description of nextfile() see turboc.c.
X*/
X
X#ifdef TURBOC
X# define PATHSIZE    200
X# define PICKNAME
X# define BIGBUF      16384
X# define DELFILE     remove
Xextern int MVFILE PARMS ((char *src, char *dest));            /* Turbo C */
X# define USE_SIG
X# define SIG_T void     /* return type from (*signal) */
X# define INT_EXIT 127   /* status when a signal causes exit */
X# define CHECK_BREAK  brktst();
Xvoid brktst PARMS ((void));
X# define SPEC_INIT   spec_init();
X# define SPEC_EXIT   spec_exit();
Xvoid spec_init PARMS ((void));
Xvoid spec_exit PARMS ((void));
X# define WILDCARD
X
X/* date and time */
X# include <io.h>
X  typedef struct ftime        SGFTIME;
X# define GETFT(f,name,var)    getftime(fileno(f), &var)
X# define SETFT(f,name,var)    setftime(fileno(f), &var)
X#endif /* TURBOC */
X
X#ifdef SYS_V
X# define NIX         /* see below */
X# define PATHSIZE    200
X# define BIGBUF      16384
X# define  MVFILE(src,dest)    (!(!link(src,dest)&&!unlink(src)))
X# define SIG_T int
X#endif /* SYS_V */
X
X#ifdef BSD
X# define NIX         /* see below */
X# define PATHSIZE    1027
X# undef  BIGBUF
X# define  MVFILE     rename
X# define SIG_T int
X#endif /* BSD */
X
X#ifdef VMS
X# define PATHSIZE    1024
X# define PICKNAME
X# define BIGBUF      16384
X# define DELFILE     delete
X# define  MVFILE     rename
X# define USE_SIG
X# define SIG_T int
X# define INT_EXIT    127
X# define SPEC_INIT
X# define SPEC_EXIT
X#endif /* VMS */
X
X/************************************************************/
X/*** remaining definitions should not need to be changed ****/
X/************************************************************/
X
X/* define ASCII character values for linefeed, carriage return, control Z */
X#define  LF    10
X#define  CR    13
X#define  CTRLZ 26
X
X/* error codes */
X#define  ERRBINF  1  /* binary file */
X#define  ERRSIG   2  /* interrupted by signal */
X
X/* how to strip high bit */
X#define  STRIP(c)    c &= 0x7f
X
X/**** BINCHAR(c) returns nonzero if c is a binary char ****/
X#ifndef BINCHAR
X# define USE_TABLE      /* use internal table -- see flip.c */
X# define BINCHAR(c)  bintab[c]
X#endif
X
X/**** mode strings for fopen() -- to work around Ultrix problem ****/
X/**** (Thanks to Taso N. Devetzis for reporting this)           ****/
X#ifdef ULTRIX_BUG
X# define WB          "w"
X# define RB          "r"
X# define R_PL_B      "r+"
X#else
X# define WB          "wb"     /* write binary */
X# define RB          "rb"     /* read binary */
X# define R_PL_B      "r+b"    /* read + update binary */
X#endif /* ULTRIX_BUG */
X
X/* things common to most **IX systems */
X#ifdef NIX
X# define SPEC_INIT
X# define SPEC_EXIT
X# define CHECK_BREAK
X# define PICKNAME
X# define DELFILE     unlink
X# define USE_SIG
X# define INT_EXIT    127
X# include <sys/types.h>          /* for file time */
X# include <sys/stat.h>           /* for file time */
X  typedef struct stat            SGFTIME;
X# define GETFT(file,name,var)    fstat(fileno(file),&var)
X# define SETFT(file,name,var)    do { time_t x[2]; x[0] = var.st_atime; \
X                                      x[1] = var.st_mtime; utime (name, x); \
X                                  } while (0)
X#endif /* NIX */
X
X#endif /* OK_NL */
SHAR_EOF
fi
echo shar: "extracting 'flip.man'" '(4455 characters)'
if test -f 'flip.man'
then
	echo shar: "will not over-write existing file 'flip.man'"
else
sed 's/^X//' << \SHAR_EOF > 'flip.man'
X
X     FLIP(1)                  REFERENCE MANUAL              FLIP(1)
X
X
X     NAME
X          flip - do newline conversions between **IX and MS-DOS
X
X     SYNOPSIS
X          flip -h
X          flip -umvtsbz file ...
X
X     DESCRIPTION
X          Flip is a file interchange program that converts text file
X          formats between **IX and MS-DOS.  It converts lines ending
X          with carriage-return (CR) and linefeed (LF) to lines ending
X          with just linefeed, or vice versa.
X
X          Flip has the following features.
X
X          o    If a file contains isolated CR characters for
X               underlining or overprinting, flip does not change them.
X
X          o    When asked to convert a file to the same format that it
X               already has, flip causes no change to the file.  Thus
X               to convert all files to **IX format you can type
X
X                    flip -u *.*  (under MS-DOS)
X                    flip -u *    (under **IX)
X
X               and all files will end up right, regardless of whether
X               they were in MS-DOS or in **IX format to begin with.
X               This also works in the opposite direction.
X
X          o    Flip preserves file timestamps.  You can override this.
X
X          o    Flip is written in C and will compile and run under
X               MS-DOS/Turbo C, 4.3BSD, and System V.
X
X          o    Flip accepts wildcards and multiple filenames on the
X               command line.
X
X          o    If a user interrupt aborts Flip, it does not leave
X               behind any garbage files or cause corruption of the
X               files being converted.
X
X          o    Flip will normally refuse to convert binary files.  You
X               can override this.
X
X          o    When converting from MS-DOS to **IX format, flip
X               removes any trailing control Z (the last character in
X               the file), but leaves embedded control Z characters
X               unchanged.  This minimizes the possibility of
X               accidentally converting a binary file that contains a
X               control Z near the beginning.  You can override this
X               and ask flip to recognize the first control Z found as
X               end-of-file.
X
X          o    Flip can be asked to strip the high (parity) bit as it
X               converts a file.
X
X          Flip is normally invoked as:
X
X               flip -umhvtb file ...
X
X          One of -u, -m, or -h is required.  Switches may be given
X          separately or combined together after a dash.  For example,
X          the three command lines given below are equivalent:
X
X               flip -uvt *.c
X               flip -u -v -t *.c
X               flip -u -vt *.c
X
X          The meanings of the switches are as follows.
X
X          -u   convert to **IX format (CR LF => LF, lone CR or LF
X               unchanged, trailing control Z removed, embedded control
X               Z unchanged)
X
X          -m   convert to MS-DOS format (lone LF => CR LF, lone CR
X               unchanged)
X
X          -h   give a help message
X
X          -v   be verbose, print filenames as they are processed
X
X          -t   touch files (don't preserve timestamps)
X
X          -s   strip high bit
X
X          -b   convert binary files too (else binary files are left
X               unchanged)
X
X          -z   truncate file at first control Z encountered
X
X          On systems that allow a program to know its own name, flip
X          may be renamed (or linked) to a file called toix (or
X          toix.exe under MS-DOS) for conversion to **IX format, or to
X          a file called toms (or toms.exe under MS-DOS) for conversion
X          to MS-DOS format.  When invoked with the name toix or toms,
X          flip will act as if it were invoked with the -u or -m option
X          respectively.
X
X     COPYRIGHT
X          Both this documentation and flip are Copyright 1989 Rahul
X          Dhesi, all rights reserved.  Permission is granted to copy,
X          use, and distribute for any commercial or noncommercial
X          purpose in accordance with the requirements of version 1.0
X          of the GNU General Public license.
X
X          Note:  This software has not been endorsed by the Free
X          Software Foundation, the creator of the GNU license, and I
X          am not affiliated with that organization.
X
X     AUTHOR
X          Rahul Dhesi
X
X     DATE
X          This manual was formatted 1989/04/07.  It is for version
X          1.00 of flip.
SHAR_EOF
fi
echo shar: "extracting 'flip.prj'" '(56 characters)'
if test -f 'flip.prj'
then
	echo shar: "will not over-write existing file 'flip.prj'"
else
sed 's/^X//' << \SHAR_EOF > 'flip.prj'
Xflip.c			(flip.h)
Xgetopt.c		(flip.h)
Xturboc.c		(flip.h)
SHAR_EOF
fi
echo shar: "extracting 'getopt.c'" '(2801 characters)'
if test -f 'getopt.c'
then
	echo shar: "will not over-write existing file 'getopt.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getopt.c'
X/* ::[[ @(#) getopt.c 1.5 89/07/02 00:18:19 ]]:: */
X#ifndef LINT
Xstatic char sccsid[]="::[[ @(#) getopt.c 1.5 89/07/02 00:18:19 ]]::";
X#endif
X
X/*
XChecksum:  505161377      (check or update this with "brik")
X*/
X
X/*
X * Here's something you've all been waiting for:  the AT&T public domain
X * source for getopt(3).  It is the code which was given out at the 1985
X * UNIFORUM conference in Dallas.  I obtained it by electronic mail
X * directly from AT&T.  The people there assure me that it is indeed
X * in the public domain.
X *
X * There is no manual page.  That is because the one they gave out at
X * UNIFORUM was slightly different from the current System V Release 2
X * manual page.  The difference apparently involved a note about the
X * famous rules 5 and 6, recommending using white space between an option
X * and its first argument, and not grouping options that have arguments.
X * Getopt itself is currently lenient about both of these things White
X * space is allowed, but not mandatory, and the last option in a group can
X * have an argument.  That particular version of the man page evidently
X * has no official existence, and my source at AT&T did not send a copy.
X * The current SVR2 man page reflects the actual behavor of this getopt.
X * However, I am not about to post a copy of anything licensed by AT&T.
X */
X
X/*
XMinor modifications by Rahul Dhesi 1989/03/06
X*/
X
X#include "flip.h"
X
X#ifdef STDINCLUDE
X# include <string.h>
X#else
Xextern int strcmp PARMS ((char *, char *));
Xextern char *strchr PARMS ((char *, char));
X#endif
X
X/* Avoid possible compiler warning if we simply redefine NULL or EOF */
X#define XNULL   0
X#define XEOF (-1)
X
X#define ERR(szz,czz) if(opterr){fprintf(stderr,"%s%s%c\n",argv[0],szz,czz);}
X
Xint   opterr = 1;
Xint   optind = 1;
Xint   optopt;
Xchar  *optarg;
X
Xint
Xgetopt(argc, argv, opts)
Xint   argc;
Xchar  **argv, *opts;
X{
X   static int sp = 1;
X   register int c;
X   register char *cp;
X
X   if(sp == 1)
X      if(optind >= argc ||
X         argv[optind][0] != '-' || argv[optind][1] == '\0')
X         return(XEOF);
X      else if(strcmp(argv[optind], "--") == XNULL) {
X         optind++;
X         return(XEOF);
X      }
X   optopt = c = argv[optind][sp];
X   if(c == ':' || (cp=strchr(opts, c)) == XNULL) {
X      ERR(": illegal option -- ", c);
X      if(argv[optind][++sp] == '\0') {
X         optind++;
X         sp = 1;
X      }
X      return('?');
X   }
X   if(*++cp == ':') {
X      if(argv[optind][sp+1] != '\0')
X         optarg = &argv[optind++][sp+1];
X      else if(++optind >= argc) {
X         ERR(": option requires an argument -- ", c);
X         sp = 1;
X         return('?');
X      } else
X         optarg = argv[optind++];
X      sp = 1;
X   } else {
X      if(argv[optind][++sp] == '\0') {
X         sp = 1;
X         optind++;
X      }
X      optarg = XNULL;
X   }
X   return(c);
X}
SHAR_EOF
fi
echo shar: "extracting 'install.doc'" '(1522 characters)'
if test -f 'install.doc'
then
	echo shar: "will not over-write existing file 'install.doc'"
else
sed 's/^X//' << \SHAR_EOF > 'install.doc'
X
X                             Installing Flip 1.00
X
XInstallation instructions are provided for System V Release 2, 4.3BSD,
XUltrix, Microport System V/AT, and MS-DOS/Turbo C.  To install under other
Xsimilar environments look carefully in flip.h and make changes as needed.
X
X
XMS-DOS/TURBO C
X
XThe files supplied are suitable for compilation with Borland's Turbo C 2.0
Xfor MS-DOS.
X
XA makefile "makefile.tcc" is supplied.  Use the command line compiler
X"tcc.exe".  You will need a good make program, such as NDMAKE.  Edit
X"turboc.cfg" so it correctly reflects the include directories on your
Xsystem.  Then type "make -f makefile.tcc".
X
XYou can also use the intergrated environment "tc.exe".  Convert "turboc.cfg"
Xto "tcconfig.tc" using Borland's "tcconfig.exe" program.  Invoke tc.exe and
Xload the configuration file "tcconfig.tc".  A project file "flip.prj" is
Xsupplied.  Compile as usual.
X
X
XSYSTEM V RELEASE 2, 4.3BSD, OR MICROPORT SYSTEM V/AT
X
XRename the provided file "makefile.nix" to "makefile".
X
XDepending on the system, type:
X
X     make sys_v                 for System V Release 2
X     make bsd                   for 4.3BSD
X     make uport                 for Microport System V/AT (large model)
X     make ultrix                for Ultrix, includes bug fix, not tested
X
XIt may work to do "make sys_v" for Microport System V/AT, but I'm not sure,
Xas I haven't yet restored my small model libraries which vanished from my
Xdisk one day without warning.
X
XUnder any flavor of **IX you can link "flip" to "toix" and "toms".
SHAR_EOF
fi
echo shar: "extracting 'makefile.nix'" '(1731 characters)'
if test -f 'makefile.nix'
then
	echo shar: "will not over-write existing file 'makefile.nix'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile.nix'
X# Makefile for flip for **IX.  ::[[ @(#) makefile.nix 1.4 89/07/04 12:00:02 ]]::
X
X# The contents of this makefile are hereby released to the public domain.
X#                               -- Rahul Dhesi 1989/06/19
X
X# Before use make sure this file is called "makefile".  (Rename it if
X# necessary.)  Then invoke as follows:
X
X#   "make sys_v"        makes executable flip for System V Release 2
X#   "make bsd"          makes executable flip for 4.3BSD
X#   "make install"      moves flip into BINDIR, copies flip.1 into MANDIR
X#   "make clean"        deletes object and executable files
X
X# Where to install executable and manual files on "make install".  The trailing
X# "/." forces an error message if the destination directory doesn't exist.
XBINDIR = /usr/local/bin/.
XMANDIR = /usr/man/man1/.
X
X# CC is compiler, LD is loader (may be same as compiler), CFLAGS are flags
X# for compiler, LDFLAGS are flags for loader, CFMORE are additional
X# (relatively unchanging) flags for compiler
X
XCC = cc
XCFLAGS =
XCFMORE = -c -DNDEBUG -O
XLD = cc
XLDFLAGS = -o flip
X
X# If your system does not supply getopt as a library function,
X# add getopt.o to the RHS list on the next line and uncomment the
X# two nonblank lines after that.
XOBJS = flip.o
X
X#getopt.o: getopt.c flip.h
X#	$(CC) $(CFLAGS) $(CFMORE) $*.c
X
Xnothing:
X	@echo \
X	'Please type "make sys_v", "make bsd", "make uport", or "make ultrix"'
X
Xsys_v:
X	make "CFLAGS=-DSYS_V" flip
X
Xuport:
X	make "CFLAGS=-DSYS_V -Ml" "LDFLAGS=-Ml -o flip" flip
X
Xbsd:
X	make "CFLAGS=-DBSD" flip
X
Xultrix:
X	make "CFLAGS=-DBSD -DULTRIX_BUG" flip
X
Xflip: $(OBJS)
X	$(LD) $(LDFLAGS) $(OBJS)
X
Xflip.o: flip.c flip.h
X	$(CC) $(CFLAGS) $(CFMORE) $*.c
X
Xclean:
X	rm -f *.o core flip
X
Xinstall:
X	mv flip $(BINDIR)
X	cp flip.1 $(MANDIR)
SHAR_EOF
fi
echo shar: "extracting 'makefile.tcc'" '(605 characters)'
if test -f 'makefile.tcc'
then
	echo shar: "will not over-write existing file 'makefile.tcc'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile.tcc'
X# ::[[ @(#) makefile.tcc 1.1 89/07/02 00:19:54 ]]::
X# Makefile for flip for MS-DOS and Turbo C 2.0.  The supplied turboc.cfg
X# configuration file must be in the current directory;  edit it to make
X# sure the include directories are correct.
X
XCC = tcc
XCFLAGS = -c -DTURBOC -DLINT -DNDEBUG
XCFMORE =
XLD = tcc
XLDFLAGS = -eFLIP
XLDMORE =
X
XOBJS = flip.obj getopt.obj turboc.obj
X
Xflip.exe: $(OBJS)
X	$(LD) $(LDFLAGS) $(LDMORE) $(OBJS)
X
Xflip.obj: flip.c flip.h
X	$(CC) $(CFLAGS) $(CFMORE) $*.c
X
Xgetopt.obj: getopt.c flip.h
X	$(CC) $(CFLAGS) $(CFMORE) $*.c
X
Xturboc.obj: turboc.c flip.h
X	$(CC) $(CFLAGS) $(CFMORE) $*.c
SHAR_EOF
fi
echo shar: "extracting 'turboc.c'" '(10224 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/* ::[[ @(#) turboc.c 1.6 89/07/02 00:19:31 ]]:: */
X#ifndef LINT
Xstatic char sccsid[]="::[[ @(#) turboc.c 1.6 89/07/02 00:19:31 ]]::";
X#endif
X
X/*
XCopyright 1989 Rahul Dhesi, All rights reserved.
X
XThis file is used only for MS-DOS & Turbo C.
X*/
X
X/*
XChecksum: 3933529970      (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
Xextern unsigned _stklen = 10000;
X
X#include "assert.h"
X#include "flip.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
X/*
XFor Turbo C, we implement MVFILE as a file copy to avoid wildcard
Xexpansion finding the same file again after a direct rename.  To
Xavoid leaving a partially-written destination file, we trap ^C,
Xand if it occurs, delete the dest file and quickly do just a simple
Xrename to it.
X*/
X
X#define BLOCKSIZ  16384
X#include <fcntl.h>
X#include <sys/stat.h>
X#include <io.h>
X#include <signal.h>
X
Xvoid handler (int);        /* ^C handler */
Xchar  *xsrc, *xdest;       /* global for handler() */
Xvoid (*oldsignal) (int);   /* global for handler() */
Xint infd, outfd;           /* global for handler() */
Xint brk_flag;              /* ms-dos break flag status */
Xint getcbrk (void);
Xint setcbrk (int);
X
Xint MVFILE (src, dest)
Xchar *src;
Xchar *dest;
X{
X   int retval;
X   char buf[BLOCKSIZ];
X
X   retval = -1;               /* default error return */
X   xsrc = src;  xdest = dest; /* make visible to handler */
X
X   oldsignal = signal (SIGINT, handler);
X   outfd = open (dest, O_CREAT|O_TRUNC|O_BINARY, S_IREAD|S_IWRITE);
X   if (outfd == -1)
X      goto erret;
X   infd = open (src, O_RDONLY|O_BINARY);
X   if (infd == -1) {
X      close (outfd);
X      goto erret;
X   }
X   while ((retval = read (infd, buf, BLOCKSIZ)) > 0) {
X      if (write (outfd, buf, retval) != retval) {
X         retval = -1;
X         goto done;
X      }
X   }
X done: /* retval is zero on normal exit from loop, else nonzero */
X   close (infd); close (outfd);
X
X   if (retval == 0) {
X      signal (SIGINT, oldsignal);      /* avoid race condition */
X      unlink (src);
X      return (retval);
X   }
Xerret:
X   /* if error during read/write, do rename to avoid loss of dest file */
X   unlink (dest);
X   retval = rename (src, dest);
X   signal (SIGINT, oldsignal);
X   return (retval);
X}
X
Xvoid handler (int sig)
X{
X   signal (sig, SIG_IGN);
X   close (infd);  close (outfd);
X   unlink (xdest);
X   rename (xsrc, xdest);
X   signal (sig, oldsignal);
X   raise  (sig);                 /* original handler gets signal now */
X}
X
X#include <conio.h>
Xvoid brktst() { kbhit(); }      /* test for user interrupt */
X
Xvoid spec_init()
X{
X   brk_flag = getcbrk();
X   setcbrk (0);
X}
X
Xvoid spec_exit()
X{
X   setcbrk (brk_flag);
X}
SHAR_EOF
fi
echo shar: "extracting 'turboc.cfg'" '(140 characters)'
if test -f 'turboc.cfg'
then
	echo shar: "will not over-write existing file 'turboc.cfg'"
else
sed 's/^X//' << \SHAR_EOF > 'turboc.cfg'
X-wamp
X-wcln
X-wuse
X-wrvl
X-wsig
X-wamb
X-wstv
X-wpro
X-wnod
X-wucp
X-A
X-O
X-Z
X-k-
X-d
X-I\turboc\include
X-L\turboc\lib
X-eFLIP
X-DTURBOC
X-DLINT
X-DNDEBUG
SHAR_EOF
fi
exit 0
#	End of shell archive