The R Project SVN R

Rev

Rev 73256 | Rev 82931 | Go to most recent revision | 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
68643 maechler 4
 *  Copyright (C) 1998-2015   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
 
36990 ripley 29
SEXP attribute_hidden 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() */
36990 ripley 67
SEXP attribute_hidden 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
 
60633 ripley 98
SEXP attribute_hidden 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) {
45446 ripley 106
	Rboolean _new = asLogical(onOff);
107
	if(_new == TRUE || _new == FALSE)
66751 maechler 108
	    if(trace) SET_TRACE_STATE(_new);
109
	    else      SET_DEBUG_STATE(_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:
118
Rboolean R_current_debug_state() { return GET_DEBUG_STATE; }
119
Rboolean R_current_trace_state() { return GET_TRACE_STATE; }
38002 tlumley 120
 
121
 
122
/* memory tracing */
123
/* report when a traced object is duplicated */
124
 
67181 luke 125
#ifdef R_MEMORY_PROFILING
126
 
51256 ripley 127
SEXP attribute_hidden do_tracemem(SEXP call, SEXP op, SEXP args, SEXP rho)
38002 tlumley 128
{
129
    SEXP object;
63692 ripley 130
    char buffer[21];
38002 tlumley 131
 
132
    checkArity(op, args);
51267 ripley 133
    check1arg(args, call, "x");
38002 tlumley 134
 
38426 ripley 135
    object = CAR(args);
40183 ripley 136
    if (TYPEOF(object) == CLOSXP ||
38002 tlumley 137
	TYPEOF(object) == BUILTINSXP ||
138
	TYPEOF(object) == SPECIALSXP)
40183 ripley 139
	errorcall(call, _("argument must not be a function"));
38002 tlumley 140
 
141
    if(object == R_NilValue)
40183 ripley 142
	errorcall(call, _("cannot trace NULL"));
38002 tlumley 143
 
144
    if(TYPEOF(object) == ENVSXP || TYPEOF(object) == PROMSXP)
40183 ripley 145
	errorcall(call,
146
		  _("'tracemem' is not useful for promise and environment objects"));
38002 tlumley 147
    if(TYPEOF(object) == EXTPTRSXP || TYPEOF(object) == WEAKREFSXP)
40183 ripley 148
	errorcall(call,
149
		  _("'tracemem' is not useful for weak reference or external pointer objects"));
38002 tlumley 150
 
48998 rgentlem 151
    SET_RTRACE(object, 1);
63692 ripley 152
    snprintf(buffer, 21, "<%p>", (void *) object);
38002 tlumley 153
    return mkString(buffer);
154
}
155
 
51256 ripley 156
SEXP attribute_hidden do_untracemem(SEXP call, SEXP op, SEXP args, SEXP rho)
38002 tlumley 157
{
158
    SEXP object;
159
 
160
    checkArity(op, args);
51267 ripley 161
    check1arg(args, call, "x");
38002 tlumley 162
 
163
    object=CAR(args);
40183 ripley 164
    if (TYPEOF(object) == CLOSXP ||
38002 tlumley 165
	TYPEOF(object) == BUILTINSXP ||
166
	TYPEOF(object) == SPECIALSXP)
40183 ripley 167
	errorcall(call, _("argument must not be a function"));
38002 tlumley 168
 
48998 rgentlem 169
    if (RTRACE(object))
170
	SET_RTRACE(object, 0);
67181 luke 171
    return R_NilValue;
172
}
173
 
38002 tlumley 174
#else
67181 luke 175
 
176
SEXP attribute_hidden NORET do_tracemem(SEXP call, SEXP op, SEXP args, SEXP rho)
177
{
69326 luke 178
    checkArity(op, args);
179
    check1arg(args, call, "x");
40183 ripley 180
    errorcall(call, _("R was not compiled with support for memory profiling"));
38002 tlumley 181
}
182
 
67181 luke 183
SEXP attribute_hidden NORET do_untracemem(SEXP call, SEXP op, SEXP args, SEXP rho)
184
{
69326 luke 185
    checkArity(op, args);
186
    check1arg(args, call, "x");
67181 luke 187
    errorcall(call, _("R was not compiled with support for memory profiling"));
188
}
38002 tlumley 189
 
67181 luke 190
#endif /* R_MEMORY_PROFILING */
191
 
38002 tlumley 192
#ifndef R_MEMORY_PROFILING
59378 ripley 193
void memtrace_report(void* old, void *_new) {
40183 ripley 194
    return;
38002 tlumley 195
}
196
#else
40183 ripley 197
static void memtrace_stack_dump(void)
198
{
38002 tlumley 199
    RCNTXT *cptr;
38550 tlumley 200
 
38002 tlumley 201
    for (cptr = R_GlobalContext; cptr; cptr = cptr->nextcontext) {
202
	if ((cptr->callflag & (CTXT_FUNCTION | CTXT_BUILTIN))
203
	    && TYPEOF(cptr->call) == LANGSXP) {
204
	    SEXP fun = CAR(cptr->call);
205
	    Rprintf("%s ",
40705 ripley 206
		    TYPEOF(fun) == SYMSXP ? translateChar(PRINTNAME(fun)) :
38002 tlumley 207
		    "<Anonymous>");
208
	}
209
    }
210
    Rprintf("\n");
40183 ripley 211
}
38002 tlumley 212
 
59378 ripley 213
void memtrace_report(void * old, void * _new)
40183 ripley 214
{
38550 tlumley 215
    if (!R_current_trace_state()) return;
40183 ripley 216
    Rprintf("tracemem[%p -> %p]: ", (void *) old, _new);
38550 tlumley 217
    memtrace_stack_dump();
218
}
38002 tlumley 219
 
220
#endif /* R_MEMORY_PROFILING */
38550 tlumley 221
 
51256 ripley 222
SEXP attribute_hidden do_retracemem(SEXP call, SEXP op, SEXP args, SEXP rho)
38550 tlumley 223
{
224
#ifdef R_MEMORY_PROFILING
66326 luke 225
    SEXP object, previous, ans, argList;
63692 ripley 226
    char buffer[21];
66326 luke 227
    static SEXP do_retracemem_formals = NULL;
38550 tlumley 228
 
66326 luke 229
    if (do_retracemem_formals == NULL)
68923 ripley 230
	do_retracemem_formals = allocFormalsList2(install("x"),
66328 luke 231
						  R_PreviousSymbol);
66326 luke 232
 
77452 luke 233
    PROTECT(argList =  matchArgs_NR(do_retracemem_formals, args, call));
51256 ripley 234
    if(CAR(argList) == R_MissingArg) SETCAR(argList, R_NilValue);
235
    if(CADR(argList) == R_MissingArg) SETCAR(CDR(argList), R_NilValue);
38550 tlumley 236
 
66330 luke 237
    object = CAR(argList);
40183 ripley 238
    if (TYPEOF(object) == CLOSXP ||
38550 tlumley 239
	TYPEOF(object) == BUILTINSXP ||
240
	TYPEOF(object) == SPECIALSXP)
40183 ripley 241
	errorcall(call, _("argument must not be a function"));
38550 tlumley 242
 
66330 luke 243
    previous = CADR(argList);
72385 kalibera 244
    if(!isNull(previous) && (!isString(previous) || LENGTH(previous) != 1))
51256 ripley 245
	    errorcall(call, _("invalid '%s' argument"), "previous");
38550 tlumley 246
 
56663 ripley 247
    if (RTRACE(object)) {
63692 ripley 248
	snprintf(buffer, 21, "<%p>", (void *) object);
40183 ripley 249
	ans = mkString(buffer);
51256 ripley 250
    } else {
251
	R_Visible = 0;
252
	ans = R_NilValue;
253
    }
38550 tlumley 254
 
51256 ripley 255
    if (previous != R_NilValue){
48998 rgentlem 256
	SET_RTRACE(object, 1);
40183 ripley 257
	if (R_current_trace_state()) {
51256 ripley 258
	    /* FIXME: previous will have <0x....> whereas other values are
259
	       without the < > */
45446 ripley 260
	    Rprintf("tracemem[%s -> %p]: ",
51256 ripley 261
		    translateChar(STRING_ELT(previous, 0)), (void *) object);
40183 ripley 262
	    memtrace_stack_dump();
263
	}
38550 tlumley 264
    }
66326 luke 265
    UNPROTECT(1);
38550 tlumley 266
    return ans;
267
#else
59451 ripley 268
    R_Visible = 0; /* for consistency with other case */
38550 tlumley 269
    return R_NilValue;
270
#endif
271
}