The R Project SVN R

Rev

Rev 87783 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 r 1
/*
73256 maechler 2
 *  R : A Computer Language for Statistical Data Analysis
2 r 3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
87740 ripley 4
 *  Copyright (C) 1998-2025   The R Core Team.
2 r 5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
42307 ripley 17
 *  along with this program; if not, a copy is available at
68947 ripley 18
 *  https://www.R-project.org/Licenses/
2 r 19
 */
5458 ripley 20
 
5187 hornik 21
#ifdef HAVE_CONFIG_H
7701 hornik 22
#include <config.h>
5187 hornik 23
#endif
2 r 24
 
57538 ripley 25
#define R_USE_SIGNALS 1
26
#include <Defn.h>
60667 ripley 27
#include <Internal.h>
2 r 28
 
83446 ripley 29
attribute_hidden SEXP do_debug(SEXP call, SEXP op, SEXP args, SEXP rho)
2 r 30
{
47969 rgentlem 31
    SEXP ans = R_NilValue;
32
 
1839 ihaka 33
    checkArity(op,args);
6098 pd 34
#define find_char_fun \
35
    if (isValidString(CAR(args))) {				\
36
	SEXP s;							\
63223 ripley 37
	PROTECT(s = installTrChar(STRING_ELT(CAR(args), 0)));	\
10172 luke 38
	SETCAR(args, findFun(s, rho));				\
6098 pd 39
	UNPROTECT(1);						\
1839 ihaka 40
    }
6098 pd 41
    find_char_fun
42
 
68643 maechler 43
    if (TYPEOF(CAR(args)) != CLOSXP &&
44
	TYPEOF(CAR(args)) != SPECIALSXP &&
45
	TYPEOF(CAR(args)) != BUILTINSXP)
70830 luke 46
	error(_("argument must be a function"));
1839 ihaka 47
    switch(PRIMVAL(op)) {
66751 maechler 48
    case 0: // debug()
48998 rgentlem 49
	SET_RDEBUG(CAR(args), 1);
1839 ihaka 50
	break;
66751 maechler 51
    case 1: // undebug()
48998 rgentlem 52
	if( RDEBUG(CAR(args)) != 1 )
70830 luke 53
	    warning("argument is not being debugged");
48998 rgentlem 54
	SET_RDEBUG(CAR(args), 0);
1839 ihaka 55
	break;
66751 maechler 56
    case 2: // isdebugged()
68923 ripley 57
	ans = ScalarLogical(RDEBUG(CAR(args)));
58
	break;
66751 maechler 59
    case 3: // debugonce()
68923 ripley 60
	SET_RSTEP(CAR(args), 1);
61
	break;
1839 ihaka 62
    }
47969 rgentlem 63
    return ans;
2 r 64
}
65
 
68643 maechler 66
/* primitives .primTrace() and .primUntrace() */
83446 ripley 67
attribute_hidden SEXP do_trace(SEXP call, SEXP op, SEXP args, SEXP rho)
2 r 68
{
1839 ihaka 69
    checkArity(op, args);
6098 pd 70
 
71
    find_char_fun
72
 
1895 ihaka 73
    if (TYPEOF(CAR(args)) != CLOSXP &&
68643 maechler 74
	TYPEOF(CAR(args)) != SPECIALSXP &&
75
	TYPEOF(CAR(args)) != BUILTINSXP)
40183 ripley 76
	    errorcall(call, _("argument must be a function"));
1895 ihaka 77
 
1839 ihaka 78
    switch(PRIMVAL(op)) {
79
    case 0:
48998 rgentlem 80
	SET_RTRACE(CAR(args), 1);
1839 ihaka 81
	break;
82
    case 1:
48998 rgentlem 83
	SET_RTRACE(CAR(args), 0);
1839 ihaka 84
	break;
85
    }
86
    return R_NilValue;
2 r 87
}
21102 jmc 88
 
89
 
66751 maechler 90
/* maintain global trace & debug state */
21102 jmc 91
 
66751 maechler 92
static Rboolean tracing_state = TRUE, debugging_state = TRUE;
21102 jmc 93
#define GET_TRACE_STATE tracing_state
66751 maechler 94
#define GET_DEBUG_STATE debugging_state
21102 jmc 95
#define SET_TRACE_STATE(value) tracing_state = value
66751 maechler 96
#define SET_DEBUG_STATE(value) debugging_state = value
21102 jmc 97
 
