[net.sources] untic source

mark@ems.UUCP (Mark H. Colburn) (12/21/86)

Here is the source for untic, a terminfo definition disassembler.  The source
here is from the Unipress EMACS distribution tape and has been delcared 
Public Domain by Unipress.  The original author of the source is Dave Regan.
The shar file contains source, Makefile and manpage.


Mark H. Colburn             UUCP: ihnp4!meccts!ems!mark
EMS/McGraw-Hill              ATT: (612) 829-8200
9855 West 78th Street
Eden Prairie, MN  55344

---------------------------------- CUT HERE --------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1.  Remove everything above the #! /bin/sh line.
# 2.  Save the resulting test in a file
# 3.  Execute the file with /bin/sh (not csh) to create the files:
#
#		Makefile
#		README
#		untic.1
#		untic.c
#
# Created by mark (Mark H. Colburn) on Sun Dec 21 01:13:19 CST 1986
#
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
echo extracting "'Makefile'"
sed 's/^X//' >Makefile <<'SHAR_EOF'
XCFLAGS = -O -DHPUX5
XDESTDIR = /usr/local/bin
XDOCDIR = /usr/man/man1
X
Xuntic:	untic.c
X	$(CC) $(CFLAGS) untic.c -o untic
X
Xlint:
X	lint untic.c
X
Xinstall:	untic
X	cp untic $(DESTDIR)/untic
X	strip $(DESTDIR)/untic
X	cp untic.1 $(DOCDIR)/untic.1
X
Xclean:
X	rm untic
SHAR_EOF
if test 254 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 254 characters)'
fi
fi
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
echo extracting "'README'"
sed 's/^X//' >README <<'SHAR_EOF'
Xuntic -- Decompile a "terminfo" terminal description file for System V.
X
XI wrote the following program, "untic", because I needed to make a terminal
Xdescription file which was just slightly different from one of the existing
Xterminal descriptions.
X
XThis program looks up the description directly from the compiled description
Xfile.  Thus it produces a file, which when compiled, generated exactly the
Xsame information as was in the original file.
X
XThis "shar" file contains the following files:
X	README		This file
X	untic.1		A (very simple) manual page
X	Makefile	A (very simple) make file
X	untic.c		The program
X
XI hope this program is of some use to people.
X
X			Dave Regan
X			21 May 1986
X			PO Box 601
X			Corvallis OR 97339
X			hplabs!hp-pcd!orstcs!regan	(I think)
SHAR_EOF
if test 763 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 763 characters)'
fi
fi
if test -f 'untic.1'
then
	echo shar: will not over-write existing file "'untic.1'"
