message: Make msg_emit() take full ownership of its argument.
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 3 Jul 2021 18:46:17 +0000 (11:46 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 3 Jul 2021 18:46:17 +0000 (11:46 -0700)
The way it treated the argument before was just confusing.

src/data/pc+-file-reader.c
src/data/por-file-reader.c
src/data/sys-file-reader.c
src/language/control/define.c
src/language/data-io/data-parser.c
src/language/lexer/lexer.c
src/language/lexer/macro.c
src/language/lexer/macro.h
src/libpspp/message.c

index c7c9e3b7f8b062b75d3e57c0ed5be2a262e34fe5..8b945788a5b8921ee7bcf10dbdb5d69a53eb5f1e 100644 (file)
@@ -1159,12 +1159,13 @@ pcp_msg (struct pcp_reader *r, off_t offset,
     ds_put_format (&text, _("`%s': "), fh_get_file_name (r->fh));
   ds_put_vformat (&text, format, args);
 
-  struct msg m = {
+  struct msg *m = xmalloc (sizeof *m);
+  *m = (struct msg) {
     .category = msg_class_to_category (class),
     .severity = msg_class_to_severity (class),
-    .text = ds_cstr (&text),
+    .text = ds_steal_cstr (&text),
   };
-  msg_emit (&m);
+  msg_emit (m);
 }
 
 /* Displays a warning for offset OFFSET in the file. */
index 343615a826fcecb70f6e013b101b4cba1c6f36b1..8d008b1dd610a30574be726f7edc74ff54c80b39 100644 (file)
@@ -112,12 +112,13 @@ error (struct pfm_reader *r, const char *msg, ...)
   ds_put_vformat (&text, msg, args);
   va_end (args);
 
-  struct msg m = {
+  struct msg *m = xmalloc (sizeof *m);
+  *m = (struct msg) {
     .category = MSG_C_GENERAL,
     .severity = MSG_S_ERROR,
-    .text = ds_cstr (&text),
+    .text = ds_steal_cstr (&text),
   };
-  msg_emit (&m);
+  msg_emit (m);
 
   r->ok = false;
 
@@ -139,12 +140,13 @@ warning (struct pfm_reader *r, const char *msg, ...)
   ds_put_vformat (&text, msg, args);
   va_end (args);
 
-  struct msg m = {
+  struct msg *m = xmalloc (sizeof *m);
+  *m = (struct msg) {
     .category = MSG_C_GENERAL,
     .severity = MSG_S_WARNING,
-    .text = ds_cstr (&text),
+    .text = ds_steal_cstr (&text),
   };
-  msg_emit (&m);
+  msg_emit (m);
 }
 
 /* Close and destroy R.
index bc5ff9eeb2519fbe811ed720790ba5525ede26fb..f11480ac8f76c6bc2a3c72ac6a33519bbe971e48 100644 (file)
@@ -3244,12 +3244,13 @@ sys_msg (struct sfm_reader *r, off_t offset,
     ds_put_format (&text, _("`%s': "), fh_get_file_name (r->fh));
   ds_put_vformat (&text, format, args);
 
-  struct msg m = {
+  struct msg *m = xmalloc (sizeof *m);
+  *m = (struct msg) {
     .category = msg_class_to_category (class),
     .severity = msg_class_to_severity (class),
-    .text = ds_cstr (&text),
+    .text = ds_steal_cstr (&text),
   };
-  msg_emit (&m);
+  msg_emit (m);
 }
 
 /* Displays a warning for offset OFFSET in the file. */
index e8155e9214d6c77639eb4b80ac6a2e35a02d7194..0c227233c4609da591363f0b216021edebc2c2af 100644 (file)
@@ -81,7 +81,11 @@ cmd_define (struct lexer *lexer, struct dataset *ds UNUSED)
 
   /* Parse macro name. */
   struct macro *m = xmalloc (sizeof *m);
-  *m = (struct macro) { .name = ss_xstrdup (lex_tokss (lexer)) };
+  *m = (struct macro) {
+    .name = ss_xstrdup (lex_tokss (lexer)),
+    .file_name = xstrdup_if_nonnull (lex_get_file_name (lexer)),
+    .first_line = lex_get_first_line_number (lexer, 0),
+  };
   lex_get (lexer);
 
   if (!lex_force_match (lexer, T_LPAREN))
@@ -227,6 +231,7 @@ cmd_define (struct lexer *lexer, struct dataset *ds UNUSED)
       ds_put_byte (&body, '\n');
       lex_get (lexer);
     }
+  m->last_line = lex_get_last_line_number (lexer, 0);
 
   macro_tokens_from_string (&m->body, body.ss, lex_get_syntax_mode (lexer));
   ds_destroy (&body);
index 6de88b170de8400fdd37215dedc4d736bcc17754..03c6dbbb0ea36a421a956498f2fb4470c14771a3 100644 (file)
@@ -496,21 +496,23 @@ parse_error (const struct dfm_reader *reader, const struct field *field,
              int first_column, int last_column, char *error)
 {
   int line_number = dfm_get_line_number (reader);
-  const struct msg_location location = {
-    .file_name = CONST_CAST (char *, dfm_get_file_name (reader)),
+  struct msg_location *location = xmalloc (sizeof *location);
+  *location = (struct msg_location) {
+    .file_name = xstrdup (dfm_get_file_name (reader)),
     .first_line = line_number,
     .last_line = line_number + 1,
     .first_column = first_column,
     .last_column = last_column,
   };
-  struct msg m = {
+  struct msg *m = xmalloc (sizeof *m);
+  *m = (struct msg) {
     .category = MSG_C_DATA,
     .severity = MSG_S_WARNING,
-    .location = CONST_CAST (struct msg_location *, &location),
+    .location = location,
     .text = xasprintf (_("Data for variable %s is not valid as format %s: %s"),
                        field->name, fmt_name (field->format.type), error),
   };
-  msg_emit (&m);
+  msg_emit (m);
 
   free (error);
 }
index 9b55a4edbf7247b5c0f8300d5527c1be8760adb3..67ecfee07d00bb235cfbb38654075966168795f7 100644 (file)
@@ -1588,20 +1588,22 @@ lex_source_error_valist (struct lex_source *src, int n0, int n1,
   if (ds_last (&s) != '.')
     ds_put_byte (&s, '.');
 
-  struct msg_location location = {
-    .file_name = src->reader->file_name,
+  struct msg_location *location = xmalloc (sizeof *location);
+  *location = (struct msg_location) {
+    .file_name = xstrdup_if_nonnull (src->reader->file_name),
     .first_line = lex_source_get_first_line_number (src, n0),
     .last_line = lex_source_get_last_line_number (src, n1),
     .first_column = lex_source_get_first_column (src, n0),
     .last_column = lex_source_get_last_column (src, n1),
   };
-  struct msg m = {
+  struct msg *m = xmalloc (sizeof *m);
+  *m = (struct msg) {
     .category = MSG_C_SYNTAX,
     .severity = MSG_S_ERROR,
-    .location = &location,
+    .location = location,
     .text = ds_steal_cstr (&s),
   };
-  msg_emit (&m);
+  msg_emit (m);
 }
 
 static void PRINTF_FORMAT (2, 3)
index 5f68de3fdd289b22a052d5e97f51f66894bdec0a..ad6a2be20edf99372a3439d720816e41c7f8335f 100644 (file)
@@ -328,6 +328,7 @@ macro_destroy (struct macro *m)
     return;
 
   free (m->name);
+  free (m->file_name);
   for (size_t i = 0; i < m->n_params; i++)
     {
       struct macro_param *p = &m->params[i];
@@ -427,6 +428,9 @@ struct macro_expansion_stack
   {
     const struct macro_expansion_stack *next;
     const char *name;
+    const char *file_name;
+    int first_line;
+    int last_line;
   };
 
 
@@ -1539,16 +1543,45 @@ macro_error (const struct macro_expansion_stack *stack,
   char *s = xvasprintf (format, args);
   va_end (args);
 
-  /* foo.sps:12: While expanding macro 'innermost',
+  /* foo.sps:12: While expanding 'innermost',
      foo.sps:23: inside expansion of 'next_inner',
      foo.sps:34: inside expansion of 'next_inner2',
      foo.sps:45: inside expansion of 'outermost':
      error. */
   struct string header = DS_EMPTY_INITIALIZER;
-  ds_put_format (&header, "While expanding \"%s\"", stack->name);
+  if (stack->file_name || stack->first_line)
+    {
+      if (stack->file_name)
+        ds_put_format (&header, "%s:", stack->file_name);
+      if (stack->first_line)
+        {
+          if (stack->last_line > stack->first_line)
+            ds_put_format (&header, "%d-%d:",
+                           stack->first_line, stack->last_line);
+          else
+            ds_put_format (&header, "%d", stack->first_line);
+        }
+      ds_put_byte (&header, ' ');
+    }
+  ds_put_format (&header, "While expanding \"%s\"\n", stack->name);
   while ((stack = stack->next) != NULL)
-    ds_put_format (&header, ", inside expansion of \"%s\"", stack->name);
-
+    {
+      if (stack->file_name || stack->first_line)
+        {
+          if (stack->file_name)
+            ds_put_format (&header, "%s:", stack->file_name);
+          if (stack->first_line)
+            {
+              if (stack->last_line > stack->first_line)
+                ds_put_format (&header, "%d-%d:",
+                               stack->first_line, stack->last_line);
+              else
+                ds_put_format (&header, "%d", stack->first_line);
+            }
+          ds_put_byte (&header, ' ');
+        }
+    ds_put_format (&header, ", inside expansion of \"%s\"\n", stack->name);
+    }
   msg (SE, "%s: %s", ds_cstr (&header), s);
 
   ds_destroy (&header);
@@ -1885,6 +1918,9 @@ macro_expand (const struct macro_tokens *mts,
                             subme, NULL,
                             &(struct macro_expansion_stack) {
                               .name = subme->macro->name,
+                              .file_name = subme->macro->file_name,
+                              .first_line = subme->macro->first_line,
+                              .last_line = subme->macro->last_line,
                               .next = stack,
                             }, expand, break_, exp);
               macro_expander_destroy (subme);
@@ -1967,7 +2003,12 @@ void
 macro_expander_get_expansion (struct macro_expander *me, struct macro_tokens *exp)
 {
   bool expand = true;
-  struct macro_expansion_stack stack = { .name = me->macro->name };
+  struct macro_expansion_stack stack = {
+    .name = me->macro->name,
+    .file_name = me->macro->file_name,
+    .first_line = me->macro->first_line,
+    .last_line = me->macro->last_line,
+  };
   macro_expand (&me->macro->body, settings_get_mnest (),
                 me->macros, me, NULL, &stack, &expand, NULL, exp);
 }
index c10ce8e3cd2cdc4f40260698e41eed65e8c348e9..529eed05fd4a056d378dab8d6084b54ccc37d6ca 100644 (file)
@@ -88,6 +88,11 @@ struct macro
     struct hmap_node hmap_node; /* Indexed by 'name'. */
     char *name;
 
+    /* Source code location of macro definition. */
+    char *file_name;
+    int first_line;
+    int last_line;
+
     struct macro_param *params;
     size_t n_params;
 
index 7d4f9d8430a9ffdd8c008563586aaa6189fbdc50..bbba1c5506e9cdb1dad009d4eeedce06401e7f24 100644 (file)
@@ -53,13 +53,13 @@ static int messages_disabled;
 void
 vmsg (enum msg_class class, const char *format, va_list args)
 {
-  struct msg m = {
+  struct msg *m = xmalloc (sizeof *m);
+  *m = (struct msg) {
     .category = msg_class_to_category (class),
     .severity = msg_class_to_severity (class),
     .text = xvasprintf (format, args),
   };
-
-  msg_emit (&m);
+  msg_emit (m);
 }
 
 /* Writes error message in CLASS, with text FORMAT, formatted with
@@ -80,17 +80,18 @@ msg_error (int errnum, const char *format, ...)
 {
   va_list args;
   va_start (args, format);
-  char *e = xvasprintf (format, args);
+  struct string s = DS_EMPTY_INITIALIZER;
+  ds_put_vformat (&s, format, args);
   va_end (args);
+  ds_put_format (&s, ": %s", strerror (errnum));
 
-  struct msg m = {
+  struct msg *m = xmalloc (sizeof *m);
+  *m = (struct msg) {
     .category = MSG_C_GENERAL,
     .severity = MSG_S_ERROR,
-    .text = xasprintf (_("%s: %s"), e, strerror (errnum)),
+    .text = ds_steal_cstr (&s),
   };
-  msg_emit (&m);
-
-  free (e);
+  msg_emit (m);
 }
 
 
@@ -315,10 +316,10 @@ msg_ui_any_errors (void)
 
 
 static void
-ship_message (struct msg *m)
+ship_message (const struct msg *m)
 {
   enum { MAX_STACK = 4 };
-  static struct msg *stack[MAX_STACK];
+  static const struct msg *stack[MAX_STACK];
   static size_t n;
 
   /* If we're recursing on a given message, or recursing deeply, drop it. */
@@ -349,8 +350,6 @@ submit_note (char *s)
   free (s);
 }
 
-
-
 static void
 process_msg (struct msg *m)
 {
@@ -391,16 +390,13 @@ process_msg (struct msg *m)
 }
 
 
-/* Emits M as an error message.
-   Frees allocated data in M. */
+/* Emits M as an error message.  Takes ownership of M. */
 void
 msg_emit (struct msg *m)
 {
   if (!messages_disabled)
-     process_msg (m);
-
-  free (m->text);
-  free (m->command_name);
+    process_msg (m);
+  msg_destroy (m);
 }
 
 /* Disables message output until the next call to msg_enable.  If