PD Terminfo/Curses (part 4 of 11)

sources at genrad.UUCP sources at genrad.UUCP
Tue Dec 18 03:19:51 AEST 1984


This is part of a distribution of a public domain version of terminfo/curses
It is a rather large distribution, so I have broken it up into 11 modules
(each less than 64K long.) Each shar format module should end with the line
"exit".  This code is completely public domain, originally written by Pavel
Curtis of Cornell University.  This version has some small improvements and
bug fixes.

This unit contains:

	The terminfo compiler (actually two header files are missing - they
	will be supplied in the next module).

Part 5 will contain the rest of the headers, the Makefile, and some
awk scripts for transforming the sources when the Caps file changes.
----------------- cut here ----------------
: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
if test ! -d =src
then
    echo 'Making directory "=src"'
    mkdir =src
fi
echo 'x - =src/comp_captab.c'
sed 's/^X//' <<'//go.sysin dd *' >=src/comp_captab.c
X/*
 *	comp_captab.c -- The names of the capabilities in a form ready for
 *		         the making of a hash table for the compiler.
 *
 */


#include "compiler.h"
#include "term.h"


struct name_table_entry	cap_table[] =
{
	0,           "bw",	BOOLEAN,	  0,
	0,           "am",	BOOLEAN,	  1,
	0,          "xsb",	BOOLEAN,	  2,
	0,          "xhp",	BOOLEAN,	  3,
	0,         "xenl",	BOOLEAN,	  4,
	0,           "eo",	BOOLEAN,	  5,
	0,           "gn",	BOOLEAN,	  6,
	0,           "hc",	BOOLEAN,	  7,
	0,           "km",	BOOLEAN,	  8,
	0,           "hs",	BOOLEAN,	  9,
	0,           "in",	BOOLEAN,	 10,
	0,           "da",	BOOLEAN,	 11,
	0,           "db",	BOOLEAN,	 12,
	0,          "mir",	BOOLEAN,	 13,
	0,         "msgr",	BOOLEAN,	 14,
	0,           "os",	BOOLEAN,	 15,
	0,        "eslok",	BOOLEAN,	 16,
	0,           "xt",	BOOLEAN,	 17,
	0,           "hz",	BOOLEAN,	 18,
	0,           "ul",	BOOLEAN,	 19,
	0,          "xon",	BOOLEAN,	 20,
	0,         "cols",	NUMBER,		  0,
	0,           "it",	NUMBER,		  1,
	0,        "lines",	NUMBER,		  2,
	0,           "lm",	NUMBER,		  3,
	0,          "xmc",	NUMBER,		  4,
	0,           "pb",	NUMBER,		  5,
	0,           "vt",	NUMBER,		  6,
	0,          "wsl",	NUMBER,		  7,
	0,         "nlab",	NUMBER,		  8,
	0,           "lh",	NUMBER,		  9,
	0,           "lw",	NUMBER,		 10,
	0,          "cbt",	STRING,		  0,
	0,          "bel",	STRING,		  1,
	0,           "cr",	STRING,		  2,
	0,          "csr",	STRING,		  3,
	0,          "tbc",	STRING,		  4,
	0,        "clear",	STRING,		  5,
	0,           "el",	STRING,		  6,
	0,           "ed",	STRING,		  7,
	0,          "hpa",	STRING,		  8,
	0,           "CC",	STRING,		  9,
	0,          "cup",	STRING,		 10,
	0,         "cud1",	STRING,		 11,
	0,         "home",	STRING,		 12,
	0,        "civis",	STRING,		 13,
	0,         "cub1",	STRING,		 14,
	0,        "mrcup",	STRING,		 15,
	0,        "cnorm",	STRING,		 16,
	0,         "cuf1",	STRING,		 17,
	0,           "ll",	STRING,		 18,
	0,         "cuu1",	STRING,		 19,
	0,        "cvvis",	STRING,		 20,
	0,         "dch1",	STRING,		 21,
	0,          "dl1",	STRING,		 22,
	0,          "dsl",	STRING,		 23,
	0,           "hd",	STRING,		 24,
	0,        "smacs",	STRING,		 25,
	0,        "blink",	STRING,		 26,
	0,         "bold",	STRING,		 27,
	0,        "smcup",	STRING,		 28,
	0,         "smdc",	STRING,		 29,
	0,          "dim",	STRING,		 30,
	0,         "smir",	STRING,		 31,
	0,        "invis",	STRING,		 32,
	0,         "prot",	STRING,		 33,
	0,          "rev",	STRING,		 34,
	0,         "smso",	STRING,		 35,
	0,         "smul",	STRING,		 36,
	0,          "ech",	STRING,		 37,
	0,        "rmacs",	STRING,		 38,
	0,         "sgr0",	STRING,		 39,
	0,        "rmcup",	STRING,		 40,
	0,         "rmdc",	STRING,		 41,
	0,         "rmir",	STRING,		 42,
	0,         "rmso",	STRING,		 43,
	0,         "rmul",	STRING,		 44,
	0,        "flash",	STRING,		 45,
	0,           "ff",	STRING,		 46,
	0,          "fsl",	STRING,		 47,
	0,          "is1",	STRING,		 48,
	0,          "is2",	STRING,		 49,
	0,          "is3",	STRING,		 50,
	0,           "if",	STRING,		 51,
	0,         "ich1",	STRING,		 52,
	0,          "il1",	STRING,		 53,
	0,           "ip",	STRING,		 54,
	0,          "kbs",	STRING,		 55,
	0,         "ktbc",	STRING,		 56,
	0,         "kclr",	STRING,		 57,
	0,        "kctab",	STRING,		 58,
	0,        "kdch1",	STRING,		 59,
	0,         "kdl1",	STRING,		 60,
	0,        "kcud1",	STRING,		 61,
	0,        "krmir",	STRING,		 62,
	0,          "kel",	STRING,		 63,
	0,          "ked",	STRING,		 64,
	0,          "kf0",	STRING,		 65,
	0,          "kf1",	STRING,		 66,
	0,         "kf10",	STRING,		 67,
	0,          "kf2",	STRING,		 68,
	0,          "kf3",	STRING,		 69,
	0,          "kf4",	STRING,		 70,
	0,          "kf5",	STRING,		 71,
	0,          "kf6",	STRING,		 72,
	0,          "kf7",	STRING,		 73,
	0,          "kf8",	STRING,		 74,
	0,          "kf9",	STRING,		 75,
	0,        "khome",	STRING,		 76,
	0,        "kich1",	STRING,		 77,
	0,         "kil1",	STRING,		 78,
	0,        "kcub1",	STRING,		 79,
	0,          "kll",	STRING,		 80,
	0,          "knp",	STRING,		 81,
	0,          "kpp",	STRING,		 82,
	0,        "kcuf1",	STRING,		 83,
	0,         "kind",	STRING,		 84,
	0,          "kri",	STRING,		 85,
	0,         "khts",	STRING,		 86,
	0,        "kcuu1",	STRING,		 87,
	0,         "rmkx",	STRING,		 88,
	0,         "smkx",	STRING,		 89,
	0,          "lf0",	STRING,		 90,
	0,          "lf1",	STRING,		 91,
	0,         "lf10",	STRING,		 92,
	0,          "lf2",	STRING,		 93,
	0,          "lf3",	STRING,		 94,
	0,          "lf4",	STRING,		 95,
	0,          "lf5",	STRING,		 96,
	0,          "lf6",	STRING,		 97,
	0,          "lf7",	STRING,		 98,
	0,          "lf8",	STRING,		 99,
	0,          "lf9",	STRING,		100,
	0,          "rmm",	STRING,		101,
	0,          "smm",	STRING,		102,
	0,          "nel",	STRING,		103,
	0,          "pad",	STRING,		104,
	0,          "dch",	STRING,		105,
	0,           "dl",	STRING,		106,
	0,          "cud",	STRING,		107,
	0,          "ich",	STRING,		108,
	0,         "indn",	STRING,		109,
	0,           "il",	STRING,		110,
	0,          "cub",	STRING,		111,
	0,          "cuf",	STRING,		112,
	0,          "rin",	STRING,		113,
	0,          "cuu",	STRING,		114,
	0,        "pfkey",	STRING,		115,
	0,        "pfloc",	STRING,		116,
	0,          "pfx",	STRING,		117,
	0,          "mc0",	STRING,		118,
	0,          "mc4",	STRING,		119,
	0,          "mc5",	STRING,		120,
	0,          "rep",	STRING,		121,
	0,          "rs1",	STRING,		122,
	0,          "rs2",	STRING,		123,
	0,          "rs3",	STRING,		124,
	0,           "rf",	STRING,		125,
	0,           "rc",	STRING,		126,
	0,          "vpa",	STRING,		127,
	0,           "sc",	STRING,		128,
	0,          "ind",	STRING,		129,
	0,           "ri",	STRING,		130,
	0,          "sgr",	STRING,		131,
	0,          "hts",	STRING,		132,
	0,         "wind",	STRING,		133,
	0,           "ht",	STRING,		134,
	0,          "tsl",	STRING,		135,
	0,           "uc",	STRING,		136,
	0,           "hu",	STRING,		137,
	0,        "iprog",	STRING,		138,
	0,          "ka1",	STRING,		139,
	0,          "ka3",	STRING,		140,
	0,          "kb2",	STRING,		141,
	0,          "kc1",	STRING,		142,
	0,          "kc3",	STRING,		143,
	0,         "mc5p",	STRING,		144,
	0,          "rmp",	STRING,		145,
	0,         "acsc",	STRING,		146,
	0,          "pln",	STRING,		147,
};