83446 ripley 98
attribute_hidden SEXP do_traceOnOff(SEXP call, SEXP op, SEXP args, SEXP rho)
41894 ripley 99
{
60633 ripley 100
    checkArity(op, args);
101
    SEXP onOff = CAR(args);
66751 maechler 102
    Rboolean trace = (PRIMVAL(op) == 0),
103
	prev = trace ? GET_TRACE_STATE : GET_DEBUG_STATE;
60633 ripley 104
 
21102 jmc 105
    if(length(onOff) > 0) {
87783 ripley 106
	int _new = asLogical(onOff);
45446 ripley 107
	if(_new == TRUE || _new == FALSE)
87813 ripley 108
	    if(trace) SET_TRACE_STATE((Rboolean) _new);
109
	    else      SET_DEBUG_STATE((Rboolean) _new);
45446 ripley 110
	else
66751 maechler 111
	    error(_("Value for '%s' must be TRUE or FALSE"),
112
		  trace ? "tracingState" : "debuggingState");
21102 jmc 113
    }
41894 ripley 114
    return ScalarLogical(prev);
21102 jmc 115
}
116
 
66751 maechler 117
// GUIs, packages, etc can query:
86647 luke 118
attribute_hidden /* would need to be in an installed header if not hidden */
82931 ripley 119
Rboolean R_current_debug_state(void) { return GET_DEBUG_STATE; }
86647 luke 120
attribute_hidden /* would need to be in an installed header if not hidden */
82931 ripley 121
Rboolean R_current_trace_state(void) { return GET_TRACE_STATE; }
38002 tlumley 122
 
123
 
124
/* memory tracing */
125
/* report when a traced object is duplicated */
126
 
67181 luke 127
#ifdef R_MEMORY_PROFILING
128
 
83446 ripley 129
attribute_hidden SEXP do_tracemem(SEXP call, SEXP op, SEXP args, SEXP rho)
38002 tlumley 130
{
131
    SEXP object;
63692 ripley 132
    char buffer[21];
38002 tlumley 133
 
134
    checkArity(op, args);
51267 ripley 135
    check1arg(args, call, "x");
38002 tlumley 136
 
38426 ripley 137
    object = CAR(args);
40183 ripley 138
    if (TYPEOF(object) == CLOSXP ||
38002 tlumley 139
	TYPEOF(object) == BUILTINSXP ||
140
	TYPEOF(object) == SPECIALSXP)
40183 ripley 141
	errorcall(call, _("argument must not be a function"));
38002 tlumley 142
 
143
    if(object == R_NilValue)
40183 ripley 144
	errorcall(call, _("cannot trace NULL"));
38002 tlumley 145
 
146
    if(TYPEOF(object) == ENVSXP || TYPEOF(object) == PROMSXP)
40183 ripley 147
	errorcall(call,
148
		  _("'tracemem' is not useful for promise and environment objects"));
38002 tlumley 149
    if(TYPEOF(object) == EXTPTRSXP || TYPEOF(object) == WEAKREFSXP)
40183 ripley 150
	errorcall(call,
151
		  _("'tracemem' is not useful for weak reference or external pointer objects"));
38002 tlumley 152
 
48998 rgentlem 153
    SET_RTRACE(object, 1);
63692 ripley 154
    snprintf(buffer, 21, "<%p>", (void *) object);
38002 tlumley 155
    return mkString(buffer);
156
}
157
 
83446 ripley 158
attribute_hidden SEXP do_untracemem(SEXP call, SEXP op, SEXP args, SEXP rho)
38002 tlumley 159
{
160
    SEXP object;
161
 
162
    checkArity(op, args);
51267 ripley 163
    check1arg(args, call, "x");
38002 tlumley 164
 
165
    object=CAR(args);
40183 ripley 166
    if (TYPEOF(object) == CLOSXP ||
38002 tlumley 167
	TYPEOF(object) == BUILTINSXP ||
168
	TYPEOF(object) == SPECIALSXP)
40183 ripley 169
	errorcall(call, _("argument must not be a function"));
38002 tlumley 170
 
48998 rgentlem 171
    if (RTRACE(object))
172
	SET_RTRACE(object, 0);
67181 luke 173
    return R_NilValue;
174
}
175
 
38002 tlumley 176
#else
67181 luke 177
 
87740 ripley 178
NORET attribute_hidden SEXP do_tracemem(SEXP call, SEXP op, SEXP args, SEXP rho)
67181 luke 179
{
69326 luke 180
    checkArity(op, args);
181
    check1arg(args, call, "x");
40183 ripley 182
    errorcall(call, _("R was not compiled with support for memory profiling"));
38002 tlumley 183
}
184
 
87740 ripley 185
NORET attribute_hidden SEXP do_untracemem(SEXP call, SEXP op, SEXP args, SEXP rho)
67181 luke 186
{
69326 luke 187
    checkArity(op, args);
188
    check1arg(args, call, "x");
67181 luke 189
    errorcall(call, _("R was not compiled with support for memory profiling"));
190
}
38002 tlumley 191
 
