R-alpha: compatibility functions
Paul Gilbert
pgilbert@bank-banque-canada.ca
Tue, 4 Nov 1997 15:27:08 -0500
Below is a revised copy of my compatibility functions with additions
from Martin. I expect I may need a new version when 0.6 arrives but I
thought it would be worth circulating this in case it suggests anything
which might be resolved before the release of 0.6 rather than after.
Thanks to a few people for pointing out the R function machine(). I have
a kludge below for determining the same information in S. If anyone has
a better way to do this I would appreciate it.
There are also several functions where the non-unix versions have not
been defined. Suggestions would be appreciated.
Paul Gilbert
##############################################################################
# This file has code which contains operating system and S/R specific
# functions. They are intended to be used as a kernel to help
# protect other code from these problems.
# The following functions are attempted:
# For S/R differences:
# global.assign, system.info, exists.graphics.device, unlink,
# synchronize, list.add for [["new.element"]]<-
# For OS differences:
# system.call, sleep, present.working.directory, whoami, file.copy,
# file.date.info, date, mail, unlink, local.host.netname,
# Also a number of is.xxx functions are defined to identify systems.
# The variable .SPAWN is also set to be used to identify if Splus "For"
loops
# should be used. (It is sometimes better not to use these even in
Splus.)
##############################################################################
# General Logic and organization of these functions
# 1/ The first group of functions are for identifying S or R and
flavours.
# 2/ The second group of functions are for identifying the operating
system.
# 3/ The third group specify a few functions which depend only on the
# differences between S and R.
# 4/ The fourth group specify functions which depend only on the
# differences among operating system.
# 5/ The fifth group specify a few functions which depend on both R/S
and the
# differences among operating system.
# >>> I would very much like any input WRT MS Windows / Win95 / NT /
Mac <<<
# The function system.call is defined in order to provide a generic way
to
# make a call to the operating system. However, when the calls are
specific
# to Unix then the function unix() is used.
##############################################################################
system.info <- function()
{if( !exists("version"))
{ #-- `Vanilla' S (i.e. here "S version 4")
#- this now works for S version 4 (this is not S-plus 4.0,
maybe
# part of S-plus 5.0 !):
lv <- nchar(Sv <- Sversion())
r <- list(
major = substring(Sv, 1,1),
minor = substring(Sv, lv,lv))
}
else
{r <- version
r$minor <- as.numeric(r$minor)
r$major <- as.numeric(r$major)
}
if (is.Splus()) r$language <- "Splus"
else if (is.Svanilla()) r$language <- "S"
r$OSversion <- OSversion()
r$OStype <- machine()
r
}
###########################################################
# 1/ Functions are for identifying S or R and flavours.
###########################################################
#Note It is tempting to use system.info as defined above, but there is a
# bootstrapping problem to solve.
is.R <- function()
{exists("version") && !is.null(vl <- version$language) && vl == "R" }
is.R.pre0.60 <- function()
{is.R() && ((as.numeric(version$major)+.01*as.numeric(version$major))
<0.60) }
is.S <- function(){is.Svanilla() | is.Splus() }
is.Svanilla <- function(){!exists("version")}
is.Splus <- function(){exists("version") && is.null(version$language)}
is.Splus.pre3.3 <- function()
{ ## <= 3.2
is.Splus() && ((system.info()$major+.1*system.info()$minor) < 3.3)
}
###########################################################
# 2/ Functions are for identifying the operating system.
###########################################################
# if (is.R()) {machine <- machine}
if (is.S())
{machine <- function()
{if (version$os == "MS Windows") return(version$os)
if (version$os == "Macintosh") return(version$os) # needs to be
checked
else return ("Unix") # not a very satisfactory test
}
}
is.MSwindows <- function(){machine() == "MS Windows"}
is.Mac <- function(){machine() == "Macintosh" }
is.unix <- function(){machine() == "Unix" }
# Other is.xxx() should be added here.
# determining Unix flavours doesn't seem to be too important but ...
is.Sun4 <- function() {OSversion() == "SunOS4" }
is.Sun5 <- function() {OSversion() == "SunOS5" }
is.Linux <- function(){OSversion() == "linux"}
OSversion <- function()
{paste(unix("uname -s"), unix("uname -r | sed -e 's/\\.\.\*//'"),
sep="") }
###########################################################
# 3/ Functions depending only on the
# differences between S and R
###########################################################
if(is.S())
{if(is.unix())system.call <- unix
global.assign <- function(name, value) {assign(name,value, where =
1)}
.SPAWN <- TRUE
exists.graphics.device <- function(){dev.cur() !=1 }
open.graphics.device <- function(display=getenv("DISPLAY"))
{openlook(display) }
# {motif(display) }
close.graphics.device <- function(){dev.off() }
if (!exists("set.seed.Splus")) set.seed.Splus <- set.seed
set.seed <- function(seed=NULL)
{if (is.null(seed))
seed <-.Random.seed
else
{if (1==length(seed)) set.seed.Splus(seed)
else global.assign(".Random.seed", seed)
}
seed
}
"list.add<-" <- function(x, replace, value)
{# replace or add elements to a list.
x[replace] <- value
# x[[replace]] <- value would be more logical but doesn't work
x
}
}
if(is.R())
{#tempfile <- function(f)
# {# Requires C code also from Friedrich Leisch not in version
0.15 of R.
# d<-"This is simply a string long enough to hold the name of a
tmpfile";
# .C("tmpf", as.character(d))[[1]]
# }
if (is.R.pre0.60())
{tempfile <- function(pattern = "file")
{system(paste("for p in", paste(pattern, collapse = "
"), ";",
"do echo /tmp/$p$$; done"),
intern = TRUE)
}
}
unlink <- function(file) system.call(paste("rm -fr ", file))
global.assign <- function(name, value)
{assign(name,value, envir=.GlobalEnv)}
synchronize<- function(x){NULL} # perhaps this should do something?
.SPAWN <- FALSE
exists.graphics.device <- function(){exists(".Device")}
open.graphics.device <- function(display=getenv("DISPLAY"))
{x11(display) }
close.graphics.device <- function(){F} # how do I do this?
set.seed <- function(seed=NULL)
{if (is.null(seed))
{if (!exists(".Random.seed")) zzz <- runif(1) # seed may not
yet exist
seed <-.Random.seed
}
else
{if (1==length(seed))
global.assign(".Random.seed",round(runif(3,min=seed,max=1e5*seed)))
else global.assign(".Random.seed", seed)
}
seed
}
"list.add<-" <- function(x, replace, value)
{# replace or add elements to a list.
if (is.numeric(replace))
{# x<- do.call("default.[[<-", list(x,replace,value)) # use
default
x[[replace]] <- value
return(x)
}
if (is.null(value)) value <- list(NULL)
if (!is.list(value)) value <- list(value)
if (1 == length(value))
{for (i in seq(length(replace)))
x<- do.call("$<-", list(x,replace[i],value[[1]]))
}
else
{if(length(value) != length(replace) )
stop("number of replacement values != number of elements to
replace")
for (i in seq(length(replace)))
x<- do.call("$<-", list(x,replace[i],value[[i]]))
}
x
}
}
###########################################################
# 4/ Functions depending only on the
# differences among operating system.
###########################################################
if(is.unix())
{sleep <- function(n) {unix(paste("sleep ", n))} # pause for n seconds
present.working.directory <- function(){unix("pwd")} # present
directory
whoami <- function(){unix("whoami")} # return user id (for mail)
local.host.netname <-function() {unix("uname -n")}
mail <- function(to, subject="", text="")
{# If to is null then mail is not sent (useful for testing).
file <- tempfile()
write(text, file=file)
if(!is.null(to)) unix(paste("cat ",file, " | mail -s '", subject, "'
", to))
unlink(file)
invisible()
}
file.copy <- function(from, to)unix(paste("cp ", from, to)) # copy
file
file.date.info <- function(file.name)
{# This could be a lot better. It will fail for files older than a
year.
# Also, a returned format like date() below would be better.
mo <- (1:12)[c("Jan","Feb","Mar","Apr","May", "Jun","Jul","Aug",
"Sep",
"Oct","Nov","Dec") ==substring(unix(paste("ls -l
",file)),33,35)]
day <- as.integer(substring(unix(paste("ls -l
",file.name)),37,38))
hr <- as.integer(substring(unix(paste("ls -l
",file.name)),40,41))
sec <- as.integer(substring(unix(paste("ls -l
",file.name)),43,44))
c(mo,day,hr,sec)
}
}
if(is.MSwindows())
{system.call <- function(cmd)
{stop("system calls must be modified for this operating
system.")}
sleep <- system.call
present.working.directory <- system.call
whoami <- system.call
file.copy <- system.call
file.date.info <- system.call
}
###########################################################
# 5/ Functions depending on both R/S and the
# differences among operating system.
###########################################################
if(is.unix())
{if(is.R())
{unix <- function(cmd) system(cmd, intern=T)
system.call <- function(cmd) system(cmd, intern=T)
date <-function()
{d<-parse(text=strsplit(
unix("date \'+%Y %m %d %H %M %S\'")," ")[[1]])
list(y= eval(d[1]),
m=eval(d[2]),
d= eval(d[3]),
h= eval(d[4]),
m= eval(d[5]),
s= eval(d[6]),
tz=unix("date '+%Z'"))
}
}
if(is.S())
{system.call <- function(cmd) unix(cmd)
date <-function()
{d <- parse(text=unix("date '+%Y %m %d %H %M %S'"),white=T)
list(y= eval(d[1]),
m=eval(d[2]),
d= eval(d[3]),
h= eval(d[4]),
m= eval(d[5]),
s= eval(d[6]),
tz=unix("date '+%Z'"))
}
}
}
##############################################################################
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !) To: r-devel-request@stat.math.ethz.ch
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=