#include "language/lexer/macro.h"
 #include "language/lexer/scan.h"
 #include "language/lexer/token.h"
+#include "libpspp/intern.h"
 #include "libpspp/message.h"
 
 #include "gl/xalloc.h"
     .location = xmalloc (sizeof *m->location),
   };
   *m->location = (struct msg_location) {
-    .file_name = xstrdup_if_nonnull (lex_get_file_name (lexer)),
+    .file_name = intern_new_if_nonnull (lex_get_file_name (lexer)),
     .first_line = lex_get_first_line_number (lexer, 0),
   };
   lex_get (lexer);
 
 #include "data/file-handle-def.h"
 #include "data/settings.h"
 #include "language/data-io/data-reader.h"
+#include "libpspp/intern.h"
 #include "libpspp/message.h"
 #include "libpspp/str.h"
 #include "output/pivot-table.h"
   int line_number = dfm_get_line_number (reader);
   struct msg_location *location = xmalloc (sizeof *location);
   *location = (struct msg_location) {
-    .file_name = xstrdup (dfm_get_file_name (reader)),
+    .file_name = intern_new (dfm_get_file_name (reader)),
     .first_line = line_number,
     .last_line = line_number + 1,
     .first_column = first_column,
 
 #include "language/lexer/variable-parser.h"
 #include "libpspp/assertion.h"
 #include "libpspp/i18n.h"
+#include "libpspp/intern.h"
 #include "libpspp/message.h"
 #include "libpspp/str.h"
 
   int line_number = dfm_get_line_number (reader);
   struct msg_location *location = xmalloc (sizeof *location);
   *location = (struct msg_location) {
-    .file_name = xstrdup (dfm_get_file_name (reader)),
+    .file_name = intern_new (dfm_get_file_name (reader)),
     .first_line = line_number,
     .last_line = line_number + 1,
     .first_column = first_column,
 
 #include "libpspp/cast.h"
 #include "libpspp/deque.h"
 #include "libpspp/i18n.h"
+#include "libpspp/intern.h"
 #include "libpspp/ll.h"
 #include "libpspp/message.h"
 #include "libpspp/misc.h"
                     const struct lex_token *t1)
 {
   return (struct msg_location) {
-    .file_name = src->reader->file_name,
+    .file_name = intern_new_if_nonnull (src->reader->file_name),
     .first_line = t0->first_line,
     .last_line = lex_token_get_last_line_number (src, t1),
     .first_column = lex_token_get_first_column (src, t0),
 {
   struct msg_location *loc = xmalloc (sizeof *loc);
   *loc = (struct msg_location) {
-    .file_name = xstrdup_if_nonnull (lex_get_file_name (lexer)),
+    .file_name = intern_new_if_nonnull (lex_get_file_name (lexer)),
     .first_line = lex_get_first_line_number (lexer, n0),
     .last_line = lex_get_last_line_number (lexer, n1),
   };
 
   return is->string;
 }
 
+const char *
+intern_new_if_nonnull (const char *s)
+{
+  return s ? intern_new (s) : NULL;
+}
+
+
 static struct interned_string *
 interned_string_from_string (const char *s_)
 {
   return s;
 }
 
+const char *
+intern_ref_if_nonnull (const char *s)
+{
+  return s ? intern_ref (s) : NULL;
+}
+
 /* Decreases the reference count on S, which must be an interned string
    returned by intern_new().  If the reference count reaches 0, frees the
    interned string. */
 void
 intern_unref (const char *s)
 {
-  struct interned_string *is = interned_string_from_string (s);
-  if (--is->ref_cnt == 0)
+  if (s)
     {
-      hmap_delete (&interns, &is->node);
-      free (is);
+      struct interned_string *is = interned_string_from_string (s);
+      if (--is->ref_cnt == 0)
+        {
+          hmap_delete (&interns, &is->node);
+          free (is);
+        }
     }
 }
 
 
 #include <stddef.h>
 
 const char *intern_new (const char *);
+const char *intern_new_if_nonnull (const char *);
 const char *intern_ref (const char *);
+const char *intern_ref_if_nonnull (const char *);
 void intern_unref (const char *);
 
 size_t intern_strlen (const char *);
 
 #include <unistd.h>
 
 #include "libpspp/cast.h"
+#include "libpspp/intern.h"
 #include "libpspp/str.h"
 #include "libpspp/version.h"
 #include "data/settings.h"
 void
 msg_location_uninit (struct msg_location *loc)
 {
-  free (loc->file_name);
+  intern_unref (loc->file_name);
 }
 
 void
 
   struct msg_location *dst = xmalloc (sizeof *dst);
   *dst = (struct msg_location) {
-    .file_name = xstrdup_if_nonnull (src->file_name),
+    .file_name = intern_new_if_nonnull (src->file_name),
     .first_line = src->first_line,
     .last_line = src->last_line,
     .first_column = src->first_column,
 
 
 struct msg_location
   {
-    char *file_name;            /* Name of file containing error, or NULL. */
+    const char *file_name;      /* Interned file name, or NULL. */
     int first_line;             /* 1-based line number, or 0 if none. */
     int last_line;              /* 1-based exclusive last line (0=none). */
     int first_column;           /* 1-based first column, or 0 if none. */