v07i052: 2.11 News Source, Part02/09
sources-request at mirror.UUCP
sources-request at mirror.UUCP
Fri Nov 7 02:51:39 AEST 1986
Submitted by: seismo!rick (Rick Adams)
Mod.sources: Volume 7, Issue 52
Archive-name: 2.11news/Part12
# To extract, sh this file
#
# news 2.11 source part 2 of 9
#
if test ! -d src
then
mkdir src
fi
echo x - src/compress.c 1>&2
sed 's/.//' >src/compress.c <<'*-*-END-of-src/compress.c-*-*'
-#ifdef SCCSID
-static char *SccsId = "@(#)compress.c 1.12 10/29/86";
-#endif SCCSID
-static char rcs_ident[] = "Based on compress.c,v 4.0 85/07/30 12:50:00 joe Release";
-
-/*
- * Compress - data compression program
- */
-#define min(a,b) ((a>b) ? b : a)
-
-/*
- * machine variants which require cc -Dmachine: pdp11, z8000, pcxt
- */
-
-/*
- * Set USERMEM to the maximum amount of physical user memory available
- * in bytes. USERMEM is used to determine the maximum BITS that can be used
- * for compression.
- *
- * SACREDMEM is the amount of physical memory saved for others; compress
- * will hog the rest.
- */
-#ifndef SACREDMEM
-#define SACREDMEM 0
-#endif
-
-#ifndef USERMEM
-# define USERMEM 450000 /* default user memory */
-#endif
-
-#ifdef interdata /* (Perkin-Elmer) */
-#define SIGNED_COMPARE_SLOW /* signed compare is slower than unsigned */
-#endif
-
-#ifdef pdp11
-# define BITS 12 /* max bits/code for 16-bit machine */
-# define NO_UCHAR /* also if "unsigned char" functions as signed char */
-# undef USERMEM
-#endif /* pdp11 */ /* don't forget to compile with -i */
-
-#ifdef z8000
-# define BITS 12
-# undef vax /* weird preprocessor */
-# undef USERMEM
-#endif /* z8000 */
-
-#ifdef pcxt
-# define BITS 12
-# undef USERMEM
-#endif /* pcxt */
-
-#ifdef USERMEM
-# if USERMEM >= (433484+SACREDMEM)
-# define PBITS 16
-# else
-# if USERMEM >= (229600+SACREDMEM)
-# define PBITS 15
-# else
-# if USERMEM >= (127536+SACREDMEM)
-# define PBITS 14
-# else
-# if USERMEM >= (73464+SACREDMEM)
-# define PBITS 13
-# else
-# define PBITS 12
-# endif
-# endif
-# endif
-# endif
-# undef USERMEM
-#endif /* USERMEM */
-
-#ifdef PBITS /* Preferred BITS for this memory size */
-# ifndef BITS
-# define BITS PBITS
-# endif BITS
-#endif /* PBITS */
-
-#if BITS == 16
-# define HSIZE 69001 /* 95% occupancy */
-#endif
-#if BITS == 15
-# define HSIZE 35023 /* 94% occupancy */
-#endif
-#if BITS == 14
-# define HSIZE 18013 /* 91% occupancy */
-#endif
-#if BITS == 13
-# define HSIZE 9001 /* 91% occupancy */
-#endif
-#if BITS <= 12
-# define HSIZE 5003 /* 80% occupancy */
-#endif
-
-#ifdef M_XENIX /* Stupid compiler can't handle arrays with */
-# if BITS == 16 /* more than 65535 bytes - so we fake it */
-# define XENIX_16
-# else
-# if BITS > 13 /* Code only handles BITS = 12, 13, or 16 */
-# define BITS 13
-# endif
-# endif
-#endif
-
-/*
- * a code_int must be able to hold 2**BITS values of type int, and also -1
- */
-#if BITS > 15
-typedef long int code_int;
-#else
-typedef int code_int;
-#endif
-
-#ifdef SIGNED_COMPARE_SLOW
-typedef unsigned long int count_int;
-typedef unsigned short int count_short;
-#else
-typedef long int count_int;
-#endif
-
-#ifdef NO_UCHAR
- typedef char char_type;
-#else
- typedef unsigned char char_type;
-#endif /* UCHAR */
-char_type magic_header[] = { "\037\235" }; /* 1F 9D */
-
-/* Defines for third byte of header */
-#define BIT_MASK 0x1f
-#define BLOCK_MASK 0x80
-/* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
- a fourth header byte (for expansion).
-*/
-#define INIT_BITS 9 /* initial number of bits/code */
-
-/*
- * compress.c - File compression ala IEEE Computer, June 1984.
- *
- * Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
- * Jim McKie (decvax!mcvax!jim)
- * Steve Davies (decvax!vax135!petsd!peora!srd)
- * Ken Turkowski (decvax!decwrl!turtlevax!ken)
- * James A. Woods (decvax!ihnp4!ames!jaw)
- * Joe Orost (decvax!vax135!petsd!joe)
- *
- */
-
-#include <stdio.h>
-#include <ctype.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#define ARGVAL() (*++(*argv) || (--argc && *++argv))
-
-int n_bits; /* number of bits/code */
-int maxbits = BITS; /* user settable max # bits/code */
-code_int maxcode; /* maximum code, given n_bits */
-code_int maxmaxcode = 1L << BITS; /* should NEVER generate this code */
-#ifdef COMPATIBLE /* But wrong! */
-# define MAXCODE(n_bits) (1 << (n_bits) - 1)
-#else
-# define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
-#endif /* COMPATIBLE */
-
-#ifdef XENIX_16
-count_int htab0[8192];
-count_int htab1[8192];
-count_int htab2[8192];
-count_int htab3[8192];
-count_int htab4[8192];
-count_int htab5[8192];
-count_int htab6[8192];
-count_int htab7[8192];
-count_int htab8[HSIZE-65536];
-count_int * htab[9] = {
- htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8 };
-
-#define htabof(i) (htab[(i) >> 13][(i) & 0x1fff])
-unsigned short code0tab[16384];
-unsigned short code1tab[16384];
-unsigned short code2tab[16384];
-unsigned short code3tab[16384];
-unsigned short code4tab[16384];
-unsigned short * codetab[5] = {
- code0tab, code1tab, code2tab, code3tab, code4tab };
-
-#define codetabof(i) (codetab[(i) >> 14][(i) & 0x3fff])
-
-#else /* Normal machine */
-# ifdef sel
-/* support gould base register problems */
-/*NOBASE*/
-count_int htab [HSIZE];
-unsigned short codetab [HSIZE];
-/*NOBASE*/
-# else /* !gould */
-count_int htab [HSIZE];
-unsigned short codetab [HSIZE];
-# endif /* !gould */
-#define htabof(i) htab[i]
-#define codetabof(i) codetab[i]
-#endif /* !XENIX_16 */
-code_int hsize = HSIZE; /* for dynamic table sizing */
-count_int fsize;
-
-/*
- * To save much memory, we overlay the table used by compress() with those
- * used by decompress(). The tab_prefix table is the same size and type
- * as the codetab. The tab_suffix table needs 2**BITS characters. We
- * get this from the beginning of htab. The output stack uses the rest
- * of htab, and contains characters. There is plenty of room for any
- * possible stack (stack used to be 8000 characters).
- */
-
-#define tab_prefixof(i) codetabof(i)
-#ifdef XENIX_16
-# define tab_suffixof(i) ((char_type *)htab[(i)>>15])[(i) & 0x7fff]
-# define de_stack ((char_type *)(htab2))
-#else /* Normal machine */
-# define tab_suffixof(i) ((char_type *)(htab))[i]
-# define de_stack ((char_type *)&tab_suffixof(1<<BITS))
-#endif /* XENIX_16 */
-
-code_int free_ent = 0; /* first unused entry */
-int exit_stat = 0;
-
-code_int getcode();
-
-Usage() {
-#ifdef DEBUG
-fprintf(stderr,"Usage: compress [-dDVfc] [-b maxbits] [file ...]\n");
-}
-int debug = 0;
-#else
-fprintf(stderr,"Usage: compress [-dfvcV] [-b maxbits] [file ...]\n");
-}
-#endif /* DEBUG */
-int nomagic = 0; /* Use a 3-byte magic number header, unless old file */
-int zcat_flg = 0; /* Write output on stdout, suppress messages */
-int quiet = 1; /* don't tell me about compression */
-
-/*
- * block compression parameters -- after all codes are used up,
- * and compression rate changes, start over.
- */
-int block_compress = BLOCK_MASK;
-int clear_flg = 0;
-long int ratio = 0;
-#define CHECK_GAP 10000 /* ratio check interval */
-count_int checkpoint = CHECK_GAP;
-/*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
-#define FIRST 257 /* first free entry */
-#define CLEAR 256 /* table clear output code */
-
-int force = 0;
-char ofname [100];
-#ifdef DEBUG
-int verbose = 0;
-#endif /* DEBUG */
-int (*bgnd_flag)();
-
-int do_decomp = 0;
-
-/*****************************************************************
- * TAG( main )
- *
- * Algorithm from "A Technique for High Performance Data Compression",
- * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
- *
- * Usage: compress [-dfvc] [-b bits] [file ...]
- * Inputs:
- * -d: If given, decompression is done instead.
- *
- * -c: Write output on stdout, don't remove original.
- *
- * -b: Parameter limits the max number of bits/code.
- *
- * -f: Forces output file to be generated, even if one already
- * exists, and even if no space is saved by compressing.
- * If -f is not used, the user will be prompted if stdin is
- * a tty, otherwise, the output file will not be overwritten.
- *
- * -v: Write compression statistics
- *
- * file ...: Files to be compressed. If none specified, stdin
- * is used.
- * Outputs:
- * file.Z: Compressed form of file with same mode, owner, and utimes
- * or stdout (if stdin used as input)
- *
- * Assumptions:
- * When filenames are given, replaces with the compressed version
- * (.Z suffix) only if the file decreases in size.
- * Algorithm:
- * Modified Lempel-Ziv method (LZW). Basically finds common
- * substrings and replaces them with a variable size code. This is
- * deterministic, and can be done on the fly. Thus, the decompression
- * procedure needs no input table, but tracks the way the table was built.
- */
-
-main( argc, argv )
-register int argc; char **argv;
-{
- int overwrite = 0; /* Do not overwrite unless given -f flag */
- char tempname[100];
- char **filelist, **fileptr;
- char *cp, *rindex(), *malloc();
- struct stat statbuf;
- extern onintr(), oops();
-
-
- if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
- signal ( SIGINT, onintr );
- signal ( SIGSEGV, oops );
- }
-
-#ifdef COMPATIBLE
- nomagic = 1; /* Original didn't have a magic number */
-#endif /* COMPATIBLE */
-
- filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
- *filelist = NULL;
-
- if((cp = rindex(argv[0], '/')) != 0) {
- cp++;
- } else {
- cp = argv[0];
- }
- if(strcmp(cp, "uncompress") == 0) {
- do_decomp = 1;
- } else if(strcmp(cp, "zcat") == 0) {
- do_decomp = 1;
- zcat_flg = 1;
- }
-
-#ifdef BSD4_2
- /* 4.2BSD dependent - take it out if not */
- setlinebuf( stderr );
-#endif /* BSD4_2 */
-
- /* Argument Processing
- * All flags are optional.
- * -D => debug
- * -V => print Version; debug verbose
- * -d => do_decomp
- * -v => unquiet
- * -f => force overwrite of output file
- * -n => no header: useful to uncompress old files
- * -b maxbits => maxbits. If -b is specified, then maxbits MUST be
- * given also.
- * -c => cat all output to stdout
- * -C => generate output compatible with compress 2.0.
- * if a string is left, must be an input filename.
- */
- for (argc--, argv++; argc > 0; argc--, argv++) {
- if (**argv == '-') { /* A flag argument */
- while (*++(*argv)) { /* Process all flags in this arg */
- switch (**argv) {
-#ifdef DEBUG
- case 'D':
- debug = 1;
- break;
- case 'V':
- verbose = 1;
- version();
- break;
-#else
- case 'V':
- version();
- break;
-#endif /* DEBUG */
- case 'v':
- quiet = 0;
- break;
- case 'd':
- do_decomp = 1;
- break;
- case 'f':
- case 'F':
- overwrite = 1;
- force = 1;
- break;
- case 'n':
- nomagic = 1;
- break;
- case 'C':
- block_compress = 0;
- break;
- case 'b':
- if (!ARGVAL()) {
- fprintf(stderr, "Missing maxbits\n");
- Usage();
- exit(1);
- }
- maxbits = atoi(*argv);
- goto nextarg;
- case 'c':
- zcat_flg = 1;
- break;
- case 'q':
- quiet = 1;
- break;
- default:
- fprintf(stderr, "Unknown flag: '%c'; ", **argv);
- Usage();
- exit(1);
- }
- }
- }
- else { /* Input file name */
- *fileptr++ = *argv; /* Build input file list */
- *fileptr = NULL;
- /* process nextarg; */
- }
- nextarg: continue;
- }
-
- if(maxbits < INIT_BITS) maxbits = INIT_BITS;
- if (maxbits > BITS) maxbits = BITS;
- maxmaxcode = 1L << maxbits;
-
- if (*filelist != NULL) {
- for (fileptr = filelist; *fileptr; fileptr++) {
- exit_stat = 0;
- if (do_decomp != 0) { /* DECOMPRESSION */
- /* Check for .Z suffix */
- if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) {
- /* No .Z: tack one on */
- strcpy(tempname, *fileptr);
- strcat(tempname, ".Z");
- *fileptr = tempname;
- }
- /* Open input file */
- if ((freopen(*fileptr, "r", stdin)) == NULL) {
- perror(*fileptr); continue;
- }
- /* Check the magic number */
- if (nomagic == 0) {
- if ((getchar() != (magic_header[0] & 0xFF))
- || (getchar() != (magic_header[1] & 0xFF))) {
- fprintf(stderr, "%s: not in compressed format\n",
- *fileptr);
- continue;
- }
- maxbits = getchar(); /* set -b from file */
- block_compress = maxbits & BLOCK_MASK;
- maxbits &= BIT_MASK;
- maxmaxcode = 1L << maxbits;
- if(maxbits > BITS) {
- fprintf(stderr,
- "%s: compressed with %d bits, can only handle %d bits\n",
- *fileptr, maxbits, BITS);
- continue;
- }
- }
- /* Generate output filename */
- strcpy(ofname, *fileptr);
- ofname[strlen(*fileptr) - 2] = '\0'; /* Strip off .Z */
- } else { /* COMPRESSION */
- if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) {
- fprintf(stderr, "%s: already has .Z suffix -- no change\n",
- *fileptr);
- continue;
- }
- /* Open input file */
- if ((freopen(*fileptr, "r", stdin)) == NULL) {
- perror(*fileptr); continue;
- }
- stat ( *fileptr, &statbuf );
- fsize = (long) statbuf.st_size;
- /*
- * tune hash table size for small files -- ad hoc,
- * but the sizes match earlier #defines, which
- * serve as upper bounds on the number of output codes.
- */
- hsize = HSIZE;
- if ( fsize < (1 << 12) )
- hsize = min ( 5003, HSIZE );
- else if ( fsize < (1 << 13) )
- hsize = min ( 9001, HSIZE );
- else if ( fsize < (1 << 14) )
- hsize = min ( 18013, HSIZE );
- else if ( fsize < (1 << 15) )
- hsize = min ( 35023, HSIZE );
- else if ( fsize < 47000 )
- hsize = min ( 50021, HSIZE );
-
- /* Generate output filename */
- strcpy(ofname, *fileptr);
-#ifndef BSD4_2 /* Short filenames */
- if ((cp=rindex(ofname,'/')) != NULL) cp++;
- else cp = ofname;
- if (strlen(cp) > 12) {
- fprintf(stderr,"%s: filename too long to tack on .Z\n",cp);
- continue;
- }
-#endif /* BSD4_2 Long filenames allowed */
- strcat(ofname, ".Z");
- }
- /* Check for overwrite of existing file */
- if (overwrite == 0 && zcat_flg == 0) {
- if (stat(ofname, &statbuf) == 0) {
- char response[2];
- response[0] = 'n';
- fprintf(stderr, "%s already exists;", ofname);
- if (foreground()) {
- fprintf(stderr, " do you wish to overwrite %s (y or n)? ",
- ofname);
- fflush(stderr);
- read(2, response, 2);
- while (response[1] != '\n') {
- if (read(2, response+1, 1) < 0) { /* Ack! */
- perror("stderr"); break;
- }
- }
- }
- if (response[0] != 'y') {
- fprintf(stderr, "\tnot overwritten\n");
- continue;
- }
- }
- }
- if(zcat_flg == 0) { /* Open output file */
- if (freopen(ofname, "w", stdout) == NULL) {
- perror(ofname);
- continue;
- }
- if(!quiet)
- fprintf(stderr, "%s: ", *fileptr);
- }
-
- /* Actually do the compression/decompression */
- if (do_decomp == 0) compress();
-#ifndef DEBUG
- else decompress();
-#else
- else if (debug == 0) decompress();
- else printcodes();
- if (verbose) dump_tab();
-#endif /* DEBUG */
- if(zcat_flg == 0) {
- copystat(*fileptr, ofname); /* Copy stats */
- if((exit_stat == 1) || (!quiet))
- putc('\n', stderr);
- }
- }
- } else { /* Standard input */
- if (do_decomp == 0) {
- compress();
-#ifdef DEBUG
- if(verbose) dump_tab();
-#endif /* DEBUG */
- if(!quiet)
- putc('\n', stderr);
- } else {
- /* Check the magic number */
- if (nomagic == 0) {
- if ((getchar()!=(magic_header[0] & 0xFF))
- || (getchar()!=(magic_header[1] & 0xFF))) {
- fprintf(stderr, "stdin: not in compressed format\n");
- exit(1);
- }
- maxbits = getchar(); /* set -b from file */
- block_compress = maxbits & BLOCK_MASK;
- maxbits &= BIT_MASK;
- maxmaxcode = 1L << maxbits;
- fsize = 100000; /* assume stdin large for USERMEM */
- if(maxbits > BITS) {
- fprintf(stderr,
- "stdin: compressed with %d bits, can only handle %d bits\n",
- maxbits, BITS);
- exit(1);
- }
- }
-#ifndef DEBUG
- decompress();
-#else
- if (debug == 0) decompress();
- else printcodes();
- if (verbose) dump_tab();
-#endif /* DEBUG */
- }
- }
- exit(exit_stat);
-}
-
-static int offset;
-long int in_count = 1; /* length of input */
-long int bytes_out; /* length of compressed output */
-long int out_count = 0; /* # of codes output (for debugging) */
-
-/*
- * compress stdin to stdout
- *
- * Algorithm: use open addressing double hashing (no chaining) on the
- * prefix code / next character combination. We do a variant of Knuth's
- * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
- * secondary probe. Here, the modular division first probe is gives way
- * to a faster exclusive-or manipulation. Also do block compression with
- * an adaptive reset, whereby the code table is cleared when the compression
- * ratio decreases, but after the table fills. The variable-length output
- * codes are re-sized at this point, and a special CLEAR code is generated
- * for the decompressor. Late addition: construct the table according to
- * file size for noticeable speed improvement on small files. Please direct
- * questions about this implementation to ames!jaw.
- */
-
-compress() {
- register long fcode;
- register code_int i = 0;
- register int c;
- register code_int ent;
-#ifdef XENIX_16
- register code_int disp;
-#else /* Normal machine */
- register int disp;
-#endif
- register code_int hsize_reg;
- register int hshift;
-
-#ifndef COMPATIBLE
- if (nomagic == 0) {
- putchar(magic_header[0]); putchar(magic_header[1]);
- putchar((char)(maxbits | block_compress));
- if(ferror(stdout))
- writeerr();
- }
-#endif /* COMPATIBLE */
-
- offset = 0;
- bytes_out = 3; /* includes 3-byte header mojo */
- out_count = 0;
- clear_flg = 0;
- ratio = 0;
- in_count = 1;
- checkpoint = CHECK_GAP;
- maxcode = MAXCODE(n_bits = INIT_BITS);
- free_ent = ((block_compress) ? FIRST : 256 );
-
- ent = getchar ();
-
- hshift = 0;
- for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
- hshift++;
- hshift = 8 - hshift; /* set hash code range bound */
-
- hsize_reg = hsize;
- cl_hash( (count_int) hsize_reg); /* clear hash table */
-
-#ifdef SIGNED_COMPARE_SLOW
- while ( (c = getchar()) != (unsigned) EOF ) {
-#else
- while ( (c = getchar()) != EOF ) {
-#endif
- in_count++;
- fcode = (long) (((long) c << maxbits) + ent);
- i = (((long)c << hshift) ^ ent); /* xor hashing */
-
- if ( htabof (i) == fcode ) {
- ent = codetabof (i);
- continue;
- } else if ( (long)htabof (i) < 0 ) /* empty slot */
- goto nomatch;
- disp = hsize_reg - i; /* secondary hash (after G. Knott) */
- if ( i == 0 )
- disp = 1;
-probe:
- if ( (i -= disp) < 0 )
- i += hsize_reg;
-
- if ( htabof (i) == fcode ) {
- ent = codetabof (i);
- continue;
- }
- if ( (long)htabof (i) > 0 )
- goto probe;
-nomatch:
- output ( (code_int) ent );
- out_count++;
- ent = c;
-#ifdef SIGNED_COMPARE_SLOW
- if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
-#else
- if ( free_ent < maxmaxcode ) {
-#endif
- codetabof (i) = free_ent++; /* code -> hashtable */
- htabof (i) = fcode;
- }
- else if ( (count_int)in_count >= checkpoint && block_compress )
- cl_block ();
- }
- /*
- * Put out the final code.
- */
- output( (code_int)ent );
- out_count++;
- output( (code_int)-1 );
-
- /*
- * Print out stats on stderr
- */
- if(zcat_flg == 0 && !quiet) {
-#ifdef DEBUG
- fprintf( stderr,
- "%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
- in_count, out_count, bytes_out );
- prratio( stderr, in_count, bytes_out );
- fprintf( stderr, "\n");
- fprintf( stderr, "\tCompression as in compact: " );
- prratio( stderr, in_count-bytes_out, in_count );
- fprintf( stderr, "\n");
- fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
- free_ent - 1, n_bits );
-#else /* !DEBUG */
- fprintf( stderr, "Compression: " );
- prratio( stderr, in_count-bytes_out, in_count );
-#endif /* DEBUG */
- }
- if(bytes_out > in_count) /* exit(2) if no savings */
- exit_stat = 2;
- return;
-}
-
-/*****************************************************************
- * TAG( output )
- *
- * Output the given code.
- * Inputs:
- * code: A n_bits-bit integer. If == -1, then EOF. This assumes
- * that n_bits =< (long)wordsize - 1.
- * Outputs:
- * Outputs code to the file.
- * Assumptions:
- * Chars are 8 bits long.
- * Algorithm:
- * Maintain a BITS character long buffer (so that 8 codes will
- * fit in it exactly). Use the VAX insv instruction to insert each
- * code in turn. When the buffer fills up empty it and start over.
- */
-
-static char buf[BITS];
-
-#ifndef vax
-char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
-char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
-#endif /* vax */
-
-output( code )
-code_int code;
-{
-#ifdef DEBUG
- static int col = 0;
-#endif /* DEBUG */
-
- /*
- * On the VAX, it is important to have the register declarations
- * in exactly the order given, or the asm will break.
- */
- register int r_off = offset, bits= n_bits;
- register char * bp = buf;
-
-#ifdef DEBUG
- if ( verbose )
- fprintf( stderr, "%5d%c", code,
- (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
-#endif /* DEBUG */
- if ( code >= 0 ) {
-#ifdef vax
- /* VAX DEPENDENT!! Implementation on other machines is below.
- *
- * Translation: Insert BITS bits from the argument starting at
- * offset bits from the beginning of buf.
- */
- 0; /* Work around for pcc -O bug with asm and if stmt */
- asm( "insv 4(ap),r11,r10,(r9)" );
-#else /* not a vax */
-/*
- * byte/bit numbering on the VAX is simulated by the following code
- */
- /*
- * Get to the first byte.
- */
- bp += (r_off >> 3);
- r_off &= 7;
- /*
- * Since code is always >= 8 bits, only need to mask the first
- * hunk on the left.
- */
- *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
- bp++;
- bits -= (8 - r_off);
- code >>= 8 - r_off;
- /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- if ( bits >= 8 ) {
- *bp++ = code;
- code >>= 8;
- bits -= 8;
- }
- /* Last bits. */
- if(bits)
- *bp = code;
-#endif /* vax */
- offset += n_bits;
- if ( offset == (n_bits << 3) ) {
- bp = buf;
- bits = n_bits;
- bytes_out += bits;
- do
- putchar(*bp++);
- while(--bits);
- offset = 0;
- }
-
- /*
- * If the next entry is going to be too big for the code size,
- * then increase it, if possible.
- */
- if ( free_ent > maxcode || (clear_flg > 0))
- {
- /*
- * Write the whole buffer, because the input side won't
- * discover the size increase until after it has read it.
- */
- if ( offset > 0 ) {
- if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
- writeerr();
- bytes_out += n_bits;
- }
- offset = 0;
-
- if ( clear_flg ) {
- maxcode = MAXCODE (n_bits = INIT_BITS);
- clear_flg = 0;
- }
- else {
- n_bits++;
- if ( n_bits == maxbits )
- maxcode = maxmaxcode;
- else
- maxcode = MAXCODE(n_bits);
- }
-#ifdef DEBUG
- if ( debug ) {
- fprintf( stderr, "\nChange to %d bits\n", n_bits );
- col = 0;
- }
-#endif /* DEBUG */
- }
- } else {
- /*
- * At EOF, write the rest of the buffer.
- */
- if ( offset > 0 )
- fwrite( buf, 1, (offset + 7) / 8, stdout );
- bytes_out += (offset + 7) / 8;
- offset = 0;
- fflush( stdout );
-#ifdef DEBUG
- if ( verbose )
- fprintf( stderr, "\n" );
-#endif /* DEBUG */
- if( ferror( stdout ) )
- writeerr();
- }
-}
-
-/*
- * Decompress stdin to stdout. This routine adapts to the codes in the
- * file building the "string" table on-the-fly; requiring no table to
- * be stored in the compressed file. The tables used herein are shared
- * with those of the compress() routine. See the definitions above.
- */
-
-decompress() {
- register char_type *stackp;
- register int finchar;
- register code_int code, oldcode, incode;
-
- /*
- * As above, initialize the first 256 entries in the table.
- */
- maxcode = MAXCODE(n_bits = INIT_BITS);
- for ( code = 255; code >= 0; code-- ) {
- tab_prefixof(code) = 0;
- tab_suffixof(code) = (char_type)code;
- }
- free_ent = ((block_compress) ? FIRST : 256 );
-
- finchar = oldcode = getcode();
- if(oldcode == -1) /* EOF already? */
- return; /* Get out of here */
- putchar( (char)finchar ); /* first code must be 8 bits = char */
- if(ferror(stdout)) /* Crash if can't write */
- writeerr();
- stackp = de_stack;
-
- while ( (code = getcode()) > -1 ) {
-
- if ( (code == CLEAR) && block_compress ) {
- for ( code = 255; code >= 0; code-- )
- tab_prefixof(code) = 0;
- clear_flg = 1;
- free_ent = FIRST - 1;
- if ( (code = getcode ()) == -1 ) /* O, untimely death! */
- break;
- }
- incode = code;
- /*
- * Special case for KwKwK string.
- */
- if ( code >= free_ent ) {
- *stackp++ = finchar;
- code = oldcode;
- }
-
- /*
- * Generate output characters in reverse order
- */
-#ifdef SIGNED_COMPARE_SLOW
- while ( ((unsigned long)code) >= ((unsigned long)256) ) {
-#else
- while ( code >= 256 ) {
-#endif
- *stackp++ = tab_suffixof(code);
- code = tab_prefixof(code);
- }
- *stackp++ = finchar = tab_suffixof(code);
-
- /*
- * And put them out in forward order
- */
- do
- putchar ( *--stackp );
- while ( stackp > de_stack );
-
- /*
- * Generate the new entry.
- */
- if ( (code=free_ent) < maxmaxcode ) {
- tab_prefixof(code) = (unsigned short)oldcode;
- tab_suffixof(code) = finchar;
- free_ent = code+1;
- }
- /*
- * Remember previous code.
- */
- oldcode = incode;
- }
- fflush( stdout );
- if(ferror(stdout))
- writeerr();
-}
-
-/*****************************************************************
- * TAG( getcode )
- *
- * Read one code from the standard input. If EOF, return -1.
- * Inputs:
- * stdin
- * Outputs:
- * code or -1 is returned.
- */
-
-code_int
-getcode() {
- /*
- * On the VAX, it is important to have the register declarations
- * in exactly the order given, or the asm will break.
- */
- register code_int code;
- static int offset = 0, size = 0;
- static char_type buf[BITS];
- register int r_off, bits;
- register char_type *bp = buf;
-
- if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
- /*
- * If the next entry will be too big for the current code
- * size, then we must increase the size. This implies reading
- * a new buffer full, too.
- */
- if ( free_ent > maxcode ) {
- n_bits++;
- if ( n_bits == maxbits )
- maxcode = maxmaxcode; /* won't get any bigger now */
- else
- maxcode = MAXCODE(n_bits);
- }
- if ( clear_flg > 0) {
- maxcode = MAXCODE (n_bits = INIT_BITS);
- clear_flg = 0;
- }
- size = fread( buf, 1, n_bits, stdin );
- if ( size <= 0 )
- return -1; /* end of file */
- offset = 0;
- /* Round size down to integral number of codes */
- size = (size << 3) - (n_bits - 1);
- }
- r_off = offset;
- bits = n_bits;
-#ifdef vax
- asm( "extzv r10,r9,(r8),r11" );
-#else /* not a vax */
- /*
- * Get to the first byte.
- */
- bp += (r_off >> 3);
- r_off &= 7;
- /* Get first part (low order bits) */
-#ifdef NO_UCHAR
- code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
-#else
- code = (*bp++ >> r_off);
-#endif /* NO_UCHAR */
- bits -= (8 - r_off);
- r_off = 8 - r_off; /* now, offset into code word */
- /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- if ( bits >= 8 ) {
-#ifdef NO_UCHAR
- code |= (*bp++ & 0xff) << r_off;
-#else
- code |= *bp++ << r_off;
-#endif /* NO_UCHAR */
- r_off += 8;
- bits -= 8;
- }
- /* high order bits. */
- code |= (*bp & rmask[bits]) << r_off;
-#endif /* vax */
- offset += n_bits;
-
- return code;
-}
-
-char *
-rindex(s, c) /* For those who don't have it in libc.a */
-register char *s, c;
-{
- char *p;
- for (p = NULL; *s; s++)
- if (*s == c)
- p = s;
- return(p);
-}
-
-#ifdef DEBUG
-printcodes()
-{
- /*
- * Just print out codes from input file. For debugging.
- */
- code_int code;
- int col = 0, bits;
-
- bits = n_bits = INIT_BITS;
- maxcode = MAXCODE(n_bits);
- free_ent = ((block_compress) ? FIRST : 256 );
- while ( ( code = getcode() ) >= 0 ) {
- if ( (code == CLEAR) && block_compress ) {
- free_ent = FIRST - 1;
- clear_flg = 1;
- }
- else if ( free_ent < maxmaxcode )
- free_ent++;
- if ( bits != n_bits ) {
- fprintf(stderr, "\nChange to %d bits\n", n_bits );
- bits = n_bits;
- col = 0;
- }
- fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
- }
- putc( '\n', stderr );
- exit( 0 );
-}
-
-#ifdef XENIX_16
-code_int stab1[8192] ;
-code_int stab2[8192] ;
-code_int stab3[8192] ;
-code_int stab4[8192] ;
-code_int stab5[8192] ;
-code_int stab6[8192] ;
-code_int stab7[8192] ;
-code_int stab8[8192] ;
-code_int * sorttab[8] = {stab1, stab2, stab3, stab4, stab5, stab6, stab7,
- stab8 } ;
-#define stabof(i) (sorttab[(i) >> 13][(i) & 0x1fff])
-#else
-code_int sorttab[SSIZE]; /* sorted pointers into htab */
-#define stabof(i) (sorttab[i])
-#endif
-
-dump_tab() /* dump string table */
-{
- register int i, first;
- register ent;
-#define STACK_SIZE 15000
- int stack_top = STACK_SIZE;
- register c;
- unsigned mbshift ;
-
- if(do_decomp == 0) { /* compressing */
- register int flag = 1;
-
- for(i=0; i<hsize; i++) { /* build sort pointers */
- if((long)htabof(i) >= 0) {
- stabof(codetabof(i)) = i;
- }
- }
- first = block_compress ? FIRST : 256;
- for(i = first; i < free_ent; i++) {
- fprintf(stderr, "%5d: \"", i);
- de_stack[--stack_top] = '\n';
- de_stack[--stack_top] = '"';
- stack_top = in_stack((htabof(stabof(i))>>maxbits)&0xff,
- stack_top);
-/* for(ent=htabof(stabof(i)) & ((1<<maxbits)-1); */
- mbshift = ((1 << maxbits) - 1) ;
- ent = htabof(stabof(i)) & mbshift ;
- for(;
- ent > 256;
- /* ent=htabof(stabof(ent)) & ((1<<maxbits)-1)) { */
- ent=htabof(stabof(ent)) & mbshift) {
- stack_top = in_stack(htabof(stabof(ent)) >> maxbits,
- stack_top);
- }
- stack_top = in_stack(ent, stack_top);
- fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr);
- stack_top = STACK_SIZE;
- }
- } else if(!debug) { /* decompressing */
-
- for ( i = 0; i < free_ent; i++ ) {
- ent = i;
- c = tab_suffixof(ent);
- if ( isascii(c) && isprint(c) )
- fprintf( stderr, "%5d: %5d/'%c' \"",
- ent, tab_prefixof(ent), c );
- else
- fprintf( stderr, "%5d: %5d/\\%03o \"",
- ent, tab_prefixof(ent), c );
- de_stack[--stack_top] = '\n';
- de_stack[--stack_top] = '"';
- for ( ; ent != NULL;
- ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
- stack_top = in_stack(tab_suffixof(ent), stack_top);
- }
- fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr );
- stack_top = STACK_SIZE;
- }
- }
-}
-
-int
-in_stack(c, stack_top)
- register c, stack_top;
-{
- if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
- de_stack[--stack_top] = c;
- } else {
- switch( c ) {
- case '\n': de_stack[--stack_top] = 'n'; break;
- case '\t': de_stack[--stack_top] = 't'; break;
- case '\b': de_stack[--stack_top] = 'b'; break;
- case '\f': de_stack[--stack_top] = 'f'; break;
- case '\r': de_stack[--stack_top] = 'r'; break;
- case '\\': de_stack[--stack_top] = '\\'; break;
- default:
- de_stack[--stack_top] = '0' + c % 8;
- de_stack[--stack_top] = '0' + (c / 8) % 8;
- de_stack[--stack_top] = '0' + c / 64;
- break;
- }
- de_stack[--stack_top] = '\\';
- }
- return stack_top;
-}
-#endif /* DEBUG */
-
-writeerr()
-{
- perror ( ofname );
- unlink ( ofname );
- exit ( 1 );
-}
-
-copystat(ifname, ofname)
-char *ifname, *ofname;
-{
- struct stat statbuf;
- int mode;
- time_t timep[2];
-
- fclose(stdout);
- if (stat(ifname, &statbuf)) { /* Get stat on input file */
- perror(ifname);
- return;
- }
- if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) {
- if(quiet)
- fprintf(stderr, "%s: ", ifname);
- fprintf(stderr, " -- not a regular file: unchanged");
- exit_stat = 1;
- } else if (statbuf.st_nlink > 1) {
- if(quiet)
- fprintf(stderr, "%s: ", ifname);
- fprintf(stderr, " -- has %d other links: unchanged",
- statbuf.st_nlink - 1);
- exit_stat = 1;
- } else if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */
- if(!quiet)
- fprintf(stderr, " -- file unchanged");
- } else { /* ***** Successful Compression ***** */
- exit_stat = 0;
- mode = statbuf.st_mode & 07777;
- if (chmod(ofname, mode)) /* Copy modes */
- perror(ofname);
- chown(ofname, statbuf.st_uid, statbuf.st_gid); /* Copy ownership */
- timep[0] = statbuf.st_atime;
- timep[1] = statbuf.st_mtime;
- utime(ofname, timep); /* Update last accessed and modified times */
- if (unlink(ifname)) /* Remove input file */
- perror(ifname);
- if(!quiet)
- fprintf(stderr, " -- replaced with %s", ofname);
- return; /* Successful return */
- }
-
- /* Unsuccessful return -- one of the tests failed */
- if (unlink(ofname))
- perror(ofname);
-}
-/*
- * This routine returns 1 if we are running in the foreground and stderr
- * is a tty.
- */
-foreground()
-{
- if(bgnd_flag) { /* background? */
- return(0);
- } else { /* foreground */
- if(isatty(2)) { /* and stderr is a tty */
- return(1);
- } else {
- return(0);
- }
- }
-}
-
-onintr ( )
-{
- unlink ( ofname );
- exit ( 1 );
-}
-
-oops ( ) /* wild pointer -- assume bad input */
-{
- if ( do_decomp == 1 )
- fprintf ( stderr, "uncompress: corrupt input\n" );
- unlink ( ofname );
- exit ( 1 );
-}
-
-cl_block () /* table clear for block compress */
-{
- register long int rat;
-
- checkpoint = in_count + CHECK_GAP;
-#ifdef DEBUG
- if ( debug ) {
- fprintf ( stderr, "count: %ld, ratio: ", in_count );
- prratio ( stderr, in_count, bytes_out );
- fprintf ( stderr, "\n");
- }
-#endif /* DEBUG */
-
- if(in_count > 0x007fffff) { /* shift will overflow */
- rat = bytes_out >> 8;
- if(rat == 0) { /* Don't divide by zero */
- rat = 0x7fffffff;
- } else {
- rat = in_count / rat;
- }
- } else {
- rat = (in_count << 8) / bytes_out; /* 8 fractional bits */
- }
- if ( rat > ratio ) {
- ratio = rat;
- } else {
- ratio = 0;
-#ifdef DEBUG
- if(verbose)
- dump_tab(); /* dump string table */
-#endif
- cl_hash ( (count_int) hsize );
- free_ent = FIRST;
- clear_flg = 1;
- output ( (code_int) CLEAR );
-#ifdef DEBUG
- if(debug)
- fprintf ( stderr, "clear\n" );
-#endif /* DEBUG */
- }
-}
-
-cl_hash(hsize) /* reset code table */
- register count_int hsize;
-{
-#ifndef XENIX_16 /* Normal machine */
- register count_int *htab_p = htab+hsize;
-#else
- register j;
- register long k = hsize;
- register count_int *htab_p;
-#endif
- register long i;
- register long m1 = -1;
-
-#ifdef XENIX_16
- for(j=0; j<=8 && k>=0; j++,k-=8192) {
- i = 8192;
- if(k < 8192) {
- i = k;
- }
- htab_p = &(htab[j][i]);
- i -= 16;
- if(i > 0) {
-#else
- i = hsize - 16;
-#endif
- do { /* might use Sys V memset(3) here */
- *(htab_p-16) = m1;
- *(htab_p-15) = m1;
- *(htab_p-14) = m1;
- *(htab_p-13) = m1;
- *(htab_p-12) = m1;
- *(htab_p-11) = m1;
- *(htab_p-10) = m1;
- *(htab_p-9) = m1;
- *(htab_p-8) = m1;
- *(htab_p-7) = m1;
- *(htab_p-6) = m1;
- *(htab_p-5) = m1;
- *(htab_p-4) = m1;
- *(htab_p-3) = m1;
- *(htab_p-2) = m1;
- *(htab_p-1) = m1;
- htab_p -= 16;
- } while ((i -= 16) >= 0);
-#ifdef XENIX_16
- }
- }
-#endif
- for ( i += 16; i > 0; i-- )
- *--htab_p = m1;
-}
-
-prratio(stream, num, den)
-FILE *stream;
-long int num, den;
-{
- register int q; /* Doesn't need to be long */
-
- if(num > 214748L) { /* 2147483647/10000 */
- q = num / (den / 10000L);
- } else {
- q = 10000L * num / den; /* Long calculations, though */
- }
- if (q < 0) {
- putc('-', stream);
- q = -q;
- }
- fprintf(stream, "%d.%02d%%", q / 100, q % 100);
-}
-
-version()
-{
- fprintf(stderr, "%s\n", rcs_ident);
- fprintf(stderr, "Options: ");
-#ifdef vax
- fprintf(stderr, "vax, ");
-#endif
-#ifdef NO_UCHAR
- fprintf(stderr, "NO_UCHAR, ");
-#endif
-#ifdef SIGNED_COMPARE_SLOW
- fprintf(stderr, "SIGNED_COMPARE_SLOW, ");
-#endif
-#ifdef XENIX_16
- fprintf(stderr, "XENIX_16, ");
-#endif
-#ifdef COMPATIBLE
- fprintf(stderr, "COMPATIBLE, ");
-#endif
-#ifdef DEBUG
- fprintf(stderr, "DEBUG, ");
-#endif
-#ifdef BSD4_2
- fprintf(stderr, "BSD4_2, ");
-#endif
- fprintf(stderr, "BITS = %d\n", BITS);
-}
*-*-END-of-src/compress.c-*-*
echo x - src/virtterm.c 1>&2
sed 's/.//' >src/virtterm.c <<'*-*-END-of-src/virtterm.c-*-*'
-/*
- * Virtual terminal handler
- * Written by Kenneth Almquist, AGS Computers (HO 4C601, X7105).
- * Modified by Stephen Hemminger, to use TERMCAP (without curses)
- */
-
-#ifdef SCCSID
-static char *SccsId = "@(#)virtterm.c 1.12 10/29/86";
-#endif /* SCCSID */
-
-/*LINTLIBRARY*/
-
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <signal.h>
-#ifdef USG
-#include <termio.h>
-#else /* !USG */
-#include <sgtty.h>
-#endif /* !USG */
-
-/*
- * These values for MAXPLEN and MAXLLEN are used to dimension arrays
- * that hold strings of relative cursor motions. The actual arrays that
- * are used to hold screen images are malloc'd.
- */
-#define MAXPLEN 90
-#define MAXLLEN 160
-
-#define BOTLINE (ROWS - 1)
-#define DIRTY 01
-
-/* terminal escape sequences from termcap */
-#define HO _tstr[0] /* home */
-#define CL _tstr[1] /* clear screen */
-#define CD _tstr[2] /* clear to end of screen */
-#define CE _tstr[3] /* clear to end of line */
-#define xUP _tstr[4] /* up one line */
-#define DO _tstr[5] /* down one line */
-#define US _tstr[6] /* underline */
-#define UE _tstr[7] /* underline end */
-#define BT _tstr[8] /* backtab */
-#define xBC _tstr[9] /* backspace */
-#define AL _tstr[10] /* insert line */
-#define DL _tstr[11] /* delete line */
-#define CM _tstr[12] /* cursor move */
-#define CH _tstr[13] /* cursor horizontal move */
-#define CV _tstr[14] /* cursor vertical move */
-#define CS _tstr[15] /* scrolling region */
-#define SF _tstr[16] /* scroll forwards */
-#define SR _tstr[17] /* scroll backwards */
-#define TI _tstr[18] /* start cursor mode */
-#define TE _tstr[19] /* end cursor mode */
-#define TA _tstr[20] /* tab char (if not \t) */
-#define CR _tstr[21] /* carriage return (if not \r) */
-#define xPC _tstr[22] /* for reading pad character */
-char PC; /* pad character */
-char *BC, *UP; /* external variables for tgoto */
-
-static char sname[] = "hoclcdceupdousuebtbcaldlcmchcvcssfsrtitetacrpc";
-char *_tstr[23];
-int HOlen; /* length of HO string */
-
-
-/* terminal flags */
-#define BS _tflg[0] /* can backspace */
-#define AM _tflg[1] /* has auto margins */
-#define XN _tflg[2] /* no newline after wrap */
-#define RET !_tflg[3] /* has carriage return */
-#define NS _tflg[4] /* has SF (scroll forward) */
-#define PT _tflg[5] /* has tabs */
-#define XT _tflg[6] /* tabs are destructive */
-int GT = 1; /* tab stops on terminal are set */
-
-static char bname[] = "bsamxnncnsptxt";
-char _tflg[7];
-
-
-extern char *tgoto(), *tgetstr();
-extern char *getenv(), *strcpy();
-
-#define ULINE 0200
-
-/* Constants accessable by user */
-int hasscroll; /* scrolling type, 0 == no scrolling */
-int ROWS; /* number of lines on screen */
-int COLS; /* width of screen */
-
-struct line {
- char len;
- char flags;
- char *l; /* pointer to actual line text, NO NULL @ end */
-};
-
-int _row, _col;
-int _srow, _scol;
-struct line *_virt; /* what we want the screen to look like */
-struct line *_actual; /* What it actually looks like */
-int _uline = 0;
-int _junked = 1;
-int _curjunked;
-int _dir = 1;
-int _shifttop, _shiftbot;
-int _shift;
-int _scratched;
-int vputc();
-
-/*
- * Tell refresh to shift lines in region upwards count lines. Count
- * may be negative. The virtual image is not shifted; this may change
- * later. The variable _scratched is set to supress all attempts to
- * shift.
- */
-
-ushift(top, bot, count)
-{
- if (_scratched)
- return;
- if (_shift != 0 && (_shifttop != top || _shiftbot != bot)) {
- _scratched++;
- return;
- }
- _shifttop = top;
- _shiftbot = bot;
- _shift += count;
-}
-
-/*
- * generate a beep on the terminal
- */
-beep()
-{
- vputc('\7');
-}
-
-/*
- * Move to one line below the bottom of the screen.
- */
-botscreen()
-{
- _amove(BOTLINE, 0);
- vputc('\n');
- vflush();
-}
-
-move(row, col)
-{
- if (row < 0 || row >= ROWS || col < 0 || col >= COLS)
- return;
- _row = row;
- _col = col;
-}
-
-
-
-/*
- * Output string at specified location.
- */
-mvaddstr(row, col, str)
-char *str;
-{
- move(row, col);
- addstr(str);
-}
-
-addstr(s)
-char *s;
-{
- register char *p;
- register struct line *lp;
- register int col = _col;
-
- lp = &_virt[_row];
- if (lp->len < col) {
- p = &lp->l[lp->len];
- while (lp->len < col) {
- *p++ = ' ';
- lp->len++;
- }
- }
- for (p = s; *p != '\0'; p++) {
- if (*p == '\n') {
- lp->len = col;
- lp->flags |= DIRTY;
- col = 0;
- if (++_row >= ROWS)
- _row = 0;
- lp = &_virt[_row];
- }
- else {
- lp->l[col] = *p;
- lp->flags |= DIRTY;
- if (++col >= COLS) {
- lp->len = COLS;
- col = 0;
- if (++_row >= ROWS)
- _row = 0;
- lp = &_virt[_row];
- }
- }
- }
- if (lp->len <= col)
- lp->len = col;
- _col = col;
-}
-
-addch(c)
-{
- register struct line *lp;
- register char *p;
-
- lp = &_virt[_row];
- if (lp->len < _col) {
- p = &lp->l[lp->len];
- while (lp->len < _col) {
- *p++ = ' ';
- lp->len++;
- }
- }
- lp->l[_col] = c;
- if (lp->len == _col)
- lp->len++;
- if (++_col >= COLS) {
- _col = 0;
- if (++_row >= ROWS)
- _row = 0;
- }
- lp->flags |= DIRTY;
-}
-
-/*
- * Clear an entire line.
- */
-clrline(row)
-{
- register struct line *lp;
-
- lp = &_virt[row];
- if (lp->len > 0) {
- lp->len = 0;
- lp->flags |= DIRTY;
- }
-}
-
-erase()
-{
- register i;
-
- for (i = 0; i < ROWS; i++) {
- _virt[i].len = 0;
- _virt[i].flags |= DIRTY;
- }
-}
-
-refresh()
-{
- register i;
- register char *p, *q;
- register int j, len;
-
- if (checkin())
- return;
- i = 1;
- if (_junked) {
- _sclear();
- _junked = 0;
- } else if (! _scratched) {
- if (_shift > 0) {
- _ushift(_shifttop, _shiftbot, _shift);
- } else if (_shift < 0) {
- i = _dshift(_shifttop, _shiftbot, -_shift);
- } else {
- i = _dir;
- }
- }
- _dir = i;
- _shift = 0;
- if (checkin())
- return;
- _fixlines();
- for (i = _dir > 0 ? 0 : BOTLINE; i >= 0 && i < ROWS; i += _dir) {
- if ((_virt[i].flags & DIRTY) == 0)
- continue;
- _ckclrlin(i); /* decide whether to do a clear line */
- /* probably should consider cd too */
- len = _virt[i].len;
- if (_actual[i].len < len)
- len = _actual[i].len;
- p = _virt[i].l;
- q = _actual[i].l;
- for (j = 0; j < len; j++) {
- if (*p != *q) {
- /* Inline test for speed */
- if (i != _srow || j != _scol || _curjunked)
- _amove(i, j);
- _aputc(*p);
- *q = *p;
- }
- p++;
- q++;
- }
- len = _virt[i].len;
- if (_actual[i].len > len) {
- _clrtoeol(i, len);
- } else {
- for (; j < len; j++) {
- if (*p != ' ') {
- /* Inline test for speed */
- if (i != _srow || j != _scol || _curjunked)
- _amove(i, j);
- _aputc(*p);
- }
- *q++ = *p++;
- }
- _actual[i].len = len;
- }
- if (checkin())
- return;
- }
- _dir = 1;
- _amove(_row, _col);
- vflush(); /* flush output buffer */
- _scratched = 0;
-}
-
-_dshift(top, bot, count)
-{
- register i;
-
- if (count >= bot - top || hasscroll < 4) { /* must have CS or AL/DL */
- _scratched++;
- return 1;
- }
- for (i = bot - count; _actual[i].len == 0; i--)
- if (i == top)
- return 1;
- for (i = top; i <= bot; i++)
- _virt[i].flags |= DIRTY;
- for (i = bot; i >= top + count; i--) {
- /* FIXME, this should be done by recirculating the pointers */
- register j;
- j = _actual[i].len = _actual[i - count].len;
- _actual[i].flags = _actual[i - count].flags;
- strncpy(_actual[i].l, _actual[i - count].l, j);
- }
- for (; i >= top; i--)
- _actual[i].len = 0;
-
- if (hasscroll != 5) { /* can we define scrolling region, and scroll back */
- tputs(tgoto(CS, bot, top), 1, vputc);/* define scroll region */
- _curjunked = 1;
- _amove(top, 0);
- for (i = count; --i >= 0;)
- tputs(SR, 1, vputc);/* scroll back */
- tputs(tgoto(CS, BOTLINE, 0), 1, vputc);
- _curjunked = 1;
- } else {
- _amove(bot - count + 1, 0);
- if (CD && bot == BOTLINE)
- tputs(CD, 1, vputc);
- else {
- for (i = count; --i >= 0;)
- tputs(DL, ROWS - _srow, vputc);
- }
- _amove(top, 0);
- for (i = count; --i >= 0;)
- tputs(AL, ROWS - _srow, vputc);
- }
- return -1;
-}
-
-
-_ushift(top, bot, count)
-{
- register i;
-
- if (count >= bot - top || hasscroll == 0) {
- _scratched++;
- return;
- }
- for (i = top + count; _actual[i].len == 0; i++)
- if (i == bot)
- return;
- if (hasscroll == 1 || hasscroll == 3) {
- /* we cheat and shift the entire screen */
- /* be sure we are shifting more lines into than out of position */
- if ((bot - top + 1) - count <= ROWS - (bot - top + 1))
- return;
- top = 0, bot = BOTLINE;
- }
- for (i = top; i <= bot; i++)
- _virt[i].flags |= DIRTY;
- for (i = top; i <= bot - count; i++) {
- /* FIXME, this should be done by recirculating the pointers */
- register int j;
- j = _actual[i].len = _actual[i + count].len;
- _actual[i].flags = _actual[i + count].flags;
- strncpy(_actual[i].l, _actual[i + count].l, j);
- }
- for (; i <= bot; i++)
- for (; i <= bot; i++)
- _actual[i].len = 0;
-
- if (hasscroll != 5) {
- if (top != 0 || bot != BOTLINE) {
- tputs(tgoto(CS, bot, top), 0, vputc);
- _curjunked = 1;
- }
- _amove(bot, 0); /* move to bottom */
- for (i = 0; i < count; i++) {
- if (SF) /* scroll forward */
- tputs(SF, 1, vputc);
- else
- vputc('\n');
- }
- if (top != 0 || bot != BOTLINE) {
- tputs(tgoto(CS, BOTLINE, 0), 0, vputc);
- _curjunked = 1;
- }
- } else {
- _amove(top, 0);
- for (i = count; --i >= 0;)
- tputs(DL, ROWS - _srow, vputc);
- if (bot < BOTLINE) {
- _amove(bot - count + 1, 0);
- for (i = count; --i >= 0;)
- tputs(AL, ROWS - _srow, vputc);
- }
- }
-}
-
-_sclear()
-{
- register struct line *lp;
-
- tputs(CL, 0, vputc);
- _srow = _scol = 0;
- for (lp = _actual; lp < &_actual[ROWS]; lp++) {
- lp->len = 0;
- }
- for (lp = _virt; lp < &_virt[ROWS]; lp++) {
- if (lp->len != 0)
- lp->flags |= DIRTY;
- }
-}
-
-_clrtoeol(row, col)
-{
- register struct line *lp = &_actual[row];
- register i;
-
- if (CE && lp->len > col + 1) {
- _amove(row, col);
- tputs(CE, 1, vputc);
- } else {
- for (i = col ; i < lp->len ; i++) {
- if (lp->l[i] != ' ') {
- _amove(row, i);
- _aputc(' ');
- }
- }
- }
- lp->len = col;
-}
-
-_fixlines()
-{
- register struct line *lp;
- register char *p;
- register int i;
-
- for (i = 0; i < ROWS; i++) {
- lp = &_virt[i];
- if (lp->flags & DIRTY) {
- for (p = &lp->l[lp->len]; --p >= lp->l && *p == ' ';)
- ;
- lp->len = (int) (p - lp->l) + 1;
- if (lp->len == _actual[i].len && strncmp(lp->l, _actual[i].l, lp->len) == 0)
- lp->flags &= ~DIRTY;
- }
- }
-}
-
-
-/*
- * Consider clearing the line before overwriting it.
- * We always clear a line if it has underlined characters in it
- * because these can cause problems. Otherwise decide whether
- * that will decrease the number of characters to change. This
- * routine could probably be simplified with no great loss.
- */
-
-_ckclrlin(i)
-{
- int eval;
- int len;
- int first;
- register struct line *vp, *ap;
- register int j;
-
- if (!CE)
- return;
- ap = &_actual[i];
- vp = &_virt[i];
- len = ap->len;
- eval = -strlen(CE);
- if (len > vp->len) {
- len = vp->len;
- eval = 0;
- }
- for (j = 0; j < len && vp->l[j] == ap->l[j]; j++)
- ;
- if (j == len)
- return;
- first = j;
- while (j < len) {
- if (vp->l[j] == ' ') {
- if (ap->l[j] != ' ') {
- while (++j < len && vp->l[j] == ' ' && ap->l[j] != ' ') {
- eval++;
- }
- if (j == len)
- eval++;
- continue;
- }
- }
- else {
- if (vp->l[j] == ap->l[j]) {
- while (++j < len && vp->l[j] == ap->l[j]) {
- eval--;
- }
- continue;
- }
- }
- j++;
- }
- if (US) {
- for (j = 0 ; j < ap->len ; j++) {
- if (ap->l[j] & ULINE) {
- eval = 999;
- if (first > j)
- first = j;
- break;
- }
- }
- }
- for (j = first; --j >= 0;)
- if (vp->l[j] != ' ')
- break;
- if (j < 0)
- first = 0;
- if (eval > 0) {
- _amove(i, first);
- tputs(CE, 0, vputc);
- _actual[i].len = first;
- }
-}
-
-
-
-/*
- * Move routine
- * first compute direct cursor address string and cost
- * then relative motion string and cost,
- * then home then relative and cost
- * choose smallest and do it.
- *
- * The plod stuff is to build the strings (with padding) then decide
- */
-static char *plodstr; /* current location in relmove string */
-
-plodput(c)
-{
- *plodstr++ = c;
-}
-
-/* FIXME: speedup 1-char horiz moves: print the char that's there. */
-/* FIXME: avoid funniness if cm works. */
-/* FIXME: Avoid setul(0) if cursor motion OK in standout (XM?) */
-_amove(row, col)
-{
- char direct[20];
- char rel[MAXPLEN*10 + MAXLLEN*10]; /* longest move is full screen */
- char ho[MAXPLEN*10 + MAXLLEN*10];
- int cost, newcost;
- register char *movstr;
-
- if (row == _srow && col == _scol && _curjunked == 0)
- return;
- if (_uline)
- _setul(0); /* Inline test for speed */
-
- cost = 999;
- if (CM) {
- plodstr = direct;
- tputs(tgoto(CM, col, row), 0, plodput);
- cost = plodstr - direct;
- movstr = direct;
- }
- if (_curjunked == 0) {
- plodstr = rel;
- if (_vmove(_srow, row) >= 0
- && (plodstr - rel) < cost /* after vmove */
- && _hmove(_scol, col, row) >= 0
- && (newcost = plodstr - rel) < cost) { /* after both */
- cost = newcost;
- movstr = rel;
- }
- }
- if (cost > HOlen) { /* is it worth calculating */
- plodstr = ho;
- tputs(HO, 0, plodput);
- if (_vmove(0, row) >= 0
- && (plodstr - ho) < cost /* after ho, vmove */
- && _hmove(0, col, row) >= 0
- && (newcost = plodstr - ho) < cost) { /* after all three */
- cost = newcost;
- movstr = ho;
- }
- }
-
- if (cost < 999)
- while (--cost >= 0)
- vputc(*movstr++);
-
- _srow = row;
- _scol = col;
- _curjunked = 0;
-}
-
-_vmove(orow, nrow)
-{
- char direct[128];
- char *saveplod = plodstr;
-
- if (CV) {
- plodstr = direct;
- tputs(tgoto(CV, nrow, nrow), 0, plodput);
- *plodstr = '\0';
- plodstr = saveplod;
- }
- if (orow > nrow) { /* cursor up */
- if (! UP)
- return -1;
- while (orow > nrow) {
- tputs(UP, 1, plodput);
- orow--;
- }
- }
- while (orow < nrow) { /* cursor down */
- if (DO)
- tputs(DO, 1, plodput);
- else
- *plodstr++ = '\n';
- orow++;
- }
- if (CV && plodstr - saveplod >= strlen(direct)) {
- register char *p;
- plodstr = saveplod;
- for (p = direct ; *plodstr = *p++ ; plodstr++)
- ;
- }
- return 0;
-}
-
-_hmove(ocol, ncol, row)
-{
- char direct[128];
- char ret[MAXLLEN*10];
- char *saveplod = plodstr;
- char *movstr;
- int cost, newcost;
-
- cost = 999;
- if (CH) {
- plodstr = direct;
- tputs(tgoto(CH, ncol, ncol), 0, plodput);
- cost = plodstr - direct;
- movstr = direct;
- plodstr = saveplod;
- }
- if (RET && ocol > ncol) { /* consider doing carriage return */
- plodstr = ret;
- if (CR)
- tputs(CR, 1, plodput);
- else
- *plodstr++ = '\r';
- if (_relhmove(0, ncol, row) >= 0
- && (newcost = plodstr - ret) < cost) {
- cost = newcost;
- movstr = ret;
- }
- plodstr = saveplod;
- }
- if (_relhmove(ocol, ncol, row) < 0) {
- if (cost == 999)
- return -1;
- goto copy;
- }
- if (plodstr - saveplod > cost) {
-copy: plodstr = saveplod;
- while (--cost >= 0)
- *plodstr++ = *movstr++;
- }
- return 0;
-}
-
-_relhmove(ocol, ncol, row)
-{
- int tab;
-
- if (ocol < ncol && PT && GT) { /* tab (nondestructive) */
- while ((tab = (ocol + 8) & ~07) <= ncol) {
- if (TA)
- tputs(TA, 1, plodput);
- else
- *plodstr++ = '\t';
- ocol = tab;
- }
- if (tab < COLS && tab - ncol < ncol - ocol) {
- if (TA)
- tputs(TA, 1, plodput);
- else
- *plodstr++ = '\t';
- ocol = tab;
- }
- } else if (BT && GT && ocol > ncol) { /* backwards tab */
- while ((tab = (ocol - 1) &~ 07) >= ncol) {
- if (BS && tab == ocol - 1) {
- if (BC)
- tputs(BC, 1, plodput);
- else
- *plodstr++ = '\b';
- } else
- tputs(BT, 1, plodput);
- ocol = tab;
- }
- if (ncol - tab + 1 < ocol - ncol) {
- tputs(BT, 1, plodput);
- ocol = tab;
- }
- }
- if (ocol > ncol) { /* cursor left */
- if (! BS)
- return -1;
- while (ocol > ncol) {
- if (BC != NULL)
- tputs(BC, 1, plodput);
- else
- *plodstr++ = '\b';
- ocol--;
- }
- }
- if (ocol < ncol) { /* cursor right */
- register struct line *lp = &_actual[row];
- /*
- * This code doesn't move over underlined characters properly,
- * but in practice this doesn't seem to matter.
- */
- while (ocol < ncol) {
- if (ocol < lp->len)
- *plodstr++ = lp->l[ocol];
- else
- *plodstr++ = ' ';
- ocol++;
- }
- }
- return 0;
-}
-
-_aputc(c)
-{
- if (_uline != (c & ULINE)) /* Inline for speed */
- _setul(c & ULINE);
- if (++_scol >= COLS) {
- if (_srow == ROWS - 1) {
- /* Don't ever paint last char of last line */
- _scol--;
- return;
- }
- _curjunked++; /* Don't assume AM is right */
- }
- vputc(c & ~ULINE);
-}
-
-
-_setul(on)
-{
- if (on) {
- if (_uline == 0 && US != NULL) {
- tputs(US, 1, vputc);
- _uline = ULINE;
- }
- }
- else {
- if (_uline != 0 && UE != NULL) {
- tputs(UE, 1, vputc);
- _uline = 0;
- }
- }
-}
-
-/*
- * Initialize termcap strings for later use.
- */
-
-/*
- * Hacks to help with some Tek terminals
- * rad at tek
- */
-int tputs_len;
-countit(c) { tputs_len++; }
-
-initterm()
-{
- static char tcbuf[1024]; /* termcap buffer */
- register char *cp;
-#ifdef USG
- struct termio tio;
-#else /* !USG */
- struct sgttyb ttyb;
-#endif /* !USG */
-
- if ((cp = getenv("TERM")) == NULL)
- xerror("TERM not set in environment");
-
- switch (tgetent(tcbuf, cp)) {
- case 0:
- xerror("Terminal not found in TERMCAP");
- case -1:
- xerror("Can't open /etc/termcap");
- case 1:
- break;
- }
-#ifdef TIOCGWINSZ
- {
- struct winsize ws;
- int winch();
-
- COLS = ROWS = -1;
- if(ioctl(1, TIOCGWINSZ, &ws) == 0) {
- ROWS = ws.ws_row;
- COLS = ws.ws_col;
- }
- if(ROWS <= 0)
- ROWS = tgetnum("li");
- if(COLS <= 0)
- COLS = tgetnum("co");
- if ((ROWS <= 0) || (COLS <= 0))
- xerror("Can't get screen size");
-
- signal(SIGWINCH, winch); /* allow for changing window size */
- }
-#else /* !TIOCGWINSZ */
- if ((ROWS = tgetnum("li")) == -1
- || (COLS = tgetnum("co")) == -1)
- xerror("Can't get screen size");
-#endif /* !TIOCGWINSZ */
- _zap();
-
- if (CL == NULL)
- xerror ("No clear screen defined");
-
- if (HO == NULL && CM == NULL)
- xerror("No home or cursor addressing");
- if (HO)
- HOlen = strlen(HO);
- else
- HOlen = 999;
-
- PC = xPC ? xPC[0] : 0;
- BC = xBC;
- UP = xUP;
- /*
- * _vmove() may be called with a full-screen traverse,
- * meaning it will put the UP (along with any padding) into
- * the buffer as many as MAXPLEN times. This means that
- * if the UP string would be more than 10 chars long (defined
- * in _amove() ), the buffer might be overflowed (assuming
- * CH is also large).
- * This actually occurs with the Tek4023 termcap, where :up=1000UP:
- * is used to fake vi into using :cm instead, due to the fact
- * that a 4023 can't do upline relative motion at all.
- * -rdoty at tek
- */
- if (UP) {
- tputs_len = 0;
- tputs(UP, 1, countit);
- if (tputs_len > 10 )
- UP = 0;
- }
-
- if (tgetnum("ug") > 0)
- US = UE = NULL;
-
- if (XT) /* Destructive tab code not included */
- PT = 0; /* to keep things simple */
-
-#ifdef USG
- if (ioctl(0, TCGETA, &tio) == 0)
- GT = tio.c_oflag&TAB3;
-#else /* !USG */
- if (ioctl(0, TIOCGETP, &ttyb) == 0)
- GT = ttyb.sg_flags&XTABS;
-#endif /* !USG */
-
- {
- char *thelines;
- int i;
- char *malloc();
-
- thelines = malloc(2 * ROWS * COLS);
- _virt = (struct line *)malloc(2 * ROWS * sizeof (struct line));
- _actual = _virt + ROWS;
- for (i = 0; i < ROWS; i++) {
- _virt[i].len = 0;
- _virt[i].flags = 0;
- _actual[i].len = 0;
- _actual[i].flags = 0;
- _virt[i].l = thelines;
- thelines += COLS;
- _actual[i].l = thelines;
- thelines += COLS;
- }
- }
-
- /* Select article scrolling algorithm. We prefer scrolling region
- over insert/delete line because it's faster on the HP */
- hasscroll = 0;
- if (!NS) {
- hasscroll = 1;
- if (SR)
- hasscroll = 3;
- if (CS)
- hasscroll++;
- }
- if (AL && DL && hasscroll != 4)
- hasscroll = 5;
-}
-
-rawterm()
-{
- if (TI != NULL)
- tputs(TI, 0, vputc);
-}
-
-cookedterm()
-{
- if (TE != NULL) {
- tputs(TE, 0, vputc);
- vflush();
- }
-}
-
-/* get strings from termcap */
-_zap()
-{
- static char tstrbuf[1024];
- static char *tp;
- register char *namp, **sp, *bp;
-
- tp = tstrbuf;
- sp = _tstr;
- for (namp = sname; *namp; namp += 2) {
- *sp++ = tgetstr(namp, &tp);
- }
- bp = _tflg;
- for (namp = bname; *namp; namp += 2) {
- *bp++ = tgetflag(namp, &tp);
- }
-}
-#ifdef TIOCGWINSZ
-/*
- * window changed size -- update ROWS and COLS
- * and then redraw screen
- */
-winch()
-{
- struct winsize ws;
- int cols, rows;
-
- cols = rows = -1;
- if(ioctl(1, TIOCGWINSZ, &ws) == 0) {
- rows = ws.ws_row;
- cols = ws.ws_col;
- }
- if (rows == ROWS && cols == COLS) { /* just redraw it if no change */
- _junked = 1; /* redraw */
- updscr();
- return;
- }
-
- if(rows > 0)
- ROWS = rows;
- if(cols > 0)
- COLS = cols;
-
- if (ROWS > MAXPLEN)
- ROWS = MAXPLEN;
- if (COLS > MAXLLEN) {
- COLS = MAXLLEN;
- AM = XN = 1;
- }
-
- winch_upd();
-}
-#endif TIOCGWINSZ
*-*-END-of-src/virtterm.c-*-*
echo x - src/decode.c 1>&2
sed 's/.//' >src/decode.c <<'*-*-END-of-src/decode.c-*-*'
-#include <stdio.h>
-
-#ifdef SCCSID
-static char *SccsId = "@(#)decode.c 1.3 5/15/85";
-#endif /* SCCSID */
-
-/*
- * This program is the inverse of encode
- *
- * It collects runs of 12 characters, combines pairs of those
- * to form 6 13 bit numbers, extracts the top bit of each of
- * those to make a 13th 6 bit character, and splits each of
- * the remaining 6 12 bit numbers to form 12 6 bit ones.
- *
- * The strings of 6 bit numbers are collected into groups of
- * 4 and converted into 3 8 bit characters.
- *
- * Now all that would be trivial, if we didn't need to worry
- * about ending all this correctly. About 1/2 of the following
- * program wouldn't be here if the ending didn't matter....
- */
-
-/*
- * the following pair of characters can never occur as a pair
- * in legal input (since (90 * 91 + 90) > 2^13) - they are
- * noticed at the beginning of a 12 char block, and serve to
- * indicate that this block is the terminator. The character
- * immediately following is the (expanded) terminator length.
- */
-#define ENDMARK1 ((90*91 + 90) / 91)
-#define ENDMARK2 ((90*91 + 90) % 91)
-
-main()
-{
- register c;
- register char *p;
- register i;
- register first = 1;
- register cnt = 0;
- int errcnt = 0;
- char b12[12];
- char c12[12];
-
- p = b12;
- i = 12;
-
- while ((c = getchar()) != EOF) {
- if (c < ' ' || c >= (' ' + 91)) {
- if (errcnt++ == 0)
- fprintf(stderr, "decode: Bad data\n");
- continue;
- }
- if (i == 10 && p[-1] == ENDMARK1 && p[-2] == ENDMARK2) {
- cnt = c - ' ';
- i = 12;
- p -= 2;
- continue;
- }
- *p++ = c - ' ';
- if (--i == 0) {
- if (p == &b12[12]) {
- if (!first)
- pack12(c12, 12, 0);
- else
- first = 0;
- p = c12;
- } else {
- pack12(b12, 12, 0);
- p = b12;
- }
- i = 12;
- }
- }
-
- if (p >= &b12[0] && p < &b12[12]) {
- if (!first)
- pack12(c12, 12, i == 12 ? cnt : 0);
- } else
- pack12(b12, 12, i == 12 ? cnt : 0);
-
- if (i != 12) {
- if (p >= &b12[0] && p < &b12[12])
- pack12(b12, 12-i, cnt);
- else
- pack12(c12, 12-i, cnt);
- }
-
- exit(0);
-}
-
-static char b4[4];
-static int cnt = 0;
-
-pack12(p, n, last)
- register char *p;
- register n;
- int last;
-{
- register i;
- register char *q;
- char b13[13];
-
- {
- register c;
- register c13;
-
- q = b13;
- c13 = 0;
-
- for (i = 0; i < n; i += 2) {
- c = *p++ * 91;
- c += *p++;
- c13 <<= 1;
- if (c & (1 << 12))
- c13 |= 1;
- *q++ = (c >> 6) & 0x3f;
- *q++ = c & 0x3f;
- }
- *q++ = c13;
- if (last)
- q = &b13[last];
- }
-
- p = b13;
- n = q - p;
- i = cnt;
- q = &b4[cnt];
-
- while (--n > 0) {
- *q++ = *p++;
- if (++i == 4) {
- char b3[3];
- register char *b = b4;
-
- /* inline expansion of pack6bit, to save calls ... */
-
- q = b3;
- *q++ = (b[0] << 2) | ((b[1] >> 4) & 0x3);
- *q++ = (b[1] << 4) | ((b[2] >> 2) & 0xf);
- *q = (b[2] << 6) | (b[3] & 0x3f);
-
- q = b3;
- while (--i > 0)
- putchar(*q++);
-
- q = b4;
- }
- }
-
- *q++ = *p++; /* the last octet */
- ++i;
-
- if (last || i == 4) {
- pack6bit(b4, i, last);
- i = 0;
- }
-
- cnt = i;
-}
-
-pack6bit(p, n, last)
- register char *p;
- register int n;
- int last;
-{
- register char *q;
- register i = 3;
- char b3[3];
-
- if (last) {
- i = p[n-1];
- if (i >= 3) {
- fprintf(stderr, "Badly encoded file\n");
- i = 3; /* do the best we can */
- }
- }
-
- q = b3;
- *q++ = (p[0] << 2) | ((p[1] >> 4) & 0x3);
- *q++ = (p[1] << 4) | ((p[2] >> 2) & 0xf);
- *q = (p[2] << 6) | (p[3] & 0x3f);
-
- q = b3;
-
- while (--i >= 0)
- putchar(*q++);
-}
*-*-END-of-src/decode.c-*-*
exit
More information about the Mod.sources
mailing list