OSDN Git Service

re-indented by the GNU indent and rewrite the makefile for GNU make.
authorKoji Arai <jca02266@gmail.com>
Sat, 16 Feb 2008 14:00:22 +0000 (23:00 +0900)
committerKoji Arai <jca02266@gmail.com>
Sat, 16 Feb 2008 14:00:22 +0000 (23:00 +0900)
command name is changed to olha which meaning the OpenLHa.

.gitignore [new file with mode: 0755]
ar.c
ar.h
decode.c
encode.c
huf.c
io.c
makefile
maketbl.c
maketree.c

diff --git a/.gitignore b/.gitignore
new file mode 100755 (executable)
index 0000000..28128dd
--- /dev/null
@@ -0,0 +1,3 @@
+*.o
+*.exe
+*~
diff --git a/ar.c b/ar.c
index fb0d988..fb0aae1 100644 (file)
--- a/ar.c
+++ b/ar.c
-/***********************************************************\r
-       ar.c -- main file\r
-***********************************************************/\r
-\r
-static char *usage =\r
-       "ar -- compression archiver -- written by Haruhiko Okumura\n"\r
-       "  PC-VAN:SCIENCE        CompuServe:74050,1022\n"\r
-       "  NIFTY-Serve:PAF01022  INTERNET:74050.1022@compuserve.com\n"\r
-       "Usage: ar command archive [file ...]\n"\r
-       "Commands:\n"\r
-       "   a: Add files to archive (replace if present)\n"\r
-       "   x: Extract files from archive\n"\r
-       "   r: Replace files in archive\n"\r
-       "   d: Delete files from archive\n"\r
-       "   p: Print files on standard output\n"\r
-       "   l: List contents of archive\n"\r
-       "If no files are named, all files in archive are processed,\n"\r
-       "   except for commands 'a' and 'd'.\n"\r
-       "You may copy, distribute, and rewrite this program freely.\n";\r
-\r
-/***********************************************************\r
-\r
-Structure of archive block (low order byte first):\r
------preheader\r
- 1     basic header size\r
-               = 25 + strlen(filename) (= 0 if end of archive)\r
- 1     basic header algebraic sum (mod 256)\r
------basic header\r
- 5     method ("-lh0-" = stored, "-lh5-" = compressed)\r
- 4     compressed size (including extended headers)\r
- 4     original size\r
- 4     not used\r
- 1     0x20\r
- 1     0x01\r
- 1     filename length (x)\r
- x     filename\r
- 2     original file's CRC\r
- 1     0x20\r
- 2     first extended header size (0 if none)\r
------first extended header, etc.\r
------compressed file\r
-\r
-***********************************************************/\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include "ar.h"\r
-\r
-#define FNAME_MAX (255 - 25) /* max strlen(filename) */\r
-#define namelen  header[19]\r
-#define filename ((char *)&header[20])\r
-\r
-int unpackable;            /* global, set in io.c */\r
-ulong compsize, origsize;  /* global */\r
-\r
-static uchar buffer[DICSIZ];\r
-static uchar header[255];\r
-static uchar headersize, headersum;\r
-static uint  file_crc;\r
-static char  *temp_name;\r
-\r
-static uint ratio(ulong a, ulong b)  /* [(1000a + [b/2]) / b] */\r
-{\r
-       int i;\r
-\r
-       for (i = 0; i < 3; i++)\r
-               if (a <= ULONG_MAX / 10) a *= 10;  else b /= 10;\r
-       if ((ulong)(a + (b >> 1)) < a) {  a >>= 1;  b >>= 1;  }\r
-       if (b == 0) return 0;\r
-       return (uint)((a + (b >> 1)) / b);\r
-}\r
-\r
-static void put_to_header(int i, int n, ulong x)\r
-{\r
-       while (--n >= 0) {\r
-               header[i++] = (uchar)((uint)x & 0xFF);  x >>= 8;\r
-       }\r
-}\r
-\r
-static ulong get_from_header(int i, int n)\r
-{\r
-       ulong s;\r
-\r
-       s = 0;\r
-       while (--n >= 0) s = (s << 8) + header[i + n];  /* little endian */\r
-       return s;\r
-}\r
-\r
-static uint calc_headersum(void)\r
-{\r
-       int i;\r
-       uint s;\r
-\r
-       s = 0;\r
-       for (i = 0; i < headersize; i++) s += header[i];\r
-       return s & 0xFF;\r
-}\r
-\r
-static int read_header(void)\r
-{\r
-       headersize = (uchar) fgetc(arcfile);\r
-       if (headersize == 0) return 0;  /* end of archive */\r
-       headersum  = (uchar) fgetc(arcfile);\r
-       fread_crc(header, headersize, arcfile);  /* CRC not used */\r
-       if (calc_headersum() != headersum) error("Header sum error");\r
-       compsize = get_from_header(5, 4);\r
-       origsize = get_from_header(9, 4);\r
-       file_crc = (uint)get_from_header(headersize - 5, 2);\r
-       filename[namelen] = '\0';\r
-       return 1;  /* success */\r
-}\r
-\r
-static void write_header(void)\r
-{\r
-       fputc(headersize, outfile);\r
-       /* We've destroyed file_crc by null-terminating filename. */\r
-       put_to_header(headersize - 5, 2, (ulong)file_crc);\r
-       fputc(calc_headersum(), outfile);\r
-       fwrite_crc(header, headersize, outfile);  /* CRC not used */\r
-}\r
-\r
-static void skip(void)\r
-{\r
-       fseek(arcfile, compsize, SEEK_CUR);\r
-}\r
-\r
-static void copy(void)\r
-{\r
-       uint n;\r
-\r
-       write_header();\r
-       while (compsize != 0) {\r
-               n = (uint)((compsize > DICSIZ) ? DICSIZ : compsize);\r
-               if (fread ((char *)buffer, 1, n, arcfile) != n)\r
-                       error("Can't read");\r
-               if (fwrite((char *)buffer, 1, n, outfile) != n)\r
-                       error("Can't write");\r
-               compsize -= n;\r
-       }\r
-}\r
-\r
-static void store(void)\r
-{\r
-       uint n;\r
-\r
-       origsize = 0;\r
-       crc = INIT_CRC;\r
-       while ((n = fread((char *)buffer, 1, DICSIZ, infile)) != 0) {\r
-               fwrite_crc(buffer, n, outfile);  origsize += n;\r
-       }\r
-       compsize = origsize;\r
-}\r
-\r
-static int add(int replace_flag)\r
-{\r
-       long headerpos, arcpos;\r
-       uint r;\r
-\r
-       if ((infile = fopen(filename, "rb")) == NULL) {\r
-               fprintf(stderr, "Can't open %s\n", filename);\r
-               return 0;  /* failure */\r
-       }\r
-       if (replace_flag) {\r
-               printf("Replacing %s ", filename);  skip();\r
-       } else\r
-               printf("Adding %s ", filename);\r
-       headerpos = ftell(outfile);\r
-       namelen = strlen(filename);\r
-       headersize = 25 + namelen;\r
-       memcpy(header, "-lh5-", 5);  /* compress */\r
-       write_header();  /* temporarily */\r
-       arcpos = ftell(outfile);\r
-       origsize = compsize = 0;  unpackable = 0;\r
-       crc = INIT_CRC;  encode();\r
-       if (unpackable) {\r
-               header[3] = '0';  /* store */\r
-               rewind(infile);\r
-               fseek(outfile, arcpos, SEEK_SET);\r
-               store();\r
-       }\r
-       file_crc = crc ^ INIT_CRC;\r
-       fclose(infile);\r
-       put_to_header(5, 4, compsize);\r
-       put_to_header(9, 4, origsize);\r
-       memcpy(header + 13, "\0\0\0\0\x20\x01", 6);\r
-       memcpy(header + headersize - 3, "\x20\0\0", 3);\r
-       fseek(outfile, headerpos, SEEK_SET);\r
-       write_header();  /* true header */\r
-       fseek(outfile, 0L, SEEK_END);\r
-       r = ratio(compsize, origsize);\r
-       printf(" %d.%d%%\n", r / 10, r % 10);\r
-       return 1;  /* success */\r
-}\r
-\r
-int get_line(char *s, int n)\r
-{\r
-       int i, c;\r
-\r
-       i = 0;\r
-       while ((c = getchar()) != EOF && c != '\n')\r
-               if (i < n) s[i++] = (char)c;\r
-       s[i] = '\0';\r
-       return i;\r
-}\r
-\r
-static void extract(int to_file)\r
-{\r
-       int n, method;\r
-       uint ext_headersize;\r
-\r
-       if (to_file) {\r
-               while ((outfile = fopen(filename, "wb")) == NULL) {\r
-                       fprintf(stderr, "Can't open %s\nNew filename: ", filename);\r
-                       if (get_line(filename, FNAME_MAX) == 0) {\r
-                               fprintf(stderr, "Not extracted\n");\r
-                               skip();  return;\r
-                       }\r
-                       namelen = strlen(filename);\r
-               }\r
-               printf("Extracting %s ", filename);\r
-       } else {\r
-               outfile = stdout;\r
-               printf("===== %s =====\n", filename);\r
-       }\r
-       crc = INIT_CRC;\r
-       method = header[3];  header[3] = ' ';\r
-       if (! strchr("045", method) || memcmp("-lh -", header, 5)) {\r
-               fprintf(stderr, "Unknown method: %u\n", method);\r
-               skip();\r
-       } else {\r
-               ext_headersize = (uint)get_from_header(headersize - 2, 2);\r
-               while (ext_headersize != 0) {\r
-                       fprintf(stderr, "There's an extended header of size %u.\n",\r
-                               ext_headersize);\r
-                       compsize -= ext_headersize;\r
-                       if (fseek(arcfile, ext_headersize - 2, SEEK_CUR))\r
-                               error("Can't read");\r
-                       ext_headersize = fgetc(arcfile);\r
-                       ext_headersize += (uint)fgetc(arcfile) << 8;\r
-               }\r
-               crc = INIT_CRC;\r
-               if (method != '0') decode_start();\r
-               while (origsize != 0) {\r
-                       n = (uint)((origsize > DICSIZ) ? DICSIZ : origsize);\r
-                       if (method != '0') decode(n, buffer);\r
-                       else if (fread((char *)buffer, 1, n, arcfile) != n)\r
-                               error("Can't read");\r
-                       fwrite_crc(buffer, n, outfile);\r
-                       if (outfile != stdout) putc('.', stderr);\r
-                       origsize -= n;\r
-               }\r
-       }\r
-       if (to_file) fclose(outfile);  else outfile = NULL;\r
-       printf("\n");\r
-       if ((crc ^ INIT_CRC) != file_crc)\r
-               fprintf(stderr, "CRC error\n");\r
-}\r
-\r
-static void list_start(void)\r
-{\r
-       printf("Filename         Original Compressed Ratio CRC Method\n");\r
-}\r
-\r
-static void list(void)\r
-{\r
-       uint r;\r
-\r
-       printf("%-14s", filename);\r
-       if (namelen > 14) printf("\n              ");\r
-       r = ratio(compsize, origsize);\r
-       printf(" %10lu %10lu %u.%03u %04X %5.5s\n",\r
-               origsize, compsize, r / 1000, r % 1000, file_crc, header);\r
-}\r
-\r
-static int match(char *s1, char *s2)\r
-{\r
-       for ( ; ; ) {\r
-               while (*s2 == '*' || *s2 == '?') {\r
-                       if (*s2++ == '*')\r
-                               while (*s1 && *s1 != *s2) s1++;\r
-                       else if (*s1 == 0)\r
-                               return 0;\r
-                       else s1++;\r
-               }\r
-               if (*s1 != *s2) return 0;\r
-               if (*s1 == 0  ) return 1;\r
-               s1++;  s2++;\r
-       }\r
-}\r
-\r
-static int search(int argc, char *argv[])\r
-{\r
-       int i;\r
-\r
-       if (argc == 3) return 1;\r
-       for (i = 3; i < argc; i++)\r
-               if (match(filename, argv[i])) return 1;\r
-       return 0;\r
-}\r
-\r
-static void exitfunc(void)\r
-{\r
-       fclose(outfile);  remove(temp_name);\r
-}\r
-\r
-int main(int argc, char *argv[])\r
-{\r
-       int i, j, cmd, count, nfiles, found, done;\r
-\r
-       /* Check command line arguments. */\r
-       if (argc < 3\r
-        || argv[1][1] != '\0'\r
-        || ! strchr("AXRDPL", cmd = toupper(argv[1][0]))\r
-        || (argc == 3 && strchr("AD", cmd)))\r
-               error(usage);\r
-\r
-       /* Wildcards used? */\r
-       for (i = 3; i < argc; i++)\r
-               if (strpbrk(argv[i], "*?")) break;\r
-       if (cmd == 'A' && i < argc)\r
-               error("Filenames may not contain '*' and '?'");\r
-       if (i < argc) nfiles = -1;  /* contains wildcards */\r
-       else nfiles = argc - 3;     /* number of files to process */\r
-\r
-       /* Open archive. */\r
-       arcfile = fopen(argv[2], "rb");\r
-       if (arcfile == NULL && cmd != 'A')\r
-               error("Can't open archive '%s'", argv[2]);\r
-\r
-       /* Open temporary file. */\r
-       if (strchr("ARD", cmd)) {\r
-               temp_name = tmpnam(NULL);\r
-               outfile = fopen(temp_name, "wb");\r
-               if (outfile == NULL)\r
-                       error("Can't open temporary file");\r
-               atexit(exitfunc);\r
-       } else temp_name = NULL;\r
-\r
-       make_crctable();  count = done = 0;\r
-\r
-       if (cmd == 'A') {\r
-               for (i = 3; i < argc; i++) {\r
-                       for (j = 3; j < i; j++)\r
-                               if (strcmp(argv[j], argv[i]) == 0) break;\r
-                       if (j == i) {\r
-                               strcpy(filename, argv[i]);\r
-                               if (add(0)) count++;  else argv[i][0] = 0;\r
-                       } else nfiles--;\r
-               }\r
-               if (count == 0 || arcfile == NULL) done = 1;\r
-       }\r
-\r
-       while (! done && read_header()) {\r
-               found = search(argc, argv);\r
-               switch (cmd) {\r
-               case 'R':\r
-                       if (found) {\r
-                               if (add(1)) count++;  else copy();\r
-                       } else copy();\r
-                       break;\r
-               case 'A':  case 'D':\r
-                       if (found) {\r
-                               count += (cmd == 'D');  skip();\r
-                       } else copy();\r
-                       break;\r
-               case 'X':  case 'P':\r
-                       if (found) {\r
-                               extract(cmd == 'X');\r
-                               if (++count == nfiles) done = 1;\r
-                       } else skip();\r
-                       break;\r
-               case 'L':\r
-                       if (found) {\r
-                               if (count == 0) list_start();\r
-                               list();\r
-                               if (++count == nfiles) done = 1;\r
-                       }\r
-                       skip();  break;\r
-               }\r
-       }\r
-\r
-       if (temp_name != NULL && count != 0) {\r
-               fputc(0, outfile);  /* end of archive */\r
-               if (ferror(outfile) || fclose(outfile) == EOF)\r
-                       error("Can't write");\r
-               remove(argv[2]);  rename(temp_name, argv[2]);\r
-       }\r
-\r
-       printf("  %d files\n", count);\r
-       return EXIT_SUCCESS;\r
-}\r
+/***********************************************************
+       ar.c -- main file
+***********************************************************/
+
+static char *usage =
+    "ar -- compression archiver -- written by Haruhiko Okumura\n"
+    "  PC-VAN:SCIENCE        CompuServe:74050,1022\n"
+    "  NIFTY-Serve:PAF01022  INTERNET:74050.1022@compuserve.com\n"
+    "Usage: ar command archive [file ...]\n"
+    "Commands:\n"
+    "   a: Add files to archive (replace if present)\n"
+    "   x: Extract files from archive\n"
+    "   r: Replace files in archive\n"
+    "   d: Delete files from archive\n"
+    "   p: Print files on standard output\n"
+    "   l: List contents of archive\n"
+    "If no files are named, all files in archive are processed,\n"
+    "   except for commands 'a' and 'd'.\n"
+    "You may copy, distribute, and rewrite this program freely.\n";
+
+/***********************************************************
+
+Structure of archive block (low order byte first):
+-----preheader
+ 1     basic header size
+               = 25 + strlen(filename) (= 0 if end of archive)
+ 1     basic header algebraic sum (mod 256)
+-----basic header
+ 5     method ("-lh0-" = stored, "-lh5-" = compressed)
+ 4     compressed size (including extended headers)
+ 4     original size
+ 4     not used
+ 1     0x20
+ 1     0x01
+ 1     filename length (x)
+ x     filename
+ 2     original file's CRC
+ 1     0x20
+ 2     first extended header size (0 if none)
+-----first extended header, etc.
+-----compressed file
+
+***********************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "ar.h"
+
+#define FNAME_MAX (255 - 25)    /* max strlen(filename) */
+#define namelen  header[19]
+#define filename ((char *)&header[20])
+
+int unpackable;                 /* global, set in io.c */
+ulong compsize, origsize;       /* global */
+
+static uchar buffer[DICSIZ];
+static uchar header[255];
+static uchar headersize, headersum;
+static uint file_crc;
+static char *temp_name;
+
+static uint
+ratio(ulong a, ulong b)
+{                               /* [(1000a + [b/2]) / b] */
+    int i;
+
+    for (i = 0; i < 3; i++)
+        if (a <= ULONG_MAX / 10)
+            a *= 10;
+        else
+            b /= 10;
+    if ((ulong) (a + (b >> 1)) < a) {
+        a >>= 1;
+        b >>= 1;
+    }
+    if (b == 0)
+        return 0;
+    return (uint) ((a + (b >> 1)) / b);
+}
+
+static void
+put_to_header(int i, int n, ulong x)
+{
+    while (--n >= 0) {
+        header[i++] = (uchar) ((uint) x & 0xFF);
+        x >>= 8;
+    }
+}
+
+static ulong
+get_from_header(int i, int n)
+{
+    ulong s;
+
+    s = 0;
+    while (--n >= 0)
+        s = (s << 8) + header[i + n];   /* little endian */
+    return s;
+}
+
+static uint
+calc_headersum(void)
+{
+    int i;
+    uint s;
+
+    s = 0;
+    for (i = 0; i < headersize; i++)
+        s += header[i];
+    return s & 0xFF;
+}
+
+static int
+read_header(void)
+{
+    headersize = (uchar) fgetc(arcfile);
+    if (headersize == 0)
+        return 0;               /* end of archive */
+    headersum = (uchar) fgetc(arcfile);
+    fread_crc(header, headersize, arcfile);     /* CRC not used */
+    if (calc_headersum() != headersum)
+        error("Header sum error");
+    compsize = get_from_header(5, 4);
+    origsize = get_from_header(9, 4);
+    file_crc = (uint) get_from_header(headersize - 5, 2);
+    filename[namelen] = '\0';
+    return 1;                   /* success */
+}
+
+static void
+write_header(void)
+{
+    fputc(headersize, outfile);
+    /* We've destroyed file_crc by null-terminating filename. */
+    put_to_header(headersize - 5, 2, (ulong) file_crc);
+    fputc(calc_headersum(), outfile);
+    fwrite_crc(header, headersize, outfile);    /* CRC not used */
+}
+
+static void
+skip(void)
+{
+    fseek(arcfile, compsize, SEEK_CUR);
+}
+
+static void
+copy(void)
+{
+    uint n;
+
+    write_header();
+    while (compsize != 0) {
+        n = (uint) ((compsize > DICSIZ) ? DICSIZ : compsize);
+        if (fread((char *) buffer, 1, n, arcfile) != n)
+            error("Can't read");
+        if (fwrite((char *) buffer, 1, n, outfile) != n)
+            error("Can't write");
+        compsize -= n;
+    }
+}
+
+static void
+store(void)
+{
+    uint n;
+
+    origsize = 0;
+    crc = INIT_CRC;
+    while ((n = fread((char *) buffer, 1, DICSIZ, infile)) != 0) {
+        fwrite_crc(buffer, n, outfile);
+        origsize += n;
+    }
+    compsize = origsize;
+}
+
+static int
+add(int replace_flag)
+{
+    long headerpos, arcpos;
+    uint r;
+
+    if ((infile = fopen(filename, "rb")) == NULL) {
+        fprintf(stderr, "Can't open %s\n", filename);
+        return 0;               /* failure */
+    }
+    if (replace_flag) {
+        printf("Replacing %s ", filename);
+        skip();
+    }
+    else
+        printf("Adding %s ", filename);
+    headerpos = ftell(outfile);
+    namelen = strlen(filename);
+    headersize = 25 + namelen;
+    memcpy(header, "-lh5-", 5); /* compress */
+    write_header();             /* temporarily */
+    arcpos = ftell(outfile);
+    origsize = compsize = 0;
+    unpackable = 0;
+    crc = INIT_CRC;
+    encode();
+    if (unpackable) {
+        header[3] = '0';        /* store */
+        rewind(infile);
+        fseek(outfile, arcpos, SEEK_SET);
+        store();
+    }
+    file_crc = crc ^ INIT_CRC;
+    fclose(infile);
+    put_to_header(5, 4, compsize);
+    put_to_header(9, 4, origsize);
+    memcpy(header + 13, "\0\0\0\0\x20\x01", 6);
+    memcpy(header + headersize - 3, "\x20\0\0", 3);
+    fseek(outfile, headerpos, SEEK_SET);
+    write_header();             /* true header */
+    fseek(outfile, 0L, SEEK_END);
+    r = ratio(compsize, origsize);
+    printf(" %d.%d%%\n", r / 10, r % 10);
+    return 1;                   /* success */
+}
+
+int
+get_line(char *s, int n)
+{
+    int i, c;
+
+    i = 0;
+    while ((c = getchar()) != EOF && c != '\n')
+        if (i < n)
+            s[i++] = (char) c;
+    s[i] = '\0';
+    return i;
+}
+
+static void
+extract(int to_file)
+{
+    int n, method;
+    uint ext_headersize;
+
+    if (to_file) {
+        while ((outfile = fopen(filename, "wb")) == NULL) {
+            fprintf(stderr, "Can't open %s\nNew filename: ", filename);
+            if (get_line(filename, FNAME_MAX) == 0) {
+                fprintf(stderr, "Not extracted\n");
+                skip();
+                return;
+            }
+            namelen = strlen(filename);
+        }
+        printf("Extracting %s ", filename);
+    }
+    else {
+        outfile = stdout;
+        printf("===== %s =====\n", filename);
+    }
+    crc = INIT_CRC;
+    method = header[3];
+    header[3] = ' ';
+    if (!strchr("045", method) || memcmp("-lh -", header, 5)) {
+        fprintf(stderr, "Unknown method: %u\n", method);
+        skip();
+    }
+    else {
+        ext_headersize = (uint) get_from_header(headersize - 2, 2);
+        while (ext_headersize != 0) {
+            fprintf(stderr, "There's an extended header of size %u.\n",
+                    ext_headersize);
+            compsize -= ext_headersize;
+            if (fseek(arcfile, ext_headersize - 2, SEEK_CUR))
+                error("Can't read");
+            ext_headersize = fgetc(arcfile);
+            ext_headersize += (uint) fgetc(arcfile) << 8;
+        }
+        crc = INIT_CRC;
+        if (method != '0')
+            decode_start();
+        while (origsize != 0) {
+            n = (uint) ((origsize > DICSIZ) ? DICSIZ : origsize);
+            if (method != '0')
+                decode(n, buffer);
+            else if (fread((char *) buffer, 1, n, arcfile) != n)
+                error("Can't read");
+            fwrite_crc(buffer, n, outfile);
+            if (outfile != stdout)
+                putc('.', stderr);
+            origsize -= n;
+        }
+    }
+    if (to_file)
+        fclose(outfile);
+    else
+        outfile = NULL;
+    printf("\n");
+    if ((crc ^ INIT_CRC) != file_crc)
+        fprintf(stderr, "CRC error\n");
+}
+
+static void
+list_start(void)
+{
+    printf("Filename         Original Compressed Ratio CRC Method\n");
+}
+
+static void
+list(void)
+{
+    uint r;
+
+    printf("%-14s", filename);
+    if (namelen > 14)
+        printf("\n              ");
+    r = ratio(compsize, origsize);
+    printf(" %10lu %10lu %u.%03u %04X %5.5s\n",
+           origsize, compsize, r / 1000, r % 1000, file_crc, header);
+}
+
+static int
+match(char *s1, char *s2)
+{
+    for (;;) {
+        while (*s2 == '*' || *s2 == '?') {
+            if (*s2++ == '*')
+                while (*s1 && *s1 != *s2)
+                    s1++;
+            else if (*s1 == 0)
+                return 0;
+            else
+                s1++;
+        }
+        if (*s1 != *s2)
+            return 0;
+        if (*s1 == 0)
+            return 1;
+        s1++;
+        s2++;
+    }
+}
+
+static int
+search(int argc, char *argv[])
+{
+    int i;
+
+    if (argc == 3)
+        return 1;
+    for (i = 3; i < argc; i++)
+        if (match(filename, argv[i]))
+            return 1;
+    return 0;
+}
+
+static void
+exitfunc(void)
+{
+    fclose(outfile);
+    remove(temp_name);
+}
+
+int
+main(int argc, char *argv[])
+{
+    int i, j, cmd, count, nfiles, found, done;
+
+    /* Check command line arguments. */
+    if (argc < 3
+        || argv[1][1] != '\0' || !strchr("AXRDPL", cmd = toupper(argv[1][0]))
+        || (argc == 3 && strchr("AD", cmd)))
+        error(usage);
+
+    /* Wildcards used? */
+    for (i = 3; i < argc; i++)
+        if (strpbrk(argv[i], "*?"))
+            break;
+    if (cmd == 'A' && i < argc)
+        error("Filenames may not contain '*' and '?'");
+    if (i < argc)
+        nfiles = -1;            /* contains wildcards */
+    else
+        nfiles = argc - 3;      /* number of files to process */
+
+    /* Open archive. */
+    arcfile = fopen(argv[2], "rb");
+    if (arcfile == NULL && cmd != 'A')
+        error("Can't open archive '%s'", argv[2]);
+
+    /* Open temporary file. */
+    if (strchr("ARD", cmd)) {
+        temp_name = tmpnam(NULL);
+        outfile = fopen(temp_name, "wb");
+        if (outfile == NULL)
+            error("Can't open temporary file");
+        atexit(exitfunc);
+    }
+    else
+        temp_name = NULL;
+
+    make_crctable();
+    count = done = 0;
+
+    if (cmd == 'A') {
+        for (i = 3; i < argc; i++) {
+            for (j = 3; j < i; j++)
+                if (strcmp(argv[j], argv[i]) == 0)
+                    break;
+            if (j == i) {
+                strcpy(filename, argv[i]);
+                if (add(0))
+                    count++;
+                else
+                    argv[i][0] = 0;
+            }
+            else
+                nfiles--;
+        }
+        if (count == 0 || arcfile == NULL)
+            done = 1;
+    }
+
+    while (!done && read_header()) {
+        found = search(argc, argv);
+        switch (cmd) {
+        case 'R':
+            if (found) {
+                if (add(1))
+                    count++;
+                else
+                    copy();
+            }
+            else
+                copy();
+            break;
+        case 'A':
+        case 'D':
+            if (found) {
+                count += (cmd == 'D');
+                skip();
+            }
+            else
+                copy();
+            break;
+        case 'X':
+        case 'P':
+            if (found) {
+                extract(cmd == 'X');
+                if (++count == nfiles)
+                    done = 1;
+            }
+            else
+                skip();
+            break;
+        case 'L':
+            if (found) {
+                if (count == 0)
+                    list_start();
+                list();
+                if (++count == nfiles)
+                    done = 1;
+            }
+            skip();
+            break;
+        }
+    }
+
+    if (temp_name != NULL && count != 0) {
+        fputc(0, outfile);      /* end of archive */
+        if (ferror(outfile) || fclose(outfile) == EOF)
+            error("Can't write");
+        remove(argv[2]);
+        rename(temp_name, argv[2]);
+    }
+
+    printf("  %d files\n", count);
+    return EXIT_SUCCESS;
+}
diff --git a/ar.h b/ar.h
index a271541..95b285f 100644 (file)
--- a/ar.h
+++ b/ar.h
@@ -1,71 +1,70 @@
-/***********************************************************\r
-       ar.h\r
-***********************************************************/\r
-#include <stdio.h>\r
-#include <limits.h>\r
-typedef unsigned char  uchar;   /*  8 bits or more */\r
-typedef unsigned int   uint;    /* 16 bits or more */\r
-typedef unsigned short ushort;  /* 16 bits or more */\r
-typedef unsigned long  ulong;   /* 32 bits or more */\r
-\r
-/* ar.c */\r
-\r
-extern int unpackable;\r
-extern ulong origsize, compsize;\r
-\r
-/* io.c */\r
-\r
-#define INIT_CRC  0  /* CCITT: 0xFFFF */\r
-extern FILE *arcfile, *infile, *outfile;\r
-extern uint crc, bitbuf;\r
-#define BITBUFSIZ (CHAR_BIT * sizeof bitbuf)\r
-\r
-void error(char *fmt, ...);\r
-void make_crctable(void);\r
-void fillbuf(int n);\r
-uint getbits(int n);\r
-/* void putbit(int bit); */\r
-void putbits(int n, uint x);\r
-int fread_crc(uchar *p, int n, FILE *f);\r
-void fwrite_crc(uchar *p, int n, FILE *f);\r
-void init_getbits(void);\r
-void init_putbits(void);\r
-\r
-/* encode.c and decode.c */\r
-\r
-#define DICBIT    13    /* 12(-lh4-) or 13(-lh5-) */\r
-#define DICSIZ (1U << DICBIT)\r
-#define MATCHBIT   8    /* bits for MAXMATCH - THRESHOLD */\r
-#define MAXMATCH 256    /* formerly F (not more than UCHAR_MAX + 1) */\r
-#define THRESHOLD  3    /* choose optimal value */\r
-#define PERC_FLAG 0x8000U\r
-\r
-void encode(void);\r
-void decode_start(void);\r
-void decode(uint count, uchar text[]);\r
-\r
-/* huf.c */\r
-\r
-#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)\r
-       /* alphabet = {0, 1, 2, ..., NC - 1} */\r
-#define CBIT 9  /* $\lfloor \log_2 NC \rfloor + 1$ */\r
-#define CODE_BIT  16  /* codeword length */\r
-\r
-extern ushort left[], right[];\r
-\r
-void huf_encode_start(void);\r
-void huf_decode_start(void);\r
-uint decode_c(void);\r
-uint decode_p(void);\r
-void output(uint c, uint p);\r
-void huf_encode_end(void);\r
-\r
-/* maketbl.c */\r
-\r
-void make_table(int nchar, uchar bitlen[],\r
-                               int tablebits, ushort table[]);\r
-\r
-/* maketree.c */\r
-\r
-int make_tree(int nparm, ushort freqparm[],\r
-                               uchar lenparm[], ushort codeparm[]);\r
+/***********************************************************
+       ar.h
+***********************************************************/
+#include <stdio.h>
+#include <limits.h>
+typedef unsigned char uchar;    /*  8 bits or more */
+typedef unsigned int uint;      /* 16 bits or more */
+typedef unsigned short ushort;  /* 16 bits or more */
+typedef unsigned long ulong;    /* 32 bits or more */
+
+/* ar.c */
+
+extern int unpackable;
+extern ulong origsize, compsize;
+
+/* io.c */
+
+#define INIT_CRC  0             /* CCITT: 0xFFFF */
+extern FILE *arcfile, *infile, *outfile;
+extern uint crc, bitbuf;
+#define BITBUFSIZ (CHAR_BIT * sizeof bitbuf)
+
+void error(char *fmt, ...);
+void make_crctable(void);
+void fillbuf(int n);
+uint getbits(int n);
+/* void putbit(int bit); */
+void putbits(int n, uint x);
+int fread_crc(uchar * p, int n, FILE * f);
+void fwrite_crc(uchar * p, int n, FILE * f);
+void init_getbits(void);
+void init_putbits(void);
+
+/* encode.c and decode.c */
+
+#define DICBIT    13            /* 12(-lh4-) or 13(-lh5-) */
+#define DICSIZ (1U << DICBIT)
+#define MATCHBIT   8            /* bits for MAXMATCH - THRESHOLD */
+#define MAXMATCH 256            /* formerly F (not more than UCHAR_MAX + 1) */
+#define THRESHOLD  3            /* choose optimal value */
+#define PERC_FLAG 0x8000U
+
+void encode(void);
+void decode_start(void);
+void decode(uint count, uchar text[]);
+
+/* huf.c */
+
+#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
+        /* alphabet = {0, 1, 2, ..., NC - 1} */
+#define CBIT 9                  /* $\lfloor \log_2 NC \rfloor + 1$ */
+#define CODE_BIT  16            /* codeword length */
+
+extern ushort left[], right[];
+
+void huf_encode_start(void);
+void huf_decode_start(void);
+uint decode_c(void);
+uint decode_p(void);
+void output(uint c, uint p);
+void huf_encode_end(void);
+
+/* maketbl.c */
+
+void make_table(int nchar, uchar bitlen[], int tablebits, ushort table[]);
+
+/* maketree.c */
+
+int make_tree(int nparm, ushort freqparm[],
+              uchar lenparm[], ushort codeparm[]);
index 8f4a6fb..2259de2 100644 (file)
--- a/decode.c
+++ b/decode.c
@@ -1,47 +1,53 @@
-/***********************************************************\r
-       decode.c\r
-***********************************************************/\r
-#include "ar.h"\r
-\r
-static int j;  /* remaining bytes to copy */\r
-\r
-void decode_start(void)\r
-{\r
-       huf_decode_start();\r
-       j = 0;\r
-}\r
-\r
-void decode(uint count, uchar buffer[])\r
-       /* The calling function must keep the number of\r
-          bytes to be processed.  This function decodes\r
-          either 'count' bytes or 'DICSIZ' bytes, whichever\r
-          is smaller, into the array 'buffer[]' of size\r
-          'DICSIZ' or more.\r
-          Call decode_start() once for each new file\r
-          before calling this function. */\r
-{\r
-       static uint i;\r
-       uint r, c;\r
-\r
-       r = 0;\r
-       while (--j >= 0) {\r
-               buffer[r] = buffer[i];\r
-               i = (i + 1) & (DICSIZ - 1);\r
-               if (++r == count) return;\r
-       }\r
-       for ( ; ; ) {\r
-               c = decode_c();\r
-               if (c <= UCHAR_MAX) {\r
-                       buffer[r] = c;\r
-                       if (++r == count) return;\r
-               } else {\r
-                       j = c - (UCHAR_MAX + 1 - THRESHOLD);\r
-                       i = (r - decode_p() - 1) & (DICSIZ - 1);\r
-                       while (--j >= 0) {\r
-                               buffer[r] = buffer[i];\r
-                               i = (i + 1) & (DICSIZ - 1);\r
-                               if (++r == count) return;\r
-                       }\r
-               }\r
-       }\r
-}\r
+/***********************************************************
+       decode.c
+***********************************************************/
+#include "ar.h"
+
+static int j;                   /* remaining bytes to copy */
+
+void
+decode_start(void)
+{
+    huf_decode_start();
+    j = 0;
+}
+
+void
+decode(uint count, uchar buffer[])
+        /* The calling function must keep the number of
+           bytes to be processed.  This function decodes
+           either 'count' bytes or 'DICSIZ' bytes, whichever
+           is smaller, into the array 'buffer[]' of size
+           'DICSIZ' or more.
+           Call decode_start() once for each new file
+           before calling this function. */
+{
+    static uint i;
+    uint r, c;
+
+    r = 0;
+    while (--j >= 0) {
+        buffer[r] = buffer[i];
+        i = (i + 1) & (DICSIZ - 1);
+        if (++r == count)
+            return;
+    }
+    for (;;) {
+        c = decode_c();
+        if (c <= UCHAR_MAX) {
+            buffer[r] = c;
+            if (++r == count)
+                return;
+        }
+        else {
+            j = c - (UCHAR_MAX + 1 - THRESHOLD);
+            i = (r - decode_p() - 1) & (DICSIZ - 1);
+            while (--j >= 0) {
+                buffer[r] = buffer[i];
+                i = (i + 1) & (DICSIZ - 1);
+                if (++r == count)
+                    return;
+            }
+        }
+    }
+}
index 92483ca..05cc0db 100644 (file)
--- a/encode.c
+++ b/encode.c
-/***********************************************************\r
-       encode.c -- sliding dictionary with percolating update\r
-***********************************************************/\r
-#include "ar.h"\r
-#include <stdlib.h>\r
-#include <string.h>  /* memmove() */\r
-\r
-#define PERCOLATE  1\r
-#define NIL        0\r
-#define MAX_HASH_VAL (3 * DICSIZ + (DICSIZ / 512 + 1) * UCHAR_MAX)\r
-\r
-typedef short node;\r
-\r
-static uchar *text, *childcount;\r
-static node pos, matchpos, avail,\r
-       *position, *parent, *prev, *next = NULL;\r
-static int remainder, matchlen;\r
-\r
-#if MAXMATCH <= (UCHAR_MAX + 1)\r
-       static uchar *level;\r
-#else\r
-       static ushort *level;\r
-#endif\r
-\r
-static void allocate_memory(void)\r
-{\r
-       if (next != NULL) return;\r
-    text = malloc(DICSIZ * 2 + MAXMATCH);\r
-       level      = malloc((DICSIZ + UCHAR_MAX + 1) * sizeof(*level));\r
-       childcount = malloc((DICSIZ + UCHAR_MAX + 1) * sizeof(*childcount));\r
-       #if PERCOLATE\r
-         position = malloc((DICSIZ + UCHAR_MAX + 1) * sizeof(*position));\r
-       #else\r
-         position = malloc(DICSIZ * sizeof(*position));\r
-       #endif\r
-       parent     = malloc(DICSIZ * 2 * sizeof(*parent));\r
-       prev       = malloc(DICSIZ * 2 * sizeof(*prev));\r
-       next       = malloc((MAX_HASH_VAL + 1) * sizeof(*next));\r
-       if (next == NULL) error("Out of memory.");\r
-}\r
-\r
-static void init_slide(void)\r
-{\r
-       node i;\r
-\r
-       for (i = DICSIZ; i <= DICSIZ + UCHAR_MAX; i++) {\r
-               level[i] = 1;\r
-               #if PERCOLATE\r
-                       position[i] = NIL;  /* sentinel */\r
-               #endif\r
-       }\r
-       for (i = DICSIZ; i < DICSIZ * 2; i++) parent[i] = NIL;\r
-       avail = 1;\r
-       for (i = 1; i < DICSIZ - 1; i++) next[i] = i + 1;\r
-       next[DICSIZ - 1] = NIL;\r
-       for (i = DICSIZ * 2; i <= MAX_HASH_VAL; i++) next[i] = NIL;\r
-}\r
-\r
-#define HASH(p, c) ((p) + ((c) << (DICBIT - 9)) + DICSIZ * 2)\r
-\r
-static node child(node q, uchar c)\r
-       /* q's child for character c (NIL if not found) */\r
-{\r
-       node r;\r
-\r
-       r = next[HASH(q, c)];\r
-       parent[NIL] = q;  /* sentinel */\r
-       while (parent[r] != q) r = next[r];\r
-       return r;\r
-}\r
-\r
-static void makechild(node q, uchar c, node r)\r
-       /* Let r be q's child for character c. */\r
-{\r
-       node h, t;\r
-\r
-       h = HASH(q, c);\r
-       t = next[h];  next[h] = r;  next[r] = t;\r
-       prev[t] = r;  prev[r] = h;\r
-       parent[r] = q;  childcount[q]++;\r
-}\r
-\r
-void split(node old)\r
-{\r
-       node new, t;\r
-\r
-       new = avail;  avail = next[new];  childcount[new] = 0;\r
-       t = prev[old];  prev[new] = t;  next[t] = new;\r
-       t = next[old];  next[new] = t;  prev[t] = new;\r
-       parent[new] = parent[old];\r
-       level[new] = matchlen;\r
-       position[new] = pos;\r
-       makechild(new, text[matchpos + matchlen], old);\r
-       makechild(new, text[pos + matchlen], pos);\r
-}\r
-\r
-static void insert_node(void)\r
-{\r
-       node q, r, j, t;\r
-       uchar c, *t1, *t2;\r
-\r
-       if (matchlen >= 4) {\r
-               matchlen--;\r
-               r = (matchpos + 1) | DICSIZ;\r
-               while ((q = parent[r]) == NIL) r = next[r];\r
-               while (level[q] >= matchlen) {\r
-                       r = q;  q = parent[q];\r
-               }\r
-               #if PERCOLATE\r
-                       t = q;\r
-                       while (position[t] < 0) {\r
-                               position[t] = pos;  t = parent[t];\r
-                       }\r
-                       if (t < DICSIZ) position[t] = pos | PERC_FLAG;\r
-               #else\r
-                       t = q;\r
-                       while (t < DICSIZ) {\r
-                               position[t] = pos;  t = parent[t];\r
-                       }\r
-               #endif\r
-       } else {\r
-               q = text[pos] + DICSIZ;  c = text[pos + 1];\r
-               if ((r = child(q, c)) == NIL) {\r
-                       makechild(q, c, pos);  matchlen = 1;\r
-                       return;\r
-               }\r
-               matchlen = 2;\r
-       }\r
-       for ( ; ; ) {\r
-               if (r >= DICSIZ) {\r
-                       j = MAXMATCH;  matchpos = r;\r
-               } else {\r
-                       j = level[r];\r
-                       matchpos = position[r] & ~PERC_FLAG;\r
-               }\r
-               if (matchpos >= pos) matchpos -= DICSIZ;\r
-               t1 = &text[pos + matchlen];  t2 = &text[matchpos + matchlen];\r
-               while (matchlen < j) {\r
-                       if (*t1 != *t2) {  split(r);  return;  }\r
-                       matchlen++;  t1++;  t2++;\r
-               }\r
-               if (matchlen >= MAXMATCH) break;\r
-               position[r] = pos;\r
-               q = r;\r
-               if ((r = child(q, *t1)) == NIL) {\r
-                       makechild(q, *t1, pos);  return;\r
-               }\r
-               matchlen++;\r
-       }\r
-       t = prev[r];  prev[pos] = t;  next[t] = pos;\r
-       t = next[r];  next[pos] = t;  prev[t] = pos;\r
-       parent[pos] = q;  parent[r] = NIL;\r
-       next[r] = pos;  /* special use of next[] */\r
-}\r
-\r
-static void delete_node(void)\r
-{\r
-       #if PERCOLATE\r
-               node q, r, s, t, u;\r
-       #else\r
-               node r, s, t, u;\r
-       #endif\r
-\r
-       if (parent[pos] == NIL) return;\r
-       r = prev[pos];  s = next[pos];\r
-       next[r] = s;  prev[s] = r;\r
-       r = parent[pos];  parent[pos] = NIL;\r
-       if (r >= DICSIZ || --childcount[r] > 1) return;\r
-       #if PERCOLATE\r
-               t = position[r] & ~PERC_FLAG;\r
-       #else\r
-               t = position[r];\r
-       #endif\r
-       if (t >= pos) t -= DICSIZ;\r
-       #if PERCOLATE\r
-               s = t;  q = parent[r];\r
-               while ((u = position[q]) & PERC_FLAG) {\r
-                       u &= ~PERC_FLAG;  if (u >= pos) u -= DICSIZ;\r
-                       if (u > s) s = u;\r
-                       position[q] = (s | DICSIZ);  q = parent[q];\r
-               }\r
-               if (q < DICSIZ) {\r
-                       if (u >= pos) u -= DICSIZ;\r
-                       if (u > s) s = u;\r
-                       position[q] = s | DICSIZ | PERC_FLAG;\r
-               }\r
-       #endif\r
-       s = child(r, text[t + level[r]]);\r
-       t = prev[s];  u = next[s];\r
-       next[t] = u;  prev[u] = t;\r
-       t = prev[r];  next[t] = s;  prev[s] = t;\r
-       t = next[r];  prev[t] = s;  next[s] = t;\r
-       parent[s] = parent[r];  parent[r] = NIL;\r
-       next[r] = avail;  avail = r;\r
-}\r
-\r
-static void get_next_match(void)\r
-{\r
-       int n;\r
-\r
-       remainder--;\r
-       if (++pos == DICSIZ * 2) {\r
-               memmove(&text[0], &text[DICSIZ], DICSIZ + MAXMATCH);\r
-               n = fread_crc(&text[DICSIZ + MAXMATCH], DICSIZ, infile);\r
-               remainder += n;  pos = DICSIZ;  putc('.', stderr);\r
-       }\r
-       delete_node();  insert_node();\r
-}\r
-\r
-void encode(void)\r
-{\r
-       int lastmatchlen;\r
-       node lastmatchpos;\r
-\r
-       allocate_memory();  init_slide();  huf_encode_start();\r
-       remainder = fread_crc(&text[DICSIZ], DICSIZ + MAXMATCH, infile);\r
-       putc('.', stderr);\r
-       matchlen = 0;\r
-       pos = DICSIZ;  insert_node();\r
-       if (matchlen > remainder) matchlen = remainder;\r
-       while (remainder > 0 && ! unpackable) {\r
-               lastmatchlen = matchlen;  lastmatchpos = matchpos;\r
-               get_next_match();\r
-               if (matchlen > remainder) matchlen = remainder;\r
-               if (matchlen > lastmatchlen || lastmatchlen < THRESHOLD)\r
-                       output(text[pos - 1], 0);\r
-               else {\r
-                       output(lastmatchlen + (UCHAR_MAX + 1 - THRESHOLD),\r
-                                  (pos - lastmatchpos - 2) & (DICSIZ - 1));\r
-                       while (--lastmatchlen > 0) get_next_match();\r
-                       if (matchlen > remainder) matchlen = remainder;\r
-               }\r
-       }\r
-       huf_encode_end();\r
-}\r
+/***********************************************************
+       encode.c -- sliding dictionary with percolating update
+***********************************************************/
+#include "ar.h"
+#include <stdlib.h>
+#include <string.h>             /* memmove() */
+
+#define PERCOLATE  1
+#define NIL        0
+#define MAX_HASH_VAL (3 * DICSIZ + (DICSIZ / 512 + 1) * UCHAR_MAX)
+
+typedef short node;
+
+static uchar *text, *childcount;
+static node pos, matchpos, avail, *position, *parent, *prev, *next = NULL;
+static int remainder, matchlen;
+
+#if MAXMATCH <= (UCHAR_MAX + 1)
+static uchar *level;
+#else
+static ushort *level;
+#endif
+
+static void
+allocate_memory(void)
+{
+    if (next != NULL)
+        return;
+    text = malloc(DICSIZ * 2 + MAXMATCH);
+    level = malloc((DICSIZ + UCHAR_MAX + 1) * sizeof(*level));
+    childcount = malloc((DICSIZ + UCHAR_MAX + 1) * sizeof(*childcount));
+#if PERCOLATE
+    position = malloc((DICSIZ + UCHAR_MAX + 1) * sizeof(*position));
+#else
+    position = malloc(DICSIZ * sizeof(*position));
+#endif
+    parent = malloc(DICSIZ * 2 * sizeof(*parent));
+    prev = malloc(DICSIZ * 2 * sizeof(*prev));
+    next = malloc((MAX_HASH_VAL + 1) * sizeof(*next));
+    if (next == NULL)
+        error("Out of memory.");
+}
+
+static void
+init_slide(void)
+{
+    node i;
+
+    for (i = DICSIZ; i <= DICSIZ + UCHAR_MAX; i++) {
+        level[i] = 1;
+#if PERCOLATE
+        position[i] = NIL;      /* sentinel */
+#endif
+    }
+    for (i = DICSIZ; i < DICSIZ * 2; i++)
+        parent[i] = NIL;
+    avail = 1;
+    for (i = 1; i < DICSIZ - 1; i++)
+        next[i] = i + 1;
+    next[DICSIZ - 1] = NIL;
+    for (i = DICSIZ * 2; i <= MAX_HASH_VAL; i++)
+        next[i] = NIL;
+}
+
+#define HASH(p, c) ((p) + ((c) << (DICBIT - 9)) + DICSIZ * 2)
+
+static node
+child(node q, uchar c)
+        /* q's child for character c (NIL if not found) */
+{
+    node r;
+
+    r = next[HASH(q, c)];
+    parent[NIL] = q;            /* sentinel */
+    while (parent[r] != q)
+        r = next[r];
+    return r;
+}
+
+static void
+makechild(node q, uchar c, node r)
+        /* Let r be q's child for character c. */
+{
+    node h, t;
+
+    h = HASH(q, c);
+    t = next[h];
+    next[h] = r;
+    next[r] = t;
+    prev[t] = r;
+    prev[r] = h;
+    parent[r] = q;
+    childcount[q]++;
+}
+
+void
+split(node old)
+{
+    node new, t;
+
+    new = avail;
+    avail = next[new];
+    childcount[new] = 0;
+    t = prev[old];
+    prev[new] = t;
+    next[t] = new;
+    t = next[old];
+    next[new] = t;
+    prev[t] = new;
+    parent[new] = parent[old];
+    level[new] = matchlen;
+    position[new] = pos;
+    makechild(new, text[matchpos + matchlen], old);
+    makechild(new, text[pos + matchlen], pos);
+}
+
+static void
+insert_node(void)
+{
+    node q, r, j, t;
+    uchar c, *t1, *t2;
+
+    if (matchlen >= 4) {
+        matchlen--;
+        r = (matchpos + 1) | DICSIZ;
+        while ((q = parent[r]) == NIL)
+            r = next[r];
+        while (level[q] >= matchlen) {
+            r = q;
+            q = parent[q];
+        }
+#if PERCOLATE
+        t = q;
+        while (position[t] < 0) {
+            position[t] = pos;
+            t = parent[t];
+        }
+        if (t < DICSIZ)
+            position[t] = pos | PERC_FLAG;
+#else
+        t = q;
+        while (t < DICSIZ) {
+            position[t] = pos;
+            t = parent[t];
+        }
+#endif
+    }
+    else {
+        q = text[pos] + DICSIZ;
+        c = text[pos + 1];
+        if ((r = child(q, c)) == NIL) {
+            makechild(q, c, pos);
+            matchlen = 1;
+            return;
+        }
+        matchlen = 2;
+    }
+    for (;;) {
+        if (r >= DICSIZ) {
+            j = MAXMATCH;
+            matchpos = r;
+        }
+        else {
+            j = level[r];
+            matchpos = position[r] & ~PERC_FLAG;
+        }
+        if (matchpos >= pos)
+            matchpos -= DICSIZ;
+        t1 = &text[pos + matchlen];
+        t2 = &text[matchpos + matchlen];
+        while (matchlen < j) {
+            if (*t1 != *t2) {
+                split(r);
+                return;
+            }
+            matchlen++;
+            t1++;
+            t2++;
+        }
+        if (matchlen >= MAXMATCH)
+            break;
+        position[r] = pos;
+        q = r;
+        if ((r = child(q, *t1)) == NIL) {
+            makechild(q, *t1, pos);
+            return;
+        }
+        matchlen++;
+    }
+    t = prev[r];
+    prev[pos] = t;
+    next[t] = pos;
+    t = next[r];
+    next[pos] = t;
+    prev[t] = pos;
+    parent[pos] = q;
+    parent[r] = NIL;
+    next[r] = pos;              /* special use of next[] */
+}
+
+static void
+delete_node(void)
+{
+#if PERCOLATE
+    node q, r, s, t, u;
+#else
+    node r, s, t, u;
+#endif
+
+    if (parent[pos] == NIL)
+        return;
+    r = prev[pos];
+    s = next[pos];
+    next[r] = s;
+    prev[s] = r;
+    r = parent[pos];
+    parent[pos] = NIL;
+    if (r >= DICSIZ || --childcount[r] > 1)
+        return;
+#if PERCOLATE
+    t = position[r] & ~PERC_FLAG;
+#else
+    t = position[r];
+#endif
+    if (t >= pos)
+        t -= DICSIZ;
+#if PERCOLATE
+    s = t;
+    q = parent[r];
+    while ((u = position[q]) & PERC_FLAG) {
+        u &= ~PERC_FLAG;
+        if (u >= pos)
+            u -= DICSIZ;
+        if (u > s)
+            s = u;
+        position[q] = (s | DICSIZ);
+        q = parent[q];
+    }
+    if (q < DICSIZ) {
+        if (u >= pos)
+            u -= DICSIZ;
+        if (u > s)
+            s = u;
+        position[q] = s | DICSIZ | PERC_FLAG;
+    }
+#endif
+    s = child(r, text[t + level[r]]);
+    t = prev[s];
+    u = next[s];
+    next[t] = u;
+    prev[u] = t;
+    t = prev[r];
+    next[t] = s;
+    prev[s] = t;
+    t = next[r];
+    prev[t] = s;
+    next[s] = t;
+    parent[s] = parent[r];
+    parent[r] = NIL;
+    next[r] = avail;
+    avail = r;
+}
+
+static void
+get_next_match(void)
+{
+    int n;
+
+    remainder--;
+    if (++pos == DICSIZ * 2) {
+        memmove(&text[0], &text[DICSIZ], DICSIZ + MAXMATCH);
+        n = fread_crc(&text[DICSIZ + MAXMATCH], DICSIZ, infile);
+        remainder += n;
+        pos = DICSIZ;
+        putc('.', stderr);
+    }
+    delete_node();
+    insert_node();
+}
+
+void
+encode(void)
+{
+    int lastmatchlen;
+    node lastmatchpos;
+
+    allocate_memory();
+    init_slide();
+    huf_encode_start();
+    remainder = fread_crc(&text[DICSIZ], DICSIZ + MAXMATCH, infile);
+    putc('.', stderr);
+    matchlen = 0;
+    pos = DICSIZ;
+    insert_node();
+    if (matchlen > remainder)
+        matchlen = remainder;
+    while (remainder > 0 && !unpackable) {
+        lastmatchlen = matchlen;
+        lastmatchpos = matchpos;
+        get_next_match();
+        if (matchlen > remainder)
+            matchlen = remainder;
+        if (matchlen > lastmatchlen || lastmatchlen < THRESHOLD)
+            output(text[pos - 1], 0);
+        else {
+            output(lastmatchlen + (UCHAR_MAX + 1 - THRESHOLD),
+                   (pos - lastmatchpos - 2) & (DICSIZ - 1));
+            while (--lastmatchlen > 0)
+                get_next_match();
+            if (matchlen > remainder)
+                matchlen = remainder;
+        }
+    }
+    huf_encode_end();
+}
diff --git a/huf.c b/huf.c
index 1dc0810..3f0673b 100644 (file)
--- a/huf.c
+++ b/huf.c
-/***********************************************************\r
-       huf.c -- static Huffman\r
-***********************************************************/\r
-#include <stdlib.h>\r
-#include "ar.h"\r
-\r
-#define NP (DICBIT + 1)\r
-#define NT (CODE_BIT + 3)\r
-#define PBIT 4  /* smallest integer such that (1U << PBIT) > NP */\r
-#define TBIT 5  /* smallest integer such that (1U << TBIT) > NT */\r
-#if NT > NP\r
-       #define NPT NT\r
-#else\r
-       #define NPT NP\r
-#endif\r
-\r
-ushort left[2 * NC - 1], right[2 * NC - 1];\r
-static uchar *buf, c_len[NC], pt_len[NPT];\r
-static uint   bufsiz = 0, blocksize;\r
-static ushort c_freq[2 * NC - 1], c_table[4096], c_code[NC],\r
-                         p_freq[2 * NP - 1], pt_table[256], pt_code[NPT],\r
-                         t_freq[2 * NT - 1];\r
-\r
-/***** encoding *****/\r
-\r
-static void count_t_freq(void)\r
-{\r
-       int i, k, n, count;\r
-\r
-       for (i = 0; i < NT; i++) t_freq[i] = 0;\r
-       n = NC;\r
-       while (n > 0 && c_len[n - 1] == 0) n--;\r
-       i = 0;\r
-       while (i < n) {\r
-               k = c_len[i++];\r
-               if (k == 0) {\r
-                       count = 1;\r
-                       while (i < n && c_len[i] == 0) {  i++;  count++;  }\r
-                       if (count <= 2) t_freq[0] += count;\r
-                       else if (count <= 18) t_freq[1]++;\r
-                       else if (count == 19) {  t_freq[0]++;  t_freq[1]++;  }\r
-                       else t_freq[2]++;\r
-               } else t_freq[k + 2]++;\r
-       }\r
-}\r
-\r
-static void write_pt_len(int n, int nbit, int i_special)\r
-{\r
-       int i, k;\r
-\r
-       while (n > 0 && pt_len[n - 1] == 0) n--;\r
-       putbits(nbit, n);\r
-       i = 0;\r
-       while (i < n) {\r
-               k = pt_len[i++];\r
-               if (k <= 6) putbits(3, k);\r
-               else putbits(k - 3, (1U << (k - 3)) - 2);\r
-               if (i == i_special) {\r
-                       while (i < 6 && pt_len[i] == 0) i++;\r
-                       putbits(2, (i - 3) & 3);\r
-               }\r
-       }\r
-}\r
-\r
-static void write_c_len(void)\r
-{\r
-       int i, k, n, count;\r
-\r
-       n = NC;\r
-       while (n > 0 && c_len[n - 1] == 0) n--;\r
-       putbits(CBIT, n);\r
-       i = 0;\r
-       while (i < n) {\r
-               k = c_len[i++];\r
-               if (k == 0) {\r
-                       count = 1;\r
-                       while (i < n && c_len[i] == 0) {  i++;  count++;  }\r
-                       if (count <= 2) {\r
-                               for (k = 0; k < count; k++)\r
-                                       putbits(pt_len[0], pt_code[0]);\r
-                       } else if (count <= 18) {\r
-                               putbits(pt_len[1], pt_code[1]);\r
-                               putbits(4, count - 3);\r
-                       } else if (count == 19) {\r
-                               putbits(pt_len[0], pt_code[0]);\r
-                               putbits(pt_len[1], pt_code[1]);\r
-                               putbits(4, 15);\r
-                       } else {\r
-                               putbits(pt_len[2], pt_code[2]);\r
-                               putbits(CBIT, count - 20);\r
-                       }\r
-               } else putbits(pt_len[k + 2], pt_code[k + 2]);\r
-       }\r
-}\r
-\r
-static void encode_c(int c)\r
-{\r
-       putbits(c_len[c], c_code[c]);\r
-}\r
-\r
-static void encode_p(uint p)\r
-{\r
-       uint c, q;\r
-\r
-       c = 0;  q = p;  while (q) {  q >>= 1;  c++;  }\r
-       putbits(pt_len[c], pt_code[c]);\r
-       if (c > 1) putbits(c - 1, p & (0xFFFFU >> (17 - c)));\r
-}\r
-\r
-static void send_block(void)\r
-{\r
-       uint i, k, flags, root, pos, size;\r
-\r
-       root = make_tree(NC, c_freq, c_len, c_code);\r
-       size = c_freq[root];  putbits(16, size);\r
-       if (root >= NC) {\r
-               count_t_freq();\r
-               root = make_tree(NT, t_freq, pt_len, pt_code);\r
-               if (root >= NT) {\r
-                       write_pt_len(NT, TBIT, 3);\r
-               } else {\r
-                       putbits(TBIT, 0);  putbits(TBIT, root);\r
-               }\r
-               write_c_len();\r
-       } else {\r
-        putbits(TBIT, 0);  putbits(TBIT, 0);\r
-               putbits(CBIT, 0);  putbits(CBIT, root);\r
-       }\r
-       root = make_tree(NP, p_freq, pt_len, pt_code);\r
-       if (root >= NP) {\r
-               write_pt_len(NP, PBIT, -1);\r
-       } else {\r
-               putbits(PBIT, 0);  putbits(PBIT, root);\r
-       }\r
-       pos = 0;\r
-       for (i = 0; i < size; i++) {\r
-               if (i % CHAR_BIT == 0) flags = buf[pos++];  else flags <<= 1;\r
-               if (flags & (1U << (CHAR_BIT - 1))) {\r
-                       encode_c(buf[pos++] + (1U << CHAR_BIT));\r
-                       k = buf[pos++] << CHAR_BIT;  k += buf[pos++];\r
-                       encode_p(k);\r
-               } else encode_c(buf[pos++]);\r
-               if (unpackable) return;\r
-       }\r
-       for (i = 0; i < NC; i++) c_freq[i] = 0;\r
-       for (i = 0; i < NP; i++) p_freq[i] = 0;\r
-}\r
-\r
-static uint output_pos, output_mask;\r
-\r
-void output(uint c, uint p)\r
-{\r
-       static uint cpos;\r
-\r
-       if ((output_mask >>= 1) == 0) {\r
-               output_mask = 1U << (CHAR_BIT - 1);\r
-               if (output_pos >= bufsiz - 3 * CHAR_BIT) {\r
-                       send_block();\r
-                       if (unpackable) return;\r
-                       output_pos = 0;\r
-               }\r
-               cpos = output_pos++;  buf[cpos] = 0;\r
-       }\r
-       buf[output_pos++] = (uchar) c;  c_freq[c]++;\r
-       if (c >= (1U << CHAR_BIT)) {\r
-               buf[cpos] |= output_mask;\r
-               buf[output_pos++] = (uchar)(p >> CHAR_BIT);\r
-               buf[output_pos++] = (uchar) p;\r
-               c = 0;  while (p) {  p >>= 1;  c++;  }\r
-               p_freq[c]++;\r
-       }\r
-}\r
-\r
-void huf_encode_start(void)\r
-{\r
-       int i;\r
-\r
-       if (bufsiz == 0) {\r
-               bufsiz = 16 * 1024U;\r
-               while ((buf = malloc(bufsiz)) == NULL) {\r
-                       bufsiz = (bufsiz / 10U) * 9U;\r
-                       if (bufsiz < 4 * 1024U) error("Out of memory.");\r
-               }\r
-       }\r
-       buf[0] = 0;\r
-       for (i = 0; i < NC; i++) c_freq[i] = 0;\r
-       for (i = 0; i < NP; i++) p_freq[i] = 0;\r
-       output_pos = output_mask = 0;\r
-       init_putbits();\r
-}\r
-\r
-void huf_encode_end(void)\r
-{\r
-       if (! unpackable) {\r
-               send_block();\r
-               putbits(CHAR_BIT - 1, 0);  /* flush remaining bits */\r
-       }\r
-}\r
-\r
-/***** decoding *****/\r
-\r
-static void read_pt_len(int nn, int nbit, int i_special)\r
-{\r
-       int i, c, n;\r
-       uint mask;\r
-\r
-       n = getbits(nbit);\r
-       if (n == 0) {\r
-               c = getbits(nbit);\r
-               for (i = 0; i < nn; i++) pt_len[i] = 0;\r
-               for (i = 0; i < 256; i++) pt_table[i] = c;\r
-       } else {\r
-               i = 0;\r
-               while (i < n) {\r
-                       c = bitbuf >> (BITBUFSIZ - 3);\r
-                       if (c == 7) {\r
-                               mask = 1U << (BITBUFSIZ - 1 - 3);\r
-                               while (mask & bitbuf) {  mask >>= 1;  c++;  }\r
-                       }\r
-                       fillbuf((c < 7) ? 3 : c - 3);\r
-                       pt_len[i++] = c;\r
-                       if (i == i_special) {\r
-                               c = getbits(2);\r
-                               while (--c >= 0) pt_len[i++] = 0;\r
-                       }\r
-               }\r
-               while (i < nn) pt_len[i++] = 0;\r
-               make_table(nn, pt_len, 8, pt_table);\r
-       }\r
-}\r
-\r
-static void read_c_len(void)\r
-{\r
-       int i, c, n;\r
-       uint mask;\r
-\r
-       n = getbits(CBIT);\r
-       if (n == 0) {\r
-               c = getbits(CBIT);\r
-               for (i = 0; i < NC; i++) c_len[i] = 0;\r
-               for (i = 0; i < 4096; i++) c_table[i] = c;\r
-       } else {\r
-               i = 0;\r
-               while (i < n) {\r
-                       c = pt_table[bitbuf >> (BITBUFSIZ - 8)];\r
-                       if (c >= NT) {\r
-                               mask = 1U << (BITBUFSIZ - 1 - 8);\r
-                               do {\r
-                                       if (bitbuf & mask) c = right[c];\r
-                                       else               c = left [c];\r
-                                       mask >>= 1;\r
-                               } while (c >= NT);\r
-                       }\r
-                       fillbuf(pt_len[c]);\r
-                       if (c <= 2) {\r
-                               if      (c == 0) c = 1;\r
-                               else if (c == 1) c = getbits(4) + 3;\r
-                               else             c = getbits(CBIT) + 20;\r
-                               while (--c >= 0) c_len[i++] = 0;\r
-                       } else c_len[i++] = c - 2;\r
-               }\r
-               while (i < NC) c_len[i++] = 0;\r
-               make_table(NC, c_len, 12, c_table);\r
-       }\r
-}\r
-\r
-uint decode_c(void)\r
-{\r
-       uint j, mask;\r
-\r
-       if (blocksize == 0) {\r
-               blocksize = getbits(16);\r
-               read_pt_len(NT, TBIT, 3);\r
-               read_c_len();\r
-               read_pt_len(NP, PBIT, -1);\r
-       }\r
-       blocksize--;\r
-       j = c_table[bitbuf >> (BITBUFSIZ - 12)];\r
-       if (j >= NC) {\r
-               mask = 1U << (BITBUFSIZ - 1 - 12);\r
-               do {\r
-                       if (bitbuf & mask) j = right[j];\r
-                       else               j = left [j];\r
-                       mask >>= 1;\r
-               } while (j >= NC);\r
-       }\r
-       fillbuf(c_len[j]);\r
-       return j;\r
-}\r
-\r
-uint decode_p(void)\r
-{\r
-       uint j, mask;\r
-\r
-       j = pt_table[bitbuf >> (BITBUFSIZ - 8)];\r
-       if (j >= NP) {\r
-               mask = 1U << (BITBUFSIZ - 1 - 8);\r
-               do {\r
-                       if (bitbuf & mask) j = right[j];\r
-                       else               j = left [j];\r
-                       mask >>= 1;\r
-               } while (j >= NP);\r
-       }\r
-       fillbuf(pt_len[j]);\r
-       if (j != 0) j = (1U << (j - 1)) + getbits(j - 1);\r
-       return j;\r
-}\r
-\r
-void huf_decode_start(void)\r
-{\r
-       init_getbits();  blocksize = 0;\r
-}\r
+/***********************************************************
+       huf.c -- static Huffman
+***********************************************************/
+#include <stdlib.h>
+#include "ar.h"
+
+#define NP (DICBIT + 1)
+#define NT (CODE_BIT + 3)
+#define PBIT 4                  /* smallest integer such that (1U << PBIT) > NP */
+#define TBIT 5                  /* smallest integer such that (1U << TBIT) > NT */
+#if NT > NP
+#define NPT NT
+#else
+#define NPT NP
+#endif
+
+ushort left[2 * NC - 1], right[2 * NC - 1];
+static uchar *buf, c_len[NC], pt_len[NPT];
+static uint bufsiz = 0, blocksize;
+static ushort c_freq[2 * NC - 1], c_table[4096], c_code[NC],
+    p_freq[2 * NP - 1], pt_table[256], pt_code[NPT], t_freq[2 * NT - 1];
+
+/***** encoding *****/
+
+static void
+count_t_freq(void)
+{
+    int i, k, n, count;
+
+    for (i = 0; i < NT; i++)
+        t_freq[i] = 0;
+    n = NC;
+    while (n > 0 && c_len[n - 1] == 0)
+        n--;
+    i = 0;
+    while (i < n) {
+        k = c_len[i++];
+        if (k == 0) {
+            count = 1;
+            while (i < n && c_len[i] == 0) {
+                i++;
+                count++;
+            }
+            if (count <= 2)
+                t_freq[0] += count;
+            else if (count <= 18)
+                t_freq[1]++;
+            else if (count == 19) {
+                t_freq[0]++;
+                t_freq[1]++;
+            }
+            else
+                t_freq[2]++;
+        }
+        else
+            t_freq[k + 2]++;
+    }
+}
+
+static void
+write_pt_len(int n, int nbit, int i_special)
+{
+    int i, k;
+
+    while (n > 0 && pt_len[n - 1] == 0)
+        n--;
+    putbits(nbit, n);
+    i = 0;
+    while (i < n) {
+        k = pt_len[i++];
+        if (k <= 6)
+            putbits(3, k);
+        else
+            putbits(k - 3, (1U << (k - 3)) - 2);
+        if (i == i_special) {
+            while (i < 6 && pt_len[i] == 0)
+                i++;
+            putbits(2, (i - 3) & 3);
+        }
+    }
+}
+
+static void
+write_c_len(void)
+{
+    int i, k, n, count;
+
+    n = NC;
+    while (n > 0 && c_len[n - 1] == 0)
+        n--;
+    putbits(CBIT, n);
+    i = 0;
+    while (i < n) {
+        k = c_len[i++];
+        if (k == 0) {
+            count = 1;
+            while (i < n && c_len[i] == 0) {
+                i++;
+                count++;
+            }
+            if (count <= 2) {
+                for (k = 0; k < count; k++)
+                    putbits(pt_len[0], pt_code[0]);
+            }
+            else if (count <= 18) {
+                putbits(pt_len[1], pt_code[1]);
+                putbits(4, count - 3);
+            }
+            else if (count == 19) {
+                putbits(pt_len[0], pt_code[0]);
+                putbits(pt_len[1], pt_code[1]);
+                putbits(4, 15);
+            }
+            else {
+                putbits(pt_len[2], pt_code[2]);
+                putbits(CBIT, count - 20);
+            }
+        }
+        else
+            putbits(pt_len[k + 2], pt_code[k + 2]);
+    }
+}
+
+static void
+encode_c(int c)
+{
+    putbits(c_len[c], c_code[c]);
+}
+
+static void
+encode_p(uint p)
+{
+    uint c, q;
+
+    c = 0;
+    q = p;
+    while (q) {
+        q >>= 1;
+        c++;
+    }
+    putbits(pt_len[c], pt_code[c]);
+    if (c > 1)
+        putbits(c - 1, p & (0xFFFFU >> (17 - c)));
+}
+
+static void
+send_block(void)
+{
+    uint i, k, flags, root, pos, size;
+
+    root = make_tree(NC, c_freq, c_len, c_code);
+    size = c_freq[root];
+    putbits(16, size);
+    if (root >= NC) {
+        count_t_freq();
+        root = make_tree(NT, t_freq, pt_len, pt_code);
+        if (root >= NT) {
+            write_pt_len(NT, TBIT, 3);
+        }
+        else {
+            putbits(TBIT, 0);
+            putbits(TBIT, root);
+        }
+        write_c_len();
+    }
+    else {
+        putbits(TBIT, 0);
+        putbits(TBIT, 0);
+        putbits(CBIT, 0);
+        putbits(CBIT, root);
+    }
+    root = make_tree(NP, p_freq, pt_len, pt_code);
+    if (root >= NP) {
+        write_pt_len(NP, PBIT, -1);
+    }
+    else {
+        putbits(PBIT, 0);
+        putbits(PBIT, root);
+    }
+    pos = 0;
+    for (i = 0; i < size; i++) {
+        if (i % CHAR_BIT == 0)
+            flags = buf[pos++];
+        else
+            flags <<= 1;
+        if (flags & (1U << (CHAR_BIT - 1))) {
+            encode_c(buf[pos++] + (1U << CHAR_BIT));
+            k = buf[pos++] << CHAR_BIT;
+            k += buf[pos++];
+            encode_p(k);
+        }
+        else
+            encode_c(buf[pos++]);
+        if (unpackable)
+            return;
+    }
+    for (i = 0; i < NC; i++)
+        c_freq[i] = 0;
+    for (i = 0; i < NP; i++)
+        p_freq[i] = 0;
+}
+
+static uint output_pos, output_mask;
+
+void
+output(uint c, uint p)
+{
+    static uint cpos;
+
+    if ((output_mask >>= 1) == 0) {
+        output_mask = 1U << (CHAR_BIT - 1);
+        if (output_pos >= bufsiz - 3 * CHAR_BIT) {
+            send_block();
+            if (unpackable)
+                return;
+            output_pos = 0;
+        }
+        cpos = output_pos++;
+        buf[cpos] = 0;
+    }
+    buf[output_pos++] = (uchar) c;
+    c_freq[c]++;
+    if (c >= (1U << CHAR_BIT)) {
+        buf[cpos] |= output_mask;
+        buf[output_pos++] = (uchar) (p >> CHAR_BIT);
+        buf[output_pos++] = (uchar) p;
+        c = 0;
+        while (p) {
+            p >>= 1;
+            c++;
+        }
+        p_freq[c]++;
+    }
+}
+
+void
+huf_encode_start(void)
+{
+    int i;
+
+    if (bufsiz == 0) {
+        bufsiz = 16 * 1024U;
+        while ((buf = malloc(bufsiz)) == NULL) {
+            bufsiz = (bufsiz / 10U) * 9U;
+            if (bufsiz < 4 * 1024U)
+                error("Out of memory.");
+        }
+    }
+    buf[0] = 0;
+    for (i = 0; i < NC; i++)
+        c_freq[i] = 0;
+    for (i = 0; i < NP; i++)
+        p_freq[i] = 0;
+    output_pos = output_mask = 0;
+    init_putbits();
+}
+
+void
+huf_encode_end(void)
+{
+    if (!unpackable) {
+        send_block();
+        putbits(CHAR_BIT - 1, 0);       /* flush remaining bits */
+    }
+}
+
+/***** decoding *****/
+
+static void
+read_pt_len(int nn, int nbit, int i_special)
+{
+    int i, c, n;
+    uint mask;
+
+    n = getbits(nbit);
+    if (n == 0) {
+        c = getbits(nbit);
+        for (i = 0; i < nn; i++)
+            pt_len[i] = 0;
+        for (i = 0; i < 256; i++)
+            pt_table[i] = c;
+    }
+    else {
+        i = 0;
+        while (i < n) {
+            c = bitbuf >> (BITBUFSIZ - 3);
+            if (c == 7) {
+                mask = 1U << (BITBUFSIZ - 1 - 3);
+                while (mask & bitbuf) {
+                    mask >>= 1;
+                    c++;
+                }
+            }
+            fillbuf((c < 7) ? 3 : c - 3);
+            pt_len[i++] = c;
+            if (i == i_special) {
+                c = getbits(2);
+                while (--c >= 0)
+                    pt_len[i++] = 0;
+            }
+        }
+        while (i < nn)
+            pt_len[i++] = 0;
+        make_table(nn, pt_len, 8, pt_table);
+    }
+}
+
+static void
+read_c_len(void)
+{
+    int i, c, n;
+    uint mask;
+
+    n = getbits(CBIT);
+    if (n == 0) {
+        c = getbits(CBIT);
+        for (i = 0; i < NC; i++)
+            c_len[i] = 0;
+        for (i = 0; i < 4096; i++)
+            c_table[i] = c;
+    }
+    else {
+        i = 0;
+        while (i < n) {
+            c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
+            if (c >= NT) {
+                mask = 1U << (BITBUFSIZ - 1 - 8);
+                do {
+                    if (bitbuf & mask)
+                        c = right[c];
+                    else
+                        c = left[c];
+                    mask >>= 1;
+                } while (c >= NT);
+            }
+            fillbuf(pt_len[c]);
+            if (c <= 2) {
+                if (c == 0)
+                    c = 1;
+                else if (c == 1)
+                    c = getbits(4) + 3;
+                else
+                    c = getbits(CBIT) + 20;
+                while (--c >= 0)
+                    c_len[i++] = 0;
+            }
+            else
+                c_len[i++] = c - 2;
+        }
+        while (i < NC)
+            c_len[i++] = 0;
+        make_table(NC, c_len, 12, c_table);
+    }
+}
+
+uint
+decode_c(void)
+{
+    uint j, mask;
+
+    if (blocksize == 0) {
+        blocksize = getbits(16);
+        read_pt_len(NT, TBIT, 3);
+        read_c_len();
+        read_pt_len(NP, PBIT, -1);
+    }
+    blocksize--;
+    j = c_table[bitbuf >> (BITBUFSIZ - 12)];
+    if (j >= NC) {
+        mask = 1U << (BITBUFSIZ - 1 - 12);
+        do {
+            if (bitbuf & mask)
+                j = right[j];
+            else
+                j = left[j];
+            mask >>= 1;
+        } while (j >= NC);
+    }
+    fillbuf(c_len[j]);
+    return j;
+}
+
+uint
+decode_p(void)
+{
+    uint j, mask;
+
+    j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
+    if (j >= NP) {
+        mask = 1U << (BITBUFSIZ - 1 - 8);
+        do {
+            if (bitbuf & mask)
+                j = right[j];
+            else
+                j = left[j];
+            mask >>= 1;
+        } while (j >= NP);
+    }
+    fillbuf(pt_len[j]);
+    if (j != 0)
+        j = (1U << (j - 1)) + getbits(j - 1);
+    return j;
+}
+
+void
+huf_decode_start(void)
+{
+    init_getbits();
+    blocksize = 0;
+}
diff --git a/io.c b/io.c
index f2db597..b38ab2b 100644 (file)
--- a/io.c
+++ b/io.c
-/***********************************************************\r
-       io.c -- input/output\r
-***********************************************************/\r
-#include "ar.h"\r
-#include <stdlib.h>\r
-#include <stdarg.h>\r
-\r
-#define CRCPOLY  0xA001  /* ANSI CRC-16 */\r
-                         /* CCITT: 0x8408 */\r
-#define UPDATE_CRC(c) \\r
-       crc = crctable[(crc ^ (c)) & 0xFF] ^ (crc >> CHAR_BIT)\r
-\r
-FILE *arcfile, *infile, *outfile;\r
-uint crc, bitbuf;\r
-\r
-static ushort crctable[UCHAR_MAX + 1];\r
-static uint  subbitbuf;\r
-static int   bitcount;\r
-\r
-void error(char *fmt, ...)\r
-{\r
-       va_list args;\r
-\r
-       va_start(args, fmt);\r
-       putc('\n', stderr);\r
-       vfprintf(stderr, fmt, args);\r
-       putc('\n', stderr);\r
-       va_end(args);\r
-       exit(EXIT_FAILURE);\r
-}\r
-\r
-void make_crctable(void)\r
-{\r
-       uint i, j, r;\r
-\r
-       for (i = 0; i <= UCHAR_MAX; i++) {\r
-               r = i;\r
-               for (j = 0; j < CHAR_BIT; j++)\r
-                       if (r & 1) r = (r >> 1) ^ CRCPOLY;\r
-                       else       r >>= 1;\r
-               crctable[i] = r;\r
-       }\r
-}\r
-\r
-void fillbuf(int n)  /* Shift bitbuf n bits left, read n bits */\r
-{\r
-       bitbuf <<= n;\r
-       while (n > bitcount) {\r
-               bitbuf |= subbitbuf << (n -= bitcount);\r
-               if (compsize != 0) {\r
-                       compsize--;  subbitbuf = (uchar) getc(arcfile);\r
-               } else subbitbuf = 0;\r
-               bitcount = CHAR_BIT;\r
-       }\r
-       bitbuf |= subbitbuf >> (bitcount -= n);\r
-}\r
-\r
-uint getbits(int n)\r
-{\r
-       uint x;\r
-\r
-       x = bitbuf >> (BITBUFSIZ - n);  fillbuf(n);\r
-       return x;\r
-}\r
-\r
-void putbits(int n, uint x)  /* Write rightmost n bits of x */\r
-{\r
-       if (n < bitcount) {\r
-               subbitbuf |= x << (bitcount -= n);\r
-       } else {\r
-               if (compsize < origsize) {\r
-                       putc(subbitbuf | (x >> (n -= bitcount)), outfile);\r
-                       compsize++;\r
-               } else unpackable = 1;\r
-               if (n < CHAR_BIT) {\r
-                       subbitbuf = x << (bitcount = CHAR_BIT - n);\r
-               } else {\r
-                       if (compsize < origsize) {\r
-                               putc(x >> (n - CHAR_BIT), outfile);\r
-                               compsize++;\r
-                       } else unpackable = 1;\r
-                       subbitbuf = x << (bitcount = 2 * CHAR_BIT - n);\r
-               }\r
-       }\r
-}\r
-\r
-int fread_crc(uchar *p, int n, FILE *f)\r
-{\r
-       int i;\r
-\r
-       i = n = fread(p, 1, n, f);  origsize += n;\r
-       while (--i >= 0) UPDATE_CRC(*p++);\r
-       return n;\r
-}\r
-\r
-void fwrite_crc(uchar *p, int n, FILE *f)\r
-{\r
-       if (fwrite(p, 1, n, f) < n) error("Unable to write");\r
-       while (--n >= 0) UPDATE_CRC(*p++);\r
-}\r
-\r
-void init_getbits(void)\r
-{\r
-       bitbuf = 0;  subbitbuf = 0;  bitcount = 0;\r
-       fillbuf(BITBUFSIZ);\r
-}\r
-\r
-void init_putbits(void)\r
-{\r
-       bitcount = CHAR_BIT;  subbitbuf = 0;\r
-}\r
+/***********************************************************
+       io.c -- input/output
+***********************************************************/
+#include "ar.h"
+#include <stdlib.h>
+#include <stdarg.h>
+
+#define CRCPOLY  0xA001         /* ANSI CRC-16 */
+                         /* CCITT: 0x8408 */
+#define UPDATE_CRC(c) \
+       crc = crctable[(crc ^ (c)) & 0xFF] ^ (crc >> CHAR_BIT)
+
+FILE *arcfile, *infile, *outfile;
+uint crc, bitbuf;
+
+static ushort crctable[UCHAR_MAX + 1];
+static uint subbitbuf;
+static int bitcount;
+
+void
+error(char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+    putc('\n', stderr);
+    vfprintf(stderr, fmt, args);
+    putc('\n', stderr);
+    va_end(args);
+    exit(EXIT_FAILURE);
+}
+
+void
+make_crctable(void)
+{
+    uint i, j, r;
+
+    for (i = 0; i <= UCHAR_MAX; i++) {
+        r = i;
+        for (j = 0; j < CHAR_BIT; j++)
+            if (r & 1)
+                r = (r >> 1) ^ CRCPOLY;
+            else
+                r >>= 1;
+        crctable[i] = r;
+    }
+}
+
+void
+fillbuf(int n)
+{                               /* Shift bitbuf n bits left, read n bits */
+    bitbuf <<= n;
+    while (n > bitcount) {
+        bitbuf |= subbitbuf << (n -= bitcount);
+        if (compsize != 0) {
+            compsize--;
+            subbitbuf = (uchar) getc(arcfile);
+        }
+        else
+            subbitbuf = 0;
+        bitcount = CHAR_BIT;
+    }
+    bitbuf |= subbitbuf >> (bitcount -= n);
+}
+
+uint
+getbits(int n)
+{
+    uint x;
+
+    x = bitbuf >> (BITBUFSIZ - n);
+    fillbuf(n);
+    return x;
+}
+
+void
+putbits(int n, uint x)
+{                               /* Write rightmost n bits of x */
+    if (n < bitcount) {
+        subbitbuf |= x << (bitcount -= n);
+    }
+    else {
+        if (compsize < origsize) {
+            putc(subbitbuf | (x >> (n -= bitcount)), outfile);
+            compsize++;
+        }
+        else
+            unpackable = 1;
+        if (n < CHAR_BIT) {
+            subbitbuf = x << (bitcount = CHAR_BIT - n);
+        }
+        else {
+            if (compsize < origsize) {
+                putc(x >> (n - CHAR_BIT), outfile);
+                compsize++;
+            }
+            else
+                unpackable = 1;
+            subbitbuf = x << (bitcount = 2 * CHAR_BIT - n);
+        }
+    }
+}
+
+int
+fread_crc(uchar * p, int n, FILE * f)
+{
+    int i;
+
+    i = n = fread(p, 1, n, f);
+    origsize += n;
+    while (--i >= 0)
+        UPDATE_CRC(*p++);
+    return n;
+}
+
+void
+fwrite_crc(uchar * p, int n, FILE * f)
+{
+    if (fwrite(p, 1, n, f) < n)
+        error("Unable to write");
+    while (--n >= 0)
+        UPDATE_CRC(*p++);
+}
+
+void
+init_getbits(void)
+{
+    bitbuf = 0;
+    subbitbuf = 0;
+    bitcount = 0;
+    fillbuf(BITBUFSIZ);
+}
+
+void
+init_putbits(void)
+{
+    bitcount = CHAR_BIT;
+    subbitbuf = 0;
+}
index c01dcea..0091979 100644 (file)
--- a/makefile
+++ b/makefile
@@ -1,16 +1,5 @@
-########################################\r
-#  'ar' -- compression archiver        #\r
-#  makefile for Turbo C compact model  #\r
-########################################\r
-\r
-MDL  = c  ##### compact model #####\r
-OBJS = ar.obj io.obj encode.obj decode.obj maketree.obj maketbl.obj huf.obj\r
-\r
-ar.exe: $(OBJS)\r
-       tlink /c /d /x a:\tc\lib\c0$(MDL) \\r
-       ar io encode decode maketree maketbl huf, ar, , a:\tc\lib\c$(MDL)\r
-\r
-.c.obj:\r
-       tcc -c -m$(MDL) -N -w -w-stv -Ia:\tc\include $<\r
-\r
-$(OBJS): ar.h\r
+EXEEXT=.exe
+OBJS = ar.o io.o encode.o decode.o maketree.o maketbl.o huf.o
+
+olha$(EXEEXT): $(OBJS)
+       $(CC) $^ -o $@
index faa6608..1b8d37b 100644 (file)
--- a/maketbl.c
+++ b/maketbl.c
@@ -1,56 +1,68 @@
-/***********************************************************\r
-       maketbl.c -- make table for decoding\r
-***********************************************************/\r
-#include "ar.h"\r
-\r
-void make_table(int nchar, uchar bitlen[], int tablebits, ushort table[])\r
-{\r
-       ushort count[17], weight[17], start[18], *p;\r
-       uint i, k, len, ch, jutbits, avail, nextcode, mask;\r
-\r
-       for (i = 1; i <= 16; i++) count[i] = 0;\r
-       for (i = 0; i < nchar; i++) count[bitlen[i]]++;\r
-\r
-       start[1] = 0;\r
-       for (i = 1; i <= 16; i++)\r
-               start[i + 1] = start[i] + (count[i] << (16 - i));\r
-       if (start[17] != (ushort)(1U << 16)) error("Bad table");\r
-\r
-       jutbits = 16 - tablebits;\r
-       for (i = 1; i <= tablebits; i++) {\r
-               start[i] >>= jutbits;\r
-               weight[i] = 1U << (tablebits - i);\r
-       }\r
-       while (i <= 16) weight[i++] = 1U << (16 - i);\r
-\r
-       i = start[tablebits + 1] >> jutbits;\r
-       if (i != (ushort)(1U << 16)) {\r
-               k = 1U << tablebits;\r
-               while (i != k) table[i++] = 0;\r
-       }\r
-\r
-       avail = nchar;\r
-       mask = 1U << (15 - tablebits);\r
-       for (ch = 0; ch < nchar; ch++) {\r
-               if ((len = bitlen[ch]) == 0) continue;\r
-               nextcode = start[len] + weight[len];\r
-               if (len <= tablebits) {\r
-                       for (i = start[len]; i < nextcode; i++) table[i] = ch;\r
-               } else {\r
-                       k = start[len];\r
-                       p = &table[k >> jutbits];\r
-                       i = len - tablebits;\r
-                       while (i != 0) {\r
-                               if (*p == 0) {\r
-                                       right[avail] = left[avail] = 0;\r
-                                       *p = avail++;\r
-                               }\r
-                               if (k & mask) p = &right[*p];\r
-                               else          p = &left[*p];\r
-                               k <<= 1;  i--;\r
-                       }\r
-                       *p = ch;\r
-               }\r
-               start[len] = nextcode;\r
-       }\r
-}\r
+/***********************************************************
+       maketbl.c -- make table for decoding
+***********************************************************/
+#include "ar.h"
+
+void
+make_table(int nchar, uchar bitlen[], int tablebits, ushort table[])
+{
+    ushort count[17], weight[17], start[18], *p;
+    uint i, k, len, ch, jutbits, avail, nextcode, mask;
+
+    for (i = 1; i <= 16; i++)
+        count[i] = 0;
+    for (i = 0; i < nchar; i++)
+        count[bitlen[i]]++;
+
+    start[1] = 0;
+    for (i = 1; i <= 16; i++)
+        start[i + 1] = start[i] + (count[i] << (16 - i));
+    if (start[17] != (ushort) (1U << 16))
+        error("Bad table");
+
+    jutbits = 16 - tablebits;
+    for (i = 1; i <= tablebits; i++) {
+        start[i] >>= jutbits;
+        weight[i] = 1U << (tablebits - i);
+    }
+    while (i <= 16)
+        weight[i++] = 1U << (16 - i);
+
+    i = start[tablebits + 1] >> jutbits;
+    if (i != (ushort) (1U << 16)) {
+        k = 1U << tablebits;
+        while (i != k)
+            table[i++] = 0;
+    }
+
+    avail = nchar;
+    mask = 1U << (15 - tablebits);
+    for (ch = 0; ch < nchar; ch++) {
+        if ((len = bitlen[ch]) == 0)
+            continue;
+        nextcode = start[len] + weight[len];
+        if (len <= tablebits) {
+            for (i = start[len]; i < nextcode; i++)
+                table[i] = ch;
+        }
+        else {
+            k = start[len];
+            p = &table[k >> jutbits];
+            i = len - tablebits;
+            while (i != 0) {
+                if (*p == 0) {
+                    right[avail] = left[avail] = 0;
+                    *p = avail++;
+                }
+                if (k & mask)
+                    p = &right[*p];
+                else
+                    p = &left[*p];
+                k <<= 1;
+                i--;
+            }
+            *p = ch;
+        }
+        start[len] = nextcode;
+    }
+}
index f96ddc3..158e576 100644 (file)
-/***********************************************************\r
-       maketree.c -- make Huffman tree\r
-***********************************************************/\r
-#include "ar.h"\r
-\r
-static int    n, heapsize;\r
-static short  heap[NC + 1];\r
-static ushort *freq, *sortptr, len_cnt[17];\r
-static uchar  *len;\r
-\r
-static void count_len(int i)  /* call with i = root */\r
-{\r
-       static int depth = 0;\r
-\r
-       if (i < n) len_cnt[(depth < 16) ? depth : 16]++;\r
-       else {\r
-               depth++;\r
-               count_len(left [i]);\r
-               count_len(right[i]);\r
-               depth--;\r
-       }\r
-}\r
-\r
-static void make_len(int root)\r
-{\r
-       int i, k;\r
-       uint cum;\r
-\r
-       for (i = 0; i <= 16; i++) len_cnt[i] = 0;\r
-       count_len(root);\r
-       cum = 0;\r
-       for (i = 16; i > 0; i--)\r
-               cum += len_cnt[i] << (16 - i);\r
-       while (cum != (1U << 16)) {\r
-               fprintf(stderr, "17");\r
-               len_cnt[16]--;\r
-               for (i = 15; i > 0; i--) {\r
-                       if (len_cnt[i] != 0) {\r
-                               len_cnt[i]--;  len_cnt[i+1] += 2;  break;\r
-                       }\r
-               }\r
-               cum--;\r
-       }\r
-       for (i = 16; i > 0; i--) {\r
-               k = len_cnt[i];\r
-               while (--k >= 0) len[*sortptr++] = i;\r
-       }\r
-}\r
-\r
-static void downheap(int i)\r
-       /* priority queue; send i-th entry down heap */\r
-{\r
-       int j, k;\r
-\r
-       k = heap[i];\r
-       while ((j = 2 * i) <= heapsize) {\r
-               if (j < heapsize && freq[heap[j]] > freq[heap[j + 1]])\r
-                       j++;\r
-               if (freq[k] <= freq[heap[j]]) break;\r
-               heap[i] = heap[j];  i = j;\r
-       }\r
-       heap[i] = k;\r
-}\r
-\r
-static void make_code(int n, uchar len[], ushort code[])\r
-{\r
-       int    i;\r
-       ushort start[18];\r
-\r
-       start[1] = 0;\r
-       for (i = 1; i <= 16; i++)\r
-               start[i + 1] = (start[i] + len_cnt[i]) << 1;\r
-       for (i = 0; i < n; i++) code[i] = start[len[i]]++;\r
-}\r
-\r
-int make_tree(int nparm, ushort freqparm[],\r
-                               uchar lenparm[], ushort codeparm[])\r
-       /* make tree, calculate len[], return root */\r
-{\r
-       int i, j, k, avail;\r
-\r
-       n = nparm;  freq = freqparm;  len = lenparm;\r
-       avail = n;  heapsize = 0;  heap[1] = 0;\r
-       for (i = 0; i < n; i++) {\r
-               len[i] = 0;\r
-               if (freq[i]) heap[++heapsize] = i;\r
-       }\r
-       if (heapsize < 2) {\r
-               codeparm[heap[1]] = 0;  return heap[1];\r
-       }\r
-       for (i = heapsize / 2; i >= 1; i--)\r
-               downheap(i);  /* make priority queue */\r
-       sortptr = codeparm;\r
-       do {  /* while queue has at least two entries */\r
-               i = heap[1];  /* take out least-freq entry */\r
-               if (i < n) *sortptr++ = i;\r
-               heap[1] = heap[heapsize--];\r
-               downheap(1);\r
-               j = heap[1];  /* next least-freq entry */\r
-               if (j < n) *sortptr++ = j;\r
-               k = avail++;  /* generate new node */\r
-               freq[k] = freq[i] + freq[j];\r
-               heap[1] = k;  downheap(1);  /* put into queue */\r
-               left[k] = i;  right[k] = j;\r
-       } while (heapsize > 1);\r
-       sortptr = codeparm;\r
-       make_len(k);\r
-       make_code(nparm, lenparm, codeparm);\r
-       return k;  /* return root */\r
-}\r
+/***********************************************************
+       maketree.c -- make Huffman tree
+***********************************************************/
+#include "ar.h"
+
+static int n, heapsize;
+static short heap[NC + 1];
+static ushort *freq, *sortptr, len_cnt[17];
+static uchar *len;
+
+static void
+count_len(int i)
+{                               /* call with i = root */
+    static int depth = 0;
+
+    if (i < n)
+        len_cnt[(depth < 16) ? depth : 16]++;
+    else {
+        depth++;
+        count_len(left[i]);
+        count_len(right[i]);
+        depth--;
+    }
+}
+
+static void
+make_len(int root)
+{
+    int i, k;
+    uint cum;
+
+    for (i = 0; i <= 16; i++)
+        len_cnt[i] = 0;
+    count_len(root);
+    cum = 0;
+    for (i = 16; i > 0; i--)
+        cum += len_cnt[i] << (16 - i);
+    while (cum != (1U << 16)) {
+        fprintf(stderr, "17");
+        len_cnt[16]--;
+        for (i = 15; i > 0; i--) {
+            if (len_cnt[i] != 0) {
+                len_cnt[i]--;
+                len_cnt[i + 1] += 2;
+                break;
+            }
+        }
+        cum--;
+    }
+    for (i = 16; i > 0; i--) {
+        k = len_cnt[i];
+        while (--k >= 0)
+            len[*sortptr++] = i;
+    }
+}
+
+static void
+downheap(int i)
+        /* priority queue; send i-th entry down heap */
+{
+    int j, k;
+
+    k = heap[i];
+    while ((j = 2 * i) <= heapsize) {
+        if (j < heapsize && freq[heap[j]] > freq[heap[j + 1]])
+            j++;
+        if (freq[k] <= freq[heap[j]])
+            break;
+        heap[i] = heap[j];
+        i = j;
+    }
+    heap[i] = k;
+}
+
+static void
+make_code(int n, uchar len[], ushort code[])
+{
+    int i;
+    ushort start[18];
+
+    start[1] = 0;
+    for (i = 1; i <= 16; i++)
+        start[i + 1] = (start[i] + len_cnt[i]) << 1;
+    for (i = 0; i < n; i++)
+        code[i] = start[len[i]]++;
+}
+
+int
+make_tree(int nparm, ushort freqparm[], uchar lenparm[], ushort codeparm[])
+        /* make tree, calculate len[], return root */
+{
+    int i, j, k, avail;
+
+    n = nparm;
+    freq = freqparm;
+    len = lenparm;
+    avail = n;
+    heapsize = 0;
+    heap[1] = 0;
+    for (i = 0; i < n; i++) {
+        len[i] = 0;
+        if (freq[i])
+            heap[++heapsize] = i;
+    }
+    if (heapsize < 2) {
+        codeparm[heap[1]] = 0;
+        return heap[1];
+    }
+    for (i = heapsize / 2; i >= 1; i--)
+        downheap(i);            /* make priority queue */
+    sortptr = codeparm;
+    do {                        /* while queue has at least two entries */
+        i = heap[1];            /* take out least-freq entry */
+        if (i < n)
+            *sortptr++ = i;
+        heap[1] = heap[heapsize--];
+        downheap(1);
+        j = heap[1];            /* next least-freq entry */
+        if (j < n)
+            *sortptr++ = j;
+        k = avail++;            /* generate new node */
+        freq[k] = freq[i] + freq[j];
+        heap[1] = k;
+        downheap(1);            /* put into queue */
+        left[k] = i;
+        right[k] = j;
+    } while (heapsize > 1);
+    sortptr = codeparm;
+    make_len(k);
+    make_code(nparm, lenparm, codeparm);
+    return k;                   /* return root */
+}