Hi all,
I got no feedback at all concerning the merge of this patch in the source tree.
Am I supposed to do this myself? How should I do this (do I have subversion
commit
access)? Is this patch acceptable at all? Is it being tested?
I got some personal reactions on my post, proving there is general interest in
getting rid of the inconvenience of importing long labels from SPSS files.
Kurt Van Dijck wrote:
Hi,
A frequently seen issue with importing SPSS data files, is that R does
not import the 'long variable names'.
I built a patch on the R-project's foreign module, in order to import
the 'long variable names' from SPSS (record 7, subtype 13).
To complete the job, I had to expand the "struct variable" definition
to have 64 +1 charachters. I'm not aware of side effects.
The sfm-read.c code works fine.
I didn't test a variety of platforms, as I don't have an idea of what is
regarded as sufficient testing. Anyway, I don't expect major troubles there
(no byteswapping problems, no 32<->64 bit issues) as it's mainly
character processing.
The patch is relative to the foreign directory. It was created
against the trunk of R-project yesterday.
We would appreciate that you import such patch into the main tree.
Kind regards,
Kurt Van Dijck (C programmer) & Ilse Laurijssen (R user)
Belgium
Index: src/sfm-read.c
===
--- src/sfm-read.c(revision 5168)
+++ src/sfm-read.c(working copy)
@@ -188,6 +188,8 @@
static int read_variables (struct file_handle * h, struct variable ***
var_by_index);
static int read_machine_int32_info (struct file_handle * h, int size,
int count, int *encoding);
static int read_machine_flt64_info (struct file_handle * h, int size,
int count);
+static int read_long_var_names (struct file_handle * h, struct
dictionary *
+, unsigned long size, unsigned int count);
static int read_documents (struct file_handle * h);
/* Displays the message X with corrupt_msg, then jumps to the lossage
@@ -418,11 +420,15 @@
break;
case 7: /* Multiple-response sets (later versions of SPSS). */
- case 13: /* long variable names. PSPP now has code for these
- that could be ported if someone is interested. */
skip = 1;
break;
+ case 13:/* long variable names. PSPP now has code for these
+ that could be ported if someone is interested. */
+if (!read_long_var_names(h, ext->dict, data.size, data.count))
+ goto lossage;
+break;
+
case 16: /* See
http://www.nabble.com/problem-loading-SPSS-15.0-save-files-t2726500.html */
skip = 1;
break;
@@ -584,14 +590,72 @@
return 0;
}
+/* Read record type 7, subtype 13.
+ * long variable names
+ */
static int
+read_long_var_names (struct file_handle * h, struct dictionary * dict
+, unsigned long size, unsigned int count)
+{
+ char * data;
+ unsigned int j;
+ struct variable ** lp;
+ struct variable ** end;
+ char * p;
+ char * endp;
+ char * val;
+ if ((1 != size)||(0 == count)) {
+warning("%s: strange record info seen, size=%u, count=%u"
+ ", ignoring long variable names"
+ , h->fn, size, count);
+return 0;
+ }
+ size *= count;
+ data = Calloc (size +1, char);
+ bufread(h, data, size, 0);
+ /* parse */
+ end = &dict->var[dict->nvar];
+ p = data;
+ do {
+if (0 != (endp = strchr(p, '\t')))
+ *endp = 0; /* put null terminator */
+if (0 == (val = strchr(p, '='))) {
+ warning("%s: no long variable name for variable '%s'", h->fn, p);
+} else {
+ *val = 0;
+ ++val;
+ /* now, p is key, val is long name */
+ for (lp = dict->var; lp < end; ++lp) {
+if (!strcmp(lp[0]->name, p)) {
+ strncpy(lp[0]->name, val, sizeof(lp[0]->name));
+ break;
+}
+ }
+ if (lp >= end) {
+warning("%s: long variable name mapping '%s' to '%s'"
+"for variable which does not exist"
+, h->fn, p, val);
+ }
+}
+p = &endp[1]; /* put to next */
+ } while (endp);
+
+ free(data);
+ return 1;
+
+lossage:
+ free(data);
+ return 0;
+}
+
+static int
read_header (struct file_handle * h, struct sfm_read_info * inf)
{
struct sfm_fhuser_ext *ext = h->ext;/* File extension strcut. */
struct sysfile_header hdr;/* Disk buffer. */
struct dictionary *dict;/* File dictionary. */
char prod_name[sizeof hdr.prod_name + 1];/* Buffer for product
name. */
- int skip_amt = 0;/* Amount of product name to omit. */
+ int skip_amt = 0;/* Amount of product name to omit. */
int i;
/* Create the dictionary. */
@@ -1495,7 +1559,7 @@
/* Reads one case from system file H into the value array PERM
according to the instructions given in associated dictionary DICT,
which must have the get.* elements appropriately set. Returns
- nonzero only if successful. */
+ n