/* The following code is used to recursive traverse a block */
/* of code and extract all the symbols present in that code. */
typedef struct {
SEXP ans;
int UniqueNames;
int IncludeFunctions;
int StoreValues;
int ItemCounts;
int MaxCount;
} NameWalkerData;
NameWalkerData *nameData;
static void namewalk(SEXP s)
{
int i, j, n;
switch(TYPEOF(s)) {
case SYMSXP:
if(nameData->ItemCounts < nameData->MaxCount) {
if(nameData->StoreValues) {
if(nameData->UniqueNames) {
for(j=0 ; jItemCounts ; j++) {
if(STRING_ELT(nameData->ans, j) == PRINTNAME(s))
goto ignore;
}
}
SET_STRING_ELT(nameData->ans, nameData->ItemCounts, PRINTNAME(s));
}
nameData->ItemCounts += 1;
}
ignore:
break;
case LANGSXP:
if(!nameData->IncludeFunctions) s = CDR(s);
while(s != R_NilValue) {
namewalk(CAR(s));
s = CDR(s);
}
break;
case EXPRSXP:
n = length(s);
for(i=0 ; iIncludeFunctions = asLogical(CAR(args));
if(nameData->IncludeFunctions == NA_LOGICAL)
nameData->IncludeFunctions = 0;
args = CDR(args);
nameData->MaxCount = asInteger(CAR(args));
if(nameData->MaxCount < 0 || nameData->MaxCount == NA_INTEGER)
nameData->MaxCount = 0;
args = CDR(args);
nameData->UniqueNames = asLogical(CAR(args));
if(nameData->UniqueNames == NA_LOGICAL)
nameData->UniqueNames = 1;
nameData->StoreValues = 0;
nameData->ItemCounts = 0;
namewalk(expr);
savecount = nameData->ItemCounts;
nameData->ans = allocVector(STRSXP, nameData->ItemCounts);
nameData->StoreValues = 1;
nameData->ItemCounts = 0;
namewalk(expr);
if(nameData->ItemCounts != savecount) {
PROTECT(expr = nameData->ans);
nameData->ans = allocVector(STRSXP, nameData->ItemCounts);
for(i=0 ; iItemCounts ; i++)
SET_STRING_ELT(nameData->ans, i, STRING_ELT(expr, i));
UNPROTECT(1);
}
return nameData->ans;
}
Duncan Temple Lang
<duncan@research.bell-labs.com>
Last modified: Wed Dec 20 12:26:28 EST 2000