struct name_table_entry *cap_hash_table[360];

int	Hashtabsize = 360;
int	Captabsize = 180;


#if (BOOLCOUNT!=21)||(NUMCOUNT!=11)||(STRCOUNT!=148)
	--> term.h and comp_captab.c disagree about the <--
	--> numbers of booleans, numbers and/or strings <--
#endif
//go.sysin dd *
echo 'x - =src/comp_error.c'
sed 's/^X//' <<'//go.sysin dd *' >=src/comp_error.c
X/*********************************************************************
*                         COPYRIGHT NOTICE                           *
**********************************************************************
*        This software is copyright (C) 1982 by Pavel Curtis         *
*                                                                    *
*        Permission is granted to reproduce and distribute           *
*        this file by any means so long as no fee is charged         *
*        above a nominal handling fee and so long as this            *
*        notice is always included in the copies.                    *
*                                                                    *
*        Other rights are reserved except as explicitly granted      *
*        by written permission of the author.                        *
*                Pavel Curtis                                        *
*                Computer Science Dept.                              *
*                405 Upson Hall                                      *
*                Cornell University                                  *
*                Ithaca, NY 14853                                    *
*                                                                    *
*                Ph- (607) 256-4934                                  *
*                                                                    *
*                Pavel.Cornell at Udel-Relay   (ARPAnet)                *
*                decvax!cornell!pavel       (UUCPnet)                *
*********************************************************************/

X/*
 *	comp_error.c -- Error message routines
 *
 *  $Log:	RCS/comp_error.v $
 * Revision 2.1  82/10/25  14:45:31  pavel
 * Added Copyright Notice
 * 
 * Revision 2.0  82/10/24  15:16:32  pavel
 * Beta-one Test Release
 * 
 * Revision 1.3  82/08/23  22:29:31  pavel
 * The REAL Alpha-one Release Version
 * 
 * Revision 1.2  82/08/19  19:09:44  pavel
 * Alpha Test Release One
 * 
 * Revision 1.1  82/08/12  18:36:02  pavel
 * Initial revision
 * 
 *
 */

static char RCSid[] =
	"$Header:   RCS/comp_error.v  Revision 2.1  82/10/25  14:45:31  pavel  Exp$";

#include "compiler.h"

extern char *string_table;
extern short term_names;

warning(fmt, a1, a2, a3, a4, a5, a6)
char	*fmt, *a1, *a2, *a3, *a4, *a5, *a6;
{
    fprintf (stderr, "compile: Warning: near line %d: ", curr_line);
    fprintf (stderr, "terminal '%s', ", string_table+term_names);
    fprintf (stderr, fmt, a1, a2, a3, a4, a5, a6);
    fprintf (stderr, "\n");
}


err_abort(fmt, a1, a2, a3, a4, a5, a6)
char	*fmt, *a1, *a2, *a3, *a4, *a5, *a6;
{
    fprintf (stderr, "compile: Line %d: ", curr_line);
    fprintf (stderr, "terminal '%s', ", string_table+term_names);
    fprintf (stderr, fmt, a1, a2, a3, a4, a5, a6);
    fprintf (stderr, "\n");
    exit(1);
}


syserr_abort(fmt, a1, a2, a3, a4, a5, a6)
char	*fmt, *a1, *a2, *a3, *a4, *a5, *a6;
{
    fprintf (stderr, "PROGRAM ERROR: Line %d: ", curr_line);
    fprintf (stderr, "terminal '%s', ", string_table+term_names);
    fprintf (stderr, fmt, a1, a2, a3, a4, a5, a6);
    fprintf (stderr, "\n");
    abort();
}
//go.sysin dd *
echo 'x - =src/comp_hash.c'
sed 's/^X//' <<'//go.sysin dd *' >=src/comp_hash.c
X/*********************************************************************
*                         COPYRIGHT NOTICE                           *
**********************************************************************
*        This software is copyright (C) 1982 by Pavel Curtis         *
*                                                                    *
*        Permission is granted to reproduce and distribute           *
*        this file by any means so long as no fee is charged         *
*        above a nominal handling fee and so long as this            *
*        notice is always included in the copies.                    *
*                                                                    *
*        Other rights are reserved except as explicitly granted      *
*        by written permission of the author.                        *
*                Pavel Curtis                                        *
*                Computer Science Dept.                              *
*                405 Upson Hall                                      *
*                Cornell University                                  *
*                Ithaca, NY 14853                                    *
*                                                                    *
*                Ph- (607) 256-4934                                  *
*                                                                    *
*                Pavel.Cornell at Udel-Relay   (ARPAnet)                *
*                decvax!cornell!pavel       (UUCPnet)                *
*********************************************************************/

X/*
 *	comp_hash.c --- Routines to deal with the hashtable of capability
 *			names.
 *
 *  $Log:	RCS/comp_hash.v $
 * Revision 2.1  82/10/25  14:45:34  pavel
 * Added Copyright Notice
 * 
 * Revision 2.0  82/10/24  15:16:34  pavel
 * Beta-one Test Release
 * 
 * Revision 1.3  82/08/23  22:29:33  pavel
 * The REAL Alpha-one Release Version
 * 
 * Revision 1.2  82/08/19  19:09:46  pavel
 * Alpha Test Release One
 * 
 * Revision 1.1  82/08/12  18:36:23  pavel
 * Initial revision
 * 
 *
 */

