Subcommand to export a model as a C function
[pspp-builds.git] / src / file-handle.q
index dc1e9383c60abfa16260cae8d38694ef7f5ff908..24a91a9fed371922a05438bb47460afe706476ef 100644 (file)
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA. */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
 
 #include <config.h>
 #include "file-handle.h"
-#include <assert.h>
+#include "error.h"
 #include <errno.h>
 #include <stdlib.h>
 #include "alloc.h"
 #include "filename.h"
 #include "command.h"
 #include "lexer.h"
-#include "getline.h"
+#include "getl.h"
 #include "error.h"
 #include "magic.h"
 #include "var.h"
-/* (headers) */
+#include "linked-list.h"
+#include "file-handle-def.h"
 
-/* File handle private data. */
-struct private_file_handle 
-  {
-    char *name;                 /* File handle identifier. */
-    char *filename;            /* Filename as provided by user. */
-    struct file_identity *identity; /* For checking file identity. */
-    struct file_locator where; /* Used for reporting error messages. */
-    enum file_handle_mode mode;        /* File mode. */
-    size_t length;             /* Length of fixed-format records. */
-  };
-
-/* Linked list of file handles. */
-struct file_handle_list 
-  {
-    struct file_handle *handle;
-    struct file_handle_list *next;
-  };
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
 
-static struct file_handle_list *file_handles;
-struct file_handle *inline_file;
+/* (headers) */
 
-static struct file_handle *create_file_handle (const char *handle_name,
-                                               const char *filename);
 
 /* (specification)
    "FILE HANDLE" (fh_):
      name=string;
-     recform=recform:fixed/!variable/spanned;
      lrecl=integer;
-     mode=mode:!character/image/binary/multipunch/_360.
+     tabwidth=integer "x>=0" "%s must be nonnegative";
+     mode=mode:!character/image.
 */
 /* (declarations) */
 /* (functions) */
 
-static struct file_handle *
-get_handle_with_name (const char *handle_name) 
-{
-  struct file_handle_list *iter;
-
-  for (iter = file_handles; iter != NULL; iter = iter->next)
-    if (!strcmp (handle_name, iter->handle->private->name))
-      return iter->handle;
-  return NULL;
-}
-
-static struct file_handle *
-get_handle_for_filename (const char *filename)
-{
-  struct file_identity *identity;
-  struct file_handle_list *iter;
-      
-  /* First check for a file with the same identity. */
-  identity = fn_get_identity (filename);
-  if (identity != NULL) 
-    {
-      for (iter = file_handles; iter != NULL; iter = iter->next)
-        if (iter->handle->private->identity != NULL
-            && !fn_compare_file_identities (identity,
-                                         iter->handle->private->identity)) 
-          {
-            fn_free_identity (identity);
-            return iter->handle; 
-          }
-      fn_free_identity (identity);
-    }
-
-  /* Then check for a file with the same name. */
-  for (iter = file_handles; iter != NULL; iter = iter->next)
-    if (!strcmp (filename, iter->handle->private->filename))
-      return iter->handle; 
-
-  return NULL;
-}
 
 int
 cmd_file_handle (void)
 {
-  char handle_name[9];
+  char handle_name[LONG_NAME_LEN + 1];
+  enum file_handle_mode mode = MODE_TEXT;
+  size_t length = 1024;
+  size_t tab_width = 4;
 
   struct cmd_file_handle cmd;
   struct file_handle *handle;
 
   if (!lex_force_id ())
     return CMD_FAILURE;
-  strcpy (handle_name, tokid);
+  str_copy_trunc (handle_name, sizeof handle_name, tokid);
 
   handle = get_handle_with_name (handle_name);
   if (handle != NULL)
     {
-      msg (SE, _("File handle %s already refers to "
-                "file %s.  File handle cannot be redefined within a "
-                 "session."),
-          tokid, handle->private->filename);
+      msg (SE, _("File handle %s already refers to file %s.  "
+                 "File handles cannot be redefined within a session."),
+          handle_name, handle_get_filename(handle));
       return CMD_FAILURE;
     }
 
@@ -148,106 +94,58 @@ cmd_file_handle (void)
       goto lossage;
     }
 
-  handle = create_file_handle (handle_name, cmd.s_name);
   switch (cmd.mode)
     {
     case FH_CHARACTER:
-      handle->private->mode = MODE_TEXT;
+      mode = MODE_TEXT;
+      if (cmd.sbc_tabwidth)
+        tab_width = cmd.n_tabwidth[0];
+      else
+        tab_width = 4;
       break;
     case FH_IMAGE:
-      handle->private->mode = MODE_BINARY;
-      if (cmd.n_lrecl == NOT_LONG)
+      mode = MODE_BINARY;
+      if (cmd.n_lrecl[0] == NOT_LONG)
        {
          msg (SE, _("Fixed-length records were specified on /RECFORM, but "
                      "record length was not specified on /LRECL.  "
                      "Assuming 1024-character records."));
-          handle->private->length = 1024;
+          length = 1024;
        }
-      else if (cmd.n_lrecl < 1)
+      else if (cmd.n_lrecl[0] < 1)
        {
          msg (SE, _("Record length (%ld) must be at least one byte.  "
-                    "1-character records will be assumed."), cmd.n_lrecl);
-          handle->private->length = 1;
+                    "1-character records will be assumed."), cmd.n_lrecl[0]);
+          length = 1;
        }
       else
