Edit

IABSD.fr/xenocara/app/xterm/trace.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2013-03-09 14:45:38
    Hash : a232c777
    Message : Update to xterm 291. Tested by many.

  • app/xterm/trace.c
  • /* $XTermId: trace.c,v 1.145 2013/02/06 09:51:17 tom Exp $ */
    
    /*
     * Copyright 1997-2012,2013 by Thomas E. Dickey
     *
     *                         All Rights Reserved
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name(s) of the above copyright
     * holders shall not be used in advertising or otherwise to promote the
     * sale, use or other dealings in this Software without prior written
     * authorization.
     */
    
    /*
     * debugging support via TRACE macro.
     */
    
    #include <xterm.h>		/* for definition of GCC_UNUSED */
    #include <version.h>
    
    #if OPT_TRACE
    
    #include <data.h>
    #include <trace.h>
    
    #include <time.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <stdio.h>
    #include <stdarg.h>
    #include <assert.h>
    
    #include <X11/Xatom.h>
    #include <X11/Xmu/Atoms.h>
    
    #ifdef HAVE_X11_TRANSLATEI_H
    #include <X11/TranslateI.h>
    #else
    #ifdef __cplusplus
    extern "C" {
    #endif
    
        extern String _XtPrintXlations(Widget w,
    				   XtTranslations xlations,
    				   Widget accelWidget,
    				   _XtBoolean includeRHS);
    #ifdef __cplusplus
    }
    #endif
    #endif
    const char *trace_who = "parent";
    
    static FILE *trace_fp;
    
    void
    Trace(const char *fmt,...)
    {
        static const char *trace_out;
        va_list ap;
    
        if (trace_fp != 0
    	&& trace_who != trace_out) {
    	fclose(trace_fp);
    	trace_fp = 0;
        }
        trace_out = trace_who;
    
        if (!trace_fp) {
    	char name[BUFSIZ];
    #if 0				/* usually I do not want unique names */
    	int unique;
    	for (unique = 0;; ++unique) {
    	    if (unique)
    		sprintf(name, "Trace-%s.out-%d", trace_who, unique);
    	    else
    		sprintf(name, "Trace-%s.out", trace_who);
    	    if ((trace_fp = fopen(name, "r")) == 0) {
    		break;
    	    }
    	    fclose(trace_fp);
    	}
    #else
    	sprintf(name, "Trace-%s.out", trace_who);
    #endif
    	trace_fp = fopen(name, "w");
    	if (trace_fp != 0) {
    	    fprintf(trace_fp, "%s\n", xtermVersion());
    	    TraceIds(NULL, 0);
    	}
    	if (!trace_fp) {
    	    xtermWarning("Cannot open \"%s\"\n", name);
    	    exit(EXIT_FAILURE);
    	}
        }
    
        va_start(ap, fmt);
        vfprintf(trace_fp, fmt, ap);
        (void) fflush(trace_fp);
        va_end(ap);
    }
    
    void
    TraceClose(void)
    {
        if (trace_fp != 0) {
    	(void) fclose(trace_fp);
    	(void) fflush(stdout);
    	(void) fflush(stderr);
    	(void) visibleChars(NULL, 0);
    	(void) visibleIChars(NULL, 0);
    	(void) visibleIChar(NULL, 0);
    	trace_fp = 0;
        }
    }
    
    void
    TraceIds(const char *fname, int lnum)
    {
        Trace("process %d ", (int) getpid());
    #ifdef HAVE_UNISTD_H
        Trace("real (%u/%u) effective (%u/%u)",
    	  (unsigned) getuid(), (unsigned) getgid(),
    	  (unsigned) geteuid(), (unsigned) getegid());
    #endif
        if (fname != 0) {
    	Trace(" (%s@%d)\n", fname, lnum);
        } else {
    	time_t now = time((time_t *) 0);
    	Trace("-- %s", ctime(&now));
        }
    }
    
    void
    TraceTime(const char *fname, int lnum)
    {
        time_t now;
        if (fname != 0) {
    	Trace("datetime (%s@%d) ", fname, lnum);
        }
        now = time((time_t *) 0);
        Trace("-- %s", ctime(&now));
    }
    
    static void
    formatAscii(char *dst, unsigned value)
    {
        switch (value) {
        case '\\':
    	sprintf(dst, "\\\\");
    	break;
        case '\b':
    	sprintf(dst, "\\b");
    	break;
        case '\n':
    	sprintf(dst, "\\n");
    	break;
        case '\r':
    	sprintf(dst, "\\r");
    	break;
        case '\t':
    	sprintf(dst, "\\t");
    	break;
        default:
    	if (E2A(value) < 32 || (E2A(value) >= 127 && E2A(value) < 160))
    	    sprintf(dst, "\\%03o", value);
    	else
    	    sprintf(dst, "%c", CharOf(value));
    	break;
        }
    }
    
    #if OPT_DEC_CHRSET
    
    const char *
    visibleChrsetName(unsigned chrset)
    {
        const char *result = "?";
        switch (chrset) {
        case CSET_SWL:
    	result = "CSET_SWL";
    	break;
        case CSET_DHL_TOP:
    	result = "CSET_DHL_TOP";
    	break;
        case CSET_DHL_BOT:
    	result = "CSET_DHL_BOT";
    	break;
        case CSET_DWL:
    	result = "CSET_DWL";
    	break;
        }
        return result;
    }
    #endif
    
    char *
    visibleChars(const Char * buf, unsigned len)
    {
        static char *result;
        static unsigned used;
    
        if (buf != 0) {
    	unsigned limit = ((len + 1) * 8) + 1;
    	char *dst;
    
    	if (limit > used) {
    	    used = limit;
    	    result = XtRealloc(result, used);
    	}
    	if (result != 0) {
    	    dst = result;
    	    *dst = '\0';
    	    while (len--) {
    		unsigned value = *buf++;
    		formatAscii(dst, value);
    		dst += strlen(dst);
    	    }
    	}
        } else if (result != 0) {
    	free(result);
    	result = 0;
    	used = 0;
        }
        return result;
    }
    
    char *
    visibleIChars(IChar * buf, unsigned len)
    {
        static char *result;
        static unsigned used;
    
        if (buf != 0) {
    	unsigned limit = ((len + 1) * 8) + 1;
    	char *dst;
    
    	if (limit > used) {
    	    used = limit;
    	    result = XtRealloc(result, used);
    	}
    	if (result != 0) {
    	    dst = result;
    	    *dst = '\0';
    	    while (len--) {
    		unsigned value = *buf++;
    #if OPT_WIDE_CHARS
    		if (value > 255)
    		    sprintf(dst, "\\u+%04X", value);
    		else
    #endif
    		    formatAscii(dst, value);
    		dst += strlen(dst);
    	    }
    	}
        } else if (result != 0) {
    	free(result);
    	result = 0;
    	used = 0;
        }
        return result;
    }
    
    char *
    visibleIChar(IChar * buf, unsigned len)
    {
        static char *result;
        static unsigned used;
    
        if (buf != 0) {
    	unsigned limit = ((len + 1) * 8) + 1;
    	char *dst;
    
    	if (limit > used) {
    	    used = limit;
    	    result = XtRealloc(result, used);
    	}
    	if (result != 0) {
    	    dst = result;
    	    while (len--) {
    		unsigned value = *buf++;
    #if OPT_WIDE_CHARS
    		if (value > 255)
    		    sprintf(dst, "\\u+%04X", value);
    		else
    #endif
    		    formatAscii(dst, value);
    		dst += strlen(dst);
    	    }
    	}
        } else if (result != 0) {
    	free(result);
    	result = 0;
    	used = 0;
        }
        return result;
    }
    
    #define CASETYPE(name) case name: result = #name; break
    
    const char *
    visibleKeyboardType(xtermKeyboardType type)
    {
        const char *result = "?";
        switch (type) {
    	CASETYPE(keyboardIsLegacy);	/* bogus vt220 codes for F1-F4, etc. */
    	CASETYPE(keyboardIsDefault);
    	CASETYPE(keyboardIsHP);
    	CASETYPE(keyboardIsSCO);
    	CASETYPE(keyboardIsSun);
    	CASETYPE(keyboardIsTermcap);
    	CASETYPE(keyboardIsVT220);
        }
        return result;
    }
    
    const char *
    visibleEventType(int type)
    {
        const char *result = "?";
        switch (type) {
    	CASETYPE(KeyPress);
    	CASETYPE(KeyRelease);
    	CASETYPE(ButtonPress);
    	CASETYPE(ButtonRelease);
    	CASETYPE(MotionNotify);
    	CASETYPE(EnterNotify);
    	CASETYPE(LeaveNotify);
    	CASETYPE(FocusIn);
    	CASETYPE(FocusOut);
    	CASETYPE(KeymapNotify);
    	CASETYPE(Expose);
    	CASETYPE(GraphicsExpose);
    	CASETYPE(NoExpose);
    	CASETYPE(VisibilityNotify);
    	CASETYPE(CreateNotify);
    	CASETYPE(DestroyNotify);
    	CASETYPE(UnmapNotify);
    	CASETYPE(MapNotify);
    	CASETYPE(MapRequest);
    	CASETYPE(ReparentNotify);
    	CASETYPE(ConfigureNotify);
    	CASETYPE(ConfigureRequest);
    	CASETYPE(GravityNotify);
    	CASETYPE(ResizeRequest);
    	CASETYPE(CirculateNotify);
    	CASETYPE(CirculateRequest);
    	CASETYPE(PropertyNotify);
    	CASETYPE(SelectionClear);
    	CASETYPE(SelectionRequest);
    	CASETYPE(SelectionNotify);
    	CASETYPE(ColormapNotify);
    	CASETYPE(ClientMessage);
    	CASETYPE(MappingNotify);
        }
        return result;
    }
    
    const char *
    visibleNotifyMode(int code)
    {
        const char *result = "?";
        switch (code) {
    	CASETYPE(NotifyNormal);
    	CASETYPE(NotifyGrab);
    	CASETYPE(NotifyUngrab);
    	CASETYPE(NotifyWhileGrabbed);
        }
        return result;
    }
    
    const char *
    visibleNotifyDetail(int code)
    {
        const char *result = "?";
        switch (code) {
    	CASETYPE(NotifyAncestor);
    	CASETYPE(NotifyVirtual);
    	CASETYPE(NotifyInferior);
    	CASETYPE(NotifyNonlinear);
    	CASETYPE(NotifyNonlinearVirtual);
    	CASETYPE(NotifyPointer);
    	CASETYPE(NotifyPointerRoot);
    	CASETYPE(NotifyDetailNone);
        }
        return result;
    }
    
    const char *
    visibleSelectionTarget(Display * d, Atom a)
    {
        const char *result = "?";
    
        if (a == XA_STRING) {
    	result = "XA_STRING";
        } else if (a == XA_TEXT(d)) {
    	result = "XA_TEXT()";
        } else if (a == XA_COMPOUND_TEXT(d)) {
    	result = "XA_COMPOUND_TEXT()";
        } else if (a == XA_UTF8_STRING(d)) {
    	result = "XA_UTF8_STRING()";
        } else if (a == XA_TARGETS(d)) {
    	result = "XA_TARGETS()";
        }
    
        return result;
    }
    
    const char *
    visibleXError(int code)
    {
        static char temp[80];
        const char *result = "?";
        switch (code) {
    	CASETYPE(Success);
    	CASETYPE(BadRequest);
    	CASETYPE(BadValue);
    	CASETYPE(BadWindow);
    	CASETYPE(BadPixmap);
    	CASETYPE(BadAtom);
    	CASETYPE(BadCursor);
    	CASETYPE(BadFont);
    	CASETYPE(BadMatch);
    	CASETYPE(BadDrawable);
    	CASETYPE(BadAccess);
    	CASETYPE(BadAlloc);
    	CASETYPE(BadColor);
    	CASETYPE(BadGC);
    	CASETYPE(BadIDChoice);
    	CASETYPE(BadName);
    	CASETYPE(BadLength);
    	CASETYPE(BadImplementation);
        default:
    	sprintf(temp, "%d", code);
    	result = temp;
    	break;
        }
        return result;
    }
    
    #if OPT_TRACE_FLAGS
    #define isScrnFlag(flag) ((flag) == LINEWRAPPED)
    
    static char *
    ScrnText(LineData * ld)
    {
        return visibleIChars(ld->charData, ld->lineSize);
    }
    
    #define SHOW_BAD_LINE(name, ld) \
    	Trace("OOPS " #name " bad row\n")
    
    #define SHOW_SCRN_FLAG(name,code) \
    	Trace(#name " %s:%s\n", \
    	      code ? "*" : "", \
    	      ScrnText(ld))
    
    void
    LineClrFlag(LineData * ld, int flag)
    {
        if (ld == 0) {
    	SHOW_BAD_LINE(LineClrFlag, ld);
    	assert(0);
        } else if (isScrnFlag(flag)) {
    	SHOW_SCRN_FLAG(LineClrFlag, 0);
        }
    
        LineFlags(ld) &= ~flag;
    }
    
    void
    LineSetFlag(LineData * ld, int flag)
    {
        if (ld == 0) {
    	SHOW_BAD_LINE(LineSetFlag, ld);
    	assert(0);
        } else if (isScrnFlag(flag)) {
    	SHOW_SCRN_FLAG(LineSetFlag, 1);
        }
    
        LineFlags(ld) |= flag;
    }
    
    int
    LineTstFlag(LineData ld, int flag)
    {
        int code = 0;
        if (ld == 0) {
    	SHOW_BAD_LINE(LineTstFlag, ld);
        } else {
    	code = LineFlags(ld);
    
    	if (isScrnFlag(flag)) {
    	    SHOW_SCRN_FLAG(LineTstFlag, code);
    	}
        }
        return code;
    }
    #endif /* OPT_TRACE_FLAGS */
    
    /*
     * Trace the normal or alternate screen, showing color values up to 16, e.g.,
     * for debugging with vttest.
     */
    void
    TraceScreen(XtermWidget xw, int whichBuf)
    {
        TScreen *screen = TScreenOf(xw);
        int row, col;
    
        if (screen->editBuf_index[whichBuf]) {
    	TRACE(("TraceScreen %d:\n", whichBuf));
    	for (row = 0; row <= screen->max_row; ++row) {
    	    LineData *ld = getLineData(screen, row);
    	    TRACE((" %3d:", row));
    	    if (ld != 0) {
    		for (col = 0; col < ld->lineSize; ++col) {
    		    int ch = (int) ld->charData[col];
    		    if (ch < ' ')
    			ch = ' ';
    		    if (ch >= 127)
    			ch = '#';
    		    TRACE(("%c", ch));
    		}
    		TRACE((":\n"));
    
    		TRACE(("  xx:"));
    		for (col = 0; col < ld->lineSize; ++col) {
    		    unsigned attrs = ld->attribs[col];
    		    char ch;
    		    if (attrs & PROTECTED) {
    			ch = '*';
    		    } else if (attrs & BLINK) {
    			ch = 'B';
    		    } else if (attrs & CHARDRAWN) {
    			ch = '+';
    		    } else {
    			ch = ' ';
    		    }
    		    TRACE(("%c", ch));
    		}
    		TRACE((":\n"));
    
    #if 0
    		TRACE(("  fg:"));
    		for (col = 0; col < ld->lineSize; ++col) {
    		    unsigned fg = extract_fg(xw, ld->color[col], ld->attribs[col]);
    		    if (fg > 15)
    			fg = 15;
    		    TRACE(("%1x", fg));
    		}
    		TRACE((":\n"));
    
    		TRACE(("  bg:"));
    		for (col = 0; col < ld->lineSize; ++col) {
    		    unsigned bg = extract_bg(xw, ld->color[col], ld->attribs[col]);
    		    if (bg > 15)
    			bg = 15;
    		    TRACE(("%1x", bg));
    		}
    		TRACE((":\n"));
    #endif
    	    } else {
    		TRACE(("null lineData\n"));
    	    }
    	}
        } else {
    	TRACE(("TraceScreen %d is nil\n", whichBuf));
        }
    }
    
    void
    TraceFocus(Widget w, XEvent * ev)
    {
        TRACE(("trace_focus event type %d:%s\n",
    	   ev->type, visibleEventType(ev->type)));
        switch (ev->type) {
        case FocusIn:
        case FocusOut:
    	{
    	    XFocusChangeEvent *event = (XFocusChangeEvent *) ev;
    	    TRACE(("\tdetail: %s\n", visibleNotifyDetail(event->detail)));
    	    TRACE(("\tmode:   %s\n", visibleNotifyMode(event->mode)));
    	    TRACE(("\twindow: %#lx\n", event->window));
    	}
    	break;
        case EnterNotify:
        case LeaveNotify:
    	{
    	    XCrossingEvent *event = (XCrossingEvent *) ev;
    	    TRACE(("\tdetail:    %s\n", visibleNotifyDetail(event->detail)));
    	    TRACE(("\tmode:      %s\n", visibleNotifyMode(event->mode)));
    	    TRACE(("\twindow:    %#lx\n", event->window));
    	    TRACE(("\tfocus:     %d\n", event->focus));
    	    TRACE(("\troot:      %#lx\n", event->root));
    	    TRACE(("\tsubwindow: %#lx\n", event->subwindow));
    	}
    	break;
        }
        while (w != 0) {
    	TRACE(("w %p -> %#lx\n", (void *) w, XtWindow(w)));
    	w = XtParent(w);
        }
    }
    
    void
    TraceSizeHints(XSizeHints * hints)
    {
        TRACE(("size hints:\n"));
        if (hints->flags & (USPosition | PPosition))
    	TRACE(("   position   %d,%d%s%s\n", hints->y, hints->x,
    	       hints->flags & USPosition ? " user" : "",
    	       hints->flags & PPosition ? " prog" : ""));
        if (hints->flags & (USSize | PSize))
    	TRACE(("   size       %d,%d%s%s\n", hints->height, hints->width,
    	       hints->flags & USSize ? " user" : "",
    	       hints->flags & PSize ? " prog" : ""));
        if (hints->flags & PMinSize)
    	TRACE(("   min        %d,%d\n", hints->min_height, hints->min_width));
        if (hints->flags & PMaxSize)
    	TRACE(("   max        %d,%d\n", hints->max_height, hints->max_width));
        if (hints->flags & PResizeInc)
    	TRACE(("   inc        %d,%d\n", hints->height_inc, hints->width_inc));
        else
    	TRACE(("   inc        NONE!\n"));
        if (hints->flags & PAspect)
    	TRACE(("   min aspect %d/%d\n", hints->min_aspect.y, hints->min_aspect.y));
        if (hints->flags & PAspect)
    	TRACE(("   max aspect %d/%d\n", hints->max_aspect.y, hints->max_aspect.y));
        if (hints->flags & PBaseSize)
    	TRACE(("   base       %d,%d\n", hints->base_height, hints->base_width));
        if (hints->flags & PWinGravity)
    	TRACE(("   gravity    %d\n", hints->win_gravity));
    }
    
    static void
    TraceEventMask(const char *tag, long mask)
    {
    #define DATA(name) { name##Mask, #name }
        /* *INDENT-OFF* */
        static struct {
    	long mask;
    	const char *name;
        } table[] = {
    	DATA(KeyPress),
    	DATA(KeyRelease),
    	DATA(ButtonPress),
    	DATA(ButtonRelease),
    	DATA(EnterWindow),
    	DATA(LeaveWindow),
    	DATA(PointerMotion),
    	DATA(PointerMotionHint),
    	DATA(Button1Motion),
    	DATA(Button2Motion),
    	DATA(Button3Motion),
    	DATA(Button4Motion),
    	DATA(Button5Motion),
    	DATA(ButtonMotion),
    	DATA(KeymapState),
    	DATA(Exposure),
    	DATA(VisibilityChange),
    	DATA(StructureNotify),
    	DATA(ResizeRedirect),
    	DATA(SubstructureNotify),
    	DATA(SubstructureRedirect),
    	DATA(FocusChange),
    	DATA(PropertyChange),
    	DATA(ColormapChange),
    	DATA(OwnerGrabButton),
        };
    #undef DATA
        Cardinal n;
        /* *INDENT-ON* */
    
        for (n = 0; n < XtNumber(table); ++n) {
    	if (table[n].mask & mask) {
    	    TRACE(("%s %s\n", tag, table[n].name));
    	}
        }
    }
    
    void
    TraceWindowAttributes(XWindowAttributes * attrs)
    {
        TRACE(("window attributes:\n"));
        TRACE(("   position     %d,%d\n", attrs->y, attrs->x));
        TRACE(("   size         %dx%d\n", attrs->height, attrs->width));
        TRACE(("   border       %d\n", attrs->border_width));
        TRACE(("   depth        %d\n", attrs->depth));
        TRACE(("   bit_gravity  %d\n", attrs->bit_gravity));
        TRACE(("   win_gravity  %d\n", attrs->win_gravity));
        TRACE(("   root         %#lx\n", (long) attrs->root));
        TRACE(("   class        %s\n", ((attrs->class == InputOutput)
    				    ? "InputOutput"
    				    : ((attrs->class == InputOnly)
    				       ? "InputOnly"
    				       : "unknown"))));
        TRACE(("   map_state    %s\n", ((attrs->map_state == IsUnmapped)
    				    ? "IsUnmapped"
    				    : ((attrs->map_state == IsUnviewable)
    				       ? "IsUnviewable"
    				       : ((attrs->map_state == IsViewable)
    					  ? "IsViewable"
    					  : "unknown")))));
        TRACE(("   all_events\n"));
        TraceEventMask("        ", attrs->all_event_masks);
        TRACE(("   your_events\n"));
        TraceEventMask("        ", attrs->your_event_mask);
        TRACE(("   no_propagate\n"));
        TraceEventMask("        ", attrs->do_not_propagate_mask);
    }
    
    void
    TraceWMSizeHints(XtermWidget xw)
    {
        XSizeHints sizehints = xw->hints;
    
        getXtermSizeHints(xw);
        TraceSizeHints(&xw->hints);
        xw->hints = sizehints;
    }
    
    /*
     * Some calls to XGetAtom() will fail, and we don't want to stop.  So we use
     * our own error-handler.
     */
    /* ARGSUSED */
    static int
    no_error(Display * dpy GCC_UNUSED, XErrorEvent * event GCC_UNUSED)
    {
        return 1;
    }
    
    const char *
    ModifierName(unsigned modifier)
    {
        const char *s = "";
        if (modifier & ShiftMask)
    	s = " Shift";
        else if (modifier & LockMask)
    	s = " Lock";
        else if (modifier & ControlMask)
    	s = " Control";
        else if (modifier & Mod1Mask)
    	s = " Mod1";
        else if (modifier & Mod2Mask)
    	s = " Mod2";
        else if (modifier & Mod3Mask)
    	s = " Mod3";
        else if (modifier & Mod4Mask)
    	s = " Mod4";
        else if (modifier & Mod5Mask)
    	s = " Mod5";
        return s;
    }
    
    void
    TraceTranslations(const char *name, Widget w)
    {
        String result;
        XErrorHandler save = XSetErrorHandler(no_error);
        XtTranslations xlations;
        Widget xcelerat;
    
        TRACE(("TraceTranslations for %s (widget %#lx) {{\n", name, (long) w));
        if (w) {
    	XtVaGetValues(w,
    		      XtNtranslations, &xlations,
    		      XtNaccelerators, &xcelerat,
    		      (XtPointer) 0);
    	TRACE(("... xlations %#08lx\n", (long) xlations));
    	TRACE(("... xcelerat %#08lx\n", (long) xcelerat));
    	result = _XtPrintXlations(w, xlations, xcelerat, True);
    	TRACE(("%s\n", NonNull(result)));
    	if (result)
    	    XFree((char *) result);
        } else {
    	TRACE(("none (widget is null)\n"));
        }
        TRACE(("}}\n"));
        XSetErrorHandler(save);
    }
    
    XtGeometryResult
    TraceResizeRequest(const char *fn, int ln, Widget w,
    		   unsigned reqwide,
    		   unsigned reqhigh,
    		   Dimension * gotwide,
    		   Dimension * gothigh)
    {
        XtGeometryResult rc;
    
        TRACE(("%s@%d ResizeRequest %ux%u\n", fn, ln, reqhigh, reqwide));
        rc = XtMakeResizeRequest((Widget) w,
    			     (Dimension) reqwide,
    			     (Dimension) reqhigh,
    			     gotwide, gothigh);
        TRACE(("... ResizeRequest -> "));
        if (gothigh && gotwide)
    	TRACE(("%dx%d ", *gothigh, *gotwide));
        TRACE(("(%d)\n", rc));
        return rc;
    }
    
    #define XRES_S(name) Trace(#name " = %s\n", NonNull(resp->name))
    #define XRES_B(name) Trace(#name " = %s\n", BtoS(resp->name))
    #define XRES_I(name) Trace(#name " = %d\n", resp->name)
    
    void
    TraceXtermResources(void)
    {
        XTERM_RESOURCE *resp = &resource;
    
        Trace("XTERM_RESOURCE settings:\n");
        XRES_S(icon_geometry);
        XRES_S(title);
        XRES_S(icon_hint);
        XRES_S(icon_name);
        XRES_S(term_name);
        XRES_S(tty_modes);
        XRES_I(minBufSize);
        XRES_I(maxBufSize);
        XRES_B(hold_screen);
        XRES_B(utmpInhibit);
        XRES_B(utmpDisplayId);
        XRES_B(messages);
        XRES_S(menuLocale);
        XRES_S(omitTranslation);
        XRES_S(keyboardType);
    #if OPT_PRINT_ON_EXIT
        XRES_I(printModeNow);
        XRES_I(printModeOnXError);
        XRES_I(printOptsNow);
        XRES_I(printOptsOnXError);
        XRES_S(printFileNow);
        XRES_S(printFileOnXError);
    #endif
    #if OPT_SUNPC_KBD
        XRES_B(sunKeyboard);
    #endif
    #if OPT_HP_FUNC_KEYS
        XRES_B(hpFunctionKeys);
    #endif
    #if OPT_SCO_FUNC_KEYS
        XRES_B(scoFunctionKeys);
    #endif
    #if OPT_SUN_FUNC_KEYS
        XRES_B(sunFunctionKeys);
    #endif
    #if OPT_INITIAL_ERASE
        XRES_B(ptyInitialErase);
        XRES_B(backarrow_is_erase);
    #endif
        XRES_B(useInsertMode);
    #if OPT_ZICONBEEP
        XRES_I(zIconBeep);
        XRES_S(zIconFormat);
    #endif
    #if OPT_PTY_HANDSHAKE
        XRES_B(wait_for_map);
        XRES_B(ptyHandshake);
        XRES_B(ptySttySize);
    #endif
    #if OPT_SAME_NAME
        XRES_B(sameName);
    #endif
    #if OPT_SESSION_MGT
        XRES_B(sessionMgt);
    #endif
    #if OPT_TOOLBAR
        XRES_B(toolBar);
    #endif
    #if OPT_MAXIMIZE
        XRES_B(maximized);
        XRES_S(fullscreen_s);
    #endif
    }
    
    void
    TraceArgv(const char *tag, char **argv)
    {
        int n = 0;
    
        TRACE(("%s:\n", tag));
        while (*argv != 0) {
    	TRACE(("  %d:%s\n", n++, *argv++));
        }
    }
    
    static char *
    parse_option(char *dst, String src, int first)
    {
        char *s;
    
        if (!strncmp(src, "-/+", (size_t) 3)) {
    	dst[0] = (char) first;
    	strcpy(dst + 1, src + 3);
        } else {
    	strcpy(dst, src);
        }
        for (s = dst; *s != '\0'; s++) {
    	if (*s == '#' || *s == '%' || *s == 'S') {
    	    s[1] = '\0';
    	} else if (*s == ' ') {
    	    *s = '\0';
    	    break;
    	}
        }
        return dst;
    }
    
    static Bool
    same_option(OptionHelp * opt, XrmOptionDescRec * res)
    {
        char temp[BUFSIZ];
        return !strcmp(parse_option(temp, opt->opt, res->option[0]), res->option);
    }
    
    static Bool
    standard_option(String opt)
    {
        static const char *table[] =
        {
    	"+rv",
    	"+synchronous",
    	"-background",
    	"-bd",
    	"-bg",
    	"-bordercolor",
    	"-borderwidth",
    	"-bw",
    	"-display",
    	"-fg",
    	"-fn",
    	"-font",
    	"-foreground",
    	"-geometry",
    	"-iconic",
    	"-name",
    	"-reverse",
    	"-rv",
    	"-selectionTimeout",
    	"-synchronous",
    	"-title",
    	"-xnllanguage",
    	"-xrm",
    	"-xtsessionID",
        };
        Cardinal n;
        char temp[BUFSIZ];
    
        opt = parse_option(temp, opt, '-');
        for (n = 0; n < XtNumber(table); n++) {
    	if (!strcmp(opt, table[n]))
    	    return True;
        }
        return False;
    }
    
    /*
     * Analyse the options/help messages for inconsistencies.
     */
    void
    TraceOptions(OptionHelp * options, XrmOptionDescRec * resources, Cardinal res_count)
    {
        OptionHelp *opt_array = sortedOpts(options, resources, res_count);
        size_t j, k;
        XrmOptionDescRec *res_array = sortedOptDescs(resources, res_count);
        Bool first, found;
    
        TRACE(("Checking options-tables for inconsistencies:\n"));
    
    #if 0
        TRACE(("Options listed in help-message:\n"));
        for (j = 0; options[j].opt != 0; j++)
    	TRACE(("%5d %-28s %s\n", j, opt_array[j].opt, opt_array[j].desc));
        TRACE(("Options listed in resource-table:\n"));
        for (j = 0; j < res_count; j++)
    	TRACE(("%5d %-28s %s\n", j, res_array[j].option, res_array[j].specifier));
    #endif
    
        /* list all options[] not found in resources[] */
        for (j = 0, first = True; options[j].opt != 0; j++) {
    	found = False;
    	for (k = 0; k < res_count; k++) {
    	    if (same_option(&opt_array[j], &res_array[k])) {
    		found = True;
    		break;
    	    }
    	}
    	if (!found) {
    	    if (first) {
    		TRACE(("Options listed in help, not found in resource list:\n"));
    		first = False;
    	    }
    	    TRACE(("  %-28s%s\n", opt_array[j].opt,
    		   standard_option(opt_array[j].opt) ? " (standard)" : ""));
    	}
        }
    
        /* list all resources[] not found in options[] */
        for (j = 0, first = True; j < res_count; j++) {
    	found = False;
    	for (k = 0; options[k].opt != 0; k++) {
    	    if (same_option(&opt_array[k], &res_array[j])) {
    		found = True;
    		break;
    	    }
    	}
    	if (!found) {
    	    if (first) {
    		TRACE(("Resource list items not found in options-help:\n"));
    		first = False;
    	    }
    	    TRACE(("  %s\n", res_array[j].option));
    	}
        }
    
        TRACE(("Resource list items that will be ignored by XtOpenApplication:\n"));
        for (j = 0; j < res_count; j++) {
    	switch (res_array[j].argKind) {
    	case XrmoptionSkipArg:
    	    TRACE(("  %-28s {param}\n", res_array[j].option));
    	    break;
    	case XrmoptionSkipNArgs:
    	    TRACE(("  %-28s {%ld params}\n", res_array[j].option, (long)
    		   res_array[j].value));
    	    break;
    	case XrmoptionSkipLine:
    	    TRACE(("  %-28s {remainder of line}\n", res_array[j].option));
    	    break;
    	case XrmoptionIsArg:
    	case XrmoptionNoArg:
    	case XrmoptionResArg:
    	case XrmoptionSepArg:
    	case XrmoptionStickyArg:
    	default:
    	    break;
    	}
        }
    }
    #else
    extern void empty_trace(void);
    void
    empty_trace(void)
    {
    }
    #endif