/*
 *  unlzw_gzip.cc
 *
 *  (c) 1999, Emmanuel Lesueur
 */

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <exec/memory.h>
#include <stdarg.h>

#ifdef __PPC__
#   define strlen strlenZZ
#   include <powerup/ppcproto/dos.h>
#   include <powerup/gcclib/powerup_protos.h>
#   undef strlen

inline BPTR myOpen(const char* n,LONG m) {
    return PPCOpen((char*)n,m);
}
inline LONG myClose(BPTR f) {
    return PPCClose(f);
}
inline LONG myRead(BPTR f,void* b,size_t sz) {
    return PPCRead(f,b,sz);
}
inline LONG myWrite(BPTR f,void* b,size_t sz) {
    return PPCWrite(f,b,sz);
}
inline APTR myAllocMem(ULONG sz,ULONG f) {
    return PPCAllocMem(sz,f);
}
inline void myFreeMem(APTR p,ULONG sz) {
    PPCFreeMem(p,sz);
}
#else
#   include <proto/dos.h>
#   include <proto/exec.h>
inline BPTR myOpen(const char* n,LONG m) {
    return Open((char*)n,m);
}
inline LONG myClose(BPTR f) {
    return Close(f);
}
inline LONG myRead(BPTR f,void* b,size_t sz) {
    return Read(f,b,sz);
}
inline LONG myWrite(BPTR f,void* b,size_t sz) {
    return Write(f,b,sz);
}
inline APTR myAllocMem(ULONG sz,ULONG f) {
    return AllocMem(sz,f);
}
inline void myFreeMem(APTR p,ULONG sz) {
    FreeMem(p,sz);
}
#endif

#define IMPL
#include "../xpdf/UnLZW.h"

extern "C" const char* unlzw(Pipe* in,Pipe* out,const char* cmd) {
    size_t sz=in->size()+3;
    char tmp[256];
    strcpy(tmp,cmd);
    char* filename;
    char* t=tmp+strlen(tmp);
    *t++=' ';
    filename=t;
    *t++='A';
    *t++='p';
    *t++='d';
    *t++='f';
    unsigned x=(unsigned)&tmp;
    while(x) {
	*t++=char('0'+(x&3));
	x>>=3;
    }
    *t++='.';
    *t++='Z';
    *t='\0';
    const char* err=NULL;
    if(char* buf=(char*)myAllocMem(sz,MEMF_ANY)) {
	char *p=buf;
	size_t sz2=sz-3;
	*p++=char(0x1f);
	*p++=char(0x9d);
	*p++=char(0x8c);
	while(int n=in->read(p,sz2)) {
	    p+=n;
	    sz2-=n;
	}
	if(sz2!=0)
	    return "Unexpected end of stream.";
	if(BPTR file=myOpen(filename,MODE_NEWFILE)) {
	    myWrite(file,buf,sz);
	    myClose(file);
	} else
	    err="Error writing temporary file.";
	myFreeMem(buf,sz);
    }
    if(err)
	;
    else if(!SystemTagList(tmp,NULL)) {
	t[-2]='\0';
	if(BPTR file=myOpen(filename,MODE_OLDFILE)) {
	    sz=0;
	    if(FileInfoBlock* fib=(FileInfoBlock*)AllocDosObject(DOS_FIB,NULL)) {
		if(ExamineFH(file,fib))
		    sz=fib->fib_Size;
		FreeDosObject(DOS_FIB,fib);
	    }
	    if(sz) {
		if(void* buf=myAllocMem(sz,MEMF_ANY)) {
		    sz=myRead(file,buf,sz);
		    if(sz!=-1)
			out->write(buf,sz);
		    myFreeMem(buf,sz);
		}
	    } else
		err="Can't find file size";
	    myClose(file);
	} else {
	    err = "Can't read temporary file.";
	    t[-2]='.';
	}
    } else
	err="Can't execute gzip command";

    DeleteFile(filename);
    return err;
}