static char RCSid[] =
	"$Header:   RCS/comp_hash.v  Revision 2.1  82/10/25  14:45:34  pavel  Exp$";

#include "compiler.h"
#include "term.h"



X/*
 *	make_hash_table()
 *
 *	Takes the entries in cap_table[] and hashes them into cap_hash_table[]
 *	by name.  There are Captabsize entries in cap_table[] and Hashtabsize
 *	slots in cap_hash_table[].
 *
 */

make_hash_table()
{
	int	i;
	int	hashvalue;
	int	collisions = 0;

	for (i=0; i < Captabsize; i++)
	{
	    hashvalue = hash_function(cap_table[i].nte_name);       
	    DEBUG(9, "%d\n", hashvalue);

	    if (cap_hash_table[hashvalue] != (struct name_table_entry *) 0)
		collisions++;

	    cap_table[i].nte_link = cap_hash_table[hashvalue];
	    cap_hash_table[hashvalue] = &cap_table[i];
	}

	DEBUG(3, "Hash table complete\n%d collisions ", collisions);
	DEBUG(3, "out of %d entries\n", Captabsize);
}



X/*
 *	int hash_function(string)
 *
 *	Computes the hashing function on the given string.
 *
 *	The current hash function is the sum of each consectutive pair
 *	of characters, taken as two-byte integers, mod Hashtabsize.
 *
 */

static
int
hash_function(string)
char	*string;
{
	long	sum = 0;

	while (*string)
	{
	    sum += *string + (*(string + 1) << 8);
	    string++;
	}

	return (sum % Hashtabsize);
}



X/*
 *	struct name_table_entry *
 *	find_entry(string)
 *
 *	Finds the entry for the given string in the hash table if present.
 *	Returns a pointer to the entry in the table or 0 if not found.
 *
 */

struct name_table_entry *
find_entry(string)
char	*string;
{
	int	hashvalue;
	struct name_table_entry	*ptr;

	hashvalue = hash_function(string);

	ptr = cap_hash_table[hashvalue];

	while (ptr != (struct name_table_entry *) 0  &&
			       	           strcmp(ptr->nte_name, string) != 0)
	    ptr = ptr->nte_link;

	return (ptr);
}
//go.sysin dd *
echo 'x - =src/comp_main.c'
sed 's/^X//' <<'//go.sysin dd *' >=src/comp_main.c
X/*********************************************************************
*                         COPYRIGHT NOTICE                           *
**********************************************************************
*        This software is copyright (C) 1982 by Pavel Curtis         *
*                                                                    *
*        Permission is granted to reproduce and distribute           *
*        this file by any means so long as no fee is charged         *
*        above a nominal handling fee and so long as this            *
*        notice is always included in the copies.                    *
*                                                                    *
*        Other rights are reserved except as explicitly granted      *
*        by written permission of the author.                        *
*                Pavel Curtis                                        *
*                Computer Science Dept.                              *
*                405 Upson Hall                                      *
*                Cornell University                                  *
*                Ithaca, NY 14853                                    *
*                                                                    *
*                Ph- (607) 256-4934                                  *
*                                                                    *
*                Pavel.Cornell at Udel-Relay   (ARPAnet)                *
*                decvax!cornell!pavel       (UUCPnet)                *
*********************************************************************/

X/*
 *	comp_main.c --- Main program for terminfo compiler
 *
 *  $Log:	RCS/comp_main.v $
 * Revision 2.1  82/10/25  14:45:37  pavel
 * Added Copyright Notice
 * 
 * Revision 2.0  82/10/24  15:16:37  pavel
 * Beta-one Test Release
 * 
 * Revision 1.3  82/08/23  22:29:36  pavel
 * The REAL Alpha-one Release Version
 * 
 * Revision 1.2  82/08/19  19:09:49  pavel
 * Alpha Test Release One
 * 
 * Revision 1.1  82/08/12  18:36:55  pavel
 * Initial revision
 * 
 *
 */

static char RCSid[] =
	"$Header:   RCS/comp_main.v  Revision 2.1  82/10/25  14:45:37  pavel  Exp$";


#include <sys/types.h>
#include <sys/stat.h>
#include "compiler.h"

char	*source_file = "/etc/terminfo";
char	*destination = SRCDIR;
char	*usage_string = "\tcompile [-v[n]] source-file\n";
char	check_only = 0;


main (argc, argv)
int	argc;
char	*argv[];
{
	int	i;
	int	argflag = FALSE;

	debug_level = 0;

	for (i=1; i < argc; i++)
	{
	    if (argv[i][0] == '-')
	    {
		switch (argv[i][1])
		{
		    case 'c':
			check_only = 1;
			break;

		    case 'v':
			debug_level = argv[i][2]  ?  atoi(&argv[i][2])  :  1;
			break;

		    default:
			fprintf(stderr, "%s: Unknown option. Usage is:\n\t%s\n",
						       argv[0], usage_string);
			exit(1);
		}
	    }
	    else if (argflag)
	    {
		fprintf(stderr, "%s: Too many file names.  Usage is:\n\t%s\n",
							argv[0], usage_string);
		exit(1);
	    }
	    else
	    {
		argflag = TRUE;
		source_file = argv[i];
	    }
	}

	init(argv[0]);
	make_hash_table();
	compile();

	exit(0);
}




X/*
 *	init(progname)
 *
 *	Miscelaneous initialisations
 *
 *	Open source file as standard input
 *	Check for access rights to destination directories
 *	Create any directories which don't exist.
 *
 */

init(progname)
char	*progname;
{
	struct stat	statbuf;
	char		*dirnames = "abcdefghijklmnopqrstuvwxyz0123456789";
	char		*getenv();
	char		dir[2];

	start_time = time(0);

	curr_line = 0;

	if (freopen(source_file, "r", stdin) == NULL)
	{
	    fprintf(stderr, "%s: Can't open %s\n", progname, source_file);
	    exit(1);
	}

	if (getenv("TERMINFO") != NULL)
	    destination = getenv("TERMINFO");

	if (access(destination, 7) < 0)
	{
	    fprintf(stderr, "%s: %s non-existant or permission denied\n",
							progname, destination);
	    exit(1);
	}

	if (chdir(destination) < 0)
	{
	    fprintf(stderr, "%s: %s is not a directory\n",
							progname, destination);
	    exit(1);
	}
	
	dir[1] = '\0';
	for (dir[0] = *dirnames; *dirnames != '\0'; dir[0] = *(++dirnames))
	{
	    if (stat(dir, &statbuf) < 0)
	    {
		mkdir(dir);
		chmod(dir, 0755);
	    }
	    else if (access(dir, 7) < 0)
	    {
		fprintf(stderr, "%s: %s/%s: Permission denied\n",
						    progname, destination, dir);
		exit(1);
	    }
	    else if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
	    {
		fprintf(stderr, "%s: %s/%s: Not a directory\n",
						    progname, destination, dir);
		exit(1);
	    }
	}
}



X/*
 *	mkdir(dirname)
 *
 *	forks and execs the mkdir program to create the given directory
 *
 */

