message: Make msg_emit() take full ownership of its argument.
[pspp] / src / language / lexer / macro.c
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);
 }