summaryrefslogtreecommitdiff
path: root/usr/src/cmd/tic
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/tic')
-rw-r--r--usr/src/cmd/tic/Makefile67
-rw-r--r--usr/src/cmd/tic/req.flg33
-rw-r--r--usr/src/cmd/tic/tic_captab.c57
-rw-r--r--usr/src/cmd/tic/tic_error.c191
-rw-r--r--usr/src/cmd/tic/tic_hash.c215
-rw-r--r--usr/src/cmd/tic/tic_main.c276
-rw-r--r--usr/src/cmd/tic/tic_parse.c904
-rw-r--r--usr/src/cmd/tic/tic_read.c296
-rw-r--r--usr/src/cmd/tic/tic_scan.c510
9 files changed, 2549 insertions, 0 deletions
diff --git a/usr/src/cmd/tic/Makefile b/usr/src/cmd/tic/Makefile
new file mode 100644
index 0000000000..0bc08a394f
--- /dev/null
+++ b/usr/src/cmd/tic/Makefile
@@ -0,0 +1,67 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1989,1996 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+
+PROG= tic
+
+OBJS= \
+ tic_captab.o \
+ tic_error.o \
+ tic_hash.o \
+ tic_main.o \
+ tic_parse.o \
+ tic_read.o \
+ tic_scan.o
+
+SRCS= $(OBJS:%.o=%.c)
+
+include ../Makefile.cmd
+
+LDLIBS += -lcurses
+CPPFLAGS += -I../../lib/libcurses/screen
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+$(POFILE): $(POFILES)
+ $(RM) $@
+ cat $(POFILES) > $@
+
+
+install: all $(ROOTPROG)
+
+clean:
+ $(RM) $(OBJS)
+
+lint: lint_SRCS
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/tic/req.flg b/usr/src/cmd/tic/req.flg
new file mode 100644
index 0000000000..0912843156
--- /dev/null
+++ b/usr/src/cmd/tic/req.flg
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+echo_file usr/src/lib/libcurses/screen/curses_inc.h
+echo_file usr/src/lib/libcurses/screen/compiler.h
+echo_file usr/src/lib/libcurses/screen/curshdr.h
+echo_file usr/src/lib/libcurses/screen/curses_wchar.h
+echo_file usr/src/lib/libcurses/screen/object.h
diff --git a/usr/src/cmd/tic/tic_captab.c b/usr/src/cmd/tic/tic_captab.c
new file mode 100644
index 0000000000..6ad8e0d547
--- /dev/null
+++ b/usr/src/cmd/tic/tic_captab.c
@@ -0,0 +1,57 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * comp_captab.c -- The names of the capabilities in a form ready for
+ * the making of a hash table for the compiler.
+ *
+ */
+
+
+#include "curses_inc.h"
+#include "compiler.h"
+
+
+struct name_table_entry cap_table[512];
+
+struct name_table_entry *cap_hash_table[360];
+
+int Hashtabsize = 360;
+int Captabsize = 0;
+int BoolCount = 0;
+int NumCount = 0;
+int StrCount = 0;
diff --git a/usr/src/cmd/tic/tic_error.c b/usr/src/cmd/tic/tic_error.c
new file mode 100644
index 0000000000..13bf098848
--- /dev/null
+++ b/usr/src/cmd/tic/tic_error.c
@@ -0,0 +1,191 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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@Udel-Relay(ARPAnet)
+ * decvax!cornell!pavel(UUCPnet)
+ */
+
+/*
+ * tic_error.c -- Error message routines
+ *
+ * $Log: RCS/tic_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
+ *
+ *
+ */
+
+#include <unistd.h>
+
+#include "compiler.h"
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+extern char *string_table;
+extern short term_names;
+extern char *progname;
+
+/* VARARGS1 */
+#ifdef __STDC__
+void
+warning(char *fmt, ...)
+#else
+warning(va_alist)
+va_dcl
+#endif
+{
+#ifndef __STDC__
+ register char *fmt;
+#endif
+ va_list args;
+
+#ifdef __STDC__
+ va_start(args, fmt);
+#else
+ va_start(args);
+ fmt = va_arg(args, char *);
+#endif
+ fprintf(stderr, "%s: Warning: near line %d: ", progname, curr_line);
+ if (string_table != NULL) {
+ fprintf(stderr, "terminal '%s', ", string_table+term_names);
+ }
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+}
+
+
+/* VARARGS1 */
+#ifdef __STDC__
+err_abort(char *fmt, ...)
+#else
+err_abort(va_alist)
+va_dcl
+#endif
+{
+#ifndef __STDC__
+ register char *fmt;
+#endif
+ va_list args;
+
+#ifdef __STDC__
+ va_start(args, fmt);
+#else
+ va_start(args);
+ fmt = va_arg(args, char *);
+#endif
+ fprintf(stderr, "%s: Line %d: ", progname, curr_line);
+ if (string_table != NULL) {
+ fprintf(stderr, "terminal '%s', ", string_table+term_names);
+ }
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ exit(1);
+}
+
+
+/* VARARGS1 */
+#ifdef __STDC__
+void
+syserr_abort(char *fmt, ...)
+#else
+syserr_abort(va_alist)
+va_dcl
+#endif
+{
+#ifndef __STDC__
+ register char *fmt;
+#endif
+ va_list args;
+
+#ifdef __STDC__
+ va_start(args, fmt);
+#else
+ va_start(args);
+ fmt = va_arg(args, char *);
+#endif
+ fprintf(stderr, "PROGRAM ERROR: Line %d: ", curr_line);
+ if (string_table != NULL) {
+ fprintf(stderr, "terminal '%s', ", string_table+term_names);
+ }
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "*** Possibly corrupted terminfo file ***\n");
+ va_end(args);
+ exit(1);
+}
diff --git a/usr/src/cmd/tic/tic_hash.c b/usr/src/cmd/tic/tic_hash.c
new file mode 100644
index 0000000000..093d2a036b
--- /dev/null
+++ b/usr/src/cmd/tic/tic_hash.c
@@ -0,0 +1,215 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+*************************************************************************
+* 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@Udel-Relay(ARPAnet) *
+* decvax!cornell!pavel(UUCPnet) *
+*********************************************************************** */
+
+/*
+ * 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
+ *
+ *
+ */
+
+#include "curses_inc.h"
+#include "compiler.h"
+
+
+
+/*
+ * 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[].
+ *
+ */
+
+void
+make_hash_table()
+{
+ int i;
+ int hashvalue;
+ int collisions = 0;
+
+ make_nte();
+ 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);
+ return;
+}
+
+/*
+ * Make the name_table_entry from the capnames.c set of tables.
+ */
+make_nte()
+{
+ register int i, n;
+ extern char *boolnames[], *numnames[], *strnames[];
+
+ n = 0;
+
+ for (i = 0; boolnames[i]; i++) {
+ cap_table[n].nte_link = NULL;
+ cap_table[n].nte_name = boolnames[i];
+ cap_table[n].nte_type = BOOLEAN;
+ cap_table[n].nte_index = i;
+ n++;
+ }
+ BoolCount = i;
+
+ for (i = 0; numnames[i]; i++) {
+ cap_table[n].nte_link = NULL;
+ cap_table[n].nte_name = numnames[i];
+ cap_table[n].nte_type = NUMBER;
+ cap_table[n].nte_index = i;
+ n++;
+ }
+ NumCount = i;
+
+ for (i = 0; strnames[i]; i++) {
+ cap_table[n].nte_link = NULL;
+ cap_table[n].nte_name = strnames[i];
+ cap_table[n].nte_type = STRING;
+ cap_table[n].nte_index = i;
+ n++;
+ }
+ StrCount = i;
+
+ Captabsize = n;
+}
+
+
+/*
+ * 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(char *string)
+{
+ long sum = 0;
+
+ while (*string) {
+ sum += *string + (*(string + 1) << 8);
+ string++;
+ }
+
+ return (sum % Hashtabsize);
+}
+
+
+
+/*
+ * 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(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);
+}
diff --git a/usr/src/cmd/tic/tic_main.c b/usr/src/cmd/tic/tic_main.c
new file mode 100644
index 0000000000..c5ddc9b6e7
--- /dev/null
+++ b/usr/src/cmd/tic/tic_main.c
@@ -0,0 +1,276 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996, by Sun Microsystems, Inc.
+ * All Rights reserved.
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+*************************************************************************
+* 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 Halli *
+* Cornell Universityi *
+* Ithaca, NY 14853 *
+* *
+* Ph- (607) 256-4934 *
+* *
+* Pavel.Cornell@Udel-Relay(ARPAnet) *
+* decvax!cornell!pavel(UUCPnet) *
+*********************************************************************** */
+
+/*
+ * 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
+ *
+ *
+ */
+
+
+#define EXTERN /* EXTERN=extern in other .c files */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "compiler.h"
+
+char *source_file = "./terminfo.src";
+char *destination = SRCDIR;
+char *usage_string = "[-v[n]] [-c] source-file\n";
+char check_only = 0;
+char *progname;
+
+extern void make_hash_table(); /* should be in a header file :-( */
+extern void compile(); /* should be in a header file :-( */
+extern void syserr_abort(); /* should be in a header file :-( */
+static void init();
+
+main(int argc, char *argv[])
+{
+ int i;
+ int argflag = FALSE;
+
+ debug_level = 0;
+ progname = argv[0];
+
+ umask(022);
+
+ 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: %s\n",
+ argv[0], progname, 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();
+ make_hash_table();
+ compile();
+
+ exit(0);
+
+ return(0);
+}
+
+/*
+ * init()
+ *
+ * Miscellaneous initializations
+ *
+ * Open source file as standard input
+ * Change directory to working terminfo directory.
+ *
+ */
+
+static void
+init()
+{
+ char *env = getenv("TERMINFO");
+
+ start_time = time((time_t *) 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 (env && *env)
+ destination = env;
+
+ if (check_only) {
+ DEBUG(1, "Would be working in %s\n", destination);
+ } else {
+ DEBUG(1, "Working in %s\n", destination);
+ }
+
+ if (access(destination, 7) < 0) {
+ fprintf(stderr, "%s: %s nonexistent 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);
+ }
+
+}
+
+/*
+ *
+ * check_dir(dirletter)
+ *
+ * Check for access rights to the destination directory.
+ * Create any directories which don't exist.
+ *
+ */
+
+void
+check_dir(char dirletter)
+{
+ struct stat64 statbuf;
+ static char dirnames[128];
+ static char dir[2] = " ";
+
+ if (dirnames[dirletter] == 0) {
+ dir[0] = dirletter;
+ if (stat64(dir, &statbuf) < 0) {
+ if (mkdir(dir, 0755) < 0)
+ syserr_abort("mkdir %s returned bad status", dir);
+ dirnames[dirletter] = 1;
+ } else if (access(dir, 7) < 0) {
+ fprintf(stderr, "%s: %s/%s: Permission denied\n",
+ progname, destination, dir);
+ perror(dir);
+ exit(1);
+ } else if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
+ fprintf(stderr, "%s: %s/%s: Not a directory\n",
+ progname, destination, dir);
+ perror(dir);
+ exit(1);
+ }
+ }
+ return;
+}
+
+#include <curses.h>
+#if (defined(SYSV) || defined(USG)) && !defined(SIGPOLL)
+/*
+ * mkdir(dirname, mode)
+ *
+ * forks and execs the mkdir program to create the given directory
+ *
+ */
+
+mkdir(dirname, mode)
+#ifdef __STDC__
+const
+#endif
+char *dirname;
+int mode;
+{
+ int fork_rtn;
+ int status;
+
+ fork_rtn = fork();
+
+ switch (fork_rtn) {
+ case 0: /* Child */
+ (void) execl("/bin/mkdir", "mkdir", dirname, (char *)0);
+ _exit(1);
+
+ case -1: /* Error */
+ fprintf(stderr, "%s: SYSTEM ERROR!! Fork failed!!!\n",
+ progname);
+ exit(1);
+
+ default:
+ (void) wait(&status);
+ if ((status != 0) || (chmod(dirname, mode) == -1))
+ return (-1);
+ return (0);
+ }
+}
+#endif
diff --git a/usr/src/cmd/tic/tic_parse.c b/usr/src/cmd/tic/tic_parse.c
new file mode 100644
index 0000000000..ebbc88dd50
--- /dev/null
+++ b/usr/src/cmd/tic/tic_parse.c
@@ -0,0 +1,904 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * *******************************************************************
+ * 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@Udel-Relay (ARPAnet) *
+ * decvax!cornell!pavel (UUCPnet) *
+ * ********************************************************************
+ */
+
+/*
+ * comp_parse.c -- The high-level (ha!) parts of the compiler,
+ * that is, the routines which drive the scanner,
+ * etc.
+ *
+ * $Log: RCS/comp_parse.v $
+ * 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
+ *
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "curses_inc.h"
+#include "compiler.h"
+#include "object.h"
+
+extern char check_only;
+extern char *progname;
+
+char *string_table;
+int next_free; /* next free character in string_table */
+unsigned 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;
+
+/*
+ * 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
+ *
+ */
+
+
+/*
+ * compile()
+ *
+ * Main loop of the compiler.
+ *
+ * get_token()
+ * if curr_token != NAMES
+ * err_abort()
+ * while (not at end of file)
+ * do an entry
+ *
+ */
+
+void
+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((struct use_item *)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 && !check_only) {
+ 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");
+}
+
+/*
+ * 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
+ * dump compiled entry into filesystem
+ *
+ */
+
+int
+do_entry(item_ptr)
+struct use_item *item_ptr;
+{
+ long entry_offset;
+ register int token_type;
+ register struct name_table_entry *entry_ptr;
+ int found_forward_use = FALSE;
+ short Booleans[MAXBOOLS],
+ Numbers[MAXNUMS],
+ Strings[MAXSTRINGS];
+
+ 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:
+ if (Booleans[entry_ptr->nte_index] == 0)
+ Booleans[entry_ptr->nte_index] = TRUE;
+ break;
+
+ case NUMBER:
+ if (Numbers[entry_ptr->nte_index] == -1)
+ Numbers[entry_ptr->nte_index] =
+ curr_token.tk_valnumber;
+ break;
+
+ case STRING:
+ if (Strings[entry_ptr->nte_index] == -1)
+ 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);
+
+ dump_structure(Booleans, Numbers, Strings);
+
+ complete = 1;
+ return (token_type);
+}
+
+/*
+ Change all cancellations to a non-entry.
+ For booleans, @ -> false
+ For nums, @ -> -1
+ For strings, @ -> -1
+
+ This only has to be done for entries which
+ have to be compatible with the pre-Vr3 format.
+*/
+#ifndef NOCANCELCOMPAT
+elim_cancellations(Booleans, Numbers, Strings)
+short Booleans[];
+short Numbers[];
+short Strings[];
+{
+ register int i;
+ 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;
+ }
+}
+#endif /* NOCANCELCOMPAT */
+/*
+ Change the cancellation signal from the -2 used internally to
+ the 2 used within the binary.
+*/
+change_cancellations(Booleans)
+short Booleans[];
+{
+ register int i;
+ for (i = 0; i < BoolCount; i++) {
+ if (Booleans[i] == -2)
+ Booleans[i] = 2;
+ }
+
+}
+
+/*
+ * enqueue(offset)
+ *
+ * Put a record of the given offset onto the use-list.
+ *
+ */
+
+enqueue(offset)
+long offset;
+{
+ struct use_item *item;
+
+ 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 ++;
+}
+
+/*
+ * 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 --;
+}
+
+/*
+ * invalid_term_name(name)
+ *
+ * Look for invalid characters in a term name. These include
+ * space, tab and '/'.
+ *
+ * Generate an error message if given name does not begin with a
+ * digit or letter, then exit.
+ *
+ * return TRUE if name is invalid.
+ *
+ */
+
+static int invalid_term_name(name)
+register char *name;
+{
+ int error = 0;
+ if (! isdigit(*name) && ! islower(*name) && ! isupper(*name))
+ error++;
+
+ for (; *name; name++)
+ if (isalnum(*name))
+ continue;
+ else if (isspace(*name) || (*name == '/'))
+ return (1);
+ if (error) {
+ fprintf(stderr, "%s: Line %d: Illegal terminal name - '%s'\n",
+ progname, curr_line, name);
+ fprintf(stderr,
+ "Terminal names must start with a letter or digit\n");
+ exit(1);
+ }
+ return (0);
+}
+
+/*
+ * 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
+ * if necessary
+ * clear CANCELS out of the structure
+ * creat(first-name)
+ * write object information to first-name
+ * close(first-name)
+ * for each valid name
+ * link to first-name
+ *
+ */
+
+dump_structure(Booleans, Numbers, Strings)
+short Booleans[];
+short Numbers[];
+short Strings[];
+{
+ struct stat64 statbuf;
+ FILE *fp;
+ char name_list[1024];
+ register char *first_name, *other_names, *cur_name;
+ char filename[128 + 2 + 1];
+ char linkname[128 + 2 + 1];
+ int len;
+ int alphastart = 0;
+ extern char *strchr(), *strrchr();
+
+ strcpy(name_list, term_names + string_table);
+ DEBUG(7, "Name list = '%s'\n", name_list);
+
+ first_name = name_list;
+ /* Set othernames to 1 past first '|' in the list. */
+ /* Null out that '|' in the process. */
+ other_names = strchr(first_name, '|');
+ if (other_names)
+ *other_names++ = '\0';
+
+ if (invalid_term_name(first_name))
+ warning("'%s': bad first term name.", first_name);
+
+
+ DEBUG(7, "First name = '%s'\n", first_name);
+ DEBUG(7, "Other names = '%s'\n", other_names ? other_names : "NULL");
+
+ if ((len = strlen(first_name)) > 128)
+ warning("'%s': terminal name too long.", first_name);
+ else if (len == 1)
+ warning("'%s': terminal name too short.", first_name);
+
+ check_dir(first_name[0]);
+
+ sprintf(filename, "%c/%s", first_name[0], first_name);
+
+ if (strlen(filename) > 16)
+ warning("'%s' filename too long, truncating to '%.16s'\n",
+ filename, filename);
+ if (stat64(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);
+ }
+
+ if (!check_only) {
+ unlink(filename);
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ perror(filename);
+ syserr_abort("Can't open %s/%s\n",
+ destination, filename);
+ }
+ DEBUG(1, "Created %.16s\n", filename);
+ } else DEBUG(1, "Would have created %.16s\n", filename);
+
+#ifndef NOCANCELCOMPAT
+ /* if there is no '+' in the name, eliminate */
+ /* cancellation markings. */
+ if (strchr(first_name, '+') == 0)
+ elim_cancellations(Booleans, Numbers, Strings);
+ else
+#endif /* NOCANCELCOMPAT */
+ change_cancellations(Booleans);
+
+ if (!check_only) {
+ if (write_object(fp, Booleans, Numbers, Strings) < 0) {
+ syserr_abort("Error in writing %s/%s",
+ destination, filename);
+ }
+ fclose(fp);
+ }
+
+ alphastart = isalpha(first_name[0]);
+
+ while (other_names) {
+ cur_name = other_names;
+ other_names = strchr(cur_name, '|');
+ if (other_names)
+ *other_names++ = '\0';
+ if (*cur_name == '\0')
+ continue;
+
+ if ((len = strlen(cur_name)) > 128) {
+ warning("'%s': terminal name too long.", cur_name);
+ continue;
+ } else if (len == 1) {
+ warning("'%s': terminal name too short.", first_name);
+ continue;
+ }
+
+ if (invalid_term_name(cur_name)) {
+ if (other_names)
+ warning("'%s': bad term name found in list.",
+ cur_name);
+ continue;
+ }
+
+ check_dir(cur_name[0]);
+
+ sprintf(linkname, "%c/%s", cur_name[0], cur_name);
+
+ if (strlen(linkname) > 16) {
+ if (other_names) {
+ warning(
+"'%s' linkname too long, truncating to '%.16s'\n", linkname, linkname);
+ } else {
+ continue;
+ }
+ }
+ alphastart |= isalpha(cur_name[0]);
+
+ if (strcmp(first_name, cur_name) == 0) {
+ warning("Terminal name '%s' synonym for itself",
+ first_name);
+ } else {
+ if (!check_only) {
+ if (stat64(linkname, &statbuf) >= 0 &&
+ statbuf.st_mtime >= start_time) {
+ warning(
+"'%s' defined in more than one entry.", cur_name);
+ fprintf(stderr,
+ "Entry being used is '%s'.\n",
+ (unsigned)term_names +
+ string_table);
+ }
+ unlink(linkname);
+ if (link(filename, linkname) < 0)
+ syserr_abort("Can't link %s to %s",
+ filename, linkname);
+ DEBUG(1, "Linked %.16s\n", linkname);
+ } else DEBUG(1, "Would have linked %.16s\n", linkname);
+ }
+ }
+
+ if (!alphastart) {
+ warning("At least one synonym should begin with a letter.");
+ }
+}
+
+/*
+ * int
+ * write_object(fp, 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, Booleans, Numbers, Strings)
+FILE *fp;
+short Booleans[];
+short Numbers[];
+short Strings[];
+{
+ struct header header;
+ char *namelist;
+ short namelen;
+ char zero = '\0';
+ register int i;
+ char cBooleans[MAXBOOLS];
+ register int l_next_free;
+
+ namelist = term_names + string_table;
+ namelen = strlen(namelist) + 1;
+
+ l_next_free = next_free;
+ if (l_next_free % 256 == 255)
+ l_next_free++;
+
+ 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(l_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 = l_next_free;
+ }
+
+ for (i = 0; i < BoolCount; i++)
+ cBooleans[i] = Booleans[i];
+
+ if (fwrite(&header, sizeof (header), 1, fp) != 1 ||
+ fwrite(namelist, sizeof (char), namelen, fp) != namelen ||
+ fwrite(cBooleans, 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((char *)Numbers, sizeof (short), NumCount, fp) != NumCount ||
+ fwrite((char *)Strings, sizeof (short), StrCount, fp)
+ != StrCount ||
+ fwrite(string_table, sizeof (char), l_next_free, fp)
+ != l_next_free)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * 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;
+{
+ int old_next_free;
+
+ /* Do not let an offset be 255. It reads as -1 in Vr2 binaries. */
+ if (next_free % 256 == 255)
+ next_free++;
+
+ 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 %u\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 %u\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);
+}
+
+/*
+ * init_structure(Booleans, Numbers, Strings)
+ *
+ * Initialise the given arrays
+ * Reset the next_free counter to zero.
+ *
+ */
+
+init_structure(Booleans, Numbers, Strings)
+short 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;
+}
+
+/*
+ * 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;
+short Booleans[];
+short Numbers[];
+short Strings[];
+{
+ struct _bool_struct use_bools;
+ struct _num_struct use_nums;
+ struct _str_struct use_strs;
+ struct stat64 statbuf;
+ char filename[50];
+ int i;
+ char *UB = &use_bools._auto_left_margin; /* first bool */
+ short *UN = &use_nums._columns; /* first num */
+ char **US = &use_strs.strs._back_tab; /* first str */
+
+ if (invalid_term_name(curr_token.tk_valstring))
+ warning("%s: bad term name", curr_token.tk_valstring);
+
+ sprintf(filename, "%c/%s", curr_token.tk_valstring[0],
+ curr_token.tk_valstring);
+
+ if (stat64(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_bools, &use_nums, &use_strs) < 0)
+ syserr_abort("Error in re-reading compiled file %s",
+ filename);
+
+ for (i = 0; i < BoolCount; i++) {
+ if (Booleans[i] == FALSE)
+ if (UB[i] == TRUE) /* now true */
+ Booleans[i] = TRUE;
+ else if (UB[i] > TRUE) /* cancelled */
+ Booleans[i] = -2;
+ }
+
+ for (i = 0; i < NumCount; i++) {
+ if (Numbers[i] == -1)
+ Numbers[i] = UN[i];
+ }
+
+ for (i = 0; i < StrCount; i++) {
+ if (Strings[i] == -1)
+ if (US[i] == (char *)-1)
+ Strings[i] = -2;
+ else if (US[i] != (char *)0)
+ Strings[i] = save_str(US[i]);
+ }
+
+ }
+ return (0);
+}
diff --git a/usr/src/cmd/tic/tic_read.c b/usr/src/cmd/tic/tic_read.c
new file mode 100644
index 0000000000..b6acd1d7ce
--- /dev/null
+++ b/usr/src/cmd/tic/tic_read.c
@@ -0,0 +1,296 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996-1997 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * ********************************************************************
+ * 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@Udel-Relay (ARPAnet) *
+ * decvax!cornell!pavel (UUCPnet) *
+ * ********************************************************************
+ */
+
+/*
+ * read_entry.c -- Routine for reading in a compiled terminfo file
+ *
+ * $Log: RCS/read_entry.v $
+ * Revision 2.1 82/10/25 14:49:55 pavel
+ * Added Copyright Notice
+ *
+ * Revision 2.0 82/10/24 15:18:22 pavel
+ * Beta-one Test Release
+ *
+ * Revision 1.3 82/08/23 22:31:15 pavel
+ * The REAL Alpha-one Release Version
+ *
+ * Revision 1.2 82/08/19 19:11:49 pavel
+ * Alpha Test Release One
+ *
+ * Revision 1.1 82/08/12 22:25:13 pavel
+ * Initial revision
+ *
+ *
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include "curses_inc.h"
+#include "object.h"
+
+#define OFFSET_BUFSIZE 100
+
+#define swap(x) (((x >> 8) & 0377) + 256 * (x & 0377))
+
+#define min(a, b) ((a) > (b) ? (b) : (a))
+
+/*
+ * int
+ * read_entry(filename, ptr)
+ *
+ * Read the compiled terminfo entry in the given file into the
+ * structure pointed to by ptr, allocating space for the string
+ * table and placing its address in ptr->str_table.
+ *
+ */
+
+static char TermNames[128]; /* Buffer for terminal names for first term */
+static char StringTable[2048]; /* String table for first terminal */
+static int beencalled = 0; /* read_entry has been called before */
+
+int
+read_entry(filename, bptr, nptr, sptr)
+char *filename;
+struct _bool_struct *bptr;
+struct _num_struct *nptr;
+struct _str_struct *sptr;
+{
+ int fd;
+ int numread;
+ int num_strings;
+ int cur_string;
+ int i;
+ struct header header;
+ unsigned char bytebuf[2];
+ char ch;
+ char *UB; /* booleans */
+ short *UN; /* numbers */
+ char **US; /* strings */
+ char *pst; /* pointer to string table */
+ int swapping = must_swap();
+ extern int BoolCount;
+ extern int NumCount;
+ extern int StrCount;
+ extern long lseek();
+ unsigned char byte[OFFSET_BUFSIZE][2];
+ short number[OFFSET_BUFSIZE];
+
+ fd = open(filename, 0);
+
+ if (fd < 0)
+ return (-1);
+
+ read(fd, &header, sizeof (header));
+
+ if (swapping) {
+ header.magic = swap(header.magic);
+ header.name_size = swap(header.name_size);
+ header.bool_count = swap(header.bool_count);
+ header.num_count = swap(header.num_count);
+ header.str_count = swap(header.str_count);
+ header.str_size = swap(header.str_size);
+ }
+
+ if (header.magic != MAGIC) {
+ close(fd);
+ return (-1);
+ }
+
+ read(fd, TermNames, min(127, header.name_size));
+ TermNames[127] = '\0';
+ if (header.name_size > 127)
+ lseek(fd, (long)(header.name_size - 127), 1);
+
+ UB = &(bptr->_auto_left_margin);
+ UN = &(nptr->_columns);
+ US = &(sptr->strs._back_tab);
+ read(fd, UB, min(BoolCount, header.bool_count));
+ if (header.bool_count > BoolCount)
+ lseek(fd, (long)(header.bool_count - BoolCount), 1);
+ else
+ for (i = header.bool_count; i < BoolCount; i++)
+ UB[i] = 0;
+
+ if ((header.name_size + header.bool_count) % 2 != 0)
+ read(fd, &ch, 1);
+
+ if (!swapping)
+ read(fd, (char *)UN, min(NumCount, header.num_count) * 2);
+ else {
+ for (i = 0; i < min(header.num_count, NumCount); i++) {
+ read(fd, (char *)bytebuf, 2);
+ if (bytebuf[1] == 0377) {
+ if (bytebuf[0] == 0376) /* -2 == cancelled */
+ UN[i] = -2;
+ else if (bytebuf[0] == 0377)
+ /* -1 == not there */
+ UN[i] = -1;
+ else
+ UN[i] = bytebuf[0] + 256 * bytebuf[1];
+ } else
+ UN[i] = bytebuf[0] + 256 * bytebuf[1];
+ }
+ }
+
+ if (header.num_count > NumCount)
+ lseek(fd, (long)(2 * (header.num_count - NumCount)), 1);
+ else
+ for (i = header.num_count; i < NumCount; i++)
+ UN[i] = -1;
+
+ if (beencalled) {
+ /* beencalled is non-zero only if we've been called */
+ pst = malloc((unsigned)header.str_size);
+ if (pst == NULL) {
+ close(fd);
+ return (-1);
+ }
+ } else {
+ pst = StringTable;
+ beencalled++;
+ }
+
+ num_strings = min(StrCount, header.str_count);
+ cur_string = 0;
+
+ while (num_strings > 0) {
+
+ if (swapping) {
+ numread = read(fd, byte, 2*min(num_strings,
+ OFFSET_BUFSIZE));
+ if (numread <= 0) {
+ close(fd);
+ return (-1);
+ }
+ for (i = 0; i < numread / 2; i++) {
+ if (byte[i][0] == 0377 && byte[i][1] == 0377)
+ /* -1 */
+ US[i + cur_string] = 0;
+ else if (byte[i][0] == 0376 &&
+ byte[i][1] == 0377)
+ /* -2 */
+ US[i + cur_string] = (char *)-1;
+ else
+ US[i + cur_string] = (byte[i][0] +
+ 256*byte[i][1]) + pst;
+ }
+ } else {
+ numread = read(fd, number, 2*min(num_strings,
+ OFFSET_BUFSIZE));
+ if (numread <= 0) {
+ close(fd);
+ return (-1);
+ }
+ for (i = 0; i < numread / 2; i++) {
+ if (number[i] == -1) /* not there */
+ US[i + cur_string] = 0;
+ else if (number[i] == -2) /* cancelled */
+ US[i + cur_string] = (char *)-1;
+ else
+ US[i + cur_string] = number[i] + pst;
+ }
+ }
+
+ cur_string += numread / 2;
+ num_strings -= numread / 2;
+ }
+
+ if (header.str_count > StrCount)
+ lseek(fd, (long)(2 * (header.str_count - StrCount)), 1);
+ else for (i = header.str_count; i < StrCount; i++)
+ US[i] = 0;
+
+ numread = read(fd, pst, header.str_size);
+ close(fd);
+ if (numread != header.str_size)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * int
+ * must_swap()
+ *
+ * Test whether this machine will need byte-swapping
+ *
+ */
+
+int
+must_swap()
+{
+ union {
+ short num;
+ char byte[2];
+ } test;
+
+ test.num = 1;
+ return (test.byte[1]);
+}
diff --git a/usr/src/cmd/tic/tic_scan.c b/usr/src/cmd/tic/tic_scan.c
new file mode 100644
index 0000000000..d669d91ac4
--- /dev/null
+++ b/usr/src/cmd/tic/tic_scan.c
@@ -0,0 +1,510 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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@Udel-Relay(ARPAnet)
+ * decvax!cornell!pavel(UUCPnet)
+ */
+
+/*
+ * 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
+ *
+ *
+ */
+
+
+#include <stdio.h>
+#include <ctype.h>
+#include "compiler.h"
+
+#define iswhite(ch) (ch == ' ' || ch == '\t')
+
+
+static int first_column; /* See 'next_char()' below */
+
+
+
+/*
+ * 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 int ch;
+ static char buffer[1024];
+ register char *ptr;
+ int dot_flag = FALSE;
+
+ while ((ch = next_char()) == '\n' || (isascii(ch) && iswhite(ch)));
+
+ if (ch == EOF)
+ type = EOF;
+ else {
+ if (ch == '.') {
+ dot_flag = TRUE;
+
+ while ((ch = next_char()) == ' ' || ch == '\t');
+ }
+
+ if (! isascii(ch) || ! isalnum(ch)) {
+ warning("Illegal character - '%c'", ch);
+ panic_mode(',');
+ }
+
+ ptr = buffer;
+ if (ch != '\n') *(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 (isascii(ch) && 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;
+ if ((ch = next_char()) == ',')
+ warning("Missing numeric value");
+ backspace();
+ if ((ch = next_char()) == '0') {
+ if ((ch = next_char()) == 'x' || ch == 'X') {
+ while (isascii(ch = next_char()) &&
+ isxdigit(ch)) {
+ number *= 16;
+ if (isdigit(ch))
+ number += ch - '0';
+ else if (ch >= 'a' && ch <= 'f')
+ number += 10 + ch - 'a';
+ else
+ number += 10 + ch - 'A';
+ }
+ } else {
+ backspace();
+ while ((ch = next_char()) >= '0' &&
+ ch <= '7')
+ number = number * 8 + ch - '0';
+ }
+ } else {
+ backspace();
+ while (isascii(ch = next_char()) &&
+ isdigit(ch))
+ 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 != NULL && ch != ',')
+ warning("Missing comma");
+ if (ch == NULL)
+ warning("NULL string value");
+ 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);
+}
+
+
+
+/*
+ * int
+ * 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
+ * inputline. 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];
+
+int
+next_char()
+{
+ char *rtn_value;
+ long ftell();
+ char *p;
+
+ 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)
+ return (EOF);
+ curr_line++;
+ p = &line[0];
+ while (*p && iswhite(*p)) {
+ p++;
+ }
+ } while (*p == '#');
+
+ curr_column = 0;
+ while (isascii(line[curr_column]) && 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");
+}
+
+
+
+/*
+ * reset_input()
+ *
+ * Resets the input-reading routines. Used after a seek has been done.
+ *
+ */
+
+reset_input()
+{
+ curr_column = -1;
+}
+
+
+
+/*
+ * int
+ * trans_string(ptr)
+ *
+ * Reads characters using next_char() until encountering a comma, a new
+ * entry, 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
+ *
+ */
+
+int
+trans_string(char *ptr)
+{
+ register int count = 0;
+ int number;
+ register int i;
+ register int ch;
+
+ while ((ch = next_char()) != ',' && ch != EOF && !first_column) {
+ if (ch == '^') {
+ ch = next_char();
+ if (ch == EOF)
+ err_abort("Premature EOF");
+
+ if (!isascii(ch) || ! isprint(ch)) {
+ warning("Illegal ^ character - '%c'", ch);
+ }
+
+ if (ch == '@')
+ *(ptr++) = 0200;
+ else
+ *(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++) = '\010'; 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 - '%c'",
+ ch);
+ *(ptr++) = ch;
+ } /* endswitch (ch) */
+ } /* endelse (ch < '0' || ch > '7') */
+ } /* end else if (ch == '\\') */
+ else {
+ if (ch != '\n') *(ptr++) = ch;
+ }
+
+ count ++;
+
+ if (count > 1000)
+ warning("Very long string found. Missing comma?");
+ } /* end while */
+
+ if (ch == EOF)
+ warning("Premature EOF - missing comma?");
+ /* start of new description */
+ else if (first_column) {
+ backspace();
+ warning("Missing comma?");
+ /* pretend we did get a comma */
+ ch = ',';
+ }
+
+ *ptr = '\0';
+
+ if (count == 0)
+ return (NULL);
+ return (ch);
+}
+
+/*
+ * Panic mode error recovery - skip everything until a "ch" is found.
+ */
+panic_mode(int ch)
+{
+ register int c;
+
+ for (;;) {
+ c = next_char();
+ if (c == ch)
+ return;
+ if (c == EOF)
+ return;
+ }
+}