67181 luke 192
#endif /* R_MEMORY_PROFILING */
193
 
38002 tlumley 194
#ifndef R_MEMORY_PROFILING
86643 luke 195
attribute_hidden void memtrace_report(void* old, void *_new) {
40183 ripley 196
    return;
38002 tlumley 197
}
198
#else
87120 hornik 199
static void memtrace_stack_dump(void)
40183 ripley 200
{
38002 tlumley 201
    RCNTXT *cptr;
38550 tlumley 202
 
38002 tlumley 203
    for (cptr = R_GlobalContext; cptr; cptr = cptr->nextcontext) {
204
	if ((cptr->callflag & (CTXT_FUNCTION | CTXT_BUILTIN))
205
	    && TYPEOF(cptr->call) == LANGSXP) {
206
	    SEXP fun = CAR(cptr->call);
207
	    Rprintf("%s ",
85209 luke 208
		    TYPEOF(fun) == SYMSXP ? EncodeChar(PRINTNAME(fun)) :
38002 tlumley 209
		    "<Anonymous>");
210
	}
211
    }
212
    Rprintf("\n");
40183 ripley 213
}
38002 tlumley 214
 
59378 ripley 215
void memtrace_report(void * old, void * _new)
40183 ripley 216
{
38550 tlumley 217
    if (!R_current_trace_state()) return;
40183 ripley 218
    Rprintf("tracemem[%p -> %p]: ", (void *) old, _new);
38550 tlumley 219
    memtrace_stack_dump();
220
}
38002 tlumley 221
 
222
#endif /* R_MEMORY_PROFILING */
38550 tlumley 223
 
83446 ripley 224
attribute_hidden SEXP do_retracemem(SEXP call, SEXP op, SEXP args, SEXP rho)
38550 tlumley 225
{
226
#ifdef R_MEMORY_PROFILING
66326 luke 227
    SEXP object, previous, ans, argList;
63692 ripley 228
    char buffer[21];
66326 luke 229
    static SEXP do_retracemem_formals = NULL;
78074 kalibera 230
    Rboolean visible; 
38550 tlumley 231
 
66326 luke 232
    if (do_retracemem_formals == NULL)
68923 ripley 233
	do_retracemem_formals = allocFormalsList2(install("x"),
66328 luke 234
						  R_PreviousSymbol);
66326 luke 235
 
77452 luke 236
    PROTECT(argList =  matchArgs_NR(do_retracemem_formals, args, call));
51256 ripley 237
    if(CAR(argList) == R_MissingArg) SETCAR(argList, R_NilValue);
238
    if(CADR(argList) == R_MissingArg) SETCAR(CDR(argList), R_NilValue);
38550 tlumley 239
 
66330 luke 240
    object = CAR(argList);
40183 ripley 241
    if (TYPEOF(object) == CLOSXP ||
38550 tlumley 242
	TYPEOF(object) == BUILTINSXP ||
243
	TYPEOF(object) == SPECIALSXP)
40183 ripley 244
	errorcall(call, _("argument must not be a function"));
38550 tlumley 245
 
66330 luke 246
    previous = CADR(argList);
72385 kalibera 247
    if(!isNull(previous) && (!isString(previous) || LENGTH(previous) != 1))
51256 ripley 248
	    errorcall(call, _("invalid '%s' argument"), "previous");
38550 tlumley 249
 
56663 ripley 250
    if (RTRACE(object)) {
63692 ripley 251
	snprintf(buffer, 21, "<%p>", (void *) object);
78074 kalibera 252
	visible = TRUE;
40183 ripley 253
	ans = mkString(buffer);
51256 ripley 254
    } else {
78074 kalibera 255
	visible = FALSE;
51256 ripley 256
	ans = R_NilValue;
257
    }
38550 tlumley 258
 
51256 ripley 259
    if (previous != R_NilValue){
48998 rgentlem 260
	SET_RTRACE(object, 1);
40183 ripley 261
	if (R_current_trace_state()) {
51256 ripley 262
	    /* FIXME: previous will have <0x....> whereas other values are
263
	       without the < > */
45446 ripley 264
	    Rprintf("tracemem[%s -> %p]: ",
51256 ripley 265
		    translateChar(STRING_ELT(previous, 0)), (void *) object);
40183 ripley 266
	    memtrace_stack_dump();
267
	}
38550 tlumley 268
    }
66326 luke 269
    UNPROTECT(1);
78074 kalibera 270
    R_Visible = visible;
38550 tlumley 271
    return ans;
272
#else
78074 kalibera 273
    R_Visible = FALSE; /* for consistency with other case */
38550 tlumley 274
    return R_NilValue;
275
#endif
276
}