summaryrefslogtreecommitdiff
path: root/acorn
diff options
context:
space:
mode:
authorLorry <lorry@roadtrain.codethink.co.uk>2012-07-20 19:30:57 +0100
committerLorry <lorry@roadtrain.codethink.co.uk>2012-07-20 19:30:57 +0100
commit04664087ad66f5614f82a2cfba3ae4eda15e792b (patch)
tree332090b15fd2db1b93abf40dccf06211d9aba297 /acorn
downloadzip-04664087ad66f5614f82a2cfba3ae4eda15e792b.tar.gz
Tarball conversion
Diffstat (limited to 'acorn')
-rw-r--r--acorn/GMakefile130
-rw-r--r--acorn/ReadMe85
-rw-r--r--acorn/ReadMe.GMakefile16
-rw-r--r--acorn/RunMe1st23
-rw-r--r--acorn/acornzip.c592
-rw-r--r--acorn/makefile115
-rw-r--r--acorn/match.s217
-rw-r--r--acorn/osdep.h28
-rw-r--r--acorn/riscos.c394
-rw-r--r--acorn/riscos.h119
-rw-r--r--acorn/sendbits.s105
-rw-r--r--acorn/srcrenamebin0 -> 6175 bytes
-rw-r--r--acorn/swiven.h59
-rw-r--r--acorn/swiven.s276
-rw-r--r--acorn/zipsfx9
-rw-r--r--acorn/zipup.h16
16 files changed, 2184 insertions, 0 deletions
diff --git a/acorn/GMakefile b/acorn/GMakefile
new file mode 100644
index 0000000..01842c4
--- /dev/null
+++ b/acorn/GMakefile
@@ -0,0 +1,130 @@
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+# add -g to CC to debug
+# add -d to BIND to debug
+CC = gcc -mlibscl
+BIND = $(CC)
+AS = $(CC) -c
+ASM = AS
+SQUEEZE = squeeze -v
+E =
+
+# flags
+# CFLAGS flags for C compile
+# LFLAGS1 flags after output file spec, before obj file list
+# LFLAGS2 flags after obj file list (libraries, etc)
+#
+LIB =
+CFLAGS = -O2 -mthrowback -DASMV
+ASMFLAGS = -throwback -objasm -upper
+LFLAGS1 =
+LFLAGS2 = $(LIB)
+
+# Uncomment the following line to enable support for Unix
+# Extra Field (Timezone)
+#CFLAGS = $(CFLAGS) -DUSE_EF_UT_TIME
+
+# object file lists
+OBJZ = o.zip o.zipfile o.zipup o.fileio o.util o.globals o.crc32 \
+ o.crypt o.ttyio o.riscos o.acornzip o.swiven
+
+OBJI = o.deflate o.trees
+OBJA = o.match o.sendbits
+OBJU = o.zipfile_ o.fileio_ o.util_ o.globals o.riscos o.acornzip_ o.swiven
+OBJN = o.zipnote $(OBJU)
+OBJC = o.zipcloak $(OBJU) o.crc32_ o.crypt_ o.ttyio
+OBJS = o.zipsplit $(OBJU)
+
+ZIP_H = h.zip h.ziperr h.tailor acorn.h.osdep acorn.h.riscos acorn.h.swiven
+
+all: zip zipnote zipsplit zipcloak
+
+install: %.zip %.zipnote %.zipsplit %.zipcloak %.acorn.zipsfx \
+ zip zipnote zipsplit zipcloak acorn.zipsfx
+ $(SQUEEZE) zip %.zip
+ $(SQUEEZE) zipnote %.zipnote
+ $(SQUEEZE) zipsplit %.zipsplit
+ $(SQUEEZE) zipcloak %.zipcloak
+ copy acorn.zipsfx %.zipsfx ~CVF
+
+# rules for zip, zipnote, zipcloak and zipsplit
+
+o.api: c.api
+ $(CC) $(CFLAGS) -c c.api -o o.api
+o.crc32: c.crc32 $(ZIP_H) h.crc32
+ $(CC) $(CFLAGS) -c c.crc32 -o o.crc32
+o.crypt: c.crypt $(ZIP_H) h.crypt h.crc32 h.ttyio
+ $(CC) $(CFLAGS) -c c.crypt -o o.crypt
+o.deflate: c.deflate $(ZIP_H)
+ $(CC) $(CFLAGS) -c c.deflate -o o.deflate
+o.fileio: c.fileio $(ZIP_H) h.crc32
+ $(CC) $(CFLAGS) -c c.fileio -o o.fileio
+o.globals: c.globals $(ZIP_H)
+ $(CC) $(CFLAGS) -c c.globals -o o.globals
+o.mktime: c.mktime
+ $(CC) $(CFLAGS) -c c.mktime -o o.mktime
+o.trees: c.trees $(ZIP_H)
+ $(CC) $(CFLAGS) -c c.trees -o o.trees
+o.ttyio: c.ttyio $(ZIP_H) h.crypt
+ $(CC) $(CFLAGS) -c c.ttyio -o o.ttyio
+o.util: c.util $(ZIP_H)
+ $(CC) $(CFLAGS) -c c.util -o o.util
+o.zip: c.zip $(ZIP_H) h.crc32 h.crypt h.revision h.ttyio
+ $(CC) $(CFLAGS) -c c.zip -o o.zip
+o.zipcloak: c.zipcloak $(ZIP_H) h.crc32 h.crypt h.revision h.ttyio
+ $(CC) $(CFLAGS) -c c.zipcloak -o o.zipcloak
+o.zipfile: c.zipfile $(ZIP_H) h.crc32
+ $(CC) $(CFLAGS) -c c.zipfile -o o.zipfile
+o.zipnote: c.zipnote $(ZIP_H) h.revision
+ $(CC) $(CFLAGS) -c c.zipnote -o o.zipnote
+o.zipsplit: c.zipsplit $(ZIP_H) h.revision
+ $(CC) $(CFLAGS) -c c.zipsplit -o o.zipsplit
+o.zipup: c.zipup $(ZIP_H) h.crc32 h.crypt h.revision
+ $(CC) $(CFLAGS) -c c.zipup -o o.zipup
+
+o.crc32_: c.crc32 $(ZIP_H) h.crc32
+ $(CC) $(CFLAGS) -DUTIL -c c.crc32 -o o.crc32_
+o.crypt_: c.crypt $(ZIP_H) h.crypt h.crc32 h.ttyio
+ $(CC) $(CFLAGS) -DUTIL -c c.crypt -o o.crypt_
+o.util_: c.util $(ZIP_H)
+ $(CC) $(CFLAGS) -DUTIL -c c.util -o o.util_
+o.fileio_: c.fileio $(ZIP_H) h.crc32
+ $(CC) $(CFLAGS) -DUTIL -c c.fileio -o o.fileio_
+o.zipfile_: c.zipfile $(ZIP_H) h.crc32
+ $(CC) $(CFLAGS) -DUTIL -c c.zipfile -o o.zipfile_
+o.acornzip_: acorn.c.acornzip $(ZIP_H)
+ $(CC) $(CFLAGS) -I@ -DUTIL -c acorn.c.acornzip -o o.acornzip_
+
+o.riscos: acorn.c.riscos acorn.h.riscos $(ZIP_H)
+ $(CC) $(CFLAGS) -I@ -c acorn.c.riscos -o o.riscos
+
+o.acornzip: acorn.c.acornzip $(ZIP_H)
+ $(CC) $(CFLAGS) -I@ -c acorn.c.acornzip -o o.acornzip
+
+o.match: acorn.s.match
+ $(ASM) $(ASMFLAGS) -I@ acorn.s.match -o o.match
+
+o.sendbits: acorn.s.sendbits
+ $(ASM) $(ASMFLAGS) -I@ acorn.s.sendbits -o o.sendbits
+
+o.swiven: acorn.s.swiven
+ $(ASM) $(ASMFLAGS) -I@ acorn.s.swiven -o o.swiven
+
+zip: $(OBJZ) $(OBJI) $(OBJA)
+ $(BIND) -o zip$(E) $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote: $(OBJN)
+ $(BIND) -o zipnote$(E) $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak: $(OBJC)
+ $(BIND) -o zipcloak$(E) $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit: $(OBJS)
+ $(BIND) -o zipsplit$(E) $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+clean:
+ remove zip
+ remove zipcloak
+ remove zipsplit
+ remove zipnote
+ create o.!fake! 0
+ wipe o.* ~cf
+
+# end of Makefile
diff --git a/acorn/ReadMe b/acorn/ReadMe
new file mode 100644
index 0000000..41c37a5
--- /dev/null
+++ b/acorn/ReadMe
@@ -0,0 +1,85 @@
+Acorn-specific compile instructions
+-----------------------------------
+
+Use the "RunMe1st" file (it is an Obey file) to convert all the files from
+"filename/[chs]" to "[chs].filename" (so that zip could be easily compiled
+under RISC OS). It will also set the correct makefile.
+
+To compile just set the CSD to the main zip directory and run 'amu'.
+
+Currently only the Acorn C V5 compiler has been tested but probably also
+Acorn C V4 and the Acorn Assembler V2 will be able to compile zip.
+
+The default makefile is configured without the support for the
+Extended Timestamp Extra Field. If you wan to enable it you have to
+add "-DUSE_EF_UT_TIME" to CFLAGS (see makefile). Without the Extended
+Timestamp Field support, zipfiles created by zip are identical to the
+zipfiles created by SparkFS. However, the Extended Timestamp Field can
+be useful if you are going to unzip your zipfiles on a non-RISC OS machine
+since the correct time stamp will be preserved across different timezones.
+Note that in this case, both the SparkFS Extra Field and the Extended
+Timestamp Extra Field will be used, so the zipfiles will still be fully
+compatible with SparkFS and with the RISC OS version of unzip.
+
+The executables-only distributions will be compiled without the support for
+the Extended Timestamp Extra Field. If you need it but you can't compile zip
+yourself, you can contact the authors at the Info-ZIP address who will do it
+for you.
+
+
+Acorn-specific usage instructions
+---------------------------------
+
+An extra option ('I') has been added to the Acorn port: if it is specified
+zip will not consider Image files (eg. DOS partitions or Spark archives when
+SparkFS is loaded) as directories but will store them as single files. This
+means that if you have, say, SparkFS loaded, zipping a Spark archive will
+result in a zipfile containing a directory (and its content) while using the
+'I' option will result in a zipfile containing a Spark archive. Obviously
+this second case will also be obtained (without the 'I' option) if SparkFS
+isn't loaded.
+
+When adding files to a zipfile; to maintain FileCore compliance, all
+files named "file/ext" will be added to the archive as "file.ext".
+This presents no problem if you wish to use unzip to extract them on any
+other machine, as the files are correctly named. This also presents no
+problem if you use unzip for RISC OS, as the files are converted back to
+"file/ext" format. The only problem appears when you use SparkFS to
+decompress the files, as a file called "file.ext" will be extracted as
+"file_ext", not what it was added as. You must be careful about this.
+
+Case Specific. Depending on how you type the command, files will be added
+exactly as named; in this example:
+*zip new/zip newfile
+*zip new/zip NewFile
+*zip new/zip NEWFILE
+will create an archive containing 3 copies of the same Risc OS file 'newfile'
+called 'newfile', 'NewFile' and 'NEWFILE'. Please be careful.
+
+The Acorn port conserves file attributes, including filetype, so if you
+zip on an Acorn, and unzip on another Acorn, filetypes will be maintained
+precisely as if you used uncompressed files. If you de-archive on another
+machine (PC, Mac, Unix etc..), filetypes will be ignored, but the files
+will be identical despite this. This feature is fully compatible with
+SparkFS, so zipfiles created by zip will be correctly uncompressed (including
+filetype, etc.) by SparkFS.
+
+An additional feature went into this port to cope better with C-code
+and extensions. This allows the acorn files "c.foo" to be added to the
+archive as "foo/c", eventually appearing in the archive as "foo.c", allowing
+for better handling of C or C++ code. Example:
+*Set Zip$Exts "dir1:dir2:dir3"
+*zip new/zip dir1.file
+*zip new/zip dir2.help
+*zip new/zip dir3.textfile
+Creates a zipfile new/zip, with entries file.dir1, help.dir2, textfile.dir3.
+The usual settings for Zip$Exts are "h:o:s:c", allowing C code to be added
+to the archive in standard form.
+
+A final note about the Acorn port regards the use of the 'n' option: this is
+used to specify a list of suffixes that will not be compressed (eg. .ZIP,
+since it is already a compressed file). Since RISC OS uses filetypes instead
+of suffixes, this list of suffixes is actually considered as a list of
+filetypes (3 hex digit format). By default, zip doesn't compress filetypes
+DDC (Archive, Spark or Zip), D96 (CFS files) and 68E (PackDir).
+
diff --git a/acorn/ReadMe.GMakefile b/acorn/ReadMe.GMakefile
new file mode 100644
index 0000000..8762cdb
--- /dev/null
+++ b/acorn/ReadMe.GMakefile
@@ -0,0 +1,16 @@
+GMakefile is for use with Acorn RISC OS and the forthcoming
+post-Acorn RISC OS for the compilation of both the current release and
+development versions of zip.
+
+It is recommended that you use gcc 2.95.4 or higher and you will need a
+suitable 'make' utility. Both are available from
+<URL:http://hard-mofo.dsvr.net/gcc/>.
+
+You will need the files gcc.zip and cc1.zip for the C compiler with the
+documentation available in the gccdoc.zip archive. GNU make can be
+found in the utils.zip archive, although most versions of 'make' should be
+fine.
+
+When using gcc, check RunMe1st for two lines which need uncommenting.
+
+
diff --git a/acorn/RunMe1st b/acorn/RunMe1st
new file mode 100644
index 0000000..a330adb
--- /dev/null
+++ b/acorn/RunMe1st
@@ -0,0 +1,23 @@
+| This Obey file prepares the zip port for a Desktop C re-compile.
+| Run it and it will copy all the needed files into the correct
+| place.
+
+| Set the correct type of 'srcrename' so that the only requirement
+| for the user is to set 'RunMe1st' to Obey
+SetType <Obey$Dir>.srcrename FF8
+
+| Run 'srcrename' on the main zip directory with recursion enabled
+/<Obey$Dir>.srcrename -r -e c:h:s:o <Obey$Dir>.^
+
+| Create the 'o' directory
+CDir <Obey$Dir>.^.o
+
+| Put the Makefile in its correct place and set the correct filetype
+Copy <Obey$Dir>.makefile <Obey$Dir>.^.makefile ~C ~V F
+
+| Uncomment the following lines if you're using gcc
+|| Put the Makefile in its correct place and set the correct filetype
+|Copy <Obey$Dir>.GMakefile <Obey$Dir>.^.makefile ~C~VF
+
+SetType <Obey$Dir>.^.makefile FE1
+SetType <Obey$Dir>.zipsfx Obey
diff --git a/acorn/acornzip.c b/acorn/acornzip.c
new file mode 100644
index 0000000..40debc0
--- /dev/null
+++ b/acorn/acornzip.c
@@ -0,0 +1,592 @@
+/*
+ Copyright (c) 1990-2002 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2000-Apr-09 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include <stdlib.h>
+#include <string.h>
+#include "zip.h"
+
+#ifndef UTIL
+
+#define PAD 0
+#define PATH_END '/'
+
+
+local int wild_recurse(char *whole, char *wildtail);
+local int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut);
+
+extern char *label;
+local ulg label_time = 0;
+local ulg label_mode = 0;
+local time_t label_utim = 0;
+
+char *readd(DIR *d)
+/* 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;
+
+ e = readdir(d);
+ return (e == NULL ? (char *) NULL : e->d_name);
+}
+
+/* What we have here is a mostly-generic routine using opend()/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]". */
+
+/* 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;
+ struct stat statb;
+ int disk_not_mounted=0;
+ int e = ZE_MISS;
+
+ if (!isshexp(wildtail)) {
+ if (stat(whole,&statb)==0 && (statb.st_mode & S_IREAD)!=0) {
+ 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 == '.') {
+ 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, '.')) != NULL) {
+ /* this "+ 1" dodges the ^^^ hole left by *glue == 0 */
+ *(subwild++) = 0; /* wildtail = one component pattern */
+ newlen = strlen(whole) + strlen(subwild) + 32;
+ } else
+ newlen = strlen(whole) + 31;
+ 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++) = '.';
+ 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 = '.';
+ if (newwhole) free(newwhole);
+ if (e == ZE_MISS && amatch)
+ e = ZE_OK;
+ return e;
+}
+
+int wild(p)
+char *p;
+{
+ char *path;
+ int toret;
+
+ /* special handling of stdin request */
+ if (strcmp(p, "-") == 0) /* if compressing stdin */
+ return newname(p, 0, 0);
+
+ path=p;
+ if (strchr(p, ':')==NULL && *p!='@') {
+ if (!(path=malloc(strlen(p)+3))) {
+ return ZE_MEM;
+ }
+ strcpy(path,"@.");
+ strcat(path,p);
+ }
+
+ toret=wild_recurse(path, path);
+
+ if (path!=p) {
+ free(path);
+ }
+ return toret;
+}
+
+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;
+ if (strcmp(n, ".") == 0) {
+ *p = '\0'; /* avoid "./" prefix and do not create zip entry */
+ } else {
+ strcpy(p, n);
+ a = p + strlen(p);
+ if (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 (strcmp(e, ".") && strcmp(e, ".."))
+ {
+ 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 */
+ char *tmp;
+ int dosflag;
+ char *lastlastdir=NULL; /* pointer to 2 dirs before... */
+ char *lastdir=NULL; /* pointer to last dir... */
+
+ /* Malloc space for internal name and copy it */
+ if ((tmp = malloc(strlen(x) + 1)) == NULL)
+ return NULL;
+ strcpy(tmp, x);
+
+ dosflag = dosify; /* default for non-DOS and non-OS/2 */
+
+ /* Find starting point in name before doing malloc */
+ for(t=tmp;*t;t++) {
+ if (*t=='/') {
+ *t='.';
+ }
+ else if (*t=='.') {
+ *t='/';
+ lastlastdir=lastdir;
+ lastdir=t+1;
+ }
+ }
+
+ t=strchr(tmp,'$'); /* skip FS name */
+ if (t!=NULL)
+ t+=2; /* skip '.' after '$' */
+ else
+ t=tmp;
+ if (*t=='@') /* skip @. at the beginning of filenames */
+ t+=2;
+
+ /* Make changes, if any, to the copied name (leave original intact) */
+
+ /* return a pointer to '\0' if the file is a directory with the same
+ same name as an extension to swap (eg. 'c', 'h', etc.) */
+ if (isdir && exts2swap!=NULL) {
+ if (lastlastdir==NULL)
+ lastlastdir=t;
+ if (checkext(lastlastdir)) {
+ free((void *)tmp);
+ n=malloc(1);
+ if (n!=NULL)
+ *n='\0';
+ return n;
+ }
+ }
+
+ if (exts2swap!=NULL && lastdir!=NULL) {
+ if (lastlastdir==NULL)
+ lastlastdir=t;
+ if (checkext(lastlastdir)) {
+ if (swapext(lastlastdir,lastdir-1)) {
+ free((void *)tmp);
+ return NULL;
+ }
+ }
+ }
+
+ if (!pathput)
+ t = last(t, PATH_END);
+
+ /* Malloc space for internal name and copy it */
+ if ((n = malloc(strlen(t) + 1)) == NULL) {
+ free((void *)tmp);
+ return NULL;
+ }
+ strcpy(n, t);
+
+ free((void *)tmp);
+
+ 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 */
+ char *t; /* scans name */
+ char *lastext=NULL; /* pointer to last extension */
+ char *lastdir=NULL; /* pointer to last dir */
+
+ if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
+ return NULL;
+ strcpy(x, n);
+
+ for(t=x;*t;t++) {
+ if (*t=='.') {
+ *t='/';
+ lastext=t+1;
+ }
+ else if (*t=='/') {
+ *t='.';
+ lastdir=t+1;
+ }
+ }
+
+ if (exts2swap!=NULL && (int)lastext>(int)lastdir) {
+ if (lastdir==NULL)
+ lastdir=x;
+ if (checkext(lastext)) {
+ if (swapext(lastdir,lastext-1)) {
+ free((void *)x);
+ return NULL;
+ }
+ }
+ }
+
+ return x;
+}
+
+local int uxtime2acornftime(unsigned *pexadr, unsigned *pldadr, time_t ut)
+{
+ unsigned timlo; /* 3 lower bytes of acorn file-time plus carry byte */
+ unsigned timhi; /* 2 high bytes of acorn file-time */
+
+ timlo = ((unsigned)ut & 0x00ffffffU) * 100 + 0x00996a00U;
+ timhi = ((unsigned)ut >> 24);
+ timhi = timhi * 100 + 0x0000336eU + (timlo >> 24);
+ if (timhi & 0xffff0000U)
+ return 1; /* calculation overflow, do not change time */
+
+ /* insert the five time bytes into loadaddr and execaddr variables */
+ *pexadr = (timlo & 0x00ffffffU) | ((timhi & 0x000000ffU) << 24);
+ *pldadr = (*pldadr & 0xffffff00U) | ((timhi >> 8) & 0x000000ffU);
+
+ return 0; /* subject to future extension to signal overflow */
+}
+
+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 m_time;
+ unsigned int loadaddr, execaddr;
+ int attr;
+
+ /* Convert DOS time to time_t format in m_time */
+ m_time = dos2unixtime(d);
+
+ /* set the file's modification time */
+ SWI_OS_File_5(f,NULL,&loadaddr,NULL,NULL,&attr);
+
+ if (uxtime2acornftime(&execaddr, &loadaddr, m_time) != 0)
+ return;
+
+ SWI_OS_File_1(f,loadaddr,execaddr,attr);
+}
+
+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() */
+ /* convert FNMAX to malloc - 11/8/04 EG */
+ 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) {
+ /* forge stat values for stdin since Amiga and RISCOS have no fstat() */
+ s.st_mode = (S_IREAD|S_IWRITE|S_IFREG);
+ s.st_size = -1;
+ s.st_mtime = time(&s.st_mtime);
+ } else if (LSSTAT(name, &s) != 0) {
+ /* Accept about any file kind including directories
+ * (stored with trailing / with -r option)
+ */
+ free(name);
+ return 0;
+ }
+ free(name);
+
+ 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;
+ }
+
+ return unix2dostime((time_t *) &s.st_mtime);
+}
+
+int set_extra_field(z, z_utim)
+ struct zlist far *z;
+ iztimes *z_utim;
+{
+#ifdef USE_EF_UT_TIME
+ char *eb_ptr;
+#endif /* USE_EF_UT_TIME */
+ char *name;
+ extra_block *block;
+
+#define EB_SPARK_LEN 20
+#define EB_SPARK_SIZE (EB_HEADSIZE+EB_SPARK_LEN)
+#ifdef USE_EF_UT_TIME
+# ifdef IZ_CHECK_TZ
+# define EB_UTTIME_SIZE (zp_tz_is_valid ? EB_HEADSIZE+EB_UT_LEN(1) : 0)
+# else
+# define EB_UTTIME_SIZE (EB_HEADSIZE+EB_UT_LEN(1))
+# endif
+#else
+# define EB_UTTIME_SIZE 0
+#endif
+#define EF_SPARK_TOTALSIZE (EB_SPARK_SIZE + EB_UTTIME_SIZE)
+
+ if ((name=(char *)malloc(strlen(z->name)+1))==NULL) {
+ fprintf(stderr," set_extra_field: not enough memory for directory name\n");
+ return ZE_MEM;
+ }
+
+ strcpy(name,z->name);
+
+ if (name[strlen(name)-1]=='.') { /* remove the last '.' in directory names */
+ name[strlen(name)-1]=0;
+ }
+
+ z->extra=(char *)malloc(EF_SPARK_TOTALSIZE);
+ if (z->extra==NULL) {
+ fprintf(stderr," set_extra_field: not enough memory\n");
+ free(name);
+ return ZE_MEM;
+ }
+ z->cextra = z->extra;
+ z->cext = z->ext = EF_SPARK_TOTALSIZE;
+
+ block=(extra_block *)z->extra;
+ block->ID=SPARKID;
+ block->size=EB_SPARK_LEN;
+ block->ID_2=SPARKID_2;
+ block->zero=0;
+
+ if (SWI_OS_File_5(name,NULL,&block->loadaddr,&block->execaddr,
+ NULL,&block->attr) != NULL) {
+ fprintf(stderr," OS error while set_extra_field of %s\n",name);
+ }
+
+ free(name);
+
+#ifdef USE_EF_UT_TIME
+# ifdef IZ_CHECK_TZ
+ if (zp_tz_is_valid) {
+# endif
+ eb_ptr = z->extra + EB_SPARK_SIZE;
+
+ eb_ptr[0] = 'U';
+ eb_ptr[1] = 'T';
+ eb_ptr[2] = EB_UT_LEN(1); /* length of data part of e.f. */
+ eb_ptr[3] = 0;
+ eb_ptr[4] = EB_UT_FL_MTIME;
+ eb_ptr[5] = (char)(z_utim->mtime);
+ eb_ptr[6] = (char)(z_utim->mtime >> 8);
+ eb_ptr[7] = (char)(z_utim->mtime >> 16);
+ eb_ptr[8] = (char)(z_utim->mtime >> 24);
+# ifdef IZ_CHECK_TZ
+ }
+# endif
+#endif /* USE_EF_UT_TIME */
+
+ return ZE_OK;
+}
+
+#endif /* !UTIL */
+
+
+/******************************/
+/* Function version_local() */
+/******************************/
+
+void version_local()
+{
+ static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
+
+ printf(CompiledWith,
+#ifdef __GNUC__
+ "gcc ", __VERSION__,
+#else
+# ifdef __CC_NORCROFT
+ "Norcroft ", "cc",
+# else
+ "cc", "",
+# endif
+#endif
+
+ "RISC OS",
+
+ " (Acorn Computers Ltd)",
+
+#ifdef __DATE__
+ " on ", __DATE__
+#else
+ "", ""
+#endif
+ );
+
+} /* end function version_local() */
diff --git a/acorn/makefile b/acorn/makefile
new file mode 100644
index 0000000..323ffca
--- /dev/null
+++ b/acorn/makefile
@@ -0,0 +1,115 @@
+# Makefile for Zip, ZipNote, ZipCloak and ZipSplit
+
+# add -g to CC to debug
+# add -d to BIND to debug
+CC = cc
+BIND = link
+AS = $(CC) -c
+ASM = objasm
+SQUEEZE = squeeze -v
+E =
+
+# flags
+# CFLAGS flags for C compile
+# LFLAGS1 flags after output file spec, before obj file list
+# LFLAGS2 flags after obj file list (libraries, etc)
+#
+LIB =
+CBASE = -throwback -wn -DASMV -apcs 3/26
+CFLAGS = $(CBASE) -IC:,@.
+ASMFLAGS = -Throwback -Stamp -NoCache -CloseExec -quit -apcs 3/26
+LFLAGS1 =
+LFLAGS2 = $(LIB) C:o.Stubs
+
+# Uncomment the following line to enable support for Unix
+# Extra Field (Timezone)
+#CFLAGS = $(CFLAGS) -DUSE_EF_UT_TIME
+
+# object file lists
+OBJZ = zip.o zipfile.o zipup.o fileio.o util.o globals.o crc32.o \
+ crypt.o ttyio.o riscos.o acornzip.o swiven.o
+
+OBJI = deflate.o trees.o
+OBJA = match.o sendbits.o
+OBJU = zipfile_.o fileio_.o util_.o globals.o riscos.o acornzip_.o swiven.o
+OBJN = zipnote.o $(OBJU)
+OBJC = zipcloak.o $(OBJU) crc32_.o crypt_.o ttyio.o
+OBJS = zipsplit.o $(OBJU)
+
+ZIP_H = zip.h ziperr.h tailor.h acorn/osdep.h acorn/riscos.h acorn/swiven.h
+
+all: zip zipnote zipsplit zipcloak
+
+
+install: %.zip %.zipnote %.zipsplit %.zipcloak %.zipsfx \
+ zip zipnote zipsplit zipcloak zipsfx
+ $(SQUEEZE) zip %.zip
+ $(SQUEEZE) zipnote %.zipnote
+ $(SQUEEZE) zipsplit %.zipsplit
+ $(SQUEEZE) zipcloak %.zipcloak
+ copy acorn.zipsfx %.zipsfx ~CVF
+
+# suffix rules
+.SUFFIXES: _.o .o .c
+.c_.o:
+ $(CC) $(CFLAGS) -DUTIL -c $*.c -o $*_.o
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+.s.o:
+ $(ASM) $(ASMFLAGS) -from @*.s -to @*.o
+
+# rules for zip, zipnote, zipcloak and zipsplit
+$(OBJZ): $(ZIP_H)
+$(OBJI): $(ZIP_H)
+$(OBJN): $(ZIP_H)
+$(OBJS): $(ZIP_H)
+$(OBJC): $(ZIP_H)
+zip.o crc32.o crypt.o fileio.o zipfile.o zipup.o: crc32.h
+zipcloak.o crc32_.o crypt_.o fileio_.o zipfile_.o: crc32.h
+zip.o zipup.o crypt.o ttyio.o zipcloak.o crypt_.o: crypt.h
+zip.o zipup.o zipnote.o zipcloak.o zipsplit.o: revision.h
+zip.o crypt.o ttyio.o zipcloak.o crypt_.o: ttyio.h
+
+crc32_.o: crc32.c
+ $(CC) $(CFLAGS) -DUTIL -c c.crc32 -o o.crc32_
+crypt_.o: crypt.c
+ $(CC) $(CFLAGS) -DUTIL -c c.crypt -o o.crypt_
+util_.o: util.c
+ $(CC) $(CFLAGS) -DUTIL -c c.util -o o.util_
+fileio_.o: fileio.c
+ $(CC) $(CFLAGS) -DUTIL -c c.fileio -o o.fileio_
+zipfile_.o: zipfile.c
+ $(CC) $(CFLAGS) -DUTIL -c c.zipfile -o o.zipfile_
+acornzip_.o: acorn/acornzip.c $(ZIP_H)
+ $(CC) $(CFLAGS) -DUTIL -c acorn/acornzip.c -o o.acornzip_
+
+riscos.o: acorn/riscos.c acorn/riscos.h
+ $(CC) $(CFLAGS) -c acorn/riscos.c
+
+acornzip.o: acorn/acornzip.c $(ZIP_H)
+ $(CC) $(CFLAGS) -c acorn/acornzip.c
+
+match.o: acorn/match.s
+ $(ASM) $(ASMFLAGS) -from acorn.s.match -to o.match
+
+sendbits.o: acorn/sendbits.s
+ $(ASM) $(ASMFLAGS) -from acorn.s.sendbits -to o.sendbits
+
+swiven.o: acorn/swiven.s
+ $(ASM) $(ASMFLAGS) -from acorn.s.swiven -to o.swiven
+
+zip: $(OBJZ) $(OBJI) $(OBJA)
+ $(BIND) -o zip$(E) $(LFLAGS1) $(OBJZ) $(OBJI) $(OBJA) $(LFLAGS2)
+zipnote: $(OBJN)
+ $(BIND) -o zipnote$(E) $(LFLAGS1) $(OBJN) $(LFLAGS2)
+zipcloak: $(OBJC)
+ $(BIND) -o zipcloak$(E) $(LFLAGS1) $(OBJC) $(LFLAGS2)
+zipsplit: $(OBJS)
+ $(BIND) -o zipsplit$(E) $(LFLAGS1) $(OBJS) $(LFLAGS2)
+
+clean: ;remove zip; remove zipcloak;
+ remove zipsplit; remove zipnote;
+ create o.!fake! 0
+ wipe o.* ~cf
+
+# end of Makefile
diff --git a/acorn/match.s b/acorn/match.s
new file mode 100644
index 0000000..ee68ce6
--- /dev/null
+++ b/acorn/match.s
@@ -0,0 +1,217 @@
+;===========================================================================
+; 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.s for ARM by Sergio Monesi.
+
+r0 RN 0
+r1 RN 1
+r2 RN 2
+r3 RN 3
+r4 RN 4
+r5 RN 5
+r6 RN 6
+r7 RN 7
+r8 RN 8
+r9 RN 9
+sl RN 10
+fp RN 11
+ip RN 12
+sp RN 13
+lr RN 14
+pc RN 15
+
+MAX_DIST EQU 32506
+WMASK EQU 32767
+MAX_MATCH EQU 258
+
+ AREA |C$$code|, CODE, READONLY
+
+
+; r1 = chain_lenght
+; r2 = scan
+; r3 = match
+; r4 = len (tmp)
+; r5 = best_len
+; r6 = limit
+; r7 = strend
+; r8 = scan_end1
+; r9 = scan_end
+; lr = window
+; fp = prev
+
+|__max_chain_length|
+ IMPORT max_chain_length
+ DCD max_chain_length
+|__window|
+ IMPORT window
+ DCD window
+|__prev|
+ IMPORT prev
+ DCD prev
+|__prev_length|
+ IMPORT prev_length
+ DCD prev_length
+|__strstart|
+ IMPORT strstart
+ DCD strstart
+|__good_match|
+ IMPORT good_match
+ DCD good_match
+|__nice_match|
+ IMPORT nice_match
+ DCD nice_match
+|__match_start|
+ IMPORT match_start
+ DCD match_start
+
+ DCB "longest_match"
+ DCB &00,&00,&00
+ DCD &ff000010
+
+ EXPORT longest_match
+longest_match
+ STMFD sp!, {r4-r9,fp,lr}
+
+ LDR fp, [pc, #|__prev|-.-8]
+
+ LDR r1, [pc, #|__max_chain_length|-.-8]
+ LDR r1, [r1]
+ LDR lr, [pc, #|__window|-.-8]
+
+ LDR ip, [pc, #|__strstart|-.-8]
+ LDR ip, [ip]
+ ADD r2, lr, ip
+ LDR r5, [pc, #|__prev_length|-.-8]
+ LDR r5, [r5]
+ SUBS ip, ip, #MAX_DIST-250 ; if r6 > MAX_DIST
+ SUBCSS r6, ip, #250 ; r6 = r6 - MAXDIST
+ MOVLS r6, #0 ; else r6 = 0
+
+ ADD r7, r2, #MAX_MATCH-256
+ ADD r7, r7, #256 ; r7 = r2 + MAX_MATCH (=258);
+
+ SUB ip, r5, #1
+ LDRB r8, [r2, ip]
+ LDRB r9, [r2, r5]
+
+ LDR ip, [pc, #|__good_match|-.-8]
+ LDR ip, [ip]
+ CMP r5, ip
+ MOVCS r1, r1, LSR #2
+
+cycle
+ ADD r3, lr, r0
+
+ LDRB ip, [r3, r5]
+ CMP ip, r9
+ BNE cycle_end
+
+ SUB ip, r5, #1
+ LDRB ip, [r3, ip]
+ CMP ip, r8
+ BNE cycle_end
+
+ LDRB ip, [r2]
+ LDRB r4, [r3]
+ CMP ip, r4
+ BNE cycle_end
+
+ LDRB ip, [r3, #1]
+ LDRB r4, [r2, #1]
+ CMP ip, r4
+ BNE cycle_end
+
+ ADD r2, r2, #2
+ ADD r3, r3, #2
+
+inn_cycle
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ LDRB ip, [r2, #1]!
+ LDRB r4, [r3, #1]!
+ CMP ip, r4
+ BNE exit_inn_cycle
+
+ CMP r2, r7
+ BCC inn_cycle
+
+exit_inn_cycle
+ SUB r4, r2, r7 ; len = MAX_MATCH - (int)(strend - scan);
+ ADD r4, r4, #MAX_MATCH-256
+ ADD r4, r4, #256
+
+ SUB r2, r2, r4 ; scan = strend - MAX_MATCH
+
+ CMP r4, r5 ; if (len > best_len) {
+ BLE cycle_end
+
+ LDR ip, [pc, #|__match_start|-.-8] ; match_start = cur_match;
+ STR r0, [ip]
+ MOV r5, r4 ; best_len = len;
+
+ LDR ip, [pc, #|__nice_match|-.-8] ; if (len >= nice_match)
+ LDR ip, [ip]
+ CMP r4, ip
+ BGE exit_match ; break;
+
+ SUB ip, r5, #1 ; scan_end1 = scan[best_len-1];
+ LDRB r8, [r2, ip]
+ LDRB r9, [r2, r5] ; scan_end = scan[best_len];
+
+cycle_end
+ MOV ip, r0, LSL #17 ; cur_match & WMASK
+ MOV ip, ip, LSR #17
+
+ LDR r0, [fp, ip, ASL #1] ; cur_match = prev[cur_match & WMASK]
+ MOV r0, r0, ASL #16
+ MOV r0, r0, LSR #16
+
+ CMP r0, r6 ; cur_match > limit
+ BLS exit_match
+ SUBS r1, r1, #1 ; --chain_length
+ BNE cycle ; chain_length != 0
+
+exit_match
+ MOV r0, r5
+
+ LDMFD sp!, {r4-r9,fp,pc}^
+
+ END
diff --git a/acorn/osdep.h b/acorn/osdep.h
new file mode 100644
index 0000000..9f7783e
--- /dev/null
+++ b/acorn/osdep.h
@@ -0,0 +1,28 @@
+/*
+ Copyright (c) 1990-2007 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2007-Mar-4 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+#include "riscos.h"
+
+#define RISCOS
+#define NO_SYMLINKS
+#define NO_FCNTL_H
+#define NO_UNISTD_H
+#define NO_MKTEMP
+
+#define PROCNAME(n) (action == ADD || action == UPDATE ? wild(n) : \
+ procname(n, 1))
+
+#define isatty(a) 1
+#define fseek(f,o,t) riscos_fseek((f),(o),(t))
+
+#define localtime riscos_localtime
+#define gmtime riscos_gmtime
+
+#ifdef ZCRYPT_INTERNAL
+# define ZCR_SEED2 (unsigned)3141592654L /* use PI as seed pattern */
+#endif
diff --git a/acorn/riscos.c b/acorn/riscos.c
new file mode 100644
index 0000000..84dd2d3
--- /dev/null
+++ b/acorn/riscos.c
@@ -0,0 +1,394 @@
+/*
+ Copyright (c) 1990-2002 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2000-Apr-09 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* riscos.c */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zip.h"
+#include "riscos.h"
+
+#define MAXEXT 256
+
+/* External globals */
+extern int scanimage;
+
+/* Local globals (!?!?) */
+char *exts2swap = NULL; /* Extensions to swap (actually, directory names) */
+
+int stat(char *filename,struct stat *res)
+{
+ int attr; /* object attributes */
+ unsigned int load; /* load address */
+ unsigned int exec; /* exec address */
+ int type; /* type: 0 not found, 1 file, 2 dir, 3 image */
+
+ if (!res)
+ return -1;
+
+ if (SWI_OS_File_5(filename,&type,&load,&exec,(int *)&res->st_size,&attr)!=NULL)
+ return -1;
+
+ if (type==0)
+ return -1;
+
+ res->st_dev=0;
+ res->st_ino=0;
+ res->st_nlink=0;
+ res->st_uid=1;
+ res->st_gid=1;
+ res->st_rdev=0;
+ res->st_blksize=1024;
+
+ res->st_mode = ((attr & 0001) << 8) | ((attr & 0002) << 6) |
+ ((attr & 0020) >> 2) | ((attr & 0040) >> 4);
+
+ switch (type) {
+ case 1: /* File */
+ res->st_mode |= S_IFREG;
+ break;
+ case 2: /* Directory */
+ res->st_mode |= S_IFDIR | 0700;
+ break;
+ case 3: /* Image file */
+ if (scanimage)
+ res->st_mode |= S_IFDIR | 0700;
+ else
+ res->st_mode |= S_IFREG;
+ break;
+ }
+
+ if ((((unsigned int) load) >> 20) == 0xfff) { /* date stamped file */
+ unsigned int t1, t2, tc;
+
+ t1 = (unsigned int) (exec);
+ t2 = (unsigned int) (load & 0xff);
+
+ tc = 0x6e996a00U;
+ if (t1 < tc)
+ t2--;
+ t1 -= tc;
+ t2 -= 0x33; /* 00:00:00 Jan. 1 1970 = 0x336e996a00 */
+
+ t1 = (t1 / 100) + (t2 * 42949673U); /* 0x100000000 / 100 = 42949672.96 */
+ t1 -= (t2 / 25); /* compensate for .04 error */
+
+ res->st_atime = res->st_mtime = res->st_ctime = t1;
+ }
+ else
+ res->st_atime = res->st_mtime = res->st_ctime = 0;
+
+ return 0;
+}
+
+#ifndef SFX
+
+DIR *opendir(char *dirname)
+{
+ DIR *thisdir;
+ int type;
+ int attr;
+ os_error *er;
+
+ thisdir=(DIR *)malloc(sizeof(DIR));
+ if (thisdir==NULL)
+ return NULL;
+
+ thisdir->dirname=(char *)malloc(strlen(dirname)+1);
+ if (thisdir->dirname==NULL) {
+ free(thisdir);
+ return NULL;
+ }
+
+ strcpy(thisdir->dirname,dirname);
+ if (thisdir->dirname[strlen(thisdir->dirname)-1]=='.')
+ thisdir->dirname[strlen(thisdir->dirname)-1]=0;
+
+ if (er=SWI_OS_File_5(thisdir->dirname,&type,NULL,NULL,NULL,&attr),er!=NULL ||
+ type<=1 || (type==3 && !scanimage))
+ {
+ free(thisdir->dirname);
+ free(thisdir);
+ return NULL;
+ }
+
+ thisdir->buf=malloc(DIR_BUFSIZE);
+ if (thisdir->buf==NULL) {
+ free(thisdir->dirname);
+ free(thisdir);
+ return NULL;
+ }
+
+ thisdir->size=DIR_BUFSIZE;
+ thisdir->offset=0;
+ thisdir->read=0;
+
+ return thisdir;
+}
+
+struct dirent *readdir(DIR *d)
+{
+ static struct dirent dent;
+
+ if (d->read==0) { /* no more objects read in the buffer */
+ if (d->offset==-1) { /* no more objects to read */
+ return NULL;
+ }
+
+ d->read=255;
+ if (SWI_OS_GBPB_9(d->dirname,d->buf,&d->read,&d->offset,DIR_BUFSIZE,NULL)!=NULL)
+ return NULL;
+
+ if (d->read==0) {
+ d->offset=-1;
+ return NULL;
+ }
+ d->read--;
+ d->act=(char *)d->buf;
+ }
+ else { /* some object is ready in buffer */
+ d->read--;
+ d->act=(char *)(d->act+strlen(d->act)+1);
+ }
+
+ strcpy(dent.d_name,d->act);
+ dent.d_namlen=strlen(dent.d_name);
+
+ return &dent;
+}
+
+void closedir(DIR *d)
+{
+ if (d->buf!=NULL)
+ free(d->buf);
+ if (d->dirname!=NULL)
+ free(d->dirname);
+ free(d);
+}
+
+int unlink(f)
+char *f; /* file to delete */
+/* Delete the file *f, returning non-zero on failure. */
+{
+ os_error *er;
+ char canon[256];
+ int size=255;
+
+ er=SWI_OS_FSControl_37(f,canon,&size);
+ if (er==NULL) {
+ er=SWI_OS_FSControl_27(canon,0x100);
+ }
+ else {
+ er=SWI_OS_FSControl_27(f,0x100);
+ }
+ return (int)er;
+}
+
+int deletedir(char *d)
+{
+ int objtype;
+ char *s;
+ int len;
+ os_error *er;
+
+ len = strlen(d);
+ if ((s = malloc(len + 1)) == NULL)
+ return -1;
+
+ strcpy(s,d);
+ if (s[len-1]=='.')
+ s[len-1]=0;
+
+ if (er=SWI_OS_File_5(s,&objtype,NULL,NULL,NULL,NULL),er!=NULL) {
+ free(s);
+ return -1;
+ }
+ if (objtype<2 || (!scanimage && objtype==3)) {
+ /* this is a file or it doesn't exist */
+ free(s);
+ return -1;
+ }
+
+ if (er=SWI_OS_File_6(s),er!=NULL) {
+ /* maybe this is a problem with the DDEUtils module, try to canonicalise the path */
+ char canon[256];
+ int size=255;
+
+ if (er=SWI_OS_FSControl_37(s,canon,&size),er!=NULL) {
+ free(s);
+ return -1;
+ }
+ if (er=SWI_OS_File_6(canon),er!=NULL) {
+ free(s);
+ return -1;
+ }
+ }
+ free(s);
+ return 0;
+}
+
+#endif /* !SFX */
+
+int chmod(char *file, int mode)
+{
+/*************** NOT YET IMPLEMENTED!!!!!! ******************/
+/* I don't know if this will be needed or not... */
+ file=file;
+ mode=mode;
+ return 0;
+}
+
+void setfiletype(char *fname,int ftype)
+{
+ char str[256];
+ sprintf(str,"SetType %s &%3.3X",fname,ftype);
+ SWI_OS_CLI(str);
+}
+
+void getRISCOSexts(char *envstr)
+{
+ char *envptr; /* value returned by getenv */
+
+ envptr = getenv(envstr);
+ if (envptr == NULL || *envptr == 0) return;
+
+ exts2swap=malloc(1+strlen(envptr));
+ if (exts2swap == NULL)
+ return;
+
+ strcpy(exts2swap, envptr);
+}
+
+int checkext(char *suff)
+{
+ register char *extptr=exts2swap;
+ register char *suffptr;
+ register int e,s;
+
+ if (extptr != NULL) while(*extptr) {
+ suffptr=suff;
+ e=*extptr; s=*suffptr;
+ while (e && e!=':' && s && s!='.' && s!='/' && e==s) {
+ e=*++extptr; s=*++suffptr;
+ }
+ if (e==':') e=0;
+ if (s=='.' || s=='/') s=0;
+ if (!e && !s) {
+ return 1;
+ }
+ while(*extptr!=':' && *extptr!='\0') /* skip to next extension */
+ extptr++;
+ if (*extptr!='\0')
+ extptr++;
+ }
+ return 0;
+}
+
+int swapext(char *name, char *exptr)
+{
+ char *ext;
+ char *p1=exptr;
+ char *p2;
+ int extchar=*exptr;
+ unsigned int i=0;
+
+ while(*++p1 && *p1!='.' && *p1!='/')
+ ;
+ ext=malloc(i=p1-exptr);
+ if (!ext)
+ return 1;
+ memcpy(ext, exptr+1, i);
+ p2=exptr-1;
+ p1=exptr+i-1;
+ while(p2 >= name)
+ *p1--=*p2--;
+ strcpy(name,ext);
+ *p1=(extchar=='/'?'.':'/');
+ free(ext);
+ return 0;
+}
+
+void remove_prefix(void)
+{
+ SWI_DDEUtils_Prefix(NULL);
+}
+
+void set_prefix(void)
+{
+ char *pref;
+ int size=0;
+
+ if (SWI_OS_FSControl_37("@",pref,&size)!=NULL)
+ return;
+
+ size=1-size;
+
+ if (pref=malloc(size),pref!=NULL) {
+ if (SWI_OS_FSControl_37("@",pref,&size)!=NULL) {
+ free(pref);
+ return;
+ }
+
+ if (SWI_DDEUtils_Prefix(pref)==NULL) {
+ atexit(remove_prefix);
+ }
+
+ free(pref);
+ }
+}
+
+#ifdef localtime
+# undef localtime
+#endif
+
+#ifdef gmtime
+# undef gmtime
+#endif
+
+/* Acorn's implementation of localtime() and gmtime()
+ * doesn't consider the timezone offset, so we have to
+ * add it before calling the library functions
+ */
+
+struct tm *riscos_localtime(const time_t *timer)
+{
+ time_t localt=*timer;
+
+ localt+=SWI_Read_Timezone()/100;
+
+ return localtime(&localt);
+}
+
+struct tm *riscos_gmtime(const time_t *timer)
+{
+ time_t localt=*timer;
+
+ localt+=SWI_Read_Timezone()/100;
+
+ return gmtime(&localt);
+}
+
+
+int riscos_fseek(FILE *fd, long offset, int whence)
+{
+ int ret;
+ switch (whence)
+ {
+ case SEEK_END:
+ ret = (fseek) (fd, 0, SEEK_END);
+ if (ret)
+ return ret;
+ /* fall through */
+ case SEEK_CUR:
+ offset += ftell (fd);
+ /* fall through */
+ default: /* SEEK_SET */
+ return (fseek) (fd, offset < 0 ? 0 : offset, SEEK_SET);
+ }
+}
diff --git a/acorn/riscos.h b/acorn/riscos.h
new file mode 100644
index 0000000..c45a148
--- /dev/null
+++ b/acorn/riscos.h
@@ -0,0 +1,119 @@
+/*
+ Copyright (c) 1990-2002 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2000-Apr-09 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* riscos.h */
+
+#ifndef __riscos_h
+#define __riscos_h
+
+#include <time.h>
+#include <stdio.h>
+
+typedef struct {
+ int errnum;
+ char errmess[252];
+} os_error;
+
+#ifndef __swiven_h
+# include "swiven.h"
+#endif
+
+#define MAXPATHLEN 256
+#define MAXFILENAMELEN 64 /* should be 11 for ADFS, 13 for DOS, 64 seems a sensible value... */
+#define DIR_BUFSIZE 1024 /* this should be enough to read a whole E-Format directory */
+
+struct stat {
+ unsigned int st_dev;
+ int st_ino;
+ unsigned int st_mode;
+ int st_nlink;
+ unsigned short st_uid;
+ unsigned short st_gid;
+ unsigned int st_rdev;
+ unsigned int st_size;
+ unsigned int st_blksize;
+ time_t st_atime;
+ time_t st_mtime;
+ time_t st_ctime;
+};
+
+typedef struct {
+ char *dirname;
+ void *buf;
+ int size;
+ char *act;
+ int offset;
+ int read;
+} DIR;
+
+#define dstrm DIR
+
+struct dirent {
+ unsigned int d_off; /* offset of next disk directory entry */
+ int d_fileno; /* file number of entry */
+ size_t d_reclen; /* length of this record */
+ size_t d_namlen; /* length of d_name */
+ char d_name[MAXFILENAMELEN]; /* name */
+};
+
+typedef struct {
+ unsigned int load_addr;
+ unsigned int exec_addr;
+ int lenght;
+ int attrib;
+ int objtype;
+ char name[13];
+} riscos_direntry;
+
+#define SPARKID 0x4341 /* = "AC" */
+#define SPARKID_2 0x30435241 /* = "ARC0" */
+
+typedef struct {
+ short ID;
+ short size;
+ int ID_2;
+ unsigned int loadaddr;
+ unsigned int execaddr;
+ int attr;
+ int zero;
+} extra_block;
+
+
+#define S_IFMT 0770000
+
+#define S_IFDIR 0040000
+#define S_IFREG 0100000 /* 0200000 in UnixLib !?!?!?!? */
+
+#ifndef S_IEXEC
+# define S_IEXEC 0000100
+# define S_IWRITE 0000200
+# define S_IREAD 0000400
+#endif
+
+extern char *exts2swap; /* Extensions to swap */
+
+int stat(char *filename,struct stat *res);
+DIR *opendir(char *dirname);
+struct dirent *readdir(DIR *d);
+char *readd(DIR *d);
+void closedir(DIR *d);
+int unlink(char *f);
+int chmod(char *file, int mode);
+void setfiletype(char *fname,int ftype);
+void getRISCOSexts(char *envstr);
+int checkext(char *suff);
+int swapext(char *name, char *exptr);
+void remove_prefix(void);
+void set_prefix(void);
+struct tm *riscos_localtime(const time_t *timer);
+struct tm *riscos_gmtime(const time_t *timer);
+
+int riscos_fseek(FILE *fd, long offset, int whence);
+/* work around broken assumption that fseek() is OK with -ve file offsets */
+
+#endif /* !__riscos_h */
diff --git a/acorn/sendbits.s b/acorn/sendbits.s
new file mode 100644
index 0000000..f12921a
--- /dev/null
+++ b/acorn/sendbits.s
@@ -0,0 +1,105 @@
+;===========================================================================
+; 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
+;===========================================================================
+; sendbits.s for ARM by Sergio Monesi and Darren Salt.
+
+r0 RN 0
+r1 RN 1
+r2 RN 2
+r3 RN 3
+r4 RN 4
+r5 RN 5
+r6 RN 6
+r7 RN 7
+r8 RN 8
+r9 RN 9
+sl RN 10
+fp RN 11
+ip RN 12
+sp RN 13
+lr RN 14
+pc RN 15
+
+ AREA |Asm$$Code|, CODE, READONLY
+
+ = "send_bits",0
+ ALIGN
+ & &FF00000C
+
+ IMPORT __rt_stkovf_split_small
+ IMPORT flush_outbuf
+
+ IMPORT bi_valid
+ IMPORT bi_buf
+ IMPORT out_size
+ IMPORT out_offset
+ IMPORT out_buf
+
+ EXPORT send_bits
+send_bits
+ MOV ip,sp
+ STMDB sp!,{r4,r5,fp,ip,lr,pc}
+ SUB fp,ip,#4
+ LDR r5,=bi_buf
+ LDR r3,=bi_valid
+ LDR r4,[r5]
+ LDR r2,[r3]
+ ORR r4,r4,r0,LSL r2 ; |= value<<bi_valid
+ ADD r2,r2,r1 ; += length
+ CMP r2,#&10
+ STRLE r2,[r3] ; short? store & return
+ STRLE r4,[r5]
+ LDMLEDB fp,{r4,r5,fp,sp,pc}^
+
+ SUB r2,r2,#&10 ; adjust bi_valid, bi_buf
+ MOV ip,r4,LSR #16 ; (done early, keeping the old bi_buf
+ STR r2,[r3] ; in R4 for later storage)
+ STR ip,[r5]
+
+ LDR r0,=out_size
+ LDR r1,=out_offset
+ LDR r0,[r0]
+ LDR r2,[r1]
+ SUB r0,r0,#1
+ CMP r2,r0 ; if out_offset >= out_size-1
+ LDRHS r0,=out_buf
+ LDRHS r0,[r0]
+ BLHS flush_outbuf ; then flush the buffer
+ LDR r0,=out_buf
+ LDR r1,=out_offset
+ LDR r0,[r0]
+ LDR r2,[r1]
+ MOV r5,r4,LSR #8
+ STRB r4,[r0,r2]! ; store 'old' bi_buf
+ STRB r5,[r0,#1]
+ ADD r2,r2,#2
+ STR r2,[r1]
+
+ LDMDB fp,{r4,r5,fp,sp,pc}^
+
+
+ptr_bi & bi_valid
+ & bi_buf
+
+
+ = "bi_reverse",0
+ ALIGN
+ & &FF00000C
+
+ EXPORT bi_reverse
+bi_reverse
+ MOV r2,#0
+loop MOVS r0,r0,LSR #1
+ ADCS r2,r2,r2
+ SUBS r1,r1,#1
+ BNE loop
+ MOV r0,r2
+ MOVS pc,lr
+
+
+ END
diff --git a/acorn/srcrename b/acorn/srcrename
new file mode 100644
index 0000000..7bd6119
--- /dev/null
+++ b/acorn/srcrename
Binary files differ
diff --git a/acorn/swiven.h b/acorn/swiven.h
new file mode 100644
index 0000000..c860d7d
--- /dev/null
+++ b/acorn/swiven.h
@@ -0,0 +1,59 @@
+/*
+ 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
+*/
+/* swiven.h */
+
+#ifndef __swiven_h
+#define __swiven_h
+
+os_error *SWI_OS_FSControl_26(char *source, char *dest, int actionmask);
+/* copy */
+
+os_error *SWI_OS_FSControl_27(char *filename, int actionmask);
+/* wipe */
+
+os_error *SWI_OS_GBPB_9(char *dirname, void *buf, int *number,
+ int *offset, int size, char *match);
+/* read dir */
+
+os_error *SWI_OS_File_1(char *filename, unsigned int loadaddr,
+ unsigned int execaddr, int attrib);
+/* write file attributes */
+
+os_error *SWI_OS_File_5(char *filename, int *objtype, unsigned int *loadaddr,
+ unsigned int *execaddr, int *length, int *attrib);
+/* read file info */
+
+os_error *SWI_OS_File_6(char *filename);
+/* delete */
+
+os_error *SWI_OS_File_7(char *filename, int loadaddr, int execaddr, int size);
+/* create an empty file */
+
+os_error *SWI_OS_CLI(char *cmd);
+/* execute a command */
+
+int SWI_OS_ReadC(void);
+/* get a key from the keyboard buffer */
+
+os_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused);
+/* reads an OS varibale */
+
+os_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size);
+/* reads the path of a specified directory */
+
+os_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size);
+/* canonicalise path */
+
+os_error *SWI_DDEUtils_Prefix(char *dir);
+/* sets the 'prefix' directory */
+
+int SWI_Read_Timezone(void);
+/* returns the timezone offset (centiseconds) */
+
+#endif /* !__swiven_h */
diff --git a/acorn/swiven.s b/acorn/swiven.s
new file mode 100644
index 0000000..1630124
--- /dev/null
+++ b/acorn/swiven.s
@@ -0,0 +1,276 @@
+;===========================================================================
+; 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
+;===========================================================================
+; SWI veneers used by Zip/Unzip
+;
+
+r0 RN 0
+r1 RN 1
+r2 RN 2
+r3 RN 3
+r4 RN 4
+r5 RN 5
+r6 RN 6
+r7 RN 7
+r8 RN 8
+r9 RN 9
+r10 RN 10
+r11 RN 11
+r12 RN 12
+sp RN 13
+lr RN 14
+pc RN 15
+
+sl RN 10
+fp RN 11
+ip RN 12
+
+
+XOS_Bit EQU &020000
+
+OS_GBPB EQU &00000C
+OS_File EQU &000008
+OS_FSControl EQU &000029
+OS_CLI EQU &000005
+OS_ReadC EQU &000004
+OS_ReadVarVal EQU &000023
+DDEUtils_Prefix EQU &042580
+Territory_ReadCurrentTimeZone EQU &043048
+
+ MACRO
+ STARTCODE $name
+ EXPORT $name
+$name
+ MEND
+
+
+ AREA |C$$code|, CODE, READONLY
+
+; os_error *SWI_OS_FSControl_26(char *source, char *dest, int actionmask);
+
+ STARTCODE SWI_OS_FSControl_26
+
+ MOV ip, lr
+
+ MOV r3, r2
+ MOV r2, r1
+ MOV r1, r0
+ MOV r0, #26
+
+ SWI OS_FSControl + XOS_Bit
+
+ MOVVC r0, #0
+
+ MOVS pc, ip
+
+
+; os_error *SWI_OS_FSControl_27(char *filename, int actionmask);
+
+ STARTCODE SWI_OS_FSControl_27
+
+ MOV ip, lr
+
+ MOV r3, r1
+ MOV r1, r0
+ MOV r0, #27
+
+ SWI OS_FSControl + XOS_Bit
+
+ MOVVC r0, #0
+
+ MOVS pc, ip
+
+
+; os_error *SWI_OS_GBPB_9(char *dirname, void *buf, int *number,
+; int *offset, int size, char *match);
+
+ STARTCODE SWI_OS_GBPB_9
+
+ MOV ip, sp
+ STMFD sp!, {r2-r6,lr}
+ LDMIA ip, {r5,r6}
+ LDR r4, [r3]
+ LDR r3, [r2]
+ MOV r2, r1
+ MOV r1, r0
+ MOV r0, #9
+ SWI OS_GBPB + XOS_Bit
+ LDMVSFD sp!, {r2-r6,pc}^
+ MOV r0, #0
+ LDMFD sp, {r5,r6}
+ STR r3, [r5]
+ STR r4, [r6]
+ LDMFD sp!, {r2-r6,pc}^
+
+
+; os_error *SWI_OS_File_1(char *filename, int loadaddr, int execaddr, int attrib);
+
+ STARTCODE SWI_OS_File_1
+
+ STMFD sp!, {r5,lr}
+ MOV r5, r3
+ MOV r3, r2
+ MOV r2, r1
+ MOV r1, r0
+ MOV r0, #1
+ SWI OS_File + XOS_Bit
+ MOVVC r0, #0
+ LDMFD sp!, {r5,pc}^
+
+
+
+; os_error *SWI_OS_File_5(char *filename, int *objtype, int *loadaddr,
+; int *execaddr, int *length, int *attrib);
+
+ STARTCODE SWI_OS_File_5
+
+ STMFD sp!, {r1-r5,lr}
+ MOV r1, r0
+ MOV r0, #5
+ SWI OS_File + XOS_Bit
+ LDMVSFD sp!, {r1-r5,pc}^
+ LDR lr, [sp]
+ TEQ lr, #0
+ STRNE r0, [lr]
+ LDR lr, [sp, #4]
+ TEQ lr ,#0
+ STRNE r2, [lr]
+ LDR lr, [sp, #8]
+ TEQ lr, #0
+ STRNE r3, [lr]
+ LDR lr, [sp ,#24]
+ TEQ lr, #0
+ STRNE r4, [lr]
+ LDR lr, [sp ,#28]
+ TEQ lr, #0
+ STRNE r5, [lr]
+ MOV r0, #0
+ LDMFD sp!, {r1-r5,pc}^
+
+
+; os_error *SWI_OS_File_6(char *filename);
+
+ STARTCODE SWI_OS_File_6
+
+ STMFD sp!, {r4-r5,lr}
+ MOV r1, r0
+ MOV r0, #6
+ SWI OS_File + XOS_Bit
+ MOVVC r0, #0
+ LDMFD sp!, {r4-r5,pc}^
+
+
+; os_error *SWI_OS_File_7(char *filename, int loadaddr, int execaddr, int size);
+
+ STARTCODE SWI_OS_File_7
+
+ STMFD sp!, {r4-r5,lr}
+ MOV r5, r3
+ MOV r4, #0
+ MOV r3, r2
+ MOV r2, r1
+ MOV r1, r0
+ MOV r0, #7
+ SWI OS_File + XOS_Bit
+ MOVVC r0, #0
+ LDMFD sp!, {r4-r5,pc}^
+
+
+; os_error *SWI_OS_CLI(char *cmd);
+
+ STARTCODE SWI_OS_CLI
+
+ MOV ip, lr
+ SWI OS_CLI + XOS_Bit
+ MOVVC r0, #0
+ MOVS pc, ip
+
+
+; int SWI_OS_ReadC(void);
+
+ STARTCODE SWI_OS_ReadC
+
+ MOV ip, lr
+ SWI OS_ReadC + XOS_Bit
+ MOVS pc, ip
+
+
+; os_error *SWI_OS_ReadVarVal(char *var, char *buf, int len, int *bytesused);
+
+ STARTCODE SWI_OS_ReadVarVal
+
+ STMFD sp!, {r4,lr}
+ MOV ip, r3
+ MOV r3, #0
+ MOV r4, #0
+ SWI OS_ReadVarVal + XOS_Bit
+ LDMVSFD sp!, {r4,pc}^
+ TEQ ip, #0
+ STRNE r2, [ip]
+ MOV r0, #0
+ LDMFD sp!, {r4,pc}^
+
+
+; os_error *SWI_OS_FSControl_54(char *buffer, int dir, char *fsname, int *size);
+
+ STARTCODE SWI_OS_FSControl_54
+
+ STMFD sp!, {r3-r6,lr}
+ LDR r5, [r3]
+ MOV r3, r2
+ MOV r2, r1
+ MOV r1, r0
+ MOV r0, #54
+ SWI OS_FSControl + XOS_Bit
+ LDMVSFD sp!, {r3-r6,pc}^
+ MOV r0, #0
+ LDMFD sp!, {r3}
+ STR r5, [r3]
+ LDMFD sp!, {r4-r6,pc}^
+
+
+; os_error *SWI_OS_FSControl_37(char *pathname, char *buffer, int *size);
+
+ STARTCODE SWI_OS_FSControl_37
+
+ STMFD sp!, {r2,r3-r5,lr}
+ LDR r5, [r2]
+ MOV r3, #0
+ MOV r4, #0
+ MOV r2, r1
+ MOV r1, r0
+ MOV r0, #37
+ SWI OS_FSControl + XOS_Bit
+ LDMVSFD sp!, {r2,r3-r5,pc}^
+ MOV r0, #0
+ LDMFD sp!, {r2}
+ STR r5, [r2]
+ LDMFD sp!, {r3-r5,pc}^
+
+
+; os_error *SWI_DDEUtils_Prefix(char *dir);
+
+ STARTCODE SWI_DDEUtils_Prefix
+
+ MOV ip, lr
+ SWI DDEUtils_Prefix + XOS_Bit
+ MOVVC r0, #0
+ MOVS pc, ip
+
+; int SWI_Read_Timezone(void);
+
+ STARTCODE SWI_Read_Timezone
+
+ MOV ip, lr
+ SWI Territory_ReadCurrentTimeZone + XOS_Bit
+ MOVVC r0, r1
+ MOVVS r0, #0
+ MOVS pc, ip
+
+
+ END
diff --git a/acorn/zipsfx b/acorn/zipsfx
new file mode 100644
index 0000000..7d63492
--- /dev/null
+++ b/acorn/zipsfx
@@ -0,0 +1,9 @@
+| zipsfx 0.1
+| Written by Darren Salt
+| Assumes that unzipsfx is on Run$Path (eg. in !Boot.Library)
+| Assumes that IfThere is available as either *command or utility
+
+If "%1" = "" Then Error 220 Syntax: zipsfx |<archive> |<SEA>
+If "%0" = "" Then Error 220 Syntax: zipsfx |<archive> |<SEA>
+Copy Run:unzipsfx %1 A~C~D~F~L~N~R~S~T~V
+Print %0 { >> %1 } \ No newline at end of file
diff --git a/acorn/zipup.h b/acorn/zipup.h
new file mode 100644
index 0000000..47c3536
--- /dev/null
+++ b/acorn/zipup.h
@@ -0,0 +1,16 @@
+/*
+ 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
+*/
+#define fhow "r"
+#define fbad (NULL)
+typedef FILE *ftype;
+#define zopen(n,p) fopen(n,p)
+#define zread(f,b,n) fread((b),1,(n),(FILE*)(f))
+#define zclose(f) fclose(f)
+#define zerr(f) (k==(extent)(-1L))
+#define zstdin 0