1 
2 # line 2 "loadkeys.y"
3 /*
4  * CDDL HEADER START
5  *
6  * The contents of this file are subject to the terms of the
7  * Common Development and Distribution License, Version 1.0 only
8  * (the "License").  You may not use this file except in compliance
9  * with the License.
10  *
11  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
12  * or http://www.opensolaris.org/os/licensing.
13  * See the License for the specific language governing permissions
14  * and limitations under the License.
15  *
16  * When distributing Covered Code, include this CDDL HEADER in each
17  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
18  * If applicable, add the following below this CDDL HEADER, with the
19  * fields enclosed by brackets "[]" replaced with your own identifying
20  * information: Portions Copyright [yyyy] [name of copyright owner]
21  *
22  * CDDL HEADER END
23  */
24 
25 #ifndef lint
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 #endif
28 
29 /*
30  * Copyright (c) 1999 by Sun Microsystems, Inc.
31  * All rights reserved.
32  */
33 
34 #include <sys/param.h>
35 #include <ctype.h>
36 #include <stdio.h>
37 #include <search.h>
38 #include <string.h>
39 #include <malloc.h>
40 #include <fcntl.h>
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <unistd.h>
44 #include <sys/kbd.h>
45 #include <sys/kbio.h>
46 
47 #define	ALL	-1	/* special symbol for all tables */
48 
49 /*
50  * SunOS 4.x and Solaris 2.[1234] put Type 4 key tables into
51  * the keytables directory with no type qualification.
52  * If we're a SPARC, we might be using an NFS server that
53  * doesn't have the new type-qualified directories.
54  * (loadkeys wasn't used on non-SPARCs in 2.[1234].)
55  */
56 #ifdef	sparc
57 #define	COMPATIBILITY_DIR
58 #endif
59 
60 static char	keytable_dir[] = "/usr/share/lib/keytables/type_%d/";
61 #ifdef	COMPATIBILITY_DIR
62 static char	keytable_dir2[] = "/usr/share/lib/keytables/";
63 #endif
64 static char	layout_prefix[] = "layout_";
65 
66 struct keyentry {
67 	struct keyentry	*ke_next;
68 	struct kiockeymap ke_entry;
69 };
70 
71 typedef struct keyentry keyentry;
72 
73 static keyentry *firstentry;
74 static keyentry *lastentry;
75 
76 struct dupentry {
77 	struct dupentry *de_next;
78 	int	de_station;
79 	int	de_otherstation;
80 };
81 
82 typedef struct dupentry dupentry;
83 
84 static dupentry *firstduplicate;
85 static dupentry *lastduplicate;
86 
87 static dupentry *firstswap;
88 static dupentry *lastswap;
89 
90 static char	*infilename;
91 static FILE	*infile;
92 static int	lineno;
93 static int	begline;
94 
95 static char	*strings[16] = {
96 	"\033[H",		/* HOMEARROW */
97 	"\033[A",		/* UPARROW */
98 	"\033[B",		/* DOWNARROW */
99 	"\033[D",		/* LEFTARROW */
100 	"\033[C",		/* RIGHTARROW */
101 };
102 
103 static int	nstrings = 5;	/* start out with 5 strings */
104 
105 typedef enum {
106 	SM_INVALID,	/* this shift mask is invalid for this keyboard */
107 	SM_NORMAL,	/* "normal", valid shift mask */
108 	SM_NUMLOCK,	/* "Num Lock" shift mask */
109 	SM_UP		/* "Up" shift mask */
110 } smtype_t;
111 
112 typedef struct {
113 	int	sm_mask;
114 	smtype_t sm_type;
115 } smentry_t;
116 
117 static	smentry_t shiftmasks[] = {
118 	{ 0,		SM_NORMAL },
119 	{ SHIFTMASK,	SM_NORMAL },
120 	{ CAPSMASK,	SM_NORMAL },
121 	{ CTRLMASK,	SM_NORMAL },
122 	{ ALTGRAPHMASK,	SM_NORMAL },
123 	{ NUMLOCKMASK,	SM_NUMLOCK },
124 	{ UPMASK,	SM_UP },
125 };
126 
127 
128 #define	NSHIFTS	(sizeof (shiftmasks) / sizeof (shiftmasks[0]))
129 
130 static void	enter_mapentry(int station, keyentry *entrylistp);
131 static keyentry *makeentry(int tablemask, int entry);
132 static int	loadkey(int kbdfd, keyentry *kep);
133 static int	dupkey(int kbdfd, dupentry *dep, int shiftmask);
134 static int	swapkey(int kbdfd, dupentry *dep, int shiftmask);
135 static int	yylex();
136 static int	readesc(FILE *stream, int delim, int single_char);
137 static int	wordcmp(const void *w1, const void *w2);
138 static int	yyerror(char *msg);
139 static void	usage(void);
140 static void	set_layout(char *arg);
141 static FILE	*open_mapping_file(char *pathbuf, char *name,
142 			boolean_t explicit_name, int type);
143 
144 int
145 main(argc, argv)
146 	int argc;
147 	char **argv;
148 {
149 	register int kbdfd;
150 	int type;
151 	int layout;
152 	/* maxint is 8 hex digits. */
153 	char layout_filename[sizeof(layout_prefix)+8];
154 	char pathbuf[MAXPATHLEN];
155 	register int shift;
156 	struct kiockeymap mapentry;
157 	register keyentry *kep;
158 	register dupentry *dep;
159 	boolean_t explicit_name;
160 
161 	while(++argv, --argc) {
162 		if(argv[0][0] != '-') break;
163 		switch(argv[0][1]) {
164 		case 'e':
165 			/* -e obsolete, silently ignore */
166 			break;
167 		case 's':
168 			if (argc != 2) {
169 				usage();
170 				/* NOTREACHED */
171 			}
172 			set_layout(argv[1]);
173 			exit(0);
174 		default:
175 			usage();
176 			/* NOTREACHED */
177 		}
178 	}
179 
180 	if (argc > 1) usage();
181 
182 	if ((kbdfd = open("/dev/kbd", O_WRONLY)) < 0) {
183 		/* perror("loadkeys: /dev/kbd"); */
184 		return (1);
185 	}
186 
187 	if (ioctl(kbdfd, KIOCTYPE, &type) < 0) {
188 		/*
189 		 * There may not be a keyboard connected,
190 		 * return silently
191 		 */
192 		return (1);
193 	}
194 
195 	if (argc == 0) {
196 		/* If no keyboard detected, exit silently. */
197 		if (type == -1)
198 			return (0);
199 
200 		if (ioctl(kbdfd, KIOCLAYOUT, &layout) < 0) {
201 			perror("loadkeys: ioctl(KIOCLAYOUT)");
202 			return (1);
203 		}
204 
205 		(void) sprintf(layout_filename,
206 				"%s%.2x", layout_prefix, layout);
207 		infilename = layout_filename;
208 		explicit_name = B_FALSE;
209 	} else {
210 		infilename = argv[0];
211 		explicit_name = B_TRUE;
212 	}
213 
214 	infile = open_mapping_file(pathbuf, infilename, explicit_name, type);
215 	if (infile == NULL) return (1);
216 
217 	infilename = pathbuf;
218 
219 	lineno = 0;
220 	begline = 1;
221 	yyparse();
222 	fclose(infile);
223 
224 	/*
225 	 * See which shift masks are valid for this keyboard.
226 	 * We do that by trying to get the entry for keystation 0 and that
227 	 * shift mask; if the "ioctl" fails, we assume it's because the shift
228 	 * mask is invalid.
229 	 */
230 	for (shift = 0; shift < NSHIFTS; shift++) {
231 		mapentry.kio_tablemask =
232 		    shiftmasks[shift].sm_mask;
233 		mapentry.kio_station = 0;
234 		if (ioctl(kbdfd, KIOCGKEY, &mapentry) < 0)
235 			shiftmasks[shift].sm_type = SM_INVALID;
236 	}
237 
238 	for (kep = firstentry; kep != NULL; kep = kep->ke_next) {
239 		if (kep->ke_entry.kio_tablemask == ALL) {
240 			for (shift = 0; shift < NSHIFTS; shift++) {
241 				switch (shiftmasks[shift].sm_type) {
242 
243 				case SM_INVALID:
244 					continue;
245 
246 				case SM_NUMLOCK:
247 					/*
248 					 * Defaults to NONL, not to a copy of
249 					 * the base entry.
250 					 */
251 					if (kep->ke_entry.kio_entry != HOLE)
252 						kep->ke_entry.kio_entry = NONL;
253 					break;
254 
255 				case SM_UP:
256 					/*
257 					 * Defaults to NOP, not to a copy of
258 					 * the base entry.
259 					 */
260 					if (kep->ke_entry.kio_entry != HOLE)
261 						kep->ke_entry.kio_entry = NOP;
262 					break;
263 				}
264 				kep->ke_entry.kio_tablemask =
265 				    shiftmasks[shift].sm_mask;
266 				if (!loadkey(kbdfd, kep))
267 					return (1);
268 			}
269 		} else {
270 			if (!loadkey(kbdfd, kep))
271 				return (1);
272 		}
273 	}
274 
275 	for (dep = firstswap; dep != NULL; dep = dep->de_next) {
276 		for (shift = 0; shift < NSHIFTS; shift++) {
277 			if (shiftmasks[shift].sm_type != SM_INVALID) {
278 				if (!swapkey(kbdfd, dep,
279 				    shiftmasks[shift].sm_mask))
280 					return (0);
281 			}
282 		}
283 	}
284 
285 	for (dep = firstduplicate; dep != NULL; dep = dep->de_next) {
286 		for (shift = 0; shift < NSHIFTS; shift++) {
287 			if (shiftmasks[shift].sm_type != SM_INVALID) {
288 				if (!dupkey(kbdfd, dep,
289 				    shiftmasks[shift].sm_mask))
290 					return (0);
291 			}
292 		}
293 	}
294 
295 	close(kbdfd);
296 	return (0);
297 }
298 
299 static void
300 usage()
301 {
302 	(void) fprintf(stderr, "usage: loadkeys [ file ]\n");
303 	exit(1);
304 }
305 
306 static void
307 set_layout(char *arg)
308 {
309 	int layout;
310 	int ret;
311 	int kbdfd;
312 
313 	layout = (int) strtol(arg, &arg, 0);
314 	if (*arg != '\0') {
315 		fprintf(stderr, "usage:  loadkeys -s layoutnumber\n");
316 		exit(1);
317 	}
318 
319 	if ((kbdfd = open("/dev/kbd", O_WRONLY)) < 0) {
320 		perror("/dev/kbd");
321 		exit(1);
322 	}
323 
324 	ret = ioctl(kbdfd, KIOCSLAYOUT, layout);
325 	if (ret == -1) {
326 		perror("KIOCSLAYOUT");
327 	}
328 
329 	close(kbdfd);
330 }
331 
332 /*
333  * Attempt to find the specified mapping file.  Return a FILE * if found,
334  * else print a message on stderr and return NULL.
335  */
336 FILE *
337 open_mapping_file(
338 	char *pathbuf,
339 	char *name,
340 	boolean_t explicit_name,
341 	int type
342 ) {
343 	/* If the user specified the name, try it "raw". */
344 	if (explicit_name) {
345 		strcpy(pathbuf, name);
346 		infile = fopen(pathbuf, "r");
347 		if (infile) return (infile);
348 		if (errno != ENOENT) goto fopen_fail;
349 	}
350 
351 	/* Everything after this point applies only to relative names. */
352 	if (*name == '/') goto fopen_fail;
353 
354 	/* Try the type-qualified directory name. */
355 	sprintf(pathbuf, keytable_dir, type);
356 	if ((int)(strlen(pathbuf) + strlen(name) + 1) >= MAXPATHLEN) {
357 		(void) fprintf(stderr, "loadkeys: Name %s is too long\n",
358 				name);
359 		return (NULL);
360 	}
361 	(void) strcat(pathbuf, name);
362 	infile = fopen(pathbuf, "r");
363 	if (infile) return (infile);
364 	if (errno != ENOENT) goto fopen_fail;
365 
366 #ifdef	COMPATIBILITY_DIR
367 	/* If not, and either the name was specified explicitly */
368 	/*     or this is a type 4... */
369 	if (explicit_name || type == KB_SUN4) {
370 		/* Try the compatibility name. */
371 		/* No need to check len here, it's shorter. */
372 		(void) strcpy(pathbuf, keytable_dir2);
373 		(void) strcat(pathbuf, infilename);
374 		infile = fopen(pathbuf, "r");
375 		if (infile) return (infile);
376 		if (errno != ENOENT) goto fopen_fail;
377 	}
378 #endif
379 
380 fopen_fail:
381 	(void) fprintf(stderr, "loadkeys: ");
382 	perror(name);
383 	return (NULL);
384 }
385 
386 /*
387  * We have a list of entries for a given keystation, and the keystation number
388  * for that keystation; put that keystation number into all the entries in that
389  * list, and chain that list to the end of the main list of entries.
390  */
391 static void
392 enter_mapentry(station, entrylistp)
393 	int station;
394 	keyentry *entrylistp;
395 {
396 	register keyentry *kep;
397 
398 	if (lastentry == NULL)
399 		firstentry = entrylistp;
400 	else
401 		lastentry->ke_next = entrylistp;
402 	kep = entrylistp;
403 	for (;;) {
404 		kep->ke_entry.kio_station = (u_char)station;
405 		if (kep->ke_next == NULL) {
406 			lastentry = kep;
407 			break;
408 		}
409 		kep = kep->ke_next;
410 	}
411 }
412 
413 /*
414  * Allocate and fill in a new entry.
415  */
416 static keyentry *
417 makeentry(tablemask, entry)
418 	int tablemask;
419 	int entry;
420 {
421 	register keyentry *kep;
422 	register int index;
423 
424 	if ((kep = (keyentry *) malloc((unsigned)sizeof (keyentry))) == NULL)
425 		yyerror("out of memory for entries");
426 	kep->ke_next = NULL;
427 	kep->ke_entry.kio_tablemask = tablemask;
428 	kep->ke_entry.kio_station = 0;
429 	kep->ke_entry.kio_entry = (u_short)entry;
430 	index = entry - STRING;
431 	if (index >= 0 && index <= 15)
432 		(void) strncpy(kep->ke_entry.kio_string, strings[index],
433 		    KTAB_STRLEN);
434 	return (kep);
435 }
436 
437 /*
438  * Make a set of entries for a keystation that indicate that that keystation's
439  * settings should be copied from another keystation's settings.
440  */
441 static void
442 duplicate_mapentry(station, otherstation)
443 	int station;
444 	int otherstation;
445 {
446 	register dupentry *dep;
447 
448 	if ((dep = (dupentry *) malloc((unsigned)sizeof (dupentry))) == NULL)
449 		yyerror("out of memory for entries");
450 
451 	if (lastduplicate == NULL)
452 		firstduplicate = dep;
453 	else
454 		lastduplicate->de_next = dep;
455 	lastduplicate = dep;
456 	dep->de_next = NULL;
457 	dep->de_station = station;
458 	dep->de_otherstation = otherstation;
459 }
460 
461 /*
462  * Make a set of entries for a keystation that indicate that that keystation's
463  * settings should be swapped with another keystation's settings.
464  */
465 static void
466 swap_mapentry(station, otherstation)
467 	int station;
468 	int otherstation;
469 {
470 	register dupentry *dep;
471 
472 	if ((dep = (dupentry *) malloc((unsigned)sizeof (dupentry))) == NULL)
473 		yyerror("out of memory for entries");
474 
475 	if (lastswap == NULL)
476 		firstswap = dep;
477 	else
478 		lastswap->de_next = dep;
479 	lastswap = dep;
480 	dep->de_next = NULL;
481 	dep->de_station = station;
482 	dep->de_otherstation = otherstation;
483 }
484 
485 static int
486 loadkey(kbdfd, kep)
487 	int kbdfd;
488 	register keyentry *kep;
489 {
490 	if (ioctl(kbdfd, KIOCSKEY, &kep->ke_entry) < 0) {
491 		perror("loadkeys: ioctl(KIOCSKEY)");
492 		return (0);
493 	}
494 	return (1);
495 }
496 
497 static int
498 dupkey(kbdfd, dep, shiftmask)
499 	int kbdfd;
500 	register dupentry *dep;
501 	int shiftmask;
502 {
503 	struct kiockeymap entry;
504 
505 	entry.kio_tablemask = shiftmask;
506 	entry.kio_station = dep->de_otherstation;
507 	if (ioctl(kbdfd, KIOCGKEY, &entry) < 0) {
508 		perror("loadkeys: ioctl(KIOCGKEY)");
509 		return (0);
510 	}
511 	entry.kio_station = dep->de_station;
512 	if (ioctl(kbdfd, KIOCSKEY, &entry) < 0) {
513 		perror("loadkeys: ioctl(KIOCSKEY)");
514 		return (0);
515 	}
516 	return (1);
517 }
518 
519 
520 
521 static int
522 swapkey(kbdfd, dep, shiftmask)
523 	int kbdfd;
524 	register dupentry *dep;
525 	int shiftmask;
526 {
527 	struct kiockeymap entry1, entry2;
528 
529 	entry1.kio_tablemask = shiftmask;
530 	entry1.kio_station = dep->de_station;
531 	if (ioctl(kbdfd, KIOCGKEY, &entry1) < 0) {
532 		perror("loadkeys: ioctl(KIOCGKEY)");
533 		return (0);
534 	}
535 	entry2.kio_tablemask = shiftmask;
536 	entry2.kio_station = dep->de_otherstation;
537 	if (ioctl(kbdfd, KIOCGKEY, &entry2) < 0) {
538 		perror("loadkeys: ioctl(KIOCGKEY)");
539 		return (0);
540 	}
541 	entry1.kio_station = dep->de_otherstation;
542 	if (ioctl(kbdfd, KIOCSKEY, &entry1) < 0) {
543 		perror("loadkeys: ioctl(KIOCSKEY)");
544 		return (0);
545 	}
546 	entry2.kio_station = dep->de_station;
547 	if (ioctl(kbdfd, KIOCSKEY, &entry2) < 0) {
548 		perror("loadkeys: ioctl(KIOCSKEY)");
549 		return (0);
550 	}
551 	return (1);
552 }
553 
554 # line 556 "loadkeys.y"
555 typedef union
556 #ifdef __cplusplus
557 	YYSTYPE
558 #endif
559  {
560 	keyentry *keyentry;
561 	int	number;
562 } YYSTYPE;
563 # define TABLENAME 257
564 # define INT 258
565 # define CHAR 259
566 # define CHARSTRING 260
567 # define CONSTANT 261
568 # define FKEY 262
569 # define KEY 263
570 # define SAME 264
571 # define AS 265
572 # define SWAP 266
573 # define WITH 267
574 
575 #include <inttypes.h>
576 
577 #ifdef __STDC__
578 #include <stdlib.h>
579 #include <string.h>
580 #define	YYCONST	const
581 #else
582 #include <malloc.h>
583 #include <memory.h>
584 #define	YYCONST
585 #endif
586 
587 #include <values.h>
588 
589 #if defined(__cplusplus) || defined(__STDC__)
590 
591 #if defined(__cplusplus) && defined(__EXTERN_C__)
592 extern "C" {
593 #endif
594 #ifndef yyerror
595 #if defined(__cplusplus)
596 	void yyerror(YYCONST char *);
597 #endif
598 #endif
599 #ifndef yylex
600 	int yylex(void);
601 #endif
602 	int yyparse(void);
603 #if defined(__cplusplus) && defined(__EXTERN_C__)
604 }
605 #endif
606 
607 #endif
608 
609 #define yyclearin yychar = -1
610 #define yyerrok yyerrflag = 0
611 extern int yychar;
612 extern int yyerrflag;
613 YYSTYPE yylval;
614 YYSTYPE yyval;
615 typedef int yytabelem;
616 #ifndef YYMAXDEPTH
617 #define YYMAXDEPTH 150
618 #endif
619 #if YYMAXDEPTH > 0
620 int yy_yys[YYMAXDEPTH], *yys = yy_yys;
621 YYSTYPE yy_yyv[YYMAXDEPTH], *yyv = yy_yyv;
622 #else	/* user does initial allocation */
623 int *yys;
624 YYSTYPE *yyv;
625 #endif
626 static int yymaxdepth = YYMAXDEPTH;
627 # define YYERRCODE 256
628 
629 # line 683 "loadkeys.y"
630 
631 
632 typedef struct {
633 	char	*w_string;
634 	int	w_type;		/* token type */
635 	int	w_lval;		/* yylval for this token */
636 } word_t;
637 
638 /*
639  * Table must be in alphabetical order.
640  */
641 word_t	wordtab[] = {
642 	{ "all",	TABLENAME,	ALL },
643 	{ "alt",	CONSTANT,	ALT },
644 	{ "altg",	TABLENAME,	ALTGRAPHMASK },
645 	{ "altgraph",	CONSTANT,	ALTGRAPH },
646 	{ "as",		AS,		0 },
647 	{ "base",	TABLENAME,	0 },
648 	{ "bf",		FKEY,		BOTTOMFUNC },
649 	{ "buckybits",	CONSTANT,	BUCKYBITS },
650 	{ "caps",	TABLENAME,	CAPSMASK },
651 	{ "capslock",	CONSTANT,	CAPSLOCK },
652 	{ "compose",	CONSTANT,	COMPOSE },
653 	{ "ctrl",	TABLENAME,	CTRLMASK },
654 	{ "downarrow",	CONSTANT,	DOWNARROW },
655 	{ "error",	CONSTANT,	ERROR },
656 	{ "fa_acute",	CONSTANT,	FA_ACUTE },
657 	{ "fa_cedilla",	CONSTANT,	FA_CEDILLA },
658 	{ "fa_cflex",	CONSTANT,	FA_CFLEX },
659 	{ "fa_grave",	CONSTANT,	FA_GRAVE },
660 	{ "fa_tilde",	CONSTANT,	FA_TILDE },
661 	{ "fa_umlaut",	CONSTANT,	FA_UMLAUT },
662 	{ "hole",	CONSTANT,	HOLE },
663 	{ "homearrow",	CONSTANT,	HOMEARROW },
664 	{ "idle",	CONSTANT,	IDLE },
665 	{ "key",	KEY,		0 },
666 	{ "leftarrow",	CONSTANT,	LEFTARROW },
667 	{ "leftctrl",	CONSTANT,	LEFTCTRL },
668 	{ "leftshift",	CONSTANT,	LEFTSHIFT },
669 	{ "lf",		FKEY,		LEFTFUNC },
670 	{ "metabit",	CONSTANT,	METABIT },
671 	{ "nonl",	CONSTANT,	NONL },
672 	{ "nop",	CONSTANT,	NOP },
673 	{ "numl",	TABLENAME,	NUMLOCKMASK },
674 	{ "numlock",	CONSTANT,	NUMLOCK },
675 	{ "oops",	CONSTANT,	OOPS },
676 	{ "pad0",	CONSTANT,	PAD0 },
677 	{ "pad1",	CONSTANT,	PAD1 },
678 	{ "pad2",	CONSTANT,	PAD2 },
679 	{ "pad3",	CONSTANT,	PAD3 },
680 	{ "pad4",	CONSTANT,	PAD4 },
681 	{ "pad5",	CONSTANT,	PAD5 },
682 	{ "pad6",	CONSTANT,	PAD6 },
683 	{ "pad7",	CONSTANT,	PAD7 },
684 	{ "pad8",	CONSTANT,	PAD8 },
685 	{ "pad9",	CONSTANT,	PAD9 },
686 	{ "paddot",	CONSTANT,	PADDOT },
687 	{ "padenter",	CONSTANT,	PADENTER },
688 	{ "padequal",	CONSTANT,	PADEQUAL },
689 	{ "padminus",	CONSTANT,	PADMINUS },
690 	{ "padplus",	CONSTANT,	PADPLUS },
691 	{ "padsep",	CONSTANT,	PADSEP },
692 	{ "padslash",	CONSTANT,	PADSLASH },
693 	{ "padstar",	CONSTANT,	PADSTAR },
694 	{ "reset",	CONSTANT,	RESET },
695 	{ "rf",		FKEY,		RIGHTFUNC },
696 	{ "rightarrow",	CONSTANT,	RIGHTARROW },
697 	{ "rightctrl",	CONSTANT,	RIGHTCTRL },
698 	{ "rightshift",	CONSTANT,	RIGHTSHIFT },
699 	{ "same",	SAME,		0 },
700 	{ "shift",	TABLENAME,	SHIFTMASK },
701 	{ "shiftkeys",	CONSTANT,	SHIFTKEYS },
702 	{ "shiftlock",	CONSTANT,	SHIFTLOCK },
703 	{ "string",	CONSTANT,	STRING },
704 	{ "swap",	SWAP,		0 },
705 	{ "systembit",	CONSTANT,	SYSTEMBIT },
706 	{ "tf",		FKEY,		TOPFUNC },
707 	{ "up",		TABLENAME,	UPMASK },
708 	{ "uparrow",	CONSTANT,	UPARROW },
709 	{ "with",	WITH,		0 },
710 };
711 
712 #define	NWORDS		(sizeof (wordtab) / sizeof (wordtab[0]))
713 
714 static int
715 yylex()
716 {
717 	register int c;
718 	char tokbuf[256+1];
719 	register char *cp;
720 	register int tokentype;
721 
722 	while ((c = getc(infile)) == ' ' || c == '\t')
723 		;
724 	if (begline) {
725 		lineno++;
726 		begline = 0;
727 		if (c == '#') {
728 			while ((c = getc(infile)) != EOF && c != '\n')
729 				;
730 		}
731 	}
732 	if (c == EOF)
733 		return (0);	/* end marker */
734 	if (c == '\n') {
735 		begline = 1;
736 		return (c);
737 	}
738 
739 	switch (c) {
740 
741 	case '\'':
742 		tokentype = CHAR;
743 		if ((c = getc(infile)) == EOF)
744 			yyerror("unterminated character constant");
745 		if (c == '\n') {
746 			(void) ungetc(c, infile);
747 			yylval.number = '\'';
748 		} else {
749 			switch (c) {
750 
751 			case '\'':
752 				yyerror("null character constant");
753 				break;
754 
755 			case '\\':
756 				yylval.number = readesc(infile, '\'', 1);
757 				break;
758 
759 			default:
760 				yylval.number = c;
761 				break;
762 			}
763 			if ((c = getc(infile)) == EOF || c == '\n')
764 				yyerror("unterminated character constant");
765 			else if (c != '\'')
766 				yyerror("only one character allowed in character constant");
767 		}
768 		break;
769 
770 	case '"':
771 		if ((c = getc(infile)) == EOF)
772 			yyerror("unterminated string constant");
773 		if (c == '\n') {
774 			(void) ungetc(c, infile);
775 			tokentype = CHAR;
776 			yylval.number = '"';
777 		} else {
778 			tokentype = CHARSTRING;
779 			cp = &tokbuf[0];
780 			do {
781 				if (cp > &tokbuf[256])
782 					yyerror("line too long");
783 				if (c == '\\')
784 					c = readesc(infile, '"', 0);
785 				*cp++ = (char)c;
786 			} while ((c = getc(infile)) != EOF && c != '\n' &&
787 				c != '"');
788 			if (c != '"')
789 				yyerror("unterminated string constant");
790 			*cp = '\0';
791 			if (nstrings == 16)
792 				yyerror("too many strings");
793 			if ((int) strlen(tokbuf) > KTAB_STRLEN)
794 				yyerror("string too long");
795 			strings[nstrings] = strdup(tokbuf);
796 			yylval.number = STRING+nstrings;
797 			nstrings++;
798 		}
799 		break;
800 
801 	case '(':
802 	case ')':
803 	case '+':
804 		tokentype = c;
805 		break;
806 
807 	case '^':
808 		if ((c = getc(infile)) == EOF)
809 			yyerror("missing newline at end of line");
810 		tokentype = CHAR;
811 		if (c == ' ' || c == '\t' || c == '\n') {
812 			/*
813 			 * '^' by itself.
814 			 */
815 			yylval.number = '^';
816 		} else {
817 			yylval.number = c & 037;
818 			if ((c = getc(infile)) == EOF)
819 				yyerror("missing newline at end of line");
820 			if (c != ' ' && c != '\t' && c != '\n')
821 				yyerror("invalid control character");
822 		}
823 		(void) ungetc(c, infile);
824 		break;
825 
826 	default:
827 		cp = &tokbuf[0];
828 		do {
829 			if (cp > &tokbuf[256])
830 				yyerror("line too long");
831 			*cp++ = (char)c;
832 		} while ((c = getc(infile)) != EOF && (isalnum(c) || c == '_'));
833 		if (c == EOF)
834 			yyerror("newline missing");
835 		(void) ungetc(c, infile);
836 		*cp = '\0';
837 		if (strlen(tokbuf) == 1) {
838 			tokentype = CHAR;
839 			yylval.number = (unsigned char)tokbuf[0];
840 		} else if (strlen(tokbuf) == 2 && tokbuf[0] == '^') {
841 			tokentype = CHAR;
842 			yylval.number = (unsigned char)(tokbuf[1] & 037);
843 		} else {
844 			word_t word;
845 			register word_t *wptr;
846 			char *ptr;
847 
848 			for (cp = &tokbuf[0]; (c = *cp) != '\0'; cp++) {
849 				if (isupper(c))
850 					*cp = tolower(c);
851 			}
852 			word.w_string = tokbuf;
853 			wptr = (word_t *)bsearch((char *)&word,
854 			    (char *)wordtab, NWORDS, sizeof (word_t),
855 			    wordcmp);
856 			if (wptr != NULL) {
857 				yylval.number = wptr->w_lval;
858 				tokentype = wptr->w_type;
859 			} else {
860 				yylval.number = strtol(tokbuf, &ptr, 10);
861 				if (ptr == tokbuf)
862 					yyerror("syntax error");
863 				else
864 					tokentype = INT;
865 			}
866 			break;
867 		}
868 	}
869 
870 	return (tokentype);
871 }
872 
873 static int
874 readesc(stream, delim, single_char)
875 	FILE *stream;
876 	int delim;
877 	int single_char;
878 {
879 	register int c;
880 	register int val;
881 	register int i;
882 
883 	if ((c = getc(stream)) == EOF || c == '\n')
884 		yyerror("unterminated character constant");
885 
886 	if (c >= '0' && c <= '7') {
887 		val = 0;
888 		i = 1;
889 		for (;;) {
890 			val = val*8 + c - '0';
891 			if ((c = getc(stream)) == EOF || c == '\n')
892 				yyerror("unterminated character constant");
893 			if (c == delim)
894 				break;
895 			i++;
896 			if (i > 3) {
897 				if (single_char)
898 					yyerror("escape sequence too long");
899 				else
900 					break;
901 			}
902 			if (c < '0' || c > '7') {
903 				if (single_char)
904 					yyerror("illegal character in escape sequence");
905 				else
906 					break;
907 			}
908 		}
909 		(void) ungetc(c, stream);
910 	} else {
911 		switch (c) {
912 
913 		case 'n':
914 			val = '\n';
915 			break;
916 
917 		case 't':
918 			val = '\t';
919 			break;
920 
921 		case 'b':
922 			val = '\b';
923 			break;
924 
925 		case 'r':
926 			val = '\r';
927 			break;
928 
929 		case 'v':
930 			val = '\v';
931 			break;
932 
933 		case '\\':
934 			val = '\\';
935 			break;
936 
937 		default:
938 			if (c == delim)
939 				val = delim;
940 			else
941 				yyerror("illegal character in escape sequence");
942 		}
943 	}
944 	return (val);
945 }
946 
947 static int
948 wordcmp(const void *w1, const void *w2)
949 {
950 	return (strcmp(
951 		((const word_t *)w1)->w_string,
952 		((const word_t *)w2)->w_string));
953 }
954 
955 static int
956 yyerror(msg)
957 	char *msg;
958 {
959 	(void) fprintf(stderr, "%s, line %d: %s\n", infilename, lineno, msg);
960 	exit(1);
961 }
962 static YYCONST yytabelem yyexca[] ={
963 -1, 1,
964 	0, -1,
965 	-2, 0,
966 	};
967 # define YYNPROD 22
968 # define YYLAST 260
969 static YYCONST yytabelem yyact[]={
970 
971     21,    22,     5,    23,    14,    17,    13,    26,    27,     7,
972      8,    30,    15,    11,    36,    31,     6,    12,    25,    33,
973     32,     9,     2,     1,    24,    18,    10,     0,    16,     0,
974      0,    28,     0,     0,    29,     0,     0,     0,     0,     0,
975      0,     0,     0,     0,     0,     0,     0,     0,    35,    34,
976      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
977      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
978      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
979      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
980      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
981      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
982      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
983      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
984      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
985      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
986      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
987      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
988      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
989      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
990      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
991      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
992      0,     0,     0,     0,     0,     0,     0,     0,     0,    20,
993     19,    26,    27,     0,     0,     0,     0,     0,     0,     0,
994      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
995      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
996      0,     0,     0,     0,     0,     3,     0,     0,     4,    13 };
997 static YYCONST yytabelem yypact[]={
998 
999 -10000000,    -8,-10000000,  -249,  -249,-10000000,  -251,-10000000,-10000000,  -263,
1000      2,  -260,-10000000,   -40,  -249,-10000000,-10000000,  -249,-10000000,-10000000,
1001 -10000000,-10000000,-10000000,-10000000,   -32,-10000000,-10000000,   -25,    10,     9,
1002   -254,  -249,-10000000,-10000000,-10000000,   -27,-10000000 };
1003 static YYCONST yytabelem yypgo[]={
1004 
1005      0,    26,    17,    25,    24,    18,    16,    23,    22 };
1006 static YYCONST yytabelem yyr1[]={
1007 
1008      0,     7,     7,     8,     8,     8,     8,     1,     1,     2,
1009      3,     3,     3,     3,     3,     3,     4,     4,     5,     5,
1010      6,     6 };
1011 static YYCONST yytabelem yyr2[]={
1012 
1013      0,     4,     0,     9,    13,    11,     2,     5,     3,     5,
1014      3,     3,     3,     3,     3,     3,     3,     7,     3,     9,
1015      3,     3 };
1016 static YYCONST yytabelem yychk[]={
1017 
1018 -10000000,    -7,    -8,   263,   266,    10,    -6,   258,   259,    -6,
1019     -1,   264,    -2,   257,   267,    10,    -2,   265,    -3,   260,
1020    259,    40,    41,    43,    -4,    -5,   261,   262,    -6,    -6,
1021     43,    40,    10,    10,    -5,    -6,    41 };
1022 static YYCONST yytabelem yydef[]={
1023 
1024      2,    -2,     1,     0,     0,     6,     0,    20,    21,     0,
1025      0,     0,     8,     0,     0,     3,     7,     0,     9,    10,
1026     11,    12,    13,    14,    15,    16,    18,     0,     0,     0,
1027      0,     0,     5,     4,    17,     0,    19 };
1028 typedef struct
1029 #ifdef __cplusplus
1030 	yytoktype
1031 #endif
1032 {
1033 #ifdef __cplusplus
1034 const
1035 #endif
1036 char *t_name; int t_val; } yytoktype;
1037 #ifndef YYDEBUG
1038 #	define YYDEBUG	0	/* don't allow debugging */
1039 #endif
1040 
1041 #if YYDEBUG
1042 
1043 yytoktype yytoks[] =
1044 {
1045 	"TABLENAME",	257,
1046 	"INT",	258,
1047 	"CHAR",	259,
1048 	"CHARSTRING",	260,
1049 	"CONSTANT",	261,
1050 	"FKEY",	262,
1051 	"KEY",	263,
1052 	"SAME",	264,
1053 	"AS",	265,
1054 	"SWAP",	266,
1055 	"WITH",	267,
1056 	"-unknown-",	-1	/* ends search */
1057 };
1058 
1059 #ifdef __cplusplus
1060 const
1061 #endif
1062 char * yyreds[] =
1063 {
1064 	"-no such reduction-",
1065 	"table : table line",
1066 	"table : /* empty */",
1067 	"line : KEY number entrylist '\n'",
1068 	"line : KEY number SAME AS number '\n'",
1069 	"line : SWAP number WITH number '\n'",
1070 	"line : '\n'",
1071 	"entrylist : entrylist entry",
1072 	"entrylist : entry",
1073 	"entry : TABLENAME code",
1074 	"code : CHARSTRING",
1075 	"code : CHAR",
1076 	"code : '('",
1077 	"code : ')'",
1078 	"code : '+'",
1079 	"code : expr",
1080 	"expr : term",
1081 	"expr : expr '+' term",
1082 	"term : CONSTANT",
1083 	"term : FKEY '(' number ')'",
1084 	"number : INT",
1085 	"number : CHAR",
1086 };
1087 #endif /* YYDEBUG */
1088 # line	1 "/usr/share/lib/ccs/yaccpar"
1089 /*
1090  * CDDL HEADER START
1091  *
1092  * The contents of this file are subject to the terms of the
1093  * Common Development and Distribution License, Version 1.0 only
1094  * (the "License").  You may not use this file except in compliance
1095  * with the License.
1096  *
1097  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1098  * or http://www.opensolaris.org/os/licensing.
1099  * See the License for the specific language governing permissions
1100  * and limitations under the License.
1101  *
1102  * When distributing Covered Code, include this CDDL HEADER in each
1103  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1104  * If applicable, add the following below this CDDL HEADER, with the
1105  * fields enclosed by brackets "[]" replaced with your own identifying
1106  * information: Portions Copyright [yyyy] [name of copyright owner]
1107  *
1108  * CDDL HEADER END
1109  */
1110 /*
1111  * Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
1112  * Use is subject to license terms.
1113  */
1114 
1115 /* Copyright (c) 1988 AT&T */
1116 /* All Rights Reserved */
1117 
1118 #pragma ident	"%Z%%M%	%I%	%E% SMI"
1119 
1120 /*
1121 ** Skeleton parser driver for yacc output
1122 */
1123 
1124 /*
1125 ** yacc user known macros and defines
1126 */
1127 #define YYERROR		goto yyerrlab
1128 #define YYACCEPT	return(0)
1129 #define YYABORT		return(1)
1130 #define YYBACKUP( newtoken, newvalue )\
1131 {\
1132 	if ( yychar >= 0 || ( yyr2[ yytmp ] >> 1 ) != 1 )\
1133 	{\
1134 		yyerror( "syntax error - cannot backup" );\
1135 		goto yyerrlab;\
1136 	}\
1137 	yychar = newtoken;\
1138 	yystate = *yyps;\
1139 	yylval = newvalue;\
1140 	goto yynewstate;\
1141 }
1142 #define YYRECOVERING()	(!!yyerrflag)
1143 #define YYNEW(type)	malloc(sizeof(type) * yynewmax)
1144 #define YYCOPY(to, from, type) \
1145 	(type *) memcpy(to, (char *) from, yymaxdepth * sizeof (type))
1146 #define YYENLARGE( from, type) \
1147 	(type *) realloc((char *) from, yynewmax * sizeof(type))
1148 #ifndef YYDEBUG
1149 #	define YYDEBUG	1	/* make debugging available */
1150 #endif
1151 
1152 /*
1153 ** user known globals
1154 */
1155 int yydebug;			/* set to 1 to get debugging */
1156 
1157 /*
1158 ** driver internal defines
1159 */
1160 #define YYFLAG		(-10000000)
1161 
1162 /*
1163 ** global variables used by the parser
1164 */
1165 YYSTYPE *yypv;			/* top of value stack */
1166 int *yyps;			/* top of state stack */
1167 
1168 int yystate;			/* current state */
1169 int yytmp;			/* extra var (lasts between blocks) */
1170 
1171 int yynerrs;			/* number of errors */
1172 int yyerrflag;			/* error recovery flag */
1173 int yychar;			/* current input token number */
1174 
1175 
1176 
1177 #ifdef YYNMBCHARS
1178 #define YYLEX()		yycvtok(yylex())
1179 /*
1180 ** yycvtok - return a token if i is a wchar_t value that exceeds 255.
1181 **	If i<255, i itself is the token.  If i>255 but the neither
1182 **	of the 30th or 31st bit is on, i is already a token.
1183 */
1184 #if defined(__STDC__) || defined(__cplusplus)
1185 int yycvtok(int i)
1186 #else
1187 int yycvtok(i) int i;
1188 #endif
1189 {
1190 	int first = 0;
1191 	int last = YYNMBCHARS - 1;
1192 	int mid;
1193 	wchar_t j;
1194 
1195 	if(i&0x60000000){/*Must convert to a token. */
1196 		if( yymbchars[last].character < i ){
1197 			return i;/*Giving up*/
1198 		}
1199 		while ((last>=first)&&(first>=0)) {/*Binary search loop*/
1200 			mid = (first+last)/2;
1201 			j = yymbchars[mid].character;
1202 			if( j==i ){/*Found*/
1203 				return yymbchars[mid].tvalue;
1204 			}else if( j<i ){
1205 				first = mid + 1;
1206 			}else{
1207 				last = mid -1;
1208 			}
1209 		}
1210 		/*No entry in the table.*/
1211 		return i;/* Giving up.*/
1212 	}else{/* i is already a token. */
1213 		return i;
1214 	}
1215 }
1216 #else/*!YYNMBCHARS*/
1217 #define YYLEX()		yylex()
1218 #endif/*!YYNMBCHARS*/
1219 
1220 /*
1221 ** yyparse - return 0 if worked, 1 if syntax error not recovered from
1222 */
1223 #if defined(__STDC__) || defined(__cplusplus)
1224 int yyparse(void)
1225 #else
1226 int yyparse()
1227 #endif
1228 {
1229 	register YYSTYPE *yypvt = 0;	/* top of value stack for $vars */
1230 
1231 #if defined(__cplusplus) || defined(lint)
1232 /*
1233 	hacks to please C++ and lint - goto's inside
1234 	switch should never be executed
1235 */
1236 	static int __yaccpar_lint_hack__ = 0;
1237 	switch (__yaccpar_lint_hack__)
1238 	{
1239 		case 1: goto yyerrlab;
1240 		case 2: goto yynewstate;
1241 	}
1242 #endif
1243 
1244 	/*
1245 	** Initialize externals - yyparse may be called more than once
1246 	*/
1247 	yypv = &yyv[-1];
1248 	yyps = &yys[-1];
1249 	yystate = 0;
1250 	yytmp = 0;
1251 	yynerrs = 0;
1252 	yyerrflag = 0;
1253 	yychar = -1;
1254 
1255 #if YYMAXDEPTH <= 0
1256 	if (yymaxdepth <= 0)
1257 	{
1258 		if ((yymaxdepth = YYEXPAND(0)) <= 0)
1259 		{
1260 			yyerror("yacc initialization error");
1261 			YYABORT;
1262 		}
1263 	}
1264 #endif
1265 
1266 	{
1267 		register YYSTYPE *yy_pv;	/* top of value stack */
1268 		register int *yy_ps;		/* top of state stack */
1269 		register int yy_state;		/* current state */
1270 		register int  yy_n;		/* internal state number info */
1271 	goto yystack;	/* moved from 6 lines above to here to please C++ */
1272 
1273 		/*
1274 		** get globals into registers.
1275 		** branch to here only if YYBACKUP was called.
1276 		*/
1277 	yynewstate:
1278 		yy_pv = yypv;
1279 		yy_ps = yyps;
1280 		yy_state = yystate;
1281 		goto yy_newstate;
1282 
1283 		/*
1284 		** get globals into registers.
1285 		** either we just started, or we just finished a reduction
1286 		*/
1287 	yystack:
1288 		yy_pv = yypv;
1289 		yy_ps = yyps;
1290 		yy_state = yystate;
1291 
1292 		/*
1293 		** top of for (;;) loop while no reductions done
1294 		*/
1295 	yy_stack:
1296 		/*
1297 		** put a state and value onto the stacks
1298 		*/
1299 #if YYDEBUG
1300 		/*
1301 		** if debugging, look up token value in list of value vs.
1302 		** name pairs.  0 and negative (-1) are special values.
1303 		** Note: linear search is used since time is not a real
1304 		** consideration while debugging.
1305 		*/
1306 		if ( yydebug )
1307 		{
1308 			register int yy_i;
1309 
1310 			printf( "State %d, token ", yy_state );
1311 			if ( yychar == 0 )
1312 				printf( "end-of-file\n" );
1313 			else if ( yychar < 0 )
1314 				printf( "-none-\n" );
1315 			else
1316 			{
1317 				for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
1318 					yy_i++ )
1319 				{
1320 					if ( yytoks[yy_i].t_val == yychar )
1321 						break;
1322 				}
1323 				printf( "%s\n", yytoks[yy_i].t_name );
1324 			}
1325 		}
1326 #endif /* YYDEBUG */
1327 		if ( ++yy_ps >= &yys[ yymaxdepth ] )	/* room on stack? */
1328 		{
1329 			/*
1330 			** reallocate and recover.  Note that pointers
1331 			** have to be reset, or bad things will happen
1332 			*/
1333 			long yyps_index = (yy_ps - yys);
1334 			long yypv_index = (yy_pv - yyv);
1335 			long yypvt_index = (yypvt - yyv);
1336 			int yynewmax;
1337 #ifdef YYEXPAND
1338 			yynewmax = YYEXPAND(yymaxdepth);
1339 #else
1340 			yynewmax = 2 * yymaxdepth;	/* double table size */
1341 			if (yymaxdepth == YYMAXDEPTH)	/* first time growth */
1342 			{
1343 				char *newyys = (char *)YYNEW(int);
1344 				char *newyyv = (char *)YYNEW(YYSTYPE);
1345 				if (newyys != 0 && newyyv != 0)
1346 				{
1347 					yys = YYCOPY(newyys, yys, int);
1348 					yyv = YYCOPY(newyyv, yyv, YYSTYPE);
1349 				}
1350 				else
1351 					yynewmax = 0;	/* failed */
1352 			}
1353 			else				/* not first time */
1354 			{
1355 				yys = YYENLARGE(yys, int);
1356 				yyv = YYENLARGE(yyv, YYSTYPE);
1357 				if (yys == 0 || yyv == 0)
1358 					yynewmax = 0;	/* failed */
1359 			}
1360 #endif
1361 			if (yynewmax <= yymaxdepth)	/* tables not expanded */
1362 			{
1363 				yyerror( "yacc stack overflow" );
1364 				YYABORT;
1365 			}
1366 			yymaxdepth = yynewmax;
1367 
1368 			yy_ps = yys + yyps_index;
1369 			yy_pv = yyv + yypv_index;
1370 			yypvt = yyv + yypvt_index;
1371 		}
1372 		*yy_ps = yy_state;
1373 		*++yy_pv = yyval;
1374 
1375 		/*
1376 		** we have a new state - find out what to do
1377 		*/
1378 	yy_newstate:
1379 		if ( ( yy_n = yypact[ yy_state ] ) <= YYFLAG )
1380 			goto yydefault;		/* simple state */
1381 #if YYDEBUG
1382 		/*
1383 		** if debugging, need to mark whether new token grabbed
1384 		*/
1385 		yytmp = yychar < 0;
1386 #endif
1387 		if ( ( yychar < 0 ) && ( ( yychar = YYLEX() ) < 0 ) )
1388 			yychar = 0;		/* reached EOF */
1389 #if YYDEBUG
1390 		if ( yydebug && yytmp )
1391 		{
1392 			register int yy_i;
1393 
1394 			printf( "Received token " );
1395 			if ( yychar == 0 )
1396 				printf( "end-of-file\n" );
1397 			else if ( yychar < 0 )
1398 				printf( "-none-\n" );
1399 			else
1400 			{
1401 				for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
1402 					yy_i++ )
1403 				{
1404 					if ( yytoks[yy_i].t_val == yychar )
1405 						break;
1406 				}
1407 				printf( "%s\n", yytoks[yy_i].t_name );
1408 			}
1409 		}
1410 #endif /* YYDEBUG */
1411 		if ( ( ( yy_n += yychar ) < 0 ) || ( yy_n >= YYLAST ) )
1412 			goto yydefault;
1413 		if ( yychk[ yy_n = yyact[ yy_n ] ] == yychar )	/*valid shift*/
1414 		{
1415 			yychar = -1;
1416 			yyval = yylval;
1417 			yy_state = yy_n;
1418 			if ( yyerrflag > 0 )
1419 				yyerrflag--;
1420 			goto yy_stack;
1421 		}
1422 
1423 	yydefault:
1424 		if ( ( yy_n = yydef[ yy_state ] ) == -2 )
1425 		{
1426 #if YYDEBUG
1427 			yytmp = yychar < 0;
1428 #endif
1429 			if ( ( yychar < 0 ) && ( ( yychar = YYLEX() ) < 0 ) )
1430 				yychar = 0;		/* reached EOF */
1431 #if YYDEBUG
1432 			if ( yydebug && yytmp )
1433 			{
1434 				register int yy_i;
1435 
1436 				printf( "Received token " );
1437 				if ( yychar == 0 )
1438 					printf( "end-of-file\n" );
1439 				else if ( yychar < 0 )
1440 					printf( "-none-\n" );
1441 				else
1442 				{
1443 					for ( yy_i = 0;
1444 						yytoks[yy_i].t_val >= 0;
1445 						yy_i++ )
1446 					{
1447 						if ( yytoks[yy_i].t_val
1448 							== yychar )
1449 						{
1450 							break;
1451 						}
1452 					}
1453 					printf( "%s\n", yytoks[yy_i].t_name );
1454 				}
1455 			}
1456 #endif /* YYDEBUG */
1457 			/*
1458 			** look through exception table
1459 			*/
1460 			{
1461 				register YYCONST int *yyxi = yyexca;
1462 
1463 				while ( ( *yyxi != -1 ) ||
1464 					( yyxi[1] != yy_state ) )
1465 				{
1466 					yyxi += 2;
1467 				}
1468 				while ( ( *(yyxi += 2) >= 0 ) &&
1469 					( *yyxi != yychar ) )
1470 					;
1471 				if ( ( yy_n = yyxi[1] ) < 0 )
1472 					YYACCEPT;
1473 			}
1474 		}
1475 
1476 		/*
1477 		** check for syntax error
1478 		*/
1479 		if ( yy_n == 0 )	/* have an error */
1480 		{
1481 			/* no worry about speed here! */
1482 			switch ( yyerrflag )
1483 			{
1484 			case 0:		/* new error */
1485 				yyerror( "syntax error" );
1486 				goto skip_init;
1487 			yyerrlab:
1488 				/*
1489 				** get globals into registers.
1490 				** we have a user generated syntax type error
1491 				*/
1492 				yy_pv = yypv;
1493 				yy_ps = yyps;
1494 				yy_state = yystate;
1495 			skip_init:
1496 				yynerrs++;
1497 				/* FALLTHRU */
1498 			case 1:
1499 			case 2:		/* incompletely recovered error */
1500 					/* try again... */
1501 				yyerrflag = 3;
1502 				/*
1503 				** find state where "error" is a legal
1504 				** shift action
1505 				*/
1506 				while ( yy_ps >= yys )
1507 				{
1508 					yy_n = yypact[ *yy_ps ] + YYERRCODE;
1509 					if ( yy_n >= 0 && yy_n < YYLAST &&
1510 						yychk[yyact[yy_n]] == YYERRCODE)					{
1511 						/*
1512 						** simulate shift of "error"
1513 						*/
1514 						yy_state = yyact[ yy_n ];
1515 						goto yy_stack;
1516 					}
1517 					/*
1518 					** current state has no shift on
1519 					** "error", pop stack
1520 					*/
1521 #if YYDEBUG
1522 #	define _POP_ "Error recovery pops state %d, uncovers state %d\n"
1523 					if ( yydebug )
1524 						printf( _POP_, *yy_ps,
1525 							yy_ps[-1] );
1526 #	undef _POP_
1527 #endif
1528 					yy_ps--;
1529 					yy_pv--;
1530 				}
1531 				/*
1532 				** there is no state on stack with "error" as
1533 				** a valid shift.  give up.
1534 				*/
1535 				YYABORT;
1536 			case 3:		/* no shift yet; eat a token */
1537 #if YYDEBUG
1538 				/*
1539 				** if debugging, look up token in list of
1540 				** pairs.  0 and negative shouldn't occur,
1541 				** but since timing doesn't matter when
1542 				** debugging, it doesn't hurt to leave the
1543 				** tests here.
1544 				*/
1545 				if ( yydebug )
1546 				{
1547 					register int yy_i;
1548 
1549 					printf( "Error recovery discards " );
1550 					if ( yychar == 0 )
1551 						printf( "token end-of-file\n" );
1552 					else if ( yychar < 0 )
1553 						printf( "token -none-\n" );
1554 					else
1555 					{
1556 						for ( yy_i = 0;
1557 							yytoks[yy_i].t_val >= 0;
1558 							yy_i++ )
1559 						{
1560 							if ( yytoks[yy_i].t_val
1561 								== yychar )
1562 							{
1563 								break;
1564 							}
1565 						}
1566 						printf( "token %s\n",
1567 							yytoks[yy_i].t_name );
1568 					}
1569 				}
1570 #endif /* YYDEBUG */
1571 				if ( yychar == 0 )	/* reached EOF. quit */
1572 					YYABORT;
1573 				yychar = -1;
1574 				goto yy_newstate;
1575 			}
1576 		}/* end if ( yy_n == 0 ) */
1577 		/*
1578 		** reduction by production yy_n
1579 		** put stack tops, etc. so things right after switch
1580 		*/
1581 #if YYDEBUG
1582 		/*
1583 		** if debugging, print the string that is the user's
1584 		** specification of the reduction which is just about
1585 		** to be done.
1586 		*/
1587 		if ( yydebug )
1588 			printf( "Reduce by (%d) \"%s\"\n",
1589 				yy_n, yyreds[ yy_n ] );
1590 #endif
1591 		yytmp = yy_n;			/* value to switch over */
1592 		yypvt = yy_pv;			/* $vars top of value stack */
1593 		/*
1594 		** Look in goto table for next state
1595 		** Sorry about using yy_state here as temporary
1596 		** register variable, but why not, if it works...
1597 		** If yyr2[ yy_n ] doesn't have the low order bit
1598 		** set, then there is no action to be done for
1599 		** this reduction.  So, no saving & unsaving of
1600 		** registers done.  The only difference between the
1601 		** code just after the if and the body of the if is
1602 		** the goto yy_stack in the body.  This way the test
1603 		** can be made before the choice of what to do is needed.
1604 		*/
1605 		{
1606 			/* length of production doubled with extra bit */
1607 			register int yy_len = yyr2[ yy_n ];
1608 
1609 			if ( !( yy_len & 01 ) )
1610 			{
1611 				yy_len >>= 1;
1612 				yyval = ( yy_pv -= yy_len )[1];	/* $$ = $1 */
1613 				yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
1614 					*( yy_ps -= yy_len ) + 1;
1615 				if ( yy_state >= YYLAST ||
1616 					yychk[ yy_state =
1617 					yyact[ yy_state ] ] != -yy_n )
1618 				{
1619 					yy_state = yyact[ yypgo[ yy_n ] ];
1620 				}
1621 				goto yy_stack;
1622 			}
1623 			yy_len >>= 1;
1624 			yyval = ( yy_pv -= yy_len )[1];	/* $$ = $1 */
1625 			yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
1626 				*( yy_ps -= yy_len ) + 1;
1627 			if ( yy_state >= YYLAST ||
1628 				yychk[ yy_state = yyact[ yy_state ] ] != -yy_n )
1629 			{
1630 				yy_state = yyact[ yypgo[ yy_n ] ];
1631 			}
1632 		}
1633 					/* save until reenter driver code */
1634 		yystate = yy_state;
1635 		yyps = yy_ps;
1636 		yypv = yy_pv;
1637 	}
1638 	/*
1639 	** code supplied by user is placed in this switch
1640 	*/
1641 	switch( yytmp )
1642 	{
1643 
1644 case 3:
1645 # line 574 "loadkeys.y"
1646 {
1647 		enter_mapentry(yypvt[-2].number, yypvt[-1].keyentry);
1648 		} break;
1649 case 4:
1650 # line 578 "loadkeys.y"
1651 {
1652 		duplicate_mapentry(yypvt[-4].number, yypvt[-1].number);
1653 		} break;
1654 case 5:
1655 # line 582 "loadkeys.y"
1656 {
1657 		swap_mapentry(yypvt[-3].number, yypvt[-1].number);
1658 		} break;
1659 case 7:
1660 # line 590 "loadkeys.y"
1661 {
1662 		/*
1663 		 * Append this entry to the end of the entry list.
1664 		 */
1665 		register keyentry *kep;
1666 		kep = yypvt[-1].keyentry;
1667 		for (;;) {
1668 			if (kep->ke_next == NULL) {
1669 				kep->ke_next = yypvt[-0].keyentry;
1670 				break;
1671 			}
1672 			kep = kep->ke_next;
1673 		}
1674 		yyval.keyentry = yypvt[-1].keyentry;
1675 		} break;
1676 case 8:
1677 # line 606 "loadkeys.y"
1678 {
1679 		yyval.keyentry = yypvt[-0].keyentry;
1680 		} break;
1681 case 9:
1682 # line 613 "loadkeys.y"
1683 {
1684 		yyval.keyentry = makeentry(yypvt[-1].number, yypvt[-0].number);
1685 		} break;
1686 case 10:
1687 # line 620 "loadkeys.y"
1688 {
1689 		yyval.number = yypvt[-0].number;
1690 		} break;
1691 case 11:
1692 # line 624 "loadkeys.y"
1693 {
1694 		yyval.number = yypvt[-0].number;
1695 		} break;
1696 case 12:
1697 # line 628 "loadkeys.y"
1698 {
1699 		yyval.number = '(';
1700 		} break;
1701 case 13:
1702 # line 632 "loadkeys.y"
1703 {
1704 		yyval.number = ')';
1705 		} break;
1706 case 14:
1707 # line 636 "loadkeys.y"
1708 {
1709 		yyval.number = '+';
1710 		} break;
1711 case 15:
1712 # line 640 "loadkeys.y"
1713 {
1714 		yyval.number = yypvt[-0].number;
1715 		} break;
1716 case 16:
1717 # line 647 "loadkeys.y"
1718 {
1719 		yyval.number = yypvt[-0].number;
1720 		} break;
1721 case 17:
1722 # line 651 "loadkeys.y"
1723 {
1724 		yyval.number = yypvt[-2].number + yypvt[-0].number;
1725 		} break;
1726 case 18:
1727 # line 658 "loadkeys.y"
1728 {
1729 		yyval.number = yypvt[-0].number;
1730 		} break;
1731 case 19:
1732 # line 662 "loadkeys.y"
1733 {
1734 		if (yypvt[-1].number < 1 || yypvt[-1].number > 16)
1735 			yyerror("invalid function key number");
1736 		yyval.number = yypvt[-3].number + yypvt[-1].number - 1;
1737 		} break;
1738 case 20:
1739 # line 671 "loadkeys.y"
1740 {
1741 		yyval.number = yypvt[-0].number;
1742 		} break;
1743 case 21:
1744 # line 675 "loadkeys.y"
1745 {
1746 		if (isdigit(yypvt[-0].number))
1747 			yyval.number = yypvt[-0].number - '0';
1748 		else
1749 			yyerror("syntax error");
1750 		} break;
1751 # line	556 "/usr/share/lib/ccs/yaccpar"
1752 	}
1753 	goto yystack;		/* reset registers in driver code */
1754 }
1755 
1756