-        handle->private->length = cmd.n_lrecl;
+        length = cmd.n_lrecl[0];
       break;
     default:
       assert (0);
     }
 
+  handle = create_file_handle (handle_name, cmd.s_name, 
+                              mode, length, tab_width);
+
+  free_file_handle (&cmd);
   return CMD_SUCCESS;
 
  lossage:
   free_file_handle (&cmd);
   return CMD_FAILURE;
 }
-\f
-/* File handle functions. */
-
-/* Creates and returns a new file handle with the given values
-   and defaults for other values.  Adds the created file handle
-   to the global list. */
-static struct file_handle *
-create_file_handle (const char *handle_name, const char *filename)
-{
-  struct file_handle *handle;
-  struct file_handle_list *list;
-
-  /* Create and initialize file handle. */
-  handle = xmalloc (sizeof *handle);
-  handle->private = xmalloc (sizeof *handle->private);
-  handle->private->name = xstrdup (handle_name);
-  handle->private->filename = xstrdup (filename);
-  handle->private->identity = fn_get_identity (filename);
-  handle->private->where.filename = handle->private->filename;
-  handle->private->where.line_number = 0;
-  handle->private->mode = MODE_TEXT;
-  handle->private->length = 1024;
-  handle->ext = NULL;
-  handle->class = NULL;
-
-  /* Add file handle to global list. */
-  list = xmalloc (sizeof *list);
-  list->handle = handle;
-  list->next = file_handles;
-  file_handles = list;
 
-  return handle;
-}
 
-/* Closes the stdio FILE associated with handle H.  Frees internal
-   buffers associated with that file.  Does *not* destroy the file
-   handle H.  (File handles are permanent during a session.)  */
-void
-fh_close_handle (struct file_handle *h)
-{
-  if (h == NULL)
-    return;
 
-  if (h->class != NULL)
-    h->class->close (h);
-  h->class = NULL;
-  h->ext = NULL;
-}
+static struct linked_list *handle_list;
 
-/* Initialize the hash of file handles; inserts the "inline file"
-   inline_file. */
-void
-fh_init_files (void)
-{
-  if (inline_file == NULL) 
-    {
-      inline_file = create_file_handle ("INLINE", _("<Inline File>"));
-      inline_file->private->length = 80; 
-    }
-}
 
 /* Parses a file handle name, which may be a filename as a string or
    a file handle name as an identifier.  Returns the file handle or
    NULL on failure. */
 struct file_handle *
-fh_parse_file_handle (void)
+fh_parse (void)
 {
   struct file_handle *handle;
 
@@ -262,55 +160,41 @@ fh_parse_file_handle (void)
   if (token == T_ID) 
     handle = get_handle_with_name (tokid);
   if (handle == NULL)
-    handle = get_handle_for_filename (ds_value (&tokstr));
+    handle = get_handle_for_filename (ds_c_str (&tokstr));
   if (handle == NULL) 
     {
-      char *filename = ds_value (&tokstr);
+      char *filename = ds_c_str (&tokstr);
       char *handle_name = xmalloc (strlen (filename) + 3);
       sprintf (handle_name, "\"%s\"", filename);
-      handle = create_file_handle (handle_name, filename);
+      handle = create_file_handle_with_defaults (handle_name, filename);
+      ll_push_front(handle_list, handle);
       free (handle_name);
     }
 
   lex_get ();
 
+
   return handle;
 }
 
-/* Returns the identifier of file HANDLE.  If HANDLE was created
-   by referring to a filename instead of a handle name, returns
-   the filename, enclosed in double quotes.  Return value is
-   owned by the file handle. 
 
-   Useful for printing error messages about use of file handles.  */
-const char *
-handle_get_name (const struct file_handle *handle)
-{
-  return handle->private->name;
-}
 
-/* Returns the name of the file associated with HANDLE. */
-const char *
-handle_get_filename (const struct file_handle *handle) 
+void 
+fh_init(void)
 {
-  return handle->private->filename;
+  handle_list = ll_create(destroy_file_handle,0);
 }
 
-/* Returns the mode of HANDLE. */
-enum file_handle_mode
-handle_get_mode (const struct file_handle *handle) 
+void 
+fh_done(void)
 {
-  assert (handle != NULL);
-  return handle->private->mode;
+  if ( handle_list )  
+  {
+    ll_destroy(handle_list);
+    handle_list = 0;
+  }
 }
 
-/* Returns the width of a logical record on HANDLE. */
-size_t
-handle_get_record_width (const struct file_handle *handle)
-{
-  assert (handle != NULL);
-  return handle->private->length;
-}
 
 /*
    Local variables: