-\f
-/* Finds a DO REPEAT macro with the given NAME and returns the
- appropriate substitution if found, or NAME otherwise. */
-static struct substring
-find_substitution (struct repeat_block *block, struct substring name)
-{
- struct repeat_macro *macro = find_macro (block, name);
- return macro ? macro->replacements[block->loop_idx] : name;
-}
-
-/* Makes appropriate DO REPEAT macro substitutions within the
- repeated lines. */
-static void
-do_repeat_filter (struct getl_interface *interface, struct string *line)
-{
- struct repeat_block *block
- = UP_CAST (interface, struct repeat_block, parent);
- bool in_apos, in_quote, dot;
- struct substring input;
- struct string output;
- int c;
-
- ds_init_empty (&output);
-
- /* Strip trailing whitespace, check for & remove terminal dot. */
- ds_rtrim (line, ss_cstr (CC_SPACES));
- dot = ds_chomp (line, '.');
- input = ds_ss (line);
- in_apos = in_quote = false;
- while ((c = ss_first (input)) != EOF)
- {
- if (c == '\'' && !in_quote)
- in_apos = !in_apos;
- else if (c == '"' && !in_apos)
- in_quote = !in_quote;
-
- if (in_quote || in_apos || !lex_is_id1 (c))
- {
- ds_put_byte (&output, c);
- ss_advance (&input, 1);
- }
- else
- {
- struct substring id;
- ss_get_bytes (&input, lex_id_get_length (input), &id);
- ds_put_substring (&output, find_substitution (block, id));
- }
- }
- if (dot)
- ds_put_byte (&output, '.');
-
- ds_swap (line, &output);
- ds_destroy (&output);
-}
-
-static struct repeat_line *
-current_line (const struct getl_interface *interface)
-{
- struct repeat_block *block
- = UP_CAST (interface, struct repeat_block, parent);
- return (block->cur_line != ll_null (&block->lines)
- ? ll_data (block->cur_line, struct repeat_line, ll)
- : NULL);
-}
-
-/* Function called by getl to read a line. Puts the line in
- OUTPUT and its syntax mode in *SYNTAX. Returns true if a line
- was obtained, false if the source is exhausted. */
-static bool
-do_repeat_read (struct getl_interface *interface,
- struct string *output)
-{
- struct repeat_block *block
- = UP_CAST (interface, struct repeat_block, parent);
- struct repeat_line *line;
-
- block->cur_line = ll_next (block->cur_line);
- if (block->cur_line == ll_null (&block->lines))
- {
- block->loop_idx++;
- if (block->loop_idx >= block->loop_cnt)
- return false;
-
- block->cur_line = ll_head (&block->lines);
- }
-
- line = current_line (interface);
- ds_assign_substring (output, line->text);
- return true;
-}
-
-/* Frees a DO REPEAT block.
- Called by getl to close out the DO REPEAT block. */
-static void
-do_repeat_close (struct getl_interface *interface)
-{
- struct repeat_block *block
- = UP_CAST (interface, struct repeat_block, parent);
- pool_destroy (block->pool);
-}
-
-
-static bool
-always_false (const struct getl_interface *i UNUSED)
-{
- return false;
-}
-
-/* Returns the name of the source file from which the previous
- line was originally obtained, or a null pointer if none. */
-static const char *
-do_repeat_name (const struct getl_interface *interface)
-{
- struct repeat_line *line = current_line (interface);
- return line ? line->file_name : NULL;
-}
-
-/* Returns the line number in the source file from which the
- previous line was originally obtained, or 0 if none. */
-static int
-do_repeat_location (const struct getl_interface *interface)
-{
- struct repeat_line *line = current_line (interface);
- return line ? line->line_number : 0;
-}