Commit ac2b7142 authored by Jeffrey Lee's avatar Jeffrey Lee

Implement task association. Add proper error messages. Other tweaks.

Detail:
  Resources/UK/Messages - Messages file for error messages
  c/errors, h/errors - Error lookup/conversion code
  c/task, h/task - Task association code
  Makefile - Updated for new source files, messages file, and C version of assembler header
  c/cmodule, h/globals - Updated to generate proper errors and add task association support. Fixed SWI handler to work. Tweak implementation of Compress/Decompress SWIs.
  cmhg/modhead - Use exported value of SWI chunk instead of hardcoded value. Add service call veneer for Service_WimpCloseDown.
  hdr/ZLib - Export list of errors. Use exported value of SWI chunk instead of hardcoded value.
Admin:
  Tested in softload form
  Compress/Decompress SWIs, gzip SWIs, and task association all seem to work. Other SWIs untested.


Version 0.02. Tagged as 'ZLib-0_02'
parent 9e67a19e
......@@ -38,10 +38,11 @@ LIBS = ${DEBUGLIBS} ${NET5LIBS}
endif
COMPONENT = ZLib
OBJS = cmodule
OBJS = cmodule errors task
CMHGFILE = modhead
HDRS =
ASMHDRS = ZLib
ASMCHDRS = ZLib
LIBS += C:zlib.o.zlibzm
CINCLUDES = -Itbox:
......@@ -50,8 +51,6 @@ CMHGDEFINES = -DCOMPONENT=${COMPONENT}
CMHGDEPENDS = cmodule
RAMCDEFINES = -DSTANDALONE
RES_OBJ = # fudge
include CModule
# Dynamic dependencies:
#{DictTokens}
NoMem:Insufficient memory for ZLib operation
InvCFlg:Invalid ZLib_Compress flag
InvDFlg:Invalid ZLib_Decompress flag
ZLibErr:ZLib error %0
ZLibEr2:ZLib error %0: %1
UKSWI:Unknown ZLib SWI
InvTA:Invalid ZLib_TaskAssociate operation
InvGZSk:Invalid ZLib_GZSeek parameter
/* (0.01)
/* (0.02)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.01
#define Module_MajorVersion_CMHG 0.02
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 04 Feb 2012
#define Module_Date_CMHG 30 Mar 2012
#define Module_MajorVersion "0.01"
#define Module_Version 1
#define Module_MajorVersion "0.02"
#define Module_Version 2
#define Module_MinorVersion ""
#define Module_Date "04 Feb 2012"
#define Module_Date "30 Mar 2012"
#define Module_ApplicationDate "04-Feb-12"
#define Module_ApplicationDate "30-Mar-12"
#define Module_ComponentName "ZLib"
#define Module_ComponentPath "bsd/RiscOS/Sources/Programmer/ZLib"
#define Module_FullVersion "0.01"
#define Module_HelpVersion "0.01 (04 Feb 2012)"
#define Module_LibraryVersionInfo "0:1"
#define Module_FullVersion "0.02"
#define Module_HelpVersion "0.02 (30 Mar 2012)"
#define Module_LibraryVersionInfo "0:2"
......@@ -39,16 +39,23 @@
#include "DebugLib/DebugLib.h"
#include "globals.h"
#include "errors.h"
#include "task.h"
void *private_word;
#define ERROR(X) (_kernel_oserror *) ("\0\0\0\0" X)
MessagesFD messages;
#ifdef STANDALONE
extern void* Resources(void);
#endif
_kernel_oserror* module_init (const char *cmd_tail, int podule_base, void *pw)
{
(void) cmd_tail;
(void) podule_base;
(void) pw;
_kernel_oserror *e;
/* set up debugging */
debug_initialise(Module_Title, "", "");
......@@ -57,6 +64,22 @@ _kernel_oserror* module_init (const char *cmd_tail, int podule_base, void *pw)
private_word = pw;
/* Set up messages */
#ifdef STANDALONE
e = _swix(ResourceFS_RegisterFiles,_IN(0),Resources());
if(e)
return e;
#endif
e = _swix(MessageTrans_OpenFile,_INR(0,2),&messages,"Resources:$.Resources.ZLib.Messages",0);
if(e)
{
#ifdef STANDALONE
_swix(ResourceFS_DeregisterFiles,_IN(0),Resources());
#endif
return e;
}
return NULL;
}
......@@ -66,7 +89,16 @@ _kernel_oserror *module_final(int fatal, int podule, void *pw)
(void) podule;
(void) pw;
/* TODO - Complain if stuff still active? */
/* TODO - Free all memory
Tricky since many streams will be in application space
So maybe just refuse to exit if (task-associated) streams are active? */
/* Close messages */
_swix(MessageTrans_CloseFile,_IN(0),&messages);
#ifdef STANDALONE
_swix(ResourceFS_DeregisterFiles,_IN(0),Resources());
#endif
return NULL;
}
......@@ -118,16 +150,18 @@ static _kernel_oserror *do_gzopen(_kernel_swi_regs *r)
{
/* Oh, crumbs */
gzclose(file);
e = ERROR("Out of memory!");
e = ERROR(NoMem);
return e;
}
header.extra = extra;
header.extra_max = 1024;
if(gzgetheader(file, &header) < 0)
{
int err;
const char *msg = gzerror(file, &err);
e = getzliberror(err,msg);
gzclose(file);
free(extra);
e = ERROR("Failed reading header");
return e;
}
/* Scan for 'AC' subfield */
......@@ -175,8 +209,10 @@ static _kernel_oserror *do_gzopen(_kernel_swi_regs *r)
header.os = 0xd;
if(gzputheader(file, &header) < 0)
{
int err;
const char *msg = gzerror(file, &err);
e = getzliberror(err,msg);
gzclose(file);
e = ERROR("Failed writing header");
return e;
}
}
......@@ -190,13 +226,14 @@ _kernel_oserror *module_swis(int swi_offset, _kernel_swi_regs *r, void *pw)
int flags;
int ret;
z_streamp stream;
_kernel_oserror *e;
switch(swi_offset)
{
case ZLib_Compress:
case ZLib_Compress-ZLib_00:
flags = r->r[0];
if(flags & ~COMPRESS_VALID_FLAGS)
return ERROR("Invalid ZLib_Compress flag");
return ERROR(InvalidCompressFlag);
if(flags & COMPRESS_FLAG_RETURNWORKSPACE)
{
r->r[0] = sizeof(z_stream);
......@@ -215,15 +252,18 @@ _kernel_oserror *module_swis(int swi_offset, _kernel_swi_regs *r, void *pw)
ret = deflateInit(stream,9); /* Assume best compression wanted? */
if(ret)
{
return ERROR("ZLib error");
return getzliberror(ret,stream->msg);
}
if(!(flags & COMPRESS_FLAG_WORKSPACENOTBOUND))
{
task_strmcreate(stream,true);
}
/* TODO - workspace binding flag */
}
stream->next_in = (Bytef *) r->r[2];
stream->avail_in = (uInt) r->r[3];
stream->next_out = (Bytef *) r->r[4];
stream->avail_out = (uInt) r->r[5];
ret = deflate(stream,(flags & COMPRESS_FLAG_MOREREMAINING?0:Z_FINISH)); /* TODO - Only specify Z_FINISH if no input data? */
ret = deflate(stream,(flags & COMPRESS_FLAG_MOREREMAINING)?0:Z_FINISH);
r->r[2] = (int) stream->next_in;
r->r[3] = (int) stream->avail_in;
r->r[4] = (int) stream->next_out;
......@@ -232,20 +272,24 @@ _kernel_oserror *module_swis(int swi_offset, _kernel_swi_regs *r, void *pw)
{
case Z_OK:
case Z_BUF_ERROR:
r->r[0] = (r->r[2]?COMPRESS_NEED_OUTPUT:COMPRESS_NEED_INPUT); /* TODO - May be wrong for Z_OK */
r->r[0] = ((r->r[3] || !(flags & COMPRESS_FLAG_MOREREMAINING))?COMPRESS_NEED_OUTPUT:COMPRESS_NEED_INPUT);
return NULL;
case Z_STREAM_END:
r->r[0] = COMPRESS_COMPLETE;
deflateEnd(stream);
task_strmdestroy(stream);
return NULL;
default:
return ERROR("ZLib error");
e = getzliberror(ret,stream->msg);
deflateEnd(stream);
task_strmdestroy(stream);
return e;
}
case ZLib_Decompress:
case ZLib_Decompress-ZLib_00:
flags = r->r[0];
if(flags & ~DECOMPRESS_VALID_FLAGS)
return ERROR("Invalid ZLib_Decompress flag");
return ERROR(InvalidDecompressFlag);
if(flags & DECOMPRESS_FLAG_RETURNWORKSPACE)
{
r->r[0] = sizeof(z_stream);
......@@ -261,15 +305,18 @@ _kernel_oserror *module_swis(int swi_offset, _kernel_swi_regs *r, void *pw)
ret = inflateInit(stream);
if(ret)
{
return ERROR("ZLib error");
return getzliberror(ret,stream->msg);
}
if(!(flags & DECOMPRESS_FLAG_WORKSPACENOTBOUND))
{
task_strmcreate(stream,false);
}
/* TODO - workspace binding flag */
}
stream->next_in = (Bytef *) r->r[2];
stream->avail_in = (uInt) r->r[3];
stream->next_out = (Bytef *) r->r[4];
stream->avail_out = (uInt) r->r[5];
ret = deflate(stream,((flags & DECOMPRESS_FLAG_MOREREMAINING) && !(flags & DECOMPRESS_FLAG_ASSUMEWILLFIT)?0:Z_FINISH)); /* TODO - ROL docs are vague for whether ASSUMEWILLFIT actually does anything */
ret = inflate(stream,(flags & DECOMPRESS_FLAG_MOREREMAINING)?0:Z_FINISH);
r->r[2] = (int) stream->next_in;
r->r[3] = (int) stream->avail_in;
r->r[4] = (int) stream->next_out;
......@@ -278,141 +325,189 @@ _kernel_oserror *module_swis(int swi_offset, _kernel_swi_regs *r, void *pw)
{
case Z_OK:
case Z_BUF_ERROR:
r->r[0] = (r->r[2]?DECOMPRESS_NEED_OUTPUT:DECOMPRESS_NEED_INPUT); /* TODO - May be wrong for Z_OK */
r->r[0] = ((r->r[3] || !(flags & DECOMPRESS_FLAG_MOREREMAINING))?DECOMPRESS_NEED_OUTPUT:DECOMPRESS_NEED_INPUT);
return NULL;
case Z_STREAM_END:
r->r[0] = DECOMPRESS_COMPLETE;
inflateEnd(stream);
task_strmdestroy(stream);
return NULL;
default:
return ERROR("ZLib error");
e = getzliberror(ret,stream->msg);
inflateEnd(stream);
task_strmdestroy(stream);
return e;
}
case ZLib_CRC32:
case ZLib_CRC32-ZLib_00:
r->r[0] = (int) crc32((uLong) r->r[0], (const Bytef *) r->r[1], (uInt) (r->r[2]-r->r[1]));
return NULL;
case ZLib_Adler32:
case ZLib_Adler32-ZLib_00:
r->r[0] = (int) adler32((uLong) r->r[0], (const Bytef *) r->r[1], (uInt) (r->r[2]-r->r[1]));
return NULL;
case ZLib_Version:
case ZLib_Version-ZLib_00:
r->r[0] = (int) zlib_version;
return NULL;
case ZLib_ZCompress:
case ZLib_ZCompress-ZLib_00:
r->r[0] = compress((Bytef *) r->r[0], (uLongf *) &r->r[1], (const Bytef *) r->r[2], (uLong) r->r[3]);
return NULL;
case ZLib_ZCompress2:
case ZLib_ZCompress2-ZLib_00:
r->r[0] = compress2((Bytef *) r->r[0], (uLongf *) &r->r[1], (const Bytef *) r->r[2], (uLong) r->r[3], r->r[4]);
return NULL;
case ZLib_ZUncompress:
case ZLib_ZUncompress-ZLib_00:
r->r[0] = uncompress((Bytef *) r->r[0], (uLongf *) &r->r[1], (const Bytef *) r->r[2], (uLong) r->r[3]);
return NULL;
case ZLib_DeflateInit:
r->r[0] = deflateInit_((z_streamp) r->r[0], r->r[1], (const char *) r->r[2], r->r[3]);
case ZLib_DeflateInit-ZLib_00:
ret = deflateInit_((z_streamp) r->r[0], r->r[1], (const char *) r->r[2], r->r[3]);
if(ret == Z_OK)
task_strmcreate((z_streamp) r->r[0],true);
r->r[0] = ret;
return NULL;
case ZLib_InflateInit:
r->r[0] = inflateInit_((z_streamp) r->r[0], (const char *) r->r[1], r->r[2]);
case ZLib_InflateInit-ZLib_00:
ret = inflateInit_((z_streamp) r->r[0], (const char *) r->r[1], r->r[2]);
if(ret == Z_OK)
task_strmcreate((z_streamp) r->r[0],false);
r->r[0] = ret;
return NULL;
case ZLib_DeflateInit2:
r->r[0] = deflateInit2_((z_streamp) r->r[0], r->r[1], r->r[2], r->r[3], r->r[4], r->r[5], (const char *) r->r[6], r->r[7]);
case ZLib_DeflateInit2-ZLib_00:
ret = deflateInit2_((z_streamp) r->r[0], r->r[1], r->r[2], r->r[3], r->r[4], r->r[5], (const char *) r->r[6], r->r[7]);
if(ret == Z_OK)
task_strmcreate((z_streamp) r->r[0],true);
r->r[0] = ret;
return NULL;
case ZLib_InflateInit2:
r->r[0] = inflateInit2_((z_streamp) r->r[0], r->r[1], (const char *) r->r[2], r->r[3]);
case ZLib_InflateInit2-ZLib_00:
ret = inflateInit2_((z_streamp) r->r[0], r->r[1], (const char *) r->r[2], r->r[3]);
if(ret == Z_OK)
task_strmcreate((z_streamp) r->r[0],false);
r->r[0] = ret;
return NULL;
case ZLib_Deflate:
case ZLib_Deflate-ZLib_00:
r->r[0] = deflate((z_streamp) r->r[0], r->r[1]);
return NULL;
case ZLib_DeflateEnd:
case ZLib_DeflateEnd-ZLib_00:
task_strmdestroy((z_streamp) r->r[0]);
r->r[0] = deflateEnd((z_streamp) r->r[0]);
return NULL;
case ZLib_Inflate:
case ZLib_Inflate-ZLib_00:
r->r[0] = inflate((z_streamp) r->r[0], r->r[1]);
return NULL;
case ZLib_InflateEnd:
case ZLib_InflateEnd-ZLib_00:
task_strmdestroy((z_streamp) r->r[0]);
r->r[0] = inflateEnd((z_streamp) r->r[0]);
return NULL;
case ZLib_DeflateSetDictionary:
case ZLib_DeflateSetDictionary-ZLib_00:
r->r[0] = deflateSetDictionary((z_streamp) r->r[0], (const Bytef *) r->r[1], (uInt) r->r[2]);
return NULL;
case ZLib_DeflateCopy:
r->r[0] = deflateCopy((z_streamp) r->r[0], (z_streamp) r->r[1]);
case ZLib_DeflateCopy-ZLib_00:
ret = deflateCopy((z_streamp) r->r[0], (z_streamp) r->r[1]);
if(ret == Z_OK)
task_strmcreate((z_streamp) r->r[0],true);
r->r[0] = ret;
return NULL;
case ZLib_DeflateReset:
case ZLib_DeflateReset-ZLib_00:
r->r[0] = deflateReset((z_streamp) r->r[0]);
return NULL;
case ZLib_DeflateParams:
case ZLib_DeflateParams-ZLib_00:
r->r[0] = deflateParams((z_streamp) r->r[0], r->r[1], r->r[2]);
return NULL;
case ZLib_InflateSetDictionary:
case ZLib_InflateSetDictionary-ZLib_00:
r->r[0] = inflateSetDictionary((z_streamp) r->r[0], (const Bytef *) r->r[1], (uInt) r->r[2]);
return NULL;
case ZLib_InflateSync:
case ZLib_InflateSync-ZLib_00:
r->r[0] = inflateSync((z_streamp) r->r[0]);
return NULL;
case ZLib_InflateReset:
case ZLib_InflateReset-ZLib_00:
r->r[0] = inflateReset((z_streamp) r->r[0]);
return NULL;
case ZLib_GZOpen:
case ZLib_GZOpen-ZLib_00:
return do_gzopen(r);
case ZLib_GZRead:
case ZLib_GZRead-ZLib_00:
r->r[0] = gzread((gzFile) r->r[0], (voidp) r->r[1], r->r[2]);
return NULL;
case ZLib_GZWrite:
case ZLib_GZWrite-ZLib_00:
r->r[0] = gzwrite((gzFile) r->r[0], (const voidp) r->r[1], r->r[2]);
return NULL;
case ZLib_GZFlush:
case ZLib_GZFlush-ZLib_00:
r->r[0] = gzflush((gzFile) r->r[0], r->r[1]);
return NULL;
case ZLib_GZClose:
case ZLib_GZClose-ZLib_00:
r->r[0] = gzclose((gzFile) r->r[0]);
/* TODO - Set filetype to &F89 */
/* TODO - Set filetype to &F89? */
return NULL;
case ZLib_GZError:
/* TODO - Is R1 correct? */
case ZLib_GZError-ZLib_00:
r->r[0] = (int) gzerror((gzFile) r->r[0], &r->r[1]);
return NULL;
case ZLib_GZSeek:
/* TODO - Translate R2? */
r->r[0] = (int) gzseek((gzFile) r->r[0], (z_off_t) r->r[1], r->r[2]);
case ZLib_GZSeek-ZLib_00:
if(r->r[2] == 0)
flags = SEEK_SET;
else if(r->r[2] == 1)
flags = SEEK_CUR;
else
return ERROR(InvalidGZSeek);
r->r[0] = (int) gzseek((gzFile) r->r[0], (z_off_t) r->r[1], flags);
return NULL;
case ZLib_GZTell:
case ZLib_GZTell-ZLib_00:
r->r[0] = (int) gztell((gzFile) r->r[0]);
return NULL;
case ZLib_GZEOF:
case ZLib_GZEOF-ZLib_00:
r->r[0] = (int) gzeof((gzFile) r->r[0]);
return NULL;
case ZLib_TaskAssociate:
return ERROR("Unimplemented"); /* TODO! Need to listen out for Service_WimpCloseDown? How to be sure that stream memory is available so we can free it? Free internal_state manually? Or construct fake stream? Could be dangerous, *End() functions check state. And what if custom alloc/free in use? */
case ZLib_TaskAssociate-ZLib_00:
switch(r->r[1])
{
case TASKASSOCIATE_DISASSOCIATE:
task_associate((z_streamp) r->r[0],false);
return NULL;
case TASKASSOCIATE_ASSOCIATE:
task_associate((z_streamp) r->r[0],true);
return NULL;
default:
return ERROR(InvalidTaskAssociate);
}
default:
return ERROR("No such SWI");
return ERROR(UnknownSWI);
}
}
void module_service(int service_number, _kernel_swi_regs *r, void *pw)
{
(void) pw;
switch (service_number)
{
case Service_WimpCloseDown:
if(!r->r[0])
task_close(r->r[2]);
break;
}
}
/*
 * Copyright (c) 2012, RISC OS Open Ltd
 * All rights reserved.
 *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of RISC OS Open Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
 */