mkdir(dirname)
char	*dirname;
{
	int	fork_rtn;
	int	status;

	fork_rtn = fork();

	switch (fork_rtn)
	{
	    case 0:		/* Child */
		execl("/bin/mkdir", "mkdir", dirname, 0);
		exit(1);

	    case -1:		/* Error */
		fprintf(stderr, "compile: SYSTEM ERROR!! Fork failed!!!\n");
		abort();

	    default:
		wait(&status);
		if (status != 0)
		    syserr_abort("mkdir returned bad status");
		break;
	}
}
//go.sysin dd *
echo 'x - =src/comp_parse.c'
sed 's/^X//' <<'//go.sysin dd *' >=src/comp_parse.c
X/*********************************************************************
*                         COPYRIGHT NOTICE                           *
**********************************************************************
*        This software is copyright (C) 1982 by Pavel Curtis         *
*                                                                    *
*        Permission is granted to reproduce and distribute           *
*        this file by any means so long as no fee is charged         *
*        above a nominal handling fee and so long as this            *
*        notice is always included in the copies.                    *
*                                                                    *
*        Other rights are reserved except as explicitly granted      *
*        by written permission of the author.                        *
*                Pavel Curtis                                        *
*                Computer Science Dept.                              *
*                405 Upson Hall                                      *
*                Cornell University                                  *
*                Ithaca, NY 14853                                    *
*                                                                    *
*                Ph- (607) 256-4934                                  *
*                                                                    *
*                Pavel.Cornell at Udel-Relay   (ARPAnet)                *
*                decvax!cornell!pavel       (UUCPnet)                *
*********************************************************************/

X/*
 *	comp_parse.c -- The high-level (ha!) parts of the compiler,
 *			that is, the routines which drive the scanner,
 *			etc.
 *
 *   $Log:	comp_parse.c,v $
 * Revision 3.1  84/12/13  11:19:32  john
 * Revisions by Mark Horton
 * 
 * Revision 2.1  82/10/25  14:45:43  pavel
 * Added Copyright Notice
 * 
 * Revision 2.0  82/10/24  15:16:39  pavel
 * Beta-one Test Release
 * 
 * Revision 1.3  82/08/23  22:29:39  pavel
 * The REAL Alpha-one Release Version
 * 
 * Revision 1.2  82/08/19  19:09:53  pavel
 * Alpha Test Release One
 * 
 * Revision 1.1  82/08/12  18:37:12  pavel
 * Initial revision
 * 
 *
 */

static char RCSid[] =
	"$Header: comp_parse.c,v 3.1 84/12/13 11:19:32 john Exp $";

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include "compiler.h"
#include "term.h"
#include "object.h"


char	*string_table;
int	next_free;	/* next free character in string_table */
int	table_size = 0; /* current string_table size */
short	term_names;	/* string table offset - current terminal */
int	part2 = 0;	/* set to allow old compiled defns to be used */
int	complete = 0;	/* 1 if entry done with no forward uses */

struct use_item
{
	long	offset;
	struct use_item	*fptr, *bptr;
};

struct use_header
{
	struct use_item	*head, *tail;
};

struct use_header	use_list = {NULL, NULL};
int			use_count = 0;

X/*
 *  The use_list is a doubly-linked list with NULLs terminating the lists:
 *
 *	   use_item    use_item    use_item
 *	  ---------   ---------   ---------
 *	  |       |   |       |   |       |   offset
 *        |-------|   |-------|   |-------|
 *	  |   ----+-->|   ----+-->|  NULL |   fptr
 *	  |-------|   |-------|   |-------|
 *	  |  NULL |<--+----   |<--+----   |   bptr
 *	  ---------   ---------   ---------
 *	  ^                       ^
 *	  |  ------------------   |
 *	  |  |       |        |   |
 *	  +--+----   |    ----+---+
 *	     |       |        |
 *	     ------------------
 *	       head     tail
 *	          use_list
 *
 */


X/*
 *	compile()
 *
 *	Main loop of the compiler.
 *
 *	get_token()
 *	if curr_token != NAMES
 *	    err_abort()
 *	while (not at end of file)
 *	    do an entry
 *
 */

compile()
{
	char			line[1024];
	int			token_type;
	struct use_item	*ptr;
	int			old_use_count;

	token_type = get_token();

	if (token_type != NAMES)
	    err_abort("File does not start with terminal names in column one");
	
	while (token_type != EOF)
	    token_type = do_entry(NULL);

	DEBUG(2, "Starting handling of forward USE's\n", "");

	for (part2=0; part2<2; part2++) {
	    old_use_count = -1;
	DEBUG(2, "\n\nPART %d\n\n", part2);
	    while (use_list.head != NULL  &&  old_use_count != use_count)
	    {
		old_use_count = use_count;
		for (ptr = use_list.tail; ptr != NULL; ptr = ptr->bptr)
		{
		    fseek(stdin, ptr->offset, 0);
		    reset_input();
		    if ((token_type = get_token()) != NAMES)
			syserr_abort("Token after a seek not NAMES");
		    (void) do_entry(ptr);
		    if (complete)
			dequeue(ptr);
		}

		for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr)
		{
		    fseek(stdin, ptr->offset, 0);
		    reset_input();
		    if ((token_type = get_token()) != NAMES)
			syserr_abort("Token after a seek not NAMES");
		    (void) do_entry(ptr);
		    if (complete)
			dequeue(ptr);
		}
		
		DEBUG(2, "Finished a pass through enqueued forward USE's\n", "");
	    }
	}

	if (use_list.head != NULL)
	{
	    fprintf(stderr, "\nError in following up use-links.  Either there is\n");
	    fprintf(stderr, "a loop in the links or they reference non-existant\n");
	    fprintf(stderr, "terminals.  The following is a list of the entries\n");
	    fprintf(stderr, "involved:\n\n");

	    for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr)
	    {
		fseek(stdin, ptr->offset, 0);
		fgets(line, 1024, stdin);
		fprintf(stderr, "%s", line);
	    }

	    exit(1);
	}
}

dump_list(str)
char *str;
{
	struct use_item *ptr;
	char line[512];

	fprintf(stderr, "dump_list %s\n", str);
	for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr)
	{
		fseek(stdin, ptr->offset, 0);
		fgets(line, 1024, stdin);
		fprintf(stderr, "ptr %x off %d bptr %x fptr %x str %s",
		ptr, ptr->offset, ptr->bptr, ptr->fptr, line);
	}
	fprintf(stderr, "\n");
}



X/*
 *	int
 *	do_entry(item_ptr)
 *
 *	Compile one entry.  During the first pass, item_ptr is NULL.  In pass
 *	two, item_ptr points to the current entry in the use_list.
 *
 *	found-forward-use = FALSE
 *	re-initialise internal arrays
 *	save names in string_table
 *	get_token()
 *	while (not EOF and not NAMES)
 *	    if found-forward-use
 *		do nothing
 *	    else if 'use'
 *		if handle_use() < 0
 *		    found-forward-use = TRUE
 *          else
 *	        check for existance and type-correctness
 *	        enter cap into structure
 *	        if STRING
 *	            save string in string_table
 *	    get_token()
 *      if ! found-forward-use
 *	    clear CANCELS out of the structure
 *	    dump compiled entry into filesystem
 *
 */

