command name is changed to olha which meaning the OpenLHa.
--- /dev/null
+*.o
+*.exe
+*~
-/***********************************************************\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;
+}
-/***********************************************************\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[]);
-/***********************************************************\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;
+ }
+ }
+ }
+}
-/***********************************************************\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();
+}
-/***********************************************************\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;
+}
-/***********************************************************\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;
+}
-########################################\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 $@
-/***********************************************************\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;
+ }
+}
-/***********************************************************\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 */
+}