Rev 5284 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
### This file is part of the 'foreign' package for R.# This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program 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 General Public License for more details.## A copy of the GNU General Public License is available at# http://www.r-project.org/Licenses/#SModeNames <-c("name", "string", "literal", "compiled", "(", ")", "[", "]","{", "}", ",", "=", "!", ":", "addop", "*/", "<dummy>", "^","-", "$", "logop", "&|", "<-", "->", "sp.op", " ", "repeat","if", "else", "break", ";", "next", "while", "for", "in", "recursive.return","return", "argument", "system", "end.of.file", "expression","system.function", "missing", "call", "function", "?", "unbalanced","[[", "unknown", "]]", "quit", "continue", "comment.expression","vector", "call(...)", "<<-", "graphics", "arg.lvalue", "internal","S.call", "S.data", "comment", "comment(leftover)","evaluation.frame", "destination")nam.or.i <- function(nam, i) if (nam != "") nam else iread.S <- function (file){endian <- .Platform$endians <- file(file, open = "rb")on.exit(close(s))readheader <- function(s){head <- readBin(s, "int", 8L, 1L)all(head == c(0L, 83L, 32L, 100L, 97L, 116L, 97L, 1L))}ReadSObj <- function (code, len){if (code == 1L)result <- as.logical(readBin(s, "int", len, endian = endian))else if (code == 2L)result <- readBin(s, "int", len, endian = endian)else if (code == 3L)result <- readBin(s, "numeric", len, size=4L, endian = endian)else if (code == 4L)result <- readBin(s, "numeric", len, endian = endian)else if (code == 5L) {charsize <- readBin(s, "int", endian = endian)newpos <- charsize + seek(s, NA)result <- readBin(s, "character", len)seek(s, newpos)}else if (code == 6L) {result <- list()if (len) {names <- ReadSObj(5L, len)codes <- ReadSObj(2L, len)lens <- ReadSObj(2L, len)offsets <- ReadSObj(2, len)for (i in 1L:len) {seek(s, offsets[i])temp <-if (codes[i] > 0L)ReadSObj(codes[i], lens[i]) else as.name(names[i])result[[nam.or.i(names[i], i)]] <- temp}}}else if (code == 7L)result <- readBin(s, "complex", len, endian = endian)else if (code == 21L) {temp <- ReadSObj(6L, len)result <- temp[[".Data"]]attributes(result) <-temp[-match(c(".Data", ".Dim", ".Dimnames", ".Label"),names(temp), nomatch = 0L)]dim(result) <- temp[[".Dim"]]names(result) <- names(temp[[".Data"]])if (!is.null(temp[[".Label"]]))levels(result) <- temp[[".Label"]]if (!is.null(temp[[".Dimnames"]]))dimnames(result) <- temp[[".Dimnames"]]}else if (code %in% 257L:321L) {code <- SModeNames[code - 256L]if (code %in% c("name", "missing"))result <- ReadSObj(5L, len)elseresult <- ReadSObj(6L, len)if (code == "function")try(result <- as.function(result, env=.GlobalEnv))else if (code %in% c("break", "if", "for", "return", "S.call","while", "<-", "<<-", "(", "{"))result <- as.call(c(as.name(code),result))else if (code == "call(...)")# these aren't special in Rresult <- result[[1L]]else if (code == "comment") # ignore commentsresult <- NULLelse if (code == "comment.expression")# just keep the expression, not the commentresult <- result[unlist(lapply(result,function(y) !is.null(y)))][[1L]]else if (code == "internal")result <- as.call(list(as.name(".Internal"), result[[1L]]))else if (code == "missing")result <- call("stop", "Argument is missing")else try(mode(result) <- code)}else {return(paste("Unrecognized S mode", code, "not supported"))}result}if(readheader(s)) {code <- readBin(s, "int", endian = endian)if (code < 0L | code > 65535L) {endian <- switch(endian, big = "little", little = "big")seek(s, seek(s, NA) - 4)code <- readBin(s, "int", endian = endian)if (code < 0L | code > 65535L)stop("internal error - illegal S code value")}len <- readBin(s, "int", endian = endian)return(ReadSObj(code, len))}else stop("not an S object")}data.restore <-function (file, print = FALSE, verbose = FALSE, env = .GlobalEnv){dump <- file(file, open="rt")on.exit(close(dump))ReadSdump <- function(top = FALSE, prefix) {name <- readLines(dump, 1L)if(length(name) == 0L) return(NULL)code <- readLines(dump, 1L)len <- as.integer(readLines(dump, 1L))if (top && print)cat("\"", name, "\": ", code, "\n", sep="")if (verbose)cat(prefix, summary(dump)$position, name, code, len, "\n")## first decide between atomic and "the rest"if (code %in% c("logical", "numeric","integer","single","double","character", "name", "missing", "complex")) {value <- readLines(dump, len)value[value == "N"] <- as.character(NA)if (code != "character")value <-if (code == "logical")# "0", "1" and <NA> :as.logical(as.integer(value))else if (code %in% c("integer", "double", "name", "complex"))methods::as(value, code)else if (code %in% c("numeric","single"))as.numeric(value)else if (code == "missing")## Workaround: should be value <- as.name("")call("stop",paste("Argument ", sQuote(name), " is missing",sep=""))}else if (code %in% c("list", "structure", "NULL", SModeNames)) {value <- list()for (i in seq_len(len)) {temp <- ReadSdump(FALSE, c(prefix, " "))value[[nam.or.i(temp$name,i)]] <- temp$value}if (code == "structure") {thelist <- valuevalue <- thelist[[".Data"]]attributes(value) <-thelist[-match(c(".Data", ".Dim", ".Dimnames", ".Label"),names(thelist), nomatch = 0L)]dim(value) <- thelist[[".Dim"]]names(value) <- names(thelist[[".Data"]])if (!is.null(thelist[[".Label"]]))levels(value) <- thelist[[".Label"]]if (!is.null(thelist[[".Dimnames"]]))try(dimnames(value) <- thelist[[".Dimnames"]])if (!is.null(tsp <- thelist[[".Tsp"]]))# valid R ts()try(value <- stats::ts(c(value),tsp[1L],tsp[2L],tsp[3L]))}else if (code == "function")try(value <- as.function(value,env=env))else if (code %in% c("break", "if", "for", "return", "S.call","while", "<-", "<<-", "(", "{"))value <- as.call(c(as.name(code), value))else if (code == "NULL") {value <- if (name != "") as.name(name)}else if (code == "call(...)")# these aren't special in Rvalue <- value[[1L]]else if (code == "comment") # ignore commentsvalue <- NULLelse if (code == "comment.expression")# just keep the expression, not the commentvalue <- value[unlist(lapply(value,function(y) !is.null(y)))][[1L]]else if (code == "internal")value <- as.call(list(as.name(".Internal"), value[[1L]]))else try(mode(value) <- code)}else {stop(gettextf("S mode %s (near byte offset %s) not supported",sQuote(code), seek(dump)), domain = NA)}list(name = name, value = value)}repeat {temp <- ReadSdump(TRUE, " ")if(is.null(temp)) breakassign(temp$name, temp$value, envir = env)}file}