int
do_entry(item_ptr)
struct use_item	*item_ptr;
{
	long					entry_offset;
	int					i;
	register int				token_type;
	register struct name_table_entry	*entry_ptr;
	int					found_forward_use = FALSE;
	char					Booleans[BOOLCOUNT];
	short					Numbers[NUMCOUNT],
						Strings[STRCOUNT];

	init_structure(Booleans, Numbers, Strings);
	complete = 0;
	term_names = save_str(curr_token.tk_name);
	DEBUG(2, "Starting '%s'\n", curr_token.tk_name);
	entry_offset = curr_file_pos;

	for (token_type = get_token();
		token_type != EOF  &&  token_type != NAMES;
		token_type = get_token())
	{
	    if (found_forward_use)
		/* do nothing */ ;
	    else if (strcmp(curr_token.tk_name, "use") == 0)
	    {
		if (handle_use(item_ptr, entry_offset,
					Booleans, Numbers, Strings) < 0)
		    found_forward_use = TRUE;
	    }
	    else
	    {
		entry_ptr = find_entry(curr_token.tk_name);

		if (entry_ptr == NOTFOUND) {
		    warning("Unknown Capability - '%s'",
                                                          curr_token.tk_name);
		    continue;
		}


		if (token_type != CANCEL
                                        &&  entry_ptr->nte_type != token_type)
		    warning("Wrong type used for capability '%s'",
							  curr_token.tk_name);
		switch (token_type)
		{
		    case CANCEL:
			switch (entry_ptr->nte_type)
			{
			    case BOOLEAN:
				Booleans[entry_ptr->nte_index] = -2;
				break;

			    case NUMBER:
				Numbers[entry_ptr->nte_index] = -2;
				break;

			    case STRING:
				Strings[entry_ptr->nte_index] = -2;
				break;
			}
			break;
		
		    case BOOLEAN:
			Booleans[entry_ptr->nte_index] = TRUE;
			break;
		    
		    case NUMBER:
			Numbers[entry_ptr->nte_index] =
                                                      curr_token.tk_valnumber;
			break;

		    case STRING:
			Strings[entry_ptr->nte_index] =
                                            save_str(curr_token.tk_valstring);
			break;

		    default:
			warning("Unknown token type");
			panic_mode(',');
			continue;
		}
	    } /* end else cur_token.name != "use" */

	} /* endwhile (not EOF and not NAMES) */

	if (found_forward_use)
	    return(token_type);

	for (i=0; i < BOOLCOUNT; i++)
	{
	    if (Booleans[i] == -2)
		Booleans[i] = FALSE;
	}

	for (i=0; i < NUMCOUNT; i++)
	{
	    if (Numbers[i] == -2)
		Numbers[i] = -1;
	}

	for (i=0; i < STRCOUNT; i++)
	{
	    if (Strings[i] == -2)
		Strings[i] = -1;
	}

	dump_structure(term_names, Booleans, Numbers, Strings);

	complete = 1;
	return(token_type);
}




X/*
 *	enqueue(offset)
 *
 *      Put a record of the given offset onto the use-list.
 *
 */

enqueue(offset)
long	offset;
{
	struct use_item	*item;
	char			*malloc();

	item = (struct use_item *) malloc(sizeof(struct use_item));

	if (item == NULL)
	    syserr_abort("Not enough memory for use_list element");

	item->offset = offset;

	if (use_list.head != NULL)
	{
	    item->bptr = use_list.tail;
	    use_list.tail->fptr = item;
	    item->fptr = NULL;
	    use_list.tail = item;
	}
	else
	{
	    use_list.tail = use_list.head = item;
	    item->fptr = item->bptr = NULL;
	}

	use_count ++;
}




X/*
 *	dequeue(ptr)
 *
 *	remove the pointed-to item from the use_list
 *
 */

dequeue(ptr)
struct use_item	*ptr;
{
	if (ptr->fptr == NULL)
	    use_list.tail = ptr->bptr;
	else
	    (ptr->fptr)->bptr = ptr->bptr;

	if (ptr->bptr == NULL)
	    use_list.head = ptr->fptr;
	else
	    (ptr->bptr)->fptr = ptr->fptr;
	
	use_count --;
}



X/*
 *	dump_structure()
 *
 *	Save the compiled version of a description in the filesystem.
 *
 *	make a copy of the name-list
 *	break it up into first-name and all-but-last-name
 *	creat(first-name)
 *	write object information to first-name
 *	close(first-name)
 *      for each name in all-but-last-name
 *	    link to first-name
 *
 */

dump_structure(term_names, Booleans, Numbers, Strings)
short	term_names;
char	Booleans[];
short	Numbers[];
short	Strings[];
{
	struct stat	statbuf;
	FILE		*fp;
	char		name_list[1024];
	register char	*first_name, *other_names;
	register char	*ptr;
	char		filename[50];
	char		linkname[50];
	extern char check_only;

	strcpy(name_list, term_names + string_table);
	DEBUG(7, "Name list = '%s'\n", name_list);

	first_name = name_list;

	ptr = &name_list[strlen(name_list) - 1];
	other_names = ptr + 1;

	while (ptr > name_list  &&  *ptr != '|')
	    ptr--;

	if (ptr != name_list)
	{
	    *ptr = '\0';

	    for (ptr = name_list; *ptr != '\0'  &&  *ptr != '|'; ptr++)
		;
	    
	    if (*ptr == '\0')
		other_names = ptr;
	    else
	    {
		*ptr = '\0';
		other_names = ptr + 1;
	    }
	}

	if (check_only) {
		DEBUG(1, "Checked %s\n", first_name);
		return;
	}

	DEBUG(7, "First name = '%s'\n", first_name);
	DEBUG(7, "Other names = '%s'\n", other_names);

	if (strlen(first_name) > 100)
	    warning("'%s': terminal name too long.", first_name);

	check_name(first_name);

	sprintf(filename, "%c/%s", first_name[0], first_name);

	if (stat(filename, &statbuf) >= 0  &&  statbuf.st_mtime >= start_time)
	{
	    warning("'%s' defined in more than one entry.", first_name);
	    fprintf(stderr, "Entry being used is '%s'.\n",
			    (unsigned) term_names + string_table);
	}

	unlink(filename);
	fp = fopen(filename, "w");
	if (fp == NULL)
	{
	    perror(filename);
	    syserr_abort("Can't open %s/%s\n", destination, filename);
	}
	DEBUG(1, "Created %s\n", filename);

	if (write_object(fp, term_names, Booleans, Numbers, Strings) < 0)
	{
	    syserr_abort("Error in writing %s/%s", destination, filename);
	}
	fclose(fp);

	while (*other_names != '\0')
	{
	    ptr = other_names++;
	    while (*other_names != '|'  &&  *other_names != '\0')
		other_names++;

	    if (*other_names != '\0')
		*(other_names++) = '\0';

	    if (strlen(ptr) > 100)
	    {
		warning("'%s': terminal name too long.", ptr);
		continue;
	    }

	    sprintf(linkname, "%c/%s", ptr[0], ptr);

	    if (strcmp(filename, linkname) == 0)
	    {
		warning("Terminal name '%s' synonym for itself", first_name);
	    }
	    else if (stat(linkname, &statbuf) >= 0  &&
						statbuf.st_mtime >= start_time)
	    {
		warning("'%s' defined in more than one entry.", ptr);
		fprintf(stderr, "Entry being used is '%s'.\n",
			    (unsigned) term_names + string_table);
	    }
	    else
	    {
		unlink(linkname);
		if (link(filename, linkname) < 0)
		    syserr_abort("Can't link %s to %s", filename, linkname);
		DEBUG(1, "Linked %s\n", linkname);
	    }
	}
}




