1 /* $XTermId: trace.c,v 1.119 2011/02/09 10:04:50 tom Exp $ */
4 * Copyright 1997-2010,2011 by Thomas E. Dickey
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
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
35 * debugging support via TRACE macro.
38 #include <xterm.h> /* for definition of GCC_UNUSED */
48 #include <sys/types.h>
53 #include <X11/Xatom.h>
54 #include <X11/Xmu/Atoms.h>
56 #ifdef HAVE_X11_TRANSLATEI_H
57 #include <X11/TranslateI.h>
63 extern String _XtPrintXlations(Widget w,
64 XtTranslations xlations,
66 _XtBoolean includeRHS);
71 const char *trace_who = "parent";
73 static FILE *trace_fp;
76 Trace(const char *fmt,...)
78 static const char *trace_out;
82 && trace_who != trace_out) {
86 trace_out = trace_who;
90 #if 0 /* usually I do not want unique names */
92 for (unique = 0;; ++unique) {
94 sprintf(name, "Trace-%s.out-%d", trace_who, unique);
96 sprintf(name, "Trace-%s.out", trace_who);
97 if ((trace_fp = fopen(name, "r")) == 0) {
103 sprintf(name, "Trace-%s.out", trace_who);
105 trace_fp = fopen(name, "w");
107 fprintf(trace_fp, "%s\n", xtermVersion());
115 vfprintf(trace_fp, fmt, ap);
116 (void) fflush(trace_fp);
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);
135 TraceIds(const char *fname, int lnum)
137 Trace("process %d ", (int) getpid());
139 Trace("real (%u/%u) effective (%u/%u)",
140 (unsigned) getuid(), (unsigned) getgid(),
141 (unsigned) geteuid(), (unsigned) getegid());
144 Trace(" (%s@%d)\n", fname, lnum);
146 time_t now = time((time_t *) 0);
147 Trace("-- %s", ctime(&now));
152 formatAscii(char *dst, unsigned value)
156 sprintf(dst, "\\\\");
171 if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(value) < 160))
172 sprintf(dst, "\\%03o", value);
174 sprintf(dst, "%c", CharOf(value));
182 visibleChrsetName(unsigned chrset)
184 const char *result = "?";
190 result = "CSET_DHL_TOP";
193 result = "CSET_DHL_BOT";
204 visibleChars(const Char * buf, unsigned len)
207 static unsigned used;
210 unsigned limit = ((len + 1) * 8) + 1;
215 result = XtRealloc(result, used);
221 unsigned value = *buf++;
222 formatAscii(dst, value);
226 } else if (result != 0) {
235 visibleIChars(IChar * buf, unsigned len)
238 static unsigned used;
241 unsigned limit = ((len + 1) * 8) + 1;
246 result = XtRealloc(result, used);
252 unsigned value = *buf++;
255 sprintf(dst, "\\u+%04X", value);
258 formatAscii(dst, value);
262 } else if (result != 0) {
271 visibleIChar(IChar * buf, unsigned len)
274 static unsigned used;
277 unsigned limit = ((len + 1) * 8) + 1;
282 result = XtRealloc(result, used);
287 unsigned value = *buf++;
290 sprintf(dst, "\\u+%04X", value);
293 formatAscii(dst, value);
297 } else if (result != 0) {
305 #define CASETYPE(name) case name: result = #name; break
308 visibleKeyboardType(xtermKeyboardType type)
310 const char *result = "?";
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);
324 visibleEventType(int type)
326 const char *result = "?";
329 CASETYPE(KeyRelease);
330 CASETYPE(ButtonPress);
331 CASETYPE(ButtonRelease);
332 CASETYPE(MotionNotify);
333 CASETYPE(EnterNotify);
334 CASETYPE(LeaveNotify);
337 CASETYPE(KeymapNotify);
339 CASETYPE(GraphicsExpose);
341 CASETYPE(VisibilityNotify);
342 CASETYPE(CreateNotify);
343 CASETYPE(DestroyNotify);
344 CASETYPE(UnmapNotify);
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);
366 visibleNotifyDetail(int code)
368 const char *result = "?";
370 CASETYPE(NotifyAncestor);
371 CASETYPE(NotifyVirtual);
372 CASETYPE(NotifyInferior);
373 CASETYPE(NotifyNonlinear);
374 CASETYPE(NotifyNonlinearVirtual);
375 CASETYPE(NotifyPointer);
376 CASETYPE(NotifyPointerRoot);
377 CASETYPE(NotifyDetailNone);
383 visibleSelectionTarget(Display * d, Atom a)
385 const char *result = "?";
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()";
403 visibleXError(int code)
405 static char temp[80];
406 const char *result = "?";
409 CASETYPE(BadRequest);
417 CASETYPE(BadDrawable);
422 CASETYPE(BadIDChoice);
425 CASETYPE(BadImplementation);
427 sprintf(temp, "%d", code);
435 #define isScrnFlag(flag) ((flag) == LINEWRAPPED)
438 ScrnText(LineData * ld)
440 return visibleIChars(ld->charData, ld->lineSize);
443 #define SHOW_BAD_LINE(name, ld) \
444 Trace("OOPS " #name " bad row\n")
446 #define SHOW_SCRN_FLAG(name,code) \
447 Trace(#name " %s:%s\n", \
452 LineClrFlag(LineData * ld, int flag)
455 SHOW_BAD_LINE(LineClrFlag, ld);
457 } else if (isScrnFlag(flag)) {
458 SHOW_SCRN_FLAG(LineClrFlag, 0);
461 LineFlags(ld) &= ~flag;
465 LineSetFlag(LineData * ld, int flag)
468 SHOW_BAD_LINE(LineSetFlag, ld);
470 } else if (isScrnFlag(flag)) {
471 SHOW_SCRN_FLAG(LineSetFlag, 1);
474 LineFlags(ld) |= flag;
478 LineTstFlag(LineData ld, int flag)
482 SHOW_BAD_LINE(LineTstFlag, ld);
484 code = LineFlags(ld);
486 if (isScrnFlag(flag)) {
487 SHOW_SCRN_FLAG(LineTstFlag, code);
492 #endif /* OPT_TRACE_FLAGS */
495 TraceFocus(Widget w, XEvent * ev)
497 TRACE(("trace_focus event type %d:%s\n",
498 ev->type, visibleEventType(ev->type)));
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));
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));
522 TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
528 TraceSizeHints(XSizeHints * hints)
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));
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));
558 TraceWMSizeHints(XtermWidget xw)
560 XSizeHints sizehints = xw->hints;
562 getXtermSizeHints(xw);
563 TraceSizeHints(&xw->hints);
564 xw->hints = sizehints;
568 * Some calls to XGetAtom() will fail, and we don't want to stop. So we use
569 * our own error-handler.
573 no_error(Display * dpy GCC_UNUSED, XErrorEvent * event GCC_UNUSED)
579 TraceTranslations(const char *name, Widget w)
582 XErrorHandler save = XSetErrorHandler(no_error);
583 XtTranslations xlations;
586 TRACE(("TraceTranslations for %s (widget %#lx) {{\n", name, (long) w));
589 XtNtranslations, &xlations,
590 XtNaccelerators, &xcelerat,
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)));
597 XFree((char *) result);
599 TRACE(("none (widget is null)\n"));
602 XSetErrorHandler(save);
606 TraceResizeRequest(const char *fn, int ln, Widget w,
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));
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)
628 TraceXtermResources(void)
630 XTERM_RESOURCE *resp = &resource;
632 Trace("XTERM_RESOURCE settings:\n");
634 XRES_S(icon_geometry);
641 XRES_B(utmpDisplayId);
647 XRES_B(hpFunctionKeys);
649 #if OPT_SCO_FUNC_KEYS
650 XRES_B(scoFunctionKeys);
652 #if OPT_SUN_FUNC_KEYS
653 XRES_B(sunFunctionKeys);
655 #if OPT_INITIAL_ERASE
656 XRES_B(ptyInitialErase);
657 XRES_B(backarrow_is_erase);
659 XRES_B(useInsertMode);
663 #if OPT_PTY_HANDSHAKE
664 XRES_B(wait_for_map);
665 XRES_B(ptyHandshake);
677 TraceArgv(const char *tag, char **argv)
681 TRACE(("%s:\n", tag));
683 TRACE((" %d:%s\n", n++, *argv++));
688 parse_option(char *dst, String src, int first)
692 if (!strncmp(src, "-/+", (size_t) 3)) {
693 dst[0] = (char) first;
694 strcpy(dst + 1, src + 3);
698 for (s = dst; *s != '\0'; s++) {
699 if (*s == '#' || *s == '%' || *s == 'S') {
701 } else if (*s == ' ') {
710 same_option(OptionHelp * opt, XrmOptionDescRec * res)
713 return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
717 standard_option(String opt)
719 static const char *table[] =
749 opt = parse_option(temp, opt, '-');
750 for (n = 0; n < XtNumber(table); n++) {
751 if (!strcmp(opt, table[n]))
758 * Analyse the options/help messages for inconsistencies.
761 TraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
763 OptionHelp *opt_array = sortedOpts(options, resources, res_count);
765 XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
768 TRACE(("Checking options-tables for inconsistencies:\n"));
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));
779 /* list all options[] not found in resources[] */
780 for (j = 0, first = True; options[j].opt != 0; j++) {
782 for (k = 0; k < res_count; k++) {
783 if (same_option(&opt_array[j], &res_array[k])) {
790 TRACE(("Options listed in help, not found in resource list:\n"));
793 TRACE((" %-28s%s\n", opt_array[j].opt,
794 standard_option(opt_array[j].opt) ? " (standard)" : ""));
798 /* list all resources[] not found in options[] */
799 for (j = 0, first = True; j < res_count; j++) {
801 for (k = 0; options[k].opt != 0; k++) {
802 if (same_option(&opt_array[k], &res_array[j])) {
809 TRACE(("Resource list items not found in options-help:\n"));
812 TRACE((" %s\n", res_array[j].option));
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));
822 case XrmoptionSkipNArgs:
823 TRACE((" %-28s {%ld params}\n", res_array[j].option, (long)
824 res_array[j].value));
826 case XrmoptionSkipLine:
827 TRACE((" %-28s {remainder of line}\n", res_array[j].option));
831 case XrmoptionResArg:
832 case XrmoptionSepArg:
833 case XrmoptionStickyArg:
840 extern void empty_trace(void);