Yuri Chornoivan contributed some typo fixes
[pspp] / src / data / session.c
index 24c22b24ed3001285b84cb9427f76fbb93eb4e48..90922f3b244e455b6b88b401b5bcf42ad549b8b4 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
 
    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
@@ -25,6 +25,7 @@
 #include "libpspp/assertion.h"
 #include "libpspp/cast.h"
 #include "libpspp/hash-functions.h"
+#include "libpspp/i18n.h"
 #include "libpspp/str.h"
 #include "libpspp/hmapx.h"
 
 
 struct session
   {
+    struct session *parent;
     struct hmapx datasets;
     struct dataset *active;
     char *syntax_encoding;      /* Default encoding for syntax files. */
+    unsigned int n_dataset_names; /* For session_generate_dataset_name(). */
   };
 
 static struct hmapx_node *session_lookup_dataset__ (const struct session *,
                                                     const char *name);
 
 struct session *
-session_create (void)
+session_create (struct session *parent)
 {
   struct session *s;
 
   s = xmalloc (sizeof *s);
+  s->parent = parent;
   hmapx_init (&s->datasets);
   s->active = NULL;
-  s->syntax_encoding = xstrdup ("Auto");
+  s->syntax_encoding = xstrdup (s->parent != NULL
+                                ? s->parent->syntax_encoding : "Auto");
+  s->n_dataset_names = 0;
   return s;
 }
 
@@ -63,6 +69,7 @@ session_destroy (struct session *s)
       s->active = NULL;
       HMAPX_FOR_EACH_SAFE (ds, node, next, &s->datasets)
         dataset_destroy (ds);
+      hmapx_destroy (&s->datasets);
       free (s->syntax_encoding);
       free (s);
     }
@@ -90,9 +97,13 @@ session_add_dataset (struct session *s, struct dataset *ds)
   if (old == s->active)
     s->active = ds;
   if (old != NULL)
-    session_remove_dataset (s, old);
+    {
+      session_remove_dataset (s, old);
+      dataset_destroy (old);
+    }
 
-  hmapx_insert (&s->datasets, ds, hash_case_string (dataset_name (ds), 0));
+  hmapx_insert (&s->datasets, ds,
+                utf8_hash_case_string (dataset_name (ds), 0));
   if (s->active == NULL)
     s->active = ds;
 
@@ -111,7 +122,9 @@ struct dataset *
 session_lookup_dataset (const struct session *s, const char *name)
 {
   struct hmapx_node *node = session_lookup_dataset__ (s, name);
-  return node != NULL ? node->data : NULL;
+  return (node != NULL ? node->data
+          : s->parent != NULL ? session_lookup_dataset (s->parent, name)
+          : NULL);
 }
 
 struct dataset *
@@ -164,6 +177,25 @@ session_get_dataset_by_seqno (const struct session *s, unsigned int seqno)
       return ds;
   return NULL;
 }
+
+/* Returns an identifier that is not currently in use as a dataset name.
+   The caller must free the returned identifier, with free(). */
+char *
+session_generate_dataset_name (struct session *s)
+{
+  for (;;)
+    {
+      char *name;
+
+      s->n_dataset_names++;
+      assert(s->n_dataset_names != 0);
+
+      name = xasprintf ("DataSet%u", s->n_dataset_names);
+      if (!session_lookup_dataset (s, name))
+        return name;
+      free (name);
+    }
+}
 \f
 static struct hmapx_node *
 session_lookup_dataset__ (const struct session *s_, const char *name)
@@ -172,8 +204,9 @@ session_lookup_dataset__ (const struct session *s_, const char *name)
   struct hmapx_node *node;
   struct dataset *ds;
 
-  HMAPX_FOR_EACH_WITH_HASH (ds, node, hash_case_string (name, 0), &s->datasets)
-    if (!strcasecmp (dataset_name (ds), name))
+  HMAPX_FOR_EACH_WITH_HASH (ds, node, utf8_hash_case_string (name, 0),
+                            &s->datasets)
+    if (!utf8_strcasecmp (dataset_name (ds), name))
       return node;
 
   return NULL;