#include "swis.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <errno.h>
#include "Global/RISCOS.h"
#include "Global/Services.h"
#include "globals.h"
#include "errors.h"
typedef struct {
int num;
const char token[8];
} msgerr;
static const msgerr errors[] =
{
{ ErrorNumber_ZLib_NoMem, "NoMem" },
{ ErrorNumber_ZLib_InvalidCompressFlag, "InvCFlg" },
{ ErrorNumber_ZLib_InvalidDecompressFlag, "InvDFlg" },
{ ErrorNumber_ZLib_ZLibError, "ZLibErr" },
{ ErrorNumber_ZLib_UnknownSWI, "UKSWI" },
{ ErrorNumber_ZLib_InvalidTaskAssociate, "InvTA" },
{ ErrorNumber_ZLib_InvalidGZSeek, "InvGZSk" },
};
_kernel_oserror *getourerror(int err)
{
return _swix(MessageTrans_ErrorLookup,_INR(0,2),&errors[err],&messages,0);
}
_kernel_oserror *getzliberror(int err,const char *msg)
{
char num[32];
char *e;
switch(err)
{
case Z_ERRNO:
sprintf(num,"Z_ERRNO %d",errno);
e = num;
break;
case Z_STREAM_ERROR:
e = "Z_STREAM_ERROR";
break;
case Z_DATA_ERROR:
e = "Z_DATA_ERROR";
break;
case Z_MEM_ERROR:
e = "Z_MEM_ERROR";
break;
case Z_BUF_ERROR:
e = "Z_BUF_ERROR";
break;
case Z_VERSION_ERROR:
e = "Z_VERSION_ERROR";
break;
default:
sprintf(num,"%d",err);
e = num;
break;
}
static const msgerr blk[2] = {
{ ErrorNumber_ZLib_ZLibError, "ZLibErr" },
{ ErrorNumber_ZLib_ZLibError, "ZLibEr2" },
};
return _swix(MessageTrans_ErrorLookup,_INR(0,2)|_INR(4,5),&blk[msg?1:0],&messages,0,e,msg);
}
/*
*Copyright(c)2012, RISC OS Open Ltd
*Allrightsreserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of RISC OS Open Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "swis.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdbool.h>
#include "Global/RISCOS.h"
#include "Global/Services.h"
#include "DebugLib/DebugLib.h"
#include "task.h"
/* For now keep things simple and assume there won't be large numbers of tasks/streams active at once */
#define STREAMS_PER_BLOCK 16 /* Must be power of two! */
typedef struct {
int handle; /* Task handle */
z_streamp strm; /* Stream */
bool isdeflate; /* Whether this was an inflate or deflate stream (there's no way of determining which is which using the zlib API!) */
bool isactive; /* Whether this association is active (must keep inactive associations so we can remember if they were inflate or deflate) */
} task_stream;
typedef struct stream_block_t {
task_stream streams[STREAMS_PER_BLOCK];
struct stream_block_t *next,*prev;
} stream_block;
static stream_block *streams = NULL;
static stream_block *last = NULL;
static int numstreams = 0;
static void task_dump(void)
{
#ifdef DEBUGLIB
stream_block *cur = streams;
int i=0,j=0;
dprintf(("","task_dump: %d streams, list=%08x, last=%08x\n",numstreams,streams,last));
while(i<numstreams)
{
if(!j)
dprintf((""," block %08x: next %08x prev %08x\n",cur,cur->next,cur->prev));
dprintf((""," task %08x strm %08x isdeflate %d isactive %d\n",cur->streams[j].handle,cur->streams[j].strm,cur->streams[j].isdeflate,cur->streams[j].isactive));
i++;
if(++j == STREAMS_PER_BLOCK)
{
j = 0;
cur = cur->next;
}
}
#endif
}
static int get_task_handle(void)
{
int handle;
if(_swix(Wimp_ReadSysInfo,_IN(0)|_OUT(0),5,&handle))
return 0;
return handle;
}
static void task_remove(stream_block *block,int i)
{
/* Swap with the last entry to keep the list contiguous */
int lastidx = (--numstreams) & (STREAMS_PER_BLOCK-1);
block->streams[i] = last->streams[lastidx];
/* Remove last block if it's now empty */
if(!lastidx)
{
stream_block *empty = last;
last = last->prev;
if(last)
last->next = NULL;
else
streams = NULL;
free(empty);
}
}
void task_strmcreate(z_streamp strm,bool isdeflate)
{
int handle = get_task_handle();
if(!handle || !strm)
return;
/* Walk the list to make sure this stream isn't already listed */
dprintf(("","task_strmcreate: task %08x strm %08x isdeflate %d\n",handle,strm,isdeflate));
stream_block *cur = streams;
int i=0,j=0;
while(i<numstreams)
{
if((cur->streams[j].handle == handle) && (cur->streams[j].strm == strm))
{
cur->streams[j].isdeflate = isdeflate;
cur->streams[j].isactive = true;
dprintf((""," -> updating existing stream\n"));
return;
}
i++;
if(++j == STREAMS_PER_BLOCK)
{
j = 0;
cur = cur->next;
}
}
if(!last || !j)
{
stream_block *newblock = malloc(sizeof(stream_block));
if(!newblock)
{
/* Give up? */
return;
}
newblock->next = NULL;
newblock->prev = last;
if(last)
last->next = newblock;
last = newblock;
if(!streams)
streams = last;
}
last->streams[j].handle = handle;
last->streams[j].strm = strm;
last->streams[j].isdeflate = isdeflate;
last->streams[j].isactive = true;
numstreams++;