xref: /onnv-gate/usr/src/cmd/tic/tic_parse.c (revision 350:06f97f931994)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*350Sdp  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*350Sdp  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
320Sstevel@tonic-gate  * The Regents of the University of California
330Sstevel@tonic-gate  * All Rights Reserved
340Sstevel@tonic-gate  *
350Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
360Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
370Sstevel@tonic-gate  * contributors.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
410Sstevel@tonic-gate 
420Sstevel@tonic-gate /*
430Sstevel@tonic-gate  *  *******************************************************************
440Sstevel@tonic-gate  *                         COPYRIGHT NOTICE                           *
450Sstevel@tonic-gate  * ********************************************************************
460Sstevel@tonic-gate  *        This software is copyright (C) 1982 by Pavel Curtis         *
470Sstevel@tonic-gate  *                                                                    *
480Sstevel@tonic-gate  *        Permission is granted to reproduce and distribute           *
490Sstevel@tonic-gate  *        this file by any means so long as no fee is charged         *
500Sstevel@tonic-gate  *        above a nominal handling fee and so long as this            *
510Sstevel@tonic-gate  *        notice is always included in the copies.                    *
520Sstevel@tonic-gate  *                                                                    *
530Sstevel@tonic-gate  *        Other rights are reserved except as explicitly granted      *
540Sstevel@tonic-gate  *        by written permission of the author.                        *
550Sstevel@tonic-gate  *                Pavel Curtis                                        *
560Sstevel@tonic-gate  *                Computer Science Dept.                              *
570Sstevel@tonic-gate  *                405 Upson Hall                                      *
580Sstevel@tonic-gate  *                Cornell University                                  *
590Sstevel@tonic-gate  *                Ithaca, NY 14853                                    *
600Sstevel@tonic-gate  *                                                                    *
610Sstevel@tonic-gate  *                Ph- (607) 256-4934                                  *
620Sstevel@tonic-gate  *                                                                    *
630Sstevel@tonic-gate  *                Pavel.Cornell@Udel-Relay   (ARPAnet)                *
640Sstevel@tonic-gate  *                decvax!cornell!pavel       (UUCPnet)                *
650Sstevel@tonic-gate  * ********************************************************************
660Sstevel@tonic-gate  */
670Sstevel@tonic-gate 
680Sstevel@tonic-gate /*
690Sstevel@tonic-gate  *	comp_parse.c -- The high-level (ha!) parts of the compiler,
700Sstevel@tonic-gate  *			that is, the routines which drive the scanner,
710Sstevel@tonic-gate  *			etc.
720Sstevel@tonic-gate  *
730Sstevel@tonic-gate  *   $Log:	RCS/comp_parse.v $
740Sstevel@tonic-gate  * Revision 2.1  82/10/25  14:45:43  pavel
750Sstevel@tonic-gate  * Added Copyright Notice
760Sstevel@tonic-gate  *
770Sstevel@tonic-gate  * Revision 2.0  82/10/24  15:16:39  pavel
780Sstevel@tonic-gate  * Beta-one Test Release
790Sstevel@tonic-gate  *
800Sstevel@tonic-gate  * Revision 1.3  82/08/23  22:29:39  pavel
810Sstevel@tonic-gate  * The REAL Alpha-one Release Version
820Sstevel@tonic-gate  *
830Sstevel@tonic-gate  * Revision 1.2  82/08/19  19:09:53  pavel
840Sstevel@tonic-gate  * Alpha Test Release One
850Sstevel@tonic-gate  *
860Sstevel@tonic-gate  * Revision 1.1  82/08/12  18:37:12  pavel
870Sstevel@tonic-gate  * Initial revision
880Sstevel@tonic-gate  *
890Sstevel@tonic-gate  *
900Sstevel@tonic-gate  */
910Sstevel@tonic-gate 
920Sstevel@tonic-gate #include <sys/types.h>
930Sstevel@tonic-gate #include <sys/stat.h>
940Sstevel@tonic-gate #include <stdio.h>
950Sstevel@tonic-gate #include <ctype.h>
960Sstevel@tonic-gate #include <stdlib.h>
97*350Sdp #include <strings.h>
98*350Sdp #include <unistd.h>
990Sstevel@tonic-gate #include "curses_inc.h"
1000Sstevel@tonic-gate #include "compiler.h"
1010Sstevel@tonic-gate #include "object.h"
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate extern	char check_only;
1040Sstevel@tonic-gate extern	char *progname;
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate char	*string_table;
1070Sstevel@tonic-gate int	next_free;	/* next free character in string_table */
1080Sstevel@tonic-gate unsigned int	table_size = 0; /* current string_table size */
1090Sstevel@tonic-gate short	term_names;	/* string table offset - current terminal */
1100Sstevel@tonic-gate int	part2 = 0;	/* set to allow old compiled defns to be used */
1110Sstevel@tonic-gate int	complete = 0;	/* 1 if entry done with no forward uses */
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate struct use_item {
1140Sstevel@tonic-gate 	long	offset;
1150Sstevel@tonic-gate 	struct use_item	*fptr, *bptr;
1160Sstevel@tonic-gate };
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate struct use_header {
1190Sstevel@tonic-gate 	struct use_item	*head, *tail;
1200Sstevel@tonic-gate };
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate struct use_header	use_list = {NULL, NULL};
1230Sstevel@tonic-gate int			use_count = 0;
1240Sstevel@tonic-gate 
125*350Sdp void dequeue(struct use_item *);
126*350Sdp void init_structure(short Booleans[], short Numbers[], short Strings[]);
127*350Sdp void dump_structure(short Booleans[], short Numbers[], short Strings[]);
128*350Sdp 
1290Sstevel@tonic-gate /*
1300Sstevel@tonic-gate  *  The use_list is a doubly-linked list with NULLs terminating the lists:
1310Sstevel@tonic-gate  *
1320Sstevel@tonic-gate  *	   use_item    use_item    use_item
1330Sstevel@tonic-gate  *	  ---------   ---------   ---------
1340Sstevel@tonic-gate  *	  |       |   |       |   |       |   offset
1350Sstevel@tonic-gate  *        |-------|   |-------|   |-------|
1360Sstevel@tonic-gate  *	  |   ----+-->|   ----+-->|  NULL |   fptr
1370Sstevel@tonic-gate  *	  |-------|   |-------|   |-------|
1380Sstevel@tonic-gate  *	  |  NULL |<--+----   |<--+----   |   bptr
1390Sstevel@tonic-gate  *	  ---------   ---------   ---------
1400Sstevel@tonic-gate  *	  ^                       ^
1410Sstevel@tonic-gate  *	  |  ------------------   |
1420Sstevel@tonic-gate  *	  |  |       |        |   |
1430Sstevel@tonic-gate  *	  +--+----   |    ----+---+
1440Sstevel@tonic-gate  *	     |       |        |
1450Sstevel@tonic-gate  *	     ------------------
1460Sstevel@tonic-gate  *	       head     tail
1470Sstevel@tonic-gate  *	          use_list
1480Sstevel@tonic-gate  *
1490Sstevel@tonic-gate  */
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate /*
1530Sstevel@tonic-gate  *	compile()
1540Sstevel@tonic-gate  *
1550Sstevel@tonic-gate  *	Main loop of the compiler.
1560Sstevel@tonic-gate  *
1570Sstevel@tonic-gate  *	get_token()
1580Sstevel@tonic-gate  *	if curr_token != NAMES
1590Sstevel@tonic-gate  *	    err_abort()
1600Sstevel@tonic-gate  *	while (not at end of file)
1610Sstevel@tonic-gate  *	    do an entry
1620Sstevel@tonic-gate  *
1630Sstevel@tonic-gate  */
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate void
compile()1660Sstevel@tonic-gate compile()
1670Sstevel@tonic-gate {
1680Sstevel@tonic-gate 	char			line[1024];
1690Sstevel@tonic-gate 	int			token_type;
1700Sstevel@tonic-gate 	struct use_item	*ptr;
1710Sstevel@tonic-gate 	int			old_use_count;
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	token_type = get_token();
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	if (token_type != NAMES)
1760Sstevel@tonic-gate 		err_abort(
1770Sstevel@tonic-gate "File does not start with terminal names in column one");
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	while (token_type != EOF)
1800Sstevel@tonic-gate 		token_type = do_entry((struct use_item *)NULL);
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	DEBUG(2, "Starting handling of forward USE's\n", "");
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	for (part2 = 0; part2 < 2; part2++) {
1850Sstevel@tonic-gate 		old_use_count = -1;
1860Sstevel@tonic-gate 		DEBUG(2, "\n\nPART %d\n\n", part2);
1870Sstevel@tonic-gate 		while (use_list.head != NULL && old_use_count != use_count) {
1880Sstevel@tonic-gate 			old_use_count = use_count;
1890Sstevel@tonic-gate 			for (ptr = use_list.tail; ptr != NULL;
1900Sstevel@tonic-gate 							ptr = ptr->bptr) {
1910Sstevel@tonic-gate 				fseek(stdin, ptr->offset, 0);
1920Sstevel@tonic-gate 				reset_input();
1930Sstevel@tonic-gate 				if ((token_type = get_token()) != NAMES)
1940Sstevel@tonic-gate 					syserr_abort(
1950Sstevel@tonic-gate "Token after a seek not NAMES");
1960Sstevel@tonic-gate 				(void) do_entry(ptr);
1970Sstevel@tonic-gate 				if (complete)
1980Sstevel@tonic-gate 					dequeue(ptr);
1990Sstevel@tonic-gate 			}
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 			for (ptr = use_list.head; ptr != NULL;
2020Sstevel@tonic-gate 							ptr = ptr->fptr) {
2030Sstevel@tonic-gate 				fseek(stdin, ptr->offset, 0);
2040Sstevel@tonic-gate 				reset_input();
2050Sstevel@tonic-gate 				if ((token_type = get_token()) != NAMES)
2060Sstevel@tonic-gate 					syserr_abort(
2070Sstevel@tonic-gate "Token after a seek not NAMES");
2080Sstevel@tonic-gate 				(void) do_entry(ptr);
2090Sstevel@tonic-gate 				if (complete)
2100Sstevel@tonic-gate 					dequeue(ptr);
2110Sstevel@tonic-gate 			}
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 			DEBUG(2,
2140Sstevel@tonic-gate "Finished a pass through enqueued forward USE's\n", "");
2150Sstevel@tonic-gate 		}
2160Sstevel@tonic-gate 	}
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	if (use_list.head != NULL && !check_only) {
2190Sstevel@tonic-gate 		fprintf(stderr,
2200Sstevel@tonic-gate "\nError in following up use-links.  Either there is\n");
2210Sstevel@tonic-gate 		fprintf(stderr,
2220Sstevel@tonic-gate "a loop in the links or they reference non-existant\n");
2230Sstevel@tonic-gate 		fprintf(stderr,
2240Sstevel@tonic-gate 			"terminals.  The following is a list of the entries\n");
2250Sstevel@tonic-gate 		fprintf(stderr, "involved:\n\n");
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 		for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) {
2280Sstevel@tonic-gate 			fseek(stdin, ptr->offset, 0);
2290Sstevel@tonic-gate 			fgets(line, 1024, stdin);
2300Sstevel@tonic-gate 			fprintf(stderr, "%s", line);
2310Sstevel@tonic-gate 		}
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 		exit(1);
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
237*350Sdp void
dump_list(char * str)238*350Sdp dump_list(char *str)
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate 	struct use_item *ptr;
2410Sstevel@tonic-gate 	char line[512];
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	fprintf(stderr, "dump_list %s\n", str);
2440Sstevel@tonic-gate 	for (ptr = use_list.head; ptr != NULL; ptr = ptr->fptr) {
2450Sstevel@tonic-gate 		fseek(stdin, ptr->offset, 0);
2460Sstevel@tonic-gate 		fgets(line, 1024, stdin);
2470Sstevel@tonic-gate 		fprintf(stderr, "ptr %x off %d bptr %x fptr %x str %s",
2480Sstevel@tonic-gate 		ptr, ptr->offset, ptr->bptr, ptr->fptr, line);
2490Sstevel@tonic-gate 	}
2500Sstevel@tonic-gate 	fprintf(stderr, "\n");
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate /*
2540Sstevel@tonic-gate  *	int
2550Sstevel@tonic-gate  *	do_entry(item_ptr)
2560Sstevel@tonic-gate  *
2570Sstevel@tonic-gate  *	Compile one entry.  During the first pass, item_ptr is NULL.  In pass
2580Sstevel@tonic-gate  *	two, item_ptr points to the current entry in the use_list.
2590Sstevel@tonic-gate  *
2600Sstevel@tonic-gate  *	found-forward-use = FALSE
2610Sstevel@tonic-gate  *	re-initialise internal arrays
2620Sstevel@tonic-gate  *	save names in string_table
2630Sstevel@tonic-gate  *	get_token()
2640Sstevel@tonic-gate  *	while (not EOF and not NAMES)
2650Sstevel@tonic-gate  *	    if found-forward-use
2660Sstevel@tonic-gate  *		do nothing
2670Sstevel@tonic-gate  *	    else if 'use'
2680Sstevel@tonic-gate  *		if handle_use() < 0
2690Sstevel@tonic-gate  *		    found-forward-use = TRUE
2700Sstevel@tonic-gate  *          else
2710Sstevel@tonic-gate  *	        check for existance and type-correctness
2720Sstevel@tonic-gate  *	        enter cap into structure
2730Sstevel@tonic-gate  *	        if STRING
2740Sstevel@tonic-gate  *	            save string in string_table
2750Sstevel@tonic-gate  *	    get_token()
2760Sstevel@tonic-gate  *      if ! found-forward-use
2770Sstevel@tonic-gate  *	    dump compiled entry into filesystem
2780Sstevel@tonic-gate  *
2790Sstevel@tonic-gate  */
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate int
do_entry(item_ptr)2820Sstevel@tonic-gate do_entry(item_ptr)
2830Sstevel@tonic-gate struct use_item	*item_ptr;
2840Sstevel@tonic-gate {
2850Sstevel@tonic-gate 	long					entry_offset;
286*350Sdp 	int					token_type;
287*350Sdp 	struct name_table_entry			*entry_ptr;
2880Sstevel@tonic-gate 	int					found_forward_use = FALSE;
2890Sstevel@tonic-gate 	short					Booleans[MAXBOOLS],
2900Sstevel@tonic-gate 						Numbers[MAXNUMS],
2910Sstevel@tonic-gate 						Strings[MAXSTRINGS];
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	init_structure(Booleans, Numbers, Strings);
2940Sstevel@tonic-gate 	complete = 0;
2950Sstevel@tonic-gate 	term_names = save_str(curr_token.tk_name);
2960Sstevel@tonic-gate 	DEBUG(2, "Starting '%s'\n", curr_token.tk_name);
2970Sstevel@tonic-gate 	entry_offset = curr_file_pos;
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	for (token_type = get_token();
3000Sstevel@tonic-gate 				token_type != EOF && token_type != NAMES;
3010Sstevel@tonic-gate 				token_type = get_token()) {
3020Sstevel@tonic-gate 		if (found_forward_use)
3030Sstevel@tonic-gate 			/* do nothing */;
3040Sstevel@tonic-gate 		else if (strcmp(curr_token.tk_name, "use") == 0) {
3050Sstevel@tonic-gate 			if (handle_use(item_ptr, entry_offset,
3060Sstevel@tonic-gate 					Booleans, Numbers, Strings) < 0)
3070Sstevel@tonic-gate 				found_forward_use = TRUE;
3080Sstevel@tonic-gate 		} else {
3090Sstevel@tonic-gate 			entry_ptr = find_entry(curr_token.tk_name);
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 			if (entry_ptr == NOTFOUND) {
3120Sstevel@tonic-gate 				warning("Unknown Capability - '%s'",
3130Sstevel@tonic-gate 							curr_token.tk_name);
3140Sstevel@tonic-gate 				continue;
3150Sstevel@tonic-gate 			}
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 			if (token_type != CANCEL &&
3190Sstevel@tonic-gate 					entry_ptr->nte_type != token_type)
3200Sstevel@tonic-gate 				warning("Wrong type used for capability '%s'",
3210Sstevel@tonic-gate 							curr_token.tk_name);
3220Sstevel@tonic-gate 			switch (token_type) {
3230Sstevel@tonic-gate 			case CANCEL:
3240Sstevel@tonic-gate 				switch (entry_ptr->nte_type) {
3250Sstevel@tonic-gate 				case BOOLEAN:
3260Sstevel@tonic-gate 					Booleans[entry_ptr->nte_index] = -2;
3270Sstevel@tonic-gate 					break;
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 				case NUMBER:
3300Sstevel@tonic-gate 					Numbers[entry_ptr->nte_index] = -2;
3310Sstevel@tonic-gate 					break;
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 				case STRING:
3340Sstevel@tonic-gate 					Strings[entry_ptr->nte_index] = -2;
3350Sstevel@tonic-gate 					break;
3360Sstevel@tonic-gate 				}
3370Sstevel@tonic-gate 				break;
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 			case BOOLEAN:
3400Sstevel@tonic-gate 				if (Booleans[entry_ptr->nte_index] == 0)
3410Sstevel@tonic-gate 					Booleans[entry_ptr->nte_index] = TRUE;
3420Sstevel@tonic-gate 				break;
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 			case NUMBER:
3450Sstevel@tonic-gate 				if (Numbers[entry_ptr->nte_index] == -1)
3460Sstevel@tonic-gate 					Numbers[entry_ptr->nte_index] =
3470Sstevel@tonic-gate 						curr_token.tk_valnumber;
3480Sstevel@tonic-gate 				break;
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 			case STRING:
3510Sstevel@tonic-gate 				if (Strings[entry_ptr->nte_index] == -1)
3520Sstevel@tonic-gate 					Strings[entry_ptr->nte_index] =
3530Sstevel@tonic-gate 					    save_str(curr_token.tk_valstring);
3540Sstevel@tonic-gate 				break;
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 			default:
3570Sstevel@tonic-gate 				warning("Unknown token type");
3580Sstevel@tonic-gate 				panic_mode(',');
3590Sstevel@tonic-gate 				continue;
3600Sstevel@tonic-gate 			}
3610Sstevel@tonic-gate 		} /* end else cur_token.name != "use" */
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	} /* endwhile (not EOF and not NAMES) */
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	if (found_forward_use)
3660Sstevel@tonic-gate 		return (token_type);
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	dump_structure(Booleans, Numbers, Strings);
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	complete = 1;
3710Sstevel@tonic-gate 	return (token_type);
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate /*
3750Sstevel@tonic-gate     Change all cancellations to a non-entry.
3760Sstevel@tonic-gate     For booleans, @ -> false
3770Sstevel@tonic-gate     For nums, @ -> -1
3780Sstevel@tonic-gate     For strings, @ -> -1
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate     This only has to be done for entries which
3810Sstevel@tonic-gate     have to be compatible with the pre-Vr3 format.
3820Sstevel@tonic-gate */
3830Sstevel@tonic-gate #ifndef NOCANCELCOMPAT
384*350Sdp void
elim_cancellations(short Booleans[],short Numbers[],short Strings[])385*350Sdp elim_cancellations(short Booleans[], short Numbers[], short Strings[])
3860Sstevel@tonic-gate {
387*350Sdp 	int i;
3880Sstevel@tonic-gate 	for (i = 0; i < BoolCount; i++) {
3890Sstevel@tonic-gate 		if (Booleans[i] == -2)
3900Sstevel@tonic-gate 			Booleans[i] = FALSE;
3910Sstevel@tonic-gate 	}
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 	for (i = 0; i < NumCount; i++) {
3940Sstevel@tonic-gate 		if (Numbers[i] == -2)
3950Sstevel@tonic-gate 			Numbers[i] = -1;
3960Sstevel@tonic-gate 	}
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 	for (i = 0; i < StrCount; i++) {
3990Sstevel@tonic-gate 		if (Strings[i] == -2)
4000Sstevel@tonic-gate 			Strings[i] = -1;
4010Sstevel@tonic-gate 	}
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate #endif /* NOCANCELCOMPAT */
4040Sstevel@tonic-gate /*
4050Sstevel@tonic-gate     Change the cancellation signal from the -2 used internally to
4060Sstevel@tonic-gate     the 2 used within the binary.
4070Sstevel@tonic-gate */
408*350Sdp void
change_cancellations(short Booleans[])409*350Sdp change_cancellations(short Booleans[])
4100Sstevel@tonic-gate {
411*350Sdp 	int i;
4120Sstevel@tonic-gate 	for (i = 0; i < BoolCount; i++) {
4130Sstevel@tonic-gate 		if (Booleans[i] == -2)
4140Sstevel@tonic-gate 			Booleans[i] = 2;
4150Sstevel@tonic-gate 	}
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate /*
4200Sstevel@tonic-gate  *	enqueue(offset)
4210Sstevel@tonic-gate  *
4220Sstevel@tonic-gate  *      Put a record of the given offset onto the use-list.
4230Sstevel@tonic-gate  *
4240Sstevel@tonic-gate  */
4250Sstevel@tonic-gate 
426*350Sdp void
enqueue(long offset)427*350Sdp enqueue(long offset)
4280Sstevel@tonic-gate {
4290Sstevel@tonic-gate 	struct use_item	*item;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	item = (struct use_item *)malloc(sizeof (struct use_item));
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	if (item == NULL)
4340Sstevel@tonic-gate 		syserr_abort("Not enough memory for use_list element");
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	item->offset = offset;
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	if (use_list.head != NULL) {
4390Sstevel@tonic-gate 		item->bptr = use_list.tail;
4400Sstevel@tonic-gate 		use_list.tail->fptr = item;
4410Sstevel@tonic-gate 		item->fptr = NULL;
4420Sstevel@tonic-gate 		use_list.tail = item;
4430Sstevel@tonic-gate 	} else {
4440Sstevel@tonic-gate 		use_list.tail = use_list.head = item;
4450Sstevel@tonic-gate 		item->fptr = item->bptr = NULL;
4460Sstevel@tonic-gate 	}
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	use_count ++;
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate /*
4520Sstevel@tonic-gate  *	dequeue(ptr)
4530Sstevel@tonic-gate  *
4540Sstevel@tonic-gate  *	remove the pointed-to item from the use_list
4550Sstevel@tonic-gate  *
4560Sstevel@tonic-gate  */
4570Sstevel@tonic-gate 
458*350Sdp void
dequeue(struct use_item * ptr)459*350Sdp dequeue(struct use_item *ptr)
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate 	if (ptr->fptr == NULL)
4620Sstevel@tonic-gate 		use_list.tail = ptr->bptr;
4630Sstevel@tonic-gate 	else
4640Sstevel@tonic-gate 		(ptr->fptr)->bptr = ptr->bptr;
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 	if (ptr->bptr == NULL)
4670Sstevel@tonic-gate 		use_list.head = ptr->fptr;
4680Sstevel@tonic-gate 	else
4690Sstevel@tonic-gate 		(ptr->bptr)->fptr = ptr->fptr;
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	use_count --;
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate /*
4750Sstevel@tonic-gate  *	invalid_term_name(name)
4760Sstevel@tonic-gate  *
4770Sstevel@tonic-gate  *	Look for invalid characters in a term name. These include
4780Sstevel@tonic-gate  *	space, tab and '/'.
4790Sstevel@tonic-gate  *
4800Sstevel@tonic-gate  *	Generate an error message if given name does not begin with a
4810Sstevel@tonic-gate  *	digit or letter, then exit.
4820Sstevel@tonic-gate  *
4830Sstevel@tonic-gate  *	return TRUE if name is invalid.
4840Sstevel@tonic-gate  *
4850Sstevel@tonic-gate  */
4860Sstevel@tonic-gate 
487*350Sdp static int
invalid_term_name(char * name)488*350Sdp invalid_term_name(char *name)
4890Sstevel@tonic-gate {
4900Sstevel@tonic-gate 	int error = 0;
4910Sstevel@tonic-gate 	if (! isdigit(*name) && ! islower(*name) && ! isupper(*name))
4920Sstevel@tonic-gate 		error++;
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	for (; *name; name++)
4950Sstevel@tonic-gate 		if (isalnum(*name))
4960Sstevel@tonic-gate 			continue;
4970Sstevel@tonic-gate 		else if (isspace(*name) || (*name == '/'))
4980Sstevel@tonic-gate 			return (1);
4990Sstevel@tonic-gate 	if (error) {
5000Sstevel@tonic-gate 		fprintf(stderr, "%s: Line %d: Illegal terminal name - '%s'\n",
5010Sstevel@tonic-gate 						progname, curr_line, name);
5020Sstevel@tonic-gate 		fprintf(stderr,
5030Sstevel@tonic-gate 			"Terminal names must start with a letter or digit\n");
5040Sstevel@tonic-gate 		exit(1);
5050Sstevel@tonic-gate 	}
5060Sstevel@tonic-gate 	return (0);
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate /*
5100Sstevel@tonic-gate  *	dump_structure()
5110Sstevel@tonic-gate  *
5120Sstevel@tonic-gate  *	Save the compiled version of a description in the filesystem.
5130Sstevel@tonic-gate  *
5140Sstevel@tonic-gate  *	make a copy of the name-list
5150Sstevel@tonic-gate  *	break it up into first-name and all-but-last-name
5160Sstevel@tonic-gate  *	if necessary
5170Sstevel@tonic-gate  *	    clear CANCELS out of the structure
5180Sstevel@tonic-gate  *	creat(first-name)
5190Sstevel@tonic-gate  *	write object information to first-name
5200Sstevel@tonic-gate  *	close(first-name)
5210Sstevel@tonic-gate  *      for each valid name
5220Sstevel@tonic-gate  *	    link to first-name
5230Sstevel@tonic-gate  *
5240Sstevel@tonic-gate  */
5250Sstevel@tonic-gate 
526*350Sdp void
dump_structure(short Booleans[],short Numbers[],short Strings[])527*350Sdp dump_structure(short Booleans[], short Numbers[], short Strings[])
5280Sstevel@tonic-gate {
5290Sstevel@tonic-gate 	struct stat64	statbuf;
5300Sstevel@tonic-gate 	FILE		*fp;
5310Sstevel@tonic-gate 	char		name_list[1024];
532*350Sdp 	char		*first_name, *other_names, *cur_name;
5330Sstevel@tonic-gate 	char		filename[128 + 2 + 1];
5340Sstevel@tonic-gate 	char		linkname[128 + 2 + 1];
5350Sstevel@tonic-gate 	int		len;
5360Sstevel@tonic-gate 	int		alphastart = 0;
5370Sstevel@tonic-gate 	extern char	*strchr(), *strrchr();
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	strcpy(name_list, term_names + string_table);
5400Sstevel@tonic-gate 	DEBUG(7, "Name list = '%s'\n", name_list);
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 	first_name = name_list;
5430Sstevel@tonic-gate 	/* Set othernames to 1 past first '|' in the list. */
5440Sstevel@tonic-gate 	/* Null out that '|' in the process. */
5450Sstevel@tonic-gate 	other_names = strchr(first_name, '|');
5460Sstevel@tonic-gate 	if (other_names)
5470Sstevel@tonic-gate 		*other_names++ = '\0';
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 	if (invalid_term_name(first_name))
5500Sstevel@tonic-gate 		warning("'%s': bad first term name.", first_name);
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	DEBUG(7, "First name = '%s'\n", first_name);
5540Sstevel@tonic-gate 	DEBUG(7, "Other names = '%s'\n", other_names ? other_names : "NULL");
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	if ((len = strlen(first_name)) > 128)
5570Sstevel@tonic-gate 		warning("'%s': terminal name too long.", first_name);
5580Sstevel@tonic-gate 	else if (len == 1)
5590Sstevel@tonic-gate 		warning("'%s': terminal name too short.", first_name);
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 	check_dir(first_name[0]);
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	sprintf(filename, "%c/%s", first_name[0], first_name);
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	if (strlen(filename) > 16)
5660Sstevel@tonic-gate 		warning("'%s' filename too long, truncating to '%.16s'\n",
5670Sstevel@tonic-gate 							filename, filename);
5680Sstevel@tonic-gate 	if (stat64(filename, &statbuf) >= 0 && statbuf.st_mtime >= start_time) {
5690Sstevel@tonic-gate 		warning("'%s' defined in more than one entry.", first_name);
5700Sstevel@tonic-gate 		fprintf(stderr, "Entry being used is '%s'.\n",
5710Sstevel@tonic-gate 			    (unsigned)term_names + string_table);
5720Sstevel@tonic-gate 	}
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 	if (!check_only) {
5750Sstevel@tonic-gate 		unlink(filename);
5760Sstevel@tonic-gate 		fp = fopen(filename, "w");
5770Sstevel@tonic-gate 		if (fp == NULL) {
5780Sstevel@tonic-gate 			perror(filename);
5790Sstevel@tonic-gate 			syserr_abort("Can't open %s/%s\n",
5800Sstevel@tonic-gate 							destination, filename);
5810Sstevel@tonic-gate 		}
5820Sstevel@tonic-gate 		DEBUG(1, "Created %.16s\n", filename);
5830Sstevel@tonic-gate 	} else DEBUG(1, "Would have created %.16s\n", filename);
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate #ifndef NOCANCELCOMPAT
5860Sstevel@tonic-gate 	/* if there is no '+' in the name, eliminate */
5870Sstevel@tonic-gate 	/* cancellation markings. */
5880Sstevel@tonic-gate 	if (strchr(first_name, '+') == 0)
5890Sstevel@tonic-gate 		elim_cancellations(Booleans, Numbers, Strings);
5900Sstevel@tonic-gate 	else
5910Sstevel@tonic-gate #endif /* NOCANCELCOMPAT */
5920Sstevel@tonic-gate 		change_cancellations(Booleans);
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	if (!check_only) {
5950Sstevel@tonic-gate 		if (write_object(fp, Booleans, Numbers, Strings) < 0) {
5960Sstevel@tonic-gate 			syserr_abort("Error in writing %s/%s",
5970Sstevel@tonic-gate 						destination, filename);
5980Sstevel@tonic-gate 		}
5990Sstevel@tonic-gate 		fclose(fp);
6000Sstevel@tonic-gate 	}
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	alphastart = isalpha(first_name[0]);
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 	while (other_names) {
6050Sstevel@tonic-gate 		cur_name = other_names;
6060Sstevel@tonic-gate 		other_names = strchr(cur_name, '|');
6070Sstevel@tonic-gate 		if (other_names)
6080Sstevel@tonic-gate 			*other_names++ = '\0';
6090Sstevel@tonic-gate 		if (*cur_name == '\0')
6100Sstevel@tonic-gate 			continue;
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 		if ((len = strlen(cur_name)) > 128) {
6130Sstevel@tonic-gate 			warning("'%s': terminal name too long.", cur_name);
6140Sstevel@tonic-gate 			continue;
6150Sstevel@tonic-gate 		} else if (len == 1) {
6160Sstevel@tonic-gate 			warning("'%s': terminal name too short.", first_name);
6170Sstevel@tonic-gate 			continue;
6180Sstevel@tonic-gate 		}
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 		if (invalid_term_name(cur_name)) {
6210Sstevel@tonic-gate 			if (other_names)
6220Sstevel@tonic-gate 				warning("'%s': bad term name found in list.",
6230Sstevel@tonic-gate 								cur_name);
6240Sstevel@tonic-gate 			continue;
6250Sstevel@tonic-gate 		}
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 		check_dir(cur_name[0]);
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate 		sprintf(linkname, "%c/%s", cur_name[0], cur_name);
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 		if (strlen(linkname) > 16) {
6320Sstevel@tonic-gate 			if (other_names) {
6330Sstevel@tonic-gate 				warning(
6340Sstevel@tonic-gate "'%s' linkname too long, truncating to '%.16s'\n", linkname, linkname);
6350Sstevel@tonic-gate 			} else {
6360Sstevel@tonic-gate 				continue;
6370Sstevel@tonic-gate 			}
6380Sstevel@tonic-gate 		}
6390Sstevel@tonic-gate 		alphastart |= isalpha(cur_name[0]);
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 		if (strcmp(first_name, cur_name) == 0) {
6420Sstevel@tonic-gate 			warning("Terminal name '%s' synonym for itself",
6430Sstevel@tonic-gate 							first_name);
6440Sstevel@tonic-gate 		} else  {
6450Sstevel@tonic-gate 			if (!check_only) {
6460Sstevel@tonic-gate 				if (stat64(linkname, &statbuf) >= 0 &&
6470Sstevel@tonic-gate 					    statbuf.st_mtime >= start_time) {
6480Sstevel@tonic-gate 					warning(
6490Sstevel@tonic-gate "'%s' defined in more than one entry.", cur_name);
6500Sstevel@tonic-gate 					fprintf(stderr,
6510Sstevel@tonic-gate 					    "Entry being used is '%s'.\n",
6520Sstevel@tonic-gate 					    (unsigned)term_names +
6530Sstevel@tonic-gate 								string_table);
6540Sstevel@tonic-gate 				}
6550Sstevel@tonic-gate 				unlink(linkname);
6560Sstevel@tonic-gate 				if (link(filename, linkname) < 0)
6570Sstevel@tonic-gate 					syserr_abort("Can't link %s to %s",
6580Sstevel@tonic-gate 							filename, linkname);
6590Sstevel@tonic-gate 				DEBUG(1, "Linked %.16s\n", linkname);
6600Sstevel@tonic-gate 			} else DEBUG(1, "Would have linked %.16s\n", linkname);
6610Sstevel@tonic-gate 		}
6620Sstevel@tonic-gate 	}
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	if (!alphastart) {
6650Sstevel@tonic-gate 		warning("At least one synonym should begin with a letter.");
6660Sstevel@tonic-gate 	}
6670Sstevel@tonic-gate }
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate /*
6700Sstevel@tonic-gate  *	int
6710Sstevel@tonic-gate  *	write_object(fp, Booleans, Numbers, Strings)
6720Sstevel@tonic-gate  *
6730Sstevel@tonic-gate  *	Write out the compiled entry to the given file.
6740Sstevel@tonic-gate  *	Return 0 if OK or -1 if not.
6750Sstevel@tonic-gate  *
6760Sstevel@tonic-gate  */
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate #define	swap(x)		(((x >> 8) & 0377) + 256 * (x & 0377))
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate #define	might_swap(x)	(must_swap()  ?  swap(x)  :  (x))
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate int
write_object(fp,Booleans,Numbers,Strings)6840Sstevel@tonic-gate write_object(fp, Booleans, Numbers, Strings)
6850Sstevel@tonic-gate FILE	*fp;
6860Sstevel@tonic-gate short	Booleans[];
6870Sstevel@tonic-gate short	Numbers[];
6880Sstevel@tonic-gate short	Strings[];
6890Sstevel@tonic-gate {
6900Sstevel@tonic-gate 	struct header	header;
6910Sstevel@tonic-gate 	char		*namelist;
6920Sstevel@tonic-gate 	short		namelen;
6930Sstevel@tonic-gate 	char		zero = '\0';
694*350Sdp 	int		i;
6950Sstevel@tonic-gate 	char		cBooleans[MAXBOOLS];
696*350Sdp 	int		l_next_free;
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 	namelist = term_names + string_table;
6990Sstevel@tonic-gate 	namelen = strlen(namelist) + 1;
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	l_next_free = next_free;
7020Sstevel@tonic-gate 	if (l_next_free % 256 == 255)
7030Sstevel@tonic-gate 		l_next_free++;
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	if (must_swap()) {
7060Sstevel@tonic-gate 		header.magic = swap(MAGIC);
7070Sstevel@tonic-gate 		header.name_size = swap(namelen);
7080Sstevel@tonic-gate 		header.bool_count = swap(BoolCount);
7090Sstevel@tonic-gate 		header.num_count = swap(NumCount);
7100Sstevel@tonic-gate 		header.str_count = swap(StrCount);
7110Sstevel@tonic-gate 		header.str_size = swap(l_next_free);
7120Sstevel@tonic-gate 	} else {
7130Sstevel@tonic-gate 		header.magic = MAGIC;
7140Sstevel@tonic-gate 		header.name_size = namelen;
7150Sstevel@tonic-gate 		header.bool_count = BoolCount;
7160Sstevel@tonic-gate 		header.num_count = NumCount;
7170Sstevel@tonic-gate 		header.str_count = StrCount;
7180Sstevel@tonic-gate 		header.str_size = l_next_free;
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	for (i = 0; i < BoolCount; i++)
7220Sstevel@tonic-gate 		cBooleans[i] = Booleans[i];
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 	if (fwrite(&header, sizeof (header), 1, fp) != 1 ||
7250Sstevel@tonic-gate 		    fwrite(namelist, sizeof (char), namelen, fp) != namelen ||
7260Sstevel@tonic-gate 		    fwrite(cBooleans, sizeof (char), BoolCount, fp) !=
7270Sstevel@tonic-gate 								BoolCount)
7280Sstevel@tonic-gate 		return (-1);
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	if ((namelen+BoolCount) % 2 != 0 &&
7310Sstevel@tonic-gate 				fwrite(&zero, sizeof (char), 1, fp) != 1)
7320Sstevel@tonic-gate 		return (-1);
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	if (must_swap()) {
7350Sstevel@tonic-gate 		for (i = 0; i < NumCount; i++)
7360Sstevel@tonic-gate 			Numbers[i] = swap(Numbers[i]);
7370Sstevel@tonic-gate 		for (i = 0; i < StrCount; i++)
7380Sstevel@tonic-gate 			Strings[i] = swap(Strings[i]);
7390Sstevel@tonic-gate 	}
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 	if (fwrite((char *)Numbers, sizeof (short), NumCount, fp) != NumCount ||
7420Sstevel@tonic-gate 		    fwrite((char *)Strings, sizeof (short), StrCount, fp)
7430Sstevel@tonic-gate 							!= StrCount ||
7440Sstevel@tonic-gate 		    fwrite(string_table, sizeof (char), l_next_free, fp)
7450Sstevel@tonic-gate 							!= l_next_free)
7460Sstevel@tonic-gate 		return (-1);
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 	return (0);
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate /*
7520Sstevel@tonic-gate  *	int
7530Sstevel@tonic-gate  *	save_str(string)
7540Sstevel@tonic-gate  *
7550Sstevel@tonic-gate  *	copy string into next free part of string_table, doing a realloc()
7560Sstevel@tonic-gate  *	if necessary.  return offset of beginning of string from start of
7570Sstevel@tonic-gate  *	string_table.
7580Sstevel@tonic-gate  *
7590Sstevel@tonic-gate  */
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate int
save_str(string)7620Sstevel@tonic-gate save_str(string)
7630Sstevel@tonic-gate char	*string;
7640Sstevel@tonic-gate {
7650Sstevel@tonic-gate 	int	old_next_free;
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 	/* Do not let an offset be 255. It reads as -1 in Vr2 binaries. */
7680Sstevel@tonic-gate 	if (next_free % 256 == 255)
7690Sstevel@tonic-gate 		next_free++;
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 	old_next_free = next_free;
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 	if (table_size == 0) {
7740Sstevel@tonic-gate 		if ((string_table = malloc(1024)) == NULL)
7750Sstevel@tonic-gate 			syserr_abort("Out of memory");
7760Sstevel@tonic-gate 		table_size = 1024;
7770Sstevel@tonic-gate 		DEBUG(5, "Made initial string table allocation.  Size is %u\n",
7780Sstevel@tonic-gate 							    table_size);
7790Sstevel@tonic-gate 	}
7800Sstevel@tonic-gate 
7810Sstevel@tonic-gate 	while (table_size <= next_free + strlen(string)) {
7820Sstevel@tonic-gate 		if ((string_table = realloc(string_table, table_size + 1024))
7830Sstevel@tonic-gate 								== NULL)
7840Sstevel@tonic-gate 			syserr_abort("Out of memory");
7850Sstevel@tonic-gate 		table_size += 1024;
7860Sstevel@tonic-gate 		DEBUG(5, "Extended string table.  Size now %u\n", table_size);
7870Sstevel@tonic-gate 	}
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 	strcpy(&string_table[next_free], string);
7900Sstevel@tonic-gate 	DEBUG(7, "Saved string '%s' ", string);
7910Sstevel@tonic-gate 	DEBUG(7, "at location %d\n", next_free);
7920Sstevel@tonic-gate 	next_free += strlen(string) + 1;
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate 	return (old_next_free);
7950Sstevel@tonic-gate }
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate /*
7980Sstevel@tonic-gate  *	init_structure(Booleans, Numbers, Strings)
7990Sstevel@tonic-gate  *
8000Sstevel@tonic-gate  *	Initialise the given arrays
8010Sstevel@tonic-gate  *	Reset the next_free counter to zero.
8020Sstevel@tonic-gate  *
8030Sstevel@tonic-gate  */
8040Sstevel@tonic-gate 
805*350Sdp void
init_structure(short Booleans[],short Numbers[],short Strings[])806*350Sdp init_structure(short Booleans[], short Numbers[], short Strings[])
8070Sstevel@tonic-gate {
8080Sstevel@tonic-gate 	int	i;
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate 	for (i = 0; i < BoolCount; i++)
8110Sstevel@tonic-gate 		Booleans[i] = FALSE;
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 	for (i = 0; i < NumCount; i++)
8140Sstevel@tonic-gate 		Numbers[i] = -1;
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 	for (i = 0; i < StrCount; i++)
8170Sstevel@tonic-gate 		Strings[i] = -1;
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate 	next_free = 0;
8200Sstevel@tonic-gate }
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate /*
8230Sstevel@tonic-gate  *	int
8240Sstevel@tonic-gate  *	handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings)
8250Sstevel@tonic-gate  *
8260Sstevel@tonic-gate  *	Merge the compiled file whose name is in cur_token.valstring
8270Sstevel@tonic-gate  *	with the current entry.
8280Sstevel@tonic-gate  *
8290Sstevel@tonic-gate  *		if it's a forward use-link
8300Sstevel@tonic-gate  *		    if item_ptr == NULL
8310Sstevel@tonic-gate  *		        queue it up for later handling
8320Sstevel@tonic-gate  *	            else
8330Sstevel@tonic-gate  *		        ignore it (we're already going through the queue)
8340Sstevel@tonic-gate  *	        else it's a backward use-link
8350Sstevel@tonic-gate  *	            read in the object file for that terminal
8360Sstevel@tonic-gate  *	            merge contents with current structure
8370Sstevel@tonic-gate  *
8380Sstevel@tonic-gate  *	Returned value is 0 if it was a backward link and we
8390Sstevel@tonic-gate  *	successfully read it in, -1 if a forward link.
8400Sstevel@tonic-gate  */
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate int
handle_use(item_ptr,entry_offset,Booleans,Numbers,Strings)8430Sstevel@tonic-gate handle_use(item_ptr, entry_offset, Booleans, Numbers, Strings)
8440Sstevel@tonic-gate long		entry_offset;
8450Sstevel@tonic-gate struct use_item	*item_ptr;
8460Sstevel@tonic-gate short		Booleans[];
8470Sstevel@tonic-gate short		Numbers[];
8480Sstevel@tonic-gate short		Strings[];
8490Sstevel@tonic-gate {
8500Sstevel@tonic-gate 	struct _bool_struct	use_bools;
8510Sstevel@tonic-gate 	struct _num_struct	use_nums;
8520Sstevel@tonic-gate 	struct _str_struct	use_strs;
8530Sstevel@tonic-gate 	struct stat64	statbuf;
8540Sstevel@tonic-gate 	char		filename[50];
8550Sstevel@tonic-gate 	int		i;
8560Sstevel@tonic-gate 	char  *UB = &use_bools._auto_left_margin;	/* first bool */
8570Sstevel@tonic-gate 	short *UN = &use_nums._columns;			/* first num */
8580Sstevel@tonic-gate 	char **US = &use_strs.strs._back_tab;		/* first str */
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	if (invalid_term_name(curr_token.tk_valstring))
8610Sstevel@tonic-gate 		warning("%s: bad term name", curr_token.tk_valstring);
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 	sprintf(filename, "%c/%s", curr_token.tk_valstring[0],
8640Sstevel@tonic-gate 						curr_token.tk_valstring);
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate 	if (stat64(filename, &statbuf) < 0 ||
8670Sstevel@tonic-gate 				part2 == 0 && statbuf.st_mtime < start_time) {
8680Sstevel@tonic-gate 		DEBUG(2, "Forward USE to %s", curr_token.tk_valstring);
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 		if (item_ptr == NULL) {
8710Sstevel@tonic-gate 			DEBUG(2, " (enqueued)\n", "");
8720Sstevel@tonic-gate 			enqueue(entry_offset);
8730Sstevel@tonic-gate 		} else DEBUG(2, " (skipped)\n", "");
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate 		return (-1);
8760Sstevel@tonic-gate 	} else {
8770Sstevel@tonic-gate 		DEBUG(2, "Backward USE to %s\n", curr_token.tk_valstring);
8780Sstevel@tonic-gate 		if (read_entry(filename, &use_bools, &use_nums, &use_strs) < 0)
8790Sstevel@tonic-gate 			syserr_abort("Error in re-reading compiled file %s",
8800Sstevel@tonic-gate 								filename);
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 		for (i = 0; i < BoolCount; i++) {
8830Sstevel@tonic-gate 			if (Booleans[i] == FALSE)
8840Sstevel@tonic-gate 				if (UB[i] == TRUE)		/* now true */
8850Sstevel@tonic-gate 					Booleans[i] = TRUE;
8860Sstevel@tonic-gate 				else if (UB[i] > TRUE)	/* cancelled */
8870Sstevel@tonic-gate 					Booleans[i] = -2;
8880Sstevel@tonic-gate 		}
8890Sstevel@tonic-gate 
8900Sstevel@tonic-gate 		for (i = 0; i < NumCount; i++) {
8910Sstevel@tonic-gate 			if (Numbers[i] == -1)
8920Sstevel@tonic-gate 				Numbers[i] = UN[i];
8930Sstevel@tonic-gate 		}
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 		for (i = 0; i < StrCount; i++) {
8960Sstevel@tonic-gate 			if (Strings[i] == -1)
8970Sstevel@tonic-gate 				if (US[i] == (char *)-1)
8980Sstevel@tonic-gate 					Strings[i] = -2;
8990Sstevel@tonic-gate 				else if (US[i] != (char *)0)
9000Sstevel@tonic-gate 					Strings[i] = save_str(US[i]);
9010Sstevel@tonic-gate 		}
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate 	}
9040Sstevel@tonic-gate 	return (0);
9050Sstevel@tonic-gate }
906