X/*
 *	int
 *	write_object(fp, term_names, Booleans, Numbers, Strings)
 *
 *	Write out the compiled entry to the given file.
 *	Return 0 if OK or -1 if not.
 *
 */

#define swap(x)		(((x >> 8) & 0377) + 256 * (x & 0377))

#define might_swap(x)	(must_swap()  ?  swap(x)  :  (x))


int
write_object(fp, term_names, Booleans, Numbers, Strings)
XFILE	*fp;
short	term_names;
char	Booleans[];
short	Numbers[];
short	Strings[];
{
    	struct header	header;
	char		*namelist;
	short		namelen;
	char		zero = '\0';
	int		i;

	namelist = term_names + string_table;
	namelen = strlen(namelist) + 1;

	if (must_swap())
	{
	    header.magic = swap(MAGIC);
	    header.name_size = swap(namelen);
	    header.bool_count = swap(BOOLCOUNT);
	    header.num_count = swap(NUMCOUNT);
	    header.str_count = swap(STRCOUNT);
	    header.str_size = swap(next_free);
	}
	else
	{
	    header.magic = MAGIC;
	    header.name_size = namelen;
	    header.bool_count = BOOLCOUNT;
	    header.num_count = NUMCOUNT;
	    header.str_count = STRCOUNT;
	    header.str_size = next_free;
	}

	if (fwrite(&header, sizeof(header), 1, fp) != 1
		||  fwrite(namelist, sizeof(char), namelen, fp) != namelen
		||  fwrite(Booleans, sizeof(char), BOOLCOUNT, fp) != BOOLCOUNT)
	    return(-1);
	
	if ((namelen+BOOLCOUNT) % 2 != 0  &&  fwrite(&zero, sizeof(char), 1, fp) != 1)
	    return(-1);

	if (must_swap())
	{
	    for (i=0; i < NUMCOUNT; i++)
		Numbers[i] = swap(Numbers[i]);
	    for (i=0; i < STRCOUNT; i++)
		Strings[i] = swap(Strings[i]);
	}

	if (fwrite(Numbers, sizeof(short), NUMCOUNT, fp) != NUMCOUNT
	       ||  fwrite(Strings, sizeof(short), STRCOUNT, fp) != STRCOUNT
	       ||  fwrite(string_table, sizeof(char), next_free, fp)
								  != next_free)
	    return(-1);

}



X/*
 *	check_name(name)
 *
 *	Generate an error message if given name does not begin with a
 *	digit or lower-case letter.
 *
 */

check_name(name)
char	*name;
{
	if (! isdigit(name[0])  &&  ! islower(name[0]))
	{
	    fprintf(stderr, "compile: Line %d: Illegal terminal name - '%s'\n",
							    curr_line, name);
	    fprintf(stderr,
			"Terminal names must start with lowercase or digit\n");
	    exit(1);
	}
}



X/*
 *	int
 *	save_str(string)
 *
 *	copy string into next free part of string_table, doing a realloc()
 *	if necessary.  return offset of beginning of string from start of
 *	string_table.
 *
 */

int
save_str(string)
char	*string;
{
	char	*malloc(), *realloc();
	int	old_next_free = next_free;

	if (table_size == 0)
	{
	    if ((string_table = malloc(1024)) == NULL)
		syserr_abort("Out of memory");
	    table_size = 1024;
	    DEBUG(5, "Made initial string table allocation.  Size is %d\n",
								    table_size);
	}

	while (table_size < next_free + strlen(string))
	{
	    if ((string_table = realloc(string_table, table_size + 1024))
									== NULL)
		syserr_abort("Out of memory");
	    table_size += 1024;
	    DEBUG(5, "Extended string table.  Size now %d\n", table_size);
	}

	strcpy(&string_table[next_free], string);
	DEBUG(7, "Saved string '%s' ", string);
	DEBUG(7, "at location %d\n", next_free);
	next_free += strlen(string) + 1;

	return(old_next_free);
}



X/*
 *	init_structure(Booleans, Numbers, Strings)
 *
 *	Initialise the given arrays
 *	Reset the next_free counter to zero.
 *
 */

init_structure(Booleans, Numbers, Strings)
char	Booleans[];
short	Numbers[], Strings[];
{
	int	i;

	for (i=0; i < BOOLCOUNT; i++)
	    Booleans[i] = FALSE;
	
	for (i=0; i < NUMCOUNT; i++)
	    Numbers[i] = -1;

	for (i=0; i < STRCOUNT; i++)
	    Strings[i] = -1;

	next_free = 0;
}



X/*
**	int
**	handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings)
**
**	Merge the compiled file whose name is in cur_token.valstring
**	with the current entry.
**
**		if it's a forward use-link
**	    	    if item_ptr == NULL
**		        queue it up for later handling
**	            else
**		        ignore it (we're already going through the queue)
**	        else it's a backward use-link
**	            read in the object file for that terminal
**	            merge contents with current structure
**
**	Returned value is 0 if it was a backward link and we
**	successfully read it in, -1 if a forward link.
*/

int
handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings)
long		entry_offset;
struct use_item	*item_ptr;
char		Booleans[];
short		Numbers[];
short		Strings[];
{
	struct term	use_term;
	struct stat	statbuf;
	char		filename[50];
        int             i;

	check_name(curr_token.tk_valstring);

	sprintf(filename, "%c/%s", curr_token.tk_valstring[0],
                                                     curr_token.tk_valstring);

	if (stat(filename, &statbuf) < 0  ||  part2==0 && statbuf.st_mtime < start_time)
	{
	    DEBUG(2, "Forward USE to %s", curr_token.tk_valstring);

 	    if (item_ptr == NULL)
 	    {
 		DEBUG(2, " (enqueued)\n", "");
 		enqueue(entry_offset);
 	    }
 	    else 
 		DEBUG(2, " (skipped)\n", "");
	    
	    return(-1);
	}
	else
	{
	    DEBUG(2, "Backward USE to %s\n", curr_token.tk_valstring);
	    if (read_entry(filename, &use_term) < 0)
		syserr_abort("Error in re-reading compiled file %s", filename);

	    for (i=0; i < BOOLCOUNT; i++)
	    {
		if (Booleans[i] == FALSE  &&  use_term.Booleans[i] == TRUE)
		    Booleans[i] = TRUE;
	    }

	    for (i=0; i < NUMCOUNT; i++)
	    {
		if (Numbers[i] == -1  &&  use_term.Numbers[i] != -1)
		    Numbers[i] = use_term.Numbers[i];
	    }

	    for (i=0; i < STRCOUNT; i++)
	    {
		if (Strings[i] == -1  &&  use_term.Strings[i] != (char *) 0)
		    Strings[i] = save_str(use_term.Strings[i]);
	    }

	}
}
//go.sysin dd *
echo 'x - =src/comp_scan.c'
sed 's/^X//' <<'//go.sysin dd *' >=src/comp_scan.c
X/*********************************************************************
*                         COPYRIGHT NOTICE                           *
**********************************************************************
*        This software is copyright (C) 1982 by Pavel Curtis         *
*                                                                    *
*        Permission is granted to reproduce and distribute           *
*        this file by any means so long as no fee is charged         *
*        above a nominal handling fee and so long as this            *
*        notice is always included in the copies.                    *
*                                                                    *
*        Other rights are reserved except as explicitly granted      *
*        by written permission of the author.                        *
*                Pavel Curtis                                        *
*                Computer Science Dept.                              *
*                405 Upson Hall                                      *
*                Cornell University                                  *
*                Ithaca, NY 14853                                    *
*                                                                    *
*                Ph- (607) 256-4934                                  *
*                                                                    *
*                Pavel.Cornell at Udel-Relay   (ARPAnet)                *
*                decvax!cornell!pavel       (UUCPnet)                *
*********************************************************************/

