1 /*  Copyright 1992, 1993 John Bovey, University of Kent at Canterbury.
2  *
3  *  Redistribution and use in source code and/or executable forms, with
4  *  or without modification, are permitted provided that the following
5  *  condition is met:
6  *
7  *  Any redistribution must retain the above copyright notice, this
8  *  condition and the following disclaimer, either as part of the
9  *  program source code included in the redistribution or in human-
10  *  readable materials provided with the redistribution.
11  *
12  *  THIS SOFTWARE IS PROVIDED "AS IS".  Any express or implied
13  *  warranties concerning this software are disclaimed by the copyright
14  *  holder to the fullest extent permitted by applicable law.  In no
15  *  event shall the copyright-holder be liable for any damages of any
16  *  kind, however caused and on any theory of liability, arising in any
17  *  way out of the use of, or inability to use, this software.
18  *
19  *  -------------------------------------------------------------------
20  *
21  *  In other words, do not misrepresent my work as your own work, and
22  *  do not sue me if it causes problems.  Feel free to do anything else
23  *  you wish with it.
24  */
25 
26 char xvt_command_c_sccsid[] = "@(#)command.c	1.3 9/12/93 (UKC)";
27 
28 #ifdef __STDC__
29 #include <stdarg.h>
30 #else
31 #include <varargs.h>
32 #endif
33 #include <X11/Xlib.h>
34 #include <X11/Xutil.h>
35 #include <X11/keysym.h>
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 #include <sys/time.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <signal.h>
43 #include <fcntl.h>
44 #include <errno.h>
45 #include <string.h>
46 #include "rvt.h"
47 #include "token.h"
48 #include "command.h"
49 #include "ttyinit.h"
50 #include "screen.h"
51 #include "xsetup.h"
52 
53 #ifdef AIX3
54 #include <sys/select.h>
55 #endif /* AIX3 */
56 
57 #define NLMAX	15	/* max number of lines to scroll */
58 
59 #define KBUFSIZE	256	/* size of keyboard mapping buffer */
60 #define COM_BUF_SIZE	2048	/* size of buffer used to read from the command */
61 #define COM_PUSH_MAX	20	/* max number of characters that can be pushed
62 				   back into the input queue */
63 #define MP_INTERVAL	500	/* multi-press interval in milliseconds */
64 
65 /*  Special character returned by get_com_char().
66  */
67 #define GCC_NULL	0x100		/* Input buffer is empty */
68 #define ESC		033
69 
70 /*  Flags used to control get_com_char();
71  */
72 #define BUF_ONLY	1
73 #define GET_XEVENTS	2
74 
75 /*  Global variables that are set up at the beginning and then not changed
76  */
77 extern Display		*display;
78 extern Window		vt_win;
79 extern Window		sb_win;
80 extern Window		main_win;
81 
82 int comm_fd = -1;	/* file descriptor connected to the command */
83 int fd_width;	/* width of file descriptors being used */
84 
85 static int x_fd;	/* file descriptor of the X server connection */
86 static int app_cur_keys = 0;/* flag to say cursor keys are in application mode */
87 static int app_kp_keys = 0;	/* flag to set application keypad keys */
88 static int sun_function_keys = 0;	/* flag set to use Sun function key mapping */
89 static Atom wm_del_win;
90 
91 static unsigned char *send_buf = NULL;	/* characters waiting to be sent to the command */
92 static unsigned char *send_nxt = NULL;	/* next character to be sent */
93 static int send_count = 0;	/* number of characters waiting to be sent */
94 
95 /*  Static variables used to record interesting X events.
96  */
97 /*  Small X event structure used to queue interesting X events that need to
98  *  be converted into tokens.
99  */
100 struct xeventst {
101 	int xe_type;
102 	int xe_button;
103 	int xe_state;
104 	int xe_x;
105 	int xe_y;
106 	int xe_width;
107 	int xe_height;
108 	int xe_detail;
109 	unsigned long xe_time;
110 	Window xe_window;
111 	Atom xe_property;		/* for selection requests */
112 	Atom xe_target;
113 	Window xe_requestor;		/* ditto */
114 	struct xeventst *xe_next;
115 	struct xeventst *xe_prev;
116 };
117 
118 static struct xeventst *xevent_start = NULL;
119 static struct xeventst *xevent_last = NULL;		/* start and end of queue */
120 
121 /*  Variables used for buffered command input.
122  */
123 static unsigned char com_buf[COM_BUF_SIZE];
124 static unsigned char *com_buf_next, *com_buf_top;
125 static unsigned char com_stack[COM_PUSH_MAX];	/* stack of pushed back characters */
126 static unsigned char *com_stack_top;
127 
128 /*  Thanks to Rob McMullen for the following function key mapping tables
129  *  and code.
130  */
131 /*  Structure used to describe the string generated by a function key,
132  *  keypad key, etc.
133  */
134 struct keystringst {
135 	char ks_type;		/* the way  to generate the string (see below) */
136 	unsigned char ks_value;	/* value used in creating the string */
137 };
138 
139 /*  Different values for ks_type which determine how the value is used to
140  *  generate the string.
141  */
142 #define KS_TYPE_NONE	(char)0		/* No output */
143 #define KS_TYPE_CHAR	(char)1		/* as printf("%c",ks_value) */
144 #define KS_TYPE_XTERM	(char)2		/* as printf("\033[%d",ks_value) */
145 #define KS_TYPE_SUN	(char)3		/* as printf("\033[%dz",ks_value) */
146 #define KS_TYPE_APPKEY	(char)4		/* as printf("\033O%c",ks_value) */
147 #define KS_TYPE_NONAPP	(char)5		/* as printf("\033[%c",ks_value) */
148 /* Added by cpbs for Debian, 1999/12/7: this is only used for the Delete key */
149 #define KS_TYPE_VT220	(char)6		/* as printf("\033[%d~",ks_value) */
150 
151 /*  Structure used to map a keysym to a string.
152  */
153 struct keymapst {
154 	KeySym km_keysym;
155 	struct keystringst km_normal;	/* The usual string */
156 	struct keystringst km_alt;	/* The alternative string */
157 };
158 
159 /*  Table of function key mappings
160  */
161 static struct keymapst func_key_table[] = {
162 	{XK_F1,		{KS_TYPE_XTERM,11},	{KS_TYPE_SUN,224}},
163 	{XK_F2,		{KS_TYPE_XTERM,12},	{KS_TYPE_SUN,225}},
164 	{XK_F3,		{KS_TYPE_XTERM,13},	{KS_TYPE_SUN,226}},
165 	{XK_F4,		{KS_TYPE_XTERM,14},	{KS_TYPE_SUN,227}},
166 	{XK_F5,		{KS_TYPE_XTERM,15},	{KS_TYPE_SUN,228}},
167 	{XK_F6,		{KS_TYPE_XTERM,17},	{KS_TYPE_SUN,229}},
168 	{XK_F7,		{KS_TYPE_XTERM,18},	{KS_TYPE_SUN,230}},
169 	{XK_F8,		{KS_TYPE_XTERM,19},	{KS_TYPE_SUN,231}},
170 	{XK_F9,		{KS_TYPE_XTERM,20},	{KS_TYPE_SUN,232}},
171 	{XK_F10,	{KS_TYPE_XTERM,21},	{KS_TYPE_SUN,233}},
172 	{XK_F11,	{KS_TYPE_XTERM,23},	{KS_TYPE_SUN,192}},
173 	{XK_F12,	{KS_TYPE_XTERM,24},	{KS_TYPE_SUN,193}},
174 	{XK_F13,	{KS_TYPE_XTERM,25},	{KS_TYPE_SUN,194}},
175 	{XK_F14,	{KS_TYPE_XTERM,26},	{KS_TYPE_SUN,195}},
176 	{XK_F15,	{KS_TYPE_XTERM,28},	{KS_TYPE_SUN,196}},
177 	{XK_F16,	{KS_TYPE_XTERM,29},	{KS_TYPE_SUN,197}},
178 	{XK_F17,	{KS_TYPE_XTERM,31},	{KS_TYPE_SUN,198}},
179 	{XK_F18,	{KS_TYPE_XTERM,32},	{KS_TYPE_SUN,199}},
180 	{XK_F19,	{KS_TYPE_XTERM,33},	{KS_TYPE_SUN,200}},
181 	{XK_F20,	{KS_TYPE_XTERM,34},	{KS_TYPE_SUN,201}},
182 	{XK_F21,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,208}},
183 	{XK_F22,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,209}},
184 	{XK_F23,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,210}},
185 	{XK_F24,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,211}},
186 	{XK_F25,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,212}},
187 	{XK_F26,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,213}},
188 	{XK_F27,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,214}},
189 	{XK_F28,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,215}},
190 	{XK_F29,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,216}},
191 	{XK_F30,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,217}},
192 	{XK_F31,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,218}},
193 	{XK_F32,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,219}},
194 	{XK_F33,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,220}},
195 	{XK_F34,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,221}},
196 	{XK_F35,	{KS_TYPE_NONE,0},	{KS_TYPE_SUN,222}},
197 	{XK_Find,	{KS_TYPE_XTERM,1},	{KS_TYPE_SUN,1}},
198 	{XK_Insert,	{KS_TYPE_XTERM,2},	{KS_TYPE_SUN,2}},
199 	{XK_Delete,	{KS_TYPE_VT220,3},	{KS_TYPE_SUN,3}},
200 	{XK_BackSpace,	{KS_TYPE_CHAR,127},	{KS_TYPE_SUN,3}},
201 	{XK_Select,	{KS_TYPE_XTERM,4},	{KS_TYPE_SUN,4}},
202 	{XK_Prior,	{KS_TYPE_XTERM,5},	{KS_TYPE_SUN,5}},
203 	{XK_Next,	{KS_TYPE_XTERM,6},	{KS_TYPE_SUN,6}},
204 	{XK_Help,	{KS_TYPE_XTERM,28},	{KS_TYPE_SUN,196}},
205 	{XK_Menu,	{KS_TYPE_XTERM,29},	{KS_TYPE_SUN,197}},
206 	{0,		{KS_TYPE_NONE,0},	{KS_TYPE_NONE,0}}
207 };
208 
209 /*  PC keys and VT100 keypad function keys
210  */
211 static struct keymapst other_key_table[]={
212 	{ XK_Up,	{KS_TYPE_NONAPP,'A'},	{KS_TYPE_APPKEY,'A'}},
213 	{ XK_Down,	{KS_TYPE_NONAPP,'B'},	{KS_TYPE_APPKEY,'B'}},
214 	{ XK_Right,	{KS_TYPE_NONAPP,'C'},	{KS_TYPE_APPKEY,'C'}},
215 	{ XK_Left,	{KS_TYPE_NONAPP,'D'},	{KS_TYPE_APPKEY,'D'}},
216 	{ XK_Home,	{KS_TYPE_NONAPP,'h'},	{KS_TYPE_APPKEY,'h'}},
217 	{ XK_End,	{KS_TYPE_NONAPP,'\0'},	{KS_TYPE_APPKEY,'\0'}},
218 	{ XK_KP_F1,	{KS_TYPE_APPKEY,'P'},	{KS_TYPE_APPKEY,'P'}},
219 	{ XK_KP_F2,	{KS_TYPE_APPKEY,'Q'},	{KS_TYPE_APPKEY,'Q'}},
220 	{ XK_KP_F3,	{KS_TYPE_APPKEY,'R'},	{KS_TYPE_APPKEY,'R'}},
221 	{ XK_KP_F4,	{KS_TYPE_APPKEY,'S'},	{KS_TYPE_APPKEY,'S'}},
222 	{0,		{KS_TYPE_NONE,0},	{KS_TYPE_NONE,0}}
223 };
224 
225 /*  VT100 numeric keypad keys
226  */
227 static struct keymapst kp_key_table[]={
228 	{ XK_KP_0,	{KS_TYPE_CHAR,'0'},	{KS_TYPE_APPKEY,'p'}},
229 	{ XK_KP_1,	{KS_TYPE_CHAR,'1'},	{KS_TYPE_APPKEY,'q'}},
230 	{ XK_KP_2,	{KS_TYPE_CHAR,'2'},	{KS_TYPE_APPKEY,'r'}},
231 	{ XK_KP_3,	{KS_TYPE_CHAR,'3'},	{KS_TYPE_APPKEY,'s'}},
232 	{ XK_KP_4,	{KS_TYPE_CHAR,'4'},	{KS_TYPE_APPKEY,'t'}},
233 	{ XK_KP_5,	{KS_TYPE_CHAR,'5'},	{KS_TYPE_APPKEY,'u'}},
234 	{ XK_KP_6,	{KS_TYPE_CHAR,'6'},	{KS_TYPE_APPKEY,'v'}},
235 	{ XK_KP_7,	{KS_TYPE_CHAR,'7'},	{KS_TYPE_APPKEY,'w'}},
236 	{ XK_KP_8,	{KS_TYPE_CHAR,'8'},	{KS_TYPE_APPKEY,'x'}},
237 	{ XK_KP_9,	{KS_TYPE_CHAR,'9'},	{KS_TYPE_APPKEY,'y'}},
238 	{ XK_KP_Add,	{KS_TYPE_CHAR,'+'},	{KS_TYPE_APPKEY,'k'}},
239 	{ XK_KP_Subtract,{KS_TYPE_CHAR,'-'},	{KS_TYPE_APPKEY,'m'}},
240 	{ XK_KP_Multiply,{KS_TYPE_CHAR,'*'},	{KS_TYPE_APPKEY,'j'}},
241 	{ XK_KP_Divide,	{KS_TYPE_CHAR,'/'},	{KS_TYPE_APPKEY,'o'}},
242 	{ XK_KP_Separator,{KS_TYPE_CHAR,','},	{KS_TYPE_APPKEY,'l'}},
243 	{ XK_KP_Decimal,{KS_TYPE_CHAR,'.'},	{KS_TYPE_APPKEY,'n'}},
244 	{ XK_KP_Enter,	{KS_TYPE_CHAR,'\r'},	{KS_TYPE_APPKEY,'M'}},
245 	{ XK_KP_Space,	{KS_TYPE_CHAR,' '},	{KS_TYPE_APPKEY,' '}},
246 	{ XK_KP_Tab,	{KS_TYPE_CHAR,'\t'},	{KS_TYPE_APPKEY,'I'}},
247 	{0,		{KS_TYPE_NONE,0},	{KS_TYPE_NONE,0}}
248 };
249 
250 #ifdef __STDC__
251 static void push_xevent(struct xeventst *);
252 static struct xeventst *pop_xevent(void);
253 static unsigned char * get_keycode_value(struct keymapst *,KeySym,unsigned char *,int);
254 static unsigned char *lookup_key(XEvent *,int *);
255 static int get_com_char(int);
256 static void push_com_char(int);
257 #ifdef DEBUG
258 static void show_token_args(struct tokenst *);
259 static void show_hex_token_args(struct tokenst *);
260 #endif /* DEBUG */
261 #else /* __STDC__ */
262 static void push_xevent();
263 static struct xeventst *pop_xevent();
264 static unsigned char * get_keycode_value();
265 static unsigned char *lookup_key();
266 static int get_com_char();
267 static void push_com_char();
268 #ifdef DEBUG
269 static void show_token_args();
270 static void show_hex_token_args();
271 #endif /* DEBUG */
272 #endif /* __STDC__ */
273 
274 /*  Push a mini X event onto the queue
275  */
276 static void
push_xevent(xe)277 push_xevent(xe)
278 struct xeventst *xe;
279 {
280 	xe->xe_next = xevent_start;
281 	xe->xe_prev = NULL;
282 	if (xe->xe_next != NULL)
283 		xe->xe_next->xe_prev = xe;
284 	else
285 		xevent_last = xe;
286 }
287 
288 static struct xeventst *
pop_xevent()289 pop_xevent()
290 {
291 	struct xeventst *xe;
292 
293 	if (xevent_last == NULL)
294 		return(NULL);
295 
296 	xe = xevent_last;
297 	xevent_last = xe->xe_prev;
298 	if (xevent_last != NULL)
299 		xevent_last->xe_next = NULL;
300 	else
301 		xevent_start = NULL;
302 	return(xe);
303 }
304 
305 /*  Initialise the command connection.  This should be called after the X
306  *  server connection is established.
307  */
308 void
init_command(char * command,char ** argv)309 init_command(char *command, char **argv)
310 {
311 	/*  Enable the delete window protocol.
312 	 */
313 	wm_del_win = XInternAtom(display, "WM_DELETE_WINDOW", False);
314 	XSetWMProtocols(display, main_win, &wm_del_win, 1);
315 
316 	if ((comm_fd = run_command(command, argv)) < 0) {
317 		error("Quitting");
318 		quit(1);
319 	}
320 	x_fd = XConnectionNumber(display);
321 	com_buf_next = com_buf_top = com_buf;
322 	com_stack_top = com_stack;
323 }
324 
325 /*  Set the current cursor keys mode.
326  */
327 void
set_cur_keys(mode)328 set_cur_keys(mode)
329 int mode;
330 {
331 	app_cur_keys = (mode == HIGH);
332 }
333 
334 /*  Set the current keypad keys mode.
335  */
336 void
set_kp_keys(mode)337 set_kp_keys(mode)
338 int mode;
339 {
340 	app_kp_keys = (mode == HIGH);
341 }
342 
343 /*  Enable or disable the use of Sun function key mapping.
344  */
345 void
set_sun_function_keys(value)346 set_sun_function_keys(value)
347 int value;
348 {
349 	sun_function_keys = value;
350 }
351 
352 /*  Look up function key keycode
353 */
354 static unsigned char *
get_keycode_value(keymaptable,keysym,buf,use_alternate)355 get_keycode_value(keymaptable,keysym,buf,use_alternate)
356 struct keymapst *keymaptable;
357 KeySym keysym;
358 unsigned char *buf;
359 int use_alternate;
360 {
361 	struct keymapst *km;
362 	struct keystringst *ks;
363 
364 	for (km = keymaptable; km->km_keysym != 0; km++) {
365 		if (km->km_keysym == keysym) {
366 			ks = use_alternate ? &km->km_alt : &km->km_normal;
367 			switch (ks->ks_type) {
368 			    case KS_TYPE_NONE:
369 				return NULL;
370 			    case KS_TYPE_CHAR:
371 				sprintf((char *)buf,"%c",ks->ks_value);
372 				return buf;
373 			    case KS_TYPE_XTERM:
374 				sprintf((char *)buf,"\033[%d~",ks->ks_value);
375 				return buf;
376 			    case KS_TYPE_SUN:
377 				sprintf((char *)buf,"\033[%dz",ks->ks_value);
378 				return buf;
379 			    case KS_TYPE_APPKEY:
380 				sprintf((char *)buf,"\033O%c",ks->ks_value);
381 				return buf;
382 			    case KS_TYPE_NONAPP:
383 				sprintf((char *)buf,"\033[%c",ks->ks_value);
384 				return buf;
385 			    case KS_TYPE_VT220:
386 				sprintf((char *)buf,"\033[%d~",ks->ks_value);
387 				return buf;
388 			}
389 		}
390 	}
391 	return NULL;
392 }
393 
394 /*  Convert the keypress event into a string.
395  */
396 static unsigned char *
lookup_key(ev,pcount)397 lookup_key(ev,pcount)
398 int *pcount;
399 XEvent *ev;
400 {
401 	KeySym keysym;
402 	int count;
403 	static unsigned char kbuf[KBUFSIZE];
404 	unsigned char *s;
405 	unsigned char *str;
406 
407 	count = XLookupString(&ev->xkey,kbuf,KBUFSIZE,&keysym,NULL);
408 	s = NULL;
409 
410 	if (IsFunctionKey(keysym) || IsMiscFunctionKey(keysym)
411 					|| keysym == XK_Next || keysym == XK_Prior
412 					|| keysym == XK_Delete || keysym == XK_BackSpace)
413 		s = get_keycode_value(func_key_table,keysym,kbuf,sun_function_keys);
414 	else if (IsCursorKey(keysym) || IsPFKey(keysym))
415 		s = get_keycode_value(other_key_table,keysym,kbuf,app_cur_keys);
416 	else
417 		s = get_keycode_value(kp_key_table,keysym,kbuf,app_kp_keys);
418 
419 	if (s != NULL) {
420 		*pcount = strlen((char *)s);
421 		str = s;
422 	} else {
423 		str = kbuf;
424 		if ((ev->xkey.state & Mod1Mask) && (count == 1)) {
425 			if (is_eightbit()) {
426 				kbuf[0] |= 0200;
427 				*pcount = 1;
428 			} else {
429 				kbuf[1] = kbuf[0];
430 				kbuf[0] = '\033';
431 				*pcount = 2;
432 			}
433 		} else
434 			*pcount = count;
435 	}
436 	return (str);
437 }
438 
439 /*  Return the next input character after first passing any keyboard input
440  *  to the command.  If flags & BUF_ONLY is true then only buffered characters are
441  *  returned and once the buffer is empty the special value GCC_NULL is
442  *  returned.  If flags and GET_XEVENTS is true then GCC_NULL is returned
443  *  when an X event arrives.
444  */
445 static int
get_com_char(flags)446 get_com_char(flags)
447 int flags;
448 {
449 	XEvent event;
450 	struct xeventst *xe;
451 	fd_set in_fdset, out_fdset;
452 	unsigned char *s;
453 	int count, sv;
454 	unsigned char mask = is_eightbit() ? 0xff : 0x7f;
455 	extern int errno;
456 
457 	if (com_stack_top > com_stack)
458 		return(*--com_stack_top);
459 
460 	if (com_buf_next < com_buf_top)
461 		return(*com_buf_next++ & mask);
462 	else if (flags & BUF_ONLY)
463 		return(GCC_NULL);
464 
465 	for (;;) {
466 		FD_ZERO(&in_fdset);
467 		while (XPending(display) == 0) {
468 			if (FD_ISSET(x_fd,&in_fdset))
469 				/*  If we get to this point something is wrong
470 				 *  because there is X input available but no
471 				 *  events.  Exit the program to avoid looping
472 				 *  forever.
473 				 */
474 				quit(0);
475 			FD_SET(comm_fd,&in_fdset);
476 			FD_SET(x_fd,&in_fdset);
477 			FD_ZERO(&out_fdset);
478 			if (send_count > 0)
479 				FD_SET(comm_fd,&out_fdset);
480 			do
481 				sv = select(fd_width,&in_fdset,&out_fdset,NULL,NULL);
482 			while (sv < 0 && errno == EINTR);
483 			if (sv < 0) {
484 				error("select failed");
485 				quit(-1);
486 			}
487 
488 			if (FD_ISSET(comm_fd,&out_fdset)) {
489 				count = send_count < 100 ? send_count : 100;
490 				count = write(comm_fd,send_nxt,count);
491 				if (count < 0) {
492 					error("failed to write to command");
493 					quit(-1);
494 				}
495 				send_count -= count;
496 				send_nxt += count;
497 			}
498 
499 			if (FD_ISSET(comm_fd,&in_fdset))
500 				break;
501 		}
502 		if (FD_ISSET(comm_fd,&in_fdset))
503 			break;
504 		XNextEvent(display,&event);
505 		if (event.type == KeyPress) {
506 			s = lookup_key(&event,&count);
507 			if (count != 0)
508 				send_string(s,count);
509 		} else if (event.type == ClientMessage) {
510 			if (event.xclient.format == 32 && event.xclient.data.l[0] == wm_del_win)
511 				quit(0);
512 		} else if (event.type == MappingNotify) {
513 			XRefreshKeyboardMapping(&event.xmapping);
514 		} else if (event.type == SelectionRequest) {
515 			xe = (struct xeventst *)cmalloc(sizeof(struct xeventst));
516 			xe->xe_type = event.type;
517 			xe->xe_window = event.xselectionrequest.owner;
518 			xe->xe_time = event.xselectionrequest.time;
519 			xe->xe_requestor = event.xselectionrequest.requestor;
520 			xe->xe_target = event.xselectionrequest.target;
521 			xe->xe_property = event.xselectionrequest.property;
522 			push_xevent(xe);
523 			if (flags & GET_XEVENTS)
524 				return(GCC_NULL);
525 		} else if (event.type == SelectionNotify) {
526 			xe = (struct xeventst *)cmalloc(sizeof(struct xeventst));
527 			xe->xe_type = event.type;
528 			xe->xe_time = event.xselection.time;
529 			xe->xe_requestor = event.xselection.requestor;
530 			xe->xe_property = event.xselection.property;
531 			push_xevent(xe);
532 			if (flags & GET_XEVENTS)
533 				return(GCC_NULL);
534 		} else if (event.type == FocusIn || event.type == FocusOut) {
535 			if (event.xfocus.mode != NotifyNormal)
536 				continue;
537 			switch (event.xfocus.detail) {
538 			    case NotifyAncestor :
539 			    case NotifyInferior :
540 			    case NotifyNonlinear :
541 				break;
542 			    default :
543 				continue;
544 			}
545 			xe = (struct xeventst *)cmalloc(sizeof(struct xeventst));
546 			xe->xe_type = event.type;
547 			xe->xe_time = event.xselection.time;
548 			xe->xe_detail = event.xfocus.detail;
549 			push_xevent(xe);
550 			if (flags & GET_XEVENTS)
551 				return(GCC_NULL);
552 		} else {
553 			xe = (struct xeventst *)cmalloc(sizeof(struct xeventst));
554 			xe->xe_type = event.type;
555 			xe->xe_window = event.xany.window;
556 			if (event.type == Expose || event.type == GraphicsExpose) {
557 				xe->xe_x = event.xexpose.x;
558 				xe->xe_y = event.xexpose.y;
559 				xe->xe_width = event.xexpose.width;
560 				xe->xe_height = event.xexpose.height;
561 			} else {
562 				xe->xe_time = event.xbutton.time;
563 				xe->xe_x = event.xbutton.x;
564 				xe->xe_y = event.xbutton.y;
565 				xe->xe_state = event.xbutton.state;
566 				xe->xe_button = event.xbutton.button;
567 			}
568 			push_xevent(xe);
569 			if (flags & GET_XEVENTS)
570 				return(GCC_NULL);
571 		}
572 	}
573 
574 	count = read(comm_fd,com_buf,COM_BUF_SIZE);
575 	if (count <= 0) {
576 		if (errno == EWOULDBLOCK) {
577 			return(GCC_NULL);
578 		} else {
579 			return(EOF);
580 		}
581 	}
582 	com_buf_next = com_buf;
583 	com_buf_top = com_buf + count;
584 	return(*com_buf_next++ & mask);
585 }
586 
587 /*  Push an input character back into the input queue.
588  */
589 static void
push_com_char(c)590 push_com_char(c)
591 int c;
592 {
593 	if (com_stack_top < com_stack + COM_PUSH_MAX)
594 		*com_stack_top++ = c;
595 }
596 
597 /*  Send count characters directly to the command.
598  */
599 void
send_string(buf,count)600 send_string(buf,count)
601 unsigned char *buf;
602 int count;
603 {
604 	unsigned char *s;
605 	register unsigned char *s1, *s2;
606 	register int i;
607 
608 	if (count == 0)
609 		return;
610 
611 	if (send_count == 0) {
612 		if (send_buf != NULL) {
613 			free(send_buf);
614 			send_buf = NULL;
615 		}
616 		send_buf = (unsigned char *)cmalloc(count);
617 		s2 = send_buf;
618 		s1 = buf;
619 		for (i = 0; i < count; i++, s1++, s2++)
620 			*s2 = *s1;
621 		send_nxt = send_buf;
622 		send_count = count;
623 	} else {
624 		s = (unsigned char *)cmalloc(send_count + count);
625 		memcpy(s,send_nxt,send_count);
626 		s2 = s + send_count;
627 		s1 = buf;
628 		for (i = 0; i < count; i++, s1++, s2++)
629 			*s2 = *s1;
630 		free(send_buf);
631 		send_buf = send_nxt = s;
632 		send_count += count;
633 	}
634 }
635 
636 /*  Send printf formatted output to the command.  Only used for small ammounts
637  *  of data.
638  */
639 /*VARARGS1*/
640 void
641 #ifdef __STDC__
cprintf(char * fmt,...)642 cprintf(char *fmt,...)
643 {
644 	va_list args;
645 	static unsigned char buf[1024];
646 
647 	va_start(args,fmt);
648 #else
649 cprintf(va_alist)
650 va_dcl
651 {
652 	char *fmt;
653 	va_list args;
654 	static unsigned char buf[1024];
655 
656 	va_start(args);
657 	fmt = va_arg(args,char *);
658 #endif
659 
660 	vsprintf((char *)buf,fmt,args);
661 	va_end(args);
662 	send_string(buf,strlen((char *)buf));
663 }
664 
665 /*  Return an input token
666  */
667 void
668 get_token(tk)
669 struct tokenst *tk;
670 {
671 	int c, i, n;
672 	struct xeventst *xe;
673 	static unsigned int time1 = 0, time2 = 0;
674 
675 	tk->tk_private = 0;
676 	tk->tk_type = TK_NULL;
677 
678 	if ((xe = pop_xevent()) != NULL) {
679 		if (xe->xe_window == vt_win)
680 			tk->tk_region = SCREEN;
681 		else if (xe->xe_window == sb_win)
682 			tk->tk_region = SCROLLBAR;
683 		else if (xe->xe_window == main_win)
684 			tk->tk_region = MAINWIN;
685 		else
686 			tk->tk_region = -1;
687 		switch (xe->xe_type) {
688 		    case EnterNotify :
689 			tk->tk_type = TK_ENTRY;
690 			tk->tk_arg[0] = 1;
691 			tk->tk_nargs = 1;
692 			break;
693 		    case LeaveNotify :
694 			tk->tk_type = TK_ENTRY;
695 			tk->tk_arg[0] = 0;
696 			tk->tk_nargs = 1;
697 			break;
698 		    case FocusIn :
699 			tk->tk_type = TK_FOCUS;
700 			tk->tk_arg[0] = 1;
701 			tk->tk_arg[1] = xe->xe_detail;
702 			tk->tk_nargs = 2;
703 			break;
704 		    case FocusOut :
705 			tk->tk_type = TK_FOCUS;
706 			tk->tk_arg[0] = 0;
707 			tk->tk_arg[1] = xe->xe_detail;
708 			tk->tk_nargs = 2;
709 			break;
710 		    case Expose :
711 			tk->tk_type = TK_EXPOSE;
712 			tk->tk_arg[0] = xe->xe_x;
713 			tk->tk_arg[1] = xe->xe_y;
714 			tk->tk_arg[2] = xe->xe_width;
715 			tk->tk_arg[3] = xe->xe_height;
716 			tk->tk_nargs = 4;
717 			break;
718 		    case ConfigureNotify :
719 			tk->tk_type = TK_RESIZE;
720 			tk->tk_nargs = 0;
721 			break;
722 		    case SelectionClear :
723 			tk->tk_type = TK_SELCLEAR;
724 			tk->tk_arg[0] = xe->xe_time;
725 			tk->tk_nargs = 1;
726 			break;
727 		    case SelectionNotify :
728 			tk->tk_type = TK_SELNOTIFY;
729 			tk->tk_arg[0] = xe->xe_time;
730 			tk->tk_arg[1] = xe->xe_requestor;
731 			tk->tk_arg[2] = xe->xe_property;
732 			tk->tk_nargs = 3;
733 			break;
734 		    case SelectionRequest :
735 			tk->tk_type = TK_SELREQUEST;
736 			tk->tk_arg[0] = xe->xe_time;
737 			tk->tk_arg[1] = xe->xe_requestor;
738 			tk->tk_arg[2] = xe->xe_target;
739 			tk->tk_arg[3] = xe->xe_property;
740 			tk->tk_nargs = 4;
741 			break;
742 		    case ButtonPress :
743 			/* Deal with a SendEvent */
744 			if (xe->xe_window != vt_win &&
745 			    xe->xe_window != sb_win &&
746 			    xe->xe_window != main_win)
747 				xe->xe_window = vt_win;
748 			if (xe->xe_window == vt_win && xe->xe_state == ControlMask) {
749 				tk->tk_type = TK_SBSWITCH;
750 				tk->tk_nargs = 0;
751 				break;
752 			}
753 			if (xe->xe_window == vt_win && (xe->xe_state & ControlMask) == 0) {
754 				switch (xe->xe_button) {
755 				    case Button1 :
756 					if (xe->xe_time - time2 < MP_INTERVAL) {
757 						time1 = 0;
758 						time2 = 0;
759 						tk->tk_type = TK_SELLINE;
760 					} else if (xe->xe_time - time1 < MP_INTERVAL) {
761 						time2 = xe->xe_time;
762 						tk->tk_type = TK_SELWORD;
763 					} else {
764 						time1 = xe->xe_time;
765 						tk->tk_type = TK_SELSTART;
766 					}
767 					break;
768 				    case Button2 :
769 					tk->tk_type = TK_NULL;
770 					break;
771 				    case Button3 :
772 					tk->tk_type = TK_SELEXTND;
773 					break;
774 				}
775 				tk->tk_arg[0] = xe->xe_x;
776 				tk->tk_arg[1] = xe->xe_y;
777 				tk->tk_nargs = 2;
778 				break;
779 			}
780 			if (xe->xe_window == sb_win) {
781 				if (xe->xe_button == Button2) {
782 					tk->tk_type = TK_SBGOTO;
783 					tk->tk_arg[0] = xe->xe_y;
784 					tk->tk_nargs = 1;
785 				}
786 			}
787 			break;
788 		    case ButtonRelease :
789 			/* Deal with a SendEvent */
790 			if (xe->xe_window != vt_win &&
791 			    xe->xe_window != main_win &&
792 			    xe->xe_window != sb_win) {
793 				switch (xe->xe_button) {
794 				case Button1:
795 				case Button3:
796 					xe->xe_window = sb_win;
797 					break;
798 				case Button2:
799 					xe->xe_window = vt_win;
800 					break;
801 				}
802 			}
803 			if (xe->xe_window == sb_win) {
804 				switch (xe->xe_button) {
805 				    case Button1 :
806 					tk->tk_type = TK_SBUP;
807 					tk->tk_arg[0] = xe->xe_y;
808 					tk->tk_nargs = 1;
809 					break;
810 				    case Button3 :
811 					tk->tk_type = TK_SBDOWN;
812 					tk->tk_arg[0] = xe->xe_y;
813 					tk->tk_nargs = 1;
814 					break;
815 				}
816 			} else if (xe->xe_window == vt_win &&
817 						(xe->xe_state & ControlMask) == 0) {
818 				switch (xe->xe_button) {
819 				    case Button1 :
820 				    case Button3 :
821 					tk->tk_type = TK_SELECT;
822 					tk->tk_arg[0] = xe->xe_time;
823 					tk->tk_nargs = 1;
824 					break;
825 				    case Button2 :
826 					tk->tk_type = TK_SELINSRT;
827 					tk->tk_arg[0] = xe->xe_time;
828 					tk->tk_arg[1] = xe->xe_x;
829 					tk->tk_arg[2] = xe->xe_y;
830 					tk->tk_nargs = 3;
831 					break;
832 				}
833 			}
834 			break;
835 		    case MotionNotify :
836 			if (xe->xe_window == sb_win && (xe->xe_state & Button2Mask)) {
837 				Window root, child;
838 				int root_x, root_y, x, y;
839 				unsigned int mods;
840 
841 				XQueryPointer(display,sb_win,&root,&child,
842 					&root_x,&root_y,&x,&y,&mods);
843 				if (mods & Button2Mask) {
844 					tk->tk_type = TK_SBGOTO;
845 					tk->tk_arg[0] = y;
846 					tk->tk_nargs = 1;
847 				}
848 				break;
849 			}
850 			if (xe->xe_window == vt_win && (xe->xe_state & Button1Mask) &&
851 						       !(xe->xe_state & ControlMask)) {
852 				tk->tk_type = TK_SELDRAG;
853 				tk->tk_arg[0] = xe->xe_x;
854 				tk->tk_arg[1] = xe->xe_y;
855 				tk->tk_nargs = 2;
856 				break;
857 			}
858 			break;
859 
860 		}
861 		free((void *)xe);
862 		return;
863 	}
864 	if ((c = get_com_char(GET_XEVENTS)) == GCC_NULL) {
865 		tk->tk_type = TK_NULL;
866 		return;
867 	}
868 
869 	if (c == EOF) {
870 		tk->tk_type = TK_EOF;
871 		return;
872 	}
873 	if (is_string_char(c)) {
874 		i = 0;
875 		tk->tk_nlcount = 0;
876 		do {
877 			tk->tk_string[i++] = c;
878 			c = get_com_char(1);
879 			if (c == '\n' && ++tk->tk_nlcount >= NLMAX) {
880 				tk->tk_nlcount--;
881 				break;
882 			}
883 		} while (is_string_char(c) && i < TKS_MAX);
884 		tk->tk_length = i;
885 		tk->tk_string[i] = 0;
886 		tk->tk_type = TK_STRING;
887 		if (c != GCC_NULL)
888 			push_com_char(c);
889 	} else if (c == ESC) {
890 		c = get_com_char(0);
891 		if (c == '[') {
892 			c = get_com_char(0);
893 			if (c >= '<' && c <= '?') {
894 				tk->tk_private = c;
895 				c = get_com_char(0);
896 			}
897 
898 			/*  read any numerical arguments
899 			 */
900 			i = 0;
901 			do {
902 				n = 0;
903 				while (c >= '0' && c <= '9') {
904 					n = n * 10 + c - '0';
905 					c = get_com_char(0);
906 				}
907 				if (i < TK_MAX_ARGS)
908 					tk->tk_arg[i++] = n;
909 				if (c == ESC)
910 					push_com_char(c);
911 				if (c < ' ')
912 					return;
913 				if (c < '@')
914 					c = get_com_char(0);
915 			} while (c < '@' && c >= ' ');
916 			if (c == ESC)
917 				push_com_char(c);
918 			if (c < ' ')
919 				return;
920 			tk->tk_nargs = i;
921 			tk->tk_type = c;
922 		} else if (c == ']') {
923 			c = get_com_char(0);
924 			n = 0;
925 			while (c >= '0' && c <= '9') {
926 				n = n * 10 + c - '0';
927 				c = get_com_char(0);
928 			}
929 			tk->tk_arg[0] = n;
930 			tk->tk_nargs = 1;
931 			c = get_com_char(0);
932 			i = 0;
933 			while ((c & 0177) >= ' ' && i < TKS_MAX) {
934 				if (c >= ' ')
935 					tk->tk_string[i++] = c;
936 				c = get_com_char(0);
937 			}
938 			tk->tk_length = i;
939 			tk->tk_string[i] = 0;
940 			tk->tk_type = TK_TXTPAR;
941 		} else if (c == '#' || c == '(' || c == ')') {
942 			tk->tk_type = c;
943 			c = get_com_char(0);
944 			tk->tk_arg[0] = c;
945 			tk->tk_nargs = 1;
946 		} else if (c == '7' || c == '8' || c == '=' || c == '>') {
947 			tk->tk_type = c;
948 			tk->tk_nargs = 0;
949 		} else {
950 			switch (c) {
951 			    case 'D' :
952 				tk->tk_type = TK_IND;
953 				break;
954 			    case 'E' :
955 				tk->tk_type = TK_NEL;
956 				break;
957 			    case 'H' :
958 				tk->tk_type = TK_HTS;
959 				break;
960 			    case 'M' :
961 				tk->tk_type = TK_RI;
962 				break;
963 			    case 'N' :
964 				tk->tk_type = TK_SS2;
965 				break;
966 			    case 'O' :
967 				tk->tk_type = TK_SS3;
968 				break;
969 			    case 'Z' :
970 				tk->tk_type = TK_DECID;
971 				break;
972 			    default :
973 				return;
974 			}
975 		}
976 	} else {
977 		tk->tk_type = TK_CHAR;
978 		tk->tk_char = c;
979 	}
980 }
981 
982 #ifdef DEBUG
983 /*  Print out a token's numerical arguments. Just used by show_token()
984  */
985 static void
986 show_token_args(tk)
987 struct tokenst *tk;
988 {
989 	int i;
990 
991 	for (i = 0; i < tk->tk_nargs; i++) {
992 		if (i == 0)
993 			printf(" (%d",tk->tk_arg[i]);
994 		else
995 			printf(",%d",tk->tk_arg[i]);
996 	}
997 	if (tk->tk_nargs > 0)
998 		printf(")");
999 	if (tk->tk_private !=0)
1000 		putchar(tk->tk_private);
1001 }
1002 
1003 /*  Print out a token's numerical arguments in hex. Just used by show_token()
1004  */
1005 static void
1006 show_hex_token_args(tk)
1007 struct tokenst *tk;
1008 {
1009 	int i;
1010 
1011 	for (i = 0; i < tk->tk_nargs; i++) {
1012 		if (i == 0)
1013 			printf(" (0x%x",tk->tk_arg[i]);
1014 		else
1015 			printf(",0x%x",tk->tk_arg[i]);
1016 	}
1017 	if (tk->tk_nargs > 0)
1018 		printf(")");
1019 	if (tk->tk_private !=0)
1020 		putchar(tk->tk_private);
1021 }
1022 
1023 /*  Print out the contents of an input token - used for debugging.
1024  */
1025 void
1026 show_token(tk)
1027 struct tokenst *tk;
1028 {
1029 
1030 	/*  Screen out token types that are not currently of interest.
1031 	 */
1032 	switch (tk->tk_type) {
1033 		case TK_SELDRAG :
1034 			return;
1035 	}
1036 
1037 	switch (tk->tk_type) {
1038 		case TK_STRING :
1039 			printf("token(TK_STRING)");
1040 			printf(" \"%s\"",tk->tk_string);
1041 			break;
1042 		case TK_TXTPAR :
1043 			printf("token(TK_TXTPAR)");
1044 			printf(" (%d) \"%s\"",tk->tk_arg[0],tk->tk_string);
1045 			break;
1046 		case TK_CHAR :
1047 			printf("token(TK_CHAR)");
1048 			printf(" <%o>",tk->tk_char);
1049 			break;
1050 		case TK_EOF :
1051 			printf("token(TK_EOF)");
1052 			show_token_args(tk);
1053 			break;
1054 		case TK_FOCUS :
1055 			printf("token(TK_FOCUS)");
1056 			printf(" <%d>",tk->tk_region);
1057 			show_token_args(tk);
1058 			break;
1059 		case TK_ENTRY :
1060 			printf("token(TK_ENTRY)");
1061 			printf(" <%d>",tk->tk_region);
1062 			show_token_args(tk);
1063 			break;
1064 		case TK_SBSWITCH :
1065 			printf("token(TK_SBSWITCH)");
1066 			show_token_args(tk);
1067 			break;
1068 		case TK_SBGOTO :
1069 			printf("token(TK_SBGOTO)");
1070 			show_token_args(tk);
1071 			break;
1072 		case TK_SBUP :
1073 			printf("token(TK_SBUP)");
1074 			show_token_args(tk);
1075 			break;
1076 		case TK_SBDOWN :
1077 			printf("token(TK_SBDOWN)");
1078 			show_token_args(tk);
1079 			break;
1080 		case TK_EXPOSE :
1081 			printf("token(TK_EXPOSE)");
1082 			printf("(%d)",tk->tk_region);
1083 			show_token_args(tk);
1084 			break;
1085 		case TK_RESIZE :
1086 			printf("token(TK_RESIZE)");
1087 			show_token_args(tk);
1088 			break;
1089 		case TK_SELSTART :
1090 			printf("token(TK_SELSTART)");
1091 			show_token_args(tk);
1092 			break;
1093 		case TK_SELEXTND :
1094 			printf("token(TK_SELEXTND)");
1095 			show_token_args(tk);
1096 			break;
1097 		case TK_SELDRAG :
1098 			printf("token(TK_SELDRAG)");
1099 			show_token_args(tk);
1100 			break;
1101 		case TK_SELINSRT :
1102 			printf("token(TK_SELINSRT)");
1103 			show_token_args(tk);
1104 			break;
1105 		case TK_SELECT :
1106 			printf("token(TK_SELECT)");
1107 			show_token_args(tk);
1108 			break;
1109 		case TK_SELWORD :
1110 			printf("token(TK_SELWORD)");
1111 			show_token_args(tk);
1112 			break;
1113 		case TK_SELLINE :
1114 			printf("token(TK_SELLINE)");
1115 			show_token_args(tk);
1116 			break;
1117 		case TK_SELCLEAR :
1118 			printf("token(TK_SELCLEAR)");
1119 			show_token_args(tk);
1120 			break;
1121 		case TK_SELNOTIFY :
1122 			printf("token(TK_SELNOTIFY)");
1123 			show_hex_token_args(tk);
1124 			break;
1125 		case TK_SELREQUEST :
1126 			printf("token(TK_SELREQUEST)");
1127 			show_hex_token_args(tk);
1128 			break;
1129 		case TK_CUU :
1130 			printf("token(TK_CUU)");
1131 			show_token_args(tk);
1132 			break;
1133 		case TK_CUD :
1134 			printf("token(TK_CUD)");
1135 			show_token_args(tk);
1136 			break;
1137 		case TK_CUF :
1138 			printf("token(TK_CUF)");
1139 			show_token_args(tk);
1140 			break;
1141 		case TK_CUB :
1142 			printf("token(TK_CUB)");
1143 			show_token_args(tk);
1144 			break;
1145 		case TK_CUP :
1146 			printf("token(TK_CUP)");
1147 			show_token_args(tk);
1148 			break;
1149 		case TK_ED :
1150 			printf("token(TK_ED)");
1151 			show_token_args(tk);
1152 			break;
1153 		case TK_EL :
1154 			printf("token(TK_EL)");
1155 			show_token_args(tk);
1156 			break;
1157 		case TK_IL :
1158 			printf("token(TK_IL)");
1159 			show_token_args(tk);
1160 			break;
1161 		case TK_DL :
1162 			printf("token(TK_DL)");
1163 			show_token_args(tk);
1164 			break;
1165 		case TK_DCH :
1166 			printf("token(TK_DCH)");
1167 			show_token_args(tk);
1168 			break;
1169 		case TK_ICH :
1170 			printf("token(TK_ICH)");
1171 			show_token_args(tk);
1172 			break;
1173 		case TK_DA :
1174 			printf("token(TK_DA)");
1175 			show_token_args(tk);
1176 			break;
1177 		case TK_HVP :
1178 			printf("token(TK_HVP)");
1179 			show_token_args(tk);
1180 			break;
1181 		case TK_TBC :
1182 			printf("token(TK_TBC)");
1183 			show_token_args(tk);
1184 			break;
1185 		case TK_SET :
1186 			printf("token(TK_SET)");
1187 			show_token_args(tk);
1188 			break;
1189 		case TK_RESET :
1190 			printf("token(TK_RESET)");
1191 			show_token_args(tk);
1192 			break;
1193 		case TK_SGR :
1194 			printf("token(TK_SGR)");
1195 			show_token_args(tk);
1196 			break;
1197 		case TK_DSR :
1198 			printf("token(TK_DSR)");
1199 			show_token_args(tk);
1200 			break;
1201 		case TK_DECSTBM :
1202 			printf("token(TK_DECSTBM)");
1203 			show_token_args(tk);
1204 			break;
1205 		case TK_DECSWH :
1206 			printf("token(TK_DECSWH)");
1207 			show_token_args(tk);
1208 			break;
1209 		case TK_SCS0 :
1210 			printf("token(TK_SCS0)");
1211 			show_token_args(tk);
1212 			break;
1213 		case TK_SCS1 :
1214 			printf("token(TK_SCS1)");
1215 			show_token_args(tk);
1216 			break;
1217 		case TK_DECSC :
1218 			printf("token(TK_DECSC)");
1219 			show_token_args(tk);
1220 			break;
1221 		case TK_DECRC :
1222 			printf("token(TK_DECRC)");
1223 			show_token_args(tk);
1224 			break;
1225 		case TK_DECPAM :
1226 			printf("token(TK_DECPAM)");
1227 			show_token_args(tk);
1228 			break;
1229 		case TK_DECPNM :
1230 			printf("token(TK_DECPNM)");
1231 			show_token_args(tk);
1232 			break;
1233 		case TK_IND :
1234 			printf("token(TK_IND)");
1235 			show_token_args(tk);
1236 			break;
1237 		case TK_NEL :
1238 			printf("token(TK_NEL)");
1239 			show_token_args(tk);
1240 			break;
1241 		case TK_HTS :
1242 			printf("token(TK_HTS)");
1243 			show_token_args(tk);
1244 			break;
1245 		case TK_RI :
1246 			printf("token(TK_RI)");
1247 			show_token_args(tk);
1248 			break;
1249 		case TK_SS2 :
1250 			printf("token(TK_SS2)");
1251 			show_token_args(tk);
1252 			break;
1253 		case TK_SS3 :
1254 			printf("token(TK_SS3)");
1255 			show_token_args(tk);
1256 			break;
1257 		case TK_DECID :
1258 			printf("token(TK_DECID)");
1259 			show_token_args(tk);
1260 			break;
1261 		case TK_NULL :
1262 			return;
1263 		default :
1264 			printf("unknown token <%o>",tk->tk_type);
1265 			show_token_args(tk);
1266 			break;
1267 	}
1268 	printf("\n");
1269 }
1270 #endif /* DEBUG */
1271