initial commit
[profile/ivi/xterm.git] / trace.c
1 /* $XTermId: trace.c,v 1.119 2011/02/09 10:04:50 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
60 extern "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
71 const char *trace_who = "parent";
72
73 static FILE *trace_fp;
74
75 void
76 Trace(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
120 void
121 TraceClose(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
134 void
135 TraceIds(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
151 static void
152 formatAscii(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
181 const char *
182 visibleChrsetName(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
203 char *
204 visibleChars(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
234 char *
235 visibleIChars(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
270 char *
271 visibleIChar(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
307 const char *
308 visibleKeyboardType(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
323 const char *
324 visibleEventType(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
365 const char *
366 visibleNotifyDetail(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
382 const char *
383 visibleSelectionTarget(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
402 const char *
403 visibleXError(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
437 static char *
438 ScrnText(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
451 void
452 LineClrFlag(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
464 void
465 LineSetFlag(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
477 int
478 LineTstFlag(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
494 void
495 TraceFocus(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
527 void
528 TraceSizeHints(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
557 void
558 TraceWMSizeHints(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 */
572 static int
573 no_error(Display * dpy GCC_UNUSED, XErrorEvent * event GCC_UNUSED)
574 {
575     return 1;
576 }
577
578 void
579 TraceTranslations(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
605 int
606 TraceResizeRequest(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
627 void
628 TraceXtermResources(void)
629 {
630     XTERM_RESOURCE *resp = &resource;
631
632     Trace("XTERM_RESOURCE settings:\n");
633     XRES_S(xterm_name);
634     XRES_S(icon_geometry);
635     XRES_S(title);
636     XRES_S(icon_name);
637     XRES_S(term_name);
638     XRES_S(tty_modes);
639     XRES_B(hold_screen);
640     XRES_B(utmpInhibit);
641     XRES_B(utmpDisplayId);
642     XRES_B(messages);
643 #if OPT_SUNPC_KBD
644     XRES_B(sunKeyboard);
645 #endif
646 #if OPT_HP_FUNC_KEYS
647     XRES_B(hpFunctionKeys);
648 #endif
649 #if OPT_SCO_FUNC_KEYS
650     XRES_B(scoFunctionKeys);
651 #endif
652 #if OPT_SUN_FUNC_KEYS
653     XRES_B(sunFunctionKeys);
654 #endif
655 #if OPT_INITIAL_ERASE
656     XRES_B(ptyInitialErase);
657     XRES_B(backarrow_is_erase);
658 #endif
659     XRES_B(useInsertMode);
660 #if OPT_ZICONBEEP
661     XRES_I(zIconBeep);
662 #endif
663 #if OPT_PTY_HANDSHAKE
664     XRES_B(wait_for_map);
665     XRES_B(ptyHandshake);
666     XRES_B(ptySttySize);
667 #endif
668 #if OPT_SAME_NAME
669     XRES_B(sameName);
670 #endif
671 #if OPT_SESSION_MGT
672     XRES_B(sessionMgt);
673 #endif
674 }
675
676 void
677 TraceArgv(const char *tag, char **argv)
678 {
679     int n = 0;
680
681     TRACE(("%s:\n", tag));
682     while (*argv != 0) {
683         TRACE(("  %d:%s\n", n++, *argv++));
684     }
685 }
686
687 static char *
688 parse_option(char *dst, String src, int first)
689 {
690     char *s;
691
692     if (!strncmp(src, "-/+", (size_t) 3)) {
693         dst[0] = (char) first;
694         strcpy(dst + 1, src + 3);
695     } else {
696         strcpy(dst, src);
697     }
698     for (s = dst; *s != '\0'; s++) {
699         if (*s == '#' || *s == '%' || *s == 'S') {
700             s[1] = '\0';
701         } else if (*s == ' ') {
702             *s = '\0';
703             break;
704         }
705     }
706     return dst;
707 }
708
709 static Bool
710 same_option(OptionHelp * opt, XrmOptionDescRec * res)
711 {
712     char temp[BUFSIZ];
713     return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
714 }
715
716 static Bool
717 standard_option(String opt)
718 {
719     static const char *table[] =
720     {
721         "+rv",
722         "+synchronous",
723         "-background",
724         "-bd",
725         "-bg",
726         "-bordercolor",
727         "-borderwidth",
728         "-bw",
729         "-display",
730         "-fg",
731         "-fn",
732         "-font",
733         "-foreground",
734         "-geometry",
735         "-iconic",
736         "-name",
737         "-reverse",
738         "-rv",
739         "-selectionTimeout",
740         "-synchronous",
741         "-title",
742         "-xnllanguage",
743         "-xrm",
744         "-xtsessionID",
745     };
746     Cardinal n;
747     char temp[BUFSIZ];
748
749     opt = parse_option(temp, opt, '-');
750     for (n = 0; n < XtNumber(table); n++) {
751         if (!strcmp(opt, table[n]))
752             return True;
753     }
754     return False;
755 }
756
757 /*
758  * Analyse the options/help messages for inconsistencies.
759  */
760 void
761 TraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
762 {
763     OptionHelp *opt_array = sortedOpts(options, resources, res_count);
764     size_t j, k;
765     XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
766     Bool first, found;
767
768     TRACE(("Checking options-tables for inconsistencies:\n"));
769
770 #if 0
771     TRACE(("Options listed in help-message:\n"));
772     for (j = 0; options[j].opt != 0; j++)
773         TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
774     TRACE(("Options listed in resource-table:\n"));
775     for (j = 0; j < res_count; j++)
776         TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
777 #endif
778
779     /* list all options[] not found in resources[] */
780     for (j = 0, first = True; options[j].opt != 0; j++) {
781         found = False;
782         for (k = 0; k < res_count; k++) {
783             if (same_option(&opt_array[j], &res_array[k])) {
784                 found = True;
785                 break;
786             }
787         }
788         if (!found) {
789             if (first) {
790                 TRACE(("Options listed in help, not found in resource list:\n"));
791                 first = False;
792             }
793             TRACE(("  %-28s%s\n", opt_array[j].opt,
794                    standard_option(opt_array[j].opt) ? " (standard)" : ""));
795         }
796     }
797
798     /* list all resources[] not found in options[] */
799     for (j = 0, first = True; j < res_count; j++) {
800         found = False;
801         for (k = 0; options[k].opt != 0; k++) {
802             if (same_option(&opt_array[k], &res_array[j])) {
803                 found = True;
804                 break;
805             }
806         }
807         if (!found) {
808             if (first) {
809                 TRACE(("Resource list items not found in options-help:\n"));
810                 first = False;
811             }
812             TRACE(("  %s\n", res_array[j].option));
813         }
814     }
815
816     TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
817     for (j = 0; j < res_count; j++) {
818         switch (res_array[j].argKind) {
819         case XrmoptionSkipArg:
820             TRACE(("  %-28s {param}\n", res_array[j].option));
821             break;
822         case XrmoptionSkipNArgs:
823             TRACE(("  %-28s {%ld params}\n", res_array[j].option, (long)
824                    res_array[j].value));
825             break;
826         case XrmoptionSkipLine:
827             TRACE(("  %-28s {remainder of line}\n", res_array[j].option));
828             break;
829         case XrmoptionIsArg:
830         case XrmoptionNoArg:
831         case XrmoptionResArg:
832         case XrmoptionSepArg:
833         case XrmoptionStickyArg:
834         default:
835             break;
836         }
837     }
838 }
839 #else
840 extern void empty_trace(void);
841 void
842 empty_trace(void)
843 {
844 }
845 #endif