X/*
 *	comp_scan.c --- Lexical scanner for terminfo compiler.
 *
 *   $Log:	RCS/comp_scan.v $
 * Revision 2.1  82/10/25  14:45:55  pavel
 * Added Copyright Notice
 * 
 * Revision 2.0  82/10/24  15:17:12  pavel
 * Beta-one Test Release
 * 
 * Revision 1.3  82/08/23  22:30:03  pavel
 * The REAL Alpha-one Release Version
 * 
 * Revision 1.2  82/08/19  19:10:06  pavel
 * Alpha Test Release One
 * 
 * Revision 1.1  82/08/12  18:37:46  pavel
 * Initial revision
 * 
 *
 */

static char RCSid[] =
	"$Header:   RCS/comp_scan.v  Revision 2.1  82/10/25  14:45:55  pavel  Exp$";

#include <stdio.h>
#include <ctype.h>
#include "compiler.h"

#define iswhite(ch)	(ch == ' '  ||  ch == '\t')


static int	first_column;		/* See 'next_char()' below */



X/*
 *	int
 *	get_token()
 *
 *	Scans the input for the next token, storing the specifics in the
 *	global structure 'curr_token' and returning one of the following:
 *
 *		NAMES		A line beginning in column 1.  'name'
 *				will be set to point to everything up to
 *				but not including the first comma on the line.
 *		BOOLEAN		An entry consisting of a name followed by
 *				a comma.  'name' will be set to point to the
 *				name of the capability.
 *		NUMBER		An entry of the form
 *					name#digits,
 *				'name' will be set to point to the capability
 *				name and 'valnumber' to the number given.
 *		STRING		An entry of the form
 *					name=characters,
 *				'name' is set to the capability name and
 *				'valstring' to the string of characters, with
 *				input translations done.
 *		CANCEL		An entry of the form
 *					name@,
 *				'name' is set to the capability name and
 *				'valnumber' to -1.
 *		EOF		The end of the file has been reached.
 *
 */

int
get_token()
{
	long		number;
	int		type;
	register char	ch;
	static char	buffer[1024];
	register char	*ptr;
	int		dot_flag = FALSE;

	while ((ch = next_char()) == '\n'  ||  iswhite(ch))
	    ;
	
	if (ch == EOF)
	    type = EOF;
	else
	{
	    if (ch == '.')
	    {
		dot_flag = TRUE;

		while ((ch = next_char()) == ' '  ||  ch == '\t')
		    ;
	    }

	    if (! isalnum(ch))
	    {
		 warning("Illegal character - '%c'", ch);
		 panic_mode(',');
	    }

	    ptr = buffer;
	    *(ptr++) = ch;

	    if (first_column)
	    {
		while ((ch = next_char()) != ',' && ch != '\n' && ch != EOF)
		    *(ptr++) = ch;
		
		if (ch == EOF)
		    err_abort("Premature EOF");
		else if (ch == '\n') {
		    warning("Newline in middle of terminal name");
		    panic_mode(',');
		}
		
		*ptr = '\0';
		curr_token.tk_name = buffer;
		type = NAMES;
	    }
	    else
	    {
		ch = next_char();
		while (isalnum(ch))
		{
		    *(ptr++) = ch;
		    ch = next_char();
		}

		*ptr++ = '\0';
		switch (ch)
		{
		    case ',':
			curr_token.tk_name = buffer;
			type = BOOLEAN;
			break;

		    case '@':
			if (next_char() != ',')
			    warning("Missing comma");
			curr_token.tk_name = buffer;
			type = CANCEL;
			break;

		    case '#':
			number = 0;
			while (isdigit(ch = next_char()))
			    number = number * 10 + ch - '0';
			if (ch != ',')
			    warning("Missing comma");
			curr_token.tk_name = buffer;
			curr_token.tk_valnumber = number;
			type = NUMBER;
			break;
		    
		    case '=':
			ch = trans_string(ptr);
			if (ch != ',')
			    warning("Missing comma");
			curr_token.tk_name = buffer;
			curr_token.tk_valstring = ptr;
			type = STRING;
			break;

		    default:
			warning("Illegal character - '%c'", ch);
		}
	    } /* end else (first_column == FALSE) */
	} /* end else (ch != EOF) */

	if (dot_flag == TRUE)
	    DEBUG(8, "Commented out ", "");

	if (debug_level >= 8)
	{
	    fprintf(stderr, "Token: ");
	    switch (type)
	    {
		case BOOLEAN:
		    fprintf(stderr, "Boolean;  name='%s'\n",
                                                          curr_token.tk_name);
		    break;
		
		case NUMBER:
		    fprintf(stderr, "Number; name='%s', value=%d\n",
				curr_token.tk_name, curr_token.tk_valnumber);
		    break;
		
		case STRING:
		    fprintf(stderr, "String; name='%s', value='%s'\n",
				curr_token.tk_name, curr_token.tk_valstring);
		    break;
		
		case CANCEL:
		    fprintf(stderr, "Cancel; name='%s'\n",
                                                          curr_token.tk_name);
		    break;
		
		case NAMES:

		    fprintf(stderr, "Names; value='%s'\n",
                                                          curr_token.tk_name);
		    break;

		case EOF:
		    fprintf(stderr, "End of file\n");
		    break;

		default:
		    warning("Bad token type");
	    }
	}

	if (dot_flag == TRUE)		/* if commented out, use the next one */
	    type = get_token();

	return(type);
}



X/*
 *	char
 *	next_char()
 *
 *	Returns the next character in the input stream.  Comments and leading
 *	white space are stripped.  The global state variable 'firstcolumn' is
 *	set TRUE if the character returned is from the first column of the input
 * 	line.  The global variable curr_line is incremented for each new line.
 *	The global variable curr_file_pos is set to the file offset of the
 *	beginning of each line.
 *
 */

int	curr_column = -1;
char	line[1024];

char
next_char()
{
	char	*rtn_value;
	long	ftell();

	if (curr_column < 0  ||  curr_column > 1023  ||
						    line[curr_column] == '\0')
	{
	    do
	    {
		curr_file_pos = ftell(stdin);

		if ((rtn_value = fgets(line, 1024, stdin)) != NULL)
		    curr_line++;
	    } while (rtn_value != NULL  &&  line[0] == '#');

	    if (rtn_value == NULL)
		return (EOF);

	    curr_column = 0;
	    while (iswhite(line[curr_column]))
		curr_column++;
	}

	if (curr_column == 0  &&  line[0] != '\n')
	    first_column = TRUE;
	else
	    first_column = FALSE;
	
	return (line[curr_column++]);
}


backspace()
{
	curr_column--;

	if (curr_column < 0)
	    syserr_abort("Backspaced off beginning of line");
}