else
echo extracting "'untic.1'"
sed 's/^X//' >untic.1 <<'SHAR_EOF'
X.TH UNTIC 1 Public Domain
X.SH NAME
Xuntic \- Uncompile terminfo terminal description files
X.SH SYNOPSIS
X.B untic
X.B terminal_name
X[
X.B . . .
X]
X.SH DESCRIPTION
X.B untic
Xconvert the terminfo file which corresponds to the specified terminal name
Xinto a file that can be processed by
X.B tic.
X.PP
XIf multiple terminal names are given, a terminal description is generated
Xfor each of the named terminals.
XThe output is written on standard output.
X.PP
XIt is wise to backup the original terminal description
X(from /usr/lib/terminfo)
Xbefore compiling the generated file.
X.SH EXAMPLES
XTo uncompile the terminal description for a "vt100", type:
X.RS
Xuntic vt100 >vt100
X.RE
XTo compile this generated file, you probably need root permissions and type:
X.RS
Xtic vt100
X.RE
X.SH NOTES
XIf new capabilities are added to the terminfo database,
Xthe
X.B untic
Xprogram will need to be modified.
XWith luck, the new entries will go at the end of the appropriate tables.
X.PP
XMost of the capabilities are in the tables in the order that the capabilites
Xare documented.
XThere are a few exceptions in the string variables.
X.PP
XThis program is placed into the public domain.
XThat means that you can do anything you want to with it.
X.SH BUGS
XNone known, but . . .
X.SH FILES
XThe terminal descriptions are stored in
X.B /usr/lib/terminfo/?/*
SHAR_EOF
if test 1304 -ne "`wc -c < 'untic.1'`"
then
	echo shar: error transmitting "'untic.1'" '(should have been 1304 characters)'
fi
fi
if test -f 'untic.c'
then
	echo shar: will not over-write existing file "'untic.c'"
else
echo extracting "'untic.c'"
sed 's/^X//' >untic.c <<'SHAR_EOF'
X/*
X * Untic.c -- Uncompile a terminfo file
X *
X * Usage:
X *	untic terminal_name . . .
X *
X * This program finds the terminal description in
X *	/usr/lib/terminfo/?/terminal_name
X * It then converts the information into an ASCII file suitable for
X * running into "tic".  The resulting file is written to standard output.
X *
X * Compile by:
X *	cc -O -o untic untic.c
X *
X * It is probably a good idea to ensure that the file produced will compile
X * to the original file before trusting "untic".
X *
X * Structure of terminfo file:
X *	short	magic number
X *	short	length of terminal names + NUL
X *	short	length of booleans
X *	short	length of numerics
X *	short	length of strings
X *	short	length of string table
X *	chars	NUL terminated terminal name
X *	chars	boolean flags for each of the possible booleans
X *	shorts	values for each of the possible numerics
X *	shorts	offsets (from start of strings) for each of the
X *		possible strings
X *	chars	NUL terminated strings for each of the defined strings
X *
X * Most of the variables are in the order that the documentation lists
X * them.  This is important, as the information is stored in the file
X * based upon the ordinal position of the variable.  Some of the string
X * variables are not in order.  Presumably, if they add more variables,
X * it will be to the end of the list, and not in the middle.
X *
X * This has been tested on
X *	Plexus P20 (M68010), System 5 Release 2 (I think)
X *
X * Bugs:
X *	The longest string capability is limited to 4096 bytes.  If a longer
X *	string is encountered, the program will do unpredicatable things.
X *	(Who uses strings that long anyway?)  The longest that the terminfo
X *	file can be is 4096 bytes anyway, so this isn't too big a problem.
X *
X * Credits:
X *	Written by Dave Regan
X *	orstcs!regan
X *	16 May 86
X *
X *	I disclaim that this program does anything useful.  It might also
X *	do accidental damage.  Backup your original terminfo files.
X *
X *	This program is public domain.  That means you can do anything
X *	you want with it.
X */
X
X
X#include <stdio.h>
X#ifdef QC
X#define	OPEN_MODE	"rb"	/* Mode used to open terminfo files	*/
X#define	void	int		/* Sigh . . .				*/
X#else		/* QC */
X#include <ctype.h>
X#define	OPEN_MODE	"r"	/* Mode used to open terminfo files	*/
X#endif		/* QC */
X#ifndef TRUE
X#define	TRUE	1
X#define	FALSE	0
X#endif		/* TRUE */
X
X#define	DEBUG	FALSE		/* TRUE/FALSE to enable debugging output */
X
X#ifdef BSD
X#define	TERMINFO_DIR	"/usr/static/sys5r2v2/usr/lib/terminfo"
X#endif		/* BSD */
X#ifndef TERMINFO_DIR
X#define	TERMINFO_DIR	"/usr/lib/terminfo"
X#endif		/* TERMINFO_DIR */
X
X
X#define	MAGIC	0x011A		/* Terminfo magic number		*/
X#define	MAXLINE	65		/* Longest emited line			*/
X#define	MAX_CAP	4096		/* Longest single capability		*/
X
Xextern	char *strcpy();
X
Xint	line_len;		/* Current length of line		*/
X
Xmain(argc, argv)
X  int	argc;			/* Number of paramters			*/
X  char	*argv[];		/* The parameters themselves		*/
X    {
X    char subdir[2];		/* Subdirectory name			*/
X    FILE *file;
X    extern FILE *fopen();
X
X#ifdef CPM
X    wildexp(&argc, &argv);
X#endif		/* CPM */
X
X    /* Change directory to the working directory			*/
X    (void)chdir(TERMINFO_DIR);
X
X    /* Go through the arguments						*/
X    subdir[1] = '\0';
X    if (argc == 1)
X	convert(stdin, "stdin");
X    else
X	{
X	while (--argc)
X	    {
X	    ++argv;
X	    subdir[0] = argv[0][0];
X	    (void)chdir(subdir);
X	    if ((file = fopen(*argv, OPEN_MODE)) == NULL)
X		{
X		perror(*argv);
X		}
X	    else
X		{
X		convert(file, *argv);
X		(void)fclose(file);
X		}
X	    (void)chdir("..");
X	    }
X	}
X    }
X
X
X/*
X * Addchar -- Add a character
X */
Xchar *
Xaddchar(cptr, ch)
X  char	*cptr;
X  int	ch;
X    {
X    char *addstr(), *addoctal();
X
X    if (ch == 0x1B)
X	return (addstr(cptr, "\\E"));
X    if (ch == '\n')
X	return (addstr(cptr, "\\n"));
X    if (ch == '\r')
X	return (addstr(cptr, "\\r"));
X    if (ch == '\t')
X	return (addstr(cptr, "\\t"));
X    if (ch == '\b')
X	return (addstr(cptr, "\\b"));
X    if (ch == '\f')
X	return (addstr(cptr, "\\f"));
X    if (ch == ' ')
X	return (addstr(cptr, "\\s"));
X    if (ch == '^')
X	return (addstr(cptr, "\\^"));
X    if (ch == '\\')
X	return (addstr(cptr, "\\\\"));
X    if (ch == ',')
X	return (addstr(cptr, "\\,"));
X    if (ch == ':')
X	return (addstr(cptr, "\\:"));
X    if (ch >= ('A' - '@') && ch <= ('Z' - '@'))
X	{
X	*cptr++ = '^';
X	*cptr++ = ch + '@';
X	return (cptr);
X	}
X#ifdef notdef
X    /*
X     * Did you know that \r \n \f \t are NOT control characters
X     * as defined by "iscntrl" under BSD 4.2?  I find that
X     * rather odd.
X     */
X#endif		/* notdef */
X    if (iscntrl(ch) || isspace(ch) || ch > 0x7F)
X    	return (addoctal(cptr, ch));
X    *cptr++ = ch;
X    return (cptr);
X    }
X
X
X/*
X * Addoctal -- Add an octal character
X *
X * Use sprintf just in case "0" through "7" are not contiguous.  Some
X * machines are weird.
X */
Xchar *
Xaddoctal(cptr, ch)
X  char	*cptr;
X  int	ch;
X    {
X    char *addstr();
X
X    ch &= 0xFF;
X
X    if (ch == 0x80)
X	return (addstr(cptr, "\\0"));
X    (void)sprintf(cptr, "\\%03o", ch);
X    while (*cptr != '\0')
X	cptr++;
X    return (cptr);
X    }
X
X
X/*
X * Addstr -- Add a string to the capability
X */
Xchar *
Xaddstr(cptr, str)
X  char	*cptr, *str;
X    {
X    while (*str)
X	*cptr++ = *str++;
X    return (cptr);
X    }
X
X
X/*
X * Convert -- Do the actual conversion
X */
Xconvert(file, name)
X  FILE	*file;		/* The file with the compiled information	*/
X  char	*name;		/* Printable version of the filename		*/
X    {
X    int	ch, val, i, j, fail;
X    int name_length, bool_length, num_length, str_length, s_length;
X    char capability[MAX_CAP+1], *cptr, *addchar();
X
X    static char *booleans[] =	/* Names of boolean variables, in order	*/
X	{ "bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km",
X	  "hs", "in", "da", "db", "mir", "msgr", "os", "eslok", "xt",
X	  "hz", "ul", "xon" };
X    static char *numerics[] =	/* Names of numeric variables, in order	*/
X	{ "cols", "it", "lines", "lm", "xmc", "pb", "vt", "wsl" };
X    static char *strings[] =	/* Names of string variables, not in strict
X				   order.  Makes things a little harder	*/
X	{ "cbt", "bel", "cr", "csr", "tbc", "clear", "el", "ed", "hpa",
X	  "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup",
X	  "cnorm", "cuf1", "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl",
X	  "hd", "smacs", "blink", "bold", "smcup", "smdc", "dim", "smir",
X	  "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", 
X	  "rmcup", "rmdc", "rmir", "rmso", "rmul", "flash", "ff", "fsl",
X	  "is1", "is2", "is3", "if", "ich1", "il1", "ip", "kbs", "ktbc",
X	  "kclr", "kctab", "kdch1", "kdl1", "kcud1", "krmir", "kel", "ked",
X	  "kf0", "kf1", "kf10", "kf2", "kf3", "kf4", "kf5", "kf6", "kf7",
X	  "kf8", "kf9", "khome", "kich1", "kil1", "kcub1", "kll", "knp",
X	  "kpp", "kcuf1", "kind", "kri", "khts", "kcuu1", "rmkx", "smkx", 
X	  "lf0", "lf1", "lf10", "lf2", "lf3", "lf4", "lf5", "lf6", "lf7",
X	  "lf8", "lf9", "rmm", "smm", "nel", "pad", "dch", "dl", "cud",
X	  "ich", "indn", "il", "cub", "cuf", "rin", "cuu", "pfkey", "pfloc",
X	  "pfx", "mc0", "mc4", "mc5", "rep", "rs1", "rs2", "rs3", "rf",
X	  "rc", "vpa", "sc", "ind", "ri", "sgr", "hts", "wind", "ht", "tsl",
X	  "uc", "hu", "iprog", "ka1", "ka3", "kb2", "kc1", "kc3", "mc5p"
X#ifdef HPUX5
X	  , "meml", "memu"
X#endif
X	  };
X    int str_cap[sizeof(strings) / sizeof(char *)];
X
X    /* Check the magic number out					*/
X    if (get2(file) != MAGIC)
X	{
X	fprintf(stderr, "\"%s\" is not a terminfo file\n", name);
X	return;
X	}
X
X    /* Get the rest of the header information				*/
X    name_length = get2(file);	/* Get the length of the terminal names	*/
X    bool_length = get2(file);	/* Get the length of the booleans	*/
X    num_length = get2(file);	/* Get the length of the numerics	*/
X    str_length = get2(file);	/* Get the length of the strings	*/
X    s_length = get2(file);	/* Get the length of the string tables	*/
X
X    /* Check for too many data items					*/
X    fail = FALSE;
X    if (bool_length > (sizeof(booleans) / sizeof(char *)))
X	{
X	fprintf(stderr, "Boolean variables have been added to terminfo.\n");
X	fail = TRUE;
X	}
X    if (num_length > (sizeof(numerics) / sizeof(char *)))
X	{
X	fprintf(stderr, "Numeric variables have been added to terminfo.\n");
X	fail = TRUE;
X	}
X    if (str_length > (sizeof(strings) / sizeof(char *)))
X	{
X	fprintf(stderr, "String variables have been added to terminfo.\n");
X	fail = TRUE;
X	}
X    if (fail)
X	{
X	fprintf(stderr,
X"Update the \"untic\" program.  Use \"xxx\" if needed.  Good luck.\n");
X	return;
X	}
X
X    /* Time to get real information					*/
X    while ((ch = getc(file)) != '\0' && ch != EOF)
X	putchar(ch);
X    printf(",\n\t");
X
X    /* Send out the non-null boolean variables				*/
X    line_len = 0;
X    for (i = 0; i < bool_length; i++)
X	{
X	if ((ch = getc(file)) != 0)
X	    emit(booleans[i]);
X	}
X
X    /* The rest of the file is on a 16 bit boundary, so adjust the file	*/
X    if ((name_length + bool_length) & 0x01)
X	(void)getc(file);
X
X    /* Get the numeric variables					*/
X    for (i = 0; i < num_length; i++)
X	{
X	if ((val = get2(file)) != 0xFFFF)
X	    {
X	    (void)sprintf(capability, "%s#%d", numerics[i], val);
X	    emit(capability);
X	    }
X	}
X
X    /* Get the string variables offsets					*/
X    for (i = 0; i < str_length; i++)
X	str_cap[i] = get2(file);
X
X    /* Get the string variables themselves				*/
X    for (i = 0; i < s_length; i++)
X	{
X	for (j = 0; j < str_length; j++)	/* Find the name	*/
X	    if (str_cap[j] == i)
X		break;
X#if DEBUG
X	if (j >= str_length)
X	    fprintf(stderr, "Cannot find address %d\n", i);
X#endif		/* DEBUG */
X	(void)strcpy(capability, strings[j]);
X	cptr = &capability[strlen(capability)];
X	*cptr++ = '=';
X	for (; (ch = getc(file)) != '\0' && ch != EOF; i++)
X	    cptr = addchar(cptr, ch);
X	*cptr = '\0';
X	emit(capability);
X	}
X
X    printf("\n\n");
X    }
X
X
X/*
X * Emit -- Emit the string
X *
X * Emit the given string, and append a comma.  If the line gets too long,
X * send out a newline and a tab.
X */
Xemit(str)
X  char	*str;		/* String to emit				*/
X    {
X    if ((line_len += strlen(str) + 2) > MAXLINE)
X	{
X	line_len = strlen(str) + 2;
X	printf("\n\t");
X	}
X    printf("%s, ", str);
X    }
X
X
X/*
X * Get2 -- Get a two byte number
X */
Xget2(file)
X  FILE *file;		/* The file with the compiled information	*/
X    {
X    short temp;
X
X    temp = getc(file) & 0xFF;
X    return (temp + (getc(file) << 8));
X    }
X
X
X#ifdef CPM
Xchdir(str)
X  char	*str;
X    {
X    }
X
Xperror(str)
X  char	*str;
X    {
X    fprintf(stderr, "Cannot open \"%s\"\n", str);
X    }
X#endif		/* CPM */
SHAR_EOF
if test 10385 -ne "`wc -c < 'untic.c'`"
then
	echo shar: error transmitting "'untic.c'" '(should have been 10385 characters)'
fi
fi
# end of shell archive
exit 0
-- 
Mark H. Colburn             UUCP: ihnp4!meccts!ems!mark
EMS/McGraw-Hill              ATT: (612) 829-8200
9855 West 78th Street
Eden Prairie, MN  55344