summaryrefslogtreecommitdiff
path: root/amiga
diff options
context:
space:
mode:
Diffstat (limited to 'amiga')
-rw-r--r--amiga/LMKfile116
-rw-r--r--amiga/README1
-rw-r--r--amiga/amiga.c143
-rw-r--r--amiga/amiga.h54
-rw-r--r--amiga/amigazip.c510
-rw-r--r--amiga/crc_68.a144
-rw-r--r--amiga/deflate.a1053
-rw-r--r--amiga/filedate.c636
-rw-r--r--amiga/makefile.azt282
-rw-r--r--amiga/match.a182
-rw-r--r--amiga/match_68.a273
-rw-r--r--amiga/osdep.h109
-rw-r--r--amiga/smakefile671
-rw-r--r--amiga/stat.c293
-rw-r--r--amiga/time_lib.c541
-rw-r--r--amiga/timezone.doc85
-rw-r--r--amiga/z-stat.h95
-rw-r--r--amiga/z-time.h76
-rw-r--r--amiga/zipup.h25
19 files changed, 5289 insertions, 0 deletions
diff --git a/amiga/LMKfile b/amiga/LMKfile
new file mode 100644
index 0000000..6b6aa40
--- /dev/null
+++ b/amiga/LMKfile
@@ -0,0 +1,116 @@
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit, Amiga SAS/C 5.10b
+# See the master Makefile under the top level Zip/Unzip source directory
+# for more information on compiler macros and flags for this version.
+# Last update: Jun 25, 1998
+# -John Bush, <J.Bush@MD-B.Prime.COM>, <JBush@BIX.COM>
+
+
+#######################
+# MACROBE DEFINITIONS #
+#######################
+
+# Compiler and loader debug flags. Omit comments as req'd.
+# Do not set when building production version.
+# CDBG = -d3
+# LDBG = ADDSYM
+
+DEFINES = -DNO_MKTEMP
+CC = lc
+OPT = -O
+CFLAGS = $(OPT) $(DEFINES) $(CDBG) -v -mat -cuisf -b0 -j85i86i87i100i
+
+LD = blink
+LDSTART = LIB:c.o
+LDFLAGS = LIB LIB:lc.lib+LIB:amiga.lib
+
+TMPFILE = ram:MakeZip.tmp
+
+###############################################
+# BASIC COMPILE INSTRUCTIONS AND DEPENDENCIES #
+###############################################
+
+# default C rules
+.c.o:
+ $(CC) $(CFLAGS) -o$@ $*.c
+
+# Alternate rules for routines containing entries needed by utilities
+.c.oo:
+ $(CC) $(CFLAGS) -DUTIL -o$*.oo $*.c
+
+# object file macrough lists
+
+HFILES = zip.h ziperr.h tailor.h revision.h crypt.h ttyio.h amiga/amiga.h \
+ amiga/zipup.h amiga/osdep.h
+
+OBJA = zipfile.o zipup.o fileio.o util.o globals.o crc32.o crctab.o crypt.o \
+ ttyio.o amiga.o amigazip.o time_lib.o
+OBJI = deflate.o trees.o
+OBJU = zipfile.oo fileio.oo util.oo globals.o amiga.o amigazip.oo time_lib.o
+
+OBJZ = zip.o $(OBJA) $(OBJI)
+
+OBJN = zipnote.o $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt.oo ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIPS = zip zipnote zipcloak zipsplit
+
+all: Message $(ZIPS)
+
+Message:
+ -echo " "
+ -echo "WARNING: Lattice 5.x HAS NOT BEEN TESTED WITH THIS ZIP VERSION"
+ -echo "Report problems to <zip-bugs@lists.wku.edu>"
+ -echo " "
+
+zip: $(OBJZ) $(HFILES)
+ -echo "$(OBJZ)" > $(TMPFILE)
+ $(LD) TO Zip FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)
+ -delete $(TMPFILE) Zip.info
+
+zipnote: $(OBJN) $(HFILES)
+ -echo "$(OBJN)" > $(TMPFILE)
+ $(LD) TO ZipNote FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)
+ -delete $(TMPFILE) ZipNote.info
+
+zipcloak: $(OBJC) $(HFILES)
+ -echo "$(OBJC)" > $(TMPFILE)
+ $(LD) TO ZipCloak FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)
+ -delete $(TMPFILE) ZipCloak.info
+
+zipsplit: $(OBJS) $(HFILES)
+ -echo "$(OBJS)" > $(TMPFILE)
+ $(LD) TO ZipSplit FROM $(LDSTART) WITH $(TMPFILE) $(LDFLAGS) $(LDBG)
+ -delete $(TMPFILE) ZipSplit.info
+
+clean:
+ -delete $(OBJZ) all quiet force >nil:
+ -delete $(OBJU) all quiet force >nil:
+ -delete $(OBJA) all quiet force >nil:
+ -delete $(OBJI) all quiet force >nil:
+ -delete $(OBJN) all quiet force >nil:
+ -delete $(OBJC) all quiet force >nil:
+ -delete $(OBJS) all quiet force >nil:
+
+zip.o: zip.c $(HFILES)
+zipnote.o: zipnote.c $(HFILES)
+zipcloak.o: zipcloak.c $(HFILES)
+crypt.o: crypt.c $(HFILES)
+ttyio.o: ttyio.c $(HFILES)
+zipsplit.o: zipsplit.c $(HFILES)
+deflate.o: deflate.c $(HFILES)
+trees.o: trees.c $(HFILES)
+zipfile.o: zipfile.c $(HFILES)
+zipup.o: zipup.c $(HFILES)
+fileio.o: fileio.c $(HFILES)
+util.o: util.c $(HFILES)
+crc32.o: crc32.c $(HFILES)
+crctab.o: crctab.c $(HFILES)
+globals.o: globals.c $(HFILES)
+
+# Amiga specific objects
+amiga.o: amiga/amiga.c $(HFILES)
+amigazip.o: amiga/amigazip.c $(HFILES)
+time_lib.o: amiga/time_lib.c
+
+# end of Makefile
diff --git a/amiga/README b/amiga/README
new file mode 100644
index 0000000..861ff85
--- /dev/null
+++ b/amiga/README
@@ -0,0 +1 @@
+the -A option currently does not work for the amiga.
diff --git a/amiga/amiga.c b/amiga/amiga.c
new file mode 100644
index 0000000..93bd495
--- /dev/null
+++ b/amiga/amiga.c
@@ -0,0 +1,143 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* OS specific routines for AMIGA platform.
+ *
+ * John Bush <John.Bush@east.sun.com> BIX: jbush
+ * Paul Kienitz <kie@pacbell.net>
+ *
+ * History:
+ *
+ * Date DoBee Comments
+ * ------- -------- -----------------------------------------------
+ * 21Jan93 JBush Original coding.
+ * Incorporated filedate.c (existing routine).
+ *
+ * 31Jan93 JBush Made filedate.c include unconditional.
+ *
+ * 18Jul93 PaulK Moved Aztec _abort() here from stat.c because we
+ * can't share the same one between Zip and UnZip.
+ * Added close_leftover_open_dirs() call to it.
+ *
+ * 17Apr95 PaulK Added Amiga internal version string so that
+ * installer programs can compare the version being
+ * installed to see if the copy the user already has
+ * is older or newer. Added Prestart_Hook to support
+ * debug tracing in deflate.a.
+ *
+ * 6May95 PaulK Added GetComment() for filenote support.
+ *
+ * 12Nov95 PaulK Added #define ZIP in front of filedate.c, for
+ * new options in there; removed declare of set_con()
+ * since echon() no longer expands to it (or anything).
+ *
+ * 12Feb96 PaulK Removed call of echon() entirely.
+ *
+ * 12Jul97 PaulK Made both Aztec and SAS define USE_TIME_LIB for filedate.c
+ *
+ * 26Aug97 PaulK Added ClearIOErr_exit()
+ *
+ * 2Jan98 HWalt Adapted for SAS/C using stat.c replacement functions
+ */
+
+#include <exec/memory.h>
+#ifdef AZTEC_C
+# include <libraries/dos.h>
+# include <libraries/dosextens.h>
+# include <clib/exec_protos.h>
+# include <clib/dos_protos.h>
+# include <pragmas/exec_lib.h>
+# include <pragmas/dos_lib.h>
+#else
+# include <proto/exec.h>
+# include <proto/dos.h>
+#endif
+#include <stdlib.h>
+
+#ifndef ZCONST
+# define ZCONST const
+#endif
+#include "ziperr.h"
+void ziperr(int c, ZCONST char *h);
+
+#if defined(AZTEC_C) || defined(__SASC)
+# define USE_TIME_LIB
+#endif
+
+#define ZIP
+#if !defined(UTIL) && !defined(USE_TIME_LIB)
+# define NO_MKTIME
+#endif
+
+#ifdef AZTEC_C
+
+/* ============================================================= */
+/* filedate.c is an external file, since it's shared with UnZip. */
+/* Aztec includes it here, but SAS/C now compiles it separately. */
+# include "amiga/filedate.c"
+
+/* the same applies to stat.c */
+# include "amiga/stat.c"
+
+# define setenv BOGUS_INCOMPATIBLE_setenv
+# include <fcntl.h>
+# undef setenv
+# ifdef DEBUG
+# define PRESTART_HOOK
+# endif
+#endif
+
+extern void close_leftover_open_dirs(void);
+
+
+/* the following handles cleanup when a ^C interrupt happens: */
+
+void _abort(void) /* called when ^C is pressed */
+{
+ close_leftover_open_dirs();
+ ziperr(ZE_ABORT, "^C");
+}
+
+void ClearIOErr_exit(int e) /* EXIT is defined as this */
+{
+ if (!e)
+ ((struct Process *) FindTask(NULL))->pr_Result2 = 0;
+ /* we clear IoErr() since we are successful, in a 1.x-compatible way */
+ exit(e);
+}
+
+
+/* Make sure the version number here matches the number in revision.h */
+/* as closely as possible in strict decimal "#.#" form: */
+const char version_id[] = "\0$VER: Zip 2.3 ("
+# include "env:VersionDate"
+")\r\n";
+
+/* call this with an arg of NULL to free storage: */
+
+char *GetComment(char *filename)
+{
+ BPTR lk;
+ static struct FileInfoBlock *fib = NULL;
+
+ if (!filename) {
+ if (fib) FreeMem(fib, sizeof(*fib));
+ fib = NULL;
+ return NULL;
+ }
+ if (!fib) {
+ if (!(fib = AllocMem(sizeof(*fib), MEMF_PUBLIC)))
+ ziperr(ZE_MEM, "was checking filenotes");
+ }
+ if (!(lk = Lock(filename, ACCESS_READ)))
+ return NULL;
+ if (!Examine(lk, fib))
+ fib->fib_Comment[0] = '\0';
+ UnLock(lk);
+ return fib->fib_Comment[0] ? &fib->fib_Comment[0] : NULL;
+}
diff --git a/amiga/amiga.h b/amiga/amiga.h
new file mode 100644
index 0000000..a1461d8
--- /dev/null
+++ b/amiga/amiga.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __amiga_amiga_h
+#define __amiga_amiga_h
+
+/* amiga.h
+ *
+ * Globular definitions that affect all of AmigaDom.
+ *
+ * Originally included in unzip.h, extracted for simplicity and eeze of
+ * maintenance by John Bush.
+ *
+ * This version is for use with Zip. It is not globally included, but used
+ * only by functions in amiga/amigazip.c. Much material that was needed for
+ * UnZip is absent here.
+ *
+ */
+
+#include <fcntl.h> /* O_BINARY for open() w/o CR/LF translation */
+#include "amiga/z-stat.h" /* substitute for <stat.h> and <dire(c|n)t.h> */
+#define direct dirent
+
+#ifndef MODERN
+# define MODERN
+#endif
+
+#ifdef AZTEC_C /* Manx Aztec C, 5.0 or newer only */
+# include <clib/dos_protos.h>
+# include <pragmas/dos_lib.h> /* do inline dos.library calls */
+# define O_BINARY 0
+#endif /* AZTEC_C */
+
+
+#ifdef __SASC
+# include <dirent.h>
+# include <dos.h>
+# define disk_not_mounted 0
+# if ( (!defined(O_BINARY)) && defined(O_RAW))
+# define O_BINARY O_RAW
+# endif
+#endif /* SASC */
+
+
+/* Funkshine Prough Toe Taipes */
+
+LONG FileDate (char *, time_t[]);
+
+#endif /* __amiga_amiga_h */
diff --git a/amiga/amigazip.c b/amiga/amigazip.c
new file mode 100644
index 0000000..f72f27d
--- /dev/null
+++ b/amiga/amigazip.c
@@ -0,0 +1,510 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "zip.h"
+#include "amiga/amiga.h"
+
+#ifndef UTIL /* the companion #endif is a bit of ways down ... */
+
+#define utime FileDate
+
+#define PAD 0
+#define PATH_END '/'
+
+/* Local globals (kinda like "military intelligence" or "broadcast quality") */
+
+extern char *label; /* still declared in fileio.c */
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+/* Local functions */
+local char *readd OF((DIR *));
+local int wild_recurse OF((char *, char *));
+
+
+local char *readd(d)
+DIR *d; /* directory stream to read from */
+/* Return a pointer to the next name in the directory stream d, or NULL if
+ no more entries or an error occurs. */
+{
+ struct dirent *e = readdir(d);
+ return e == NULL ? (char *) NULL : e->d_name;
+}
+
+
+/* What we have here is a mostly-generic routine using opendir()/readd() and */
+/* isshexp()/MATCH() to find all the files matching a multi-part filespec */
+/* using the portable pattern syntax. It shouldn't take too much fiddling */
+/* to make it usable for any other platform that has directory hierarchies */
+/* but no shell-level pattern matching. It works for patterns throughout */
+/* the pathname, such as "foo:*.?/source/x*.[ch]". */
+
+#define ONENAMELEN 30
+/* the length of one filename component on the Amiga */
+
+/* whole is a pathname with wildcards, wildtail points somewhere in the */
+/* middle of it. All wildcards to be expanded must come AFTER wildtail. */
+
+local int wild_recurse(whole, wildtail) char *whole; char *wildtail;
+{
+ DIR *dir;
+ char *subwild, *name, *newwhole = NULL, *glue = NULL, plug = 0, plug2;
+ ush newlen, amatch = 0;
+ BPTR lok;
+ int e = ZE_MISS;
+
+ if (!isshexp(wildtail))
+ if (lok = Lock(whole, ACCESS_READ)) { /* p exists? */
+ UnLock(lok);
+ return procname(whole, 0);
+ } else
+ return ZE_MISS; /* woops, no wildcards! */
+
+ /* back up thru path components till existing dir found */
+ do {
+ name = wildtail + strlen(wildtail) - 1;
+ for (;;)
+ if (name-- <= wildtail || *name == PATH_END) {
+ subwild = name + 1;
+ plug2 = *subwild;
+ *subwild = 0;
+ break;
+ }
+ if (glue)
+ *glue = plug;
+ glue = subwild;
+ plug = plug2;
+ dir = opendir(whole);
+ } while (!dir && !disk_not_mounted && subwild > wildtail);
+ wildtail = subwild; /* skip past non-wild components */
+
+ if ((subwild = strchr(wildtail + 1, PATH_END)) != NULL) {
+ /* this "+ 1" dodges the ^^^ hole left by *glue == 0 */
+ *(subwild++) = 0; /* wildtail = one component pattern */
+ newlen = strlen(whole) + strlen(subwild) + (ONENAMELEN + 2);
+ } else
+ newlen = strlen(whole) + (ONENAMELEN + 1);
+ if (!dir || !(newwhole = malloc(newlen))) {
+ if (glue)
+ *glue = plug;
+
+ e = dir ? ZE_MEM : ZE_MISS;
+ goto ohforgetit;
+ }
+ strcpy(newwhole, whole);
+ newlen = strlen(newwhole);
+ if (glue)
+ *glue = plug; /* repair damage to whole */
+ if (!isshexp(wildtail)) {
+ e = ZE_MISS; /* non-wild name not found */
+ goto ohforgetit;
+ }
+
+ while (name = readd(dir)) {
+ if (MATCH(wildtail, name, 0)) {
+ strcpy(newwhole + newlen, name);
+ if (subwild) {
+ name = newwhole + strlen(newwhole);
+ *(name++) = PATH_END;
+ strcpy(name, subwild);
+ e = wild_recurse(newwhole, name);
+ } else
+ e = procname(newwhole, 0);
+ newwhole[newlen] = 0;
+ if (e == ZE_OK)
+ amatch = 1;
+ else if (e != ZE_MISS)
+ break;
+ }
+ }
+
+ ohforgetit:
+ if (dir) closedir(dir);
+ if (subwild) *--subwild = PATH_END;
+ if (newwhole) free(newwhole);
+ if (e == ZE_MISS && amatch)
+ e = ZE_OK;
+ return e;
+}
+
+int wild(p) char *p;
+{
+ char *use;
+
+ /* special handling of stdin request */
+ if (strcmp(p, "-") == 0) /* if compressing stdin */
+ return newname(p, 0, 0);
+
+ /* wild_recurse() can't handle colons in wildcard part: */
+ if (use = strchr(p, ':')) {
+ if (strchr(++use, ':'))
+ return ZE_PARMS;
+ } else
+ use = p;
+
+ return wild_recurse(p, use);
+}
+
+
+int procname(n, caseflag)
+char *n; /* name to process */
+int caseflag; /* true to force case-sensitive match */
+/* Process a name or sh expression to operate on (or exclude). Return
+ an error code in the ZE_ class. */
+{
+ char *a; /* path and name for recursion */
+ DIR *d; /* directory stream from opendir() */
+ char *e; /* pointer to name from readd() */
+ int m; /* matched flag */
+ char *p; /* path for recursion */
+ struct stat s; /* result of stat() */
+ struct zlist far *z; /* steps through zfiles list */
+
+ if (strcmp(n, "-") == 0) /* if compressing stdin */
+ return newname(n, 0, caseflag);
+ else if (LSSTAT(n, &s))
+ {
+ /* Not a file or directory--search for shell expression in zip file */
+ p = ex2in(n, 0, (int *)NULL); /* shouldn't affect matching chars */
+ m = 1;
+ for (z = zfiles; z != NULL; z = z->nxt) {
+ if (MATCH(p, z->iname, caseflag))
+ {
+ z->mark = pcount ? filter(z->zname, caseflag) : 1;
+ if (verbose)
+ fprintf(mesg, "zip diagnostic: %scluding %s\n",
+ z->mark ? "in" : "ex", z->name);
+ m = 0;
+ }
+ }
+ free((zvoid *)p);
+ return m ? ZE_MISS : ZE_OK;
+ }
+
+ /* Live name--use if file, recurse if directory */
+ if ((s.st_mode & S_IFDIR) == 0)
+ {
+ /* add or remove name of file */
+ if ((m = newname(n, 0, caseflag)) != ZE_OK)
+ return m;
+ } else {
+ /* Add trailing / to the directory name */
+ if ((p = malloc(strlen(n)+2)) == NULL)
+ return ZE_MEM;
+ strcpy(p, n);
+ a = p + strlen(p);
+ if (*p && a[-1] != '/' && a[-1] != ':')
+ strcpy(a, "/");
+ if (dirnames && (m = newname(p, 1, caseflag)) != ZE_OK) {
+ free((zvoid *)p);
+ return m;
+ }
+ /* recurse into directory */
+ if (recurse && (d = opendir(n)) != NULL)
+ {
+ while ((e = readd(d)) != NULL) {
+ if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
+ {
+ closedir(d);
+ free((zvoid *)p);
+ return ZE_MEM;
+ }
+ strcat(strcpy(a, p), e);
+ if ((m = procname(a, caseflag)) != ZE_OK) /* recurse on name */
+ {
+ if (m == ZE_MISS)
+ zipwarn("name not matched: ", a);
+ else
+ ziperr(m, a);
+ }
+ free((zvoid *)a);
+ }
+ closedir(d);
+ }
+ free((zvoid *)p);
+ } /* (s.st_mode & S_IFDIR) == 0) */
+ return ZE_OK;
+}
+
+char *ex2in(x, isdir, pdosflag)
+char *x; /* external file name */
+int isdir; /* input: x is a directory */
+int *pdosflag; /* output: force MSDOS file attributes? */
+/* Convert the external file name to a zip file name, returning the malloc'ed
+ string or NULL if not enough memory. */
+{
+ char *n; /* internal file name (malloc'ed) */
+ char *t; /* shortened name */
+ int dosflag;
+
+ dosflag = dosify; /* default for non-DOS and non-OS/2 */
+
+ /* Find starting point in name before doing malloc */
+ if ((t = strrchr(x, ':')) != NULL) /* reject ":" */
+ t++;
+ else
+ t = x;
+ { /* reject "//" */
+ char *tt = t;
+ while (tt = strchr(tt, '/'))
+ while (*++tt == '/')
+ t = tt;
+ }
+ while (*t == '/') /* reject leading "/" on what's left */
+ t++;
+
+ if (!pathput)
+ t = last(t, PATH_END);
+
+ /* Malloc space for internal name and copy it */
+ if ((n = malloc(strlen(t) + 1)) == NULL)
+ return NULL;
+ strcpy(n, t);
+
+ if (dosify)
+ msname(n);
+ /* Returned malloc'ed name */
+ if (pdosflag)
+ *pdosflag = dosflag;
+ return n;
+}
+
+char *in2ex(n)
+char *n; /* internal file name */
+/* Convert the zip file name to an external file name, returning the malloc'ed
+ string or NULL if not enough memory. */
+{
+ char *x; /* external file name */
+
+ if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+ return NULL;
+ strcpy(x, n);
+ return x;
+}
+
+void stamp(f, d)
+char *f; /* name of file to change */
+ulg d; /* dos-style time to change it to */
+/* Set last updated and accessed time of file f to the DOS time d. */
+{
+ time_t u[2]; /* argument for utime() */
+
+ /* Convert DOS time to time_t format in u */
+ u[0] = u[1] = dos2unixtime(d);
+
+ /* Set updated and accessed times of f */
+ utime(f, u);
+}
+
+ulg filetime(f, a, n, t)
+char *f; /* name of file to get info on */
+ulg *a; /* return value: file attributes */
+long *n; /* return value: file size */
+iztimes *t; /* return value: access, modific. and creation times */
+/* If file *f does not exist, return 0. Else, return the file's last
+ modified date and time as an MSDOS date and time. The date and
+ time is returned in a long with the date most significant to allow
+ unsigned integer comparison of absolute times. Also, if a is not
+ a NULL pointer, store the file attributes there, with the high two
+ bytes being the Unix attributes, and the low byte being a mapping
+ of that to DOS attributes. If n is not NULL, store the file size
+ there. If t is not NULL, the file's access, modification and creation
+ times are stored there as UNIX time_t values.
+ If f is "-", use standard input as the file. If f is a device, return
+ a file size of -1 */
+{
+ struct stat s; /* results of stat() */
+ char *name;
+ unsigned int len = strlen(f);
+
+ if (f == label) {
+ if (a != NULL)
+ *a = label_mode;
+ if (n != NULL)
+ *n = -2L; /* convention for a label name */
+ if (t != NULL)
+ t->atime = t->mtime = t->ctime = label_utim;
+ return label_time;
+ }
+
+ if ((name = malloc(len + 1)) == NULL) {
+ ZIPERR(ZE_MEM, "filetime");
+ }
+ strcpy(name, f);
+ if (name[len - 1] == '/')
+ name[len - 1] = '\0';
+ /* not all systems allow stat'ing a file with / appended */
+
+ if (strcmp(f, "-") == 0) {
+ if (fstat(fileno(stdin), &s) != 0) {
+ free(name);
+ error("fstat(stdin)");
+ }
+ } else if (SSTAT(name, &s) != 0) {
+ /* Accept about any file kind including directories
+ * (stored with trailing / with -r option)
+ */
+ free(name);
+ return 0;
+ }
+
+ if (a != NULL) {
+ *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWRITE);
+ if ((s.st_mode & S_IFDIR) != 0) {
+ *a |= MSDOS_DIR_ATTR;
+ }
+ }
+ if (n != NULL)
+ *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+ if (t != NULL) {
+ t->atime = s.st_atime;
+ t->mtime = s.st_mtime;
+ t->ctime = s.st_ctime;
+ }
+
+ free(name);
+
+ return unix2dostime(&s.st_mtime);
+}
+
+int set_extra_field(z, z_utim)
+ struct zlist far *z;
+ iztimes *z_utim;
+ /* create extra field and change z->att if desired */
+{
+#ifdef USE_EF_UT_TIME
+#ifdef IZ_CHECK_TZ
+ if (!zp_tz_is_valid) return ZE_OK; /* skip silently if no valid TZ info */
+#endif
+
+ if ((z->extra = (char *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)
+ return ZE_MEM;
+
+ z->extra[0] = 'U';
+ z->extra[1] = 'T';
+ z->extra[2] = EB_UT_LEN(1); /* length of data part of e.f. */
+ z->extra[3] = 0;
+ z->extra[4] = EB_UT_FL_MTIME;
+ z->extra[5] = (char)(z_utim->mtime);
+ z->extra[6] = (char)(z_utim->mtime >> 8);
+ z->extra[7] = (char)(z_utim->mtime >> 16);
+ z->extra[8] = (char)(z_utim->mtime >> 24);
+
+ z->cextra = z->extra;
+ z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1));
+
+ return ZE_OK;
+#else /* !USE_EF_UT_TIME */
+ return (int)(z-z);
+#endif /* ?USE_EF_UT_TIME */
+}
+
+int deletedir(d)
+char *d; /* directory to delete */
+/* Delete the directory *d if it is empty, do nothing otherwise.
+ Return the result of rmdir(), delete(), or system().
+ For VMS, d must be in format [x.y]z.dir;1 (not [x.y.z]).
+ */
+{
+ return rmdir(d);
+}
+
+#endif /* !UTIL */
+
+
+/******************************/
+/* Function version_local() */
+/******************************/
+
+
+/* NOTE: the following include depends upon the environment
+ * variable $Workbench to be set correctly. (Set by
+ * default, by Version command in Startup-sequence.)
+ */
+int WBversion = (int)
+#include "ENV:Workbench"
+;
+
+void version_local()
+{
+ static ZCONST char CompiledWith[] = "Compiled with %s%s under %s%s%s%s.\n\n";
+
+/* Define buffers. */
+
+ char buf1[16]; /* compiler name */
+ char buf2[16]; /* revstamp */
+ char buf3[16]; /* OS */
+ char buf4[16]; /* Date */
+/* char buf5[16]; /* Time */
+
+/* format "with" name strings */
+
+#ifdef AMIGA
+# ifdef __SASC
+ strcpy(buf1,"SAS/C ");
+# else
+# ifdef LATTICE
+ strcpy(buf1,"Lattice C ");
+# else
+# ifdef AZTEC_C
+ strcpy(buf1,"Manx Aztec C ");
+# else
+ strcpy(buf1,"UNKNOWN ");
+# endif
+# endif
+# endif
+/* "under" */
+ sprintf(buf3,"AmigaDOS v%d",WBversion);
+#else
+ strcpy(buf1,"Unknown compiler ");
+ strcpy(buf3,"Unknown OS");
+#endif
+
+/* Define revision, date, and time strings.
+ * NOTE: Do not calculate run time, be sure to use time compiled.
+ * Pass these strings via your makefile if undefined.
+ */
+
+#if defined(__VERSION__) && defined(__REVISION__)
+ sprintf(buf2,"version %d.%d",__VERSION__,__REVISION__);
+#else
+# ifdef __VERSION__
+ sprintf(buf2,"version %d",__VERSION__);
+# else
+ sprintf(buf2,"unknown version");
+# endif
+#endif
+
+#ifdef __DATE__
+ sprintf(buf4," on %s",__DATE__);
+#else
+ strcpy(buf4," unknown date");
+#endif
+
+/******
+#ifdef __TIME__
+ sprintf(buf5," at %s",__TIME__);
+#else
+ strcpy(buf5," unknown time");
+#endif
+******/
+
+/* Print strings using "CompiledWith" mask defined above.
+ * ("Compiled with %s%s under %s%s%s%s.")
+ */
+
+ printf(CompiledWith,
+ buf1,
+ buf2,
+ buf3,
+ buf4,
+ /* buf5, */ "",
+ "" ); /* buf6 not used */
+
+} /* end function version_local() */
diff --git a/amiga/crc_68.a b/amiga/crc_68.a
new file mode 100644
index 0000000..809a0ba
--- /dev/null
+++ b/amiga/crc_68.a
@@ -0,0 +1,144 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; crc_68 created by Paul Kienitz, last modified 04 Jan 96.
+;
+; Return an updated 32 bit CRC value, given the old value and a block of data.
+; The CRC table used to compute the value is gotten by calling get_crc_table().
+; This replaces the older updcrc() function used in Zip and fUnZip. The
+; prototype of the function is:
+;
+; ulg crc32(ulg crcval, uch *text, extent textlen);
+;
+; On the Amiga, type extent is always unsigned long, not unsigned int, because
+; int can be short or long at whim, but size_t is long.
+;
+; If using this source on a non-Amiga 680x0 system, note that we treat
+; a0/a1/d0/d1 as scratch registers not preserved across function calls.
+; We do not bother to support registerized arguments for crc32() -- the
+; textlen parm is usually large enough so that savings outside the loop
+; are pointless.
+;
+; Define NO_UNROLLED_LOOPS to use a simple short loop which might be more
+; efficient on certain machines with dinky instruction caches ('020?), or for
+; processing short strings. If loops are unrolled, the textlen parm must be
+; less than 512K; if not unrolled, it must be less than 64K.
+
+ xdef _crc32 ; (ulg val, uch *buf, extent bufsize)
+
+DO_CRC0 MACRO
+ moveq #0,ltemp
+ move.b (textbuf)+,ltemp
+ eor.b crcval,ltemp
+ lsl.w #2,ltemp
+ move.l (crc_table,ltemp.w),ltemp
+ lsr.l #8,crcval
+ eor.l ltemp,crcval
+ ENDM
+
+ machine mc68020
+
+DO_CRC2 MACRO
+ move.b (textbuf)+,btemp
+ eor.b crcval,btemp
+ lsr.l #8,crcval
+ move.l (crc_table,btemp.w*4),ltemp
+ eor.l ltemp,crcval
+ ENDM
+
+crc_table equr a0 array of unsigned long
+crcval equr d0 unsigned long initial value
+textbuf equr a1 array of unsigned char
+textbufsize equr d1 unsigned long (count of bytes in textbuf)
+btemp equr d2
+ltemp equr d3
+
+
+ xref _get_crc_table ; ulg *get_crc_table(void)
+
+ NOLIST
+ INCLUDE 'exec/execbase.i'
+ LIST
+ xref _SysBase ; struct ExecBase *
+
+
+_crc32:
+ move.l 8(sp),d0
+ bne.s valid
+ moveq #0,d0
+ rts
+valid: movem.l btemp/ltemp,-(sp)
+ jsr _get_crc_table
+ move.l d0,ltemp
+ move.l 12(sp),crcval
+ move.l 16(sp),textbuf
+ move.l 20(sp),textbufsize
+ not.l crcval
+ move.l _SysBase,crc_table
+ move.w AttnFlags(crc_table),btemp
+ move.l ltemp,crc_table
+ btst #AFB_68020,btemp
+ bne twenty
+
+ IFD NO_UNROLLED_LOOPS
+
+ bra.s decr
+loop: DO_CRC0
+decr: dbra textbufsize,loop
+ bra.s done
+
+twenty: moveq #0,btemp
+ bra.s decr2
+loop2: DO_CRC2
+decr2: dbra textbufsize,loop2
+
+ ELSE ; !NO_UNROLLED_LOOPS
+
+ move.l textbufsize,btemp
+ lsr.l #3,textbufsize
+ bra decr8
+loop8: DO_CRC0
+ DO_CRC0
+ DO_CRC0
+ DO_CRC0
+ DO_CRC0
+ DO_CRC0
+ DO_CRC0
+ DO_CRC0
+decr8: dbra textbufsize,loop8
+ and.w #7,btemp
+ bra.s decr1
+loop1: DO_CRC0
+decr1: dbra btemp,loop1
+ bra done
+
+twenty: moveq #0,btemp
+ move.l textbufsize,-(sp)
+ lsr.l #3,textbufsize
+ bra decr82
+loop82: DO_CRC2
+ DO_CRC2
+ DO_CRC2
+ DO_CRC2
+ DO_CRC2
+ DO_CRC2
+ DO_CRC2
+ DO_CRC2
+decr82: dbra textbufsize,loop82
+ move.l (sp)+,textbufsize
+ and.w #7,textbufsize
+ bra.s decr12
+loop12: DO_CRC2
+decr12: dbra textbufsize,loop12
+
+ ENDC ; ?NO_UNROLLED_LOOPS
+
+done: movem.l (sp)+,btemp/ltemp
+ not.l crcval
+;;;;; move.l crcval,d0 ; crcval already is d0
+ rts
diff --git a/amiga/deflate.a b/amiga/deflate.a
new file mode 100644
index 0000000..b21adae
--- /dev/null
+++ b/amiga/deflate.a
@@ -0,0 +1,1053 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; This is a 680x0 assembly language translation of the Info-ZIP source file
+; deflate.c, by Paul Kienitz. The function longest_match is based in part
+; on match.a by Carsten Steger, which in turn is partly based on match.s
+; for 386 by Jean-loup Gailly and Kai Uwe Rommel. Mostly, however, this
+; material is based on deflate.c, by Gailly, Rommel, and Igor Mandrichenko.
+; This code is not commented very much; see deflate.c for comments that explain
+; what the functions are doing.
+;
+; The symbols that can be used to select different versions are as follows:
+;
+; CPU020 if defined, use 68020 instructions always.
+;
+; CPUTEST if defined, check at runtime for CPU type. Another symbol
+; specifying the platform-specific test must be used with this.
+; If neither of these is defined, use 68000 instructions only.
+; Runtime test is nonportable; it is different for each OS.
+;
+; AMIGA use Amiga-specific test for 68020, if CPUTEST defined. Also
+; tells it that registers d0/a0/d1/a1 are not preserved by
+; function calls. At present, if AMIGA is not defined, it
+; causes functions to preserve all registers. ALL OF THIS CODE
+; CURRENTLY ASSUMES THAT REGISTERS D2-D7/A2-A6 WILL BE PRESERVED
+; BY ANY FUNCTIONS THAT IT CALLS.
+;
+; DYN_ALLOC should be defined here if it is defined for C source; tells us
+; that big arrays are allocated instead of static.
+;
+; WSIZE must be defined as the same number used for WSIZE in the C
+; source, and must be a power of two <= 32768. As elsewhere,
+; the default value is 32768.
+;
+; INT16 define this if ints are 16 bits; otherwise 32 bit ints assumed.
+;
+; SMALL_MEM define this if it is defined in the C source; otherwise it uses
+; the MEDIUM_MEM model. BIG_MEM and MMAP are *not* supported.
+; The FULL_SEARCH option in deflate.c is also not supported.
+;
+; DEBUG activates some tracing output, as in the C source.
+;
+; QUADLONG this selects a different version of the innermost longest_match
+; loop code for 68020 operations, comparing bytes four at a time
+; instead of two at a time. It seems to be a tiny bit faster on
+; average, but it's slower often enough that one can't generalize.
+;
+; This code currently assumes that function results are returned in D0 for
+; all platforms. It assumes that args to functions are pushed onto the stack,
+; last arg first. It also currently assumes that all C symbols have an
+; underscore prepended when referenced from assembly.
+
+ IFND CPU020
+ IFND CPUTEST
+CPU000 equ 1
+ ENDC
+ ENDC
+
+; Use these macros for accessing variables of type int:
+ IFD INT16
+MOVINT MACRO
+ move.w \1,\2
+ ENDM
+CLRINT MACRO
+ clr.w \1
+ ENDM
+INTSIZE equ 2
+ ELSE ; !INT16
+MOVINT MACRO
+ move.l \1,\2
+ ENDM
+CLRINT MACRO
+ clr.l \1
+ ENDM
+INTSIZE equ 4
+ ENDC
+
+ IFD DYN_ALLOC
+BASEPTR MACRO
+ move.l \1,\2
+ ENDM
+ ELSE
+BASEPTR MACRO
+ lea \1,\2
+ ENDM
+ ENDC
+
+; constants we use, many of them adjustable:
+
+MAX_MATCH equ 258
+MIN_MATCH equ 3
+TOO_FAR equ 4096
+ IFND WSIZE
+WSIZE equ 32768
+ ENDC
+WMASK equ WSIZE-1
+MAX_DIST equ WSIZE-MAX_MATCH-MIN_MATCH-1
+MIN_LOOKAHEAD equ MAX_MATCH+MIN_MATCH+1
+; IFD BIG_MEM ; NOT supported -- type Pos needs to be 32 bits
+;HASH_BITS equ 15
+; ELSE
+ IFD SMALL_MEM
+HASH_BITS equ 13
+ ELSE
+HASH_BITS equ 14 ; default -- MEDIUM_MEM
+ ENDC
+; ENDC ; BIG_MEM
+HASH_SIZE equ 1<<HASH_BITS
+HASH_MASK equ HASH_SIZE-1
+H_SHIFT equ (HASH_BITS+MIN_MATCH-1)/MIN_MATCH
+B_SLOW equ 1
+B_FAST equ 2
+ZE_MEM equ 4
+EOF equ -1
+
+; struct config is defined by these offsets:
+Good_length equ 0
+Max_lazy equ 2
+Nice_length equ 4
+Max_chain equ 6
+Sizeof_config equ 8
+
+
+; external functions we call:
+ xref _ct_tally ; int ct_tally(int, int)
+ xref _flush_block ; unsigned long F(char *, unsigned long, int)
+ xref _ziperr ; void ziperr(int, char *)
+ xref _error ; void error(char *)
+ xref _calloc ; stdlib function: void *calloc(size_t, size_t)
+ xref _free ; stdlib function: void free(void *)
+ IFD DEBUG
+ xref _fputc ; stdio function: int fputc(int, FILE *)
+ xref _stderr ; pointer to FILE, which we pass to fputc
+ ENDC
+
+; our entry points:
+ xdef _lm_init ; void lm_init(int level, unsigned short *flags)
+ xdef _lm_free ; void lm_free(void)
+ xdef _deflate ; void deflate(void) ...the big one
+ xdef _fill_window ; this line is just for debugging
+
+
+; ============================================================================
+; Here is where we have our global variables.
+
+ section deflatevars,data
+
+; external global variables we reference:
+ xref _verbose ; signed int
+ xref _level ; signed int
+ xref _read_buf ; int (*read_buf)(char *, unsigned int)
+
+; global variables we make available:
+
+ xdef _window
+ xdef _prev
+ xdef _head
+ xdef _window_size
+ xdef _block_start
+ xdef _strstart
+
+ IFD DYN_ALLOC
+_prev: ds.l 1 ; pointer to calloc()'d unsigned short array
+_head: ds.l 1 ; pointer to calloc()'d unsigned short array
+_window: ds.l 1 ; pointer to calloc()'d unsigned char array
+ ELSE ; !DYN_ALLOC
+_prev: ds.w WSIZE ; array of unsigned short
+_head: ds.w HASH_SIZE ; array of unsigned short
+_window: ds.b 2*WSIZE ; array of unsigned char
+ ENDC ; ?DYN_ALLOC
+_window_size: ds.l 1 ; unsigned long
+_block_start: ds.l 1 ; unsigned long
+_strstart: ds.w INTSIZE/2 ; unsigned int
+
+; Now here are our private variables:
+
+ IFD CPUTEST
+is020: ds.w 1 ; bool: CPU type is '020 or higher
+ ENDC
+ins_h: ds.w 1 ; unsigned short
+sliding: ds.w 1 ; bool: the file is read a piece at a time
+eofile: ds.w 1 ; bool: we have read in the end of the file
+max_lazy_match: ds.w 1 ; unsigned short
+lookahead: ds.w 1 ; unsigned short
+
+; These are NOT DECLARED AS STATIC in deflate.c, but currently could be:
+max_chain_len: ds.w 1 ; unsigned short (unsigned int in deflate.c)
+prev_length: ds.w 1 ; unsigned short (unsigned int in deflate.c)
+good_match: ds.w 1 ; unsigned short (unsigned int in deflate.c)
+nice_match: ds.w 1 ; unsigned short (signed int in deflate.c)
+match_start: ds.w 1 ; unsigned short (unsigned int in deflate.c)
+
+; This array of struct config is a constant and could be in the code section:
+config_table: dc.w 0,0,0,0 ; level 0: store uncompressed
+ dc.w 4,4,8,4 ; level 1: fastest, loosest compression
+ dc.w 4,5,16,8 ; level 2
+ dc.w 4,6,32,32 ; level 3: highest to use deflate_fast
+ dc.w 4,4,16,16 ; level 4: lowest to use lazy matches
+ dc.w 8,16,32,32 ; level 5
+ dc.w 8,16,128,128 ; level 6: the default level
+ dc.w 8,32,128,256 ; level 7
+ dc.w 32,128,258,1024 ; level 8
+ dc.w 32,258,258,4096 ; level 9: maximum compression, slow
+
+
+;;CAL_SH MACRO ; macro for calling zcalloc()
+;; IFD INT16
+;; move.w #2,-(sp)
+;; move.w #\1,-(sp)
+;; jsr _zcalloc
+;; addq #4,sp
+;; ELSE
+;; pea 2
+;; pea \1
+;; jsr _zcalloc
+;; addq #8,sp
+;; ENDC
+;; ENDM
+
+CAL_SH MACRO ; Okay, we're back to using regular calloc()...
+ pea 2
+ pea \1
+ jsr _calloc
+ addq #8,sp
+ ENDM
+
+; ============================================================================
+; And here we begin our functions. match_init is for internal use only:
+
+ section deflate,code
+
+match_init:
+ IFD CPUTEST ; now check for platform type
+ IFD AMIGA ; Amiga specific test for '020 CPU:
+ xref _SysBase
+ NOLIST
+ INCLUDE 'exec/execbase.i'
+ LIST
+
+ clr.w is020 ; default value is 68000
+ move.l _SysBase,a0
+ btst #AFB_68020,AttnFlags+1(a0)
+ beq.s cheap
+ move.w #1,is020
+cheap:
+ ELSE ; !AMIGA
+
+ FAIL Write an '020-detector for your system here!
+; On the Macintosh, I believe GetEnvironment() provides the information.
+
+ ENDC ; AMIGA
+ ENDC ; CPUTEST
+ rts ; match_init consists only of rts if CPUTEST unset
+
+
+; ============================================================================
+; Here is longest_match(), the function that the rest of this was built up
+; from, the hottest hot spot in the program and therefore the most heavily
+; optimized. It has two different versions, one for '020 and higher CPUs, and
+; one for 68000/68010. It can test at runtime which version to use if you
+; create a test function in match_init for your platform. Currently such a
+; test is implemented for the Amiga. It can also be assembled to use '000 or
+; '020 code only.
+
+Cur_Match equr d0 ; unsigned int, kept valid as long
+Best_Len equr d1 ; unsigned int, kept valid as long
+Scan_Start equr d3 ; pair of bytes
+Scan_End equr d4 ; pair of bytes
+Limit equr d5 ; unsigned int
+Chain_Length equr d6 ; unsigned int
+Scan_Test equr d7 ; counter, pair of bytes sometimes
+Scan equr a0 ; pointer to unsigned char
+Match equr a1 ; pointer to unsigned char
+Prev_Address equr a2 ; pointer to unsigned short
+Scan_Ini equr a3 ; pointer to unsigned char
+Match_Ini equr a5 ; pointer to unsigned char
+; Note: "pair of bytes" means the two low order bytes of the register in
+; 68020 code, but means the lowest and third lowest bytes on the 68000.
+ IFD AMIGA
+SAVEREGS reg d3-d7/a2/a3/a5 ; don't protect d0/d1/a0/a1
+ ELSE ; !AMIGA
+SAVEREGS reg d1/d3-d7/a0-a3/a5 ; protect all except d0 return val
+ ENDC ; ?AMIGA
+; d2, a4, a6 not used... on Amiga, a4 is used by small-data memory model
+
+
+longest_match:
+ movem.l SAVEREGS,-(sp)
+
+; setup steps common to byte and word versions:
+ IFD INT16
+ and.l #$0000FFFF,Cur_Match ; upper half must be zero!
+; we use an and.l down here for the sake of ATSIGN/REGARGS.
+ moveq #0,Limit ; so adding to Scan_Ini works
+ ENDC
+ move.w max_chain_len,Chain_Length
+ move.w prev_length,Best_Len
+ MOVINT _strstart,Limit
+ BASEPTR _prev,Prev_Address
+ BASEPTR _window,Match_Ini
+ move.l Match_Ini,Scan_Ini
+ addq #MIN_MATCH,Match_Ini ; optimizes inner loop
+ add.l Limit,Scan_Ini
+ sub.w #MAX_DIST,Limit
+ bhi.s limit_ok
+ moveq #0,Limit
+limit_ok:
+ cmp.w good_match,Best_Len
+ blo.s length_ok
+ lsr.w #2,Chain_Length
+length_ok:
+ subq.w #1,Chain_Length
+
+ IFD CPUTEST
+ tst.w is020 ; can we use '020 stuff today?
+ bne WORD_match
+ ENDC
+
+ IFND CPU020
+
+; for 68000 or 68010, use byte operations:
+ moveq #0,Scan_Start ; clear 2nd & 4th bytes, use 1st & 3rd
+ moveq #0,Scan_End ; likewise
+ moveq #0,Scan_Test ; likewise
+ move.b (Scan_Ini),Scan_Start
+ swap Scan_Start ; swap is faster than 8 bit shift
+ move.b 1(Scan_Ini),Scan_Start
+ move.b -1(Scan_Ini,Best_Len.w),Scan_End
+ swap Scan_End
+ move.b 0(Scan_Ini,Best_Len.w),Scan_End
+ bra.s bdo_scan
+
+blong_loop:
+ move.b -1(Scan_Ini,Best_Len.w),Scan_End
+ swap Scan_End
+ move.b 0(Scan_Ini,Best_Len.w),Scan_End
+
+bshort_loop:
+ add.w Cur_Match,Cur_Match ; assert value before doubling < 32K
+ IFNE 32768-WSIZE
+ and.w #(WMASK*2),Cur_Match
+ ENDC
+ move.w (Prev_Address,Cur_Match.l),Cur_Match
+ cmp.w Limit,Cur_Match
+ dbls Chain_Length,bdo_scan
+ bra return
+
+bdo_scan:
+ move.l Match_Ini,Match
+ add.l Cur_Match,Match
+ move.b -MIN_MATCH-1(Match,Best_Len.w),Scan_Test
+ swap Scan_Test
+ move.b -MIN_MATCH(Match,Best_Len.w),Scan_Test
+ cmp.l Scan_Test,Scan_End
+ bne.s bshort_loop
+ move.b -MIN_MATCH(Match),Scan_Test
+ swap Scan_Test
+ move.b -MIN_MATCH+1(Match),Scan_Test
+ cmp.l Scan_Test,Scan_Start
+ bne.s bshort_loop
+ move.w #(MAX_MATCH-3),Scan_Test
+ lea MIN_MATCH(Scan_Ini),Scan ; offset optimizes inner loop
+
+bscan_loop:
+ cmp.b (Match)+,(Scan)+
+ dbne Scan_Test,bscan_loop
+ subq #1,Scan
+
+ sub.l Scan_Ini,Scan ; assert difference is 16 bits
+ cmp.w Best_Len,Scan
+ bls.s bshort_loop
+ MOVINT Scan,Best_Len
+ move.w Cur_Match,match_start
+ cmp.w nice_match,Best_Len
+ blo.s blong_loop
+ IFD CPUTEST
+ bra return
+ ENDC
+
+ ENDC ; !CPU020
+
+ IFND CPU000
+ MACHINE MC68020
+
+; for 68020 or higher, use word operations even on odd addresses:
+WORD_match:
+ move.w (Scan_Ini),Scan_Start
+ move.w -1(Scan_Ini,Best_Len.w),Scan_End
+ bra.s wdo_scan
+
+wlong_loop:
+ move.w -1(Scan_Ini,Best_Len.w),Scan_End
+
+wshort_loop:
+ and.w #WMASK,Cur_Match
+ move.w (Prev_Address,Cur_Match.w*2),Cur_Match ; '020 addressing mode
+ cmp.w Limit,Cur_Match
+ dbls Chain_Length,wdo_scan
+ bra.s return
+
+wdo_scan:
+ move.l Match_Ini,Match
+ add.l Cur_Match,Match
+ cmp.w -MIN_MATCH-1(Match,Best_Len.w),Scan_End
+ bne.s wshort_loop
+ cmp.w -MIN_MATCH(Match),Scan_Start
+ bne.s wshort_loop
+ IFD QUADLONG
+; By some measurements, this version of the code is a little tiny bit faster.
+; But on some files it's slower. It probably pays off only when there are
+; long match strings, and costs in the most common case of three-byte matches.
+ moveq #((MAX_MATCH-MIN_MATCH)/16),Scan_Test ; value = 15
+ lea MIN_MATCH(Scan_Ini),Scan ; offset optimizes inner loop
+
+wscan_loop:
+ cmp.l (Match)+,(Scan)+ ; test four bytes at a time
+ bne.s odd
+ cmp.l (Match)+,(Scan)+
+ bne.s odd
+ cmp.l (Match)+,(Scan)+
+ bne.s odd
+ cmp.l (Match)+,(Scan)+
+ dbne Scan_Test,wscan_loop ; '020 can cache a bigger loop
+odd:
+ subq #4,Scan
+ subq #4,Match
+ cmp.b (Match)+,(Scan)+ ; find good bytes in bad longword
+ bne.s even
+ cmp.b (Match)+,(Scan)+
+ bne.s even
+ cmp.b (Match)+,(Scan)+
+ beq.s steven
+even: subq #1,Scan
+ ELSE ; !QUADLONG
+ moveq #((MAX_MATCH-MIN_MATCH)/2),Scan_Test ; value = 127
+ lea MIN_MATCH(Scan_Ini),Scan ; offset optimizes inner loop
+
+wscan_loop:
+ cmp.w (Match)+,(Scan)+
+ dbne Scan_Test,wscan_loop
+ subq #2,Scan
+ move.b -2(Match),Scan_Test
+ cmp.b (Scan),Scan_Test
+ bne.s steven
+ addq #1,Scan
+ ENDC ; ?QUADLONG
+steven:
+ sub.l Scan_Ini,Scan ; assert: difference is 16 bits
+ cmp.w Best_Len,Scan
+ bls.s wshort_loop
+ MOVINT Scan,Best_Len
+ move.w Cur_Match,match_start
+ cmp.w nice_match,Best_Len
+ blo.s wlong_loop
+
+ MACHINE MC68000
+ ENDC ; !CPU000
+
+return:
+ MOVINT Best_Len,d0 ; return value (upper half should be clear)
+ movem.l (sp)+,SAVEREGS
+ rts
+
+
+; =============================================================================
+; This is the deflate() function itself, our main entry point. It calls
+; longest_match, above, and some outside functions. It is a hot spot, but not
+; as hot as longest_match. It uses no special '020 code.
+
+; ================== Several macros used in deflate() and later functions:
+
+; Arg 1 is D-reg that new ins_h value is to be left in,
+; arg 2 is the byte value to be hashed into it, which must not be the same reg
+UP_HASH MACRO
+ move.w ins_h,\1
+ asl.w #H_SHIFT,\1
+ eor.b \2,\1
+ and.w #HASH_MASK,\1 ; ((ins_h << H_SHIFT) ^ c) & HASH_MASK
+ move.w \1,ins_h ; ins_h = that
+ ENDM
+
+; Arg 1 is scratch A, arg 2 is scratch D
+IN_STR MACRO
+ move.l Strst,\2
+ addq.w #MIN_MATCH-1,\2
+ move.b (Window,\2.l),\2 ; window[strstart + MIN_MATCH - 1]
+ UP_HASH Head,\2
+ add.l Head,Head ; assert upper word is zero before add
+ BASEPTR _head,\1
+ add.l Head,\1
+ move.w (\1),Head ; hash_head = head[ins_h]
+ move.w Strst,(\1) ; head[ins_h] = strstart
+ move.l Strst,\2
+ IFNE WSIZE-32768
+ and.w #WMASK,\2
+ ENDC
+ add.w \2,\2 ; masks implicitly when WSIZE == 32768
+ move.w Head,(Prev,\2.l) ; prev[str_start & WMASK] = hash_head
+ ENDM
+
+; Arg 1 is bool (int) EOF flag, flush_block result is in d0, trashes d1/a0/a1
+FLUSH_B MACRO
+ IFC '\1','#0'
+ CLRINT -(sp)
+ ELSE
+ MOVINT \1,-(sp)
+ ENDC
+ move.l _block_start,d0
+ blt.s nenu\@
+ move.l Window,a0
+ add.l d0,a0
+ bra.s nun\@
+nenu\@: sub.l a0,a0 ; if block_start < 0, push NULL
+nun\@: sub.l Strst,d0
+ neg.l d0
+ move.l d0,-(sp)
+ move.l a0,-(sp)
+ jsr _flush_block
+ lea 8+INTSIZE(sp),sp
+ ENDM
+
+; This expands to nothing unless DEBUG is defined.
+; Arg 1 is a byte to be trace-outputted -- if it is d0 it must be a valid int
+TRACE_C MACRO
+ IFD DEBUG
+ cmp.w #1,_verbose+INTSIZE-2 ; test lower word only
+ ble.s qui\@
+ IFNC '\1','d0'
+ moveq #0,d0
+ move.b \1,d0
+ ENDC
+ move.l _stderr,-(sp)
+ MOVINT d0,-(sp)
+ jsr _fputc
+ addq #4+INTSIZE,sp
+qui\@:
+ ENDC ; DEBUG
+ ENDM
+
+; ================== Here are the register vars we use, and deflate() itself:
+
+Window equr a2 ; cached address of window[]
+Prev equr a3 ; cached address of prev[]
+Strst equr d7 ; strstart cached as a longword
+Look equr d6 ; lookahead cached as short
+Head equr d5 ; local variable hash_head, short
+PrevL equr d4 ; prev_length cached as short
+MatchL equr d3 ; local variable match_length, unsigned short
+Avail equr d2 ; local variable available_match, bool
+PrevM equr a5 ; local variable prev_match, int in an A-reg
+
+ IFD AMIGA
+DEFREGS reg d2-d7/a2/a3/a5
+ ELSE
+DEFREGS reg d0-d7/a0/a2/a3/a5 ; play it safe, preserve all regs
+ ENDC
+
+
+_deflate: ; first, setup steps common to deflate and deflate_fast:
+ movem.l DEFREGS,-(sp)
+ IFD INT16
+ moveq #0,Strst ; make sure strstart is valid as a long
+ ENDC
+ moveq #0,Head ; ditto for hash_head
+ MOVINT _strstart,Strst
+ move.w lookahead,Look
+ move.w prev_length,PrevL
+ BASEPTR _window,Window
+ BASEPTR _prev,Prev
+ MOVINT _level,d0
+ cmp.w #3,d0
+ ble deflate_fast
+ moveq #MIN_MATCH-1,MatchL
+ moveq #0,Avail
+
+look_loop:
+ tst.w Look
+ beq last_tally
+ IN_STR a0,d0
+ move.w MatchL,PrevL
+ move.w match_start,PrevM
+ move.w #MIN_MATCH-1,MatchL
+
+ tst.w Head
+ beq.s no_new_match
+ cmp.w max_lazy_match,PrevL
+ bhs.s no_new_match
+ move.w Strst,d0
+ sub.w Head,d0
+ cmp.w #MAX_DIST,d0
+ bhi.s no_new_match
+ move.w PrevL,prev_length ; longest_match reads these variables
+ MOVINT Strst,_strstart
+ MOVINT Head,d0 ; parm for longest_match
+ bsr longest_match ; sets match_start
+ cmp.w Look,d0 ; does length exceed valid data?
+ bls.s stml
+ move.w Look,d0
+stml: move.w d0,MatchL ; valid length of match
+ cmp.w #MIN_MATCH,MatchL ; is the match only three bytes?
+ bne.s no_new_match
+ move.w match_start,d0
+ sub.w Strst,d0
+ cmp.w #-TOO_FAR,d0
+ bge.s no_new_match
+ moveq #MIN_MATCH-1,MatchL ; mark the current match as no good
+
+no_new_match:
+ cmp.w #MIN_MATCH,PrevL
+ blo literal
+ cmp.w MatchL,PrevL
+ blo literal
+ ; CHECK_MATCH Strst-1,PrevM,PrevL
+ MOVINT Strst,_strstart ; ct_tally reads this variable
+ move.l PrevL,d0
+ subq.w #MIN_MATCH,d0
+ MOVINT d0,-(sp)
+ move.l Strst,d0
+ sub.w PrevM,d0
+ subq.w #1,d0
+ MOVINT d0,-(sp)
+ jsr _ct_tally ; sets d0 true if we have to flush
+ addq #2*INTSIZE,sp
+ subq.w #3,PrevL ; convert for dbra (prev_length - 2)
+ sub.w PrevL,Look
+ subq.w #2,Look
+insertmatch:
+ addq.w #1,Strst
+ IN_STR a0,d1 ; don't clobber d0
+ dbra PrevL,insertmatch
+ moveq #0,Avail
+ moveq #0,PrevL ; not needed?
+ moveq #MIN_MATCH-1,MatchL
+ addq.w #1,Strst
+ tst.w d0
+ beq refill
+ FLUSH_B #0
+ move.l Strst,_block_start
+ bra.s refill
+
+literal:
+ tst.w Avail
+ bne.s yeslit
+ moveq #1,Avail
+ bra.s skipliteral
+yeslit: TRACE_C <-1(Window,Strst.l)>
+ MOVINT Strst,_strstart ; ct_tally reads this variable
+ moveq #0,d0
+ move.b -1(Window,Strst.l),d0
+ MOVINT d0,-(sp)
+ CLRINT -(sp)
+ jsr _ct_tally
+ addq #2*INTSIZE,sp
+ tst.w d0
+ beq.s skipliteral
+ FLUSH_B #0
+ move.l Strst,_block_start
+skipliteral:
+ addq.w #1,Strst
+ subq.w #1,Look
+
+refill:
+ cmp.w #MIN_LOOKAHEAD,Look
+ bhs look_loop
+ bsr fill_window
+ bra look_loop
+
+last_tally:
+ tst.w Avail
+ beq last_flush
+ MOVINT Strst,_strstart ; ct_tally reads this variable
+ moveq #0,d0
+ move.b -1(Window,Strst.l),d0
+ MOVINT d0,-(sp)
+ CLRINT -(sp)
+ jsr _ct_tally
+ addq #2*INTSIZE,sp
+last_flush:
+ FLUSH_B #1
+ bra deflate_exit
+
+; ================== This is another version used for low compression levels:
+
+deflate_fast:
+ moveq #0,MatchL
+ moveq #MIN_MATCH-1,PrevL
+flook_loop:
+ tst.w Look
+ beq flast_flush
+
+ IN_STR a0,d0
+ tst.w Head
+ beq.s fno_new_match
+ move.w Strst,d0
+ sub.w Head,d0
+ cmp.w #MAX_DIST,d0
+ bhi.s fno_new_match
+ move.w PrevL,prev_length ; longest_match reads these variables
+ MOVINT Strst,_strstart
+ MOVINT Head,d0 ; parm for longest_match
+ bsr longest_match ; sets match_start
+ cmp.w Look,d0 ; does length exceed valid data?
+ bls.s fstml
+ move.w Look,d0
+fstml: move.w d0,MatchL ; valid length of match
+
+fno_new_match:
+ cmp.w #MIN_MATCH,MatchL
+ blo fliteral
+ ; CHECK_MATCH Strst,match_start,MatchL
+ MOVINT Strst,_strstart ; ct_tally reads this variable
+ move.l MatchL,d0
+ subq.w #MIN_MATCH,d0
+ MOVINT d0,-(sp)
+ move.l Strst,d0
+ sub.w match_start,d0
+ MOVINT d0,-(sp)
+ jsr _ct_tally ; sets d0 true if we have to flush
+ addq #2*INTSIZE,sp
+ sub.w MatchL,Look
+ cmp.w max_lazy_match,MatchL
+ bhi ftoolong
+ subq.w #2,MatchL
+finsertmatch:
+ addq.w #1,Strst
+ IN_STR a0,d1 ; preserve d0
+ dbra MatchL,finsertmatch
+ moveq #0,MatchL ; not needed?
+ addq.w #1,Strst
+ bra.s flushfill
+
+ftoolong:
+ add.w MatchL,Strst
+ moveq #0,MatchL
+ moveq #0,d1 ; preserve d0
+ move.b (Window,Strst.l),d1
+ move.w d1,ins_h
+; My assembler objects to passing <1(Window,Strst.l)> directly to UP_HASH...
+ move.b 1(Window,Strst.l),Avail ; Avail is not used in deflate_fast
+ UP_HASH d1,Avail ; preserve d0
+ IFNE MIN_MATCH-3
+ FAIL needs to UP_HASH another MIN_MATCH-3 times, but with what arg?
+ ENDC
+ bra.s flushfill
+
+fliteral:
+ TRACE_C <(Window,Strst.l)>
+ MOVINT Strst,_strstart ; ct_tally reads this variable
+ moveq #0,d0
+ move.b (Window,Strst.l),d0
+ MOVINT d0,-(sp)
+ CLRINT -(sp)
+ jsr _ct_tally ; d0 set if we need to flush
+ addq #2*INTSIZE,sp
+ addq.w #1,Strst
+ subq.w #1,Look
+
+flushfill:
+ tst.w d0
+ beq.s frefill
+ FLUSH_B #0
+ move.l Strst,_block_start
+frefill:
+ cmp.w #MIN_LOOKAHEAD,Look
+ bhs flook_loop
+ bsr fill_window
+ bra flook_loop
+
+flast_flush:
+ FLUSH_B #1 ; sets our return value
+
+deflate_exit:
+ MOVINT Strst,_strstart ; save back cached values
+ move.w PrevL,prev_length
+ move.w Look,lookahead
+ movem.l (sp)+,DEFREGS
+ rts
+
+
+; =========================================================================
+; void fill_window(void) calls the input function to refill the sliding
+; window that we use to find substring matches in.
+
+More equr Head ; local variable in fill_window
+WindTop equr Prev ; local variable used for sliding
+SlidIx equr PrevL ; local variable used for sliding
+
+ IFD AMIGA
+FWREGS reg d2-d5/a2-a6 ; does NOT include Look and Strst
+ ELSE
+FWREGS reg d1-d5/a0-a6 ; likewise
+ ENDC
+; all registers available to be clobbered by the sliding operation:
+; we exclude More, WindTop, SlidIx, Look, Strst, Window, a4 and a7.
+SPAREGS reg d0-d3/a0-a1/a5-a6
+SPCOUNT equ 8 ; number of registers in SPAREGS
+
+
+_fill_window: ; C-callable entry point
+ movem.l Strst/Look,-(sp)
+ IFD INT16
+ moveq #0,Strst ; Strst must be valid as a long
+ ENDC
+ MOVINT _strstart,Strst
+ move.w lookahead,Look
+ BASEPTR _window,Window
+ bsr.s fill_window
+ MOVINT Strst,_strstart
+ move.w Look,lookahead
+ movem.l (sp)+,Strst/Look
+ rts
+
+; strstart, lookahead, and window must be cached in Strst, Look, and Window:
+fill_window: ; asm-callable entry point
+ movem.l FWREGS,-(sp)
+ tst.w eofile ; we put this up here for speed
+ bne fwdone
+ and.l #$FFFF,Look ; make sure Look is valid as long
+fw_refill:
+ move.l _window_size,More ; <= 64K
+ sub.l Look,More
+ sub.l Strst,More ; Strst is already valid as long
+ cmp.w #EOF,More
+ bne.s notboundary
+ subq.w #1,More
+ bra checkend
+
+notboundary:
+ tst.w sliding
+ beq checkend
+ cmp.w #WSIZE+MAX_DIST,Strst
+ blo checkend
+ IFGT 32768-WSIZE
+ lea WSIZE(Window),WindTop ; WindTop is aligned when Window is
+ ELSE
+ move.l Window,WindTop
+ add.l #WSIZE,WindTop
+ ENDC
+ move.l Window,d0
+ and.w #3,d0
+ beq.s isaligned
+ subq.w #1,d0
+align: move.b (WindTop)+,(Window)+ ; copy up to a longword boundary
+ dbra d0,align
+isaligned:
+; This is faster than a simple move.l (WindTop)+,(Window)+ / dbra loop:
+ move.w #(WSIZE-1)/(4*SPCOUNT),SlidIx
+slide: movem.l (WindTop)+,SPAREGS ; copy, 32 bytes at a time!
+ movem.l SPAREGS,(Window) ; a slight overshoot doesn't matter.
+ lea 4*SPCOUNT(Window),Window ; can't use (aN)+ as movem.l dest
+ dbra SlidIx,slide
+ BASEPTR _window,Window ; restore cached value
+ sub.w #WSIZE,match_start
+ sub.w #WSIZE,Strst
+ sub.l #WSIZE,_block_start
+ add.w #WSIZE,More
+ BASEPTR _head,a0
+ move.w #HASH_SIZE-1,d0
+fixhead:
+ move.w (a0),d1
+ sub.w #WSIZE,d1
+ bpl.s headok
+ moveq #0,d1
+headok: move.w d1,(a0)+
+ dbra d0,fixhead
+ BASEPTR _prev,a0
+ move.w #WSIZE-1,d0
+fixprev:
+ move.w (a0),d1
+ sub.w #WSIZE,d1
+ bpl.s prevok
+ moveq #0,d1
+prevok: move.w d1,(a0)+
+ dbra d0,fixprev
+ TRACE_C #'.'
+
+checkend: ; assert eofile is false
+ MOVINT More,-(sp) ; assert More's upper word is zero
+ move.l Strst,d0
+ add.w Look,d0
+ add.l Window,d0
+ move.l d0,-(sp)
+ move.l _read_buf,a0
+ jsr (a0) ; refill the upper part of the window
+ addq #4+INTSIZE,sp
+ tst.w d0
+ beq.s iseof
+ cmp.w #EOF,d0
+ beq.s iseof
+ add.w d0,Look
+ cmp.w #MIN_LOOKAHEAD,Look
+ blo fw_refill ; eofile is still false
+
+ bra.s fwdone
+iseof: move.w #1,eofile
+fwdone: movem.l (sp)+,FWREGS
+ rts
+
+
+; =========================================================================
+; void lm_free(void) frees dynamic arrays in the DYN_ALLOC version.
+
+ xdef _lm_free ; the entry point
+
+_lm_free:
+ IFD DYN_ALLOC
+ move.l _window,d0
+ beq.s lf_no_window
+ move.l d0,-(sp)
+ jsr _free
+ addq #4,sp
+ clr.l _window
+lf_no_window:
+ move.l _prev,d0
+ beq.s lf_no_prev
+ move.l d0,-(sp)
+ jsr _free
+ move.l _head,(sp) ; reuse the same stack arg slot
+ jsr _free
+ addq #4,sp
+ clr.l _prev
+ clr.l _head
+lf_no_prev:
+ ENDC
+ rts
+
+; ============================================================================
+; void lm_init(int pack_level, unsigned short *flags) allocates dynamic arrays
+; if any, and initializes all variables so that deflate() is ready to go.
+
+ xdef _lm_init ; the entry point
+
+Level equr d2
+;Window equr a2 ; as in deflate()
+ IFD AMIGA
+INIREGS reg d2/a2
+ ELSE
+INIREGS reg d0-d2/a0-a1
+ ENDC
+
+_lm_init:
+ MOVINT 4(sp),d0
+ move.l 4+INTSIZE(sp),a0
+ movem.l INIREGS,-(sp)
+ move.w d0,Level
+ cmp.w #1,Level
+ blt.s levelerr
+ bgt.s try9
+ bset.b #B_FAST,1(a0)
+try9: cmp.w #9,Level
+ bgt.s levelerr
+ blt.s levelok
+ bset.b #B_SLOW,1(a0)
+ bra.s levelok
+levelerr:
+ pea level_message
+ jsr _error ; never returns
+levelok:
+ clr.w sliding
+ tst.l _window_size
+ bne.s gotawindowsize
+ move.w #1,sliding
+ move.l #2*WSIZE,_window_size
+gotawindowsize:
+
+ BASEPTR _window,Window
+ IFD DYN_ALLOC
+ move.l Window,d0 ; fake tst.l
+ bne.s gotsomewind
+ CAL_SH WSIZE
+ move.l d0,Window
+ move.l d0,_window
+ bne.s gotsomewind
+ pea window_message
+ MOVINT #ZE_MEM,-(sp)
+ jsr _ziperr ; never returns
+gotsomewind:
+ tst.l _prev
+ bne.s gotsomehead
+ CAL_SH WSIZE
+ move.l d0,_prev
+ beq.s nohead
+ CAL_SH HASH_SIZE
+ move.l d0,_head
+ bne.s gotfreshhead ; newly calloc'd memory is zeroed
+nohead: pea hash_message
+ MOVINT #ZE_MEM,-(sp)
+ jsr _ziperr ; never returns
+gotsomehead:
+ ENDC ; DYN_ALLOC
+
+ move.w #(HASH_SIZE/2)-1,d0 ; two shortwords per loop
+ BASEPTR _head,a0
+wipeh: clr.l (a0)+
+ dbra d0,wipeh
+gotfreshhead:
+ move.l Level,d0
+ IFEQ Sizeof_config-8
+ asl.l #3,d0
+ ELSE
+ mulu #Sizeof_config,d0
+ ENDC
+ lea config_table,a0
+ add.l d0,a0
+ move.w Max_lazy(a0),max_lazy_match
+ move.w Good_length(a0),good_match
+ move.w Nice_length(a0),nice_match
+ move.w Max_chain(a0),max_chain_len
+ CLRINT _strstart
+ clr.l _block_start
+ bsr match_init
+
+ clr.w eofile
+ MOVINT #WSIZE,-(sp) ; We read only 32K because lookahead is short
+ move.l Window,-(sp) ; even when int size is long, as if deflate.c
+ move.l _read_buf,a0 ; were compiled with MAXSEG_64K defined.
+ jsr (a0)
+ addq #4+INTSIZE,sp
+ move.w d0,lookahead
+ beq.s noread
+ cmp.w #EOF,d0
+ bne.s irefill
+noread: move.w #1,eofile
+ clr.w lookahead
+ bra.s init_done
+
+irefill:
+ move.w lookahead,d0
+ cmp.w #MIN_LOOKAHEAD,d0
+ bhs.s hashify
+ bsr _fill_window ; use the C-callable version
+hashify:
+ clr.w ins_h
+ moveq #MIN_MATCH-2,d0
+hash1: move.b (Window)+,d1
+ UP_HASH Level,d1
+ dbra d0,hash1
+
+init_done:
+ movem.l (sp)+,INIREGS
+ rts
+
+; strings for error messages:
+hash_message dc.b 'hash table allocation',0
+window_message dc.b 'window allocation',0
+level_message dc.b 'bad pack level',0
+
+ end
diff --git a/amiga/filedate.c b/amiga/filedate.c
new file mode 100644
index 0000000..84c7bed
--- /dev/null
+++ b/amiga/filedate.c
@@ -0,0 +1,636 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* Low-level Amiga routines shared between Zip and UnZip.
+ *
+ * Contains: FileDate()
+ * locale_TZ()
+ * getenv() [Aztec C only; replaces bad C library versions]
+ * setenv() [ditto]
+ * tzset() [ditto]
+ * gmtime() [ditto]
+ * localtime() [ditto]
+ * time() [ditto]
+ * sendpkt()
+ * Agetch()
+ *
+ * The first nine are used by all Info-ZIP programs except fUnZip.
+ * The last two are used by all except the non-CRYPT version of fUnZip.
+ * Probably some of the stuff in here is unused by ZipNote and ZipSplit too...
+ * sendpkt() is used by Agetch() and FileDate(), and by windowheight() in
+ * amiga/amiga.c (UnZip). time() is used only by Zip.
+ */
+
+
+/* HISTORY/CHANGES
+ * 2 Sep 92, Greg Roelofs, Original coding.
+ * 6 Sep 92, John Bush, Incorporated into UnZip 5.1
+ * 6 Sep 92, John Bush, Interlude "FileDate()" defined, which calls or
+ * redefines SetFileDate() depending upon AMIGADOS2 definition.
+ * 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining
+ * revision via OpenLibrary() call. Now only one version of
+ * the program runs on both platforms (1.3.x vs. 2.x)
+ * 11 Oct 92, John Bush, Merged with Zip version and changed arg passing
+ * to take time_t input instead of struct DateStamp.
+ * Arg passing made to conform with utime().
+ * 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some
+ * lint-ish errors; simplified test for AmigaDOS version.
+ * 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and
+ * UnZip's "More" prompt -- simplifies crypt.h and avoids
+ * use of library code redundant with sendpkt(). Made it
+ * available to fUnZip, which does not use FileDate().
+ * 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current
+ * timezone from the Locale preferences. These exist only under
+ * AmigaDOS 2.1 and up, but it is probably correctly set on more
+ * Amigas than the TZ environment variable is. We check that
+ * only if TZ is not validly set. We do not parse daylight
+ * savings syntax except to check for presence vs. absence of a
+ * DST part; United States rules are assumed. This is better
+ * than the tzset()s in the Amiga compilers' libraries do.
+ * 15 Jan 96, Chr. Spieler, corrected the logic when to select low level
+ * sendpkt() (when FileDate(), Agetch() or windowheight() is used),
+ * and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()).
+ * 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved
+ * stuff around for clarity.
+ * 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the
+ * new tzset(), because Aztec's is hopelessly broken. Also
+ * gmtime(), which localtime() calls.
+ * 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly.
+ * 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns
+ * local time instead of GMT. That's why their localtime() was bad,
+ * because it assumed time_t was already local, and gmtime() was
+ * the one that checked TZ.
+ * 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff.
+ * Currently, the UnZip sources do not make use of time() (and do
+ * not supply the working mktime() replacement, either!).
+ * 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that
+ * was previously embedded in tzset(), for reliable global test
+ * of whether TZ is set or not.
+ * 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler.
+ * 7 Jul 96, Paul Kienitz, smoothed together compiler-related changes.
+ * 4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C.
+ * 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding
+ * mkgmtime() so localtime() could be used.
+ * 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP;
+ * the Zip sources supply this function as part of util.c.
+ * 24 May 97, Haidinger Walter, added time_lib support for SAS/C and moved
+ * set_TZ() to time_lib.c.
+ * 12 Jul 97, Paul Kienitz, adapted time_lib stuff for Aztec.
+ * 26 Jul 97, Chr. Spieler, old mkgmtime() fixed (ydays[] def, sign vs unsign).
+ * 30 Dec 97, Haidinger Walter, adaptation for SAS/C using z-stat.h functions.
+ * 19 Feb 98, Haidinger Walter, removed alloc_remember, more SAS.C fixes.
+ * 23 Apr 98, Chr. Spieler, removed mkgmtime(), changed FileDate to convert to
+ * Amiga file-time directly.
+ * 24 Apr 98, Paul Kienitz, clip Unix dates earlier than 1978 in FileDate().
+ * 02 Sep 98, Paul Kienitz, C. Spieler, always include zip.h to get a defined
+ * header inclusion sequence that resolves all header dependencies.
+ */
+
+#ifndef __amiga_filedate_c
+#define __amiga_filedate_c
+
+
+#include "zip.h"
+#include <ctype.h>
+#include <errno.h>
+
+#include <exec/types.h>
+#include <exec/execbase.h>
+#include <exec/memory.h>
+
+#ifdef AZTEC_C
+# include <libraries/dos.h>
+# include <libraries/dosextens.h>
+# include <clib/exec_protos.h>
+# include <clib/dos_protos.h>
+# include <clib/locale_protos.h>
+# include <pragmas/exec_lib.h>
+# include <pragmas/dos_lib.h>
+# include <pragmas/locale_lib.h>
+# define ESRCH ENOENT
+# define EOSERR EIO
+#endif
+
+#ifdef __SASC
+# include <stdlib.h>
+# if (defined(_M68020) && (!defined(__USE_SYSBASE)))
+ /* on 68020 or higher processors it is faster */
+# define __USE_SYSBASE /* to use the pragma libcall instead of syscall */
+# endif /* to access functions of the exec.library */
+# include <proto/exec.h> /* see SAS/C manual:part 2,chapter 2,pages 6-7 */
+# include <proto/dos.h>
+# include <proto/locale.h>
+# ifdef DEBUG
+# include <sprof.h>
+# endif
+# ifdef MWDEBUG
+# include <stdio.h> /* include both before memwatch.h again just */
+# include <stdlib.h> /* to be safe */
+# include "memwatch.h"
+# endif /* MWDEBUG */
+#endif /* __SASC */
+
+#include "crypt.h" /* just so we can tell if CRYPT is supported */
+
+
+
+#ifndef FUNZIP
+
+#ifndef SUCCESS
+# define SUCCESS (-1L)
+# define FAILURE 0L
+#endif
+
+#define ReqVers 36L /* required library version for SetFileDate() */
+#define ENVSIZE 100 /* max space allowed for an environment var */
+
+extern struct ExecBase *SysBase;
+
+#ifndef USE_TIME_LIB
+#ifdef AZTEC_C /* should be pretty safe for reentrancy */
+ long timezone = 0; /* already declared SAS/C external */
+ int daylight = 0; /* likewise */
+#endif
+int real_timezone_is_set = FALSE; /* set by tzset() */
+#endif /* !USE_TIME_LIB */
+
+/* prototypes */
+char *getenv(const char *var);
+#ifdef __SASC
+int setenv(const char *var, const char *value, int overwrite);
+/* !!!! We have really got to find a way to operate without this. */
+#endif
+
+LONG FileDate (char *filename, time_t u[]);
+LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+int Agetch(void);
+
+/* prototypes for time replacement functions */
+#ifndef USE_TIME_LIB
+ void tzset(void);
+ int locale_TZ(void);
+ struct tm *gmtime(const time_t *when);
+ struct tm *localtime(const time_t *when);
+# ifdef __SASC
+ extern void set_TZ(long time_zone, int day_light); /* in time_lib.c */
+# endif
+# ifdef ZIP
+ time_t time(time_t *tp);
+# endif
+#endif /* !USE_TIME_LIB */
+
+/* =============================================================== */
+
+/***********************/
+/* Function filedate() */
+/***********************/
+
+/* FileDate() (originally utime.c), by Paul Wells. Modified by John Bush
+ * and others (see also sendpkt() comments, below); NewtWare SetFileDate()
+ * clone cheaply ripped off from utime().
+ */
+
+/* DESCRIPTION
+ * This routine chooses between 2 methods to set the file date on AMIGA.
+ * Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36
+ * and higher). Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate()
+ * must be accomplished by constructing a message packet and sending it
+ * to the file system handler of the file to be stamped.
+ *
+ * The system's ROM version is extracted from the external system Library
+ * base.
+ *
+ * NOTE: although argument passing conforms with utime(), note the
+ * following differences:
+ * - Return value is boolean success/failure.
+ * - If a structure or array is passed, only the first value
+ * is used, which *may* correspond to date accessed and not
+ * date modified.
+ */
+
+/* Nonzero if `y' is a leap year, else zero. */
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+
+/* Number of leap years from 1970 to `y' (not including `y' itself). */
+#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
+
+/* Accumulated number of days from 01-Jan up to start of current month. */
+#ifdef ZIP
+static const unsigned short ydays[] =
+{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+#else
+extern const unsigned short ydays[]; /* in unzip's fileio.c */
+#endif
+
+LONG FileDate(filename, u)
+ char *filename;
+ time_t u[];
+{
+ LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate);
+ LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+ struct MsgPort *taskport;
+ BPTR dirlock, lock;
+ struct FileInfoBlock *fib;
+ LONG pktargs[4];
+ UBYTE *ptr;
+ long ret;
+
+ struct DateStamp pDate;
+ struct tm *ltm;
+ int years;
+
+ /* tzset(); */
+ /* Amiga file date is based on 01-Jan-1978 00:00:00 (local time):
+ * 8 years and 2 leapdays difference from Unix time.
+ */
+ ltm = localtime(&u[0]);
+ years = ltm->tm_year + 1900;
+ if (years < 1978)
+ pDate.ds_Days = pDate.ds_Minute = pDate.ds_Tick = 0;
+ else {
+ pDate.ds_Days = (years - 1978) * 365L + (nleap(years) - 2) +
+ ((ltm->tm_mon > 1 && leap(years)) ? 1 : 0) +
+ ydays[ltm->tm_mon] + (ltm->tm_mday - 1);
+ pDate.ds_Minute = ltm->tm_hour * 60 + ltm->tm_min;
+ pDate.ds_Tick = ltm->tm_sec * TICKS_PER_SECOND;
+ }
+
+ if (SysBase->LibNode.lib_Version >= ReqVers)
+ {
+ return (SetFileDate(filename,&pDate)); /* native routine at 2.0+ */
+ }
+ else /* !(SysBase->lib_Version >=ReqVers) */
+ {
+ if( !(taskport = (struct MsgPort *)DeviceProc(filename)) )
+ {
+ errno = ESRCH; /* no such process */
+ return FAILURE;
+ }
+
+ if( !(lock = Lock(filename,SHARED_LOCK)) )
+ {
+ errno = ENOENT; /* no such file */
+ return FAILURE;
+ }
+
+ if( !(fib = (struct FileInfoBlock *)AllocMem(
+ (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )
+ {
+ errno = ENOMEM; /* insufficient memory */
+ UnLock(lock);
+ return FAILURE;
+ }
+
+ if( Examine(lock,fib)==FAILURE )
+ {
+ errno = EOSERR; /* operating system error */
+ UnLock(lock);
+ FreeMem(fib,(long)sizeof(*fib));
+ return FAILURE;
+ }
+
+ dirlock = ParentDir(lock);
+ ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC);
+ strcpy((ptr+1),fib->fib_FileName);
+ *ptr = strlen(fib->fib_FileName);
+ FreeMem(fib,(long)sizeof(*fib));
+ UnLock(lock);
+
+ /* now fill in argument array */
+
+ pktargs[0] = 0;
+ pktargs[1] = (LONG)dirlock;
+ pktargs[2] = (LONG)&ptr[0] >> 2;
+ pktargs[3] = (LONG)&pDate;
+
+ errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L);
+
+ FreeMem(ptr,64L);
+ UnLock(dirlock);
+
+ return SUCCESS;
+ } /* ?(SysBase->lib_Version >= ReqVers) */
+} /* FileDate() */
+
+
+char *getenv(const char *var) /* not reentrant! */
+{
+ static char space[ENVSIZE];
+ struct Process *me = (void *) FindTask(NULL);
+ void *old_window = me->pr_WindowPtr;
+ char *ret = NULL;
+
+ me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */
+ if (SysBase->LibNode.lib_Version >= ReqVers) {
+ if (GetVar((char *) var, space, ENVSIZE - 1, /* GVF_GLOBAL_ONLY */ 0) > 0)
+ ret = space;
+ } else { /* early AmigaDOS, get env var the crude way */
+ BPTR hand, foot, spine;
+ int z = 0;
+ if (foot = Lock("ENV:", ACCESS_READ)) {
+ spine = CurrentDir(foot);
+ if (hand = Open((char *) var, MODE_OLDFILE)) {
+ z = Read(hand, space, ENVSIZE - 1);
+ Close(hand);
+ }
+ UnLock(CurrentDir(spine));
+ }
+ if (z > 0) {
+ space[z] = '\0';
+ ret = space;
+ }
+ }
+ me->pr_WindowPtr = old_window;
+ return ret;
+}
+
+#ifdef __SASC
+int setenv(const char *var, const char *value, int overwrite)
+{
+ struct Process *me = (void *) FindTask(NULL);
+ void *old_window = me->pr_WindowPtr;
+ int ret = -1;
+
+ me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */
+ if (SysBase->LibNode.lib_Version >= ReqVers)
+ ret = !SetVar((char *) var, (char *) value, -1, GVF_GLOBAL_ONLY | LV_VAR);
+ else {
+ BPTR hand, foot, spine;
+ long len = value ? strlen(value) : 0;
+ if (foot = Lock("ENV:", ACCESS_READ)) {
+ spine = CurrentDir(foot);
+ if (len) {
+ if (hand = Open((char *) var, MODE_NEWFILE)) {
+ ret = Write(hand, (char *) value, len + 1) >= len;
+ Close(hand);
+ }
+ } else
+ ret = DeleteFile((char *) var);
+ UnLock(CurrentDir(spine));
+ }
+ }
+ me->pr_WindowPtr = old_window;
+ return ret;
+}
+#endif /* __SASC */
+
+
+#ifndef USE_TIME_LIB
+
+/* set timezone and daylight to settings found in locale.library */
+int locale_TZ(void)
+{
+ struct Library *LocaleBase;
+ struct Locale *ll;
+ struct Process *me = (void *) FindTask(NULL);
+ void *old_window = me->pr_WindowPtr;
+ BPTR eh;
+ int z, valid = FALSE;
+
+ /* read timezone from locale.library if TZ envvar missing */
+ me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */
+ if (LocaleBase = OpenLibrary("locale.library", 0)) {
+ if (ll = OpenLocale(NULL)) {
+ z = ll->loc_GMTOffset;
+ if (z == -300) {
+ if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ))
+ UnLock(eh);
+ else
+ z = 300; /* bug: locale not initialized, default is bogus! */
+ } else
+ real_timezone_is_set = TRUE;
+ timezone = z * 60;
+ daylight = (z >= 4*60 && z <= 9*60); /* apply in the Americas */
+ valid = TRUE;
+ CloseLocale(ll);
+ }
+ CloseLibrary(LocaleBase);
+ }
+ me->pr_WindowPtr = old_window;
+ return valid;
+}
+
+void tzset(void)
+{
+ char *p,*TZstring;
+ int z,valid = FALSE;
+
+ if (real_timezone_is_set)
+ return;
+ timezone = 0; /* default is GMT0 which means no offsets */
+ daylight = 0; /* from local system time */
+ TZstring = getenv("TZ"); /* read TZ envvar */
+ if (TZstring && TZstring[0]) { /* TZ exists and has contents? */
+ z = 3600;
+ for (p = TZstring; *p && !isdigit(*p) && *p != '-'; p++) ;
+ if (*p == '-')
+ z = -3600, p++;
+ if (*p) {
+ timezone = 0;
+ do {
+ while (isdigit(*p))
+ timezone = timezone * 10 + z * (*p++ - '0'), valid = TRUE;
+ if (*p == ':') p++;
+ } while (isdigit(*p) && (z /= 60) > 0);
+ }
+ while (isspace(*p)) p++; /* probably not needed */
+ if (valid) {
+ real_timezone_is_set = TRUE;
+ daylight = !!*p; /* a DST name part exists */
+ }
+ }
+ if (!valid)
+ locale_TZ(); /* read locale.library */
+#ifdef __SASC
+ /* Some SAS/C library functions, e.g. stat(), call library */
+ /* __tzset() themselves. So envvar TZ *must* exist in order to */
+ /* to get the right offset from GMT. XXX WE SHOULD TRY HARD */
+ /* find and replace any remaining functions that need this! */
+ set_TZ(timezone, daylight);
+#endif /* __SASC */
+}
+
+
+struct tm *gmtime(const time_t *when)
+{
+ static struct tm tbuf; /* this function is intrinsically non-reentrant */
+ static short smods[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ long days = *when / 86400;
+ long secs = *when % 86400;
+ short yell, yday;
+
+ tbuf.tm_wday = (days + 4) % 7; /* 1/1/70 is a Thursday */
+ tbuf.tm_year = 70 + 4 * (days / 1461);
+ yday = days % 1461;
+ while (yday >= (yell = (tbuf.tm_year & 3 ? 365 : 366)))
+ yday -= yell, tbuf.tm_year++;
+ smods[1] = (tbuf.tm_year & 3 ? 28 : 29);
+ tbuf.tm_mon = 0;
+ tbuf.tm_yday = yday;
+ while (yday >= smods[tbuf.tm_mon])
+ yday -= smods[tbuf.tm_mon++];
+ tbuf.tm_mday = yday + 1;
+ tbuf.tm_isdst = 0;
+ tbuf.tm_sec = secs % 60;
+ tbuf.tm_min = (secs / 60) % 60;
+ tbuf.tm_hour = secs / 3600;
+#ifdef AZTEC_C
+ tbuf.tm_hsec = 0; /* this field exists for Aztec only */
+#endif
+ return &tbuf;
+}
+
+struct tm *localtime(const time_t *when)
+{
+ struct tm *t;
+ time_t localwhen;
+ int dst = FALSE, sundays, lastweekday;
+
+ tzset();
+ localwhen = *when - timezone;
+ t = gmtime(&localwhen);
+ /* So far we support daylight savings correction by the USA rule only: */
+ if (daylight && t->tm_mon >= 3 && t->tm_mon <= 9) {
+ if (t->tm_mon > 3 && t->tm_mon < 9) /* May Jun Jul Aug Sep: yes */
+ dst = TRUE;
+ else {
+ sundays = (t->tm_mday + 6 - t->tm_wday) / 7;
+ if (t->tm_wday == 0 && t->tm_hour < 2 && sundays)
+ sundays--; /* a Sunday does not count until 2:00am */
+ if (t->tm_mon == 3 && sundays > 0) /* first sunday in April */
+ dst = TRUE;
+ else if (t->tm_mon == 9) {
+ lastweekday = (t->tm_wday + 31 - t->tm_mday) % 7;
+ if (sundays < (37 - lastweekday) / 7)
+ dst = TRUE; /* last sunday in October */
+ }
+ }
+ if (dst) {
+ localwhen += 3600;
+ t = gmtime(&localwhen); /* crude but effective */
+ t->tm_isdst = 1;
+ }
+ }
+ return t;
+}
+
+
+# ifdef ZIP
+time_t time(time_t *tp)
+{
+ time_t t;
+ struct DateStamp ds;
+ DateStamp(&ds);
+ t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60
+ + (ds.ds_Days + 2922) * 86400;
+ t = mktime(gmtime(&t));
+ /* gmtime leaves ds in the local timezone, mktime converts it to GMT */
+ if (tp) *tp = t;
+ return t;
+}
+# endif /* ZIP */
+#endif /* !USE_TIME_LIB */
+
+#endif /* !FUNZIP */
+
+
+#if CRYPT || !defined(FUNZIP)
+
+/* sendpkt.c
+ * by A. Finkel, P. Lindsay, C. Sheppner
+ * returns Res1 of the reply packet
+ */
+/*
+#include <exec/types.h>
+#include <exec/memory.h>
+#include <libraries/dos.h>
+#include <libraries/dosextens.h>
+#include <proto/exec.h>
+#include <proto/dos.h>
+*/
+
+LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+
+LONG sendpkt(pid,action,args,nargs)
+struct MsgPort *pid; /* process identifier (handler message port) */
+LONG action, /* packet type (desired action) */
+ *args, /* a pointer to argument list */
+ nargs; /* number of arguments in list */
+{
+
+ struct MsgPort *replyport, *CreatePort(UBYTE *, long);
+ void DeletePort(struct MsgPort *);
+ struct StandardPacket *packet;
+ LONG count, *pargs, res1;
+
+ replyport = CreatePort(NULL,0L);
+ if( !replyport ) return(0);
+
+ packet = (struct StandardPacket *)AllocMem(
+ (long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
+ if( !packet )
+ {
+ DeletePort(replyport);
+ return(0);
+ }
+
+ packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
+ packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
+ packet->sp_Pkt.dp_Port = replyport;
+ packet->sp_Pkt.dp_Type = action;
+
+ /* copy the args into the packet */
+ pargs = &(packet->sp_Pkt.dp_Arg1); /* address of 1st argument */
+ for( count=0; count<nargs; count++ )
+ pargs[count] = args[count];
+
+ PutMsg(pid,(struct Message *)packet); /* send packet */
+
+ WaitPort(replyport);
+ GetMsg(replyport);
+
+ res1 = packet->sp_Pkt.dp_Res1;
+
+ FreeMem((char *)packet,(long)sizeof(*packet));
+ DeletePort(replyport);
+
+ return(res1);
+
+} /* sendpkt() */
+
+#endif /* CRYPT || !FUNZIP */
+
+
+#if CRYPT || (defined(UNZIP) && !defined(FUNZIP))
+
+/* Agetch() reads one raw keystroke -- uses sendpkt() */
+
+int Agetch(void)
+{
+ LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
+ struct Task *me = FindTask(NULL);
+ struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI);
+ BPTR fh = cli->cli_StandardInput; /* this is immune to < redirection */
+ void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type;
+ char longspace[8];
+ long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */
+ UBYTE c;
+
+ *flag = 1;
+ sendpkt(conp, ACTION_SCREEN_MODE, flag, 1); /* assume success */
+ Read(fh, &c, 1);
+ *flag = 0;
+ sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);
+ if (c == 3) /* ^C in input */
+ Signal(me, SIGBREAKF_CTRL_C);
+ return c;
+}
+
+#endif /* CRYPT || (UNZIP && !FUNZIP) */
+
+#endif /* __amiga_filedate_c*/
diff --git a/amiga/makefile.azt b/amiga/makefile.azt
new file mode 100644
index 0000000..08f1cee
--- /dev/null
+++ b/amiga/makefile.azt
@@ -0,0 +1,282 @@
+# Makefile for Zip, ZipNote, ZipCloak, ZipSplit for Aztec C 5.2
+# Also ZipLM, a version of Zip that needs much less free memory
+# -- Paul Kienitz, last updated 25 Jun 98
+
+# Make sure platform is defined correctly, and select memory usage options:
+DEFINES = -d AMIGA -d DYN_ALLOC -d ASM_CRC
+# ASM_CRC now serves only as a notation for "Zip -L".
+
+CC = cc
+AS = as
+CFLAGS = -psb0e -sabfmnpu -wcr0u $(DEFINES)
+# -pbs means unsigned chars and short ints, -sabfmnpu is various small
+# optimizations, -wcr0u adjusts type checking strictness
+
+CFLAGD = -bs -psb0e -s0f0n -wcr0u $(DEFINES)
+# -bs is include source debugging info, -s0f0n is avoid hard-to-debug optimizations
+
+WSIZ = WSIZE=4096
+LOWFLAGS = $(CFLAGS) -d $(WSIZ) -d SMALL_MEM
+# used for compiling a low-memory-use version of Zip
+
+LOWFLAGD = $(CFLAGD) -d $(WSIZ) -d SMALL_MEM
+# for the debuggable low-memory-use version
+
+ASOPTS = -n -eAMIGA -eDYN_ALLOC -eCPUTEST -eINT16
+LOWASOPTS = $(ASOPTS) -e$(WSIZ) -eSMALL_MEM
+# Options used for assembling amiga/deflate.a; must generally match the
+# settings in DEFINES. LOWASOPTS are for the low-memory version.
+
+LD = ln
+LDLIBS = -lc16
+LDFLAGS = -m +q
+
+LDFLAGD = -m +q -g -w
+
+
+# default C rules
+.c.o :
+ $(CC) $(CFLAGS) -o $@ $*.c
+
+# rules for routines containing entries needed by utilities
+.c.oo :
+ $(CC) $(CFLAGS) -d UTIL -o $@ $*.c
+
+# rules for the low-memory version:
+
+.c.ol :
+ $(CC) $(LOWFLAGS) -o $@ $*.c
+
+# default C rules for debugging
+.c.od :
+ $(CC) $(CFLAGD) -o $@ $*.c
+
+# debugging rules for routines containing entries needed by utilities
+.c.dd :
+ $(CC) $(CFLAGD) -d UTIL -o $@ $*.c
+
+# rules for the low-memory version:
+
+.c.dl :
+ $(CC) $(LOWFLAGD) -o $@ $*.c
+
+
+# object file lists
+
+ZIP_H = zip.h ziperr.h tailor.h amiga/osdep.h amiga/z-stat.h amiga/z-time.h
+
+
+OBJZ = zip.o deflate.o trees.o zipfile.o zipup.o util.o \
+ fileio.o globals.o amiga/amiga.o amiga/amigazip.o amiga/crc_68.o \
+ amiga/time_lib.o crctab.o crypt.o ttyio.o
+
+OBJL = zip.ol deflate.ol trees.ol zipfile.ol \
+ zipup.ol util.ol fileio.ol globals.ol crypt.ol ttyio.ol crctab.ol \
+ amiga/amiga.ol amiga/amigazip.ol amiga/crc_68.o amiga/time_lib.o
+
+OBJU = zipfile.oo fileio.oo util.oo globals.o amiga/amiga.oo \
+ amiga/amigazip.oo amiga/time_lib.o
+OBJN = zipnote.o $(OBJU)
+OBJC = zipcloak.o $(OBJU) crctab.o crypt.oo ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+# These are the debuggable versions:
+
+DBJZ = zip.od deflate.od trees.od zipfile.od zipup.od \
+ util.od fileio.od globals.od amiga/amiga.od amiga/amigazip.od \
+ amiga/crc_68.o amiga/time_lib.od crctab.od crypt.od ttyio.od
+
+DBJL = zip.dl deflate.dl trees.dl zipfile.dl zipup.dl util.dl \
+ fileio.dl globals.dl amiga/amiga.dl amiga/amigazip.dl amiga/crc_68.o \
+ amiga/time_lib.od crctab.dl crypt.dl ttyio.dl
+
+DBJU = zipfile.dd fileio.dd util.dd globals.od amiga/amiga.dd \
+ amiga/amigazip.dd amiga/time_lib.od
+DBJN = zipnote.od $(DBJU)
+DBJC = zipcloak.od $(DBJU) crctab.od crypt.dd ttyio.od
+DBJS = zipsplit.od $(DBJU)
+
+
+# HERE WE GO:
+
+all : Zip ZipNote ZipSplit ZipCloak
+
+z : Zip
+
+n : ZipNote
+
+s : ZipSplit
+
+c : ZipCloak
+
+l : ZipLM
+
+# Debug versions:
+
+dall : Zip.dbg ZipNote.dbg ZipSplit.dbg ZipCloak.dbg
+
+dz : Zip.dbg
+
+dn : ZipNote.dbg
+
+ds : ZipSplit.dbg
+
+dc : ZipCloak.dbg
+
+dl : ZipLM.dbg
+
+
+Zip : $(OBJZ) $(ZIP_H)
+ $(LD) $(LDFLAGS) -o $@ $(OBJZ) $(LDLIBS)
+ -@delete Zip.dbg
+
+ZipNote : $(OBJN) $(ZIP_H)
+ $(LD) $(LDFLAGS) -o $@ $(OBJN) $(LDLIBS)
+ -@delete ZipNote.dbg
+
+ZipSplit : $(OBJS) $(ZIP_H)
+ $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
+ -@delete ZipSplit.dbg
+
+ZipCloak : $(OBJC) $(ZIP_H)
+ $(LD) $(LDFLAGS) -o $@ $(OBJC) $(LDLIBS)
+ -@delete ZipCloak.dbg
+
+ZipLM : $(OBJL) $(ZIP_H)
+ $(LD) $(LDFLAGS) -o $@ $(OBJL) $(LDLIBS)
+ -@delete ZipLM.dbg
+
+
+Zip.dbg : $(DBJZ) $(ZIP_H)
+ $(LD) $(LDFLAGD) -o Zip $(DBJZ) $(LDLIBS)
+
+ZipNote.dbg : $(DBJN) $(ZIP_H)
+ $(LD) $(LDFLAGD) -o ZipNote $(DBJN) $(LDLIBS)
+
+ZipSplit.dbg : $(DBJS) $(ZIP_H)
+ $(LD) $(LDFLAGD) -o ZipSplit $(DBJS) $(LDLIBS)
+
+ZipCloak.dbg : $(DBJC) $(ZIP_H)
+ $(LD) $(LDFLAGD) -o ZipCloak $(DBJC) $(LDLIBS)
+
+ZipLM.dbg : $(DBJL) $(ZIP_H)
+ $(LD) $(LDFLAGD) -o ZipLM $(DBJL) $(LDLIBS)
+
+
+clean : bugclean
+ -delete quiet $(OBJZ)
+ -delete quiet $(OBJL)
+ -delete quiet zipnote.o zipcloak.o zipsplit.o \
+ crypt.oo $(OBJU)
+
+bugclean :
+ -delete quiet $(DBJZ)
+ -delete quiet $(DBJL)
+ -delete quiet zipnote.od zipcloak.od zipsplit.od \
+ crypt.dd $(DBJU)
+
+cleaner : clean
+ -delete quiet Zip ZipNote ZipSplit ZipCloak ZipLM
+ -delete quiet Zip.dbg ZipNote.dbg ZipSplit.dbg ZipCloak.dbg ZipLM.dbg
+
+
+# header dependencies:
+
+zip.o zipnote.o zipcloak.o zipsplit.o crypt.o ttyio.o deflate.o \
+ trees.o zipfile.o zipup.o fileio.o util.o crctab.o \
+ globals.o amiga/amiga.o : $(ZIP_H)
+
+zip.ol zipnote.ol zipcloak.ol zipsplit.ol crypt.ol ttyio.ol deflate.ol \
+ trees.ol zipfile.ol zipup.ol fileio.ol util.ol crctab.ol \
+ globals.ol amiga/amiga.ol : $(ZIP_H)
+
+crypt.oo zipfile.oo fileio.oo util.oo : $(ZIP_H)
+
+amiga/amigazip.o amiga/amigazip.ol amiga/amigazip.oo : amiga/amiga.h $(ZIP_H)
+
+zip.o zipnote.o zipcloak.o zipsplit.o zipup.o \
+ zip.ol zipnote.ol zipcloak.ol zipsplit.ol zipup.ol : revision.h
+
+amiga/amiga.o amiga/amiga.ol : crypt.h
+
+crypt.o crypt.oo crypt.ol ttyio.o ttyio.ol zipcloak.o zipcloak.ol \
+ zip.o zip.ol zipup.o zipup.ol : crypt.h ttyio.h
+
+zipup.o zipup.ol : amiga/zipup.h
+
+
+# SPECIAL CASES:
+
+# -mr changes expression parsing; avoids a bogus "expression too complex" error:
+trees.o : trees.c
+ $(CC) $(CFLAGS) -mr -o $@ trees.c
+
+trees.ol : trees.c
+ $(CC) $(LOWFLAGS) -mr -o $@ trees.c
+
+trees.od : trees.c
+ $(CC) $(CFLAGD) -mr -o $@ trees.c
+
+trees.ld : trees.c
+ $(CC) $(LOWFLAGD) -mr -o $@ trees.c
+
+# Substitute the assembly version of deflate.c: (but not in debug version)
+deflate.o : amiga/deflate.a
+ $(AS) $(ASOPTS) -o $@ amiga/deflate.a
+
+deflate.ol : amiga/deflate.a
+ $(AS) $(LOWASOPTS) -o $@ amiga/deflate.a
+
+# The assembly CRC function:
+amiga/crc_68.o : amiga/crc_68.a
+ $(AS) -n -o $@ amiga/crc_68.a
+
+# Put the Amiga internal version data with today's date into amiga.c:
+amiga/amiga.o : amiga/amiga.c amiga/filedate.c amiga/stat.c
+ rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+ $(CC) $(CFLAGS) -o $@ amiga/amiga.c
+ delete env:VersionDate
+
+amiga/amiga.ol : amiga/amiga.c amiga/filedate.c amiga/stat.c
+ rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+ $(CC) $(LOWFLAGS) -o $@ amiga/amiga.c
+ delete env:VersionDate
+
+amiga/amiga.od : amiga/amiga.c amiga/filedate.c amiga/stat.c
+ rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+ $(CC) $(CFLAGD) -o $@ amiga/amiga.c
+ delete env:VersionDate
+
+amiga/amiga.ld : amiga/amiga.c amiga/filedate.c amiga/stat.c
+ rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+ $(CC) $(LOWFLAGD) -o $@ amiga/amiga.c
+ delete env:VersionDate
+
+amiga/amiga.oo : amiga/amiga.c amiga/filedate.c amiga/stat.c
+ rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+ $(CC) $(CFLAGS) -d UTIL -o $@ amiga/amiga.c
+ delete env:VersionDate
+
+amiga/amiga.dd : amiga/amiga.c amiga/filedate.c amiga/stat.c
+ rx > env:VersionDate "say '""'translate(date('E'), '.', '/')'""'"
+ $(CC) $(CFLAGD) -d UTIL -o $@ amiga/amiga.c
+ delete env:VersionDate
+
+# Put the compiler version number into amigazip.c:
+amiga/amigazip.o : amiga/amigazip.c
+ $(CC) $(CFLAGS) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
+
+amiga/amigazip.ol : amiga/amigazip.c
+ $(CC) $(LOWFLAGS) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
+
+amiga/amigazip.od : amiga/amigazip.c
+ $(CC) $(CFLAGD) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
+
+amiga/amigazip.ld : amiga/amigazip.c
+ $(CC) $(LOWFLAGD) -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
+
+amiga/amigazip.oo : amiga/amigazip.c
+ $(CC) $(CFLAGS) -d UTIL -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
+
+amiga/amigazip.dd : amiga/amigazip.c
+ $(CC) $(CFLAGD) -d UTIL -o $@ -d __VERSION__=5 -d __REVISION__=2 amiga/amigazip.c
diff --git a/amiga/match.a b/amiga/match.a
new file mode 100644
index 0000000..ec5bcf0
--- /dev/null
+++ b/amiga/match.a
@@ -0,0 +1,182 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; match.a -- optional optimized asm version of longest match in deflate.c
+; Written by Jean-loup Gailly
+; Adapted for the Amiga by Carsten Steger <stegerc@informatik.tu-muenchen.de>
+; using the code in match.S.
+; The major change in this code consists of removing all unaligned
+; word accesses, because they cause 68000-based Amigas to crash.
+; For maximum speed, UNALIGNED_OK can be defined in Makefile.sasc.
+; The program will then only run on 68020-based Amigas, though.
+; If you have reduced WSIZE in zip.h, then make sure this is
+; assembled with an equivalent -dWSIZE=<whatever>.
+;
+; This code will run with registerized parameters too, unless SAS
+; changes parameter passing conventions between new releases of SAS/C.
+
+
+Cur_Match reg d0 ; Must be in d0!
+Best_Len reg d1
+Loop_Counter reg d2
+Scan_Start reg d3
+Scan_End reg d4
+Limit reg d5
+Chain_Length reg d6
+Scan_Test reg d7
+Scan reg a0
+Match reg a1
+Prev_Address reg a2
+Scan_Ini reg a3
+Match_Ini reg a4
+
+MAX_MATCH equ 258
+MIN_MATCH equ 3
+ ifnd WSIZE
+WSIZE equ 32768
+ endc
+MAX_DIST equ WSIZE-MAX_MATCH-MIN_MATCH-1
+
+
+ xref _max_chain_length
+ xref _prev_length
+ xref _prev
+ xref _window
+ xref _strstart
+ xref _good_match
+ xref _match_start
+ xref _nice_match
+
+
+ section match,code
+
+ xdef _match_init
+ xdef @match_init
+ xdef _longest_match
+ xdef @longest_match
+
+
+_match_init:
+@match_init:
+ rts
+
+
+_longest_match:
+ move.l 4(sp),Cur_Match
+@longest_match:
+ ifd UNALIGNED_OK
+ movem.l d2-d6/a2-a4,-(sp)
+ else
+ movem.l d2-d7/a2-a4,-(sp)
+ endc
+ move.l _max_chain_length,Chain_Length
+ move.l _prev_length,Best_Len
+ lea _prev,Prev_Address
+ lea _window+MIN_MATCH,Match_Ini
+ move.l _strstart,Limit
+ move.l Match_Ini,Scan_Ini
+ add.l Limit,Scan_Ini
+ subi.w #MAX_DIST,Limit
+ bhi.b limit_ok
+ moveq #0,Limit
+limit_ok:
+ cmp.l _good_match,Best_Len
+ bcs.b length_ok
+ lsr.l #2,Chain_Length
+length_ok:
+ subq.l #1,Chain_Length
+
+ ifd UNALIGNED_OK
+
+ move.w -MIN_MATCH(Scan_Ini),Scan_Start
+ move.w -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End
+
+ else
+
+ move.b -MIN_MATCH(Scan_Ini),Scan_Start
+ lsl.w #8,Scan_Start
+ move.b -MIN_MATCH+1(Scan_Ini),Scan_Start
+ move.b -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End
+ lsl.w #8,Scan_End
+ move.b -MIN_MATCH(Scan_Ini,Best_Len.L),Scan_End
+
+ endc
+
+ bra.b do_scan
+
+long_loop:
+
+ ifd UNALIGNED_OK
+
+ move.w -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End
+
+ else
+
+ move.b -MIN_MATCH-1(Scan_Ini,Best_Len.L),Scan_End
+ lsl.w #8,Scan_End
+ move.b -MIN_MATCH(Scan_Ini,Best_Len.L),Scan_End
+
+ endc
+
+short_loop:
+ lsl.w #1,Cur_Match
+ move.w 0(Prev_Address,Cur_Match.L),Cur_Match
+ cmp.w Limit,Cur_Match
+ dbls Chain_Length,do_scan
+ bra.b return
+
+do_scan:
+ move.l Match_Ini,Match
+ add.l Cur_Match,Match
+
+ ifd UNALIGNED_OK
+
+ cmp.w -MIN_MATCH-1(Match,Best_Len.L),Scan_End
+ bne.b short_loop
+ cmp.w -MIN_MATCH(Match),Scan_Start
+ bne.b short_loop
+
+ else
+
+ move.b -MIN_MATCH-1(Match,Best_Len.L),Scan_Test
+ lsl.w #8,Scan_Test
+ move.b -MIN_MATCH(Match,Best_Len.L),Scan_Test
+ cmp.w Scan_Test,Scan_End
+ bne.b short_loop
+ move.b -MIN_MATCH(Match),Scan_Test
+ lsl.w #8,Scan_Test
+ move.b -MIN_MATCH+1(Match),Scan_Test
+ cmp.w Scan_Test,Scan_Start
+ bne.b short_loop
+
+ endc
+
+ move.w #(MAX_MATCH-MIN_MATCH),Loop_Counter
+ move.l Scan_Ini,Scan
+scan_loop:
+ cmpm.b (Match)+,(Scan)+
+ dbne Loop_Counter,scan_loop
+
+ sub.l Scan_Ini,Scan
+ addq.l #(MIN_MATCH-1),Scan
+ cmp.l Best_Len,Scan
+ bls.b short_loop
+ move.l Scan,Best_Len
+ move.l Cur_Match,_match_start
+ cmp.l _nice_match,Best_Len
+ bcs.b long_loop
+return:
+ move.l Best_Len,d0
+ ifd UNALIGNED_OK
+ movem.l (sp)+,d2-d6/a2-a4
+ else
+ movem.l (sp)+,d2-d7/a2-a4
+ endc
+ rts
+
+ end
diff --git a/amiga/match_68.a b/amiga/match_68.a
new file mode 100644
index 0000000..d1a6c39
--- /dev/null
+++ b/amiga/match_68.a
@@ -0,0 +1,273 @@
+;===========================================================================
+; Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+;
+; See the accompanying file LICENSE, version 1999-Oct-05 or later
+; (the contents of which are also included in zip.h) for terms of use.
+; If, for some reason, both of these files are missing, the Info-ZIP license
+; also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+;===========================================================================
+; This is a 68000 assembly language version of the Zip function
+; longest_match(). It is written for any 680x0 based computer, but at this
+; time the feature for runtime testing of CPU type is only supported for the
+; Amiga. Hopefully a similar test for the Macintosh is possible, and for any
+; other system that supports both 68000 and 68020+ CPUs. This is written by
+; Paul Kienitz, partially derived from a simpler version by Carsten Steger,
+; derived in turn from a 386 assembly function by Jean-loup Gailly and Kai Uwe
+; Rommel... but also based directly on the C original.
+;
+; The main difference of this from other longest_match() implementations is
+; that it includes both byte based and word based versions of the function,
+; and various symbols can be defined to select whether to use one routine or
+; the other, or to do a platform-specific test at runtime. The symbols that
+; can be used to select behavior are as follows:
+;
+; CPU020 if defined, use 68020 instructions always
+; CPUTEST if defined, check at runtime for CPU type. Another symbol
+; specifying the platform-specific test must be used with this.
+; If neither of these is defined, use 68000 instructions only.
+; AMIGA use Amiga-specific test for 68020, if CPUTEST defined. Also
+; tells it to let a0/a1/d1 be clobbered by functions.
+; ATSIGN define entry symbols in @foo form as well as _foo, with
+; @longest_match taking its parm in d0 instead of on the stack.
+; WSIZE if defined, determines the sliding window size for deflate;
+; the default is 32K. If you have reduced WSIZE for the C code,
+; make sure that this module is assembled with an equivalent
+; "-dWSIZE=<whatever>" (or "-e...") switch.
+;
+; NOTE: no provision is made for 16 bit ints. All external int variables are
+; treated as 32 bit values. This also assumes that longest_match's result is
+; returned in D0.
+
+ IFND CPU020
+ IFND CPUTEST
+CPU000 equ 1
+ ENDC
+ ENDC
+
+; global variables:
+ xref _max_chain_length ; unsigned int
+ xref _prev_length ; unsigned int
+ xref _match_start ; unsigned int
+ xref _strstart ; unsigned int
+ xref _good_match ; signed int
+ xref _nice_match ; signed int
+ xref _window ; array of unsigned char
+ xref _prev ; array of unsigned short
+
+; our entry points:
+ xdef _match_init ; void match_init(void);
+ xdef _longest_match ; int longest_match(unsigned cur_match);
+ IFD ATSIGN
+ xdef @match_init ; for SAS assembler
+ xdef @longest_match ; ditto
+ ENDC
+
+; flag variable for remembering CPU type:
+ IFD CPUTEST
+ section cpuflag,data
+is020: ds.w 1
+ ENDC
+
+
+ section match,code
+_match_init:
+ IFD ATSIGN
+@match_init:
+ ENDC
+
+ IFD CPUTEST ; now check for platform type
+ IFD AMIGA ; Amiga specific test for '020 CPU:
+
+ xref _SysBase
+
+ NOLIST
+ INCLUDE 'exec/execbase.i'
+ LIST
+
+ clr.w is020 ; default value is 68000
+ move.l _SysBase,a0
+ btst #AFB_68020,AttnFlags+1(a0)
+ beq.s cheap
+ move.w #1,is020
+
+cheap:
+ ELSE ; !AMIGA
+
+ !! Write an '020-detector for your system here!
+
+ ENDC ; AMIGA
+ ENDC ; CPUTEST
+ rts ; match_init consists only of rts if CPUTEST unset
+
+
+ IFD AMIGA
+SAVEREGS reg d3-d7/a2/a3/a5 ; don't protect d0/d1/a0/a1
+ ELSE
+SAVEREGS reg d1/d3-d7/a0-a3/a5 ; protect all but d0 return val
+ ENDC
+
+Cur_Match equr d0 ; Must be in d0!
+Best_Len equr d1
+Scan_Start equr d3
+Scan_End equr d4
+Limit equr d5
+Chain_Length equr d6
+Scan_Test equr d7
+Scan equr a0
+Match equr a1
+Prev_Address equr a2
+Scan_Ini equr a3
+Match_Ini equr a5
+
+
+MAX_MATCH equ 258
+MIN_MATCH equ 3
+ IFND WSIZE
+WSIZE equ 32768
+ ENDC
+MAX_DIST equ WSIZE-MAX_MATCH-MIN_MATCH-1
+
+_longest_match:
+ move.l 4(sp),Cur_Match ; stack arg to register
+ IFD ATSIGN
+@longest_match:
+ ENDC
+ movem.l SAVEREGS,-(sp)
+
+; setup steps common to byte and word versions:
+ move.l _max_chain_length,Chain_Length
+ move.l _prev_length,Best_Len
+ lea _prev,Prev_Address
+ lea _window,Match_Ini
+ move.l _strstart,Limit
+ move.l Match_Ini,Scan_Ini
+ addq #MIN_MATCH,Match_Ini
+ add.l Limit,Scan_Ini
+ subi.w #MAX_DIST,Limit
+ bhi.s limit_ok
+ moveq #0,Limit
+limit_ok:
+ cmp.l _good_match,Best_Len
+ bcs.s length_ok
+ lsr.l #2,Chain_Length
+length_ok:
+ subq.l #1,Chain_Length
+
+ IFD CPUTEST
+ tst.w is020 ; can we use '020 stuff today?
+ bne WORD_match
+ ENDC
+
+ IFND CPU020
+
+; for 68000 or 68010, use byte operations:
+ moveq #0,Scan_Start ; clear 2nd and 4th bytes, use 1st & 3rd
+ moveq #0,Scan_End
+ moveq #0,Scan_Test
+ move.b (Scan_Ini),Scan_Start
+ swap Scan_Start
+ move.b 1(Scan_Ini),Scan_Start
+ move.b -1(Scan_Ini,Best_Len),Scan_End
+ swap Scan_End
+ move.b 0(Scan_Ini,Best_Len),Scan_End
+ bra.s bdo_scan
+
+blong_loop:
+ move.b -1(Scan_Ini,Best_Len),Scan_End
+ swap Scan_End
+ move.b 0(Scan_Ini,Best_Len),Scan_End
+
+bshort_loop:
+ add.w Cur_Match,Cur_Match
+ move.w 0(Prev_Address,Cur_Match.l),Cur_Match
+ cmp.l Limit,Cur_Match
+ dbls Chain_Length,bdo_scan
+ bra return
+
+bdo_scan:
+ move.l Match_Ini,Match
+ add.l Cur_Match,Match
+ move.b -MIN_MATCH-1(Match,Best_Len),Scan_Test
+ swap Scan_Test
+ move.b -MIN_MATCH(Match,Best_Len),Scan_Test
+ cmp.l Scan_Test,Scan_End
+ bne.s bshort_loop
+ move.b -MIN_MATCH(Match),Scan_Test
+ swap Scan_Test
+ move.b -MIN_MATCH+1(Match),Scan_Test
+ cmp.l Scan_Test,Scan_Start
+ bne.s bshort_loop
+ move.w #(MAX_MATCH-MIN_MATCH),Scan_Test
+ lea MIN_MATCH(Scan_Ini),Scan
+
+bscan_loop:
+ cmpm.b (Match)+,(Scan)+
+ dbne Scan_Test,bscan_loop
+ subq #1,Scan
+
+ sub.l Scan_Ini,Scan
+ cmp.l Best_Len,Scan
+ bls.s bshort_loop
+ move.l Scan,Best_Len
+ move.l Cur_Match,_match_start
+ cmp.l _nice_match,Best_Len
+ bcs.s blong_loop
+ IFD CPUTEST
+ bra return
+ ENDC
+
+ ENDC ; !CPU020
+
+ IFND CPU000
+
+; for 68020 or higher, use word operations even on odd addresses:
+WORD_match:
+ move.w (Scan_Ini),Scan_Start
+ move.w -1(Scan_Ini,Best_Len),Scan_End
+ bra.s wdo_scan
+
+wlong_loop:
+ move.w -1(Scan_Ini,Best_Len),Scan_End
+
+wshort_loop:
+ add.w Cur_Match,Cur_Match
+ move.w (Prev_Address,Cur_Match.l),Cur_Match
+ cmp.l Limit,Cur_Match
+ dbls Chain_Length,wdo_scan
+ bra.s return
+
+wdo_scan:
+ move.l Match_Ini,Match
+ add.l Cur_Match,Match
+ cmp.w -MIN_MATCH-1(Match,Best_Len),Scan_End
+ bne.s wshort_loop
+ cmp.w -MIN_MATCH(Match),Scan_Start
+ bne.s wshort_loop
+ moveq #((MAX_MATCH-MIN_MATCH)/2),Scan_Test ; value = 127
+ lea MIN_MATCH(Scan_Ini),Scan
+
+wscan_loop:
+ cmpm.w (Match)+,(Scan)+
+ dbne Scan_Test,wscan_loop
+ subq #2,Scan
+ move.b -MIN_MATCH+1(Match),Scan_Test
+ cmp.b (Scan),Scan_Test
+ bne steven
+ addq #1,Scan
+steven:
+ sub.l Scan_Ini,Scan
+ cmp.l Best_Len,Scan
+ bls.s wshort_loop
+ move.l Scan,Best_Len
+ move.l Cur_Match,_match_start
+ cmp.l _nice_match,Best_Len
+ bcs.s wlong_loop
+
+ ENDC ; !CPU000
+
+return:
+ move.l Best_Len,d0 ; function return value
+ movem.l (sp)+,SAVEREGS
+ rts
+
+ end
diff --git a/amiga/osdep.h b/amiga/osdep.h
new file mode 100644
index 0000000..a5851e3
--- /dev/null
+++ b/amiga/osdep.h
@@ -0,0 +1,109 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __amiga_osdep_h
+#define __amiga_osdep_h
+
+/* default to MEDIUM_MEM, but allow makefile override */
+#if ( (!defined(BIG_MEM)) && (!defined(SMALL_MEM)))
+# define MEDIUM_MEM
+#endif
+
+/* check that TZ environment variable is defined before using UTC times */
+#if (!defined(NO_IZ_CHECK_TZ) && !defined(IZ_CHECK_TZ))
+# define IZ_CHECK_TZ
+#endif
+
+#define USE_CASE_MAP
+#define USE_EF_UT_TIME
+#define HANDLE_AMIGA_SFX
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+ procname(n, 1))
+#define EXIT(e) ClearIOErr_exit(e)
+void ClearIOErr_exit(int e);
+
+#include "amiga/z-stat.h"
+#ifndef USE_TIME_LIB
+# define NO_MKTIME
+#endif
+
+#ifdef __SASC
+# include <sys/types.h>
+# include <exec/execbase.h>
+# if (defined(_M68020) && (!defined(__USE_SYSBASE)))
+ /* on 68020 or higher processors it is faster */
+# define __USE_SYSBASE /* to use the pragma libcall instead of syscall */
+# endif /* to access functions of the exec.library */
+# include <proto/exec.h> /* see SAS/C manual:part 2,chapter 2,pages 6-7 */
+# include <proto/dos.h>
+# if (defined(_M68020) && !defined(UNALIGNED_OK))
+# define UNALIGNED_OK
+# endif
+# ifndef REENTRANT
+# define REENTRANT
+# endif
+# if (defined(_NEAR_DATA) && !defined(DYN_ALLOC))
+# define DYN_ALLOC
+# endif
+# ifdef DEBUG
+# include <sprof.h> /* profiler header file */
+# endif
+ /* define USE_TIME_LIB if replacement functions of time_lib are available */
+ /* replaced are: tzset(), time(), localtime() and gmtime() */
+# define USE_TIME_LIB
+
+/*
+ A word on short-integers and SAS/C (a bug of [mc]alloc?)
+ Using short integers (i.e. compiling with option SHORT-INTEGERS) is
+ *not* recommended. To get maximum compression ratio the window size stored
+ in WSIZE should be 32k (0x8000). However, since the size of the window[]
+ array is 2*WSIZE, 65536 bytes must be allocated. The calloc function can
+ only allocate UINT_MAX (defined in limits.h) bytes which is one byte short
+ (65535) of the maximum window size if you are compiling with short-ints.
+ You'll get an error message "Out of memory (window allocation)" whenever
+ you try to deflate. Note that the compiler won't produce any warning.
+ The maximum window size with short-integers is therefore 32768 bytes.
+ The following is only implemented to allow the use of short-integers but
+ it is once again not recommended because of a loss in compression ratio.
+*/
+# if (defined(_SHORTINT) && !defined(WSIZE))
+# define WSIZE 0x4000 /* only half of maximum window size */
+# endif /* possible with short-integers */
+#endif /* __SASC */
+
+#ifdef AZTEC_C
+# define NO_UNISTD_H
+# define NO_RMDIR
+# define BROKEN_FSEEK
+# define USE_TIME_LIB
+#endif
+
+#ifdef USE_TIME_LIB
+extern int real_timezone_is_set;
+# define VALID_TIMEZONE(tempvar) (tzset(), real_timezone_is_set)
+#else
+# define VALID_TIMEZONE(tempvar) ((tempvar = getenv("TZ")) && tempvar[0])
+#endif
+
+#ifdef ZCRYPT_INTERNAL
+# ifndef CLIB_EXEC_PROTOS_H
+ void *FindTask(void *);
+# endif
+# define ZCR_SEED2 (unsigned)(ulg)FindTask(NULL)
+#endif
+
+int Agetch(void); /* getch() like function, in amiga/filedate.c */
+char *GetComment(char *);
+
+#define FOPR "rb"
+#define FOPM "rb+"
+#define FOPW "wb"
+/* prototype for ctrl-C trap function */
+void _abort(void);
+
+#endif /* !__amiga_osdep_h */
diff --git a/amiga/smakefile b/amiga/smakefile
new file mode 100644
index 0000000..a772fcb
--- /dev/null
+++ b/amiga/smakefile
@@ -0,0 +1,671 @@
+#===========================================================================
+# Makefile for Zip, ZipNote, ZipCloak, ZipSplit AMIGA SAS/C Version 6.58
+# Version: 2.3 last revised: 24 Aug 98
+#===========================================================================
+# -John Bush, <John.Bush@East.Sun.COM>
+# or: <JBush@Bix.COM>
+
+# updated for SAS/C Version 6.56+ and AmigaDOS 3.1 (V40)
+# by Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>
+
+# additional supplements and maintenance by Paul Kienitz
+
+# This makefile should work with at least AmigaDOS 2.04 (V37) (not tested)
+# and will probably not work with AmigaDOS 1.3 (V34)
+
+# If you have any improvements, critics or else please feel free to mail.
+# Any response is appreciated. Haidinger Walter <walthaid@unix.ict.tuwien.ac.at>
+
+# Available targets:
+# all builds all executeables below
+# zip builds zip executeable
+# zipsplit builds zipsplit executeable
+# zipcloak builds zipcloak executeable
+# zipnote builds zipnote executeable
+# ziplm builds low memory version of zip executable
+# clean remove all files created by the compilation
+# spotless like clean target but removes binaries too
+
+
+##########################
+# USER MACRO DEFINITIONS #
+##########################
+
+# *** NOTE ***
+# The assembly version is not implemented yet.
+# (Un)commenting the assembler macros has no effect unless the
+# file dependencies are changed too.
+# Most of the amiga/*.a files do not assmble with 68000 instructions.
+# Any help is appreciated, of course.
+
+# Set the processor to generate code for.
+# Compiler: ANY 68000 68010 68020 68030 68040 68060
+# Assembler: 0 0 1 2 3 4 n/a
+# Defaults: ANY and 0
+#
+CUSECPU = ANY
+AUSECPU = 0
+
+# UNCOMMENT to use 68020 instructions in the assembly version of deflate.o
+# Only use if code is generated for 68020 or higher processors above.
+# Note: You could use CPUTEST too to enable runtime cpu detection.
+# However, it is not recommended since both 68000 and 68020 code will be
+# included which would be an unnecessary increase in size.
+# (see amiga/deflate.a for more information)
+#
+#AUSE020 = CPU020
+
+# To disable the assembler replacements and use the standard C source,
+# you have to change the Zip and ZipLM dependencies. See below for details.
+# (remember that assembler use is *not* implemented yet)
+
+# Uncomment both CUTIL and LUTIL to make use of utility.library of OS 2.04+
+# The utility.library is *not* used for UnZipSFX to ensure maximum portability
+# between the different Amiga systems (minimal config: 68000 and OS 1.2).
+# You can change this by adding the $(LUTIL) macro in the UnZipSFX linking
+# rules (See below: Final output targets, UnZipSFX:).
+# WARNINGS when using the utility library:
+# 1. All Executables will *only* work with AmigaDOS 2.04 (v37) or higher.
+# 2. You *need not* compile/link with short-integers using the
+# utility.library. It will crash your machine. See Libraries below.
+#
+# Default: commented (not used)
+#
+#CUTIL = UTILLIB DEFINE=_UTILLIB
+#LUTIL = WITH SC:LIB/utillib.with # include necessary linker defines
+# Choose one stack-handling method (default=faster)
+# StackExtend: Dynamic runtime stack extension. You won't notice stack overflows.
+# StackCheck: On a stack overflow a requester appears which allows you to exit.
+# Note that either stack watching will slow down your executable because of the
+# extra code run on each function entry. On the other hand, you won't crash
+# anymore due to stack overflows. However, you should not have *any* stack
+# problems with Info-ZIP programs if you raise your stack to 10000 (which I'd
+# recommend as a minimum default stack for all applications) or more using the
+# shell stack command. Type 'Stack 20000' or add it to your S:Shell-Startup.
+# BTW: Typing 'Stack' prints your current stack size.
+#
+CSTACK = NOSTACKCHECK STACKEXTEND # slow, but always works
+#CSTACK = STACKCHECK NOSTACKEXTEND # slow, requester & graceful exit
+#CSTACK = NOSTACKCHECK NOSTACKEXTEND # faster but relies on larger stack (>=10K)
+
+
+#
+# LIBRARIES
+# ---------
+
+# Choose one DATAOPTS , SASLIB , ASMOPTS and LSTARTUP
+# Always comment/uncomment all macros of a set.
+
+# Library to use with near data and 2-byte integers
+# Notes: o slower than 4-byte integers with 68000 cpu
+# o *not* recommended due to poor overall performance
+# o see comment in amiga/osdep.h
+#DATAOPTS = DATA=NEAR SHORTINTEGERS DEF=_NEAR_DATA
+#SASLIB = scs
+#ASMOPTS = -dINT16
+#LSTARTUP = cres.o
+
+# Library to use with near data and 4-byte integers (DEFAULT)
+# *** use this with the utility.library ***
+DATAOPTS = DATA=NEAR DEF=_NEAR_DATA
+SASLIB = sc
+ASMOPTS =
+LSTARTUP = cres.o
+
+# Library to use with far data and 2-byte integers
+# use if DYN_ALLOC is not defined
+# old default - far data always works but is slower
+#DATAOPTS = DATA=FAR SHORTINTEGERS DEF=_FAR_DATA
+#SASLIB = scsnb
+#ASMOPTS = -dINT16
+#LSTARTUP = c.o
+
+# Library to use with far data and 4-byte integers
+# if everything else fails: try this
+#DATAOPTS = DATA=FAR DEF=_FAR_DATA
+#SASLIB = scnb
+#ASMOPTS =
+#LSTARTUP = c.o
+
+
+#
+# DEBUGGING
+# ---------
+
+# Default: No debugging information added.
+# The three macros below will be overwritten if you choose to add
+# debug info, therefore no need to comment.
+
+CDBG = NODEBUG NOPROFILE NOCOVERAGE # default: no debug info
+ADBG =
+LDBG = STRIPDEBUG # default: no debug info
+
+# Compiler and loader debug flags. Uncomment as needed. Recomment when done.
+# Optimization disabled for faster compilation (by using NOOPT)
+
+#CDBG1 = DEF=DEBUG DEF=DEBUG_TIME # enables Info-Zip's debug output
+
+# Enable profiling and coverage when desired. Option COVERAGE commented
+# seperately because running coverage may corrupt your drive in case of a
+# system crash since a file 'cover.dat' is created in your working directory.
+# Note that the use of COVERAGE forces the use of the c.o startup module.
+
+#CDBG2 = PROFILE
+#CDBG3 = COVERAGE # must use c.o startup code:
+#LSTARTUP = c.o # Uncomment *only* when you use COVERAGE
+
+# *Uncomment* here macros CDBG, ADBG and LDBG to include debugging information
+
+#CDBG = $(CDBG1) $(CDBG2) $(CDBG3) ADDSYM DEBUG=FULLFLUSH STACKCHECK NOOPT
+#ADBG = DEBUG
+#LDBG = ADDSYM
+
+# Optional use of memwatch.library which can be found in your
+# sc:extras/memlib directory. Please read the short docs (memlib.doc).
+# Note that memwatch.library has a small bug: MWTerm() displays always
+# the first entry.
+# Get the latest version from aminet (dev/debug/memlib.lha) or
+# contact me to get the patch. Uncomment all macros to use.
+#CMEMLIB = DEFINE=MWDEBUG=1 # define to enable library
+#LMEMLIB = SC:LIB/memwatch.lib # path to library
+#LSTARTUP = c.o # must use c.o with memlib!
+
+
+#
+# MAPPING
+# -------
+
+# Map filenames used when mapping (no need to comment)
+#
+MAPFZ = zip.map # Zip map filename
+MAPFN = zipnote.map # ZipNote map filename
+MAPFC = zipcloak.map # ZipCloak map filename
+MAPFS = zipsplit.map # ZipSplit map filename
+MAPFL = ziplm.map # Zip low memory version map filename
+
+# Map file output: Uncomment to highlight and bold headings.
+#
+#MAPFSTYLE = FANCY
+
+# Map flags for each EXECUTABLE. Uncomment to enable mapping.
+# For map options please refer to:
+# SAS/C v6 manual, volume 1: user's guide, chapter 8, page 136: map
+# Default: all options enabled: f,h,l,o,s,x
+# |-> options start here
+#LMAPZ = $(MAPFSTYLE) MAP $(MAPFZ) f,h,l,o,s,x # Zip maps
+#LMAPN = $(MAPFSTYLE) MAP $(MAPFN) f,h,l,o,s,x # ZipNote maps
+#LMAPC = $(MAPFSTYLE) MAP $(MAPFC) f,h,l,o,s,x # ZipCloak maps
+#LMAPS = $(MAPFSTYLE) MAP $(MAPFS) f,h,l,o,s,x # ZipSplit maps
+#LMAPL = $(MAPFSTYLE) MAP $(MAPFL) f,h,l,o,s,x # Zip lowmem maps
+
+#
+# LISTINGS
+# --------
+
+# Listfile-extensions for each executable (enter *with* dot)
+#
+LISTEXTZ = .lst # extension for Zip listfiles
+LISTEXTU = .ulst # extension for utility listfiles (ZipNote,ZipCloak,ZipSplit)
+LISTEXTL = .llst # extension for Zip low memory listfiles
+
+
+# List files and cross references for each OBJECT.
+# Add/remove flags as needed. Not all listed by default.
+# Use LISTINCLUDES to determine the dependencies for smake
+#
+CLISTOPT = LISTHEADERS LISTMACROS # LISTSYSTEM LISTINCLUDES
+CXREFOPT = XHEAD XSYS
+#
+# Uncomment to enable listing (default: commented)
+# *** WARNING: List files require *lots* of disk space!
+#
+#CLIST = LIST $(CLISTOPT)
+#CXREF = XREF $(CXREFOPT)
+
+
+#
+# SUPPRESSED COMPILER WARNINGS
+# ----------------------------
+
+# Compiler warnings to ignore
+#
+# Warning 105 : module does not define any externally-known symbols
+# Warning 304 : Dead assignment eliminated...
+# Note 306 : ...function inlined...
+# Warning 317 : possibly uninitialized variable...
+# Comment to enable.
+#
+CIGNORE = IGNORE=105,304,306,317
+
+
+#
+# OBJECT EXTENSIONS
+#
+
+# Extensions used for objects of each executeable.
+# Transformation rules require unique extensions.
+# Enter *with* dot.
+#
+O = .o # extension for Zip objects
+OU = .uo # extension for utility objects (ZipNote, ZipSplit and ZipCloak)
+OL = .lo # extension for low memory Zip objects
+
+
+# Filename used to store converted options from environment variable
+# LOCAL_ZIP. Default: scoptions_local_zip
+#
+CWITHOPT = scoptions_local_zip
+
+
+# Filenames to store compiler options to prevent command line overflow
+#
+# Common options file for Zip and other executables
+CFILE = scoptions-zip
+
+
+# Temp filenames for object lists to load using linker "WITH" command.
+OBJLISTZ = zip_objlist.with # Zip object list
+OBJLISTN = zipnote_objlist.with # ZipNote object list
+OBJLISTC = zipcloak_objlist.with # ZipCloak object list
+OBJLISTS = zipsplit_objlist.with # ZipSplit object list
+OBJLISTL = ziplm_objlist.with # Zip low-mem object list
+
+
+# Filenames to store linker options
+#
+LWITHZ = zip.lnk # zip linker options
+LWITHN = zipnote.lnk # zipnote linker options
+LWITHC = zipcloak.lnk # zipcloak linker options
+LWITHS = zipsplit.lnk # zipsplit linker options
+LWITHL = ziplm.lnk # zip low-mem linker options
+
+
+# Define AMIGA_BETA to print "Beta Notice" up front. See tailor.h.
+# Undefine AMIGA_BETA when building a released version.
+#CDEFBETA = DEF=AMIGA_BETA
+
+#####################################
+# NOTHING TO CHANGE BEYOND HERE ... #
+#####################################
+# (except for C/asm dependencies)
+
+# Define MEDIUM_MEM for production release (per Paul Kienitz).
+# This reduces runtime memory requirement but not speed or compression.
+# Note: Do *not* use BIG_MEM or MMAP since it isn't yet supported by the
+ assembler version of deflate.c : amiga/deflate.a
+CUSEMEM = DEF=MEDIUM_MEM
+AUSEMEM = -DMEDIUM_MEM # for asm deflate.o, must match above
+
+
+# Defines for building low-memory use version of Zip
+WSIZEL = WSIZE=4096 # deflate.c window size for low-mem version
+CLOWMEM = DEF=SMALL_MEM DEF=$(WSIZEL)
+ALOWMEM = -DSMALL_MEM -D$(WSIZEL) # for asm deflate.o, must match above
+
+
+# Compiler definitions
+#
+CC = sc
+#
+# Optimizer flags
+#
+OPTPASSES = 6 # set number of global optimizer passes
+#
+OPT1 = OPT OPTINL OPTINLOCAL OPTTIME OPTLOOP OPTSCHED
+OPT2 = OPTCOMP=$(OPTPASSES) OPTDEP=$(OPTPASSES) OPTRDEP=$(OPTPASSES)
+OPT = $(OPT1) $(OPT2)
+
+
+# Compiler flags
+#
+CDEFINES = $(CMEMLIB) $(CDEFBETA) DEF=AMIGA
+COPTIONS = $(DATAOPTS) CODE=NEAR CPU=$(CUSECPU) VERBOSE PARAMETERS=BOTH NOMINC
+COPTIONS = $(COPTIONS) ERRORREXX NOERRORCONSOLE MEMSIZE=HUGE $(CLIST) $(CXREF)
+COPTIONS = $(COPTIONS) $(CSTACK) $(CUTIL) STRICT UNSCHAR NOICONS STRINGMERGE
+CFLAGS = $(CDEFINES) $(COPTIONS) $(OPT) $(CDBG) $(CIGNORE)
+
+
+# Linker definitions
+# See SASLIB definition above
+#
+LD = slink
+# special linker flags for pure (i.e. resident) binary.
+LDFLAGSS = FROM SC:LIB/$(LSTARTUP)
+# common linker flags for all other executeables
+LDFLAGSC = FROM SC:LIB/c.o
+LDFLAGS2 = NOICONS $(LDBG)
+LIBFLAGS = LIB $(LMEMLIB) SC:LIB/$(SASLIB).lib SC:LIB/amiga.lib
+
+
+# Assembler definitions
+#
+ASM = asm
+#
+# Options used for assembling amiga/deflate.a
+# Must match defines in C-Source.
+#
+AFLAGS0 = -d__SASC -dSASC -dAMIGA
+AFLAGS1 = $(AUSE020) $(ASMOPTS) $(ADBG)
+AFLAGS2 = -m$(AUSECPU) -jm -iINCLUDE:
+AFLAGS = $(AFLAGS0) $(AFLAGS1) $(AFLAGS2)
+ASMOPTSZ = $(AFLAGS) $(AUSEMEM) -dDYN_ALLOC # Zip asm flags
+ASMOPTSL = $(AFLAGS) $(ALOWMEM) # Zip low-mem version asm flags
+
+
+##################
+# TARGET OBJECTS #
+##################
+
+
+# Zip objects
+OBJZ1 = zip$(O) zipfile$(O) zipup$(O) fileio$(O) util$(O) globals$(O)
+OBJZ2 = crc32$(O) crctab$(O) crypt$(O) ttyio$(O)
+OBJZI = deflate$(O) trees$(O)
+OBJZA = amiga$(O) amigazip$(O) time_lib$(O) stat$(O) filedate$(O)
+OBJZ = $(OBJZ1) $(OBJZ2) $(OBJZI) $(OBJZA)
+
+# Shared utility objects for ZipNote, ZipCloak and ZipSplit
+OBJU1 = globals$(O)
+OBJUU = zipfile$(OU) fileio$(OU) util$(OU)
+OBJUA = amigazip$(OU) amiga$(O) time_lib$(O) stat$(O) filedate$(O)
+OBJU = $(OBJU1) $(OBJUU) $(OBJUA)
+
+# ZipNote objects
+OBJN1 = zipnote$(O)
+OBJN = $(OBJN1) $(OBJU)
+
+# ZipCloak objects
+OBJC1 = zipcloak$(O)
+OBJCU = $(OBJU) crypt$(OU)
+OBJCS = crctab$(O) ttyio$(O)
+OBJC = $(OBJC1) $(OBJCU) $(OBJCS)
+
+#ZipSplit objects
+OBJS1 = zipsplit$(O)
+OBJS = $(OBJS1) $(OBJU)
+
+# ZipLM objects
+OBJL1 = zip$(OL) zipfile$(OL) zipup$(OL) fileio$(OL) util$(OL) globals$(OL)
+OBJL2 = crc32$(OL) crctab$(OL) crypt$(OL) ttyio$(OL)
+OBJLI = deflate$(OL) trees$(OL)
+OBJLA = amiga$(OL) amigazip$(OL) time_lib$(O) stat$(O) filedate$(O)
+OBJL = $(OBJL1) $(OBJL2) $(OBJLI) $(OBJLA)
+
+# Common header files
+ZIP_H1 = zip.h ziperr.h tailor.h
+ZIP_HA = amiga/osdep.h amiga/z-stat.h amiga/z-time.h
+ZIP_H = $(ZIP_H1) $(ZIP_HA)
+
+# Output targets
+ZIPS = Zip ZipNote ZipCloak ZipSplit ZipLM
+
+
+# Temp filenames for object lists to load using linker "WITH" command.
+OBJLISTZ = zip_objlist.with # Zip object list
+OBJLISTN = zipnote_objlist.with # ZipNote object list
+OBJLISTC = zipcloak_objlist.with # ZipCloak object list
+OBJLISTS = zipsplit_objlist.with # ZipSplit object list
+OBJLISTL = ziplm_objlist.with # Zip low-mem object list
+
+#######################################
+# DEFAULT TARGET AND PROCESSING RULES #
+#######################################
+
+all: request flush $(ZIPS)
+
+# Zip transformation rules
+#
+.c$(O):
+ $(CC) WITH=$(CFILE) $(CUSEMEM) LISTFILE=$>$(LISTEXTZ) OBJNAME=$@ $*.c
+
+# Zip low-memory version transformation rules
+#
+.c$(OL):
+ $(CC) WITH=$(CFILE) $(CLOWMEM) LISTFILE=$>$(LISTEXTL) OBJNAME=$@ $*.c
+
+# Utilities (ZipNote, ZipCloak and ZipSplit) transformation rules
+#
+.c$(OU):
+ $(CC) WITH=$(CFILE) $(CUSEMEM) DEF=UTIL LISTFILE=$>$(LISTEXTU) OBJNAME=$@ $*.c
+
+
+########################
+# Special target rules #
+########################
+
+# Special rule to build time_lib.o for Zip (requires NO_MKTIME define)
+time_lib$(O):
+ $(CC) WITH=$(CFILE) $(CUSEMEM) DEF=ZIP LISTFILE=$>$(LISTEXTZ) OBJNAME=$@ $*.c
+
+#########################
+# Final output targets. #
+#########################
+
+
+zip: local_zip CommonFlags $(OBJZ)
+ @Echo "$(OBJZ)" > $(OBJLISTZ)
+ Type $(OBJLISTZ)
+ @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTZ) $(LIBFLAGS)" \
+ "$(LDFLAGS2) $(LMAPZ)" >$(LWITHZ)
+ Type $(LWITHZ)
+ $(LD) TO Zip WITH $(LWITHZ)
+
+zipnote: local_zip CommonFlags $(OBJN)
+ @Echo "$(OBJN)" > $(OBJLISTN)
+ Type $(OBJLISTN)
+ @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTN) $(LIBFLAGS) " \
+ "$(LDFLAGS2) $(LMAPN)" >$(LWITHN)
+ Type $(LWITHN)
+ $(LD) TO ZipNote WITH $(LWITHN)
+
+zipcloak: local_zip CommonFlags $(OBJC)
+ @Echo "$(OBJC)" > $(OBJLISTC)
+ Type $(OBJLISTC)
+ @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTC) $(LIBFLAGS) " \
+ "$(LDFLAGS2) $(LMAPC)" >$(LWITHC)
+ Type $(LWITHC)
+ $(LD) TO ZipCloak WITH $(LWITHC)
+
+zipsplit: local_zip CommonFlags $(OBJS)
+ @Echo "$(OBJS)" > $(OBJLISTS)
+ Type $(OBJLISTS)
+ @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTS) $(LIBFLAGS) " \
+ "$(LDFLAGS2) $(LMAPS)" >$(LWITHS)
+ Type $(LWITHS)
+ $(LD) TO ZipSplit WITH $(LWITHS)
+
+ziplm: local_zip CommonFlags $(OBJL)
+ @Echo "$(OBJL)" > $(OBJLISTL)
+ Type $(OBJLISTL)
+ @Echo "$(LDFLAGSS) $(LUTIL) WITH $(OBJLISTL) $(LIBFLAGS) " \
+ "$(LDFLAGS2) $(LMAPL)" >$(LWITHL)
+ Type $(LWITHL)
+ $(LD) TO ZipLM WITH $(LWITHL)
+
+
+clean:
+ -Delete >nil: $(OBJZ) quiet
+ -Delete >nil: $(OBJN) quiet
+ -Delete >nil: $(OBJC) quiet
+ -Delete >nil: $(OBJS) quiet
+ -Delete >nil: $(OBJL) quiet
+ -Delete >nil: $(OBJLISTZ) $(OBJLISTL) $(OBJLISTN) $(OBJLISTS) $(OBJLISTC) quiet
+ -Delete >nil: $(MAPFZ) $(MAPFN) $(MAPFC) $(MAPFS) $(MAPFL) quiet
+ -Delete >nil: \#?$(LISTEXTZ) \#?$(LISTEXTU) \#?$(LISTEXTL) quiet
+ -Delete >nil: $(CWITHOPT) $(CFILE) quiet
+ -Delete >nil: $(LWITHZ) $(LWITHN) $(LWITHC) $(LWITHS) $(LWITHL) quiet
+ -Delete >nil: env:VersionDate quiet
+ -Delete >nil: \#?.q.?? \#?.tmp \#?.cov quiet
+
+spotless: clean
+ -Delete >nil: $(ZIPS) quiet
+
+
+################
+# DEPENDENCIES #
+################
+
+# To change between the assembler and C sources, you have to comment/uncomment
+# the approprite lines. C sources are marked by #C-src and assembler sources
+# #asm-src at the end.
+# Zip dependencies:
+#
+
+zip$(O): zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipup$(O): zipup.c $(ZIP_H) revision.h crypt.h amiga/zipup.h
+zipfile$(O): zipfile.c $(ZIP_H) revision.h
+crypt$(O): crypt.c $(ZIP_H) crypt.h ttyio.h
+ttyio$(O): ttyio.c $(ZIP_H) crypt.h ttyio.h
+deflate$(O): deflate.c $(ZIP_H) #C-src
+trees$(O): trees.c $(ZIP_H)
+fileio$(O): fileio.c $(ZIP_H)
+util$(O): util.c $(ZIP_H) mktime.c
+crc32$(O): crc32.c $(ZIP_H)
+crctab$(O): crctab.c $(ZIP_H)
+globals$(O): globals.c $(ZIP_H)
+# Amiga specific objects
+stat$(O): amiga/stat.c amiga/z-stat.h amiga/z-time.h
+filedate$(O): amiga/filedate.c amiga/z-time.h crypt.h
+time_lib$(O): amiga/time_lib.c amiga/z-time.h
+amiga$(O): amiga/amiga.c ziperr.h
+amigazip$(O): amiga/amigazip.c $(ZIP_H) amiga/amiga.h env:Workbench
+# Substitute assembly version of deflate.c:
+#deflate$(O): amiga/deflate.a #asm-src
+# $(ASM) $(ASMOPTSZ) -o$@ $*.a #asm-src
+
+
+# Utility (ZipNote, ZipCloak, ZipSplit) dependencies:
+#
+zipnote$(O): zipnote.c $(ZIP_H) revision.h
+zipcloak$(O): zipcloak.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipsplit$(O): zipsplit.c $(ZIP_H) revision.h
+zipfile$(OU): zipfile.c $(ZIP_H) revision.h
+fileio$(OU): fileio.c $(ZIP_H)
+util$(OU): util.c $(ZIP_H) mktime.c
+crypt$(OU): crypt.c $(ZIP_H) crypt.h ttyio.h
+# Amiga specific objects
+amigazip$(OU): amiga/amigazip.c $(ZIP_H) amiga/amiga.h env:Workbench
+
+# ZipLM dependencies:
+#
+zip$(OL): zip.c $(ZIP_H) revision.h crypt.h ttyio.h
+zipup$(OL): zipup.c $(ZIP_H) revision.h crypt.h amiga/zipup.h
+zipfile$(OL): zipfile.c $(ZIP_H) revision.h
+crypt$(OL): crypt.c $(ZIP_H) crypt.h ttyio.h
+ttyio$(OL): ttyio.c $(ZIP_H) crypt.h ttyio.h
+deflate$(OL): deflate.c $(ZIP_H)
+trees$(OL): trees.c $(ZIP_H)
+fileio$(OL): fileio.c $(ZIP_H)
+util$(OL): util.c $(ZIP_H) mktime.c
+crc32$(OL): crc32.c $(ZIP_H)
+crctab$(OL): crctab.c $(ZIP_H)
+globals$(OL): globals.c $(ZIP_H)
+# Amiga specific objects
+stat$(OL): amiga/stat.c amiga/z-stat.h amiga/z-time.h
+filedate$(OL): amiga/filedate.c amiga/z-time.h crypt.h
+time_lib$(OL): amiga/time_lib.c amiga/z-time.h
+amiga$(OL): amiga/amiga.c ziperr.h
+# Substitute assembly version of deflate.c:
+#deflate$(OL): amiga/deflate.a
+# $(ASM) $(ASMOPTSL) -o$@ $*.a
+
+
+########################
+# DEPENDECIES END HERE #
+########################
+
+# flush all libraries to provide more mem for compilation
+flush:
+ @Avail flush >nil:
+
+# write common compiler flags to file and echo to user
+CommonFlags:
+ @Echo "$(CFLAGS)" >$(CFILE)
+ @Type "$(CWITHOPT)" >>$(CFILE)
+ -Type $(CFILE)
+
+
+# special rules for adding Amiga internal version number to amiga/amiga.c
+amiga$(O):
+ rx > env:VersionDate "say '""'translate(date('E'),'.','/')'""'"
+ $(CC) WITH=$(CFILE) $(CUSEMEM) LISTFILE=$>$(LISTEXTZ) OBJNAME=$@ $*.c
+ -Delete env:VersionDate
+
+amiga$(OL):
+ rx > env:VersionDate "say '""'translate(date('E'),'.','/')'""'"
+ $(CC) WITH=$(CFILE) $(CLOWMEM) LISTFILE=$>$(LISTEXTL) OBJNAME=$@ $*.c
+ -Delete env:VersionDate
+
+
+# needed in amiga/amigazip.c
+# should be set in startup-sequence, but just in case:
+# (only works with OS 2.0 and above)
+
+env\:WorkBench:
+ @Execute < < (Workbench_smk.tmp)
+ FailAt 21
+ If not exists ENV:Workbench
+ Version >nil:
+ SetEnv Workbench $$Workbench
+ Endif
+ <
+
+
+# Read environment variable LOCAL_ZIP and convert options to SAS format
+#
+# e.g.: to define FOO_ONE and FOO_TWO enter:
+#
+# SetEnv LOCAL_ZIP "-DFOO_ONE -DFOO_TWO"
+#
+# Put the statement into your startup-sequence or (for AmigaDOS 2.0 or higher
+# only) make sure LOCAL_ZIP is stored in the ENVARC: directory
+# ( Copy ENV:LOCAL_ZIP ENVARC: )
+#
+
+local_zip:
+ @Execute < < (Local_Zip_smk.tmp)
+ Failat 21
+ If exists ENV:LOCAL_ZIP
+ Echo "Using environment variable LOCAL_ZIP !"
+ Copy >NIL: ENV:LOCAL_ZIP SASCOPTS
+ Else
+ Echo "You could use envvar ZIP_OPT to set your special compilation options."
+ Delete >nil: SASCOPTS quiet
+ Endif
+ ; Do not remove the lctosc command! If LOCAL_ZIP is unset, an
+ ; empty file is created which needed by CommonFlags !
+ lctosc >$(CWITHOPT)
+ <
+
+
+
+# Echo request to the user
+#
+request:
+ @Echo ""
+ @Echo " This makefile is for use with SAS/C version 6.58."
+ @Echo " If you still have an older version, please upgrade!"
+ @Echo " Patches are available on the Aminet under biz/patch/sc\#?."
+ @Echo ""
+ @Echo " Just a simple request..."
+ @Echo " Please give me a mail that you compiled whether you encounter any errors"
+ @Echo " or not. I'd just like to know how many Amiga users actually make use of"
+ @Echo " this makefile."
+ @Echo " If you mail me, I'll put you on my mailing-list and notify you whenever"
+ @Echo " new versions of Info-Zip are released."
+ @Echo " Have a look at the makefile for changes like CPU type, UtilLib, etc."
+ @Echo " Feel free to mail comments, suggestions, etc."
+ @Echo " Enjoy Info-Zip !"
+ @Echo " Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>"
+ @Echo ""
+
+
+# Echo help in case of an error
+#
+.ONERROR:
+ @Echo ""
+ @Echo "[sigh] An error running this makefile was detected."
+ @Echo "This message may also appear if you interrupted smake by pressing CTRL-C."
+ @Echo "Contact Info-Zip authors at Zip-Bugs@lists.wku.edu or me for help."
+ @Echo "Haidinger Walter, <walthaid@unix.ict.tuwien.ac.at>"
+
diff --git a/amiga/stat.c b/amiga/stat.c
new file mode 100644
index 0000000..c453273
--- /dev/null
+++ b/amiga/stat.c
@@ -0,0 +1,293 @@
+/*
+ Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2004-May-22 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* Here we have a handmade stat() function because Aztec's c.lib stat() */
+/* does not support an st_mode field, which we need... also a chmod(). */
+
+/* This stat() is by Paul Wells, modified by Paul Kienitz. */
+/* Originally for use with Aztec C >= 5.0 and Lattice C <= 4.01 */
+/* Adapted for SAS/C 6.5x by Haidinger Walter */
+
+/* POLICY DECISION: We will not attempt to remove global variables from */
+/* this source file for Aztec C. These routines are essentially just */
+/* augmentations of Aztec's c.lib, which is itself not reentrant. If */
+/* we want to produce a fully reentrant UnZip, we will have to use a */
+/* suitable startup module, such as purify.a for Aztec by Paul Kienitz. */
+
+#ifndef __amiga_stat_c
+#define __amiga_stat_c
+
+#include <exec/types.h>
+#include <exec/memory.h>
+#include "amiga/z-stat.h" /* fake version of stat.h */
+#include <string.h>
+
+#ifdef AZTEC_C
+# include <libraries/dos.h>
+# include <libraries/dosextens.h>
+# include <clib/exec_protos.h>
+# include <clib/dos_protos.h>
+# include <pragmas/exec_lib.h>
+# include <pragmas/dos_lib.h>
+#endif
+#ifdef __SASC
+# include <sys/dir.h> /* SAS/C dir function prototypes */
+# include <sys/types.h>
+# include <proto/exec.h>
+# include <proto/dos.h>
+#endif
+
+#ifndef SUCCESS
+# define SUCCESS (-1)
+# define FAILURE (0)
+#endif
+
+
+void close_leftover_open_dirs(void); /* prototype */
+
+static DIR *dir_cleanup_list = NULL; /* for resource tracking */
+
+/* CALL THIS WHEN HANDLING CTRL-C OR OTHER UNEXPECTED EXIT! */
+void close_leftover_open_dirs(void)
+{
+ while (dir_cleanup_list)
+ closedir(dir_cleanup_list);
+}
+
+
+unsigned short disk_not_mounted;
+
+extern int stat(const char *file, struct stat *buf);
+
+stat(file,buf)
+const char *file;
+struct stat *buf;
+{
+
+ struct FileInfoBlock *inf;
+ BPTR lock;
+ time_t ftime;
+ struct tm local_tm;
+
+ if( (lock = Lock((char *)file,SHARED_LOCK))==0 )
+ /* file not found */
+ return(-1);
+
+ if( !(inf = (struct FileInfoBlock *)AllocMem(
+ (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )
+ {
+ UnLock(lock);
+ return(-1);
+ }
+
+ if( Examine(lock,inf)==FAILURE )
+ {
+ FreeMem((char *)inf,(long)sizeof(*inf));
+ UnLock(lock);
+ return(-1);
+ }
+
+ /* fill in buf */
+ buf->st_dev =
+ buf->st_nlink =
+ buf->st_uid =
+ buf->st_gid =
+ buf->st_rdev = 0;
+ buf->st_ino = inf->fib_DiskKey;
+ buf->st_blocks = inf->fib_NumBlocks;
+ buf->st_size = inf->fib_Size;
+
+ /* now the date. AmigaDOS has weird datestamps---
+ * ds_Days is the number of days since 1-1-1978;
+ * however, as Unix wants date since 1-1-1970...
+ */
+
+ ftime =
+ (inf->fib_Date.ds_Days * 86400 ) +
+ (inf->fib_Date.ds_Minute * 60 ) +
+ (inf->fib_Date.ds_Tick / TICKS_PER_SECOND ) +
+ (86400 * 8 * 365 ) +
+ (86400 * 2 ); /* two leap years */
+
+ tzset();
+ /* ftime += timezone; */
+ local_tm = *gmtime(&ftime);
+ local_tm.tm_isdst = -1;
+ ftime = mktime(&local_tm);
+
+ buf->st_ctime =
+ buf->st_atime =
+ buf->st_mtime = ftime;
+
+ buf->st_mode = (inf->fib_DirEntryType < 0 ? S_IFREG : S_IFDIR);
+
+ /* lastly, throw in the protection bits */
+ buf->st_mode |= ((inf->fib_Protection ^ 0xF) & 0xFF);
+
+ FreeMem((char *)inf, (long)sizeof(*inf));
+ UnLock((BPTR)lock);
+
+ return(0);
+
+}
+
+int fstat(int handle, struct stat *buf)
+{
+ /* fake some reasonable values for stdin */
+ buf->st_mode = (S_IREAD|S_IWRITE|S_IFREG);
+ buf->st_size = -1;
+ buf->st_mtime = time(&buf->st_mtime);
+ return 0;
+}
+
+
+/* opendir(), readdir(), closedir(), rmdir(), and chmod() by Paul Kienitz. */
+
+DIR *opendir(const char *path)
+{
+ DIR *dd = AllocMem(sizeof(DIR), MEMF_PUBLIC);
+ if (!dd) return NULL;
+ if (!(dd->d_parentlock = Lock((char *)path, MODE_OLDFILE))) {
+ disk_not_mounted = IoErr() == ERROR_DEVICE_NOT_MOUNTED;
+ FreeMem(dd, sizeof(DIR));
+ return NULL;
+ } else
+ disk_not_mounted = 0;
+ if (!Examine(dd->d_parentlock, &dd->d_fib) || dd->d_fib.fib_EntryType < 0) {
+ UnLock(dd->d_parentlock);
+ FreeMem(dd, sizeof(DIR));
+ return NULL;
+ }
+ dd->d_cleanuplink = dir_cleanup_list; /* track them resources */
+ if (dir_cleanup_list)
+ dir_cleanup_list->d_cleanupparent = &dd->d_cleanuplink;
+ dd->d_cleanupparent = &dir_cleanup_list;
+ dir_cleanup_list = dd;
+ return dd;
+}
+
+void closedir(DIR *dd)
+{
+ if (dd) {
+ if (dd->d_cleanuplink)
+ dd->d_cleanuplink->d_cleanupparent = dd->d_cleanupparent;
+ *(dd->d_cleanupparent) = dd->d_cleanuplink;
+ if (dd->d_parentlock)
+ UnLock(dd->d_parentlock);
+ FreeMem(dd, sizeof(DIR));
+ }
+}
+
+struct dirent *readdir(DIR *dd)
+{
+ return (ExNext(dd->d_parentlock, &dd->d_fib) ? (struct dirent *)dd : NULL);
+}
+
+
+#ifdef AZTEC_C
+
+int rmdir(const char *path)
+{
+ return (DeleteFile((char *)path) ? 0 : IoErr());
+}
+
+int chmod(const char *filename, int bits) /* bits are as for st_mode */
+{
+ long protmask = (bits & 0xFF) ^ 0xF;
+ return !SetProtection((char *)filename, protmask);
+}
+
+
+/* This here removes unnecessary bulk from the executable with Aztec: */
+void _wb_parse(void) { }
+
+/* fake a unix function that does not apply to amigados: */
+int umask(void) { return 0; }
+
+
+# include <signal.h>
+
+/* C library signal() messes up debugging yet adds no actual usefulness */
+typedef void (*__signal_return_type)(int);
+__signal_return_type signal() { return SIG_ERR; }
+
+
+/* The following replaces Aztec's argv-parsing function for compatibility with
+Unix-like syntax used on other platforms. It also fixes the problem the
+standard _cli_parse() has of accepting only lower-ascii characters. */
+
+int _argc, _arg_len;
+char **_argv, *_arg_lin;
+
+void _cli_parse(struct Process *pp, long alen, register UBYTE *aptr)
+{
+ register UBYTE *cp;
+ register struct CommandLineInterface *cli;
+ register short c;
+ register short starred = 0;
+# ifdef PRESTART_HOOK
+ void Prestart_Hook(void);
+# endif
+
+ cli = (struct CommandLineInterface *) (pp->pr_CLI << 2);
+ cp = (UBYTE *) (cli->cli_CommandName << 2);
+ _arg_len = cp[0] + alen + 2;
+ if (!(_arg_lin = AllocMem((long) _arg_len, 0L)))
+ return;
+ c = cp[0];
+ strncpy(_arg_lin, cp + 1, c);
+ _arg_lin[c] = 0;
+ for (cp = _arg_lin + c + 1; alen && (*aptr < '\n' || *aptr > '\r'); alen--)
+ *cp++ = *aptr++;
+ *cp = 0;
+ aptr = cp = _arg_lin + c + 1;
+ for (_argc = 1; ; _argc++) {
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (!*cp)
+ break;
+ if (*cp == '"') {
+ cp++;
+ while (c = *cp++) {
+ if (c == '"' && !starred) {
+ *aptr++ = 0;
+ starred = 0;
+ break;
+ } else if (c == '\\' && !starred)
+ starred = 1;
+ else {
+ *aptr++ = c;
+ starred = 0;
+ }
+ }
+ } else {
+ while ((c = *cp++) && c != ' ' && c != '\t')
+ *aptr++ = c;
+ *aptr++ = 0;
+ }
+ if (c == 0)
+ --cp;
+ }
+ *aptr = 0;
+ if (!(_argv = AllocMem((_argc + 1) * sizeof(*_argv), 0L))) {
+ _argc = 0;
+ return;
+ }
+ for (c = 0, cp = _arg_lin; c < _argc; c++) {
+ _argv[c] = cp;
+ cp += strlen(cp) + 1;
+ }
+ _argv[c] = NULL;
+# ifdef PRESTART_HOOK
+ Prestart_Hook();
+# endif
+}
+
+#endif /* AZTEC_C */
+
+#endif /* __amiga_stat_c */
diff --git a/amiga/time_lib.c b/amiga/time_lib.c
new file mode 100644
index 0000000..2804c05
--- /dev/null
+++ b/amiga/time_lib.c
@@ -0,0 +1,541 @@
+#define __amiga_time_lib_c
+
+/* -----------------------------------------------------------------------------
+This source is copyrighted by Norbert Pueschel <pueschel@imsdd.meb.uni-bonn.de>
+From 'clockdaemon.readme':
+(available from Aminet, main site is ftp.wustl.edu:/pub/aminet/ under
+ util/time/clockdaemon.lha)
+"The original SAS/C functions gmtime, localtime, mktime and time do not
+work correctly. The supplied link library time.lib contains replacement
+functions for them."
+The time.lib library consists of three parts (time.c, timezone.c and version.c),
+all included here. [time.lib 1.2 (1997-04-02)]
+Permission is granted to the Info-ZIP group to redistribute the time.lib source.
+The use of time.lib functions in own, noncommercial programs is permitted.
+It is only required to add the timezone.doc to such a distribution.
+Using the time.lib library in commercial software (including Shareware) is only
+permitted after prior consultation of the author.
+------------------------------------------------------------------------------*/
+/* History */
+/* 30 Mar 1997, Haidinger Walter, added AVAIL_GETVAR macro to support OS <V36 */
+/* 24 May 1997, Haidinger Walter, added NO_MKTIME macro to allow use of Zip's */
+/* mktime.c. NO_MKTIME must be defined in the makefile, though. */
+/* 25 May 1997, Haidinger Walter, moved set_TZ() here from filedate.c */
+/* 20 Jul 1997, Paul Kienitz, adapted for Aztec C, added mkgmtime(), */
+/* debugged, and made New York settings default, as is common. */
+/* 30 Sep 1997, Paul Kienitz, restored real_timezone_is_set flag */
+/* 19 Oct 1997, Paul Kienitz, corrected 16 bit multiply overflow bug */
+/* 21 Oct 1997, Chr. Spieler, shortened long lines, removed more 16 bit stuff */
+/* (n.b. __stdoffset and __dstoffset now have to be long ints) */
+/* 25 Oct 1997, Paul Kienitz, cleanup, make tzset() not redo work needlessly */
+/* 29 Oct 1997, Chr. Spieler, initialized globals _TZ, real_timezone_is_set */
+/* 31 Dec 1997, Haidinger Walter, created z-time.h to overcome sas/c header */
+/* dependencies. TZ_ENVVAR macro added. Happy New Year! */
+/* 25 Apr 1998, Chr. Spieler, __timezone must always contain __stdoffset */
+/* 28 Apr 1998, Chr. Spieler, P. Kienitz, changed __daylight to standard usage */
+
+#ifdef __SASC
+# include <proto/dos.h>
+# include <proto/locale.h>
+# include <proto/exec.h>
+ /* this setenv() is in amiga/filedate.c */
+ extern int setenv(const char *var, const char *value, int overwrite);
+#else
+# include <clib/dos_protos.h>
+# include <clib/locale_protos.h>
+# include <clib/exec_protos.h>
+# include <pragmas/exec_lib.h>
+# include <pragmas/dos_lib.h>
+# include <pragmas/locale_lib.h>
+/* Info-ZIP accesses these by their standard names: */
+# define __timezone timezone
+# define __daylight daylight
+# define __tzset tzset
+#endif
+#define NO_TIME_H
+#include "amiga/z-time.h"
+#include <exec/execbase.h>
+#include <clib/alib_stdio_protos.h>
+#include <string.h>
+#include <stdlib.h>
+
+extern struct ExecBase *SysBase;
+extern char *getenv(const char *var);
+
+typedef unsigned long time_t;
+struct tm {
+ int tm_sec; /* seconds after the minute */
+ int tm_min; /* minutes after the hour */
+ int tm_hour; /* hours since midnight */
+ int tm_mday; /* day of the month */
+ int tm_mon; /* months since January */
+ int tm_year; /* years since 1900 */
+ int tm_wday; /* days since Sunday */
+ int tm_yday; /* days since January 1 */
+ int tm_isdst; /* Daylight Savings Time flag */
+};
+struct dstdate {
+ enum { JULIAN0, JULIAN, MWD } dd_type;
+ int dd_day;
+ int dd_week;
+ int dd_month;
+ int dd_secs;
+};
+static struct dstdate __dststart;
+static struct dstdate __dstend;
+
+#define isleapyear(y) (((y)%4==0&&(!((y)%100==0)||((y)%400==0)))?1:0)
+#define yearlen(y) (isleapyear(y)?366:365)
+#define weekday(d) (((d)+4)%7)
+#define jan1ofyear(y) (((y)-70)*365+((y)-69)/4-((y)-1)/100+((y)+299)/400)
+#define wdayofyear(y) weekday(jan1ofyear(y))
+#define AMIGA2UNIX 252460800 /* seconds between 1.1.1970 and 1.1.1978 */
+#define CHECK 300 /* min. time between checks of IXGMTOFFSET */
+#define GETVAR_REQVERS 36L /* required OS version for GetVar() */
+#define AVAIL_GETVAR (SysBase->LibNode.lib_Version >= GETVAR_REQVERS)
+#ifndef TZ_ENVVAR
+# define TZ_ENVVAR "TZ" /* environment variable to parse */
+#endif
+
+#ifdef __SASC
+ extern int __daylight;
+ extern long __timezone;
+ extern char *__tzname[2];
+ extern char *_TZ;
+#else
+ int __daylight;
+ long __timezone;
+ char *__tzname[2];
+ char *_TZ = NULL;
+#endif
+int real_timezone_is_set = FALSE; /* globally visible TZ_is_valid signal */
+char __tzstn[MAXTIMEZONELEN];
+char __tzdtn[MAXTIMEZONELEN];
+/* the following 4 variables are only used internally; make them static ? */
+int __isdst;
+time_t __nextdstchange;
+long __stdoffset;
+long __dstoffset;
+#define TZLEN 64
+static char TZ[TZLEN];
+static struct tm TM;
+static const unsigned short days[2][13] = {
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+};
+#ifndef NO_MKTIME /* only used by mktime() */
+static const unsigned short monlen[2][12] = {
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+#endif
+
+/* internal prototypes */
+static time_t dst2time(int year,struct dstdate *dst);
+static void time2tm(time_t time);
+static int checkdst(time_t time);
+#ifndef NO_MKTIME
+static void normalize(int *i,int *j,int norm);
+#endif
+static long gettime(char **s);
+static void getdstdate(char **s,struct dstdate *dst);
+#ifdef __SASC
+void set_TZ(long time_zone, int day_light);
+#endif
+
+/* prototypes for sc.lib replacement functions */
+struct tm *gmtime(const time_t *t);
+struct tm *localtime(const time_t *t);
+#ifndef NO_MKTIME
+time_t mkgmtime(struct tm *tm);
+time_t mktime(struct tm *tm);
+#endif
+time_t time(time_t *tm);
+void __tzset(void);
+
+
+static time_t dst2time(int year,struct dstdate *dst)
+{
+ int isleapyear,week,mon,mday;
+ mon = 0;
+ mday = dst->dd_day;
+ isleapyear = isleapyear(year);
+ switch(dst->dd_type) {
+ case JULIAN:
+ if(!isleapyear || dst->dd_day <= 59) break;
+ default:
+ mday++;
+ break;
+ case MWD:
+ mon = dst->dd_month-1;
+ week = dst->dd_week;
+ if(week == 5) {
+ mon++;
+ week = 0;
+ }
+ mday = dst->dd_day - weekday(jan1ofyear(year)+days[isleapyear][mon]);
+ if(mday < 0) mday += 7;
+ mday += (week - 1) * 7 + 1;
+ break;
+ }
+ return((time_t)(jan1ofyear(year)+days[isleapyear][mon]+mday-1)*(time_t)86400L+
+ (time_t)dst->dd_secs);
+}
+
+static void time2tm(time_t time)
+{
+ int isleapyear;
+ TM.tm_sec = time % 60;
+ time /= 60;
+ TM.tm_min = time % 60;
+ time /= 60;
+ TM.tm_hour = time % 24;
+ time /= 24;
+ TM.tm_year = time/365 + 70; /* guess year */
+ while((TM.tm_yday = time - jan1ofyear(TM.tm_year)) < 0) TM.tm_year--;
+ isleapyear = isleapyear(TM.tm_year);
+ for(TM.tm_mon = 0;
+ TM.tm_yday >= days[isleapyear][TM.tm_mon+1];
+ TM.tm_mon++);
+ TM.tm_mday = TM.tm_yday - days[isleapyear][TM.tm_mon] + 1;
+ TM.tm_wday = (time+4)%7;
+}
+
+static int checkdst(time_t time)
+{
+ int year,day;
+ time_t t,u;
+ day = time / 86400L;
+ year = day / 365 + 70; /* guess year */
+ while(day - jan1ofyear(year) < 0) year--;
+ t = dst2time(year,&__dststart) + __stdoffset;
+ u = dst2time(year,&__dstend) + __dstoffset;
+ if(u > t) {
+ return((time >= t && time < u)?1:0);
+ }
+ else {
+ return((time < u || time >= t)?1:0);
+ }
+}
+
+struct tm *gmtime(const time_t *t)
+{
+ TM.tm_isdst = 0;
+ time2tm(*t);
+ return(&TM);
+}
+
+struct tm *localtime(const time_t *t)
+{
+ if(!_TZ) __tzset();
+ TM.tm_isdst = checkdst(*t);
+ time2tm(*t - (TM.tm_isdst ? __dstoffset : __stdoffset));
+ return(&TM);
+}
+
+#ifndef NO_MKTIME /* normalize() only used by mktime() */
+static void normalize(int *i,int *j,int norm)
+{
+ while(*i < 0) {
+ *i += norm;
+ (*j)--;
+ }
+ while(*i >= norm) {
+ *i -= norm;
+ (*j)++;
+ }
+}
+
+time_t mkgmtime(struct tm *tm)
+{
+ time_t t;
+ normalize(&tm->tm_sec,&tm->tm_min,60);
+ normalize(&tm->tm_min,&tm->tm_hour,60);
+ normalize(&tm->tm_hour,&tm->tm_mday,24);
+ normalize(&tm->tm_mon,&tm->tm_year,12);
+ while(tm->tm_mday > monlen[isleapyear(tm->tm_year)][tm->tm_mon]) {
+ tm->tm_mday -= monlen[isleapyear(tm->tm_year)][tm->tm_mon];
+ tm->tm_mon++;
+ if(tm->tm_mon == 12) {
+ tm->tm_mon = 0;
+ tm->tm_year++;
+ }
+ }
+ while(tm->tm_mday < 0) {
+ tm->tm_mon--;
+ if(tm->tm_mon == -1) {
+ tm->tm_mon = 11;
+ tm->tm_year--;
+ }
+ tm->tm_mday += monlen[isleapyear(tm->tm_year)][tm->tm_mon];
+ }
+ tm->tm_yday = tm->tm_mday + days[isleapyear(tm->tm_year)][tm->tm_mon] - 1;
+ t = jan1ofyear(tm->tm_year) + tm->tm_yday;
+ tm->tm_wday = weekday(t);
+ if(tm->tm_year < 70) return((time_t)0);
+ t = t * 86400L + tm->tm_hour * 3600L + tm->tm_min * 60L + (time_t)tm->tm_sec;
+ return(t);
+}
+
+time_t mktime(struct tm *tm)
+{
+ time_t t;
+ if(!_TZ) __tzset();
+ t = mkgmtime(tm);
+ if(tm->tm_isdst < 0) tm->tm_isdst = checkdst(t);
+ t += tm->tm_isdst ? __dstoffset : __stdoffset;
+ return(t);
+}
+#endif /* !NO_MKTIME */
+
+static long gettime(char **s)
+{
+ long num,time;
+ for(num = 0;**s >= '0' && **s <= '9';(*s)++) {
+ num = 10*num + (**s - '0');
+ }
+ time = 3600L * num;
+ if(**s == ':') {
+ (*s)++;
+ for(num = 0;**s >= '0' && **s <= '9';(*s)++) {
+ num = 10*num + (**s - '0');
+ }
+ time += 60 * num;
+ if(**s == ':') {
+ (*s)++;
+ for(num = 0;**s >= '0' && **s <= '9';(*s)++) {
+ num = 10*num + (**s - '0');
+ }
+ time += num;
+ }
+ }
+ return(time);
+}
+
+static void getdstdate(char **s,struct dstdate *dst)
+{
+ switch(**s) {
+ case 'J':
+ case 'j':
+ (*s)++;
+ dst->dd_type = JULIAN;
+ for(dst->dd_day = 0;**s >= '0' && **s <= '9';(*s)++) {
+ dst->dd_day = 10*dst->dd_day + (**s - '0');
+ }
+ break;
+ case 'M':
+ case 'm':
+ (*s)++;
+ dst->dd_type = MWD;
+ for(dst->dd_month = 0;**s >= '0' && **s <= '9';(*s)++) {
+ dst->dd_month = 10*dst->dd_month + (**s - '0');
+ }
+ if(**s != '.') return;
+ (*s)++;
+ for(dst->dd_week = 0;**s >= '0' && **s <= '9';(*s)++) {
+ dst->dd_week = 10*dst->dd_week + (**s - '0');
+ }
+ if(**s != '.') return;
+ (*s)++;
+ for(dst->dd_day = 0;**s >= '0' && **s <= '9';(*s)++) {
+ dst->dd_day = 10*dst->dd_day + (**s - '0');
+ }
+ break;
+ default:
+ dst->dd_type = JULIAN0;
+ for(dst->dd_day = 0;**s >= '0' && **s <= '9';(*s)++) {
+ dst->dd_day = 10*dst->dd_day + (**s - '0');
+ }
+ break;
+ }
+ if(**s == '/') {
+ (*s)++;
+ dst->dd_secs = gettime(s);
+ }
+}
+
+void __tzset(void)
+{
+ char *s,*t;
+ int minus = 0;
+ time_t tm;
+ struct Library *LocaleBase;
+ struct Locale *loc = NULL;
+ if (real_timezone_is_set)
+ return;
+ real_timezone_is_set = TRUE;
+ __dststart.dd_secs = __dstend.dd_secs = 7200;
+ __dststart.dd_type = __dstend.dd_type = MWD;
+ __dststart.dd_month = 4;
+ __dststart.dd_week = 1;
+ __dstend.dd_month = 10;
+ __dstend.dd_week = 5;
+ __dststart.dd_day = __dstend.dd_day = 0; /* sunday */
+ _TZ = NULL;
+ if (AVAIL_GETVAR) { /* GetVar() available? */
+ if(GetVar(TZ_ENVVAR,TZ,TZLEN,GVF_GLOBAL_ONLY) > 0)
+ _TZ = TZ;
+ } else
+ _TZ = getenv(TZ_ENVVAR);
+ if (_TZ == NULL || !_TZ[0]) {
+ static char gmt[MAXTIMEZONELEN] = DEFAULT_TZ_STR;
+ LocaleBase = OpenLibrary("locale.library",0);
+ if(LocaleBase) {
+ loc = OpenLocale(0); /* cannot return null */
+ if (loc->loc_GMTOffset == -300 || loc->loc_GMTOffset == 300) {
+ BPTR eh;
+ if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ))
+ UnLock(eh);
+ else {
+ real_timezone_is_set = FALSE;
+ loc->loc_GMTOffset = 300; /* Amigados bug: default when locale is */
+ } /* not initialized can have wrong sign */
+ }
+ sprintf(gmt, "GMT%ld:%02ld", loc->loc_GMTOffset / 60L,
+ labs(loc->loc_GMTOffset) % 60L);
+ CloseLocale(loc);
+ CloseLibrary(LocaleBase);
+ } else
+ real_timezone_is_set = FALSE;
+ _TZ = gmt;
+ }
+ for(s = _TZ,t = __tzstn;*s && *s != '+' && *s != '-' && *s != ',' &&
+ (*s < '0' || *s > '9');s++) {
+ if(t-__tzstn < MAXTIMEZONELEN-1) *(t++) = *s;
+ }
+ *t = '\0';
+ if(*s == '+') {
+ s++;
+ }
+ else {
+ if(*s == '-') {
+ minus = 1;
+ s++;
+ }
+ }
+ __stdoffset = gettime(&s);
+ if(minus) {
+ __stdoffset *= -1;
+ }
+ if(*s) {
+ minus = 0;
+ for(t = __tzdtn;*s && *s != '+' && *s != '-' && *s != ',' &&
+ (*s < '0' || *s > '9');s++) {
+ if(t-__tzdtn < MAXTIMEZONELEN-1) *(t++) = *s;
+ }
+ *t = '\0';
+ if(*s == '+') {
+ s++;
+ }
+ else {
+ if(*s == '-') {
+ minus = 1;
+ s++;
+ }
+ }
+ if(*s && *s != ',') {
+ __dstoffset = gettime(&s);
+ if(minus) {
+ __dstoffset *= -1;
+ }
+ }
+ else {
+ __dstoffset = __stdoffset - 3600L;
+ }
+ if(*s == ',') {
+ s++;
+ getdstdate(&s,&__dststart);
+ if(*s == ',') {
+ s++;
+ getdstdate(&s,&__dstend);
+ }
+ }
+ }
+ else {
+ __dstoffset = __stdoffset;
+ }
+ time2tm(time(&tm));
+ __isdst = checkdst(tm);
+ __daylight = (__dstoffset != __stdoffset);
+ __timezone = __stdoffset;
+ __nextdstchange = dst2time(TM.tm_year, __isdst ? &__dstend : &__dststart);
+ if(tm >= __nextdstchange) {
+ __nextdstchange = dst2time(TM.tm_year+1,
+ __isdst ? &__dstend : &__dststart);
+ }
+ __tzname[0] = __tzstn;
+ __tzname[1] = __tzdtn;
+#ifdef __SASC
+ if (loc) /* store TZ envvar if data read from locale */
+ set_TZ(__timezone, __daylight);
+#endif
+}
+
+time_t time(time_t *tm)
+{
+ static time_t last_check = 0;
+ static struct _ixgmtoffset {
+ LONG Offset;
+ UBYTE DST;
+ UBYTE Null;
+ } ixgmtoffset;
+ static char *envvarstr; /* ptr to environm. string (used if !AVAIL_GETVAR) */
+ struct DateStamp ds;
+ time_t now;
+ DateStamp(&ds);
+ now = ds.ds_Days * 86400L + ds.ds_Minute * 60L +
+ ds.ds_Tick / TICKS_PER_SECOND;
+ if(now - last_check > CHECK) {
+ last_check = now;
+ if (AVAIL_GETVAR) /* GetVar() available? */
+ if(GetVar("IXGMTOFFSET",(STRPTR)&ixgmtoffset,6,
+ GVF_BINARY_VAR|GVF_GLOBAL_ONLY) == -1) {
+ __tzset();
+ ixgmtoffset.Offset = __isdst ? __dstoffset : __stdoffset;
+ }
+ else
+ if (envvarstr=getenv("IXGMTOFFSET")) {
+ ixgmtoffset = *((struct _ixgmtoffset *)envvarstr); /* copy to struct */
+ __tzset();
+ ixgmtoffset.Offset = __isdst ? __dstoffset : __stdoffset;
+ }
+ }
+ now += AMIGA2UNIX;
+ now += ixgmtoffset.Offset;
+ if(tm) *tm = now;
+ return(now);
+}
+
+#ifdef __SASC
+
+/* Stores data from timezone and daylight to ENV:TZ. */
+/* ENV:TZ is required to exist by some other SAS/C library functions, */
+/* like stat() or fstat(). */
+void set_TZ(long time_zone, int day_light)
+{
+ char put_tz[MAXTIMEZONELEN]; /* string for putenv: "TZ=aaabbb:bb:bbccc" */
+ int offset;
+ void *exists; /* dummy ptr to see if global envvar TZ already exists */
+ if (AVAIL_GETVAR)
+ exists = (void *)FindVar(TZ_ENVVAR,GVF_GLOBAL_ONLY); /* OS V36+ */
+ else
+ exists = (void *)getenv(TZ_ENVVAR);
+ /* see if there is already an envvar TZ_ENVVAR. If not, create it */
+ if (exists == NULL) {
+ /* create TZ string by pieces: */
+ sprintf(put_tz, "GMT%+ld", time_zone / 3600L);
+ if (time_zone % 3600L) {
+ offset = (int) labs(time_zone % 3600L);
+ sprintf(put_tz + strlen(put_tz), ":%02d", offset / 60);
+ if (offset % 60)
+ sprintf(put_tz + strlen(put_tz), ":%02d", offset % 60);
+ }
+ if (day_light)
+ strcat(put_tz,"DST");
+ if (AVAIL_GETVAR) /* store TZ to ENV:TZ. */
+ SetVar(TZ_ENVVAR,put_tz,-1,GVF_GLOBAL_ONLY); /* OS V36+ */
+ else
+ setenv(TZ_ENVVAR,put_tz, 1);
+ }
+}
+#endif /* __SASC */
diff --git a/amiga/timezone.doc b/amiga/timezone.doc
new file mode 100644
index 0000000..7868093
--- /dev/null
+++ b/amiga/timezone.doc
@@ -0,0 +1,85 @@
+Timezone strings:
+-----------------
+This is a description of valid timezone strings for ENV[ARC]:TZ:
+"XPG3TZ - time zone information"
+The form of the time zone information is based on the XPG3 specification of
+the TZ environment variable. Spaces are allowed only in timezone
+designations, where they are significant. The following description
+closely follows the XPG3 specification, except for the paragraphs starting
+**CLARIFICATION**.
+
+<std><offset>[<dst>[<offset>],<start>[/<time>],<end>[/<time>]]
+
+Where:
+<std> and <dst>
+ Are each three or more bytes that are the designation for the
+ standard (<std>) and daylight savings time (<dst>) timezones.
+ Only <std> is required - if <dst> is missing, then daylight
+ savings time does not apply in this locale. Upper- and
+ lower-case letters are allowed. Any characters except a
+ leading colon (:), digits, a comma (,), a minus (-) or a plus
+ (+) are allowed.
+ **CLARIFICATION** The two-byte designation `UT' is permitted.
+<offset>
+ Indicates the value one must add to the local time to arrive
+ at Coordinated Universal Time. The offset has the form:
+ <hh>[:<mm>[:<ss>]]
+ The minutes <mm> and seconds <ss> are optional. The hour <hh>
+ is required and may be a single digit. The offset following
+ <std> is required. If no offset follows <dst>, daylight savings
+ time is assumed to be one hour ahead of standard time. One or
+ more digits may be used; the value is always interpreted as a
+ decimal number. The hour must be between 0 and 24, and the
+ minutes (and seconds) if present between 0 and 59. Out of
+ range values may cause unpredictable behavior. If preceded by
+ a `-', the timezone is east of the Prime Meridian; otherwise
+ it is west (which may be indicated by an optional preceding
+ `+' sign).
+ **CLARIFICATION** No more than two digits are allowed in any
+ of <hh>, <mm> or <ss>. Leading zeros are permitted.
+<start>/<time> and <end>/<time>
+ Indicates when to change to and back from daylight savings
+ time, where <start>/<time> describes when the change from
+ standard time to daylight savings time occurs, and
+ <end>/<time> describes when the change back happens. Each
+ <time> field describes when, in current local time, the change
+ is made.
+ **CLARIFICATION** It is recognized that in the Southern
+ hemisphere <start> will specify a date later than <end>.
+ The formats of <start> and <end> are one of the following:
+ J<n> The Julian day <n> (1 <= <n> <= 365). Leap days are not
+ counted. That is, in all years, February 28 is day 59
+ and March 1 is day 60. It is impossible to refer to
+ the occasional February 29.
+ <n> The zero-based Julian day (0 <= <n> <= 365). Leap days
+ are counted, and it is possible to refer to February
+ 29.
+ M<m>.<n>.<d>
+ The <d>th day, (0 <= <d> <= 6) of week <n> of month <m>
+ of the year (1 <= <n> <= 5, 1 <= <m> <= 12), where week
+ 5 means `the last <d>-day in month <m>' (which may
+ occur in either the fourth or the fifth week). Week 1
+ is the first week in which the <d>th day occurs. Day
+ zero is Sunday.
+ **CLARIFICATION** Neither <n> nor <m> may have a
+ leading zero. <d> must be a single digit.
+ **CLARIFICATION** The default <start> and <end> values
+ are from the first Sunday in April until the last Sunday
+ in October. This allows United States users to leave out
+ the <start> and <end> parts, as most are accustomed to
+ doing.
+ <time> has the same format as <offset> except that no leading
+ sign (`-' or `+') is allowed. The default, if <time> is not
+ given is 02:00:00.
+ **CLARIFICATION** The number of hours in <time> may be up
+ to 167, to allow encoding of rules such as `00:00hrs on the
+ Sunday after the second Friday in September'
+
+Example (for Central Europe):
+-----------------------------
+MET-1MEST,M3.5.0,M10.5.0/03
+
+Another example, for the US East Coast:
+---------------------------------------
+EST5EDT4,M4.1.0/02,M10.5.0/02
+This string describes the default values when no time zone is set.
diff --git a/amiga/z-stat.h b/amiga/z-stat.h
new file mode 100644
index 0000000..bb33b34
--- /dev/null
+++ b/amiga/z-stat.h
@@ -0,0 +1,95 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __amiga_z_stat_h
+#define __amiga_z_stat_h
+
+/* Since older versions of the Lattice C compiler for Amiga, and all current */
+/* versions of the Manx Aztec C compiler for Amiga, either provide no stat() */
+/* function or provide one inadequate for unzip (Aztec's has no st_mode */
+/* field), we provide our own stat() function in stat.c by Paul Wells, and */
+/* this fake stat.h file by Paul Kienitz. Paul Wells originally used the */
+/* Lattice stat.h but that does not work for Aztec and is not distributable */
+/* with this package, so I made a separate one. This has to be pulled into */
+/* unzip.h when compiling an Amiga version, as "amiga/z-stat.h". */
+
+/* We also provide here a "struct dirent" for use with opendir() & readdir() */
+/* functions included in amiga/stat.c. If you use amiga/stat.c, this must */
+/* be included wherever you use either readdir() or stat(). */
+
+#ifdef AZTEC_C
+# define __STAT_H
+#else /* __SASC */
+/* do not include the following header, replacement definitions are here */
+# define _STAT_H /* do not include SAS/C <stat.h> */
+# define _DIRENT_H /* do not include SAS/C <dirent.h> */
+# define _SYS_DIR_H /* do not include SAS/C <sys/dir.h> */
+# define _COMMIFMT_H /* do not include SAS/C <sys/commifmt.h> */
+# include <dos.h>
+#endif
+#include <libraries/dos.h>
+#include "amiga/z-time.h"
+
+
+struct stat {
+ unsigned short st_mode;
+ time_t st_ctime, st_atime, st_mtime;
+ long st_size;
+ long st_ino;
+ long st_blocks;
+ short st_attr, st_dev, st_nlink, st_uid, st_gid, st_rdev;
+};
+
+#define S_IFDIR (1<<11)
+#define S_IFREG (1<<10)
+
+#if 0
+ /* these values here are totally random: */
+# define S_IFLNK (1<<14)
+# define S_IFSOCK (1<<13)
+# define S_IFCHR (1<<8)
+# define S_IFIFO (1<<7)
+# define S_IFMT (S_IFDIR|S_IFREG|S_IFCHR|S_IFLNK)
+#else
+# define S_IFMT (S_IFDIR|S_IFREG)
+#endif
+
+#define S_IHIDDEN (1<<7)
+#define S_ISCRIPT (1<<6)
+#define S_IPURE (1<<5)
+#define S_IARCHIVE (1<<4)
+#define S_IREAD (1<<3)
+#define S_IWRITE (1<<2)
+#define S_IEXECUTE (1<<1)
+#define S_IDELETE (1<<0)
+
+int stat(const char *name, struct stat *buf);
+int fstat(int handle, struct stat *buf); /* returns dummy values */
+
+typedef struct dirent {
+ struct dirent *d_cleanuplink,
+ **d_cleanupparent;
+ BPTR d_parentlock;
+ struct FileInfoBlock d_fib;
+} DIR;
+#define d_name d_fib.fib_FileName
+
+extern unsigned short disk_not_mounted; /* flag set by opendir() */
+
+DIR *opendir(const char *);
+void closedir(DIR *);
+void close_leftover_open_dirs(void); /* call this if aborted in mid-run */
+struct dirent *readdir(DIR *);
+int umask(void);
+
+#ifdef AZTEC_C
+int rmdir(const char *);
+int chmod(const char *filename, int bits);
+#endif
+
+#endif /* __amiga_z_stat_h */
diff --git a/amiga/z-time.h b/amiga/z-time.h
new file mode 100644
index 0000000..53c01bf
--- /dev/null
+++ b/amiga/z-time.h
@@ -0,0 +1,76 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __amiga_z_time_h
+#define __amiga_z_time_h
+
+/* A <time.h> replacement for use with time_lib.c */
+/* Usage: * Define (or Undefine) USE_TIME_LIB below */
+/* * Replace any <time.h> includes by "amiga/z-time.h" */
+
+/* First of all: Select whether to use time_lib functions or not */
+#if 1
+# ifndef USE_TIME_LIB
+# define USE_TIME_LIB
+# endif
+#else
+# ifdef USE_TIME_LIB
+# undef USE_TIME_LIB
+# endif
+#endif
+
+#ifdef USE_TIME_LIB
+ /* constants needed everywhere */
+# define MAXTIMEZONELEN 16
+# ifndef DEFAULT_TZ_STR
+# define DEFAULT_TZ_STR "EST5EDT" /* US East Coast is the usual default */
+# endif
+
+ /* define time_t where needed (everywhere but amiga/time_lib.c) */
+# if defined(__SASC) && defined(NO_TIME_H) && !defined(__amiga_time_lib_c)
+ typedef unsigned long time_t; /* override sas/c's time_t */
+# define _TIME_T 1 /* mark it as already defined */
+# define _COMMTIME_H /* do not include sys/commtime.h */
+# endif
+
+# ifndef NO_TIME_H
+# include <time.h> /* time_lib.c uses NO_TIME_H */
+# endif
+
+ /* adjust included time.h */
+# ifdef __SASC
+ /* tz[sd]tn arrays have different length now: need different names */
+# define __tzstn tzstn
+# define __tzdtn tzdtn
+ /* prevent other possible name conflicts */
+# define __nextdstchange nextdstchange
+# define __stdoffset stdoffset
+# define __dstoffset dstoffset
+
+# ifndef __amiga_time_lib_c
+# ifdef TZ
+# undef TZ /* defined in sas/c time.h */
+# endif TZ
+# define TZ DEFAULT_TZ_STR /* redefine TZ to default timezone */
+ extern char __tzstn[MAXTIMEZONELEN];
+ extern char __tzdtn[MAXTIMEZONELEN];
+# endif
+# endif /* __SASC */
+
+# ifdef AZTEC_C
+ void tzset(void);
+# endif
+
+#else /* ?USE_TIME_LIB */
+
+# ifndef NO_TIME_H
+# include <time.h>
+# endif
+#endif /* !USE_TIME_LIB */
+
+#endif /* __amiga_z_time_h */
diff --git a/amiga/zipup.h b/amiga/zipup.h
new file mode 100644
index 0000000..c9316f4
--- /dev/null
+++ b/amiga/zipup.h
@@ -0,0 +1,25 @@
+/*
+ Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 1999-Oct-05 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, both of these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
+*/
+#ifndef __amiga_zipup_h
+#define __amiga_zipup_h
+
+#ifndef O_RAW
+# define O_RAW 0
+#endif
+#define fhow (O_RDONLY | O_RAW)
+#define fbad (-1)
+typedef int ftype;
+#define zopen(n,p) open(n,p)
+#define zread(f,b,n) read(f,b,n)
+#define zclose(f) close(f)
+#define zerr(f) (k == (extent)(-1L))
+#define zstdin 0
+
+#endif /* __amiga_zipup_h */
+