diff options
Diffstat (limited to 'amiga')
-rw-r--r-- | amiga/LMKfile | 116 | ||||
-rw-r--r-- | amiga/README | 1 | ||||
-rw-r--r-- | amiga/amiga.c | 143 | ||||
-rw-r--r-- | amiga/amiga.h | 54 | ||||
-rw-r--r-- | amiga/amigazip.c | 510 | ||||
-rw-r--r-- | amiga/crc_68.a | 144 | ||||
-rw-r--r-- | amiga/deflate.a | 1053 | ||||
-rw-r--r-- | amiga/filedate.c | 636 | ||||
-rw-r--r-- | amiga/makefile.azt | 282 | ||||
-rw-r--r-- | amiga/match.a | 182 | ||||
-rw-r--r-- | amiga/match_68.a | 273 | ||||
-rw-r--r-- | amiga/osdep.h | 109 | ||||
-rw-r--r-- | amiga/smakefile | 671 | ||||
-rw-r--r-- | amiga/stat.c | 293 | ||||
-rw-r--r-- | amiga/time_lib.c | 541 | ||||
-rw-r--r-- | amiga/timezone.doc | 85 | ||||
-rw-r--r-- | amiga/z-stat.h | 95 | ||||
-rw-r--r-- | amiga/z-time.h | 76 | ||||
-rw-r--r-- | amiga/zipup.h | 25 |
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 */ + |