display.c 5.28 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * File display.c - display handling for Wine internal debugger.
 *
 * Copyright (C) 1997, Eric Youngdale.
5
 * Copyright (C) 2003, Michal Miroslaw
Alexandre Julliard's avatar
Alexandre Julliard committed
6
 *
7 8 9 10 11 12 13 14 15 16 17 18 19
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Alexandre Julliard's avatar
Alexandre Julliard committed
20 21 22 23 24 25
 */

#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
26

Alexandre Julliard's avatar
Alexandre Julliard committed
27 28 29 30
#include "debugger.h"

#include <stdarg.h>

31
#define DISPTAB_DELTA 8		/* needs to be power of 2, search for MARK to see why :) */
Alexandre Julliard's avatar
Alexandre Julliard committed
32

33 34 35 36 37 38
struct display {
	struct expr *exp;
	int count;
	char format;
	char enabled;
	struct name_hash *function_name;
Alexandre Julliard's avatar
Alexandre Julliard committed
39 40
};

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
static struct display *displaypoints = NULL;
static unsigned int maxdisplays = 0, ndisplays = 0;

static struct name_hash *DEBUG_GetCurrentFrameFunctionName(void)
{
	struct name_hash *name;
	unsigned int eip, ebp;

	if (DEBUG_GetCurrentFrame(&name, &eip, &ebp))
		return name;
	return NULL;
}

int DEBUG_AddDisplay(struct expr *exp, int count, char format, int in_frame)
{
	int i;

	for (i = 0; i < ndisplays; i++)
		if (displaypoints[i].exp == NULL)
			break;

	if (i == maxdisplays)	/* no space left - expand */
		displaypoints = DBG_realloc(displaypoints,
			(maxdisplays += DISPTAB_DELTA) * sizeof(*displaypoints));

	if (i == ndisplays)
		++ndisplays;

	displaypoints[i].exp = DEBUG_CloneExpr(exp);
	displaypoints[i].count = count;
	displaypoints[i].format = format;
	displaypoints[i].enabled = TRUE;
	displaypoints[i].function_name =
		(in_frame ? DEBUG_GetCurrentFrameFunctionName() : NULL);

	return TRUE;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
78

79
int DEBUG_InfoDisplay(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
80
{
81 82 83 84 85 86 87
	int i;

	for (i = 0; i < ndisplays; i++) {
		if (displaypoints[i].exp == NULL)
			continue;

		if (displaypoints[i].function_name)
88
			DEBUG_Printf("%d in %s%s : ", i + 1,
89 90 91 92 93 94 95
				DEBUG_GetSymbolName(displaypoints[i].function_name),
				(displaypoints[i].enabled ?
					(displaypoints[i].function_name != DEBUG_GetCurrentFrameFunctionName() ?
						" (out of scope)" : "")
					: " (disabled)")
				);
		else
96 97
			DEBUG_Printf("%d%s : ", i + 1,
                                     (displaypoints[i].enabled ? "" : " (disabled)"));
98
		DEBUG_DisplayExpr(displaypoints[i].exp);
99
		DEBUG_Printf("\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
100 101
	}

102
	return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
103 104
}

105
void DEBUG_PrintOneDisplay(int i)
Alexandre Julliard's avatar
Alexandre Julliard committed
106
{
107 108 109 110 111
	DBG_VALUE value;

	if (displaypoints[i].enabled) {
		value = DEBUG_EvalExpr(displaypoints[i].exp);
		if (value.type == NULL) {
112
			DEBUG_Printf("Unable to evaluate expression ");
113
			DEBUG_DisplayExpr(displaypoints[i].exp);
114
			DEBUG_Printf("\nDisabling display %d ...\n", i + 1);
115 116 117 118 119
			displaypoints[i].enabled = FALSE;
			return;
		}
	}

120
	DEBUG_Printf("%d  : ", i + 1);
121
	DEBUG_DisplayExpr(displaypoints[i].exp);
122
	DEBUG_Printf(" = ");
123
	if (!displaypoints[i].enabled)
124
		DEBUG_Printf("(disabled)\n");
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
	else
	if (displaypoints[i].format == 'i')
		DEBUG_ExamineMemory(&value, displaypoints[i].count, displaypoints[i].format);
	else
		DEBUG_Print(&value, displaypoints[i].count, displaypoints[i].format, 0);
}

int DEBUG_DoDisplay(void)
{
	int i;
	struct name_hash *cur_function_name = DEBUG_GetCurrentFrameFunctionName();

	for (i = 0; i < ndisplays; i++) {
		if (displaypoints[i].exp == NULL || !displaypoints[i].enabled)
			continue;
		if (displaypoints[i].function_name
		    && displaypoints[i].function_name != cur_function_name)
			continue;
		DEBUG_PrintOneDisplay(i);
Alexandre Julliard's avatar
Alexandre Julliard committed
144 145
	}

146
	return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
147 148
}

149
int DEBUG_DelDisplay(int displaynum)
Alexandre Julliard's avatar
Alexandre Julliard committed
150
{
151 152 153 154
	int i;

	if (displaynum > ndisplays || displaynum == 0 || displaynum < -1
	    || displaypoints[displaynum - 1].exp == NULL) {
155
		DEBUG_Printf("Invalid display number\n");
156 157 158 159 160 161 162 163 164
		return TRUE;
	}

	if (displaynum == -1) {
		for (i = 0; i < ndisplays; i++) {
			if (displaypoints[i].exp != NULL) {
				DEBUG_FreeExpr(displaypoints[i].exp);
				displaypoints[i].exp = NULL;
			}
Alexandre Julliard's avatar
Alexandre Julliard committed
165
		}
166 167 168 169 170 171 172 173 174 175 176 177 178
		displaypoints = DBG_realloc(displaypoints,
			(maxdisplays = DISPTAB_DELTA) * sizeof(*displaypoints));
		ndisplays = 0;
	} else if (displaypoints[--displaynum].exp != NULL) {
		DEBUG_FreeExpr(displaypoints[displaynum].exp);
		displaypoints[displaynum].exp = NULL;
		while (displaynum == ndisplays - 1
		    && displaypoints[displaynum].exp == NULL)
			--ndisplays, --displaynum;
		if (maxdisplays - ndisplays >= 2 * DISPTAB_DELTA) {
			maxdisplays = (ndisplays + DISPTAB_DELTA - 1) & ~(DISPTAB_DELTA - 1); /* MARK */
			displaypoints = DBG_realloc(displaypoints,
				maxdisplays * sizeof(*displaypoints));
Alexandre Julliard's avatar
Alexandre Julliard committed
179
		}
Alexandre Julliard's avatar
Alexandre Julliard committed
180
	}
181
	return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
182 183
}

184
int DEBUG_EnableDisplay(int displaynum, int enable)
Alexandre Julliard's avatar
Alexandre Julliard committed
185
{
186 187
	--displaynum;
	if (displaynum >= ndisplays || displaynum < 0 || displaypoints[displaynum].exp == NULL) {
188
		DEBUG_Printf("Invalid display number\n");
189
		return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
190
	}
191 192 193 194 195 196 197

	displaypoints[displaynum].enabled = enable;
	if (!displaypoints[displaynum].function_name
	    || displaypoints[displaynum].function_name == DEBUG_GetCurrentFrameFunctionName())
		DEBUG_PrintOneDisplay(displaynum);

	return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
198
}