1/* vi:set ts=8 sts=8 sw=8:
2 *
3 * VIM - Vi IMproved	by Bram Moolenaar
4 *			Visual Workshop integration by Gordon Prieur
5 *
6 * Do ":help uganda"  in Vim to read copying and usage conditions.
7 * Do ":help credits" in Vim to see a list of people who contributed.
8 * See README.txt for an overview of the Vim source code.
9 */
10
11/*
12 * WorkShop Debugging Tools. What are these tools and why are they important?
13 * There are two main tools here. The first tool is a tool for delaying or
14 * stopping gvim during startup.  The second tool is a protocol log tool.
15 *
16 * The startup delay tool is called wsdebug_wait(). This is very important for
17 * debugging startup problems because gvim will be started automatically from
18 * workshop and cannot be run directly from a debugger. The only way to debug
19 * a gvim started by workshop is by attaching a debugger to it. Without this
20 * tool all starup code will have completed before you can get the pid and
21 * attach.
22 *
23 * The second tool is a protocol log tool. The workshop editor server and gvim
24 * pass information back and forth during a workshop session. Sometimes it is
25 * very important to peruse this conversation in order to understand what is
26 * happening. The wsdebug_log_init() call sets up this protocol log tool and
27 * wsdebug() and wstrace() calls output the information to the log.
28 *
29 * This code must have WSDEBUG defined for it to be compiled into vim/gvim.
30 */
31
32#ifdef WSDEBUG
33
34#include "vim.h"
35
36FILE		*ws_debug = NULL;
37u_int		 ws_dlevel = 0;		/* ws_debug verbosity level */
38
39void		 wsdebug(char *, ...);
40void		 wstrace(char *, ...);
41
42static int	 lookup(char *);
43#ifdef USE_WS_ERRORHANDLER
44static int	 errorHandler(Display *, XErrorEvent *);
45#endif
46
47
48/*
49 * wsdebug_wait	-   This function can be used to delay or stop execution of vim.
50 *		    Its normally used to delay startup while attaching a
51 *		    debugger to a running process. Since workshop starts gvim
52 *		    from a background process this is the only way to debug
53 *		    startup problems.
54 */
55
56void wsdebug_wait(
57	u_int		 wait_flags,	/* tells what to do */
58	char		*wait_var,	/* wait environment variable */
59	u_int		 wait_secs)	/* how many seconds to wait */
60{
61
62	init_homedir();			/* not inited yet */
63#ifdef USE_WDDUMP
64	WDDump(0, 0, 0);
65#endif
66
67	/* for debugging purposes only */
68	if (wait_flags & WT_ENV && wait_var && getenv(wait_var) != NULL) {
69		sleep(atoi(getenv(wait_var)));
70	} else if (wait_flags & WT_WAIT && lookup("~/.gvimwait")) {
71		sleep(wait_secs > 0 && wait_secs < 120 ? wait_secs : 20);
72	} else if (wait_flags & WT_STOP && lookup("~/.gvimstop")) {
73		int w = 1;
74		while (w) {
75			;
76		}
77	}
78}    /* end wsdebug_wait */
79
80
81void
82wsdebug_log_init(
83	char		*log_var,	/* env var with log file */
84	char		*level_var)	/* env var with ws_debug level */
85{
86	char		*file;		/* possible ws_debug output file */
87	char		*cp;		/* ws_dlevel pointer */
88
89	if (log_var && (file = getenv(log_var)) != NULL)
90	{
91		char buf[BUFSIZ];
92
93		vim_snprintf(buf, sizeof(buf), "date > %s", file);
94		system(buf);
95		ws_debug = fopen(file, "a");
96		if (level_var && (cp = getenv(level_var)) != NULL) {
97			ws_dlevel = strtoul(cp, NULL, 0);
98		} else {
99			ws_dlevel = WS_TRACE;	/* default level */
100		}
101#ifdef USE_WS_ERRORHANDLER
102		XSetErrorHandler(errorHandler);
103#endif
104	}
105
106}    /* end wsdebug_log_init */
107
108
109
110
111void
112wstrace(
113	char		*fmt,
114	...)
115{
116	va_list		 ap;
117
118	if (ws_debug!= NULL && (ws_dlevel & (WS_TRACE | WS_TRACE_VERBOSE))) {
119		va_start(ap, fmt);
120		vfprintf(ws_debug, fmt, ap);
121		va_end(ap);
122		fflush(ws_debug);
123	}
124
125}    /* end wstrace */
126
127
128void
129wsdebug(
130	char		*fmt,
131	...)
132{
133	va_list		 ap;
134
135	if (ws_debug != NULL) {
136		va_start(ap, fmt);
137		vfprintf(ws_debug, fmt, ap);
138		va_end(ap);
139		fflush(ws_debug);
140	}
141
142}    /* end wsdebug */
143
144
145static int
146lookup(
147	char		*file)
148{
149	char		 buf[BUFSIZ];
150
151	expand_env((char_u *) file, (char_u *) buf, BUFSIZ);
152	return (access(buf, F_OK) == 0);
153
154}    /* end lookup */
155
156#ifdef USE_WS_ERRORHANDLER
157static int
158errorHandler(
159	Display		*dpy,
160	XErrorEvent	*err)
161{
162	char		 msg[256];
163	char		 buf[256];
164
165	XGetErrorText(dpy, err->error_code, msg, sizeof(msg));
166	wsdebug("\n\nWSDEBUG Vim: X Error of failed request: %s\n", msg);
167
168	sprintf(buf, "%d", err->request_code);
169	XGetErrorDatabaseText(dpy,
170	    "XRequest", buf, "Unknown", msg, sizeof(msg));
171	wsdebug("\tMajor opcode of failed request: %d (%s)\n",
172	    err->request_code, msg);
173	if (err->request_code > 128) {
174		wsdebug("\tMinor opcode of failed request: %d\n",
175		    err->minor_code);
176	}
177
178	return 0;
179}
180#endif
181
182
183
184#endif /* WSDEBUG */
185