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