X/*
 *	reset_input()
 *
 *	Resets the input-reading routines.  Used after a seek has been done.
 *
 */

reset_input()
{
	curr_column = -1;
}



X/*
 *	char
 *	trans_string(ptr)
 *
 *	Reads characters using next_char() until encountering a comma, newline
 *	or end-of-file.  The returned value is the character which caused
 *	reading to stop.  The following translations are done on the input:
 *
 *		^X  goes to  ctrl-X (i.e. X & 037)
 *		{\E,\n,\r,\b,\t,\f}  go to
 *			{ESCAPE,newline,carriage-return,backspace,tab,formfeed}
 *		{\^,\\}  go to  {carat,backslash}
 *		\ddd (for ddd = up to three octal digits)  goes to
 *							the character ddd
 *
 *		\e == \E
 *		\0 == \200
 *
 */

char
trans_string(ptr)
char	*ptr;
{
	register int	count = 0;
	int		number;
	int		i;
        char		ch;

	while ((ch = next_char()) != ','  &&  ch != EOF)
	{
	    if (ch == '^')
	    {
		ch = next_char();
		if (ch == EOF)
		    err_abort("Premature EOF");

		if (! isprint(ch))
		{
		    warning("Illegal ^ character - '%c'", ch);
		}

		*(ptr++) = ch & 037;
	    }
	    else if (ch == '\\')
	    {
		ch = next_char();
		if (ch == EOF)
		    err_abort("Premature EOF");
		
		if (ch >= '0'  &&  ch <= '7')
		{
		    number = ch - '0';
		    for (i=0; i < 2; i++)
		    {
			ch = next_char();
			if (ch == EOF)
			    err_abort("Premature EOF");
			
			if (ch < '0'  ||  ch > '7')
			{
			    backspace();
			    break;
			}

			number = number * 8 + ch - '0';
		    }

		    if (number == 0)
			number = 0200;
		    *(ptr++) = (char) number;
		}
		else
		{
		    switch (ch)
		    {
			case 'E':
			case 'e':	*(ptr++) = '\033';	break;
			
			case 'l':
			case 'n':	*(ptr++) = '\n';	break;
			
			case 'r':	*(ptr++) = '\r';	break;
			
			case 'b':	*(ptr++) = '\008';	break;

			case 's':	*(ptr++) = ' ';		break;
			
			case 'f':	*(ptr++) = '\014';	break;
			
			case 't':	*(ptr++) = '\t';	break;
			
			case '\\':	*(ptr++) = '\\';	break;
			
			case '^':	*(ptr++) = '^';		break;

			case ',':	*(ptr++) = ',';		break;

			case ':':	*(ptr++) = ':';		break;

			default:
			    warning("Illegal character in \\ sequence");
			    *(ptr++) = ch;
		    } /* endswitch (ch) */
		} /* endelse (ch < '0' ||  ch > '7') */
	    } /* end else if (ch == '\\') */
	    else
	    {
		*(ptr++) = ch;
	    }
	    
	    count ++;

	    if (count > 500)
		warning("Very long string found.  Missing comma?");
	} /* end while */

	*ptr = '\0';

	return(ch);
}

X/*
 * Panic mode error recovery - skip everything until a "ch" is found.
 */
panic_mode(ch)
char ch;
{
	int c;

	for (;;) {
		c = next_char();
		if (c == ch)
			return;
		if (c == EOF);
			return;
	}
}
//go.sysin dd *
echo 'x - =src/compiler.h'
sed 's/^X//' <<'//go.sysin dd *' >=src/compiler.h
X/*********************************************************************
*                         COPYRIGHT NOTICE                           *
**********************************************************************
*        This software is copyright (C) 1982 by Pavel Curtis         *
*                                                                    *
*        Permission is granted to reproduce and distribute           *
*        this file by any means so long as no fee is charged         *
*        above a nominal handling fee and so long as this            *
*        notice is always included in the copies.                    *
*                                                                    *
*        Other rights are reserved except as explicitly granted      *
*        by written permission of the author.                        *
*                Pavel Curtis                                        *
*                Computer Science Dept.                              *
*                405 Upson Hall                                      *
*                Cornell University                                  *
*                Ithaca, NY 14853                                    *
*                                                                    *
*                Ph- (607) 256-4934                                  *
*                                                                    *
*                Pavel.Cornell at Udel-Relay   (ARPAnet)                *
*                decvax!cornell!pavel       (UUCPnet)                *
*********************************************************************/

X/*
 *	compiler.h - Global variables and structures for the terminfo
 *			compiler.
 *
 *  $Header:   RCS/compiler.v  Revision 2.1  82/10/25  14:46:04  pavel  Exp$
 *
 *  $Log:	RCS/compiler.v $
Revision 2.1  82/10/25  14:46:04  pavel
Added Copyright Notice

Revision 2.0  82/10/24  15:17:20  pavel
Beta-one Test Release

Revision 1.3  82/08/23  22:30:09  pavel
The REAL Alpha-one Release Version

Revision 1.2  82/08/19  19:10:10  pavel
Alpha Test Release One

Revision 1.1  82/08/12  18:38:11  pavel
Initial revision

 *
 */

#include <stdio.h>

#ifndef TRUE
#define TRUE	1
#define FALSE	0
#endif

#define SINGLE			/* only one terminal (actually none) */

char	*destination;		/* destination directory for object files */

long	start_time;		/* time at start of compilation */
long	time();

int	curr_line;		/* current line # in input */
long	curr_file_pos;		/* file offset of current line */

int	debug_level;		/* level of debugging output */

#define DEBUG(level, fmt, a1) \
		if (debug_level >= level)\
		    fprintf(stderr, fmt, a1);

	/*
	 *	These are the types of tokens returned by the scanner.
	 *	The first three are also used in the hash table of capability
	 *	names.  The scanner returns one of these values after loading
	 *	the specifics into the global structure curr_token.
	 *
	 */

#define BOOLEAN 0		/* Boolean capability */
#define NUMBER 1		/* Numeric capability */
#define STRING 2		/* String-valued capability */
#define CANCEL 3		/* Capability to be cancelled in following tc's */
#define NAMES  4		/* The names for a terminal type */

	/*
	 *	The global structure in which the specific parts of a
	 *	scanned token are returned.
	 *
	 */

struct token
{
	char	*tk_name;		/* name of capability */
	int	tk_valnumber;	/* value of capability (if a number) */
	char	*tk_valstring;	/* value of capability (if a string) */
};

struct token	curr_token;

	/*
	 *	The file comp_captab.c contains an array of these structures,
	 *	one per possible capability.  These are then made into a hash
	 *	table array of the same structures for use by the parser.
	 *
	 */

struct name_table_entry
{
	struct name_table_entry *nte_link;
	char	*nte_name;	/* name to hash on */
	int	nte_type;	/* BOOLEAN, NUMBER or STRING */
	short	nte_index;	/* index of associated variable in its array */
};

extern struct name_table_entry	cap_table[];
extern struct name_table_entry	*cap_hash_table[];

extern int	Captabsize;
extern int	Hashtabsize;

#define NOTFOUND	((struct name_table_entry *) 0)
	/*
	 *	Function types
	 *
	 */

struct name_table_entry	*find_entry();	/* look up entry in hash table */

char	next_char();
char	trans_string();
//go.sysin dd *
exit



More information about the Mod.sources mailing list