trace.c revision a1f3da82
1/* $XTermId: trace.c,v 1.121 2011/02/17 00:34:47 tom Exp $ */
2
3/*
4 * Copyright 1997-2010,2011 by Thomas E. Dickey
5 *
6 *                         All Rights Reserved
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * Except as contained in this notice, the name(s) of the above copyright
28 * holders shall not be used in advertising or otherwise to promote the
29 * sale, use or other dealings in this Software without prior written
30 * authorization.
31 *
32 */
33
34/*
35 * debugging support via TRACE macro.
36 */
37
38#include <xterm.h>		/* for definition of GCC_UNUSED */
39
40#if OPT_TRACE
41
42#include <data.h>
43#include <trace.h>
44
45#include <time.h>
46#include <stdlib.h>
47#include <unistd.h>
48#include <sys/types.h>
49#include <stdio.h>
50#include <stdarg.h>
51#include <assert.h>
52
53#include <X11/Xatom.h>
54#include <X11/Xmu/Atoms.h>
55
56#ifdef HAVE_X11_TRANSLATEI_H
57#include <X11/TranslateI.h>
58#else
59#ifdef __cplusplus
60extern "C" {
61#endif
62
63    extern String _XtPrintXlations(Widget w,
64				   XtTranslations xlations,
65				   Widget accelWidget,
66				   _XtBoolean includeRHS);
67#ifdef __cplusplus
68}
69#endif
70#endif
71const char *trace_who = "parent";
72
73static FILE *trace_fp;
74
75void
76Trace(const char *fmt,...)
77{
78    static const char *trace_out;
79    va_list ap;
80
81    if (trace_fp != 0
82	&& trace_who != trace_out) {
83	fclose(trace_fp);
84	trace_fp = 0;
85    }
86    trace_out = trace_who;
87
88    if (!trace_fp) {
89	char name[BUFSIZ];
90#if 0				/* usually I do not want unique names */
91	int unique;
92	for (unique = 0;; ++unique) {
93	    if (unique)
94		sprintf(name, "Trace-%s.out-%d", trace_who, unique);
95	    else
96		sprintf(name, "Trace-%s.out", trace_who);
97	    if ((trace_fp = fopen(name, "r")) == 0) {
98		break;
99	    }
100	    fclose(trace_fp);
101	}
102#else
103	sprintf(name, "Trace-%s.out", trace_who);
104#endif
105	trace_fp = fopen(name, "w");
106	if (trace_fp != 0) {
107	    fprintf(trace_fp, "%s\n", xtermVersion());
108	    TraceIds(NULL, 0);
109	}
110    }
111    if (!trace_fp)
112	abort();
113
114    va_start(ap, fmt);
115    vfprintf(trace_fp, fmt, ap);
116    (void) fflush(trace_fp);
117    va_end(ap);
118}
119
120void
121TraceClose(void)
122{
123    if (trace_fp != 0) {
124	(void) fclose(trace_fp);
125	(void) fflush(stdout);
126	(void) fflush(stderr);
127	(void) visibleChars(NULL, 0);
128	(void) visibleIChars(NULL, 0);
129	(void) visibleIChar(NULL, 0);
130	trace_fp = 0;
131    }
132}
133
134void
135TraceIds(const char *fname, int lnum)
136{
137    Trace("process %d ", (int) getpid());
138#ifdef HAVE_UNISTD_H
139    Trace("real (%u/%u) effective (%u/%u)",
140	  (unsigned) getuid(), (unsigned) getgid(),
141	  (unsigned) geteuid(), (unsigned) getegid());
142#endif
143    if (fname != 0) {
144	Trace(" (%s@%d)\n", fname, lnum);
145    } else {
146	time_t now = time((time_t *) 0);
147	Trace("-- %s", ctime(&now));
148    }
149}
150
151static void
152formatAscii(char *dst, unsigned value)
153{
154    switch (value) {
155    case '\\':
156	sprintf(dst, "\\\\");
157	break;
158    case '\b':
159	sprintf(dst, "\\b");
160	break;
161    case '\n':
162	sprintf(dst, "\\n");
163	break;
164    case '\r':
165	sprintf(dst, "\\r");
166	break;
167    case '\t':
168	sprintf(dst, "\\t");
169	break;
170    default:
171	if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(value) < 160))
172	    sprintf(dst, "\\%03o", value);
173	else
174	    sprintf(dst, "%c", CharOf(value));
175	break;
176    }
177}
178
179#if OPT_DEC_CHRSET
180
181const char *
182visibleChrsetName(unsigned chrset)
183{
184    const char *result = "?";
185    switch (chrset) {
186    case CSET_SWL:
187	result = "CSET_SWL";
188	break;
189    case CSET_DHL_TOP:
190	result = "CSET_DHL_TOP";
191	break;
192    case CSET_DHL_BOT:
193	result = "CSET_DHL_BOT";
194	break;
195    case CSET_DWL:
196	result = "CSET_DWL";
197	break;
198    }
199    return result;
200}
201#endif
202
203char *
204visibleChars(const Char * buf, unsigned len)
205{
206    static char *result;
207    static unsigned used;
208
209    if (buf != 0) {
210	unsigned limit = ((len + 1) * 8) + 1;
211	char *dst;
212
213	if (limit > used) {
214	    used = limit;
215	    result = XtRealloc(result, used);
216	}
217	if (result != 0) {
218	    dst = result;
219	    *dst = '\0';
220	    while (len--) {
221		unsigned value = *buf++;
222		formatAscii(dst, value);
223		dst += strlen(dst);
224	    }
225	}
226    } else if (result != 0) {
227	free(result);
228	result = 0;
229	used = 0;
230    }
231    return result;
232}
233
234char *
235visibleIChars(IChar * buf, unsigned len)
236{
237    static char *result;
238    static unsigned used;
239
240    if (buf != 0) {
241	unsigned limit = ((len + 1) * 8) + 1;
242	char *dst;
243
244	if (limit > used) {
245	    used = limit;
246	    result = XtRealloc(result, used);
247	}
248	if (result != 0) {
249	    dst = result;
250	    *dst = '\0';
251	    while (len--) {
252		unsigned value = *buf++;
253#if OPT_WIDE_CHARS
254		if (value > 255)
255		    sprintf(dst, "\\u+%04X", value);
256		else
257#endif
258		    formatAscii(dst, value);
259		dst += strlen(dst);
260	    }
261	}
262    } else if (result != 0) {
263	free(result);
264	result = 0;
265	used = 0;
266    }
267    return result;
268}
269
270char *
271visibleIChar(IChar * buf, unsigned len)
272{
273    static char *result;
274    static unsigned used;
275
276    if (buf != 0) {
277	unsigned limit = ((len + 1) * 8) + 1;
278	char *dst;
279
280	if (limit > used) {
281	    used = limit;
282	    result = XtRealloc(result, used);
283	}
284	if (result != 0) {
285	    dst = result;
286	    while (len--) {
287		unsigned value = *buf++;
288#if OPT_WIDE_CHARS
289		if (value > 255)
290		    sprintf(dst, "\\u+%04X", value);
291		else
292#endif
293		    formatAscii(dst, value);
294		dst += strlen(dst);
295	    }
296	}
297    } else if (result != 0) {
298	free(result);
299	result = 0;
300	used = 0;
301    }
302    return result;
303}
304
305#define CASETYPE(name) case name: result = #name; break
306
307const char *
308visibleKeyboardType(xtermKeyboardType type)
309{
310    const char *result = "?";
311    switch (type) {
312	CASETYPE(keyboardIsLegacy);	/* bogus vt220 codes for F1-F4, etc. */
313	CASETYPE(keyboardIsDefault);
314	CASETYPE(keyboardIsHP);
315	CASETYPE(keyboardIsSCO);
316	CASETYPE(keyboardIsSun);
317	CASETYPE(keyboardIsTermcap);
318	CASETYPE(keyboardIsVT220);
319    }
320    return result;
321}
322
323const char *
324visibleEventType(int type)
325{
326    const char *result = "?";
327    switch (type) {
328	CASETYPE(KeyPress);
329	CASETYPE(KeyRelease);
330	CASETYPE(ButtonPress);
331	CASETYPE(ButtonRelease);
332	CASETYPE(MotionNotify);
333	CASETYPE(EnterNotify);
334	CASETYPE(LeaveNotify);
335	CASETYPE(FocusIn);
336	CASETYPE(FocusOut);
337	CASETYPE(KeymapNotify);
338	CASETYPE(Expose);
339	CASETYPE(GraphicsExpose);
340	CASETYPE(NoExpose);
341	CASETYPE(VisibilityNotify);
342	CASETYPE(CreateNotify);
343	CASETYPE(DestroyNotify);
344	CASETYPE(UnmapNotify);
345	CASETYPE(MapNotify);
346	CASETYPE(MapRequest);
347	CASETYPE(ReparentNotify);
348	CASETYPE(ConfigureNotify);
349	CASETYPE(ConfigureRequest);
350	CASETYPE(GravityNotify);
351	CASETYPE(ResizeRequest);
352	CASETYPE(CirculateNotify);
353	CASETYPE(CirculateRequest);
354	CASETYPE(PropertyNotify);
355	CASETYPE(SelectionClear);
356	CASETYPE(SelectionRequest);
357	CASETYPE(SelectionNotify);
358	CASETYPE(ColormapNotify);
359	CASETYPE(ClientMessage);
360	CASETYPE(MappingNotify);
361    }
362    return result;
363}
364
365const char *
366visibleNotifyDetail(int code)
367{
368    const char *result = "?";
369    switch (code) {
370	CASETYPE(NotifyAncestor);
371	CASETYPE(NotifyVirtual);
372	CASETYPE(NotifyInferior);
373	CASETYPE(NotifyNonlinear);
374	CASETYPE(NotifyNonlinearVirtual);
375	CASETYPE(NotifyPointer);
376	CASETYPE(NotifyPointerRoot);
377	CASETYPE(NotifyDetailNone);
378    }
379    return result;
380}
381
382const char *
383visibleSelectionTarget(Display * d, Atom a)
384{
385    const char *result = "?";
386
387    if (a == XA_STRING) {
388	result = "XA_STRING";
389    } else if (a == XA_TEXT(d)) {
390	result = "XA_TEXT()";
391    } else if (a == XA_COMPOUND_TEXT(d)) {
392	result = "XA_COMPOUND_TEXT()";
393    } else if (a == XA_UTF8_STRING(d)) {
394	result = "XA_UTF8_STRING()";
395    } else if (a == XA_TARGETS(d)) {
396	result = "XA_TARGETS()";
397    }
398
399    return result;
400}
401
402const char *
403visibleXError(int code)
404{
405    static char temp[80];
406    const char *result = "?";
407    switch (code) {
408	CASETYPE(Success);
409	CASETYPE(BadRequest);
410	CASETYPE(BadValue);
411	CASETYPE(BadWindow);
412	CASETYPE(BadPixmap);
413	CASETYPE(BadAtom);
414	CASETYPE(BadCursor);
415	CASETYPE(BadFont);
416	CASETYPE(BadMatch);
417	CASETYPE(BadDrawable);
418	CASETYPE(BadAccess);
419	CASETYPE(BadAlloc);
420	CASETYPE(BadColor);
421	CASETYPE(BadGC);
422	CASETYPE(BadIDChoice);
423	CASETYPE(BadName);
424	CASETYPE(BadLength);
425	CASETYPE(BadImplementation);
426    default:
427	sprintf(temp, "%d", code);
428	result = temp;
429	break;
430    }
431    return result;
432}
433
434#if OPT_TRACE_FLAGS
435#define isScrnFlag(flag) ((flag) == LINEWRAPPED)
436
437static char *
438ScrnText(LineData * ld)
439{
440    return visibleIChars(ld->charData, ld->lineSize);
441}
442
443#define SHOW_BAD_LINE(name, ld) \
444	Trace("OOPS " #name " bad row\n")
445
446#define SHOW_SCRN_FLAG(name,code) \
447	Trace(#name " %s:%s\n", \
448	      code ? "*" : "", \
449	      ScrnText(ld))
450
451void
452LineClrFlag(LineData * ld, int flag)
453{
454    if (ld == 0) {
455	SHOW_BAD_LINE(LineClrFlag, ld);
456	assert(0);
457    } else if (isScrnFlag(flag)) {
458	SHOW_SCRN_FLAG(LineClrFlag, 0);
459    }
460
461    LineFlags(ld) &= ~flag;
462}
463
464void
465LineSetFlag(LineData * ld, int flag)
466{
467    if (ld == 0) {
468	SHOW_BAD_LINE(LineSetFlag, ld);
469	assert(0);
470    } else if (isScrnFlag(flag)) {
471	SHOW_SCRN_FLAG(LineSetFlag, 1);
472    }
473
474    LineFlags(ld) |= flag;
475}
476
477int
478LineTstFlag(LineData ld, int flag)
479{
480    int code = 0;
481    if (ld == 0) {
482	SHOW_BAD_LINE(LineTstFlag, ld);
483    } else {
484	code = LineFlags(ld);
485
486	if (isScrnFlag(flag)) {
487	    SHOW_SCRN_FLAG(LineTstFlag, code);
488	}
489    }
490    return code;
491}
492#endif /* OPT_TRACE_FLAGS */
493
494void
495TraceFocus(Widget w, XEvent * ev)
496{
497    TRACE(("trace_focus event type %d:%s\n",
498	   ev->type, visibleEventType(ev->type)));
499    switch (ev->type) {
500    case FocusIn:
501    case FocusOut:
502	{
503	    XFocusChangeEvent *event = (XFocusChangeEvent *) ev;
504	    TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail)));
505	    TRACE(("\tmode:   %d\n", event->mode));
506	    TRACE(("\twindow: %#lx\n", event->window));
507	}
508	break;
509    case EnterNotify:
510    case LeaveNotify:
511	{
512	    XCrossingEvent *event = (XCrossingEvent *) ev;
513	    TRACE(("\tdetail:    %s\n", visibleNotifyDetail(event->detail)));
514	    TRACE(("\tmode:      %d\n", event->mode));
515	    TRACE(("\twindow:    %#lx\n", event->window));
516	    TRACE(("\troot:      %#lx\n", event->root));
517	    TRACE(("\tsubwindow: %#lx\n", event->subwindow));
518	}
519	break;
520    }
521    while (w != 0) {
522	TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
523	w = XtParent(w);
524    }
525}
526
527void
528TraceSizeHints(XSizeHints * hints)
529{
530    TRACE(("size hints:\n"));
531    if (hints->flags & (USPosition | PPosition))
532	TRACE(("   position   %d,%d%s%s\n", hints->y, hints->x,
533	       hints->flags & USPosition ? " user" : "",
534	       hints->flags & PPosition ? " prog" : ""));
535    if (hints->flags & (USSize | PSize))
536	TRACE(("   size       %d,%d%s%s\n", hints->height, hints->width,
537	       hints->flags & USSize ? " user" : "",
538	       hints->flags & PSize ? " prog" : ""));
539    if (hints->flags & PMinSize)
540	TRACE(("   min        %d,%d\n", hints->min_height, hints->min_width));
541    if (hints->flags & PMaxSize)
542	TRACE(("   max        %d,%d\n", hints->max_height, hints->max_width));
543    if (hints->flags & PResizeInc)
544	TRACE(("   inc        %d,%d\n", hints->height_inc, hints->width_inc));
545    else
546	TRACE(("   inc        NONE!\n"));
547    if (hints->flags & PAspect)
548	TRACE(("   min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y));
549    if (hints->flags & PAspect)
550	TRACE(("   max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y));
551    if (hints->flags & PBaseSize)
552	TRACE(("   base       %d,%d\n", hints->base_height, hints->base_width));
553    if (hints->flags & PWinGravity)
554	TRACE(("   gravity    %d\n", hints->win_gravity));
555}
556
557void
558TraceWMSizeHints(XtermWidget xw)
559{
560    XSizeHints sizehints = xw->hints;
561
562    getXtermSizeHints(xw);
563    TraceSizeHints(&xw->hints);
564    xw->hints = sizehints;
565}
566
567/*
568 * Some calls to XGetAtom() will fail, and we don't want to stop.  So we use
569 * our own error-handler.
570 */
571/* ARGSUSED */
572static int
573no_error(Display * dpy GCC_UNUSED, XErrorEvent * event GCC_UNUSED)
574{
575    return 1;
576}
577
578void
579TraceTranslations(const char *name, Widget w)
580{
581    String result;
582    XErrorHandler save = XSetErrorHandler(no_error);
583    XtTranslations xlations;
584    Widget xcelerat;
585
586    TRACE(("TraceTranslations for %s (widget %#lx) {{\n", name, (long) w));
587    if (w) {
588	XtVaGetValues(w,
589		      XtNtranslations, &xlations,
590		      XtNaccelerators, &xcelerat,
591		      (XtPointer) 0);
592	TRACE(("... xlations %#08lx\n", (long) xlations));
593	TRACE(("... xcelerat %#08lx\n", (long) xcelerat));
594	result = _XtPrintXlations(w, xlations, xcelerat, True);
595	TRACE(("%s\n", NonNull(result)));
596	if (result)
597	    XFree((char *) result);
598    } else {
599	TRACE(("none (widget is null)\n"));
600    }
601    TRACE(("}}\n"));
602    XSetErrorHandler(save);
603}
604
605int
606TraceResizeRequest(const char *fn, int ln, Widget w,
607		   Dimension reqwide,
608		   Dimension reqhigh,
609		   Dimension * gotwide,
610		   Dimension * gothigh)
611{
612    int rc;
613
614    TRACE(("%s@%d ResizeRequest %dx%d\n", fn, ln, reqhigh, reqwide));
615    rc = XtMakeResizeRequest((Widget) w, reqwide, reqhigh, gotwide, gothigh);
616    TRACE(("... ResizeRequest -> "));
617    if (gothigh && gotwide)
618	TRACE(("%dx%d ", *gothigh, *gotwide));
619    TRACE(("(%d)\n", rc));
620    return rc;
621}
622
623#define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name))
624#define XRES_B(name) Trace(#name " = %s\n", BtoS(resp->name))
625#define XRES_I(name) Trace(#name " = %d\n", resp->name)
626
627void
628TraceXtermResources(void)
629{
630    XTERM_RESOURCE *resp = &resource;
631
632    Trace("XTERM_RESOURCE settings:\n");
633    XRES_S(icon_geometry);
634    XRES_S(title);
635    XRES_S(icon_name);
636    XRES_S(term_name);
637    XRES_S(tty_modes);
638    XRES_B(hold_screen);
639    XRES_B(utmpInhibit);
640    XRES_B(utmpDisplayId);
641    XRES_B(messages);
642#if OPT_SUNPC_KBD
643    XRES_B(sunKeyboard);
644#endif
645#if OPT_HP_FUNC_KEYS
646    XRES_B(hpFunctionKeys);
647#endif
648#if OPT_SCO_FUNC_KEYS
649    XRES_B(scoFunctionKeys);
650#endif
651#if OPT_SUN_FUNC_KEYS
652    XRES_B(sunFunctionKeys);
653#endif
654#if OPT_INITIAL_ERASE
655    XRES_B(ptyInitialErase);
656    XRES_B(backarrow_is_erase);
657#endif
658    XRES_B(useInsertMode);
659#if OPT_ZICONBEEP
660    XRES_I(zIconBeep);
661#endif
662#if OPT_PTY_HANDSHAKE
663    XRES_B(wait_for_map);
664    XRES_B(ptyHandshake);
665    XRES_B(ptySttySize);
666#endif
667#if OPT_SAME_NAME
668    XRES_B(sameName);
669#endif
670#if OPT_SESSION_MGT
671    XRES_B(sessionMgt);
672#endif
673#if OPT_TOOLBAR
674    XRES_B(toolBar);
675#endif
676#if OPT_MAXIMIZE
677    XRES_B(maximized);
678    XRES_S(fullscreen_s);
679#endif
680}
681
682void
683TraceArgv(const char *tag, char **argv)
684{
685    int n = 0;
686
687    TRACE(("%s:\n", tag));
688    while (*argv != 0) {
689	TRACE(("  %d:%s\n", n++, *argv++));
690    }
691}
692
693static char *
694parse_option(char *dst, String src, int first)
695{
696    char *s;
697
698    if (!strncmp(src, "-/+", (size_t) 3)) {
699	dst[0] = (char) first;
700	strcpy(dst + 1, src + 3);
701    } else {
702	strcpy(dst, src);
703    }
704    for (s = dst; *s != '\0'; s++) {
705	if (*s == '#' || *s == '%' || *s == 'S') {
706	    s[1] = '\0';
707	} else if (*s == ' ') {
708	    *s = '\0';
709	    break;
710	}
711    }
712    return dst;
713}
714
715static Bool
716same_option(OptionHelp * opt, XrmOptionDescRec * res)
717{
718    char temp[BUFSIZ];
719    return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
720}
721
722static Bool
723standard_option(String opt)
724{
725    static const char *table[] =
726    {
727	"+rv",
728	"+synchronous",
729	"-background",
730	"-bd",
731	"-bg",
732	"-bordercolor",
733	"-borderwidth",
734	"-bw",
735	"-display",
736	"-fg",
737	"-fn",
738	"-font",
739	"-foreground",
740	"-geometry",
741	"-iconic",
742	"-name",
743	"-reverse",
744	"-rv",
745	"-selectionTimeout",
746	"-synchronous",
747	"-title",
748	"-xnllanguage",
749	"-xrm",
750	"-xtsessionID",
751    };
752    Cardinal n;
753    char temp[BUFSIZ];
754
755    opt = parse_option(temp, opt, '-');
756    for (n = 0; n < XtNumber(table); n++) {
757	if (!strcmp(opt, table[n]))
758	    return True;
759    }
760    return False;
761}
762
763/*
764 * Analyse the options/help messages for inconsistencies.
765 */
766void
767TraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
768{
769    OptionHelp *opt_array = sortedOpts(options, resources, res_count);
770    size_t j, k;
771    XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
772    Bool first, found;
773
774    TRACE(("Checking options-tables for inconsistencies:\n"));
775
776#if 0
777    TRACE(("Options listed in help-message:\n"));
778    for (j = 0; options[j].opt != 0; j++)
779	TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
780    TRACE(("Options listed in resource-table:\n"));
781    for (j = 0; j < res_count; j++)
782	TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
783#endif
784
785    /* list all options[] not found in resources[] */
786    for (j = 0, first = True; options[j].opt != 0; j++) {
787	found = False;
788	for (k = 0; k < res_count; k++) {
789	    if (same_option(&opt_array[j], &res_array[k])) {
790		found = True;
791		break;
792	    }
793	}
794	if (!found) {
795	    if (first) {
796		TRACE(("Options listed in help, not found in resource list:\n"));
797		first = False;
798	    }
799	    TRACE(("  %-28s%s\n", opt_array[j].opt,
800		   standard_option(opt_array[j].opt) ? " (standard)" : ""));
801	}
802    }
803
804    /* list all resources[] not found in options[] */
805    for (j = 0, first = True; j < res_count; j++) {
806	found = False;
807	for (k = 0; options[k].opt != 0; k++) {
808	    if (same_option(&opt_array[k], &res_array[j])) {
809		found = True;
810		break;
811	    }
812	}
813	if (!found) {
814	    if (first) {
815		TRACE(("Resource list items not found in options-help:\n"));
816		first = False;
817	    }
818	    TRACE(("  %s\n", res_array[j].option));
819	}
820    }
821
822    TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
823    for (j = 0; j < res_count; j++) {
824	switch (res_array[j].argKind) {
825	case XrmoptionSkipArg:
826	    TRACE(("  %-28s {param}\n", res_array[j].option));
827	    break;
828	case XrmoptionSkipNArgs:
829	    TRACE(("  %-28s {%ld params}\n", res_array[j].option, (long)
830		   res_array[j].value));
831	    break;
832	case XrmoptionSkipLine:
833	    TRACE(("  %-28s {remainder of line}\n", res_array[j].option));
834	    break;
835	case XrmoptionIsArg:
836	case XrmoptionNoArg:
837	case XrmoptionResArg:
838	case XrmoptionSepArg:
839	case XrmoptionStickyArg:
840	default:
841	    break;
842	}
843    }
844}
845#else
846extern void empty_trace(void);
847void
848empty_trace(void)
849{
850}
851#endif
852