[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
branch master updated: linemacro implementation for the XS Parser
From: |
Patrice Dumas |
Subject: |
branch master updated: linemacro implementation for the XS Parser |
Date: |
Sun, 26 Mar 2023 19:26:09 -0400 |
This is an automated email from the git hooks/post-receive script.
pertusus pushed a commit to branch master
in repository texinfo.
The following commit(s) were added to refs/heads/master by this push:
new 81f4e13d33 linemacro implementation for the XS Parser
81f4e13d33 is described below
commit 81f4e13d33abeb15a50d0ba98031025f54cb0bdd
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Mon Mar 27 01:26:00 2023 +0200
linemacro implementation for the XS Parser
* tp/Texinfo/XS/parsetexi/api.c (linemacro_expansion),
tp/Texinfo/XS/parsetexi/context_stack.h (no_paragraph_context),
tp/Texinfo/XS/parsetexi/def.c (parse_def),
tp/Texinfo/XS/parsetexi/element_types.txt,
tp/Texinfo/XS/parsetexi/end_line.c (end_line_def_line)
(end_line_misc_line, end_line),
tp/Texinfo/XS/parsetexi/handle_commands.c (handle_block_command),
tp/Texinfo/XS/parsetexi/macro.c (handle_macro),
tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line)
(parse_texi), tp/Texinfo/XS/parsetexi/separator.c (handle_open_brace),
tp/Texinfo/XS/parsetexi/source_marks.c (register_source_mark)
(source_marks_reset_counters): handle @linemacro and linemacro defined
command calls using the same design as for perl Parser.
* tp/Texinfo/ParserNonXS.pm (%no_paragraph_contexts): set
ct_linecommand to be no paragraph context.
* tp/Texinfo/ParserNonXS.pm (_process_remaining_on_line):
change code opening arguments_container line_arg for linemacro command
call to be more like XS parser.
---
ChangeLog | 25 +++++
tp/Texinfo/ParserNonXS.pm | 12 +-
tp/Texinfo/XS/parsetexi/api.c | 1 +
tp/Texinfo/XS/parsetexi/context_stack.h | 6 +-
tp/Texinfo/XS/parsetexi/def.c | 141 +++++++++++++++++++-----
tp/Texinfo/XS/parsetexi/element_types.c | 1 +
tp/Texinfo/XS/parsetexi/element_types.h | 1 +
tp/Texinfo/XS/parsetexi/element_types.txt | 1 +
tp/Texinfo/XS/parsetexi/end_line.c | 175 ++++++++++++++++++++++++++++--
tp/Texinfo/XS/parsetexi/handle_commands.c | 2 +-
tp/Texinfo/XS/parsetexi/macro.c | 155 +++++++++++++-------------
tp/Texinfo/XS/parsetexi/macro.h | 2 +
tp/Texinfo/XS/parsetexi/parser.c | 64 ++++++++---
tp/Texinfo/XS/parsetexi/separator.c | 6 +-
tp/Texinfo/XS/parsetexi/source_marks.c | 7 ++
tp/Texinfo/XS/parsetexi/tree_types.h | 1 +
16 files changed, 468 insertions(+), 132 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index cbc3cb0e1b..16f533479a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2023-03-26 Patrice Dumas <pertusus@free.fr>
+
+ linemacro implementation for the XS Parser
+
+ * tp/Texinfo/XS/parsetexi/api.c (linemacro_expansion),
+ tp/Texinfo/XS/parsetexi/context_stack.h (no_paragraph_context),
+ tp/Texinfo/XS/parsetexi/def.c (parse_def),
+ tp/Texinfo/XS/parsetexi/element_types.txt,
+ tp/Texinfo/XS/parsetexi/end_line.c (end_line_def_line)
+ (end_line_misc_line, end_line),
+ tp/Texinfo/XS/parsetexi/handle_commands.c (handle_block_command),
+ tp/Texinfo/XS/parsetexi/macro.c (handle_macro),
+ tp/Texinfo/XS/parsetexi/parser.c (process_remaining_on_line)
+ (parse_texi), tp/Texinfo/XS/parsetexi/separator.c (handle_open_brace),
+ tp/Texinfo/XS/parsetexi/source_marks.c (register_source_mark)
+ (source_marks_reset_counters): handle @linemacro and linemacro defined
+ command calls using the same design as for perl Parser.
+
+ * tp/Texinfo/ParserNonXS.pm (%no_paragraph_contexts): set
+ ct_linecommand to be no paragraph context.
+
+ * tp/Texinfo/ParserNonXS.pm (_process_remaining_on_line):
+ change code opening arguments_container line_arg for linemacro command
+ call to be more like XS parser.
+
2023-03-26 Gavin Smith <gavinsmith0123@gmail.com>
* NEWS: add 7.0.3 news.
diff --git a/tp/Texinfo/ParserNonXS.pm b/tp/Texinfo/ParserNonXS.pm
index 5274d555bd..e8b401dfe1 100644
--- a/tp/Texinfo/ParserNonXS.pm
+++ b/tp/Texinfo/ParserNonXS.pm
@@ -543,7 +543,7 @@ foreach my $canonical_encoding ('us-ascii', 'utf-8',
'iso-8859-1',
# a paragraph
my %no_paragraph_contexts;
foreach my $no_paragraph_context ('math', 'preformatted', 'rawpreformatted',
- 'def', 'inlineraw') {
+ 'def', 'inlineraw', 'linecommand') {
$no_paragraph_contexts{'ct_'.$no_paragraph_context} = 1;
};
@@ -6867,10 +6867,12 @@ sub _process_remaining_on_line($$$$)
# FIXME needed? Correct?
$arguments_container->{'source_info'} = $source_info;
$self->_push_context('ct_linecommand', $command);
- $current = $current->{'contents'}->[-1];
- $current->{'args'} = [{ 'type' => 'line_arg',
- 'parent' => $current }];
- $current = $current->{'args'}->[-1];
+ $current = $arguments_container;
+ $current->{'args'} = [];
+ my $line_arg = { 'type' => 'line_arg',
+ 'parent' => $current };
+ push @{$current->{'args'}}, $line_arg;
+ $current = $line_arg;
$line = _start_empty_line_after_command($line, $current,
$arguments_container);
return ($current, $line, $source_info, $retval);
diff --git a/tp/Texinfo/XS/parsetexi/api.c b/tp/Texinfo/XS/parsetexi/api.c
index 83c9d83443..a96b7ceda4 100644
--- a/tp/Texinfo/XS/parsetexi/api.c
+++ b/tp/Texinfo/XS/parsetexi/api.c
@@ -471,6 +471,7 @@ store_source_mark_list (ELEMENT *e)
SAVE_S_M_TYPE (delcomment)
SAVE_S_M_TYPE (defline_continuation)
SAVE_S_M_TYPE (macro_expansion)
+ SAVE_S_M_TYPE (linemacro_expansion)
SAVE_S_M_TYPE (value_expansion)
SAVE_S_M_TYPE (ignored_conditional_block)
SAVE_S_M_TYPE (expanded_conditional_command)
diff --git a/tp/Texinfo/XS/parsetexi/context_stack.h
b/tp/Texinfo/XS/parsetexi/context_stack.h
index b2ed4f7706..e218483b5e 100644
--- a/tp/Texinfo/XS/parsetexi/context_stack.h
+++ b/tp/Texinfo/XS/parsetexi/context_stack.h
@@ -26,7 +26,8 @@ enum context {
ct_rawpreformatted,
ct_math,
ct_brace_command,
- ct_inlineraw
+ ct_inlineraw,
+ ct_linecommand
};
/* Contexts where an empty line doesn't start a new paragraph. */
@@ -35,7 +36,8 @@ enum context {
|| (c) == ct_def \
|| (c) == ct_preformatted \
|| (c) == ct_rawpreformatted \
- || (c) == ct_inlineraw)
+ || (c) == ct_inlineraw \
+ || (c) == ct_linecommand)
void push_context (enum context c, enum command_id cmd);
enum context pop_context (void);
diff --git a/tp/Texinfo/XS/parsetexi/def.c b/tp/Texinfo/XS/parsetexi/def.c
index 2a4d5de8c4..2085dca435 100644
--- a/tp/Texinfo/XS/parsetexi/def.c
+++ b/tp/Texinfo/XS/parsetexi/def.c
@@ -22,6 +22,7 @@
#include "parser.h"
#include "text.h"
#include "source_marks.h"
+#include "debug.h"
void
gather_def_item (ELEMENT *current, enum command_id next_command)
@@ -329,8 +330,9 @@ parse_def (enum command_id command, ELEMENT *current)
int type, next_type;
int i, i_def;
int arg_types_nr;
- ELEMENT *e, *e1;
+ ELEMENT *e, *e1;
DEF_ARG **result;
+ char **arguments_list;
split_def_args (current, contents_idx);
@@ -371,43 +373,128 @@ parse_def (enum command_id command, ELEMENT *current)
insert_into_contents (current, e, contents_idx + 1);
}
- /* Read arguments as CATEGORY [CLASS] [TYPE] NAME [ARGUMENTS]. */
-
+ /* prepare the arguments numbers and list */
+ if (command_data(command).flags & CF_MACRO)
+ {
+ int args_number;
+ MACRO *macro_record = lookup_macro (command);
+ ELEMENT *macro;
+ if (!macro_record)
+ fatal ("no linemacro record for arguments parsing");
+ macro = macro_record->element;
+ args_number = macro->args.number - 1;
+ arguments_list = malloc ((args_number + 1) * sizeof (char *));
+ arguments_list[args_number] = 0;
+ arg_types_nr = args_number;
+ if (args_number > 0)
+ {
+ int arg_index;
+ ELEMENT **args = macro->args.list;
+ for (arg_index = 1; arg_index <= args_number; arg_index++)
+ {
+ if (args[arg_index]->type == ET_macro_arg)
+ arguments_list[arg_index -1] = args[arg_index]->text.text;
+ else
+ arguments_list[arg_index -1] = 0;
+ }
+ /* remove one for the rest of the line argument */
+ arg_types_nr--;
- for (i_def = 0; i_def < sizeof (def_maps) / sizeof (*def_maps); i_def++)
+ result = malloc ((args_number+1) * sizeof (DEF_ARG *));
+ }
+ }
+ else
{
- if (def_maps[i_def].command == command)
- goto def_found;
+ /* Read arguments as CATEGORY [CLASS] [TYPE] NAME [ARGUMENTS]. */
+
+ for (i_def = 0; i_def < sizeof (def_maps) / sizeof (*def_maps); i_def++)
+ {
+ if (def_maps[i_def].command == command)
+ goto def_found;
+ }
+ fatal ("no arguments for def command");
+ def_found:
+
+ /* determine non arg/argtype number of arguments */
+ arg_types_nr = 0;
+ arguments_list = def_maps[i_def].arguments;
+ while (arguments_list[arg_types_nr])
+ {
+ char *arg_type_name = arguments_list[arg_types_nr];
+
+ /* FIXME keep information about arg/argtype? */
+ if (!strcmp (arg_type_name, "arg")
+ || !strcmp (arg_type_name, "argtype"))
+ break;
+ arg_types_nr++;
+ }
+ result = malloc ((arg_types_nr+1) * sizeof (DEF_ARG *));
}
- fatal ("no arguments for def command");
- def_found:
- /* determine non arg/argtype number of arguments */
- arg_types_nr = 0;
- while (def_maps[i_def].arguments[arg_types_nr])
+ for (i = 0; i < arg_types_nr; i++)
{
- char *arg_type_name = def_maps[i_def].arguments[arg_types_nr];
+ ELEMENT *e = next_bracketed_or_word_agg (current, &contents_idx);
- /* FIXME keep information about arg/argtype? */
- if (!strcmp (arg_type_name, "arg")
- || !strcmp (arg_type_name, "argtype"))
- break;
- arg_types_nr++;
+ if (e)
+ {
+ char *arg_type_name = arguments_list[i];
+ DEF_ARG *def_arg = malloc (sizeof (DEF_ARG));
+
+ result[i] = def_arg;
+ def_arg->arg_type = strdup(arg_type_name);
+ def_arg->element = e;
+ }
+ else
+ {
+ i++;
+ break;
+ }
+ }
+
+ result[i] = 0;
+ if (command_data(command).flags & CF_MACRO)
+ {
+ /* FIXME do not add leading space to def_arg */
+ /* note that element at contents_idx is not collected at that point */
+ if (contents_idx < current->contents.number)
+ {
+ DEF_ARG *def_arg = malloc (sizeof (DEF_ARG));
+ int contents_nr = current->contents.number - contents_idx;
+
+ result[i] = def_arg;
+ result[i+1] = 0;
+
+ def_arg->arg_type = strdup (arguments_list[i]);
+ if (contents_nr == 1)
+ def_arg->element = current->contents.list[contents_idx];
+ else
+ {
+ ELEMENT *new = new_element (ET_def_aggregate);
+ int j;
+ for (j = 0; j < contents_nr; j++)
+ {
+ add_to_element_contents (new,
+ remove_from_contents (current,
+
contents_idx));
+ }
+ add_to_element_contents (current, new);
+ def_arg->element = new;
+ }
+ }
+ return result;
}
- result = malloc ((arg_types_nr+1) * sizeof (DEF_ARG *));
for (i = 0; i < arg_types_nr; i++)
{
- char *arg_type_name = def_maps[i_def].arguments[i];
- DEF_ARG *def_arg = malloc (sizeof (DEF_ARG));
-
- result[i] = def_arg;
- def_arg->arg_type = strdup(arg_type_name);
- def_arg->element = next_bracketed_or_word_agg (current, &contents_idx);
- if (def_arg->element)
- add_extra_string_dup (def_arg->element, "def_role", arg_type_name);
+ if (result[i])
+ {
+ DEF_ARG *def_arg = result[i];
+ if (def_arg->element)
+ add_extra_string_dup (def_arg->element, "def_role",
def_arg->arg_type);
+ }
+ else
+ break;
}
- result[i] = 0;
/* Process args */
split_delimiters (current, contents_idx);
diff --git a/tp/Texinfo/XS/parsetexi/element_types.c
b/tp/Texinfo/XS/parsetexi/element_types.c
index b04de39add..dc1cfb4e32 100644
--- a/tp/Texinfo/XS/parsetexi/element_types.c
+++ b/tp/Texinfo/XS/parsetexi/element_types.c
@@ -68,5 +68,6 @@ char *element_type_names[] = {
"untranslated",
"macro_call",
"rmacro_call",
+"linemacro_call",
};
diff --git a/tp/Texinfo/XS/parsetexi/element_types.h
b/tp/Texinfo/XS/parsetexi/element_types.h
index adb67235ef..7ff8d35e60 100644
--- a/tp/Texinfo/XS/parsetexi/element_types.h
+++ b/tp/Texinfo/XS/parsetexi/element_types.h
@@ -71,6 +71,7 @@ ET_spaces,
ET_untranslated,
ET_macro_call,
ET_rmacro_call,
+ET_linemacro_call,
};
extern char *element_type_names[];
diff --git a/tp/Texinfo/XS/parsetexi/element_types.txt
b/tp/Texinfo/XS/parsetexi/element_types.txt
index 84a6c912ad..d82fe6fe5a 100644
--- a/tp/Texinfo/XS/parsetexi/element_types.txt
+++ b/tp/Texinfo/XS/parsetexi/element_types.txt
@@ -99,4 +99,5 @@ untranslated
# for macro expansion source marks
macro_call
rmacro_call
+linemacro_call
diff --git a/tp/Texinfo/XS/parsetexi/end_line.c
b/tp/Texinfo/XS/parsetexi/end_line.c
index 68088201b4..8106a0b014 100644
--- a/tp/Texinfo/XS/parsetexi/end_line.c
+++ b/tp/Texinfo/XS/parsetexi/end_line.c
@@ -643,19 +643,165 @@ end_line_def_line (ELEMENT *current)
ELEMENT *index_entry = 0; /* Index entry text. */
ELEMENT *def_info_name = 0;
ELEMENT *def_info_class = 0;
- ELEMENT * def_info_category = 0;
+ ELEMENT *def_info_category = 0;
int i = 0;
+ enum command_id top_cmd = current_context_command ();
+ enum context top_context = pop_context ();
- if (pop_context () != ct_def)
- fatal ("def context expected");
+ if (top_context != ct_def && top_context != ct_linecommand)
+ fatal ("def or linecommand context expected");
- k = lookup_extra (current->parent, "def_command");
- def_command = lookup_command ((char *) k->value);
+ if (top_context == ct_def)
+ {
+ k = lookup_extra (current->parent, "def_command");
+ def_command = lookup_command ((char *) k->value);
+ }
+ else
+ {
+ /* The following also works
+ k = lookup_extra (current->parent, "name");
+ def_command = lookup_command ((char *) k->value);
+ */
+ def_command = top_cmd;
+ }
def_info = parse_def (def_command, current);
+ /* def_line or linemacro_call */
current = current->parent;
+ if (top_context != ct_def)
+ {
+ /* convert arguments tree elements back to Texinfo text and substitute */
+ int args_number;
+ MACRO *macro_record = lookup_macro (def_command);
+ ELEMENT *macro;
+ ELEMENT *macro_args = 0;
+ ELEMENT *popped;
+ TEXT expanded;
+ SOURCE_MARK *macro_source_mark;
+ char *expanded_macro_text;
+
+ if (!macro_record)
+ fatal ("no linemacro record for expansion");
+
+ text_init (&expanded);
+
+ macro = macro_record->element;
+ args_number = macro->args.number - 1;
+
+ if (args_number > 0)
+ {
+ int def_info_index;
+ macro_args = new_element (ET_NONE);
+ for (def_info_index = 0; def_info_index < args_number;
def_info_index++)
+ {
+ char *argument_text;
+ ELEMENT *macro_arg_text;
+ ELEMENT *macro_arg_element;
+
+ if (!def_info[def_info_index])
+ break;
+ /* convert the argument to a Texinfo string */
+ if (def_info[def_info_index]->element)
+ {
+ ELEMENT *arg = def_info[def_info_index]->element;
+ if (arg->type == ET_bracketed_arg)
+ {
+ /* we also duplicate leading and trailing spaces */
+ KEY_PAIR *kspaces_before
+ = lookup_info (arg, "spaces_before_argument");
+ KEY_PAIR *kspaces_after
+ = lookup_info (arg, "spaces_after_argument");
+
+ if (arg->contents.number > 0
+ || kspaces_before || kspaces_after)
+ {
+ ELEMENT *tmp_element = new_element (ET_NONE);
+ tmp_element->contents = arg->contents;
+ if (kspaces_before)
+ {
+ ELEMENT *spaces_element = new_element (ET_NONE);
+ text_append (&spaces_element->text,
+ (char
*)kspaces_before->value->text.text);
+ add_info_element_oot (tmp_element,
+ "spaces_before_argument",
+ spaces_element);
+ }
+ if (kspaces_after)
+ {
+ ELEMENT *spaces_element = new_element (ET_NONE);
+ text_append (&spaces_element->text,
+ (char
*)kspaces_after->value->text.text);
+ add_info_element_oot (tmp_element,
+ "spaces_after_argument",
+ spaces_element);
+ }
+ argument_text = convert_to_texinfo (tmp_element);
+ tmp_element->contents.list = 0;
+ destroy_element (tmp_element);
+ }
+ else
+ argument_text = strdup("");
+ }
+ else
+ {
+ /* FIXME remove leading spaces but they should probably
+ not be in the input */
+ char *converted_string = convert_to_texinfo (arg);
+ argument_text = strdup(converted_string
+ + strspn (converted_string,
whitespace_chars_except_newline));
+ free (converted_string);
+ }
+ }
+ else
+ argument_text = strdup("");
+
+ free (def_info[def_info_index]->arg_type);
+ free (def_info[def_info_index]);
+
+ /* setup an argument suitable for expand_macro_body and
+ add it to macro_args */
+ macro_arg_text = new_element (ET_NONE);
+ text_append (¯o_arg_text->text, argument_text);
+ free (argument_text);
+ macro_arg_element = new_element (ET_NONE);
+ add_to_element_contents (macro_arg_element, macro_arg_text);
+ add_to_element_args (macro_args, macro_arg_element);
+ }
+ }
+ free (def_info);
+
+ expand_macro_body (macro_record, macro_args, &expanded);
+ debug ("LINEMACROBODY: %s||||||", expanded.text);
+
+ if (expanded.text)
+ expanded_macro_text = expanded.text;
+ else
+ /* we want to always have a text for the source mark */
+ expanded_macro_text = strdup ("");
+ input_push_text (expanded_macro_text, current_source_info.line_nr,
+ command_name(def_command), 0);
+
+ macro_source_mark = new_source_mark (SM_type_linemacro_expansion);
+ macro_source_mark->status = SM_status_start;
+ /* at this point current is the linemacro_call container,
+ associate it to the source mark */
+ macro_source_mark->element = current;
+
+ current = current->parent;
+ /* remove the linemacro_call container from the main tree.
+ The container holds the arguments Texinfo elements tree */
+ popped = pop_element_from_contents (current);
+
+ register_source_mark (current, macro_source_mark);
+ set_input_source_mark (macro_source_mark);
+
+ destroy_element_and_children (macro_args);
+
+ return current;
+ }
+
/* Record the index entry if def_info is not empty. */
while (def_info[i] != 0 && def_info[i]->element != 0)
@@ -1170,21 +1316,23 @@ end_line_misc_line (ELEMENT *current)
if (cmd == CM_item)
data_cmd = CM_item_LINE;
- if (!cmd)
+ if (!cmd && !current->parent->type == ET_linemacro_call)
fatal ("command name unknown for line command end");
+ /* FIXME add a condition to avoid linecommands? */
if (command_data(data_cmd).flags & CF_contain_basic_inline)
(void) pop_command (&nesting_context.basic_inline_stack_on_line);
isolate_last_space (current);
- if (current->parent->type == ET_def_line)
+ if (current->parent->type == ET_def_line
+ || current->parent->type == ET_linemacro_call)
return end_line_def_line (current);
current = current->parent;
misc_cmd = current;
arg_spec = command_data(data_cmd).data;
-
+
debug ("MISC END %s", command_name(cmd));
if (pop_context () != ct_line)
@@ -1828,7 +1976,8 @@ end_line (ELEMENT *current)
/* 'line' or 'def' at top of "context stack" - this happens when
line commands are nested (always incorrectly?) */
- if (current_context () == ct_line || current_context () == ct_def)
+ if (current_context () == ct_line || current_context () == ct_def
+ || current_context () == ct_linecommand)
{
debug_nonl ("Still opened line command %d:", current_context ());
debug_print_element (current, 1); debug("");
@@ -1840,6 +1989,14 @@ end_line (ELEMENT *current)
current = close_current (current, 0, 0);
}
}
+ else if (current_context () == ct_linecommand)
+ {
+ while (current->parent
+ && current->parent->type != ET_linemacro_call)
+ {
+ current = close_current (current, 0, 0);
+ }
+ }
else
{
while (current->parent
diff --git a/tp/Texinfo/XS/parsetexi/handle_commands.c
b/tp/Texinfo/XS/parsetexi/handle_commands.c
index eb4381dbf1..b9a07a026a 100644
--- a/tp/Texinfo/XS/parsetexi/handle_commands.c
+++ b/tp/Texinfo/XS/parsetexi/handle_commands.c
@@ -996,7 +996,7 @@ handle_block_command (ELEMENT *current, char **line_inout,
ELEMENT *block = 0;
/* New macro being defined. */
- if (cmd == CM_macro || cmd == CM_rmacro)
+ if (cmd == CM_macro || cmd == CM_rmacro || cmd == CM_linemacro)
{
block = parse_macro_command_line (cmd, &line, current);
add_to_element_contents (current, block);
diff --git a/tp/Texinfo/XS/parsetexi/macro.c b/tp/Texinfo/XS/parsetexi/macro.c
index 17067237d9..3cb30c2b8f 100644
--- a/tp/Texinfo/XS/parsetexi/macro.c
+++ b/tp/Texinfo/XS/parsetexi/macro.c
@@ -421,7 +421,7 @@ funexit:
/* ARGUMENTS element holds the arguments used in the macro invocation.
EXPANDED gets the result of the expansion. */
-static void
+void
expand_macro_body (MACRO *macro_record, ELEMENT *arguments, TEXT *expanded)
{
int pos; /* Index into arguments. */
@@ -577,91 +577,97 @@ handle_macro (ELEMENT *current, char **line_inout, enum
command_id cmd)
arguments_container->type = ET_macro_call;
else if (macro->cmd == CM_rmacro)
arguments_container->type = ET_rmacro_call;
- add_extra_string_dup (arguments_container, "name", command_name(cmd));
+ else if (macro->cmd == CM_linemacro)
+ arguments_container->type = ET_linemacro_call;
- /* Get number of args. - 1 for the macro name. */
- args_number = macro->args.number - 1;
+ add_extra_string_dup (arguments_container, "name", command_name(cmd));
- p = line + strspn (line, whitespace_chars);
- if (*p == '{')
- {
- p++;
- line = p;
- line += strspn (line, whitespace_chars);
- if (line - p)
- {
- ELEMENT *spaces_element = new_element (ET_NONE);
- text_append_n (&spaces_element->text, p, line - p);
- add_info_element_oot (arguments_container, "spaces_before_argument",
- spaces_element);
- }
- expand_macro_arguments (macro, &line, cmd, arguments_container);
- }
- /* Warning depending on the number of arguments this macro
- is supposed to take. */
- else if (args_number != 1)
+ if (macro->cmd != CM_linemacro)
{
- if (args_number > 1)
- line_warn ("@%s defined with zero or more than one argument should "
- "be invoked with {}", command_name(cmd));
- /* As agreed on the bug-texinfo mailing list, no warn when zero
- arg and not called with {}. */
- }
- else
- {
- ELEMENT *arg_elt = new_element (ET_line_arg);
- add_to_element_args (arguments_container, arg_elt);
+ /* Get number of args. - 1 for the macro name. */
+ args_number = macro->args.number - 1;
- while (1)
+ p = line + strspn (line, whitespace_chars);
+ if (*p == '{')
{
- if (*line == '\0')
+ p++;
+ line = p;
+ line += strspn (line, whitespace_chars);
+ if (line - p)
{
- /* If it takes a single line of input, and we don't have a
- full line of input already, call new_line. */
- line = new_line (arg_elt);
- if (!line)
- {
- line = "";
- break;
- }
+ ELEMENT *spaces_element = new_element (ET_NONE);
+ text_append_n (&spaces_element->text, p, line - p);
+ add_info_element_oot (arguments_container,
"spaces_before_argument",
+ spaces_element);
}
- else
+ expand_macro_arguments (macro, &line, cmd, arguments_container);
+ }
+ /* Warning depending on the number of arguments this macro
+ is supposed to take. */
+ else if (args_number != 1)
+ {
+ if (args_number > 1)
+ line_warn ("@%s defined with zero or more than one argument should
"
+ "be invoked with {}", command_name(cmd));
+ /* As agreed on the bug-texinfo mailing list, no warn when zero
+ arg and not called with {}. */
+ }
+ else
+ {
+ ELEMENT *arg_elt = new_element (ET_line_arg);
+ add_to_element_args (arguments_container, arg_elt);
+
+ while (1)
{
- int leading_spaces_added = 0;
- if (arg_elt->contents.number == 0)
+ if (*line == '\0')
{
- int leading_spaces_nr = strspn (line,
- whitespace_chars_except_newline);
- if (leading_spaces_nr)
+ /* If it takes a single line of input, and we don't have a
+ full line of input already, call new_line. */
+ line = new_line (arg_elt);
+ if (!line)
{
- ELEMENT *internal_space
- = new_element (ET_internal_spaces_before_argument);
- text_append_n (&internal_space->text, line,
- leading_spaces_nr);
- add_extra_element (internal_space,
- "spaces_associated_command",
- arguments_container);
- add_to_element_contents (arg_elt, internal_space);
-
- line += leading_spaces_nr;
-
- leading_spaces_added = 1;
+ line = "";
+ break;
}
}
- if (! leading_spaces_added)
+ else
{
- char *p = strchr (line, '\n');
- if (!p)
+ int leading_spaces_added = 0;
+ if (arg_elt->contents.number == 0)
{
- arg_elt = merge_text (arg_elt, line, 0);
- line += strlen(line);
+ int leading_spaces_nr = strspn (line,
+
whitespace_chars_except_newline);
+ if (leading_spaces_nr)
+ {
+ ELEMENT *internal_space
+ = new_element (ET_internal_spaces_before_argument);
+ text_append_n (&internal_space->text, line,
+ leading_spaces_nr);
+ add_extra_element (internal_space,
+ "spaces_associated_command",
+ arguments_container);
+ add_to_element_contents (arg_elt, internal_space);
+
+ line += leading_spaces_nr;
+
+ leading_spaces_added = 1;
+ }
}
- else
+ if (! leading_spaces_added)
{
- *p = '\0';
- arg_elt = merge_text (arg_elt, line, 0);
- line = "\n";
- break;
+ char *p = strchr (line, '\n');
+ if (!p)
+ {
+ arg_elt = merge_text (arg_elt, line, 0);
+ line += strlen(line);
+ }
+ else
+ {
+ *p = '\0';
+ arg_elt = merge_text (arg_elt, line, 0);
+ line = "\n";
+ break;
+ }
}
}
}
@@ -679,7 +685,7 @@ handle_macro (ELEMENT *current, char **line_inout, enum
command_id cmd)
goto funexit;
}
- if (macro->cmd == CM_macro)
+ if (macro->cmd != CM_rmacro)
{
if (expanding_macro (command_name(cmd)))
{
@@ -690,6 +696,11 @@ handle_macro (ELEMENT *current, char **line_inout, enum
command_id cmd)
}
}
+ macro_expansion_nr++;
+
+ if (macro->cmd == CM_linemacro)
+ goto funexit;
+
expand_macro_body (macro_record, arguments_container, &expanded);
debug ("MACROBODY: %s||||||", expanded.text);
@@ -701,8 +712,6 @@ handle_macro (ELEMENT *current, char **line_inout, enum
command_id cmd)
macro_source_mark->element = arguments_container;
register_source_mark (current, macro_source_mark);
- macro_expansion_nr++;
-
/* Put expansion in front of the current line. */
input_push_text (strdup (line), current_source_info.line_nr, 0, 0);
/* not really important as line is ignored by the caller if there
diff --git a/tp/Texinfo/XS/parsetexi/macro.h b/tp/Texinfo/XS/parsetexi/macro.h
index 6f8603d5ce..f6c7311319 100644
--- a/tp/Texinfo/XS/parsetexi/macro.h
+++ b/tp/Texinfo/XS/parsetexi/macro.h
@@ -38,6 +38,8 @@ ELEMENT *handle_macro (ELEMENT *current, char **line_inout,
enum command_id cmd_id);
void delete_macro (char *name);
void unset_macro_record (MACRO *m);
+void expand_macro_body (MACRO *macro_record, ELEMENT *arguments,
+ TEXT *expanded);
MACRO *lookup_macro (enum command_id cmd);
void wipe_macros (void);
diff --git a/tp/Texinfo/XS/parsetexi/parser.c b/tp/Texinfo/XS/parsetexi/parser.c
index 7429b37303..4199ed890d 100644
--- a/tp/Texinfo/XS/parsetexi/parser.c
+++ b/tp/Texinfo/XS/parsetexi/parser.c
@@ -1294,6 +1294,7 @@ int
process_remaining_on_line (ELEMENT **current_inout, char **line_inout)
{
ELEMENT *current = *current_inout;
+ ELEMENT *macro_call_element = 0;
char *line = *line_inout;
char *line_after_command;
int retval = STILL_MORE_TO_PROCESS;
@@ -1312,7 +1313,8 @@ process_remaining_on_line (ELEMENT **current_inout, char
**line_inout)
enum command_id cmd = 0;
int closed_nested_raw = 0;
/* Check if we are using a macro within a macro. */
- if (current->cmd == CM_macro || current->cmd == CM_rmacro)
+ if (current->cmd == CM_macro || current->cmd == CM_rmacro
+ || current->cmd == CM_linemacro)
{
p += strspn (p, whitespace_chars);
if (!strncmp (p, "@macro", strlen ("@macro")))
@@ -1325,6 +1327,11 @@ process_remaining_on_line (ELEMENT **current_inout, char
**line_inout)
p += strlen ("@rmacro");
cmd = CM_rmacro;
}
+ else if (!strncmp (p, "@linemacro", strlen ("@linemacro")))
+ {
+ p += strlen ("@linemacro");
+ cmd = CM_linemacro;
+ }
if (*p && !strchr (whitespace_chars, *p))
cmd = 0;
}
@@ -1374,7 +1381,8 @@ process_remaining_on_line (ELEMENT **current_inout, char
**line_inout)
"beginning of a line", command_name(end_cmd));
}
/* For macros, define a new macro. */
- if (end_cmd == CM_macro || end_cmd == CM_rmacro)
+ if (end_cmd == CM_macro || end_cmd == CM_rmacro
+ || end_cmd == CM_linemacro)
{
char *name;
enum command_id existing;
@@ -1687,7 +1695,6 @@ process_remaining_on_line (ELEMENT **current_inout, char
**line_inout)
if (cmd && (command_data(cmd).flags & CF_MACRO))
{
static char *allocated_line;
- ELEMENT *macro_call_element;
line = line_after_command;
macro_call_element = handle_macro (current, &line, cmd);
@@ -1696,7 +1703,14 @@ process_remaining_on_line (ELEMENT **current_inout, char
**line_inout)
if (from_alias != CM_NONE)
add_info_string_dup (macro_call_element, "alias_of",
command_name (from_alias));
-
+ }
+ if (macro_call_element && macro_call_element->type == ET_linemacro_call)
+ /* do nothing, the linemacro defined command call is done at the
+ end of the line after parsing the line similarly as for @def* */
+ {
+ }
+ else if (macro_call_element)
+ {
/* directly get the following input (macro expansion text) instead
of going through the next call of process_remaining_on_line and
the processing of empty text. No difference in output, more
@@ -1706,8 +1720,10 @@ process_remaining_on_line (ELEMENT **current_inout, char
**line_inout)
free (allocated_line);
allocated_line = next_text (current);
line = allocated_line;
+ goto funexit;
}
- goto funexit;
+ else
+ goto funexit;
}
/* expand value if it actually expands and changes the line. It is
considered again together with other commands below for all the other
cases
@@ -1884,7 +1900,9 @@ process_remaining_on_line (ELEMENT **current_inout, char
**line_inout)
line_warn ("command `@%s' must not be followed by new line",
command_name(current->cmd));
if (current_context() == ct_def
- || current_context() == ct_line)
+ || current_context() == ct_line
+ /* FIXME check that it is correct and add a test case */
+ || current_context() == ct_linecommand)
{
/* do not consider the end of line to be possibly between
the @-command and the argument if at the end of a
@@ -2075,6 +2093,20 @@ process_remaining_on_line (ELEMENT **current_inout, char
**line_inout)
goto funexit;
}
}
+ else if (macro_call_element)
+ {
+ ELEMENT *line_arg = new_element (ET_line_arg);
+
+ add_to_element_contents (current, macro_call_element);
+ /* FIXME needed? Correct? */
+ macro_call_element->source_info = current_source_info;
+ push_context (ct_linecommand, cmd);
+ current = macro_call_element;
+ add_to_element_args (current, line_arg);
+ current = line_arg;
+ start_empty_line_after_command (current, &line, macro_call_element);
+ goto funexit;
+ }
/* Warn on deprecated command */
if (command_data(cmd).flags & CF_deprecated)
@@ -2094,6 +2126,16 @@ process_remaining_on_line (ELEMENT **current_inout, char
**line_inout)
gettext is implemented */
}
+ /* special case with @ followed by a newline protecting end of lines
+ in linemacro invokations and @def* */
+ if (current_context () == ct_linecommand && cmd == CM_NEWLINE)
+ {
+ ELEMENT *command_e = new_element (ET_NONE);
+ command_e->cmd = cmd;
+ add_to_element_contents (current, command_e);
+ retval = GET_A_NEW_LINE;
+ goto funexit;
+ }
def_line_continuation = (current_context() == ct_def
&& cmd == CM_NEWLINE);
/* warn on not appearing at line beginning. Need to do before closing
@@ -2410,7 +2452,8 @@ parse_texi (ELEMENT *root_elt, ELEMENT *current_elt)
|| (command_data(current->cmd).data == BLOCK_format_raw
&& !format_expanded_p (command_name(current->cmd)))))
|| current->parent && current->parent->cmd == CM_verb)
- && current_context () != ct_def)
+ && current_context () != ct_def
+ && current_context () != ct_linecommand)
{
ELEMENT *e;
int n;
@@ -2453,7 +2496,7 @@ parse_texi (ELEMENT *root_elt, ELEMENT *current_elt)
}
}
}
-finished_totally:
+ finished_totally:
/* Check for unclosed conditionals */
while (conditional_number > 0)
@@ -2521,10 +2564,5 @@ finished_totally:
if (input_number > 0)
fprintf (stderr, "BUG: at end, input_number > 0: %d", input_number);
- /* to avoid a memory leak if @bye is given */
- /*
- input_reset_input_stack ();
- */
-
return current;
}
diff --git a/tp/Texinfo/XS/parsetexi/separator.c
b/tp/Texinfo/XS/parsetexi/separator.c
index 7fee7e5083..eeb18d4739 100644
--- a/tp/Texinfo/XS/parsetexi/separator.c
+++ b/tp/Texinfo/XS/parsetexi/separator.c
@@ -166,7 +166,8 @@ handle_open_brace (ELEMENT *current, char **line_inout)
debug ("OPENED");
}
else if (current->parent && (current->parent->cmd == CM_multitable
- || current->parent->type == ET_def_line))
+ || current->parent->type == ET_def_line
+ || current->parent->type == ET_linemacro_call))
{
ELEMENT *b, *e;
abort_empty_line (¤t, NULL);
@@ -195,7 +196,8 @@ handle_open_brace (ELEMENT *current, char **line_inout)
*/
else if (current_context() == ct_math
|| current_context() == ct_rawpreformatted
- || current_context() == ct_inlineraw)
+ || current_context() == ct_inlineraw
+ || current_context() == ct_linecommand)
{
ELEMENT *b = new_element (ET_balanced_braces);
ELEMENT *open_brace = new_element (ET_NONE);
diff --git a/tp/Texinfo/XS/parsetexi/source_marks.c
b/tp/Texinfo/XS/parsetexi/source_marks.c
index fe7b08b2d0..5a071101fb 100644
--- a/tp/Texinfo/XS/parsetexi/source_marks.c
+++ b/tp/Texinfo/XS/parsetexi/source_marks.c
@@ -26,6 +26,7 @@ int setfilename_counter = 0;
int delcomment_counter = 0;
int defline_continuation_counter = 0;
int macro_expansion_counter = 0;
+int linemacro_expansion_counter = 0;
int value_expansion_counter = 0;
int ignored_conditional_block_counter = 0;
int expanded_conditional_command_counter = 0;
@@ -137,6 +138,11 @@ register_source_mark (ELEMENT *e, SOURCE_MARK *source_mark)
macro_expansion_counter++;
source_mark->counter = macro_expansion_counter;
}
+ else if (source_mark->type == SM_type_linemacro_expansion)
+ {
+ linemacro_expansion_counter++;
+ source_mark->counter = linemacro_expansion_counter;
+ }
else if (source_mark->type == SM_type_value_expansion)
{
value_expansion_counter++;
@@ -165,6 +171,7 @@ source_marks_reset_counters (void)
delcomment_counter = 0;
defline_continuation_counter = 0;
macro_expansion_counter = 0;
+ linemacro_expansion_counter = 0;
value_expansion_counter = 0;
ignored_conditional_block_counter = 0;
expanded_conditional_command_counter = 0;
diff --git a/tp/Texinfo/XS/parsetexi/tree_types.h
b/tp/Texinfo/XS/parsetexi/tree_types.h
index e4a742bcf5..9d5e81d005 100644
--- a/tp/Texinfo/XS/parsetexi/tree_types.h
+++ b/tp/Texinfo/XS/parsetexi/tree_types.h
@@ -41,6 +41,7 @@ enum source_mark_type { SM_type_none,
SM_type_delcomment,
SM_type_defline_continuation,
SM_type_macro_expansion,
+ SM_type_linemacro_expansion,
SM_type_value_expansion,
SM_type_ignored_conditional_block,
SM_type_expanded_conditional_command
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- branch master updated: linemacro implementation for the XS Parser,
Patrice Dumas <=