#include <data/dictionary.h>
#include <data/procedure.h>
#include <data/settings.h>
+#include <libpspp/getl.h>
#include <language/command.h>
#include <language/lexer/lexer.h>
#include <language/lexer/variable-parser.h>
-#include <language/line-buffer.h>
#include <libpspp/alloc.h>
#include <libpspp/message.h>
-#include <libpspp/message.h>
#include <libpspp/misc.h>
#include <libpspp/pool.h>
#include <libpspp/str.h>
/* A DO REPEAT...END REPEAT block. */
struct repeat_block
{
+ struct getl_interface parent ;
+
struct pool *pool; /* Pool used for storage. */
struct dataset *ds; /* The dataset for this block */
struct line_list *first_line; /* First line in line buffer. */
bool print; /* Print lines as executed? */
};
-static bool parse_specification (struct repeat_block *);
-static bool parse_lines (struct repeat_block *);
+static bool parse_specification (struct lexer *, struct repeat_block *);
+static bool parse_lines (struct lexer *, struct repeat_block *);
static void create_vars (struct repeat_block *);
-static int parse_ids (const struct dictionary *dict, struct repeat_entry *, struct pool *);
-static int parse_numbers (struct repeat_entry *, struct pool *);
-static int parse_strings (struct repeat_entry *, struct pool *);
+static int parse_ids (struct lexer *, const struct dictionary *dict,
+ struct repeat_entry *, struct pool *);
+
+static int parse_numbers (struct lexer *, struct repeat_entry *,
+ struct pool *);
+
+static int parse_strings (struct lexer *, struct repeat_entry *,
+ struct pool *);
+
+static void do_repeat_filter (struct getl_interface *, struct string *);
+static bool do_repeat_read (struct getl_interface *, struct string *);
+static void do_repeat_close (struct getl_interface *);
+static bool always_false (const struct getl_interface *i UNUSED);
-static void do_repeat_filter (struct string *line, void *block);
-static bool do_repeat_read (struct string *line, char **file_name,
- int *line_number, void *block);
-static void do_repeat_close (void *block);
int
-cmd_do_repeat (struct dataset *ds)
+cmd_do_repeat (struct lexer *lexer, struct dataset *ds)
{
struct repeat_block *block;
block = pool_create_container (struct repeat_block, pool);
block->ds = ds;
- if (!parse_specification (block) || !parse_lines (block))
+ if (!parse_specification (lexer, block) || !parse_lines (lexer, block))
goto error;
create_vars (block);
block->cur_line = NULL;
block->loop_idx = -1;
- getl_include_filter (do_repeat_filter, do_repeat_close, block);
- getl_include_function (do_repeat_read, NULL, block);
+
+ block->parent.read = do_repeat_read;
+ block->parent.close = do_repeat_close;
+ block->parent.filter = do_repeat_filter;
+ block->parent.interactive = always_false;
+
+ getl_include_source ( (struct getl_interface *) block);
return CMD_SUCCESS;
/* Parses the whole DO REPEAT command specification.
Returns success. */
static bool
-parse_specification (struct repeat_block *block)
+parse_specification (struct lexer *lexer, struct repeat_block *block)
{
char first_name[LONG_NAME_LEN + 1];
int count;
/* Get a stand-in variable name and make sure it's unique. */
- if (!lex_force_id ())
+ if (!lex_force_id (lexer))
return false;
- if (dict_lookup_var (dict, tokid))
+ if (dict_lookup_var (dict, lex_tokid (lexer)))
msg (SW, _("Dummy variable name \"%s\" hides dictionary "
"variable \"%s\"."),
- tokid, tokid);
+ lex_tokid (lexer), lex_tokid (lexer));
for (iter = block->macros; iter != NULL; iter = iter->next)
- if (!strcasecmp (iter->id, tokid))
+ if (!strcasecmp (iter->id, lex_tokid (lexer)))
{
- msg (SE, _("Dummy variable name \"%s\" is given twice."), tokid);
+ msg (SE, _("Dummy variable name \"%s\" is given twice."),
+ lex_tokid (lexer));
return false;
}
list. */
e = pool_alloc (block->pool, sizeof *e);
e->next = block->macros;
- strcpy (e->id, tokid);
+ strcpy (e->id, lex_tokid (lexer));
block->macros = e;
/* Skip equals sign. */
- lex_get ();
- if (!lex_force_match ('='))
+ lex_get (lexer);
+ if (!lex_force_match (lexer, '='))
return false;
/* Get the details of the variable's possible values. */
- if (token == T_ID)
- count = parse_ids (dict, e, block->pool);
- else if (lex_is_number ())
- count = parse_numbers (e, block->pool);
- else if (token == T_STRING)
- count = parse_strings (e, block->pool);
+ if (lex_token (lexer) == T_ID)
+ count = parse_ids (lexer, dict, e, block->pool);
+ else if (lex_is_number (lexer))
+ count = parse_numbers (lexer, e, block->pool);
+ else if (lex_token (lexer) == T_STRING)
+ count = parse_strings (lexer, e, block->pool);
else
{
- lex_error (NULL);
+ lex_error (lexer, NULL);
return false;
}
if (count == 0)
return false;
- if (token != '/' && token != '.')
+ if (lex_token (lexer) != '/' && lex_token (lexer) != '.')
{
- lex_error (NULL);
+ lex_error (lexer, NULL);
return false;
}
return false;
}
- lex_match ('/');
+ lex_match (lexer, '/');
}
- while (token != '.');
+ while (lex_token (lexer) != '.');
return true;
}
/* Read all the lines we are going to substitute, inside the DO
REPEAT...END REPEAT block. */
static bool
-parse_lines (struct repeat_block *block)
+parse_lines (struct lexer *lexer, struct repeat_block *block)
{
char *previous_file_name;
struct line_list **last_line;
for (;;)
{
- const char *cur_file_name;
- int cur_line_number;
+ const char *cur_file_name = getl_source_name ();
+ int cur_line_number = getl_source_location ();
struct line_list *line;
+ struct string cur_line_copy;
bool dot;
- if (!getl_read_line (NULL))
+ if (! lex_get_line_raw (lexer))
return false;
/* If the current file has changed then record the fact. */
- getl_location (&cur_file_name, &cur_line_number);
- if (previous_file_name == NULL
+ if (cur_file_name &&
+ (previous_file_name == NULL
|| !strcmp (cur_file_name, previous_file_name))
+ )
previous_file_name = pool_strdup (block->pool, cur_file_name);
- ds_rtrim (&getl_buf, ss_cstr (CC_SPACES));
- dot = ds_chomp (&getl_buf, get_endcmd ());
- if (recognize_do_repeat (ds_cstr (&getl_buf)))
+ ds_init_string (&cur_line_copy, lex_entire_line_ds (lexer) );
+ ds_rtrim (&cur_line_copy, ss_cstr (CC_SPACES));
+ dot = ds_chomp (&cur_line_copy, get_endcmd ());
+
+ if (recognize_do_repeat (ds_cstr (&cur_line_copy)))
nesting_level++;
- else if (recognize_end_repeat (ds_cstr (&getl_buf), &block->print))
+ else if (recognize_end_repeat (ds_cstr (&cur_line_copy), &block->print))
{
if (nesting_level-- == 0)
{
- lex_discard_line ();
+ lex_discard_line (lexer);
+ ds_destroy (&cur_line_copy);
return true;
}
}
if (dot)
- ds_put_char (&getl_buf, get_endcmd ());
+ ds_put_char (&cur_line_copy, get_endcmd ());
line = *last_line = pool_alloc (block->pool, sizeof *line);
line->next = NULL;
line->file_name = previous_file_name;
line->line_number = cur_line_number;
- line->line = pool_strdup (block->pool, ds_cstr (&getl_buf));
+ line->line = pool_strdup (block->pool, ds_cstr (&cur_line_copy) );
last_line = &line->next;
+
+ ds_destroy (&cur_line_copy);
}
- lex_discard_line ();
+ lex_discard_line (lexer);
return true;
}
/* Parses a set of ids for DO REPEAT. */
static int
-parse_ids (const struct dictionary *dict, struct repeat_entry *e, struct pool *pool)
+parse_ids (struct lexer *lexer, const struct dictionary *dict,
+ struct repeat_entry *e, struct pool *pool)
{
size_t n = 0;
e->type = VAR_NAMES;
- return parse_mixed_vars_pool (dict, pool, &e->replacement, &n, PV_NONE) ? n : 0;
+ return parse_mixed_vars_pool (lexer, dict, pool,
+ &e->replacement, &n, PV_NONE) ? n : 0;
}
/* Adds STRING to E's list of replacements, which has *USED
/* Parses a list of numbers for DO REPEAT. */
static int
-parse_numbers (struct repeat_entry *e, struct pool *pool)
+parse_numbers (struct lexer *lexer, struct repeat_entry *e, struct pool *pool)
{
size_t used = 0;
size_t allocated = 0;
long a, b, i;
/* Parse A TO B into a, b. */
- if (!lex_force_int ())
+ if (!lex_force_int (lexer))
return 0;
- a = lex_integer ();
+ a = lex_integer (lexer);
- lex_get ();
- if (token == T_TO)
+ lex_get (lexer);
+ if (lex_token (lexer) == T_TO)
{
- lex_get ();
- if (!lex_force_int ())
+ lex_get (lexer);
+ if (!lex_force_int (lexer))
return 0;
- b = lex_integer ();
+ b = lex_integer (lexer);
if (b < a)
{
msg (SE, _("%ld TO %ld is an invalid range."), a, b);
return 0;
}
- lex_get ();
+ lex_get (lexer);
}
else
b = a;
e, pool, &used, &allocated);
- lex_match (',');
+ lex_match (lexer, ',');
}
- while (token != '/' && token != '.');
+ while (lex_token (lexer) != '/' && lex_token (lexer) != '.');
return used;
}
/* Parses a list of strings for DO REPEAT. */
int
-parse_strings (struct repeat_entry *e, struct pool *pool)
+parse_strings (struct lexer *lexer, struct repeat_entry *e, struct pool *pool)
{
size_t used = 0;
size_t allocated = 0;
{
char *string;
- if (token != T_STRING)
+ if (lex_token (lexer) != T_STRING)
{
msg (SE, _("String expected."));
return 0;
}
- string = lex_token_representation ();
+ string = lex_token_representation (lexer);
pool_register (pool, free, string);
add_replacement (string, e, pool, &used, &allocated);
- lex_get ();
- lex_match (',');
+ lex_get (lexer);
+ lex_match (lexer, ',');
}
- while (token != '/' && token != '.');
+ while (lex_token (lexer) != '/' && lex_token (lexer) != '.');
return used;
}
\f
int
-cmd_end_repeat (struct dataset *ds UNUSED)
+cmd_end_repeat (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
{
msg (SE, _("No matching DO REPEAT."));
return CMD_CASCADING_FAILURE;
return NULL;
}
-/* Makes appropriate DO REPEAT macro substitutions within getl_buf. */
+/* Makes appropriate DO REPEAT macro substitutions within the
+ repeated lines. */
static void
-do_repeat_filter (struct string *line, void *block_)
+do_repeat_filter (struct getl_interface *block_, struct string *line)
{
- struct repeat_block *block = block_;
+ struct repeat_block *block = (struct repeat_block *) block_;
bool in_apos, in_quote;
char *cp;
struct string output;
Puts the line in OUTPUT, sets the file name in *FILE_NAME and
line number in *LINE_NUMBER. Returns true if a line was
obtained, false if the source is exhausted. */
-static bool
-do_repeat_read (struct string *output, char **file_name, int *line_number,
- void *block_)
+static bool
+do_repeat_read (struct getl_interface *b, struct string *output)
{
- struct repeat_block *block = block_;
+ struct repeat_block *block = (struct repeat_block *) b;
struct line_list *line;
if (block->cur_line == NULL)
line = block->cur_line;
ds_assign_cstr (output, line->line);
- *file_name = line->file_name;
- *line_number = -line->line_number;
block->cur_line = line->next;
return true;
}
/* Frees a DO REPEAT block.
Called by getl to close out the DO REPEAT block. */
static void
-do_repeat_close (void *block_)
+do_repeat_close (struct getl_interface *block_)
{
- struct repeat_block *block = block_;
+ struct repeat_block *block = (struct repeat_block *) block_;
pool_destroy (block->pool);
}
+
+
+static bool
+always_false (const struct getl_interface *i UNUSED)
+{
+ return false;
+}