!quote, !unquote
[pspp] / src / language / control / define.c
index 3f23ec0b104f18ea02e401bb57f270357e11d0cd..686685fc9cb313c5e7b4456eedd021ccbcab050b 100644 (file)
@@ -63,11 +63,12 @@ parse_quoted_token (struct lexer *lexer, struct token *token)
   if (!string_lexer_next (&slex, token)
       || string_lexer_next (&slex, &another_token))
     {
-      token_destroy (token);
-      token_destroy (&another_token);
+      token_uninit (token);
+      token_uninit (&another_token);
       lex_error (lexer, _("String must contain exactly one token."));
       return false;
     }
+  lex_get (lexer);
   return true;
 }
 
@@ -86,36 +87,40 @@ cmd_define (struct lexer *lexer, struct dataset *ds UNUSED)
     goto error;
 
   size_t allocated_params = 0;
-  size_t n_keywords = 0;
   while (!lex_match (lexer, T_RPAREN))
     {
       if (m->n_params >= allocated_params)
         m->params = x2nrealloc (m->params, &allocated_params,
                                 sizeof *m->params);
 
-      struct macro_param *p = &m->params[m->n_params++];
+      size_t param_index = m->n_params++;
+      struct macro_param *p = &m->params[param_index];
       *p = (struct macro_param) { .expand_arg = true };
 
       /* Parse parameter name. */
       if (match_macro_id (lexer, "!POSITIONAL"))
         {
-          if (n_keywords)
+          if (param_index > 0 && !m->params[param_index - 1].positional)
             {
               lex_error (lexer, _("Positional parameters must precede "
                                   "keyword parameters."));
               goto error;
             }
-          p->name = NULL;
+
+          p->positional = true;
+          p->name = xasprintf ("!%zu", param_index + 1);
         }
       else
         {
-          n_keywords++;
-
-          if (!lex_force_id (lexer) || !lex_force_match (lexer, T_EQUALS))
+          if (!lex_force_id (lexer))
             goto error;
 
-          p->name = ss_xstrdup (lex_tokss (lexer));
+          p->positional = false;
+          p->name = xasprintf ("!%s", lex_tokcstr (lexer));
           lex_get (lexer);
+
+          if (!lex_force_match (lexer, T_EQUALS))
+            goto error;
         }
 
       /* Parse default value. */
@@ -132,7 +137,11 @@ cmd_define (struct lexer *lexer, struct dataset *ds UNUSED)
                   lex_error_expecting (lexer, ")");
                   goto error;
                 }
-              tokens_add (&p->def, lex_next (lexer, 0));
+              const struct macro_token mt = {
+                .token = *lex_next (lexer, 0),
+                .representation = lex_next_representation (lexer, 0, 0),
+              };
+              macro_tokens_add (&p->def, &mt);
               lex_get (lexer);
             }
         }
@@ -200,7 +209,11 @@ cmd_define (struct lexer *lexer, struct dataset *ds UNUSED)
       ds_put_byte (&body, '\n');
       lex_get (lexer);
     }
-  m->body = ds_ss (&body);
+
+  macro_tokens_from_string (&m->body, body.ss, lex_get_syntax_mode (lexer));
+  ds_destroy (&body);
+
+  lex_define_macro (lexer, m);
 
   return CMD_SUCCESS;