Added files in src/math
[pspp] / src / pfm-read.c
index a1ee05509566225fea31693fb8127896bcc72b7d..f398747584ae9b7e48c5ffeee25bebfb66581fc1 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - computes sample statistics.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
    Written by Ben Pfaff <blp@gnu.org>.
    Code for parsing floating-point numbers adapted from GNU C
    library.
 
 #include "debug-print.h"
 
+/* portable_to_local[PORTABLE] translates the given portable
+   character into the local character set. */
+static const char portable_to_local[256] =
+  {
+    "                                                                "
+    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ."
+    "<(+|&[]!$*);^-/|,%_>?`:$@'=\"      ~-   0123456789   -() {}\\     "
+    "                                                                "
+  };
+
 /* Portable file reader. */
 struct pfm_reader
   {
@@ -82,7 +92,7 @@ error (struct pfm_reader *r, const char *msg, ...)
 
   e.class = ME;
   getl_location (&e.where.filename, &e.where.line_number);
-  filename = handle_get_filename (r->fh);
+  filename = fh_get_filename (r->fh);
   e.title = title = pool_alloc (r->pool, strlen (filename) + 80);
   sprintf (title, _("portable file %s corrupt at offset %ld: "),
            filename, ftell (r->file));
@@ -149,7 +159,7 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
   struct pfm_reader *volatile r = NULL;
 
   *dict = dict_create ();
-  if (!fh_open (fh, "portable file", "rs"))
+  if (!fh_open (fh, FH_REF_FILE, "portable file", "rs"))
     goto error;
 
   /* Create and initialize reader. */
@@ -159,7 +169,7 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
   if (setjmp (r->bail_out))
     goto error;
   r->fh = fh;
-  r->file = pool_fopen (r->pool, handle_get_filename (r->fh), "rb");
+  r->file = pool_fopen (r->pool, fh_get_filename (r->fh), "rb");
   r->weight_index = -1;
   r->trans = NULL;
   r->var_cnt = 0;
@@ -171,7 +181,7 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
     {
       msg (ME, _("An error occurred while opening \"%s\" for reading "
                  "as a portable file: %s."),
-           handle_get_filename (r->fh), strerror (errno));
+           fh_get_filename (r->fh), strerror (errno));
       err_cond_fail ();
       goto error;
     }
@@ -353,16 +363,6 @@ read_pool_string (struct pfm_reader *r)
 static void
 read_header (struct pfm_reader *r)
 {
-  /* portable_to_local[PORTABLE] translates the given portable
-     character into the local character set. */
-  static const char portable_to_local[256] =
-    {
-      "                                                                "
-      "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ."
-      "<(+|&[]!$*);^-/|,%_>?`:$@'=\"      ~-   0123456789   -() {}\\     "
-      "                                                                "
-    };
-
   char *trans;
   int i;
 
@@ -400,7 +400,7 @@ read_header (struct pfm_reader *r)
   for (i = 0; i < 8; i++) 
     if (!match (r, "SPSSPORT"[i])) 
       {
-        msg (SE, _("%s: Not a portable file."), handle_get_filename (r->fh));
+        msg (SE, _("%s: Not a portable file."), fh_get_filename (r->fh));
         longjmp (r->bail_out, 1);
       }
 }
@@ -687,3 +687,38 @@ pfm_read_case (struct pfm_reader *r, struct ccase *c)
   
   return true;
 }
+
+/* Returns true if FILE is an SPSS portable file,
+   false otherwise. */
+bool
+pfm_detect (FILE *file) 
+{
+  unsigned char header[464];
+  char trans[256];
+  int cooked_cnt, raw_cnt;
+  int i;
+
+  cooked_cnt = raw_cnt = 0;
+  while (cooked_cnt < sizeof header)
+    {
+      int c = getc (file);
+      if (c == EOF || raw_cnt++ > 512)
+        return false;
+      else if (c != '\n' && c != '\r') 
+        header[cooked_cnt++] = c;
+    }
+
+  memset (trans, 0, 256);
+  for (i = 64; i < 256; i++) 
+    {
+      unsigned char c = header[i + 200];
+      if (trans[c] == 0)
+        trans[c] = portable_to_local[i];
+    }
+
+  for (i = 0; i < 8; i++) 
+    if (trans[header[i + 456]] != "SPSSPORT"[i]) 
+      return false; 
+
+  return true;
+}