[alt.sources] Small termlib

peter@sugar.hackercorp.com (Peter da Silva) (09/04/90)

Archive-name: termlib

The following implementation of termlib is hereby placed in the public
domain. It's not fancy, it doesn't inlcude terminfo, but it's small and
clean and is useful for porting termlib-based programs like Elvis to
other platforms. I originally wrote it for CP/M under the BDS C compiler
so it makes few assumptions about the environment.

The included makefile is for the Amiga, but I think it unlikely anyone would
have much trouble porting it to other machines. The implementation of tgoto
is probably out of date, but if you really need more it'd be easy enough to
expand.

The port of elvis itself to the Amiga is underway.

: This archive contains the following files...
: 'termlib.h'
: 'tinit.c'
: 'tgetnum.c'
: 'tutil.c'
: 'tvars.c'
: 'tgoto.c'
: 'tgetent.c'
: 'tputs.c'
: 'cur.c'
: 'termcap.c'
: 'tgetflag.c'
: 'tgetstr.c'
: 'Makefile'
: To extract them, run the following through /bin/sh
echo x - termlib.h
sed 's/^X//' > termlib.h << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: termlib.h
X *
X * Purpose: declare global variables and functions.
X */
X
X/* termlib.h
X * Global variables for termlib
X *
X*/
X#ifndef AMIGA
X#define AMIGA 0
X#endif
X
Xextern char *tent;             /* Pointer to terminal entry, set by tgetent */
Xextern char PC;                              /* Pad character, default NULL */
Xextern char *UP, *BC;        /* Pointers to UP and BC strings from database */
Xextern short ospeed;       /* Baud rate (1-16, 1=300, 16=19200), as in stty */
X
Xint tgetnum();
Xchar *tgoto();
Xint tgetent();
Xint tgetflag();
Xchar *tgetstr();
X
Xchar *_find();
Xchar *_addfmt();
//END
echo x - tinit.c
sed 's/^X//' > tinit.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tinit
X *
X * Purpose: simplified terminal initialisation.
X *
X * Calling conventions: name is name of terminal.
X *
X * Returned values: none.
X *
X * Notes
X *		tinit calls tgetent, then sets up the global
X *	variables PC, UP, BC, ospeed appropriately.
X *
X */
X#include "termlib.h"
X#include <stdio.h>
X#if !AMIGA
X#include <sgtty.h>
X#endif
X
X/* tinit.c (libtermlib.a)
X *
X */
X
Xchar tbuf[1024];                                /* Buffer for termcap entry */
Xchar junkbuf[1024];                                  /* Big buffer for junk */
Xchar *junkptr;
X
Xtinit(name)
Xchar *name;
X{
X#if !AMIGA
X	struct sgttyb sgbuf;
X#endif
X	char *ps;
X
X	junkptr = junkbuf;
X
X	tgetent(tbuf, name);
X
X	ps = tgetstr("pc", &junkptr);
X	if(ps) PC = *ps;
X	UP = tgetstr("up", &junkptr);
X	BC = tgetstr("bc", &junkptr);
X
X#if AMIGA
X	ospeed=0;
X#else
X	gtty(1, &sgbuf);
X	ospeed=sgbuf.sg_ospeed;
X#endif
X}
//END
echo x - tgetnum.c
sed 's/^X//' > tgetnum.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tgetnum
X *
X * Purpose: get numeric value such as 'li' or 'co' from termcap.
X *
X * Calling conventions: id = 2 character id.
X *
X * Returned values: -1 for failure, else numerical value.
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tgetnum.c (libtermlib.a)
X *
X */
X
Xtgetnum(id)
Xchar *id;
X{
X	char *ptr, buf[256];
X	ptr = buf;
X
X	if(tgetstr(id, &ptr))
X		return atoi(buf);
X	else
X		return 0;
X}
//END
echo x - tutil.c
sed 's/^X//' > tutil.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tutil.c
X *
X * Purpose: Utility routines for TERMLIB functions.
X *
X */
X
X/* tutil.c (libtermlib.a)
X * Utility routines for termlib
X *
X */
X
X_match(s1, s2)                 /* returns length of text common to s1 and s2 */
Xchar *s1, *s2;
X{
X	int i = 0;
X
X	while(s1[i] && s1[i] == s2[i])
X		i++;
X
X	return i;
X}
X
Xchar *
X_find(s, set)   /* finds next c in s that's a member of set, returns pointer */
Xchar *s, *set;
X{
X	for(; *s; s++) {
X		char    *ptr = set;
X
X		while(*ptr && *s != *ptr)
X			ptr++;
X
X		if(*ptr)
X			return s;
X	}
X
X	return s;
X}
X
Xchar *
X_addfmt(buf, fmt, val)             /* add val to buf according to format fmt */
Xchar *buf, *fmt;
Xint val;
X{
X	sprintf(buf, fmt, val);
X	while(*buf)
X		buf++;
X	return buf;
X}
//END
echo x - tvars.c
sed 's/^X//' > tvars.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tvars
X *
X * Purpose: supply actual global variables.
X */
X
X/* tvars.c (libtermlib.a)
X * Global variables for termlib
X *
X*/
X
Xchar *tent;                     /* Pointer to terminal entry, set by tgetent */
Xchar PC = 0;                                  /* Pad character, default NULL */
Xchar *UP = 0, *BC = 0;        /* Pointers to UP and BC strings from database */
Xshort ospeed;               /* Baud rate (1-16, 1=300, 16=19200), as in stty */
//END
echo x - tgoto.c
sed 's/^X//' > tgoto.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tgoto
X *
X * Purpose: decode cm cursor motion string.
X *
X * Calling conventions: cm is cursor motion string.
X *			line, col, are the desired destination.
X *
X * Returned values: a string pointing to the decoded string, or
X *		    "OOPS" if it cannot be decoded.
X *
X * Notes
X *		The accepted escapes are:
X *			%d	 as in printf, 0 origin.
X *			%2, %3	 like %02d, %03d in printf.
X *			%.	 like %c
X *			%+x	 adds <x> to value, then %.
X *			%>xy	 if value>x, adds y. No output.
X *			%i	 increments line& col, no output.
X *			%r	 reverses order of line&col. No output.
X *			%%	 prints as a single %.
X *			%n	 exclusive or row & col with 0140.
X *			%B	 BCD, no output.
X *			%D	 reverse coding (x-2*(x%16)), no output.
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tgoto.c (libtermlib.a)
X *
X */
X
Xchar *
Xtgoto(cm, col, line)
Xchar	*cm;                                      /* cm string, from termcap */
Xint	col,                                           /* column, x position */
X	line;                                            /* line, y position */
X{
X	char	*_addfmt(),
X		gx, gy,                                           /*    x, y */
X		*ptr,                                     /* pointer in 'cm' */
X		reverse = 0,                                 /* reverse flag */
X		*bufp,                         /* pointer in returned string */
X		addup = 0,                                     /* add upline */
X		addbak = 0,                                    /* add backup */
X		c;
X	static char buffer[32];
X
X	if(!cm)
X		return "OOPS";                       /* Kludge, but standard */
X
X	bufp = buffer;
X	ptr = cm;
X
X	while(*ptr) {
X		if((c = *ptr++) != '%') {                     /* normal char */
X			*bufp++ = c;
X		} else {                                         /* % escape */
X			switch(c = *ptr++) {
X			case 'd':                                 /* decimal */
X				bufp = _addfmt(bufp, "%d", line);
X				line = col;
X				break;
X			case '2':                         /* 2 digit decimal */
X				bufp = _addfmt(bufp, "%02d", line);
X				line = col;
X				break;
X			case '3':                         /* 3 digit decimal */
X				bufp = _addfmt(bufp, "%03d", line);
X				line = col;
X				break;
X			case '>':                      /* %>xy: if >x, add y */
X				gx = *ptr++;
X				gy = *ptr++;
X				if(col>gx) col += gy;
X				if(line>gx) line += gy;
X				break;
X			case '+':                              /* %+c: add c */
X				line += *ptr++;
X			case '.':                               /* print x/y */
X				if(line=='\t' ||                /* these are */
X				   line == '\n' ||             /* chars that */
X				   line=='\004' ||             /* UNIX hates */
X				   line=='\0') {
X					line++;         /* so go to next pos */
X					if(reverse==(line==col))
X						addup=1;      /* and mark UP */
X					else
X						addbak=1;           /* or BC */
X				}
X				*bufp++=line;
X				line = col;
X				break;
X			case 'r':                              /* r: reverse */
X				gx = line; 
X				line = col; 
X				col = gx;
X				reverse = 1;
X				break;
X			case 'i':             /* increment (1-origin screen) */
X				col++;
X				line++;
X				break;
X			case '%':                          /* %%=% literally */
X				*bufp++='%';
X				break;
X			case 'n':                       /* magic DM2500 code */
X				line ^= 0140;
X				col ^= 0140;
X				break;
X			case 'B':                            /* bcd encoding */
X				line = line/10<<4+line%10;
X				col = col/10<<4+col%10;
X				break;
X			case 'D':                   /* magic Delta Data code */
X				line = line-2*(line&15);
X				col = col-2*(col&15);
X				break;
X			default:                           /* Unknown escape */
X				return "OOPS";
X			}
X		}
X	}
X
X	if(addup)                                              /* add upline */
X		if(UP) {
X			ptr=UP;
X			while(isdigit(*ptr) || *ptr=='.')
X				ptr++;
X			if(*ptr=='*')
X				ptr++;
X			while(*ptr)
X				*bufp++ = *ptr++;
X		}
X
X	if(addbak)                                          /* add backspace */
X		if(BC) {
X			ptr=BC;
X			while(isdigit(*ptr) || *ptr=='.')
X				ptr++;
X			if(*ptr=='*')
X				ptr++;
X			while(*ptr)
X				*bufp++ = *ptr++;
X		} 
X		else
X			*bufp++='\b';
X
X	*bufp = 0;
X
X	return(buffer);
X}
//END
echo x - tgetent.c
sed 's/^X//' > tgetent.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tgetent
X *
X * Purpose: Get termcap entry for <term> into buffer at <tbuf>.
X *
X * Calling conventions: char tbuf[1024+], term=canonical name for
X *			terminal.
X *
X * Returned values: 1 = success, -1 = can't open file,
X *		    0 = can't find terminal.
X *
X * Notes
X *		Should probably supply static buffer.
X *
X *		Uses environment variables "TERM" and
X *	"TERMCAP". If TERM = term (that is, if the argument
X *	matches the environment) then it looks at TERMCAP.
X *		If TERMCAP begins with a slash, then it assumes
X *	this is the file to search rather than /etc/termcap.
X *		If TERMCAP does not begin with a slash, and it
X *	matches TERM, then this is used as the entry.
X *
X *		This could be simplified considerably for non-UNIX
X *	systems.
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tgetent.c (libtermlib.a)
X *
X */
X#if AMIGA
X#define TERMCAP "s:termcap"
X#else
X#define TERMCAP "/etc/termcap"
X#endif
X
Xtgetent(tbuf, term)
Xchar	*tbuf,               /* Buffer to hold termcap entry, 1024 bytes max */
X	*term;                                           /* Name of terminal */
X{
X	char    tcbuf[32],                          /* Temp buffer to handle */
X		*tc,                                     /* :tc=: entry for  */
X		*tcptr = tcbuf;                          /* extended entries */
X	char    *tcap = TERMCAP,              /* Default termcap file */
X		*getenv();
X	char    *tmp;
X	FILE    *termcap;
X
X	if((tmp=getenv("TERMCAP")) != NULL) {
X		if(*tmp == '/')           /* TERMCAP = name of termcap file */
X			tcap = tmp ;
X		else {                    /* TERMCAP = termcap entry itself */
X			int tlen = strlen(term);
X			while(*tmp && *tmp != ':') {/* Check if TERM matches */
X				while(*tmp == '|')
X					tmp++;
X				if(_match(tmp, term)==tlen) {
X					strcpy(tbuf, tmp);
X					tent=tbuf;
X					return 1;
X				} 
X				else
X					tmp = _find(tmp, ":|");
X			}
X		}
X	}
X	if(!(termcap=fopen(tcap, "r"))) {
X		strcpy(tbuf, tcap);
X		return -1;
X	}
X
X	if(getent(tbuf, term, termcap)) {
X		if(tc=tgetstr("tc", &tcptr)) {              /* extended entry */
X			rewind(termcap);
X			if(getent(tbuf+strlen(tbuf), tc, termcap)) { 
X				fclose(termcap);               /* Completed */
X				return 1; 
X			}
X			else { 
X				fclose(termcap);              /* Incomplete */
X				return 0; 
X			}
X		} else { 
X			fclose(termcap);              /* non-extended entry */
X			return 1; 
X		}
X	} else { 
X		fclose(termcap);                                /* No entry */
X		return 0; 
X	}
X}
X
Xgetent(tbuf, term, termcap)
Xchar *tbuf, *term;
XFILE *termcap;
X{
X	char    *tptr;
X	int    tlen = strlen(term);
X
X	while(nextent(tbuf, termcap)) {           /* For each possible entry */
X		tptr = tbuf;
X		while(*tptr && *tptr != ':') {    /* : terminates name field */
X			while(*tptr == '|')             /* | seperates names */
X				tptr++;
X			if(_match(tptr, term)==tlen) {             /* FOUND! */
X				fclose(termcap);
X				tent=tbuf;
X				return 1;
X			} 
X			else                           /* Look for next name */
X				tptr = _find(tptr, ":|");
X		}
X	}
X
X	return 0;
X}
X
Xnextent(tbuf, termcap)                     /* Read 1 entry from TERMCAP file */
Xchar    *tbuf;
XFILE    *termcap;
X{
X	char *lbuf =                                     /* lbuf=line buffer */
X	     tbuf;                        /* read lines straight into buffer */
X
X	while(lbuf < tbuf+1024 &&                        /* There's room and */
X	      fgets(lbuf, tbuf+1024-lbuf, termcap)) {        /* another line */
X		int llen = strlen(lbuf);
X
X		if(*lbuf=='#')                               /* eat comments */
X			continue;
X		if(lbuf[-1]==':' &&                        /* and whitespace */
X		   lbuf[0]=='\t' &&
X		   lbuf[1]==':') {
X			strcpy(lbuf, lbuf+2);
X			llen -= 2;
X		}
X		if(lbuf[llen-2]=='\\')                  /* and continuations */
X			lbuf += llen-2;
X		else {
X			lbuf[llen-1]=0;           /* no continuation, return */
X			return 1;
X		}
X	}
X
X	return 0;                                    /* ran into end of file */
X}
//END
echo x - tputs.c
sed 's/^X//' > tputs.c << '//END'
X/* TERMLIB: Terminal independant database.
X *
X * Module: tputs
X *
X * Purpose: decode padding information
X *
X * Calling conventions: cp = string to be padded, affcnt = # of items
X *			affected (lines, characters, whatever),
X *			outc = routine to output 1 character.
X *
X * Returned values: none
X *
X * Notes
X *		cp has padding information ahead of it, in the form
X *	nnnTEXT or nnn*TEXT. nnn is the number of milliseconds to delay,
X *	and may be a decimal (nnn.mmm). If the asterisk is given, then
X *	the delay is multiplied by afcnt. The delay is produced by outputting
X *	a number of nulls (or other padding char) after printing the
X *	TEXT.
X *
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tputs.c (libtermlib.a)
X *
X */
X
Xlong _bauds[16]={
X	0,	50,	75,	110,
X	134,	150,	200,	300,
X	600,	1200,	1800,	2400,
X	4800,	9600,	19200,	19200 };
X
Xtputs(cp, affcnt, outc)
Xchar *cp;                                                 /* string to print */
Xint affcnt;                                      /* Number of lines affected */
Xint (*outc)();                              /* routine to output 1 character */
X{
X	long	frac,                    /* 10^(#digits after decimal point) */
X		counter,                                           /* digits */
X		atol();
X
X	if(isdigit(*cp)) {
X		counter = 0;
X		frac = 1000;
X		while(isdigit(*cp))
X			counter = counter * 10L + (long)(*cp++ - '0');
X		if(*cp=='.')
X			while(isdigit(*++cp)) {
X				counter = counter * 10L + (long)(*cp++ - '0');
X				frac = frac * 10;
X			}
X		if(*cp!='*') {                 /* multiply by affected lines */
X			if(affcnt>1) affcnt = 1;
X		} 
X		else
X			cp++;
X
X        /* Calculate number of characters for padding counter/frac ms delay */
X		if(ospeed)
X			counter = (counter * _bauds[ospeed] * (long)affcnt) / frac;
X
X		while(*cp)                                  /* output string */
X			(*outc)(*cp++);
X		if(ospeed)
X			while(counter--)            /* followed by pad characters */
X				(*outc)(PC);
X	} 
X	else
X		while(*cp)
X			(*outc)(*cp++);
X}
//END
echo x - cur.c
sed 's/^X//' > cur.c << '//END'
X/* Cur: Provide cursor addressing for shell scripts.
X *
X * Cur performs the same functions as echo, with 2 differences:
X *  1. 
X *     a. Arguments of the form -xx result in the generation of the capability
X *        string xx. The two special strings "cm" and "cs" are handled by
X *        cur ... -cm x y ... and ... -cs lo hi ...
X *     b. Arguments of the form #xx return the value of the numeric capability
X *        xx.
X *     c. Arguments of the form +terminal force cur to assume that as the
X *        terminal type. Any number of these can be included, and will be
X *        evaluated when encountered.
X *  2. No newline is appended to the echoed string.
X *
X * Syntax: cur [string|-xx|#xx|+term]...
X *
X * Other notes: The code is obvious.
X */
X#include <stdio.h>
X#include "termlib.h"
X
Xextern char *junkptr;
X
Xmain(ac, av)
Xint ac; char **av;
X{
X	int line, col, outch();
X	char *val;
X
X	tinit(getenv("TERM"));
X
X	while(--ac)
X		if(**++av=='-') {
X			if(val=tgetstr(*av+1, &junkptr)) {
X				if(strcmp(*av+1, "cm") &&
X				   strcmp(*av+1, "cs"))
X					tputs(val, 1, outch);
X				else {
X					col = atoi(*++av); --ac;
X					line = atoi(*++av); --ac;
X					tputs(tgoto(val, col, line), 0, outch);
X				}
X			}
X		} else if(**av=='#') {
X			if(val = tgetstr(*av+1, &junkptr))
X				fputs(val, stdout);
X		} else if(**av=='+') {
X			tinit(*av+1);
X		} else
X			fputs(*av, stdout);
X}
X
Xoutch(c) char c; { putchar(c); }
//END
echo x - termcap.c
sed 's/^X//' > termcap.c << '//END'
X/* termcap... print current terminal capabilities.
X *
X * Termcap prints all the termcap capability strings for the terminal `term'.
X * The output is in machine readable form, suitable for use in the construct:
X *
X *    TERMCAP="`termcap`"; export TERMCAP
X *
X * Syntax: termcap [term]
X */
X#include <stdio.h>
X
Xchar *tent;
Xmain(ac, av)
Xint ac;
Xchar **av;
X{
X	char tbuf[1024];
X	if(ac==1) if(tgetent(tbuf, getenv("TERM"))) {
X		puts(tbuf);
X		exit(0);
X	} else exit(-1);
X	if(tgetent(tbuf, av[1])) {
X		puts(tbuf);
X		exit(0);
X	} else exit(-1);
X}
//END
echo x - tgetflag.c
sed 's/^X//' > tgetflag.c << '//END'
X/* The following software is (C) 1984 Peter da Silva,
X   the Mad Australian, in the public domain. It may
X   be re-distributed for any purpose with the inclusion
X   of this notice. */
X/* TERMLIB: Terminal independant database.
X *
X * Module: tgetflag
X *
X * Purpose: returns flag true or false as to the existence of a given
X *	    entry. used with 'bs', 'am', etc...
X *
X * Calling conventions: id is the 2 character capability id.
X *
X * Returned values: 1 for success, 0 for failure.
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tgetflag.c (libtermlib.a)
X *
XBUILD
XOBJS=tinit.o tutil.o tvars.o \
X     tgoto.o tputs.o tgetent.o tgetflag.o tgetnum.o tgetstr.o
XCFLAGS=-O
X
Xlibtermlib.a: $(OBJS) termlib.h
X	ar cr libtermlib.a $(OBJS)
X	ranlib libtermlib.a
X
X$(OBJS):: termlib.h
XEND
X*/
X
Xtgetflag(id)
Xchar *id;
X{
X	char	buf[256], *ptr = buf;
X
X	return tgetstr(id, &ptr) ? 1 : 0;
X}
//END
echo x - tgetstr.c
sed 's/^X//' > tgetstr.c << '//END'
X/* The following software is (C) 1984 Peter da Silva,
X   the Mad Australian, in the public domain. It may
X   be re-distributed for any purpose with the inclusion
X   of this notice. */
X/* TERMLIB: Terminal independant database.
X *
X * Module: tgetstr
X *
X * Purpose: get terminal capability string from database.
X *
X * Calling conventions: id is the two character capability id.
X *			(*buf) points into a hold buffer for the
X *			id. the capability is copied into the buffer
X *			and (*buf) is advanced to point to the next
X *			free byte in the buffer.
X *
X * Returned values: 0 = no such entry, otherwise returns original
X *		    (*buf) (now a pointer to the string).
X *
X * Notes
X *		It also decodes certain escape sequences in the buffer.
X *	they should be obvious from the code:
X *		\E = escape.
X *		\n, \r, \t, \f, \b match the 'c' escapes.
X *		^x matches control-x (^@...^_).
X *		\nnn matches nnn octal.
X *		\x, where x is anything else, matches x. I differ
X *	from the standard library here, in that I allow ^: to match
X *	:.
X *
X */
X#include <stdio.h>
X#include <ctype.h>
X#include "termlib.h"
X
X/* tgetstr.c (libtermlib.a)
X *
XBUILD
XOBJS=tinit.o tutil.o tvars.o \
X     tgoto.o tputs.o tgetent.o tgetflag.o tgetnum.o tgetstr.o
XCFLAGS=-O
X
Xlibtermlib.a: $(OBJS) termlib.h
X	ar cr libtermlib.a $(OBJS)
X	ranlib libtermlib.a
X
X$(OBJS):: termlib.h
XEND
X*/
X
Xchar *
Xtgetstr(id, buf)
Xchar    *id, **buf;
X{
X	int    len = strlen(id);
X	char *tmp=tent;
X	char *hold;
X
X	do {
X		tmp = _find(tmp, ":");                     /* For each field */
X		while(*tmp==':')                        /* skip empty fields */
X			tmp++;
X		if(!*tmp)
X			break;
X
X		if(_match(id, tmp)==len) {
X			tmp += len;                   /* find '=' '@' or '#' */
X			if(*tmp=='@')                  /* :xx@: entry for tc */
X				return 0;                   /* deleted entry */
X			hold= *buf;
X			while(*++tmp && *tmp != ':') {/* not at end of field */
X				switch(*tmp) {
X				case '\\':            /* Expand escapes here */
X					switch(*++tmp) {
X					case 0:        /* ignore backslashes */
X						tmp--;    /* at end of entry */
X						break;   /* shouldn't happen */
X					case 'e':
X					case 'E':                     /* ESC */
X						*(*buf)++ = '\033'; 
X						break;
X					case 'n':                      /* \n */
X						*(*buf)++ = '\n'; 
X						break;
X					case 'r':                      /* \r */
X						*(*buf)++ = '\r'; 
X						break;
X					case 't':                      /* \t */
X						*(*buf)++ = '\t'; 
X						break;
X					case 'b':                      /* \b */
X						*(*buf)++ = '\b'; 
X						break;
X					case 'f':                      /* \f */
X						*(*buf)++ = '\f'; 
X						break;
X					case '0':                    /* \nnn */
X					case '1': 
X					case '2': 
X					case '3': 
X					case '4':
X					case '5': 
X					case '6': 
X					case '7': 
X					case '8': 
X					case '9':
X						**buf = 0;
X						while(isdigit(*tmp))
X							**buf = **buf * 8 + *tmp++ - '0';
X						(*buf)++;
X						tmp--;
X						break;
X					default:      /* \x, for all other x */
X						*(*buf)++= *tmp;
X					}
X					break;
X				case '^':              /* control characters */
X					*(*buf)++ = *++tmp - '@'; 
X					break;
X				default: 
X					*(*buf)++ = *tmp;
X				}
X			}
X			*(*buf)++ = 0;
X			return hold;
X		}
X	} while(*tmp);
X
X	return 0;
X}
//END
echo x - Makefile
sed 's/^X//' > Makefile << '//END'
X#
X# The following module order is needed to create a properly sorted library
X# for Manx
X#
X
XOBJS=\
X	tgetflag.o\
X	tgetnum.o\
X	tinit.o\
X	tgoto.o\
X	tputs.o\
X	tvars.o\
X	tgetent.o\
X	tgetstr.o\
X	tutil.o
XSRC=\
X	termlib.h\
X	tinit.c\
X	tgetnum.c\
X	tutil.c\
X	tvars.c\
X	tgoto.c\
X	tgetent.c\
X	tputs.c\
X	cur.c\
X	termcap.c\
X	tgetflag.c\
X	tgetstr.c\
X	Makefile
X
XCFLAGS= +P -B -DAMIGA=1
XLIB=termlibl32.lib
X
XLIBDIR=manx:lib
XBINDIR=work:c
X
Xall: cur termcap
X
X$(LIB): $(OBJS)
X	lb $(LIB) $(OBJS)
X
Xtermcap: $(LIB) termcap.o
X	ln -o termcap termcap.o $(LIB) -lcl32
X
Xcur: $(LIB) cur.o
X	ln -o cur cur.o $(LIB) -lcl32
X
Xclean:
X	delete #?.o #?.lib termcap cur #?.bak
X
Xinstall: all
X	copy $(LIB) $(LIBDIR)
X	copy termcap $(BINDIR)
X	copy cur $(BINDIR)
X
Xtermlib.shar: $(SRC)
X	shar >termlib.shar $(SRC)
//END
: end of archive.
exit 0
-- 
Peter da Silva.   `-_-'
<peter@sugar.hackercorp.com>.