texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

branch master updated: * tp/Texinfo/ParserNonXS.pm (_parse_command_name,


From: Patrice Dumas
Subject: branch master updated: * tp/Texinfo/ParserNonXS.pm (_parse_command_name, _parse_texi_regex) (_process_remaining_on_line), tp/Texinfo/XS/MiscXS.xs (xs_parse_command_name, xs_parse_texi_regex), tp/Texinfo/XS/misc.c (xs_parse_command_name, xs_parse_texi_regex), tp/Texinfo/XS/parsetexi/parser.c (parse_command_name) (process_remaining_on_line): process text starting with @ in one place. Determine first if starting by @ (in _parse_texi_regex in the perl parser) and afterwards determine the command name, with a new fu [...]
Date: Tue, 18 Jul 2023 18:10:55 -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 4907ea77b2 * tp/Texinfo/ParserNonXS.pm (_parse_command_name, 
_parse_texi_regex) (_process_remaining_on_line), tp/Texinfo/XS/MiscXS.xs 
(xs_parse_command_name, xs_parse_texi_regex), tp/Texinfo/XS/misc.c 
(xs_parse_command_name, xs_parse_texi_regex), tp/Texinfo/XS/parsetexi/parser.c 
(parse_command_name) (process_remaining_on_line): process text starting with @ 
in one place.  Determine first if starting by @ (in _parse_texi_regex in the 
perl parser) and afterwards determine the comman [...]
4907ea77b2 is described below

commit 4907ea77b20fe0f9566506994b7322b78006dbf5
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Wed Jul 19 00:09:05 2023 +0200

    * tp/Texinfo/ParserNonXS.pm (_parse_command_name, _parse_texi_regex)
    (_process_remaining_on_line), tp/Texinfo/XS/MiscXS.xs
    (xs_parse_command_name, xs_parse_texi_regex), tp/Texinfo/XS/misc.c
    (xs_parse_command_name, xs_parse_texi_regex),
    tp/Texinfo/XS/parsetexi/parser.c (parse_command_name)
    (process_remaining_on_line): process text starting with @ in one
    place.  Determine first if starting by @ (in _parse_texi_regex in the
    perl parser) and afterwards determine the command name, with a new
    function parse_command_name.
---
 ChangeLog                        |  12 +++
 tp/Texinfo/ParserNonXS.pm        | 208 +++++++++++++++++++++------------------
 tp/Texinfo/XS/MiscXS.xs          |  43 ++++----
 tp/Texinfo/XS/misc.c             | 155 +++++++++++++++--------------
 tp/Texinfo/XS/miscxs.h           |   5 +-
 tp/Texinfo/XS/parsetexi/parser.c |  79 ++++++++-------
 6 files changed, 284 insertions(+), 218 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6c32df3e42..8bb761f332 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2023-07-18  Patrice Dumas  <pertusus@free.fr>
+
+       * tp/Texinfo/ParserNonXS.pm (_parse_command_name, _parse_texi_regex)
+       (_process_remaining_on_line), tp/Texinfo/XS/MiscXS.xs
+       (xs_parse_command_name, xs_parse_texi_regex), tp/Texinfo/XS/misc.c
+       (xs_parse_command_name, xs_parse_texi_regex),
+       tp/Texinfo/XS/parsetexi/parser.c (parse_command_name)
+       (process_remaining_on_line): process text starting with @ in one
+       place.  Determine first if starting by @ (in _parse_texi_regex in the
+       perl parser) and afterwards determine the command name, with a new
+       function parse_command_name.
+
 2023-07-17  Gavin Smith <gavinsmith0123@gmail.com>
 
        Multi-line TOC entry alignment
diff --git a/tp/Texinfo/ParserNonXS.pm b/tp/Texinfo/ParserNonXS.pm
index 085fe528d0..e6181dd83e 100644
--- a/tp/Texinfo/ParserNonXS.pm
+++ b/tp/Texinfo/ParserNonXS.pm
@@ -98,6 +98,8 @@ sub import {
   if (!$module_loaded) {
     Texinfo::XSLoader::override ("Texinfo::Parser::_parse_texi_regex",
       "Texinfo::MiscXS::parse_texi_regex");
+    Texinfo::XSLoader::override ("Texinfo::Parser::_parse_command_name",
+      "Texinfo::MiscXS::parse_command_name");
     $module_loaded = 1;
   }
   # The usual import method
@@ -4585,6 +4587,18 @@ sub _is_index_element {
   return 1;
 }
 
+# NOTE - this sub has an XS override
+sub _parse_command_name {
+  my ($line) = @_;
+  # REMACRO
+  my ($at_command, $single_letter_command)
+   = ($line =~ /^([[:alnum:]][[:alnum:]-]*)
+                |^(["'~\@&\}\{,\.!\? \t\n\*\-\^`=:\|\/\\])
+                /x);
+
+  return ($at_command, $single_letter_command);
+}
+
 # This combines several regular expressions used in '_parse_texi' to
 # look at what is next on the remaining part of the line.
 # NOTE - this sub has an XS override
@@ -4592,16 +4606,13 @@ sub _parse_texi_regex {
   my ($line) = @_;
 
   # REMACRO
-  my ($at_command, $open_brace, $close_brace, $comma,
-      $asterisk, $single_letter_command, $arobase,
-      $form_feed, $menu_only_separator, $misc_text)
-    = ($line =~ /^\@([[:alnum:]][[:alnum:]-]*)
+  my ($arobase, $open_brace, $close_brace, $comma,
+      $asterisk, $form_feed, $menu_only_separator, $misc_text)
+    = ($line =~ /^(@)
                 |^(\{)
                 |^(\})
                 |^(,)
                 |^(\*)
-                |^\@(["'~\@&\}\{,\.!\? \t\n\*\-\^`=:\|\/\\])
-                |^(@)
                 |^(\f)
                 |^([:\t.])
                 |^([^{}@,:\t.\n\f]+)
@@ -4611,9 +4622,8 @@ sub _parse_texi_regex {
     ($misc_text) = ($line =~ /^([^{}@,:\t.\n\f]+)/);
   }
 
-  return ($at_command, $open_brace, $close_brace, $comma,
-    $asterisk, $single_letter_command, $arobase,
-    $form_feed, $menu_only_separator, $misc_text);
+  return ($arobase, $open_brace, $close_brace, $comma,
+    $asterisk, $form_feed, $menu_only_separator, $misc_text);
 }
 
 sub _check_line_directive {
@@ -5065,6 +5075,7 @@ sub _handle_menu_entry_separators($$$$$$)
     # anything else corresponds to a separator that does not contain
     # : and is after a menu node (itself following a menu_entry_name)
     } else {
+      # NOTE $$line_ref can start with an @-command in that case
       print STDERR "MENU NODE done $separator\n" if ($self->{'DEBUG'});
       $current = _enter_menu_entry_node($self, $current, $source_info);
     }
@@ -6569,9 +6580,9 @@ sub _process_remaining_on_line($$$$)
 
   my $at_command_length;
   my @line_parsing = _parse_texi_regex($line);
-  my ($at_command, $open_brace, $close_brace, $comma, $asterisk,
-      $single_letter_command, $arobase, $form_feed, $menu_only_separator,
-      $misc_text) = @line_parsing;
+  my ($arobase, $open_brace, $close_brace, $comma,
+      $asterisk, $form_feed, $menu_only_separator, $misc_text)
+        = @line_parsing;
   my $menu_separator = $comma;
   $menu_separator = $menu_only_separator if (!$comma);
   print STDERR "PARSED: "
@@ -6580,90 +6591,108 @@ sub _process_remaining_on_line($$$$)
 
   my $macro_call_element;
   my $command;
+  my $at_command;
   my $from_alias;
-  if ($single_letter_command) {
-    $command = $single_letter_command;
-  } elsif ($at_command) {
-    $at_command_length = length($at_command) + 1;
-    $command = $at_command;
-
-    if (exists($self->{'aliases'}->{$command})) {
-      $from_alias = $command;
-      $command = $self->{'aliases'}->{$from_alias};
-    }
-
-    # handle user defined macros before anything else since
-    # their expansion may lead to changes in the line
-    if ($self->{'macros'}->{$command}) {
-      my $arg_line = $line;
-      substr($arg_line, 0, $at_command_length) = '';
-
-      ($macro_call_element, $arg_line, $source_info)
-        = _handle_macro($self, $current, $arg_line, $source_info, $command);
-      if ($macro_call_element) {
-        if ($from_alias) {
-          $macro_call_element->{'info'} = {}
-             if (!$macro_call_element->{'info'});
-          $macro_call_element->{'info'}->{'alias_of'} = $from_alias;
-        }
+  if ($arobase) {
+
+    my $single_letter_command;
+    my $command_string = $line;
+    substr($command_string, 0, 1) = '';
+    ($at_command, $single_letter_command) = 
_parse_command_name($command_string);
+
+    if ($single_letter_command) {
+      $command = $single_letter_command;
+      $at_command_length = 2;
+    } elsif (defined($at_command) and $at_command ne '') {
+      $at_command_length = length($at_command) +1;
+      $command = $at_command;
+
+      if (exists($self->{'aliases'}->{$command})) {
+        $from_alias = $command;
+        $command = $self->{'aliases'}->{$from_alias};
       }
-      if ($macro_call_element
-          and $macro_call_element->{'type'} eq '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 {
-        $line = $arg_line;
+
+      # handle user defined macros before anything else since
+      # their expansion may lead to changes in the line
+      if ($self->{'macros'}->{$command}) {
+        my $arg_line = $line;
+        substr($arg_line, 0, $at_command_length) = '';
+
+        ($macro_call_element, $arg_line, $source_info)
+          = _handle_macro($self, $current, $arg_line, $source_info, $command);
         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
-          # efficient.
+          if ($from_alias) {
+            $macro_call_element->{'info'} = {}
+               if (!$macro_call_element->{'info'});
+            $macro_call_element->{'info'}->{'alias_of'} = $from_alias;
+          }
+        }
+        if ($macro_call_element
+            and $macro_call_element->{'type'} eq '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 {
+          $line = $arg_line;
+          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
+            # efficient.
 
-          ($line, $source_info) = _next_text($self, $current);
+            ($line, $source_info) = _next_text($self, $current);
 
+          }
+          return ($current, $line, $source_info, $retval);
+          # goto funexit;  # used in XS code
         }
-        return ($current, $line, $source_info, $retval);
-        # goto funexit;  # used in XS code
       }
-    }
-    # expand value if it can change the line.  It considered again
-    # together with other commands below for all the other cases
-    # which may need a well formed tree, which is not needed here, and
-    # early value expansion may be needed to provide with an argument.
-    if ($command eq 'value') {
-      my $remaining_line = $line;
-      substr($remaining_line, 0, $at_command_length) = '';
-      $remaining_line =~ s/^\s*//
-         if ($self->{'IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME'});
-      # REVALUE
-      if ($remaining_line =~ s/^{([\w\-][^\s{\\}~`\^+"<>|@]*)}//) {
-        my $value = $1;
-        if (exists($self->{'values'}->{$value})) {
-          if ($self->{'MAX_MACRO_CALL_NESTING'}
-             and $self->{'value_expansion_nr'} >= 
$self->{'MAX_MACRO_CALL_NESTING'}) {
-            $self->_line_warn(sprintf(__(
-  "value call nested too deeply (set MAX_MACRO_CALL_NESTING to override; 
current value %d)"),
-                              $self->{'MAX_MACRO_CALL_NESTING'}), 
$source_info);
-            $line = $remaining_line;
+      # expand value if it can change the line.  It considered again
+      # together with other commands below for all the other cases
+      # which may need a well formed tree, which is not needed here, and
+      # early value expansion may be needed to provide with an argument.
+      if ($command eq 'value') {
+        my $remaining_line = $line;
+        substr($remaining_line, 0, $at_command_length) = '';
+        $remaining_line =~ s/^\s*//
+           if ($self->{'IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME'});
+        # REVALUE
+        if ($remaining_line =~ s/^{([\w\-][^\s{\\}~`\^+"<>|@]*)}//) {
+          my $value = $1;
+          if (exists($self->{'values'}->{$value})) {
+            if ($self->{'MAX_MACRO_CALL_NESTING'}
+                and $self->{'value_expansion_nr'}
+                         >= $self->{'MAX_MACRO_CALL_NESTING'}) {
+              $self->_line_warn(sprintf(__(
+ "value call nested too deeply (set MAX_MACRO_CALL_NESTING to override; 
current value %d)"),
+                                $self->{'MAX_MACRO_CALL_NESTING'}), 
$source_info);
+              $line = $remaining_line;
+              return ($current, $line, $source_info, $retval);
+              # goto funexit;  # used in XS code
+            }
+            $self->{'value_expansion_nr'}++;
+            _input_push_text($self, $remaining_line, 
$source_info->{'line_nr'});
+            _input_push_text($self, $self->{'values'}->{$value},
+                             $source_info->{'line_nr'}, undef, $value);
+            my $sm_value_element = _new_value_element($command, $value);
+            my $value_source_mark = {'sourcemark_type' => 'value_expansion',
+                                     'status' => 'start',
+                                     'line' => $self->{'values'}->{$value},
+                                     'element' => $sm_value_element};
+            _register_source_mark($self, $current, $value_source_mark);
+            $self->{'input'}->[0]->{'input_source_mark'} = $value_source_mark;
+            $line = '';
             return ($current, $line, $source_info, $retval);
             # goto funexit;  # used in XS code
           }
-          $self->{'value_expansion_nr'}++;
-          _input_push_text($self, $remaining_line, $source_info->{'line_nr'});
-          _input_push_text($self, $self->{'values'}->{$value},
-                           $source_info->{'line_nr'}, undef, $value);
-          my $sm_value_element = _new_value_element($command, $value);
-          my $value_source_mark = {'sourcemark_type' => 'value_expansion',
-                                   'status' => 'start',
-                                   'line' => $self->{'values'}->{$value},
-                                   'element' => $sm_value_element};
-          _register_source_mark($self, $current, $value_source_mark);
-          $self->{'input'}->[0]->{'input_source_mark'} = $value_source_mark;
-          $line = '';
-          return ($current, $line, $source_info, $retval);
-          # goto funexit;  # used in XS code
         }
       }
+    } else {
+      substr($line, 0, 1) = '';
+      # @ was followed by gibberish or by nothing, for instance at the
+      # very end of a string/file.
+      $self->_line_error(__("unexpected \@"), $source_info);
+      return ($current, $line, $source_info, $retval);
+      # goto funexit;  # used in XS code
     }
   }
 
@@ -6853,11 +6882,7 @@ sub _process_remaining_on_line($$$$)
     $current = $current_array_for_ref[0];
   # Any other @-command.
   } elsif ($command) {
-    if (!$at_command) {
-      substr($line, 0, 2) = '';
-    } else {
-      substr($line, 0, $at_command_length) = '';
-    }
+    substr($line, 0, $at_command_length) = '';
 
     print STDERR "COMMAND \@".Texinfo::Common::debug_command_name($command)
                   ."\n" if ($self->{'DEBUG'});
@@ -7057,11 +7082,6 @@ sub _process_remaining_on_line($$$$)
     } else {
       $current = _merge_text($self, $current, $form_feed);
     }
-  } elsif ($arobase) {
-    substr ($line, 0, 1) = '';
-    # this may happen with a @ at the very end of a file, therefore
-    # not followed by anything.
-    $self->_line_error(__("unexpected \@"), $source_info);
   } elsif ($menu_only_separator) {
     substr ($line, 0, 1) = '';
     $current = _merge_text($self, $current, $menu_only_separator);
diff --git a/tp/Texinfo/XS/MiscXS.xs b/tp/Texinfo/XS/MiscXS.xs
index 739e3a8a0a..128d473e97 100644
--- a/tp/Texinfo/XS/MiscXS.xs
+++ b/tp/Texinfo/XS/MiscXS.xs
@@ -103,27 +103,42 @@ xs_entity_text (text_in)
      RETVAL
 
 void
-xs_parse_texi_regex (text)
+xs_parse_command_name (text)
      SV *text
   PREINIT:
      char *at_command;
+     char *single_letter_command;
+  PPCODE:
+     xs_parse_command_name(text, &at_command, &single_letter_command);
+     EXTEND(SP,2);
+     PUSHs(sv_newmortal());
+     sv_setpv((SV*)ST(0), at_command);
+     SvUTF8_on(ST(0));
+     PUSHs(sv_newmortal());
+     sv_setpv((SV*)ST(1), single_letter_command);
+     SvUTF8_on(ST(1));
+
+
+void
+xs_parse_texi_regex (text)
+     SV *text
+  PREINIT:
+     char *arobase;
      char *open_brace;
      char *close_brace;
      char *comma;
      char *asterisk;
-     char *single_letter_command;
      char *separator_match;
-     char *arobase;
      char *form_feed;
      char *menu_only_separator;
      char *new_text;
   PPCODE:
-     xs_parse_texi_regex(text, &at_command, &open_brace, &close_brace,
-                         &comma, &asterisk, &single_letter_command,
-                         &arobase, &form_feed, &menu_only_separator, 
&new_text);
-     EXTEND(SP,9);
+     xs_parse_texi_regex(text, &arobase, &open_brace, &close_brace,
+                         &comma, &asterisk, &form_feed,
+                         &menu_only_separator, &new_text);
+     EXTEND(SP,7);
      PUSHs(sv_newmortal());
-     sv_setpv((SV*)ST(0), at_command);
+     sv_setpv((SV*)ST(0), arobase);
      SvUTF8_on(ST(0));
      PUSHs(sv_newmortal());
      sv_setpv((SV*)ST(1), open_brace);
@@ -138,20 +153,14 @@ xs_parse_texi_regex (text)
      sv_setpv((SV*)ST(4), asterisk);
      SvUTF8_on(ST(4));
      PUSHs(sv_newmortal());
-     sv_setpv((SV*)ST(5), single_letter_command);
+     sv_setpv((SV*)ST(5), form_feed);
      SvUTF8_on(ST(5));
      PUSHs(sv_newmortal());
-     sv_setpv((SV*)ST(6), arobase);
+     sv_setpv((SV*)ST(6), menu_only_separator);
      SvUTF8_on(ST(6));
      PUSHs(sv_newmortal());
-     sv_setpv((SV*)ST(7), form_feed);
+     sv_setpv((SV*)ST(7), new_text);
      SvUTF8_on(ST(7));
-     PUSHs(sv_newmortal());
-     sv_setpv((SV*)ST(8), menu_only_separator);
-     SvUTF8_on(ST(8));
-     PUSHs(sv_newmortal());
-     sv_setpv((SV*)ST(9), new_text);
-     SvUTF8_on(ST(9));
 
 SV *
 xs_default_format_protect_text (self, text_in)
diff --git a/tp/Texinfo/XS/misc.c b/tp/Texinfo/XS/misc.c
index 6d8fac3c3d..72a5050dcd 100644
--- a/tp/Texinfo/XS/misc.c
+++ b/tp/Texinfo/XS/misc.c
@@ -284,15 +284,56 @@ xs_entity_text (char *text)
   return new;
 }
 
+void xs_parse_command_name (SV *text_in,
+                            char **at_command,
+                            char **single_letter_command)
+{
+  char *text;
+
+  dTHX;
+
+  /* Make sure the input is in UTF8. */
+  if (!SvUTF8 (text_in))
+    sv_utf8_upgrade (text_in);
+  text = SvPV_nolen (text_in);
+
+  *at_command = *single_letter_command = 0;
+
+  if (isalnum(text[0]))
+    {
+      char *p, *q;
+      static char *s;
+
+      p = text;
+      q = text + 1;
+      while (isalnum (*q) || *q == '-' || *q == '_')
+        q++;
+
+      s = realloc (s, q - p + 1);
+      memcpy (s, p, q - p);
+      s[q - p] = '\0';
+      *at_command = s;
+    }
+  else if (text[0] && strchr ("([\"'~@&}{,.!?"
+                              " \t\n"
+                              "*-^`=:|/\\",
+                              text[0]))
+    {
+      static char a[2];
+      *single_letter_command = a;
+      a[0] = text[0];
+      a[1] = '\0';
+    }
+  return;
+}
+
 /* Return list ($at_command, $open_brace, ....) */
 void xs_parse_texi_regex (SV *text_in,
-                          char **at_command,
+                          char **arobase,
                           char **open_brace,
                           char **close_brace,
                           char **comma,
                           char **asterisk,
-                          char **single_letter_command,
-                          char **arobase,
                           char **form_feed,
                           char **menu_only_separator,
                           char **new_text)
@@ -306,83 +347,53 @@ void xs_parse_texi_regex (SV *text_in,
     sv_utf8_upgrade (text_in);
   text = SvPV_nolen (text_in);
 
-  *at_command = *open_brace = *close_brace = *comma = *asterisk
-     = *single_letter_command = *arobase = *form_feed
-          = *menu_only_separator = *new_text = 0;
+  *arobase = *open_brace = *close_brace = *comma = *asterisk
+     = *form_feed = *menu_only_separator = *new_text = 0;
 
-  if (*text == '@' && isalnum(text[1]))
+  if (*text == '@')
     {
-      char *p, *q;
-      static char *s;
+      *arobase = "@";
+    }
+  else if (*text == '{')
+    {
+      *open_brace = "{";
+    }
+  else if (*text == '}')
+    {
+      *close_brace = "}";
+    }
 
-      p = text + 1;
-      q = text + 2;
-      while (isalnum (*q) || *q == '-' || *q == '_')
-        q++;
-      
-      s = realloc (s, q - p + 1);
-      memcpy (s, p, q - p);
-      s[q - p] = '\0';
-      *at_command = s;
+  else if (*text == ',')
+    {
+      *comma = ",";
+    }
+  else if (strchr (":\t.", *text))
+    {
+      static char a[2];
+      *menu_only_separator = a;
+      a[0] = *text;
+      a[1] = '\0';
+    }
+  else if (*text == '\f')
+    {
+      *form_feed = "\f";
     }
   else
     {
-      if (*text == '{')
-        {
-          *open_brace = "{";
-        }
-      else if (*text == '}')
-        {
-          *close_brace = "}";
-        }
+      char *p;
 
-      else if (*text == ',')
-        {
-          *comma = ",";
-        }
-      else if (*text == '@'
-                 && text[1] && strchr ("([\"'~@&}{,.!?"
-                                       " \t\n"
-                                       "*-^`=:|/\\",
-                                       text[1]))
-        {
-          static char a[2];
-          *single_letter_command = a;
-          a[0] = text[1];
-          a[1] = '\0';
-        }
-      else if (strchr (":\t.", *text))
-        {
-          static char a[2];
-          *menu_only_separator = a;
-          a[0] = *text;
-          a[1] = '\0';
-        }
-      else if (*text == '\f')
-        {
-          *form_feed = "\f";
-        }
-      else if (*text == '@')
-        {
-          *arobase = "@";
-        }
-      else
-        {
-          char *p;
+      if (*text == '*')
+        *asterisk = "*";
 
-          if (*text == '*')
-            *asterisk = "*";
-
-          p = text;
-          p += strcspn (p, "{}@,:\t.\n\f");
-          if (p > text)
-            {
-              static char *s;
-              s = realloc (s, p - text + 1);
-              memcpy (s, text, p - text);
-              s[p - text] = '\0';
-              *new_text = s;
-            }
+      p = text;
+      p += strcspn (p, "{}@,:\t.\n\f");
+      if (p > text)
+        {
+          static char *s;
+          s = realloc (s, p - text + 1);
+          memcpy (s, text, p - text);
+          s[p - text] = '\0';
+          *new_text = s;
         }
     }
 
diff --git a/tp/Texinfo/XS/miscxs.h b/tp/Texinfo/XS/miscxs.h
index 696c61e304..686fa03520 100644
--- a/tp/Texinfo/XS/miscxs.h
+++ b/tp/Texinfo/XS/miscxs.h
@@ -1,9 +1,10 @@
 char *xs_unicode_text (char *, int);
 char *xs_entity_text (char *);
 char *xs_process_text (char *text);
+void xs_parse_command_name (SV *text,
+                            char **,
+                            char **);
 void xs_parse_texi_regex (SV *text,
-                          char **,
-                          char **,
                           char **,
                           char **,
                           char **,
diff --git a/tp/Texinfo/XS/parsetexi/parser.c b/tp/Texinfo/XS/parsetexi/parser.c
index 8f5926ef77..6056a2a0ae 100644
--- a/tp/Texinfo/XS/parsetexi/parser.c
+++ b/tp/Texinfo/XS/parsetexi/parser.c
@@ -80,6 +80,38 @@ read_command_name (char **ptr)
   return ret;
 }
 
+/* look for a command name.  Return value to be freed by caller.
+   *PTR is advanced past the read name. *SINGLE_CHAR is set to 1
+   if the command is a single character command.
+   Return 0 if name is invalid or the empty string */
+char *
+parse_command_name (char **ptr, int *single_char)
+{
+  char *p = *ptr;
+  char *ret = 0;
+  *single_char = 0;
+
+  if (*p
+      /* List of single character Texinfo commands. */
+      && strchr ("([\"'~@&}{,.!?"
+                 " \f\n\r\t"
+                 "*-^`=:|/\\",
+                 *p))
+    {
+      char single_char_str[2];
+      single_char_str[0] = *p++;
+      single_char_str[1] = '\0';
+      ret = strdup (single_char_str);
+      *single_char = 1;
+      *ptr = p;
+    }
+  else
+    {
+      ret = read_command_name (ptr);
+    }
+  return ret;
+}
+
 /* Read a name used for @set and @value. */
 char *
 read_flag_name (char **ptr)
@@ -1689,39 +1721,25 @@ process_remaining_on_line (ELEMENT **current_inout, 
char **line_inout)
 
   if (*line == '@')
     {
+      int single_char;
       line_after_command = line + 1;
 
-      /* List of single character Texinfo commands. */
-      if (strchr ("([\"'~@&}{,.!?"
-                  " \f\n\r\t"
-                  "*-^`=:|/\\",
-              *line_after_command))
+      command = parse_command_name (&line_after_command, &single_char);
+      if (command)
         {
-          char single_char[2];
-          single_char[0] = *line_after_command++;
-          single_char[1] = '\0';
-          cmd = lookup_command (single_char);
+          cmd = lookup_command (command);
+          /* known command */
+          if (cmd)
+            free (command);
+          /* command holds the unknown command name if !cmd && command */
         }
       else
         {
-          command = read_command_name (&line_after_command);
-
-          cmd = 0;
-          if (command)
-            {
-              cmd = lookup_command (command);
-              /* known command */
-              if (cmd)
-                {
-                  free (command);
-                }
-              /* command holds the unknown command name if !cmd && command */
-            }
-          else
-            {
-              /* @ was followed by gibberish.  "unexpected @" is printed
-                 below. */
-            }
+          /* @ was followed by gibberish or by nothing, for instance at the
+             very end of a string/file. */
+          line_error ("unexpected @");
+          line = line_after_command;
+          goto funexit;
         }
       if (cmd && (command_data(cmd).flags & CF_ALIAS))
         {
@@ -2359,11 +2377,6 @@ process_remaining_on_line (ELEMENT **current_inout, char 
**line_inout)
       t[1] = '\0';
       current = merge_text (current, t, 0);
     }
-  else if (*line == '@')
-    {
-      char separator = *line++;
-      line_error ("unexpected @");
-    }
   else if (*line == '\f')
     {
       char separator = *line++;
@@ -2384,7 +2397,7 @@ process_remaining_on_line (ELEMENT **current_inout, char 
**line_inout)
       else
        current = merge_text (current, "\f", 0);
     }
-  /* "Misc text except end of line." */
+  /* Misc text except end of line. */
   else if (*line != '\n')
     {
       size_t len;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]