/*
 *	Runtime support routines for T3X.
 *	Copyright (C) 1997,1998 Nils M Holm.
 *	See txtrn.t for details.
 *	See the file LICENSE for conditions of use.
 */

#ifdef plan9
#define _exit(x)	exits(0)
#include <u.h>
#include <libc.h>
#define lseek		seek
#define unlink		remove
#define	creat(F, P)	create(F, ORDWR, P)
#define off_t		long
#else
#ifdef msdos
#define off_t		long
#endif
#include <sys/types.h>
#endif

#ifdef msdos
#define BPW	2
#else
#define BPW	4
#endif
#define BUFLEN	1024
#define STRLEN	256

#define uchar	unsigned char
#define ushort	unsigned short
#define uint	unsigned int


int		Input, Output;


int	open_(), close_(), erase_(), select_(), reads_(), writes_(),
	newline_(), aton_(), ntoa_(), pack_(), unpack_(), readpacked_(),
	writepacked_(), reposition_(), rename_(), memcopy_(), memcomp_();

int	(*GV_[100])();


badgv() {
	write(2, "LIBTX: uninitialized interface\n", 31);
	_exit(-1);
}


void TXINIT() {
	int	i;

	Input = 0;
	Output = 1;
	for (i=0; i<100; i++) GV_[i] = badgv;
	GV_[0] = open_;
	GV_[1] = close_;
	GV_[2] = erase_;
	GV_[3] = select_;
	GV_[4] = reads_;
	GV_[5] = writes_;
	GV_[6] = newline_;
	GV_[7] = aton_;
	GV_[8] = ntoa_;
	GV_[9] = pack_;
	GV_[10] = unpack_;
	GV_[11] = readpacked_;
	GV_[12] = writepacked_;
	GV_[13] = reposition_;
	GV_[14] = rename_;
	GV_[15] = memcopy_;
	GV_[16] = memcomp_;
}


#ifdef plan9
int rename(old, new)
char	*old, *new;
{
	Dir	d;
	int	k, p = 0;

	if (dirstat(old, &d) < 0) return(-1);
	k = strlen(new);
	if (k >= NAMELEN) {
		p = new[NAMELEN-1];
		new[NAMELEN-1] = 0;
	}
	memmove(d.name, new, k);
	if (p) new[NAMELEN-1] = p;
	return(dirwstat(old, &d));
}
#endif


#ifndef msdos
pack_(s, v)
unsigned char	*s;
unsigned int	*v;
{
	int	i;

	for (i=0; v[i]; i++) s[i] = v[i];
	s[i] = 0;
	return((i+BPW)/BPW);
}


unpack_(v, s)
unsigned int	*v;
unsigned char	*s;
{
	int	i;

	for (i=0; s[i]; i++) v[i] = s[i];
	v[i] = 0;
	return(i);
}


length_(v)
int	*v;
{
	int	i = 0;

	while (v[i]) i++;
	return(i);
}
#endif


aton_(s)
int	*s;
{
	int	k, v = 0, g = 0;

	k = 0;
	while (	s[k] == ' ' || s[k] == '\t' || s[k] == '\n' ||
		s[k] == '\r' || s[k] == '\f'
	)
		k++;
	if (s[k] == '-' || s[k] == '%') {
		g = 1;
		k++;
	}
	else if (s[k] == '+') {
		k++;
	}
	while ('0' <= s[k] && s[k] <= '9') {
		v = v*10 + (s[k]-'0');
		k++;
	}
	return(g? -v: v);
}


int ntoa_(w, v)
int	w, v;
{
	static int	n[STRLEN+1];
	int		i, g = 0;
	unsigned	u;

	if (v<0) {
		g = 1;
		v = -v;
	}
	u = v;
	n[STRLEN] = 0;
	i = STRLEN-1;
	while (u || i == STRLEN-1) {
		n[i--] = u%10+'0';
		u = u/10;
		w--;
	}
	if (g) {
		n[i--] = '-';
		w--;
	}
	while (w>0) {
		n[i--] = ' ';
		w--;
	}
	return((int)&n[i+1]);
}


open_(mode, file)
int	*file, mode;
{
	char	name[256];
	int	fd;

	pack_(name, file);
	if (mode == 1)
		fd = creat(name, 0666);
	else if (mode == 0 || mode == 2 || mode == 3)
		fd = open(name, mode==3? 2: mode);
	else
		return(-1);
	if (fd> 0 && mode == 3) lseek(fd, 0L, 2);
	return(fd);
}


close_(fd) {
	return(close(fd));
}


erase_(file)
int	*file;
{
	char	name[256];

	pack_(name, file);
	return(unlink(name));
}


select_(new, port) {
	int	old;

	if (port) {
		old = Output;
		Output = new;
	}
	else {
		old = Input;
		Input = new;
	}
	return(old);
}


reads_(n, s)
int		n;
unsigned int	*s;
{
	unsigned char	IOBuf[BUFLEN+1];
	int		k, i;

	k = read(Input, IOBuf, n);
	if (k<0) return(k);
	for (i=0; i<k; i++) s[i] = IOBuf[i];
	s[i] = 0;
	return(k);
}


writes_(s)
int	*s;
{
	char	IOBuf[BUFLEN+1];

	pack_(IOBuf, s);
	return(write(Output, IOBuf, length_(s)));
}


newline_() {
#ifdef msdos
	write(Output, "\r\n", 2);
#else
	write(Output, "\n", 1);
#endif
}


readpacked_(len, buf, fd)
int	len, *buf, fd;
{
	return (read(fd, buf, len));
}


writepacked_(len, buf, fd)
int	len, *buf, fd;
{
	return (write(fd, buf, len));
}


reposition_(how, lo, hi, fd)
int	how, lo, hi, fd;
{
	return (lseek(fd, (off_t)(((long)hi<<16)|lo), how));
}


rename_(new, old)
int	*new, *old;
{
	char	oldp[256], newp[256];

	pack_(oldp, old);
	pack_(newp, new);
	return(rename(oldp, newp));
}


memcopy_(len, s2, s1)
int	len, *s1, *s2;
{
	return((int) memmove(s1, s2, len));
}


memcomp_(len, s2, s1)
int	len, *s1, *s2;
{
	return(memcmp(s1, s2, len));
}

